1use binaryninjacore_sys::*;
18
19pub use binaryninjacore_sys::BNModificationStatus as ModificationStatus;
20
21use std::fmt::Debug;
22use std::marker::PhantomData;
23use std::mem::MaybeUninit;
24use std::os::raw::c_void;
25use std::ptr;
26use std::slice;
27
28use crate::architecture::Architecture;
29use crate::binary_view::{BinaryView, BinaryViewBase, BinaryViewExt, Result};
30use crate::metadata::Metadata;
31use crate::platform::Platform;
32use crate::rc::*;
33use crate::settings::Settings;
34use crate::string::*;
35use crate::Endianness;
36
37pub fn register_view_type<T, F>(name: &str, long_name: &str, constructor: F) -> &'static T
44where
45 T: CustomBinaryViewType,
46 F: FnOnce(BinaryViewType) -> T,
47{
48 extern "C" fn cb_valid<T>(ctxt: *mut c_void, data: *mut BNBinaryView) -> bool
49 where
50 T: CustomBinaryViewType,
51 {
52 let view_type = unsafe { &*(ctxt as *mut T) };
53 let data = unsafe { BinaryView::ref_from_raw(BNNewViewReference(data)) };
54 let _span = ffi_span!("BinaryViewTypeBase::is_valid_for", data);
55 view_type.is_valid_for(&data)
56 }
57
58 extern "C" fn cb_deprecated<T>(ctxt: *mut c_void) -> bool
59 where
60 T: CustomBinaryViewType,
61 {
62 ffi_wrap!("BinaryViewTypeBase::is_deprecated", unsafe {
63 let view_type = &*(ctxt as *mut T);
64 view_type.is_deprecated()
65 })
66 }
67
68 extern "C" fn cb_force_loadable<T>(ctxt: *mut c_void) -> bool
69 where
70 T: CustomBinaryViewType,
71 {
72 ffi_wrap!("BinaryViewTypeBase::is_force_loadable", unsafe {
73 let view_type = &*(ctxt as *mut T);
74 view_type.is_force_loadable()
75 })
76 }
77
78 extern "C" fn cb_create<T>(ctxt: *mut c_void, data: *mut BNBinaryView) -> *mut BNBinaryView
79 where
80 T: CustomBinaryViewType,
81 {
82 ffi_wrap!("BinaryViewTypeBase::create", unsafe {
83 let view_type = &*(ctxt as *mut T);
84 let data = BinaryView::ref_from_raw(BNNewViewReference(data));
85
86 let builder = CustomViewBuilder {
87 view_type,
88 actual_parent: &data,
89 };
90
91 let _span = ffi_span!("BinaryViewTypeBase::create", data);
92 match view_type.create_custom_view(&data, builder) {
93 Ok(bv) => {
94 Ref::into_raw(bv.handle).handle
98 }
99 Err(_) => ptr::null_mut(),
100 }
101 })
102 }
103
104 extern "C" fn cb_parse<T>(ctxt: *mut c_void, data: *mut BNBinaryView) -> *mut BNBinaryView
105 where
106 T: CustomBinaryViewType,
107 {
108 ffi_wrap!("BinaryViewTypeBase::parse", unsafe {
109 let view_type = &*(ctxt as *mut T);
110 let data = BinaryView::ref_from_raw(BNNewViewReference(data));
111
112 let builder = CustomViewBuilder {
113 view_type,
114 actual_parent: &data,
115 };
116
117 let _span = ffi_span!("BinaryViewTypeBase::parse", data);
118 match view_type.parse_custom_view(&data, builder) {
119 Ok(bv) => {
120 Ref::into_raw(bv.handle).handle
124 }
125 Err(_) => ptr::null_mut(),
126 }
127 })
128 }
129
130 extern "C" fn cb_load_settings<T>(ctxt: *mut c_void, data: *mut BNBinaryView) -> *mut BNSettings
131 where
132 T: CustomBinaryViewType,
133 {
134 ffi_wrap!("BinaryViewTypeBase::load_settings", unsafe {
135 let view_type = &*(ctxt as *mut T);
136 let data = BinaryView::ref_from_raw(BNNewViewReference(data));
137
138 let _span = ffi_span!("BinaryViewTypeBase::load_settings", data);
139 match view_type.load_settings_for_data(&data) {
140 Some(settings) => Ref::into_raw(settings).handle,
141 None => ptr::null_mut() as *mut _,
142 }
143 })
144 }
145
146 let name = name.to_cstr();
147 let name_ptr = name.as_ptr();
148
149 let long_name = long_name.to_cstr();
150 let long_name_ptr = long_name.as_ptr();
151
152 let ctxt = Box::leak(Box::new(MaybeUninit::zeroed()));
153
154 let mut bn_obj = BNCustomBinaryViewType {
155 context: ctxt.as_mut_ptr() as *mut _,
156 create: Some(cb_create::<T>),
157 parse: Some(cb_parse::<T>),
158 isValidForData: Some(cb_valid::<T>),
159 isDeprecated: Some(cb_deprecated::<T>),
160 isForceLoadable: Some(cb_force_loadable::<T>),
161 getLoadSettingsForData: Some(cb_load_settings::<T>),
162 };
163
164 unsafe {
165 let handle = BNRegisterBinaryViewType(name_ptr, long_name_ptr, &mut bn_obj as *mut _);
166 if handle.is_null() {
167 drop(Box::from_raw(ctxt));
172 panic!("bvt registration failed");
173 }
174
175 ctxt.write(constructor(BinaryViewType { handle }));
176 ctxt.assume_init_mut()
177 }
178}
179
180pub trait BinaryViewTypeBase: AsRef<BinaryViewType> {
181 fn is_valid_for(&self, data: &BinaryView) -> bool;
186
187 fn is_deprecated(&self) -> bool {
192 false
193 }
194
195 fn is_force_loadable(&self) -> bool {
199 false
200 }
201
202 fn default_load_settings_for_data(&self, data: &BinaryView) -> Option<Ref<Settings>> {
203 let settings_handle =
204 unsafe { BNGetBinaryViewDefaultLoadSettingsForData(self.as_ref().handle, data.handle) };
205
206 if settings_handle.is_null() {
207 None
208 } else {
209 unsafe { Some(Settings::ref_from_raw(settings_handle)) }
210 }
211 }
212
213 fn load_settings_for_data(&self, _data: &BinaryView) -> Option<Ref<Settings>> {
214 None
215 }
216}
217
218pub trait BinaryViewTypeExt: BinaryViewTypeBase {
219 fn name(&self) -> String {
220 unsafe { BnString::into_string(BNGetBinaryViewTypeName(self.as_ref().handle)) }
221 }
222
223 fn long_name(&self) -> String {
224 unsafe { BnString::into_string(BNGetBinaryViewTypeLongName(self.as_ref().handle)) }
225 }
226
227 fn register_arch<A: Architecture>(&self, id: u32, endianness: Endianness, arch: &A) {
228 unsafe {
229 BNRegisterArchitectureForViewType(
230 self.as_ref().handle,
231 id,
232 endianness,
233 arch.as_ref().handle,
234 );
235 }
236 }
237
238 fn register_platform(&self, id: u32, plat: &Platform) {
239 let arch = plat.arch();
240
241 unsafe {
242 BNRegisterPlatformForViewType(self.as_ref().handle, id, arch.handle, plat.handle);
243 }
244 }
245
246 fn register_platform_recognizer<R>(&self, id: u32, endian: Endianness, recognizer: R)
265 where
266 R: 'static + Fn(&BinaryView, &Metadata) -> Option<Ref<Platform>> + Send + Sync,
267 {
268 #[repr(C)]
269 struct PlatformRecognizerHandlerContext<R>
270 where
271 R: 'static + Fn(&BinaryView, &Metadata) -> Option<Ref<Platform>> + Send + Sync,
272 {
273 recognizer: R,
274 }
275
276 extern "C" fn cb_recognize_low_level_il<R>(
277 ctxt: *mut c_void,
278 bv: *mut BNBinaryView,
279 metadata: *mut BNMetadata,
280 ) -> *mut BNPlatform
281 where
282 R: 'static + Fn(&BinaryView, &Metadata) -> Option<Ref<Platform>> + Send + Sync,
283 {
284 let context = unsafe { &*(ctxt as *mut PlatformRecognizerHandlerContext<R>) };
285 let bv = unsafe { BinaryView::from_raw(bv).to_owned() };
286 let metadata = unsafe { Metadata::from_raw(metadata).to_owned() };
287 match (context.recognizer)(&bv, &metadata) {
288 Some(plat) => unsafe { Ref::into_raw(plat).handle },
289 None => std::ptr::null_mut(),
290 }
291 }
292
293 let recognizer = PlatformRecognizerHandlerContext { recognizer };
294 let raw = Box::into_raw(Box::new(recognizer));
296
297 unsafe {
298 BNRegisterPlatformRecognizerForViewType(
299 self.as_ref().handle,
300 id as u64,
301 endian,
302 Some(cb_recognize_low_level_il::<R>),
303 raw as *mut c_void,
304 )
305 }
306 }
307
308 fn open(&self, data: &BinaryView) -> Result<Ref<BinaryView>> {
309 let handle = unsafe { BNCreateBinaryViewOfType(self.as_ref().handle, data.handle) };
310
311 if handle.is_null() {
312 return Err(());
314 }
315
316 unsafe { Ok(BinaryView::ref_from_raw(handle)) }
317 }
318
319 fn parse(&self, data: &BinaryView) -> Result<Ref<BinaryView>> {
320 let handle = unsafe { BNParseBinaryViewOfType(self.as_ref().handle, data.handle) };
321
322 if handle.is_null() {
323 return Err(());
325 }
326
327 unsafe { Ok(BinaryView::ref_from_raw(handle)) }
328 }
329}
330
331impl<T: BinaryViewTypeBase> BinaryViewTypeExt for T {}
332
333#[derive(Copy, Clone, PartialEq, Eq, Hash)]
337pub struct BinaryViewType {
338 pub handle: *mut BNBinaryViewType,
339}
340
341impl BinaryViewType {
342 pub(crate) unsafe fn from_raw(handle: *mut BNBinaryViewType) -> Self {
343 debug_assert!(!handle.is_null());
344 Self { handle }
345 }
346
347 pub fn list_all() -> Array<BinaryViewType> {
348 unsafe {
349 let mut count: usize = 0;
350 let types = BNGetBinaryViewTypes(&mut count as *mut _);
351 Array::new(types, count, ())
352 }
353 }
354
355 pub fn valid_types_for_data(data: &BinaryView) -> Array<BinaryViewType> {
358 unsafe {
359 let mut count: usize = 0;
360 let types = BNGetBinaryViewTypesForData(data.handle, &mut count as *mut _);
361 Array::new(types, count, ())
362 }
363 }
364
365 pub fn by_name(name: &str) -> Result<Self> {
367 let bytes = name.to_cstr();
368 let handle = unsafe { BNGetBinaryViewTypeByName(bytes.as_ref().as_ptr() as *const _) };
369 match handle.is_null() {
370 false => Ok(unsafe { BinaryViewType::from_raw(handle) }),
371 true => Err(()),
372 }
373 }
374}
375
376impl BinaryViewTypeBase for BinaryViewType {
377 fn is_valid_for(&self, data: &BinaryView) -> bool {
378 unsafe { BNIsBinaryViewTypeValidForData(self.handle, data.handle) }
379 }
380
381 fn is_deprecated(&self) -> bool {
382 unsafe { BNIsBinaryViewTypeDeprecated(self.handle) }
383 }
384
385 fn is_force_loadable(&self) -> bool {
386 unsafe { BNIsBinaryViewTypeForceLoadable(self.handle) }
387 }
388
389 fn load_settings_for_data(&self, data: &BinaryView) -> Option<Ref<Settings>> {
390 let settings_handle =
391 unsafe { BNGetBinaryViewLoadSettingsForData(self.handle, data.handle) };
392
393 if settings_handle.is_null() {
394 None
395 } else {
396 unsafe { Some(Settings::ref_from_raw(settings_handle)) }
397 }
398 }
399}
400
401impl Debug for BinaryViewType {
402 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
403 f.debug_struct("BinaryViewType")
404 .field("name", &self.name())
405 .field("long_name", &self.long_name())
406 .finish()
407 }
408}
409
410impl CoreArrayProvider for BinaryViewType {
411 type Raw = *mut BNBinaryViewType;
412 type Context = ();
413 type Wrapped<'a> = Guard<'a, BinaryViewType>;
414}
415
416unsafe impl CoreArrayProviderInner for BinaryViewType {
417 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
418 BNFreeBinaryViewTypeList(raw);
419 }
420
421 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
422 Guard::new(BinaryViewType::from_raw(*raw), &())
423 }
424}
425
426impl AsRef<BinaryViewType> for BinaryViewType {
427 fn as_ref(&self) -> &Self {
428 self
429 }
430}
431
432unsafe impl Send for BinaryViewType {}
433unsafe impl Sync for BinaryViewType {}
434
435pub trait CustomBinaryViewType: 'static + BinaryViewTypeBase + Sync {
436 fn create_custom_view<'builder>(
437 &self,
438 data: &BinaryView,
439 builder: CustomViewBuilder<'builder, Self>,
440 ) -> Result<CustomView<'builder>>;
441
442 fn parse_custom_view<'builder>(
443 &self,
444 data: &BinaryView,
445 builder: CustomViewBuilder<'builder, Self>,
446 ) -> Result<CustomView<'builder>> {
447 self.create_custom_view(data, builder)
449 }
450}
451
452pub struct CustomViewBuilder<'a, T: CustomBinaryViewType + ?Sized> {
454 view_type: &'a T,
455 actual_parent: &'a BinaryView,
456}
457
458pub unsafe trait CustomBinaryView: 'static + BinaryViewBase + Sync + Sized {
459 type Args: Send;
460
461 fn new(handle: &BinaryView, args: &Self::Args) -> Result<Self>;
462 fn init(&mut self, args: Self::Args) -> Result<()>;
463 fn on_after_snapshot_data_applied(&mut self) {}
464}
465
466#[must_use]
469pub struct CustomView<'builder> {
470 handle: Ref<BinaryView>,
475 _builder: PhantomData<&'builder ()>,
476}
477
478impl<'a, T: CustomBinaryViewType> CustomViewBuilder<'a, T> {
479 pub fn create<V>(self, parent: &BinaryView, view_args: V::Args) -> Result<CustomView<'a>>
511 where
512 V: CustomBinaryView,
513 {
514 let file = self.actual_parent.file();
515 let view_type = self.view_type;
516
517 let view_name = view_type.name();
518
519 if let Some(bv) = file.view_of_type(&view_name) {
520 tracing::error!(
530 "attempt to create duplicate view of type '{}' (existing: {:?})",
531 view_name,
532 bv.handle
533 );
534
535 return Err(());
536 }
537
538 struct CustomViewContext<V>
541 where
542 V: CustomBinaryView,
543 {
544 raw_handle: *mut BNBinaryView,
545 state: CustomViewContextState<V>,
546 }
547
548 enum CustomViewContextState<V>
549 where
550 V: CustomBinaryView,
551 {
552 Uninitialized { args: V::Args },
553 Initialized { view: V },
554 None,
557 }
558
559 impl<V: CustomBinaryView> CustomViewContext<V> {
560 fn assume_init_ref(&self) -> &V {
561 let CustomViewContextState::Initialized { view } = &self.state else {
562 panic!("CustomViewContextState in invalid state");
563 };
564 view
565 }
566 }
567
568 extern "C" fn cb_init<V>(ctxt: *mut c_void) -> bool
569 where
570 V: CustomBinaryView,
571 {
572 ffi_wrap!("BinaryViewBase::init", unsafe {
573 let context = &mut *(ctxt as *mut CustomViewContext<V>);
574 let handle = BinaryView::ref_from_raw(context.raw_handle);
575
576 let mut state = CustomViewContextState::None;
578 core::mem::swap(&mut context.state, &mut state);
579 let CustomViewContextState::Uninitialized { args } = state else {
580 panic!("CustomViewContextState in invalid state");
581 };
582 match V::new(handle.as_ref(), &args) {
583 Ok(mut view) => match view.init(args) {
584 Ok(_) => {
585 context.state = CustomViewContextState::Initialized { view };
587 true
588 }
589 Err(_) => {
590 tracing::error!(
591 "CustomBinaryView::init failed; custom view returned Err"
592 );
593 false
594 }
595 },
596 Err(_) => {
597 tracing::error!("CustomBinaryView::new failed; custom view returned Err");
598 false
599 }
600 }
601 })
602 }
603
604 extern "C" fn cb_on_after_snapshot_data_applied<V>(ctxt: *mut c_void)
605 where
606 V: CustomBinaryView,
607 {
608 ffi_wrap!("BinaryViewBase::onAfterSnapshotDataApplied", unsafe {
609 let context = &mut *(ctxt as *mut CustomViewContext<V>);
610 if let CustomViewContextState::Initialized { view } = &mut context.state {
611 view.on_after_snapshot_data_applied();
612 }
613 })
614 }
615
616 extern "C" fn cb_free_object<V>(ctxt: *mut c_void)
617 where
618 V: CustomBinaryView,
619 {
620 ffi_wrap!("BinaryViewBase::freeObject", unsafe {
621 let context = ctxt as *mut CustomViewContext<V>;
622 let context = Box::from_raw(context);
623
624 if context.raw_handle.is_null() {
625 tracing::error!(
640 "BinaryViewBase::freeObject called on partially initialized object! crash imminent!"
641 );
642 } else if matches!(
643 &context.state,
644 CustomViewContextState::None | CustomViewContextState::Uninitialized { .. }
645 ) {
646 tracing::error!("BinaryViewBase::freeObject called on leaked/never initialized custom view!");
659 }
660 })
661 }
662
663 extern "C" fn cb_read<V>(
664 ctxt: *mut c_void,
665 dest: *mut c_void,
666 offset: u64,
667 len: usize,
668 ) -> usize
669 where
670 V: CustomBinaryView,
671 {
672 ffi_wrap!("BinaryViewBase::read", unsafe {
673 let context = &*(ctxt as *mut CustomViewContext<V>);
674 let dest = slice::from_raw_parts_mut(dest as *mut u8, len);
675 context.assume_init_ref().read(dest, offset)
676 })
677 }
678
679 extern "C" fn cb_write<V>(
680 ctxt: *mut c_void,
681 offset: u64,
682 src: *const c_void,
683 len: usize,
684 ) -> usize
685 where
686 V: CustomBinaryView,
687 {
688 ffi_wrap!("BinaryViewBase::write", unsafe {
689 let context = &*(ctxt as *mut CustomViewContext<V>);
690 let src = slice::from_raw_parts(src as *const u8, len);
691 context.assume_init_ref().write(offset, src)
692 })
693 }
694
695 extern "C" fn cb_insert<V>(
696 ctxt: *mut c_void,
697 offset: u64,
698 src: *const c_void,
699 len: usize,
700 ) -> usize
701 where
702 V: CustomBinaryView,
703 {
704 ffi_wrap!("BinaryViewBase::insert", unsafe {
705 let context = &*(ctxt as *mut CustomViewContext<V>);
706 let src = slice::from_raw_parts(src as *const u8, len);
707 context.assume_init_ref().insert(offset, src)
708 })
709 }
710
711 extern "C" fn cb_remove<V>(ctxt: *mut c_void, offset: u64, len: u64) -> usize
712 where
713 V: CustomBinaryView,
714 {
715 ffi_wrap!("BinaryViewBase::remove", unsafe {
716 let context = &*(ctxt as *mut CustomViewContext<V>);
717 context.assume_init_ref().remove(offset, len as usize)
718 })
719 }
720
721 extern "C" fn cb_modification<V>(ctxt: *mut c_void, offset: u64) -> ModificationStatus
722 where
723 V: CustomBinaryView,
724 {
725 ffi_wrap!("BinaryViewBase::modification_status", unsafe {
726 let context = &*(ctxt as *mut CustomViewContext<V>);
727 context.assume_init_ref().modification_status(offset)
728 })
729 }
730
731 extern "C" fn cb_offset_valid<V>(ctxt: *mut c_void, offset: u64) -> bool
732 where
733 V: CustomBinaryView,
734 {
735 ffi_wrap!("BinaryViewBase::offset_valid", unsafe {
736 let context = &*(ctxt as *mut CustomViewContext<V>);
737 context.assume_init_ref().offset_valid(offset)
738 })
739 }
740
741 extern "C" fn cb_offset_readable<V>(ctxt: *mut c_void, offset: u64) -> bool
742 where
743 V: CustomBinaryView,
744 {
745 ffi_wrap!("BinaryViewBase::readable", unsafe {
746 let context = &*(ctxt as *mut CustomViewContext<V>);
747 context.assume_init_ref().offset_readable(offset)
748 })
749 }
750
751 extern "C" fn cb_offset_writable<V>(ctxt: *mut c_void, offset: u64) -> bool
752 where
753 V: CustomBinaryView,
754 {
755 ffi_wrap!("BinaryViewBase::writable", unsafe {
756 let context = &*(ctxt as *mut CustomViewContext<V>);
757 context.assume_init_ref().offset_writable(offset)
758 })
759 }
760
761 extern "C" fn cb_offset_executable<V>(ctxt: *mut c_void, offset: u64) -> bool
762 where
763 V: CustomBinaryView,
764 {
765 ffi_wrap!("BinaryViewBase::offset_executable", unsafe {
766 let context = &*(ctxt as *mut CustomViewContext<V>);
767 context.assume_init_ref().offset_executable(offset)
768 })
769 }
770
771 extern "C" fn cb_offset_backed_by_file<V>(ctxt: *mut c_void, offset: u64) -> bool
772 where
773 V: CustomBinaryView,
774 {
775 ffi_wrap!("BinaryViewBase::offset_backed_by_file", unsafe {
776 let context = &*(ctxt as *mut CustomViewContext<V>);
777 context.assume_init_ref().offset_backed_by_file(offset)
778 })
779 }
780
781 extern "C" fn cb_next_valid_offset<V>(ctxt: *mut c_void, offset: u64) -> u64
782 where
783 V: CustomBinaryView,
784 {
785 ffi_wrap!("BinaryViewBase::next_valid_offset_after", unsafe {
786 let context = &*(ctxt as *mut CustomViewContext<V>);
787 context.assume_init_ref().next_valid_offset_after(offset)
788 })
789 }
790
791 extern "C" fn cb_start<V>(ctxt: *mut c_void) -> u64
792 where
793 V: CustomBinaryView,
794 {
795 ffi_wrap!("BinaryViewBase::start", unsafe {
796 let context = &*(ctxt as *mut CustomViewContext<V>);
797 context.assume_init_ref().start()
798 })
799 }
800
801 extern "C" fn cb_length<V>(ctxt: *mut c_void) -> u64
802 where
803 V: CustomBinaryView,
804 {
805 ffi_wrap!("BinaryViewBase::len", unsafe {
806 let context = &*(ctxt as *mut CustomViewContext<V>);
807 context.assume_init_ref().len()
808 })
809 }
810
811 extern "C" fn cb_entry_point<V>(ctxt: *mut c_void) -> u64
812 where
813 V: CustomBinaryView,
814 {
815 ffi_wrap!("BinaryViewBase::entry_point", unsafe {
816 let context = &*(ctxt as *mut CustomViewContext<V>);
817 context.assume_init_ref().entry_point()
818 })
819 }
820
821 extern "C" fn cb_executable<V>(ctxt: *mut c_void) -> bool
822 where
823 V: CustomBinaryView,
824 {
825 ffi_wrap!("BinaryViewBase::executable", unsafe {
826 let context = &*(ctxt as *mut CustomViewContext<V>);
827 context.assume_init_ref().executable()
828 })
829 }
830
831 extern "C" fn cb_endianness<V>(ctxt: *mut c_void) -> Endianness
832 where
833 V: CustomBinaryView,
834 {
835 ffi_wrap!("BinaryViewBase::default_endianness", unsafe {
836 let context = &*(ctxt as *mut CustomViewContext<V>);
837
838 context.assume_init_ref().default_endianness()
839 })
840 }
841
842 extern "C" fn cb_relocatable<V>(ctxt: *mut c_void) -> bool
843 where
844 V: CustomBinaryView,
845 {
846 ffi_wrap!("BinaryViewBase::relocatable", unsafe {
847 let context = &*(ctxt as *mut CustomViewContext<V>);
848
849 context.assume_init_ref().relocatable()
850 })
851 }
852
853 extern "C" fn cb_address_size<V>(ctxt: *mut c_void) -> usize
854 where
855 V: CustomBinaryView,
856 {
857 ffi_wrap!("BinaryViewBase::address_size", unsafe {
858 let context = &*(ctxt as *mut CustomViewContext<V>);
859
860 context.assume_init_ref().address_size()
861 })
862 }
863
864 extern "C" fn cb_save<V>(ctxt: *mut c_void, _fa: *mut BNFileAccessor) -> bool
865 where
866 V: CustomBinaryView,
867 {
868 ffi_wrap!("BinaryViewBase::save", unsafe {
869 let _context = &*(ctxt as *mut CustomViewContext<V>);
870 false
871 })
872 }
873
874 let ctxt = Box::new(CustomViewContext::<V> {
875 raw_handle: ptr::null_mut(),
876 state: CustomViewContextState::Uninitialized { args: view_args },
877 });
878
879 let ctxt = Box::into_raw(ctxt);
880
881 let mut bn_obj = BNCustomBinaryView {
882 context: ctxt as *mut _,
883 init: Some(cb_init::<V>),
884 freeObject: Some(cb_free_object::<V>),
885 externalRefTaken: None,
886 externalRefReleased: None,
887 read: Some(cb_read::<V>),
888 write: Some(cb_write::<V>),
889 insert: Some(cb_insert::<V>),
890 remove: Some(cb_remove::<V>),
891 getModification: Some(cb_modification::<V>),
892 isValidOffset: Some(cb_offset_valid::<V>),
893 isOffsetReadable: Some(cb_offset_readable::<V>),
894 isOffsetWritable: Some(cb_offset_writable::<V>),
895 isOffsetExecutable: Some(cb_offset_executable::<V>),
896 isOffsetBackedByFile: Some(cb_offset_backed_by_file::<V>),
897 getNextValidOffset: Some(cb_next_valid_offset::<V>),
898 getStart: Some(cb_start::<V>),
899 getLength: Some(cb_length::<V>),
900 getEntryPoint: Some(cb_entry_point::<V>),
901 isExecutable: Some(cb_executable::<V>),
902 getDefaultEndianness: Some(cb_endianness::<V>),
903 isRelocatable: Some(cb_relocatable::<V>),
904 getAddressSize: Some(cb_address_size::<V>),
905 save: Some(cb_save::<V>),
906 onAfterSnapshotDataApplied: Some(cb_on_after_snapshot_data_applied::<V>),
907 };
908
909 let view_name = view_name.to_cstr();
910 unsafe {
911 let res = BNCreateCustomBinaryView(
912 view_name.as_ptr(),
913 file.handle,
914 parent.handle,
915 &mut bn_obj,
916 );
917 assert!(
918 !res.is_null(),
919 "BNCreateCustomBinaryView cannot return null"
920 );
921 (*ctxt).raw_handle = res;
922 Ok(CustomView {
923 handle: BinaryView::ref_from_raw(res),
924 _builder: PhantomData,
925 })
926 }
927 }
928
929 pub fn wrap_existing(self, wrapped_view: Ref<BinaryView>) -> Result<CustomView<'a>> {
930 Ok(CustomView {
931 handle: wrapped_view,
932 _builder: PhantomData,
933 })
934 }
935}