1#![allow(unused)]
2
3use crate::binary_view::BinaryView;
4use crate::disassembly::InstructionTextToken;
5use crate::platform::Platform;
6use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref};
7use crate::string::{raw_to_string, BnString, IntoCStr};
8use crate::types::{NamedTypeReference, QualifiedName, QualifiedNameAndType, Type, TypeContainer};
9use binaryninjacore_sys::*;
10use std::ffi::{c_char, c_int, c_void};
11use std::ptr::NonNull;
12
13pub type TokenEscapingType = BNTokenEscapingType;
14pub type TypeDefinitionLineType = BNTypeDefinitionLineType;
15
16pub fn register_type_printer<T: TypePrinter>(
18 name: &str,
19 parser: T,
20) -> (&'static mut T, CoreTypePrinter) {
21 let parser = Box::leak(Box::new(parser));
22 let mut callback = BNTypePrinterCallbacks {
23 context: parser as *mut _ as *mut c_void,
24 getTypeTokens: Some(cb_get_type_tokens::<T>),
25 getTypeTokensBeforeName: Some(cb_get_type_tokens_before_name::<T>),
26 getTypeTokensAfterName: Some(cb_get_type_tokens_after_name::<T>),
27 getTypeString: Some(cb_get_type_string::<T>),
28 getTypeStringBeforeName: Some(cb_get_type_string_before_name::<T>),
29 getTypeStringAfterName: Some(cb_get_type_string_after_name::<T>),
30 getTypeLines: Some(cb_get_type_lines::<T>),
31 printAllTypes: Some(cb_print_all_types::<T>),
32 freeTokens: Some(cb_free_tokens),
33 freeString: Some(cb_free_string),
34 freeLines: Some(cb_free_lines),
35 };
36 let raw_name = name.to_cstr();
37 let result = unsafe { BNRegisterTypePrinter(raw_name.as_ptr(), &mut callback) };
38 let core = unsafe { CoreTypePrinter::from_raw(NonNull::new(result).unwrap()) };
39 (parser, core)
40}
41
42#[repr(transparent)]
43pub struct CoreTypePrinter {
44 pub(crate) handle: NonNull<BNTypePrinter>,
45}
46
47impl CoreTypePrinter {
48 pub(crate) unsafe fn from_raw(handle: NonNull<BNTypePrinter>) -> CoreTypePrinter {
49 Self { handle }
50 }
51
52 pub fn printers() -> Array<CoreTypePrinter> {
53 let mut count = 0;
54 let result = unsafe { BNGetTypePrinterList(&mut count) };
55 assert!(!result.is_null());
56 unsafe { Array::new(result, count, ()) }
57 }
58
59 pub fn printer_by_name(name: &str) -> Option<CoreTypePrinter> {
60 let name_raw = name.to_cstr();
61 let result = unsafe { BNGetTypePrinterByName(name_raw.as_ptr()) };
62 NonNull::new(result).map(|x| unsafe { Self::from_raw(x) })
63 }
64
65 pub fn name(&self) -> String {
66 let result = unsafe { BNGetTypePrinterName(self.handle.as_ptr()) };
67 assert!(!result.is_null());
68 unsafe { BnString::into_string(result) }
69 }
70
71 pub fn get_type_tokens<T: Into<QualifiedName>>(
72 &self,
73 type_: &Type,
74 platform: &Platform,
75 name: T,
76 base_confidence: u8,
77 escaping: TokenEscapingType,
78 ) -> Option<Array<InstructionTextToken>> {
79 let mut result_count = 0;
80 let mut result = std::ptr::null_mut();
81 let mut raw_name = QualifiedName::into_raw(name.into());
82 let success = unsafe {
83 BNGetTypePrinterTypeTokens(
84 self.handle.as_ptr(),
85 type_.handle,
86 platform.handle,
87 &mut raw_name,
88 base_confidence,
89 escaping,
90 &mut result,
91 &mut result_count,
92 )
93 };
94 QualifiedName::free_raw(raw_name);
95 success.then(|| {
96 assert!(!result.is_null());
97 unsafe { Array::new(result, result_count, ()) }
98 })
99 }
100
101 pub fn get_type_tokens_before_name(
102 &self,
103 type_: &Type,
104 platform: &Platform,
105 base_confidence: u8,
106 parent_type: &Type,
107 escaping: TokenEscapingType,
108 ) -> Option<Array<InstructionTextToken>> {
109 let mut result_count = 0;
110 let mut result = std::ptr::null_mut();
111 let success = unsafe {
112 BNGetTypePrinterTypeTokensBeforeName(
113 self.handle.as_ptr(),
114 type_.handle,
115 platform.handle,
116 base_confidence,
117 parent_type.handle,
118 escaping,
119 &mut result,
120 &mut result_count,
121 )
122 };
123 success.then(|| {
124 assert!(!result.is_null());
125 unsafe { Array::new(result, result_count, ()) }
126 })
127 }
128
129 pub fn get_type_tokens_after_name(
130 &self,
131 type_: &Type,
132 platform: &Platform,
133 base_confidence: u8,
134 parent_type: &Type,
135 escaping: TokenEscapingType,
136 ) -> Option<Array<InstructionTextToken>> {
137 let mut result_count = 0;
138 let mut result = std::ptr::null_mut();
139 let success = unsafe {
140 BNGetTypePrinterTypeTokensAfterName(
141 self.handle.as_ptr(),
142 type_.handle,
143 platform.handle,
144 base_confidence,
145 parent_type.handle,
146 escaping,
147 &mut result,
148 &mut result_count,
149 )
150 };
151 success.then(|| {
152 assert!(!result.is_null());
153 unsafe { Array::new(result, result_count, ()) }
154 })
155 }
156
157 pub fn get_type_string<T: Into<QualifiedName>>(
158 &self,
159 type_: &Type,
160 platform: &Platform,
161 name: T,
162 escaping: TokenEscapingType,
163 ) -> Option<BnString> {
164 let mut result = std::ptr::null_mut();
165 let mut raw_name = QualifiedName::into_raw(name.into());
166 let success = unsafe {
167 BNGetTypePrinterTypeString(
168 self.handle.as_ptr(),
169 type_.handle,
170 platform.handle,
171 &mut raw_name,
172 escaping,
173 &mut result,
174 )
175 };
176 QualifiedName::free_raw(raw_name);
177 success.then(|| unsafe {
178 assert!(!result.is_null());
179 BnString::from_raw(result)
180 })
181 }
182
183 pub fn get_type_string_before_name(
184 &self,
185 type_: &Type,
186 platform: &Platform,
187 escaping: BNTokenEscapingType,
188 ) -> Option<BnString> {
189 let mut result = std::ptr::null_mut();
190 let success = unsafe {
191 BNGetTypePrinterTypeStringAfterName(
192 self.handle.as_ptr(),
193 type_.handle,
194 platform.handle,
195 escaping,
196 &mut result,
197 )
198 };
199 success.then(|| unsafe {
200 assert!(!result.is_null());
201 BnString::from_raw(result)
202 })
203 }
204
205 pub fn get_type_string_after_name(
206 &self,
207 type_: &Type,
208 platform: &Platform,
209 escaping: TokenEscapingType,
210 ) -> Option<BnString> {
211 let mut result = std::ptr::null_mut();
212 let success = unsafe {
213 BNGetTypePrinterTypeStringBeforeName(
214 self.handle.as_ptr(),
215 type_.handle,
216 platform.handle,
217 escaping,
218 &mut result,
219 )
220 };
221 success.then(|| unsafe {
222 assert!(!result.is_null());
223 BnString::from_raw(result)
224 })
225 }
226
227 pub fn get_type_lines<T: Into<QualifiedName>>(
228 &self,
229 type_: &Type,
230 types: &TypeContainer,
231 name: T,
232 padding_cols: isize,
233 collapsed: bool,
234 escaping: TokenEscapingType,
235 ) -> Option<Array<TypeDefinitionLine>> {
236 let mut result_count = 0;
237 let mut result = std::ptr::null_mut();
238 let mut raw_name = QualifiedName::into_raw(name.into());
239 let success = unsafe {
240 BNGetTypePrinterTypeLines(
241 self.handle.as_ptr(),
242 type_.handle,
243 types.handle.as_ptr(),
244 &mut raw_name,
245 padding_cols as c_int,
246 collapsed,
247 escaping,
248 &mut result,
249 &mut result_count,
250 )
251 };
252 QualifiedName::free_raw(raw_name);
253 success.then(|| {
254 assert!(!result.is_null());
255 unsafe { Array::<TypeDefinitionLine>::new(result, result_count, ()) }
256 })
257 }
258
259 pub fn default_print_all_types<T, I>(
266 &self,
267 types: T,
268 data: &BinaryView,
269 padding_cols: isize,
270 escaping: TokenEscapingType,
271 ) -> Option<BnString>
272 where
273 T: Iterator<Item = I>,
274 I: Into<QualifiedNameAndType>,
275 {
276 let mut result = std::ptr::null_mut();
277 let (mut raw_names, mut raw_types): (Vec<BNQualifiedName>, Vec<_>) = types
278 .map(|t| {
279 let t = t.into();
280 (
282 QualifiedName::into_raw(t.name),
283 unsafe { Ref::into_raw(t.ty) }.handle,
284 )
285 })
286 .unzip();
287 let success = unsafe {
288 BNTypePrinterDefaultPrintAllTypes(
289 self.handle.as_ptr(),
290 raw_names.as_mut_ptr(),
291 raw_types.as_mut_ptr(),
292 raw_types.len(),
293 data.handle,
294 padding_cols as c_int,
295 escaping,
296 &mut result,
297 )
298 };
299 for raw_name in raw_names {
300 QualifiedName::free_raw(raw_name);
301 }
302 for raw_type in raw_types {
303 let _ = unsafe { Type::ref_from_raw(raw_type) };
304 }
305 success.then(|| unsafe {
306 assert!(!result.is_null());
307 BnString::from_raw(result)
308 })
309 }
310
311 pub fn print_all_types<T, I>(
312 &self,
313 types: T,
314 data: &BinaryView,
315 padding_cols: isize,
316 escaping: TokenEscapingType,
317 ) -> Option<BnString>
318 where
319 T: IntoIterator<Item = I>,
320 I: Into<QualifiedNameAndType>,
321 {
322 let mut result = std::ptr::null_mut();
323 let (mut raw_names, mut raw_types): (Vec<BNQualifiedName>, Vec<_>) = types
325 .into_iter()
326 .map(|t| {
327 let t = t.into();
328 (
330 QualifiedName::into_raw(t.name),
331 unsafe { Ref::into_raw(t.ty) }.handle,
332 )
333 })
334 .unzip();
335 let success = unsafe {
336 BNTypePrinterPrintAllTypes(
337 self.handle.as_ptr(),
338 raw_names.as_mut_ptr(),
339 raw_types.as_mut_ptr(),
340 raw_types.len(),
341 data.handle,
342 padding_cols as c_int,
343 escaping,
344 &mut result,
345 )
346 };
347 for raw_name in raw_names {
348 QualifiedName::free_raw(raw_name);
349 }
350 for raw_type in raw_types {
351 let _ = unsafe { Type::ref_from_raw(raw_type) };
352 }
353 success.then(|| unsafe {
354 assert!(!result.is_null());
355 BnString::from_raw(result)
356 })
357 }
358}
359
360impl Default for CoreTypePrinter {
361 fn default() -> Self {
362 let default_settings = crate::settings::Settings::new();
364 let name = default_settings.get_string("analysis.types.printerName");
365 Self::printer_by_name(&name).unwrap()
366 }
367}
368
369impl CoreArrayProvider for CoreTypePrinter {
370 type Raw = *mut BNTypePrinter;
371 type Context = ();
372 type Wrapped<'a> = Self;
373}
374
375unsafe impl CoreArrayProviderInner for CoreTypePrinter {
376 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
377 BNFreeTypePrinterList(raw)
378 }
379
380 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
381 let handle = NonNull::new(*raw).unwrap();
383 CoreTypePrinter::from_raw(handle)
384 }
385}
386
387pub trait TypePrinter {
388 fn get_type_tokens<T: Into<QualifiedName>>(
397 &self,
398 type_: Ref<Type>,
399 platform: Option<Ref<Platform>>,
400 name: T,
401 base_confidence: u8,
402 escaping: TokenEscapingType,
403 ) -> Option<Vec<InstructionTextToken>>;
404
405 fn get_type_tokens_before_name(
415 &self,
416 type_: Ref<Type>,
417 platform: Option<Ref<Platform>>,
418 base_confidence: u8,
419 parent_type: Option<Ref<Type>>,
420 escaping: TokenEscapingType,
421 ) -> Option<Vec<InstructionTextToken>>;
422
423 fn get_type_tokens_after_name(
433 &self,
434 type_: Ref<Type>,
435 platform: Option<Ref<Platform>>,
436 base_confidence: u8,
437 parent_type: Option<Ref<Type>>,
438 escaping: TokenEscapingType,
439 ) -> Option<Vec<InstructionTextToken>>;
440
441 fn get_type_string<T: Into<QualifiedName>>(
449 &self,
450 type_: Ref<Type>,
451 platform: Option<Ref<Platform>>,
452 name: T,
453 escaping: TokenEscapingType,
454 ) -> Option<String>;
455
456 fn get_type_string_before_name(
464 &self,
465 type_: Ref<Type>,
466 platform: Option<Ref<Platform>>,
467 escaping: TokenEscapingType,
468 ) -> Option<String>;
469
470 fn get_type_string_after_name(
478 &self,
479 type_: Ref<Type>,
480 platform: Option<Ref<Platform>>,
481 escaping: TokenEscapingType,
482 ) -> Option<String>;
483
484 fn get_type_lines<T: Into<QualifiedName>>(
494 &self,
495 type_: Ref<Type>,
496 types: &TypeContainer,
497 name: T,
498 padding_cols: isize,
499 collapsed: bool,
500 escaping: TokenEscapingType,
501 ) -> Option<Vec<TypeDefinitionLine>>;
502
503 fn print_all_types(
511 &self,
512 names: Vec<QualifiedName>,
513 types: Vec<Ref<Type>>,
514 data: Ref<BinaryView>,
515 padding_cols: isize,
516 escaping: TokenEscapingType,
517 ) -> Option<String>;
518}
519
520#[derive(Clone)]
522pub struct TypeDefinitionLine {
523 pub line_type: TypeDefinitionLineType,
524 pub tokens: Vec<InstructionTextToken>,
525 pub ty: Ref<Type>,
526 pub parent_type: Option<Ref<Type>>,
527 pub root_type: Option<Ref<Type>>,
529 pub root_type_name: Option<String>,
530 pub base_type: Option<Ref<NamedTypeReference>>,
532 pub base_offset: u64,
534 pub offset: u64,
535 pub field_index: usize,
536}
537
538impl TypeDefinitionLine {
539 pub(crate) fn from_raw(value: &BNTypeDefinitionLine) -> Self {
540 Self {
541 line_type: value.lineType,
542 tokens: {
543 let raw_tokens = unsafe { std::slice::from_raw_parts(value.tokens, value.count) };
544 raw_tokens
545 .iter()
546 .map(InstructionTextToken::from_raw)
547 .collect()
548 },
549 ty: unsafe { Type::from_raw(value.type_).to_owned() },
550 parent_type: match value.parentType.is_null() {
551 false => Some(unsafe { Type::from_raw(value.parentType).to_owned() }),
552 true => None,
553 },
554 root_type: match value.rootType.is_null() {
555 false => Some(unsafe { Type::from_raw(value.rootType).to_owned() }),
556 true => None,
557 },
558 root_type_name: match value.rootTypeName.is_null() {
559 false => Some(raw_to_string(value.rootTypeName).unwrap()),
560 true => None,
561 },
562 base_type: match value.baseType.is_null() {
563 false => Some(unsafe { NamedTypeReference::from_raw(value.baseType).to_owned() }),
564 true => None,
565 },
566 base_offset: value.baseOffset,
567 offset: value.offset,
568 field_index: value.fieldIndex,
569 }
570 }
571
572 pub(crate) fn from_owned_raw(value: BNTypeDefinitionLine) -> Self {
574 let owned = Self::from_raw(&value);
575 Self::free_owned_raw(value);
576 owned
577 }
578
579 pub(crate) fn into_raw(value: Self) -> BNTypeDefinitionLine {
580 let tokens: Box<[BNInstructionTextToken]> = value
582 .tokens
583 .into_iter()
584 .map(InstructionTextToken::into_raw)
585 .collect();
586 BNTypeDefinitionLine {
587 lineType: value.line_type,
588 count: tokens.len(),
589 tokens: Box::leak(tokens).as_mut_ptr(),
591 type_: unsafe { Ref::into_raw(value.ty) }.handle,
593 parentType: value
595 .parent_type
596 .map(|t| unsafe { Ref::into_raw(t) }.handle)
597 .unwrap_or(std::ptr::null_mut()),
598 rootType: value
600 .root_type
601 .map(|t| unsafe { Ref::into_raw(t) }.handle)
602 .unwrap_or(std::ptr::null_mut()),
603 rootTypeName: value
605 .root_type_name
606 .map(|s| BnString::into_raw(BnString::new(s)))
607 .unwrap_or(std::ptr::null_mut()),
608 baseType: value
610 .base_type
611 .map(|t| unsafe { Ref::into_raw(t) }.handle)
612 .unwrap_or(std::ptr::null_mut()),
613 baseOffset: value.base_offset,
614 offset: value.offset,
615 fieldIndex: value.field_index,
616 }
617 }
618
619 pub(crate) fn free_owned_raw(raw: BNTypeDefinitionLine) {
621 if !raw.tokens.is_null() {
622 let tokens = std::ptr::slice_from_raw_parts_mut(raw.tokens, raw.count);
623 let boxed_tokens = unsafe { Box::from_raw(tokens) };
625 for token in boxed_tokens {
626 InstructionTextToken::free_raw(token);
627 }
628 }
629 if !raw.type_.is_null() {
630 let _ = unsafe { Type::ref_from_raw(raw.type_) };
632 }
633 if !raw.parentType.is_null() {
634 let _ = unsafe { Type::ref_from_raw(raw.parentType) };
636 }
637 if !raw.rootType.is_null() {
638 let _ = unsafe { Type::ref_from_raw(raw.rootType) };
640 }
641 if !raw.rootTypeName.is_null() {
642 let _ = unsafe { BnString::from_raw(raw.rootTypeName) };
644 }
645 if !raw.baseType.is_null() {
646 let _ = unsafe { NamedTypeReference::ref_from_raw(raw.baseType) };
648 }
649 }
650}
651
652impl CoreArrayProvider for TypeDefinitionLine {
653 type Raw = BNTypeDefinitionLine;
654 type Context = ();
655 type Wrapped<'a> = Self;
656}
657
658unsafe impl CoreArrayProviderInner for TypeDefinitionLine {
659 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
660 unsafe { BNFreeTypeDefinitionLineList(raw, count) };
661 }
662
663 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
664 Self::from_raw(raw)
665 }
666}
667
668unsafe extern "C" fn cb_get_type_tokens<T: TypePrinter>(
669 ctxt: *mut ::std::os::raw::c_void,
670 type_: *mut BNType,
671 platform: *mut BNPlatform,
672 name: *mut BNQualifiedName,
673 base_confidence: u8,
674 escaping: BNTokenEscapingType,
675 result: *mut *mut BNInstructionTextToken,
676 result_count: *mut usize,
677) -> bool {
678 let ctxt: &mut T = &mut *(ctxt as *mut T);
679 let qualified_name = QualifiedName::from_raw(&*name);
681 let inner_result = ctxt.get_type_tokens(
682 unsafe { Type::ref_from_raw(type_) },
683 match platform.is_null() {
684 false => Some(Platform::ref_from_raw(platform)),
685 true => None,
686 },
687 qualified_name,
688 base_confidence,
689 escaping,
690 );
691 if let Some(inner_result) = inner_result {
692 let raw_text_tokens: Box<[BNInstructionTextToken]> = inner_result
693 .into_iter()
694 .map(InstructionTextToken::into_raw)
695 .collect();
696 *result_count = raw_text_tokens.len();
697 *result = Box::leak(raw_text_tokens).as_mut_ptr();
699 true
700 } else {
701 *result = std::ptr::null_mut();
702 *result_count = 0;
703 false
704 }
705}
706
707unsafe extern "C" fn cb_get_type_tokens_before_name<T: TypePrinter>(
708 ctxt: *mut ::std::os::raw::c_void,
709 type_: *mut BNType,
710 platform: *mut BNPlatform,
711 base_confidence: u8,
712 parent_type: *mut BNType,
713 escaping: BNTokenEscapingType,
714 result: *mut *mut BNInstructionTextToken,
715 result_count: *mut usize,
716) -> bool {
717 let ctxt: &mut T = &mut *(ctxt as *mut T);
718 let inner_result = ctxt.get_type_tokens_before_name(
719 Type::ref_from_raw(type_),
720 match platform.is_null() {
721 false => Some(Platform::ref_from_raw(platform)),
722 true => None,
723 },
724 base_confidence,
725 match parent_type.is_null() {
726 false => Some(Type::ref_from_raw(parent_type)),
727 true => None,
728 },
729 escaping,
730 );
731 if let Some(inner_result) = inner_result {
732 let raw_text_tokens: Box<[BNInstructionTextToken]> = inner_result
733 .into_iter()
734 .map(InstructionTextToken::into_raw)
735 .collect();
736 *result_count = raw_text_tokens.len();
737 *result = Box::leak(raw_text_tokens).as_mut_ptr();
739 true
740 } else {
741 *result = std::ptr::null_mut();
742 *result_count = 0;
743 false
744 }
745}
746
747unsafe extern "C" fn cb_get_type_tokens_after_name<T: TypePrinter>(
748 ctxt: *mut ::std::os::raw::c_void,
749 type_: *mut BNType,
750 platform: *mut BNPlatform,
751 base_confidence: u8,
752 parent_type: *mut BNType,
753 escaping: BNTokenEscapingType,
754 result: *mut *mut BNInstructionTextToken,
755 result_count: *mut usize,
756) -> bool {
757 let ctxt: &mut T = &mut *(ctxt as *mut T);
758 let inner_result = ctxt.get_type_tokens_after_name(
759 Type::ref_from_raw(type_),
760 match platform.is_null() {
761 false => Some(Platform::ref_from_raw(platform)),
762 true => None,
763 },
764 base_confidence,
765 match parent_type.is_null() {
766 false => Some(Type::ref_from_raw(parent_type)),
767 true => None,
768 },
769 escaping,
770 );
771 if let Some(inner_result) = inner_result {
772 let raw_text_tokens: Box<[BNInstructionTextToken]> = inner_result
773 .into_iter()
774 .map(InstructionTextToken::into_raw)
775 .collect();
776 *result_count = raw_text_tokens.len();
777 *result = Box::leak(raw_text_tokens).as_mut_ptr();
779 true
780 } else {
781 *result = std::ptr::null_mut();
782 *result_count = 0;
783 false
784 }
785}
786
787unsafe extern "C" fn cb_get_type_string<T: TypePrinter>(
788 ctxt: *mut ::std::os::raw::c_void,
789 type_: *mut BNType,
790 platform: *mut BNPlatform,
791 name: *mut BNQualifiedName,
792 escaping: BNTokenEscapingType,
793 result: *mut *mut ::std::os::raw::c_char,
794) -> bool {
795 let ctxt: &mut T = &mut *(ctxt as *mut T);
796 let qualified_name = QualifiedName::from_raw(&*name);
798 let inner_result = ctxt.get_type_string(
799 Type::ref_from_raw(type_),
800 match platform.is_null() {
801 false => Some(Platform::ref_from_raw(platform)),
802 true => None,
803 },
804 qualified_name,
805 escaping,
806 );
807 if let Some(inner_result) = inner_result {
808 let raw_string = BnString::new(inner_result);
809 *result = BnString::into_raw(raw_string);
811 true
812 } else {
813 *result = std::ptr::null_mut();
814 false
815 }
816}
817
818unsafe extern "C" fn cb_get_type_string_before_name<T: TypePrinter>(
819 ctxt: *mut ::std::os::raw::c_void,
820 type_: *mut BNType,
821 platform: *mut BNPlatform,
822 escaping: BNTokenEscapingType,
823 result: *mut *mut ::std::os::raw::c_char,
824) -> bool {
825 let ctxt: &mut T = &mut *(ctxt as *mut T);
826 let inner_result = ctxt.get_type_string_before_name(
827 Type::ref_from_raw(type_),
828 match platform.is_null() {
829 false => Some(Platform::ref_from_raw(platform)),
830 true => None,
831 },
832 escaping,
833 );
834 if let Some(inner_result) = inner_result {
835 let raw_string = BnString::new(inner_result);
837 *result = BnString::into_raw(raw_string);
838 true
839 } else {
840 *result = std::ptr::null_mut();
841 false
842 }
843}
844
845unsafe extern "C" fn cb_get_type_string_after_name<T: TypePrinter>(
846 ctxt: *mut ::std::os::raw::c_void,
847 type_: *mut BNType,
848 platform: *mut BNPlatform,
849 escaping: BNTokenEscapingType,
850 result: *mut *mut ::std::os::raw::c_char,
851) -> bool {
852 let ctxt: &mut T = &mut *(ctxt as *mut T);
853 let inner_result = ctxt.get_type_string_after_name(
854 Type::ref_from_raw(type_),
855 match platform.is_null() {
856 false => Some(Platform::ref_from_raw(platform)),
857 true => None,
858 },
859 escaping,
860 );
861 if let Some(inner_result) = inner_result {
862 let raw_string = BnString::new(inner_result);
863 *result = BnString::into_raw(raw_string);
865 true
866 } else {
867 *result = std::ptr::null_mut();
868 false
869 }
870}
871
872unsafe extern "C" fn cb_get_type_lines<T: TypePrinter>(
873 ctxt: *mut ::std::os::raw::c_void,
874 type_: *mut BNType,
875 types: *mut BNTypeContainer,
876 name: *mut BNQualifiedName,
877 padding_cols: ::std::os::raw::c_int,
878 collapsed: bool,
879 escaping: BNTokenEscapingType,
880 result: *mut *mut BNTypeDefinitionLine,
881 result_count: *mut usize,
882) -> bool {
883 let ctxt: &mut T = &mut *(ctxt as *mut T);
884 let qualified_name = QualifiedName::from_raw(&*name);
886 let types_ptr = NonNull::new(types).unwrap();
887 let types = TypeContainer::from_raw(types_ptr);
888 let inner_result = ctxt.get_type_lines(
889 Type::ref_from_raw(type_),
890 &types,
891 qualified_name,
892 padding_cols as isize,
893 collapsed,
894 escaping,
895 );
896 if let Some(inner_result) = inner_result {
897 let boxed_raw_lines: Box<[_]> = inner_result
898 .into_iter()
899 .map(TypeDefinitionLine::into_raw)
900 .collect();
901 *result_count = boxed_raw_lines.len();
902 *result = Box::leak(boxed_raw_lines).as_mut_ptr();
904 true
905 } else {
906 *result = std::ptr::null_mut();
907 *result_count = 0;
908 false
909 }
910}
911
912unsafe extern "C" fn cb_print_all_types<T: TypePrinter>(
913 ctxt: *mut ::std::os::raw::c_void,
914 names: *mut BNQualifiedName,
915 types: *mut *mut BNType,
916 type_count: usize,
917 data: *mut BNBinaryView,
918 padding_cols: ::std::os::raw::c_int,
919 escaping: BNTokenEscapingType,
920 result: *mut *mut ::std::os::raw::c_char,
921) -> bool {
922 let ctxt: &mut T = &mut *(ctxt as *mut T);
923 let raw_names = std::slice::from_raw_parts(names, type_count);
924 let names: Vec<_> = raw_names.iter().map(QualifiedName::from_raw).collect();
926 let raw_types = std::slice::from_raw_parts(types, type_count);
927 let types: Vec<_> = raw_types.iter().map(|&t| Type::ref_from_raw(t)).collect();
929 let inner_result = ctxt.print_all_types(
930 names,
931 types,
932 BinaryView::ref_from_raw(data),
933 padding_cols as isize,
934 escaping,
935 );
936 if let Some(inner_result) = inner_result {
937 let raw_string = BnString::new(inner_result);
938 *result = BnString::into_raw(raw_string);
940 true
941 } else {
942 *result = std::ptr::null_mut();
943 false
944 }
945}
946
947unsafe extern "C" fn cb_free_string(_ctxt: *mut c_void, string: *mut c_char) {
948 BnString::free_raw(string);
950}
951
952unsafe extern "C" fn cb_free_tokens(
953 _ctxt: *mut ::std::os::raw::c_void,
954 tokens: *mut BNInstructionTextToken,
955 count: usize,
956) {
957 let tokens = std::ptr::slice_from_raw_parts_mut(tokens, count);
958 let boxed_tokens = Box::from_raw(tokens);
960 for token in boxed_tokens {
961 InstructionTextToken::free_raw(token);
962 }
963}
964
965unsafe extern "C" fn cb_free_lines(
966 _ctxt: *mut ::std::os::raw::c_void,
967 lines: *mut BNTypeDefinitionLine,
968 count: usize,
969) {
970 let lines = std::ptr::slice_from_raw_parts_mut(lines, count);
971 let boxes_lines = Box::from_raw(lines);
973 for line in boxes_lines {
974 TypeDefinitionLine::free_owned_raw(line);
975 }
976}