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