1#![allow(unused)]
15
16use binaryninjacore_sys::*;
17
18use crate::architecture::Architecture;
19use crate::architecture::CoreArchitecture;
20use crate::basic_block::BasicBlock;
21use crate::function::{Location, NativeBlock};
22use crate::low_level_il as llil;
23use crate::medium_level_il as mlil;
24use crate::string::IntoCStr;
25use crate::string::{raw_to_string, strings_to_string_list, BnString};
26use crate::{high_level_il as hlil, BN_INVALID_EXPR, BN_INVALID_OPERAND};
27
28use crate::rc::*;
29
30use crate::confidence::MAX_CONFIDENCE;
31use crate::function::{Function, HighlightColor};
32use crate::tags::Tag;
33use crate::types::Type;
34use crate::variable::StackVariableReference;
35
36use crate::binary_view::StringType;
37use crate::high_level_il::HighLevelILFunction;
38use crate::low_level_il::function::{FunctionForm, FunctionMutability, LowLevelILFunction};
39use crate::medium_level_il::MediumLevelILFunction;
40use crate::project::Project;
41use std::convert::From;
42use std::ffi;
43use std::fmt::{Display, Formatter};
44use std::ptr;
45use std::ptr::NonNull;
46
47pub type DisassemblyOption = BNDisassemblyOption;
48pub type InstructionTextTokenType = BNInstructionTextTokenType;
49
50#[derive(Clone, PartialEq, Debug, Default, Eq)]
51pub struct DisassemblyTextLine {
52 pub address: u64,
53 pub instruction_index: usize,
55 pub tokens: Vec<InstructionTextToken>,
56 pub highlight: HighlightColor,
57 pub tags: Vec<Ref<Tag>>,
58 pub type_info: DisassemblyTextLineTypeInfo,
59}
60
61impl DisassemblyTextLine {
62 pub(crate) fn from_raw(value: &BNDisassemblyTextLine) -> Self {
63 let raw_tokens = unsafe { std::slice::from_raw_parts(value.tokens, value.count) };
64 let tokens: Vec<_> = raw_tokens
65 .iter()
66 .map(InstructionTextToken::from_raw)
67 .collect();
68 let raw_tags = unsafe { std::slice::from_raw_parts(value.tags, value.tagCount) };
70 let tags: Vec<_> = raw_tags
71 .iter()
72 .map(|&t| unsafe { Tag::from_raw(t) }.to_owned())
73 .collect();
74 Self {
75 address: value.addr,
76 instruction_index: value.instrIndex,
77 tokens,
78 highlight: value.highlight.into(),
79 tags,
80 type_info: DisassemblyTextLineTypeInfo::from_raw(&value.typeInfo),
81 }
82 }
83
84 pub(crate) fn into_raw(value: Self) -> BNDisassemblyTextLine {
88 let tokens: Box<[BNInstructionTextToken]> = value
90 .tokens
91 .into_iter()
92 .map(InstructionTextToken::into_raw)
93 .collect();
94 let tags: Box<[*mut BNTag]> = value
95 .tags
96 .into_iter()
97 .map(|t| {
98 unsafe { Ref::into_raw(t) }.handle
101 })
102 .collect();
103 BNDisassemblyTextLine {
104 addr: value.address,
105 instrIndex: value.instruction_index,
106 count: tokens.len(),
107 tokens: Box::leak(tokens).as_mut_ptr(),
109 highlight: value.highlight.into(),
110 tagCount: tags.len(),
111 tags: Box::leak(tags).as_mut_ptr(),
113 typeInfo: DisassemblyTextLineTypeInfo::into_raw(value.type_info),
114 }
115 }
116
117 pub(crate) fn free_raw(value: BNDisassemblyTextLine) {
121 let raw_tokens = unsafe { std::slice::from_raw_parts_mut(value.tokens, value.count) };
123 let boxed_tokens = unsafe { Box::from_raw(raw_tokens) };
124 for token in boxed_tokens {
125 InstructionTextToken::free_raw(token);
127 }
128 let raw_tags = unsafe { std::slice::from_raw_parts_mut(value.tags, value.tagCount) };
130 let boxed_tags = unsafe { Box::from_raw(raw_tags) };
131 for tag in boxed_tags {
132 let _ = unsafe { Tag::ref_from_raw(tag) };
134 }
135 DisassemblyTextLineTypeInfo::free_raw(value.typeInfo);
137 }
138
139 pub fn new(tokens: Vec<InstructionTextToken>) -> Self {
140 Self {
141 tokens,
142 ..Default::default()
143 }
144 }
145
146 pub fn new_with_addr(tokens: Vec<InstructionTextToken>, addr: u64) -> Self {
147 Self {
148 address: addr,
149 tokens,
150 ..Default::default()
151 }
152 }
153}
154
155impl From<&str> for DisassemblyTextLine {
156 fn from(value: &str) -> Self {
157 Self::new(vec![InstructionTextToken::new(
158 value,
159 InstructionTextTokenKind::Text,
160 )])
161 }
162}
163
164impl From<String> for DisassemblyTextLine {
165 fn from(value: String) -> Self {
166 Self::new(vec![InstructionTextToken::new(
167 value,
168 InstructionTextTokenKind::Text,
169 )])
170 }
171}
172
173impl Display for DisassemblyTextLine {
174 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
175 for token in &self.tokens {
176 write!(f, "{}", token)?;
177 }
178 Ok(())
179 }
180}
181
182impl CoreArrayProvider for DisassemblyTextLine {
183 type Raw = BNDisassemblyTextLine;
184 type Context = ();
185 type Wrapped<'a> = Self;
186}
187
188unsafe impl CoreArrayProviderInner for DisassemblyTextLine {
189 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
190 BNFreeDisassemblyTextLines(raw, count)
191 }
192
193 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
194 Self::from_raw(raw)
195 }
196}
197
198#[derive(Default, Clone, PartialEq, Eq, Debug, Hash)]
199pub struct DisassemblyTextLineTypeInfo {
200 pub has_type_info: bool,
201 pub parent_type: Option<Ref<Type>>,
202 pub field_index: usize,
203 pub offset: u64,
204}
205
206impl DisassemblyTextLineTypeInfo {
207 pub(crate) fn from_raw(value: &BNDisassemblyTextLineTypeInfo) -> Self {
208 Self {
209 has_type_info: value.hasTypeInfo,
210 parent_type: match value.parentType.is_null() {
211 false => Some(unsafe { Type::from_raw(value.parentType).to_owned() }),
212 true => None,
213 },
214 field_index: value.fieldIndex,
215 offset: value.offset,
216 }
217 }
218
219 pub(crate) fn from_owned_raw(value: BNDisassemblyTextLineTypeInfo) -> Self {
220 Self {
221 has_type_info: value.hasTypeInfo,
222 parent_type: match value.parentType.is_null() {
223 false => Some(unsafe { Type::ref_from_raw(value.parentType) }),
224 true => None,
225 },
226 field_index: value.fieldIndex,
227 offset: value.offset,
228 }
229 }
230
231 pub(crate) fn into_raw(value: Self) -> BNDisassemblyTextLineTypeInfo {
232 BNDisassemblyTextLineTypeInfo {
233 hasTypeInfo: value.has_type_info,
234 parentType: value
235 .parent_type
236 .map(|t| unsafe { Ref::into_raw(t) }.handle)
237 .unwrap_or(std::ptr::null_mut()),
238 fieldIndex: value.field_index,
239 offset: value.offset,
240 }
241 }
242
243 pub(crate) fn into_owned_raw(value: &Self) -> BNDisassemblyTextLineTypeInfo {
244 BNDisassemblyTextLineTypeInfo {
245 hasTypeInfo: value.has_type_info,
246 parentType: value
247 .parent_type
248 .as_ref()
249 .map(|t| t.handle)
250 .unwrap_or(std::ptr::null_mut()),
251 fieldIndex: value.field_index,
252 offset: value.offset,
253 }
254 }
255
256 pub(crate) fn free_raw(value: BNDisassemblyTextLineTypeInfo) {
257 if !value.parentType.is_null() {
258 let _ = unsafe { Type::ref_from_raw(value.parentType) };
259 }
260 }
261}
262
263#[derive(Debug, Clone, PartialEq, Eq)]
264pub struct InstructionTextToken {
265 pub address: u64,
266 pub text: String,
267 pub confidence: u8,
268 pub context: InstructionTextTokenContext,
269 pub expr_index: Option<usize>,
270 pub type_: InstructionTextTokenType,
272 pub value: u64,
274 pub width: u64,
276 pub size: usize,
277 pub operand: usize,
278 pub type_names: Vec<String>,
279}
280
281impl InstructionTextToken {
282 pub(crate) fn from_raw(value: &BNInstructionTextToken) -> Self {
283 let text = raw_to_string(value.text).unwrap();
284 let type_names = if value.namesCount == 0 {
285 Vec::new()
286 } else {
287 let names = unsafe { std::slice::from_raw_parts(value.typeNames, value.namesCount) };
288 names
289 .iter()
290 .filter_map(|&name| raw_to_string(name))
291 .collect()
292 };
293 Self {
294 address: value.address,
295 width: if value.width == 0 {
296 text.len() as u64
297 } else {
298 value.width
299 },
300 text,
301 confidence: value.confidence,
302 context: value.context.into(),
303 expr_index: match value.exprIndex {
304 BN_INVALID_EXPR => None,
305 index => Some(index),
306 },
307 type_: value.type_,
308 value: value.value,
309 size: value.size,
310 operand: value.operand,
311 type_names,
312 }
313 }
314
315 pub(crate) fn into_raw(value: Self) -> BNInstructionTextToken {
316 let bn_text = BnString::new(value.text);
317 BNInstructionTextToken {
318 type_: value.type_,
319 text: BnString::into_raw(bn_text),
321 value: value.value,
322 width: value.width,
323 size: value.size,
324 operand: value.operand,
325 context: value.context.into(),
326 confidence: value.confidence,
327 address: value.address,
328 typeNames: strings_to_string_list(&value.type_names),
330 namesCount: value.type_names.len(),
331 exprIndex: value.expr_index.unwrap_or(BN_INVALID_EXPR),
332 }
333 }
334
335 pub(crate) fn free_raw(value: BNInstructionTextToken) {
336 unsafe { BnString::free_raw(value.text) };
337 if !value.typeNames.is_null() {
338 unsafe { BNFreeStringList(value.typeNames, value.namesCount) };
339 }
340 }
341
342 pub fn new(text: impl Into<String>, kind: InstructionTextTokenKind) -> Self {
347 Self::new_with_address(0, text, kind)
348 }
349
350 pub fn new_with_address(
351 address: u64,
352 text: impl Into<String>,
353 kind: InstructionTextTokenKind,
354 ) -> Self {
355 let text = text.into();
356 Self {
357 address,
358 width: text.len() as u64,
359 text,
360 confidence: MAX_CONFIDENCE,
361 context: InstructionTextTokenContext::Normal,
362 expr_index: None,
363 value: kind.try_value().unwrap_or(0),
364 size: kind.try_size().unwrap_or(0),
365 operand: kind.try_operand().unwrap_or(BN_INVALID_OPERAND),
366 type_names: kind.try_type_names().unwrap_or_default(),
367 type_: kind.into(),
368 }
369 }
370
371 pub fn kind(&self) -> InstructionTextTokenKind {
374 InstructionTextTokenKind::from_token(self)
375 }
376}
377
378impl Display for InstructionTextToken {
379 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
380 self.text.fmt(f)
381 }
382}
383
384impl CoreArrayProvider for InstructionTextToken {
385 type Raw = BNInstructionTextToken;
386 type Context = ();
387 type Wrapped<'a> = Self;
388}
389
390unsafe impl CoreArrayProviderInner for InstructionTextToken {
391 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
392 BNFreeInstructionText(raw, count)
394 }
395
396 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
397 Self::from_raw(raw)
398 }
399}
400
401impl CoreArrayProvider for Array<InstructionTextToken> {
402 type Raw = BNInstructionTextLine;
403 type Context = ();
404 type Wrapped<'a> = std::mem::ManuallyDrop<Self>;
405}
406
407unsafe impl CoreArrayProviderInner for Array<InstructionTextToken> {
408 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
409 BNFreeInstructionTextLines(raw, count)
411 }
412
413 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
414 std::mem::ManuallyDrop::new(Self::new(raw.tokens, raw.count, ()))
416 }
417}
418
419#[derive(Clone, PartialEq, Debug)]
420pub enum InstructionTextTokenKind {
421 Text,
422 Instruction,
423 OperandSeparator,
427 Register,
428 Integer {
429 value: u64,
430 size: Option<usize>,
432 operand: Option<usize>,
439 },
440 PossibleAddress {
441 value: u64,
442 size: Option<usize>,
444 operand: Option<usize>,
451 },
452 BeginMemoryOperand,
453 EndMemoryOperand,
454 FloatingPoint {
455 value: f64,
456 size: Option<usize>,
458 },
459 Annotation,
460 CodeRelativeAddress {
461 value: u64,
462 size: Option<usize>,
464 operand: Option<usize>,
471 },
472 ArgumentName {
473 value: u64,
475 },
476 HexDumpByteValue {
477 value: u8,
478 },
479 HexDumpSkippedByte,
480 HexDumpInvalidByte,
481 HexDumpText {
482 width: u64,
484 },
485 Opcode,
486 String {
487 value: u64,
490 },
491 StringContent {
495 ty: StringType,
496 },
497 CharacterConstant {
498 operand: Option<usize>,
505 },
506 Keyword {
507 value: u64,
509 },
510 TypeName,
511 FieldName {
512 offset: u64,
514 type_names: Vec<String>,
519 },
520 NameSpace,
521 NameSpaceSeparator,
522 Tag,
523 StructOffset {
524 offset: u64,
526 type_names: Vec<String>,
529 },
530 StructOffsetByteValue,
532 StructureHexDumpText {
534 width: u64,
536 },
537 GotoLabel {
538 target: u64,
539 },
540 Comment {
541 target: u64,
542 },
543 PossibleValue {
544 value: u64,
545 },
546 PossibleValueType,
548 ArrayIndex {
549 index: u64,
550 },
551 Indentation,
552 UnknownMemory,
553 EnumerationMember {
554 value: u64,
555 type_id: Option<String>,
559 },
560 Operation,
562 BaseStructureName,
563 BaseStructureSeparator,
564 Brace {
565 hash: Option<u64>,
567 },
568 ValueLocation,
569 CodeSymbol {
570 value: u64,
572 size: usize, },
575 DataSymbol {
576 value: u64,
578 size: usize, },
581 LocalVariable {
582 variable_id: u64,
586 ssa_version: usize,
588 },
589 Import {
590 target: u64,
592 },
593 AddressDisplay {
594 address: u64,
595 },
596 IndirectImport {
598 target: u64,
602 size: usize,
604 source_operand: usize,
606 },
607 ExternalSymbol {
608 value: u64,
610 },
611 StackVariable {
612 variable_id: u64,
615 },
616 AddressSeparator,
617 CollapsedInformation,
618 CollapseStateIndicator {
619 hash: Option<u64>,
621 },
622 NewLine {
623 value: u64,
625 },
626}
627
628impl InstructionTextTokenKind {
629 fn from_token(value: &InstructionTextToken) -> Self {
630 match value.type_ {
631 BNInstructionTextTokenType::TextToken => Self::Text,
632 BNInstructionTextTokenType::InstructionToken => Self::Instruction,
633 BNInstructionTextTokenType::OperandSeparatorToken => Self::OperandSeparator,
634 BNInstructionTextTokenType::RegisterToken => Self::Register,
635 BNInstructionTextTokenType::IntegerToken => Self::Integer {
636 value: value.value,
637 size: match value.size {
638 0 => None,
639 size => Some(size),
640 },
641 operand: Some(value.operand),
642 },
643 BNInstructionTextTokenType::PossibleAddressToken => Self::PossibleAddress {
644 value: value.value,
645 size: match value.size {
646 0 => None,
647 size => Some(size),
648 },
649 operand: Some(value.operand),
650 },
651 BNInstructionTextTokenType::BeginMemoryOperandToken => Self::BeginMemoryOperand,
652 BNInstructionTextTokenType::EndMemoryOperandToken => Self::EndMemoryOperand,
653 BNInstructionTextTokenType::FloatingPointToken => Self::FloatingPoint {
654 value: f64::from_bits(value.value),
655 size: match value.size {
656 0 => None,
657 size => Some(size),
658 },
659 },
660 BNInstructionTextTokenType::AnnotationToken => Self::Annotation,
661 BNInstructionTextTokenType::CodeRelativeAddressToken => Self::CodeRelativeAddress {
662 value: value.value,
663 size: match value.size {
664 0 => None,
665 size => Some(size),
666 },
667 operand: Some(value.operand),
668 },
669 BNInstructionTextTokenType::ArgumentNameToken => {
670 Self::ArgumentName { value: value.value }
671 }
672 BNInstructionTextTokenType::HexDumpByteValueToken => Self::HexDumpByteValue {
673 value: value.value as u8,
674 },
675 BNInstructionTextTokenType::HexDumpSkippedByteToken => Self::HexDumpSkippedByte,
676 BNInstructionTextTokenType::HexDumpInvalidByteToken => Self::HexDumpInvalidByte,
677 BNInstructionTextTokenType::HexDumpTextToken => {
678 Self::HexDumpText { width: value.value }
679 }
680 BNInstructionTextTokenType::OpcodeToken => Self::Opcode,
681 BNInstructionTextTokenType::StringToken => match value.context.into() {
682 BNInstructionTextTokenContext::StringReferenceTokenContext
683 | BNInstructionTextTokenContext::StringDisplayTokenContext => {
684 match value.value {
685 0 => Self::StringContent {
686 ty: StringType::AsciiString,
687 },
688 1 => Self::StringContent {
689 ty: StringType::Utf8String,
690 },
691 2 => Self::StringContent {
692 ty: StringType::Utf16String,
693 },
694 3 => Self::StringContent {
695 ty: StringType::Utf32String,
696 },
697 value => Self::String { value },
701 }
702 }
703 _ => Self::String { value: value.value },
704 },
705 BNInstructionTextTokenType::CharacterConstantToken => Self::CharacterConstant {
706 operand: Some(value.operand),
707 },
708 BNInstructionTextTokenType::KeywordToken => Self::Keyword { value: value.value },
709 BNInstructionTextTokenType::TypeNameToken => Self::TypeName,
710 BNInstructionTextTokenType::FieldNameToken => Self::FieldName {
711 offset: value.value,
712 type_names: value.type_names.clone(),
713 },
714 BNInstructionTextTokenType::NameSpaceToken => Self::NameSpace,
715 BNInstructionTextTokenType::NameSpaceSeparatorToken => Self::NameSpaceSeparator,
716 BNInstructionTextTokenType::TagToken => Self::Tag,
717 BNInstructionTextTokenType::StructOffsetToken => Self::StructOffset {
718 offset: value.value,
719 type_names: value.type_names.clone(),
720 },
721 BNInstructionTextTokenType::StructOffsetByteValueToken => Self::StructOffsetByteValue,
722 BNInstructionTextTokenType::StructureHexDumpTextToken => {
723 Self::StructureHexDumpText { width: value.value }
724 }
725 BNInstructionTextTokenType::GotoLabelToken => Self::GotoLabel {
726 target: value.value,
727 },
728 BNInstructionTextTokenType::CommentToken => Self::Comment {
729 target: value.value,
730 },
731 BNInstructionTextTokenType::PossibleValueToken => {
732 Self::PossibleValue { value: value.value }
733 }
734 BNInstructionTextTokenType::PossibleValueTypeToken => Self::PossibleValueType,
736 BNInstructionTextTokenType::ArrayIndexToken => Self::ArrayIndex { index: value.value },
737 BNInstructionTextTokenType::IndentationToken => Self::Indentation,
738 BNInstructionTextTokenType::UnknownMemoryToken => Self::UnknownMemory,
739 BNInstructionTextTokenType::EnumerationMemberToken => Self::EnumerationMember {
740 value: value.value,
741 type_id: value.type_names.first().cloned(),
742 },
743 BNInstructionTextTokenType::OperationToken => Self::Operation,
744 BNInstructionTextTokenType::BaseStructureNameToken => Self::BaseStructureName,
745 BNInstructionTextTokenType::BaseStructureSeparatorToken => Self::BaseStructureSeparator,
746 BNInstructionTextTokenType::BraceToken => Self::Brace {
747 hash: match value.value {
748 0 => None,
749 hash => Some(hash),
750 },
751 },
752 BNInstructionTextTokenType::ValueLocationToken => Self::ValueLocation,
753 BNInstructionTextTokenType::CodeSymbolToken => Self::CodeSymbol {
754 value: value.value,
755 size: value.size,
756 },
757 BNInstructionTextTokenType::DataSymbolToken => Self::DataSymbol {
758 value: value.value,
759 size: value.size,
760 },
761 BNInstructionTextTokenType::LocalVariableToken => Self::LocalVariable {
762 variable_id: value.value,
763 ssa_version: value.operand,
764 },
765 BNInstructionTextTokenType::ImportToken => Self::Import {
766 target: value.value,
767 },
768 BNInstructionTextTokenType::AddressDisplayToken => Self::AddressDisplay {
769 address: value.value,
770 },
771 BNInstructionTextTokenType::IndirectImportToken => Self::IndirectImport {
772 target: value.value,
773 size: value.size,
774 source_operand: value.operand,
775 },
776 BNInstructionTextTokenType::ExternalSymbolToken => {
777 Self::ExternalSymbol { value: value.value }
778 }
779 BNInstructionTextTokenType::StackVariableToken => Self::StackVariable {
780 variable_id: value.value,
781 },
782 BNInstructionTextTokenType::AddressSeparatorToken => Self::AddressSeparator,
783 BNInstructionTextTokenType::CollapsedInformationToken => Self::CollapsedInformation,
784 BNInstructionTextTokenType::CollapseStateIndicatorToken => {
785 Self::CollapseStateIndicator {
786 hash: match value.value {
787 0 => None,
788 hash => Some(hash),
789 },
790 }
791 }
792 BNInstructionTextTokenType::NewLineToken => Self::NewLine { value: value.value },
793 }
794 }
795
796 fn try_value(&self) -> Option<u64> {
798 match self {
800 InstructionTextTokenKind::Integer { value, .. } => Some(*value),
801 InstructionTextTokenKind::PossibleAddress { value, .. } => Some(*value),
802 InstructionTextTokenKind::PossibleValue { value, .. } => Some(*value),
803 InstructionTextTokenKind::FloatingPoint { value, .. } => Some(value.to_bits()),
804 InstructionTextTokenKind::CodeRelativeAddress { value, .. } => Some(*value),
805 InstructionTextTokenKind::ArgumentName { value, .. } => Some(*value),
806 InstructionTextTokenKind::HexDumpByteValue { value, .. } => Some(*value as u64),
807 InstructionTextTokenKind::HexDumpText { width, .. } => Some(*width),
808 InstructionTextTokenKind::String { value, .. } => Some(*value),
809 InstructionTextTokenKind::StringContent { ty, .. } => Some(*ty as u64),
810 InstructionTextTokenKind::Keyword { value, .. } => Some(*value),
811 InstructionTextTokenKind::FieldName { offset, .. } => Some(*offset),
812 InstructionTextTokenKind::StructOffset { offset, .. } => Some(*offset),
813 InstructionTextTokenKind::StructureHexDumpText { width, .. } => Some(*width),
814 InstructionTextTokenKind::GotoLabel { target, .. } => Some(*target),
815 InstructionTextTokenKind::Comment { target, .. } => Some(*target),
816 InstructionTextTokenKind::ArrayIndex { index, .. } => Some(*index),
817 InstructionTextTokenKind::EnumerationMember { value, .. } => Some(*value),
818 InstructionTextTokenKind::LocalVariable { variable_id, .. } => Some(*variable_id),
819 InstructionTextTokenKind::Import { target, .. } => Some(*target),
820 InstructionTextTokenKind::AddressDisplay { address, .. } => Some(*address),
821 InstructionTextTokenKind::IndirectImport { target, .. } => Some(*target),
822 InstructionTextTokenKind::Brace { hash, .. } => *hash,
823 InstructionTextTokenKind::CodeSymbol { value, .. } => Some(*value),
824 InstructionTextTokenKind::DataSymbol { value, .. } => Some(*value),
825 InstructionTextTokenKind::ExternalSymbol { value, .. } => Some(*value),
826 InstructionTextTokenKind::StackVariable { variable_id, .. } => Some(*variable_id),
827 InstructionTextTokenKind::CollapseStateIndicator { hash, .. } => *hash,
828 InstructionTextTokenKind::NewLine { value, .. } => Some(*value),
829 _ => None,
830 }
831 }
832
833 fn try_size(&self) -> Option<usize> {
835 match self {
836 InstructionTextTokenKind::Integer { size, .. } => *size,
837 InstructionTextTokenKind::FloatingPoint { size, .. } => *size,
838 InstructionTextTokenKind::PossibleAddress { size, .. } => *size,
839 InstructionTextTokenKind::CodeRelativeAddress { size, .. } => *size,
840 InstructionTextTokenKind::CodeSymbol { size, .. } => Some(*size),
841 InstructionTextTokenKind::DataSymbol { size, .. } => Some(*size),
842 InstructionTextTokenKind::IndirectImport { size, .. } => Some(*size),
843 _ => None,
844 }
845 }
846
847 fn try_operand(&self) -> Option<usize> {
849 match self {
850 InstructionTextTokenKind::Integer { operand, .. } => *operand,
851 InstructionTextTokenKind::PossibleAddress { operand, .. } => *operand,
852 InstructionTextTokenKind::CodeRelativeAddress { operand, .. } => *operand,
853 InstructionTextTokenKind::CharacterConstant { operand, .. } => *operand,
854 InstructionTextTokenKind::LocalVariable { ssa_version, .. } => Some(*ssa_version),
855 InstructionTextTokenKind::IndirectImport { source_operand, .. } => {
856 Some(*source_operand)
857 }
858 _ => None,
859 }
860 }
861
862 fn try_type_names(&self) -> Option<Vec<String>> {
864 match self {
865 InstructionTextTokenKind::FieldName { type_names, .. } => Some(type_names.clone()),
866 InstructionTextTokenKind::StructOffset { type_names, .. } => Some(type_names.clone()),
867 InstructionTextTokenKind::EnumerationMember { type_id, .. } => {
868 Some(vec![type_id.clone()?])
869 }
870 _ => None,
871 }
872 }
873}
874
875impl From<InstructionTextTokenKind> for BNInstructionTextTokenType {
876 fn from(value: InstructionTextTokenKind) -> Self {
877 match value {
878 InstructionTextTokenKind::Text => BNInstructionTextTokenType::TextToken,
879 InstructionTextTokenKind::Instruction => BNInstructionTextTokenType::InstructionToken,
880 InstructionTextTokenKind::OperandSeparator => {
881 BNInstructionTextTokenType::OperandSeparatorToken
882 }
883 InstructionTextTokenKind::Register => BNInstructionTextTokenType::RegisterToken,
884 InstructionTextTokenKind::Integer { .. } => BNInstructionTextTokenType::IntegerToken,
885 InstructionTextTokenKind::PossibleAddress { .. } => {
886 BNInstructionTextTokenType::PossibleAddressToken
887 }
888 InstructionTextTokenKind::BeginMemoryOperand => {
889 BNInstructionTextTokenType::BeginMemoryOperandToken
890 }
891 InstructionTextTokenKind::EndMemoryOperand => {
892 BNInstructionTextTokenType::EndMemoryOperandToken
893 }
894 InstructionTextTokenKind::FloatingPoint { .. } => {
895 BNInstructionTextTokenType::FloatingPointToken
896 }
897 InstructionTextTokenKind::Annotation => BNInstructionTextTokenType::AnnotationToken,
898 InstructionTextTokenKind::CodeRelativeAddress { .. } => {
899 BNInstructionTextTokenType::CodeRelativeAddressToken
900 }
901 InstructionTextTokenKind::ArgumentName { .. } => {
902 BNInstructionTextTokenType::ArgumentNameToken
903 }
904 InstructionTextTokenKind::HexDumpByteValue { .. } => {
905 BNInstructionTextTokenType::HexDumpByteValueToken
906 }
907 InstructionTextTokenKind::HexDumpSkippedByte => {
908 BNInstructionTextTokenType::HexDumpSkippedByteToken
909 }
910 InstructionTextTokenKind::HexDumpInvalidByte => {
911 BNInstructionTextTokenType::HexDumpInvalidByteToken
912 }
913 InstructionTextTokenKind::HexDumpText { .. } => {
914 BNInstructionTextTokenType::HexDumpTextToken
915 }
916 InstructionTextTokenKind::Opcode => BNInstructionTextTokenType::OpcodeToken,
917 InstructionTextTokenKind::String { .. } => BNInstructionTextTokenType::StringToken,
918 InstructionTextTokenKind::StringContent { .. } => {
919 BNInstructionTextTokenType::StringToken
920 }
921 InstructionTextTokenKind::CharacterConstant { .. } => {
922 BNInstructionTextTokenType::CharacterConstantToken
923 }
924 InstructionTextTokenKind::Keyword { .. } => BNInstructionTextTokenType::KeywordToken,
925 InstructionTextTokenKind::TypeName => BNInstructionTextTokenType::TypeNameToken,
926 InstructionTextTokenKind::FieldName { .. } => {
927 BNInstructionTextTokenType::FieldNameToken
928 }
929 InstructionTextTokenKind::NameSpace => BNInstructionTextTokenType::NameSpaceToken,
930 InstructionTextTokenKind::NameSpaceSeparator => {
931 BNInstructionTextTokenType::NameSpaceSeparatorToken
932 }
933 InstructionTextTokenKind::Tag => BNInstructionTextTokenType::TagToken,
934 InstructionTextTokenKind::StructOffset { .. } => {
935 BNInstructionTextTokenType::StructOffsetToken
936 }
937 InstructionTextTokenKind::StructOffsetByteValue => {
938 BNInstructionTextTokenType::StructOffsetByteValueToken
939 }
940 InstructionTextTokenKind::StructureHexDumpText { .. } => {
941 BNInstructionTextTokenType::StructureHexDumpTextToken
942 }
943 InstructionTextTokenKind::GotoLabel { .. } => {
944 BNInstructionTextTokenType::GotoLabelToken
945 }
946 InstructionTextTokenKind::Comment { .. } => BNInstructionTextTokenType::CommentToken,
947 InstructionTextTokenKind::PossibleValue { .. } => {
948 BNInstructionTextTokenType::PossibleValueToken
949 }
950 InstructionTextTokenKind::PossibleValueType => {
951 BNInstructionTextTokenType::PossibleValueTypeToken
952 }
953 InstructionTextTokenKind::ArrayIndex { .. } => {
954 BNInstructionTextTokenType::ArrayIndexToken
955 }
956 InstructionTextTokenKind::Indentation => BNInstructionTextTokenType::IndentationToken,
957 InstructionTextTokenKind::UnknownMemory => {
958 BNInstructionTextTokenType::UnknownMemoryToken
959 }
960 InstructionTextTokenKind::EnumerationMember { .. } => {
961 BNInstructionTextTokenType::EnumerationMemberToken
962 }
963 InstructionTextTokenKind::Operation => BNInstructionTextTokenType::OperationToken,
964 InstructionTextTokenKind::BaseStructureName => {
965 BNInstructionTextTokenType::BaseStructureNameToken
966 }
967 InstructionTextTokenKind::BaseStructureSeparator => {
968 BNInstructionTextTokenType::BaseStructureSeparatorToken
969 }
970 InstructionTextTokenKind::Brace { .. } => BNInstructionTextTokenType::BraceToken,
971 InstructionTextTokenKind::ValueLocation => {
972 BNInstructionTextTokenType::ValueLocationToken
973 }
974 InstructionTextTokenKind::CodeSymbol { .. } => {
975 BNInstructionTextTokenType::CodeSymbolToken
976 }
977 InstructionTextTokenKind::DataSymbol { .. } => {
978 BNInstructionTextTokenType::DataSymbolToken
979 }
980 InstructionTextTokenKind::LocalVariable { .. } => {
981 BNInstructionTextTokenType::LocalVariableToken
982 }
983 InstructionTextTokenKind::Import { .. } => BNInstructionTextTokenType::ImportToken,
984 InstructionTextTokenKind::AddressDisplay { .. } => {
985 BNInstructionTextTokenType::AddressDisplayToken
986 }
987 InstructionTextTokenKind::IndirectImport { .. } => {
988 BNInstructionTextTokenType::IndirectImportToken
989 }
990 InstructionTextTokenKind::ExternalSymbol { .. } => {
991 BNInstructionTextTokenType::ExternalSymbolToken
992 }
993 InstructionTextTokenKind::StackVariable { .. } => {
994 BNInstructionTextTokenType::StackVariableToken
995 }
996 InstructionTextTokenKind::AddressSeparator => {
997 BNInstructionTextTokenType::AddressSeparatorToken
998 }
999 InstructionTextTokenKind::CollapsedInformation => {
1000 BNInstructionTextTokenType::CollapsedInformationToken
1001 }
1002 InstructionTextTokenKind::CollapseStateIndicator { .. } => {
1003 BNInstructionTextTokenType::CollapseStateIndicatorToken
1004 }
1005 InstructionTextTokenKind::NewLine { .. } => BNInstructionTextTokenType::NewLineToken,
1006 }
1007 }
1008}
1009
1010impl Eq for InstructionTextTokenKind {}
1011
1012#[derive(Clone, Copy, PartialEq, Eq, Debug)]
1013pub enum InstructionTextTokenContext {
1014 Normal,
1015 LocalVariable,
1016 DataVariable,
1017 FunctionReturn,
1018 InstructionAddress,
1019 ILInstructionIndex,
1020 ConstData,
1021 ConstStringData,
1023 StringReference,
1025 StringDataVariable,
1027 StringDisplay,
1031 Collapsed,
1033 Expanded,
1035 CollapsiblePadding,
1037 DerivedStringReference,
1039}
1040
1041impl From<BNInstructionTextTokenContext> for InstructionTextTokenContext {
1042 fn from(value: BNInstructionTextTokenContext) -> Self {
1043 match value {
1044 BNInstructionTextTokenContext::NoTokenContext => Self::Normal,
1045 BNInstructionTextTokenContext::LocalVariableTokenContext => Self::LocalVariable,
1046 BNInstructionTextTokenContext::DataVariableTokenContext => Self::DataVariable,
1047 BNInstructionTextTokenContext::FunctionReturnTokenContext => Self::FunctionReturn,
1048 BNInstructionTextTokenContext::InstructionAddressTokenContext => {
1049 Self::InstructionAddress
1050 }
1051 BNInstructionTextTokenContext::ILInstructionIndexTokenContext => {
1052 Self::ILInstructionIndex
1053 }
1054 BNInstructionTextTokenContext::ConstDataTokenContext => Self::ConstData,
1055 BNInstructionTextTokenContext::ConstStringDataTokenContext => Self::ConstStringData,
1057 BNInstructionTextTokenContext::StringReferenceTokenContext => Self::StringReference,
1058 BNInstructionTextTokenContext::StringDataVariableTokenContext => {
1059 Self::StringDataVariable
1060 }
1061 BNInstructionTextTokenContext::StringDisplayTokenContext => Self::StringDisplay,
1062 BNInstructionTextTokenContext::ContentCollapsedContext => Self::Collapsed,
1064 BNInstructionTextTokenContext::ContentExpandedContext => Self::Expanded,
1065 BNInstructionTextTokenContext::ContentCollapsiblePadding => Self::CollapsiblePadding,
1066 BNInstructionTextTokenContext::DerivedStringReferenceTokenContext => {
1067 Self::DerivedStringReference
1068 }
1069 }
1070 }
1071}
1072
1073impl From<InstructionTextTokenContext> for BNInstructionTextTokenContext {
1074 fn from(value: InstructionTextTokenContext) -> Self {
1075 match value {
1076 InstructionTextTokenContext::Normal => Self::NoTokenContext,
1077 InstructionTextTokenContext::LocalVariable => Self::LocalVariableTokenContext,
1078 InstructionTextTokenContext::DataVariable => Self::DataVariableTokenContext,
1079 InstructionTextTokenContext::FunctionReturn => Self::FunctionReturnTokenContext,
1080 InstructionTextTokenContext::InstructionAddress => Self::InstructionAddressTokenContext,
1081 InstructionTextTokenContext::ILInstructionIndex => Self::ILInstructionIndexTokenContext,
1082 InstructionTextTokenContext::ConstData => Self::ConstDataTokenContext,
1083 InstructionTextTokenContext::ConstStringData => Self::ConstStringDataTokenContext,
1084 InstructionTextTokenContext::StringReference => Self::StringReferenceTokenContext,
1085 InstructionTextTokenContext::StringDataVariable => Self::StringDataVariableTokenContext,
1086 InstructionTextTokenContext::StringDisplay => Self::StringDisplayTokenContext,
1087 InstructionTextTokenContext::Collapsed => Self::ContentCollapsedContext,
1088 InstructionTextTokenContext::Expanded => Self::ContentExpandedContext,
1089 InstructionTextTokenContext::CollapsiblePadding => Self::ContentCollapsiblePadding,
1090 InstructionTextTokenContext::DerivedStringReference => {
1091 Self::DerivedStringReferenceTokenContext
1092 }
1093 }
1094 }
1095}
1096
1097#[repr(transparent)]
1098pub struct DisassemblyTextRenderer {
1099 handle: NonNull<BNDisassemblyTextRenderer>,
1100}
1101
1102impl DisassemblyTextRenderer {
1103 pub unsafe fn ref_from_raw(handle: NonNull<BNDisassemblyTextRenderer>) -> Ref<Self> {
1104 Ref::new(Self { handle })
1105 }
1106
1107 pub fn from_function(func: &Function, settings: Option<&DisassemblySettings>) -> Ref<Self> {
1108 let settings_ptr = settings.map(|s| s.handle).unwrap_or(ptr::null_mut());
1109 let result = unsafe { BNCreateDisassemblyTextRenderer(func.handle, settings_ptr) };
1110 unsafe { Self::ref_from_raw(NonNull::new(result).unwrap()) }
1111 }
1112
1113 pub fn from_llil<M: FunctionMutability, F: FunctionForm>(
1114 func: &LowLevelILFunction<M, F>,
1115 settings: Option<&DisassemblySettings>,
1116 ) -> Ref<Self> {
1117 let settings_ptr = settings.map(|s| s.handle).unwrap_or(ptr::null_mut());
1118 let result =
1119 unsafe { BNCreateLowLevelILDisassemblyTextRenderer(func.handle, settings_ptr) };
1120 unsafe { Self::ref_from_raw(NonNull::new(result).unwrap()) }
1121 }
1122
1123 pub fn from_mlil(
1124 func: &MediumLevelILFunction,
1125 settings: Option<&DisassemblySettings>,
1126 ) -> Ref<Self> {
1127 let settings_ptr = settings.map(|s| s.handle).unwrap_or(ptr::null_mut());
1128 let result =
1129 unsafe { BNCreateMediumLevelILDisassemblyTextRenderer(func.handle, settings_ptr) };
1130 unsafe { Self::ref_from_raw(NonNull::new(result).unwrap()) }
1131 }
1132
1133 pub fn from_hlil(
1134 func: &HighLevelILFunction,
1135 settings: Option<&DisassemblySettings>,
1136 ) -> Ref<Self> {
1137 let settings_ptr = settings.map(|s| s.handle).unwrap_or(ptr::null_mut());
1138 let result =
1139 unsafe { BNCreateHighLevelILDisassemblyTextRenderer(func.handle, settings_ptr) };
1140 unsafe { Self::ref_from_raw(NonNull::new(result).unwrap()) }
1141 }
1142
1143 pub fn function(&self) -> Ref<Function> {
1144 let result = unsafe { BNGetDisassemblyTextRendererFunction(self.handle.as_ptr()) };
1145 assert!(!result.is_null());
1146 unsafe { Function::ref_from_raw(result) }
1147 }
1148
1149 pub fn llil<M: FunctionMutability, F: FunctionForm>(&self) -> Ref<LowLevelILFunction<M, F>> {
1150 let result =
1151 unsafe { BNGetDisassemblyTextRendererLowLevelILFunction(self.handle.as_ptr()) };
1152 assert!(!result.is_null());
1153 unsafe { LowLevelILFunction::ref_from_raw(result) }
1154 }
1155
1156 pub fn mlil(&self) -> Ref<MediumLevelILFunction> {
1157 let result =
1158 unsafe { BNGetDisassemblyTextRendererMediumLevelILFunction(self.handle.as_ptr()) };
1159 assert!(!result.is_null());
1160 unsafe { MediumLevelILFunction::ref_from_raw(result) }
1161 }
1162
1163 pub fn hlil(&self) -> Ref<HighLevelILFunction> {
1164 let result =
1165 unsafe { BNGetDisassemblyTextRendererHighLevelILFunction(self.handle.as_ptr()) };
1166 assert!(!result.is_null());
1167 unsafe { HighLevelILFunction::ref_from_raw(result, true) }
1168 }
1169
1170 pub fn basic_block(&self) -> Option<Ref<BasicBlock<NativeBlock>>> {
1171 let result = unsafe { BNGetDisassemblyTextRendererBasicBlock(self.handle.as_ptr()) };
1172 if result.is_null() {
1173 return None;
1174 }
1175 Some(unsafe { Ref::new(BasicBlock::from_raw(result, NativeBlock::new())) })
1176 }
1177
1178 pub fn set_basic_block(&self, value: Option<&BasicBlock<NativeBlock>>) {
1179 let block_ptr = value.map(|b| b.handle).unwrap_or(ptr::null_mut());
1180 unsafe { BNSetDisassemblyTextRendererBasicBlock(self.handle.as_ptr(), block_ptr) }
1181 }
1182
1183 pub fn arch(&self) -> CoreArchitecture {
1184 let result = unsafe { BNGetDisassemblyTextRendererArchitecture(self.handle.as_ptr()) };
1185 assert!(!result.is_null());
1186 unsafe { CoreArchitecture::from_raw(result) }
1187 }
1188
1189 pub fn set_arch(&self, value: CoreArchitecture) {
1190 unsafe { BNSetDisassemblyTextRendererArchitecture(self.handle.as_ptr(), value.handle) }
1191 }
1192
1193 pub fn settings(&self) -> Ref<DisassemblySettings> {
1194 let result = unsafe { BNGetDisassemblyTextRendererSettings(self.handle.as_ptr()) };
1195 unsafe { DisassemblySettings::ref_from_raw(result) }
1196 }
1197
1198 pub fn set_settings(&self, settings: Option<&DisassemblySettings>) {
1199 let settings_ptr = settings.map(|s| s.handle).unwrap_or(ptr::null_mut());
1200 unsafe { BNSetDisassemblyTextRendererSettings(self.handle.as_ptr(), settings_ptr) }
1201 }
1202
1203 pub fn is_il(&self) -> bool {
1204 unsafe { BNIsILDisassemblyTextRenderer(self.handle.as_ptr()) }
1205 }
1206
1207 pub fn has_data_flow(&self) -> bool {
1208 unsafe { BNDisassemblyTextRendererHasDataFlow(self.handle.as_ptr()) }
1209 }
1210
1211 pub fn instruction_annotations(&self, addr: u64) -> Array<InstructionTextToken> {
1213 let mut count = 0;
1214 let result = unsafe {
1215 BNGetDisassemblyTextRendererInstructionAnnotations(
1216 self.handle.as_ptr(),
1217 addr,
1218 &mut count,
1219 )
1220 };
1221 assert!(!result.is_null());
1222 unsafe { Array::new(result, count, ()) }
1223 }
1224
1225 pub fn instruction_text(&self, addr: u64) -> Option<(Array<DisassemblyTextLine>, usize)> {
1227 let mut count = 0;
1228 let mut length = 0;
1229 let mut lines: *mut BNDisassemblyTextLine = ptr::null_mut();
1230 let result = unsafe {
1231 BNGetDisassemblyTextRendererInstructionText(
1232 self.handle.as_ptr(),
1233 addr,
1234 &mut length,
1235 &mut lines,
1236 &mut count,
1237 )
1238 };
1239 result.then(|| (unsafe { Array::new(lines, count, ()) }, length))
1240 }
1241
1242 pub fn disassembly_text(&self, addr: u64) -> Option<(Array<DisassemblyTextLine>, usize)> {
1244 let mut count = 0;
1245 let mut length = 0;
1246 let mut lines: *mut BNDisassemblyTextLine = ptr::null_mut();
1247 let result = unsafe {
1248 BNGetDisassemblyTextRendererLines(
1249 self.handle.as_ptr(),
1250 addr,
1251 &mut length,
1252 &mut lines,
1253 &mut count,
1254 )
1255 };
1256 result.then(|| (unsafe { Array::new(lines, count, ()) }, length))
1257 }
1258
1259 pub fn is_integer_token(token_type: InstructionTextTokenType) -> bool {
1262 unsafe { BNIsIntegerToken(token_type) }
1263 }
1264
1265 pub fn reset_deduplicated_comments(&self) {
1266 unsafe { BNResetDisassemblyTextRendererDeduplicatedComments(self.handle.as_ptr()) }
1267 }
1268
1269 pub fn symbol_tokens(
1270 &self,
1271 addr: u64,
1272 size: usize,
1273 operand: Option<usize>,
1274 ) -> Option<Array<InstructionTextToken>> {
1275 let operand = operand.unwrap_or(0xffffffff);
1276 let mut count = 0;
1277 let mut tokens: *mut BNInstructionTextToken = ptr::null_mut();
1278 let result = unsafe {
1279 BNGetDisassemblyTextRendererSymbolTokens(
1280 self.handle.as_ptr(),
1281 addr,
1282 size,
1283 operand,
1284 &mut tokens,
1285 &mut count,
1286 )
1287 };
1288 result.then(|| unsafe { Array::new(tokens, count, ()) })
1289 }
1290
1291 pub fn stack_var_reference_tokens(
1292 &self,
1293 stack_ref: StackVariableReference,
1294 ) -> Array<InstructionTextToken> {
1295 let mut stack_ref_raw = StackVariableReference::into_raw(stack_ref);
1296 let mut count = 0;
1297 let tokens = unsafe {
1298 BNGetDisassemblyTextRendererStackVariableReferenceTokens(
1299 self.handle.as_ptr(),
1300 &mut stack_ref_raw,
1301 &mut count,
1302 )
1303 };
1304 StackVariableReference::free_raw(stack_ref_raw);
1305 assert!(!tokens.is_null());
1306 unsafe { Array::new(tokens, count, ()) }
1307 }
1308
1309 pub fn integer_token(
1310 &self,
1311 int_token: InstructionTextToken,
1312 location: impl Into<Location>,
1313 ) -> Array<InstructionTextToken> {
1314 let location = location.into();
1315 let arch = location
1316 .arch
1317 .map(|a| a.handle)
1318 .unwrap_or_else(std::ptr::null_mut);
1319 let mut count = 0;
1320 let mut int_token_raw = InstructionTextToken::into_raw(int_token);
1321 let tokens = unsafe {
1322 BNGetDisassemblyTextRendererIntegerTokens(
1323 self.handle.as_ptr(),
1324 &mut int_token_raw,
1325 arch,
1326 location.addr,
1327 &mut count,
1328 )
1329 };
1330 InstructionTextToken::free_raw(int_token_raw);
1331 assert!(!tokens.is_null());
1332 unsafe { Array::new(tokens, count, ()) }
1333 }
1334
1335 pub fn wrap_comment(
1336 &self,
1337 cur_line: DisassemblyTextLine,
1338 comment: &str,
1339 has_auto_annotations: bool,
1340 leading_spaces: &str,
1341 indent_spaces: &str,
1342 ) -> Array<DisassemblyTextLine> {
1343 let cur_line_raw = DisassemblyTextLine::into_raw(cur_line);
1344 let comment_raw = comment.to_cstr();
1345 let leading_spaces_raw = leading_spaces.to_cstr();
1346 let indent_spaces_raw = indent_spaces.to_cstr();
1347 let mut count = 0;
1348 let lines = unsafe {
1349 BNDisassemblyTextRendererWrapComment(
1350 self.handle.as_ptr(),
1351 &cur_line_raw,
1352 &mut count,
1353 comment_raw.as_ref().as_ptr() as *const ffi::c_char,
1354 has_auto_annotations,
1355 leading_spaces_raw.as_ref().as_ptr() as *const ffi::c_char,
1356 indent_spaces_raw.as_ref().as_ptr() as *const ffi::c_char,
1357 )
1358 };
1359 DisassemblyTextLine::free_raw(cur_line_raw);
1360 assert!(!lines.is_null());
1361 unsafe { Array::new(lines, count, ()) }
1362 }
1363}
1364
1365impl ToOwned for DisassemblyTextRenderer {
1366 type Owned = Ref<Self>;
1367
1368 fn to_owned(&self) -> Self::Owned {
1369 unsafe { RefCountable::inc_ref(self) }
1370 }
1371}
1372
1373unsafe impl RefCountable for DisassemblyTextRenderer {
1374 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
1375 Ref::new(Self {
1376 handle: NonNull::new(BNNewDisassemblyTextRendererReference(
1377 handle.handle.as_ptr(),
1378 ))
1379 .unwrap(),
1380 })
1381 }
1382
1383 unsafe fn dec_ref(handle: &Self) {
1384 BNFreeDisassemblyTextRenderer(handle.handle.as_ptr());
1385 }
1386}
1387
1388#[derive(PartialEq, Eq, Hash)]
1390pub struct DisassemblySettings {
1391 pub(crate) handle: *mut BNDisassemblySettings,
1392}
1393
1394impl DisassemblySettings {
1395 pub fn ref_from_raw(handle: *mut BNDisassemblySettings) -> Ref<Self> {
1396 debug_assert!(!handle.is_null());
1397 unsafe { Ref::new(Self { handle }) }
1398 }
1399
1400 pub fn new() -> Ref<Self> {
1401 let handle = unsafe { BNCreateDisassemblySettings() };
1402 Self::ref_from_raw(handle)
1403 }
1404
1405 pub fn set_option(&self, option: DisassemblyOption, state: bool) {
1406 unsafe { BNSetDisassemblySettingsOption(self.handle, option, state) }
1407 }
1408
1409 pub fn is_option_set(&self, option: DisassemblyOption) -> bool {
1410 unsafe { BNIsDisassemblySettingsOptionSet(self.handle, option) }
1411 }
1412}
1413
1414impl ToOwned for DisassemblySettings {
1415 type Owned = Ref<Self>;
1416
1417 fn to_owned(&self) -> Self::Owned {
1418 unsafe { RefCountable::inc_ref(self) }
1419 }
1420}
1421
1422unsafe impl RefCountable for DisassemblySettings {
1423 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
1424 Ref::new(Self {
1425 handle: BNNewDisassemblySettingsReference(handle.handle),
1426 })
1427 }
1428
1429 unsafe fn dec_ref(handle: &Self) {
1430 BNFreeDisassemblySettings(handle.handle);
1431 }
1432}