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};
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 kind: InstructionTextTokenKind,
271}
272
273impl InstructionTextToken {
274 pub(crate) fn from_raw(value: &BNInstructionTextToken) -> Self {
275 Self {
276 address: value.address,
277 text: raw_to_string(value.text).unwrap(),
278 confidence: value.confidence,
279 context: value.context.into(),
280 expr_index: match value.exprIndex {
281 BN_INVALID_EXPR => None,
282 index => Some(index),
283 },
284 kind: InstructionTextTokenKind::from_raw(value),
285 }
286 }
287
288 pub(crate) fn into_raw(value: Self) -> BNInstructionTextToken {
289 let bn_text = BnString::new(value.text);
290 let kind_value = value.kind.try_value().unwrap_or(0);
292 let operand = value.kind.try_operand().unwrap_or(0);
293 let size = value.kind.try_size().unwrap_or(0);
294 let type_names = value.kind.try_type_names().unwrap_or_default();
295 BNInstructionTextToken {
296 type_: value.kind.into(),
297 text: BnString::into_raw(bn_text),
299 value: kind_value,
300 width: 0,
302 size,
303 operand,
304 context: value.context.into(),
305 confidence: value.confidence,
306 address: value.address,
307 typeNames: strings_to_string_list(&type_names),
309 namesCount: type_names.len(),
310 exprIndex: value.expr_index.unwrap_or(BN_INVALID_EXPR),
311 }
312 }
313
314 pub(crate) fn free_raw(value: BNInstructionTextToken) {
315 unsafe { BnString::free_raw(value.text) };
316 if !value.typeNames.is_null() {
317 unsafe { BNFreeStringList(value.typeNames, value.namesCount) };
318 }
319 }
320
321 pub fn new(text: impl Into<String>, kind: InstructionTextTokenKind) -> Self {
326 Self {
327 address: 0,
328 text: text.into(),
329 confidence: MAX_CONFIDENCE,
330 context: InstructionTextTokenContext::Normal,
331 expr_index: None,
332 kind,
333 }
334 }
335
336 pub fn new_with_address(
337 address: u64,
338 text: impl Into<String>,
339 kind: InstructionTextTokenKind,
340 ) -> Self {
341 Self {
342 address,
343 text: text.into(),
344 confidence: MAX_CONFIDENCE,
345 context: InstructionTextTokenContext::Normal,
346 expr_index: None,
347 kind,
348 }
349 }
350}
351
352impl Display for InstructionTextToken {
353 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
354 self.text.fmt(f)
355 }
356}
357
358impl CoreArrayProvider for InstructionTextToken {
359 type Raw = BNInstructionTextToken;
360 type Context = ();
361 type Wrapped<'a> = Self;
362}
363
364unsafe impl CoreArrayProviderInner for InstructionTextToken {
365 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
366 BNFreeInstructionText(raw, count)
368 }
369
370 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
371 Self::from_raw(raw)
372 }
373}
374
375impl CoreArrayProvider for Array<InstructionTextToken> {
376 type Raw = BNInstructionTextLine;
377 type Context = ();
378 type Wrapped<'a> = std::mem::ManuallyDrop<Self>;
379}
380
381unsafe impl CoreArrayProviderInner for Array<InstructionTextToken> {
382 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
383 BNFreeInstructionTextLines(raw, count)
385 }
386
387 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
388 std::mem::ManuallyDrop::new(Self::new(raw.tokens, raw.count, ()))
390 }
391}
392
393#[derive(Clone, PartialEq, Debug)]
394pub enum InstructionTextTokenKind {
395 Text,
396 Instruction,
397 OperandSeparator,
398 Register,
399 Integer {
400 value: u64,
401 size: Option<usize>,
403 },
404 PossibleAddress {
405 value: u64,
406 size: Option<usize>,
408 },
409 BeginMemoryOperand,
410 EndMemoryOperand,
411 FloatingPoint {
412 value: f64,
413 size: Option<usize>,
415 },
416 Annotation,
417 CodeRelativeAddress {
418 value: u64,
419 size: Option<usize>,
420 },
421 ArgumentName {
422 value: u64,
424 },
425 HexDumpByteValue {
426 value: u8,
427 },
428 HexDumpSkippedByte,
429 HexDumpInvalidByte,
430 HexDumpText {
431 width: u64,
433 },
434 Opcode,
435 String {
436 value: u64,
439 },
440 StringContent {
444 ty: StringType,
445 },
446 CharacterConstant,
447 Keyword {
448 value: u64,
450 },
451 TypeName,
452 FieldName {
453 offset: u64,
455 type_names: Vec<String>,
460 },
461 NameSpace,
462 NameSpaceSeparator,
463 Tag,
464 StructOffset {
465 offset: u64,
467 type_names: Vec<String>,
470 },
471 StructOffsetByteValue,
473 StructureHexDumpText {
475 width: u64,
477 },
478 GotoLabel {
479 target: u64,
480 },
481 Comment {
482 target: u64,
483 },
484 PossibleValue {
485 value: u64,
486 },
487 PossibleValueType,
489 ArrayIndex {
490 index: u64,
491 },
492 Indentation,
493 UnknownMemory,
494 EnumerationMember {
495 value: u64,
496 type_id: Option<String>,
500 },
501 Operation,
503 BaseStructureName,
504 BaseStructureSeparator,
505 Brace {
506 hash: Option<u64>,
508 },
509 CodeSymbol {
510 value: u64,
512 size: usize, },
515 DataSymbol {
516 value: u64,
518 size: usize, },
521 LocalVariable {
522 variable_id: u64,
526 ssa_version: usize,
528 },
529 Import {
530 target: u64,
532 },
533 AddressDisplay {
534 address: u64,
535 },
536 IndirectImport {
538 target: u64,
542 size: usize,
544 source_operand: usize,
546 },
547 ExternalSymbol {
548 value: u64,
550 },
551 StackVariable {
552 variable_id: u64,
555 },
556 AddressSeparator,
557 CollapsedInformation,
558 CollapseStateIndicator {
559 hash: Option<u64>,
561 },
562 NewLine {
563 value: u64,
565 },
566}
567
568impl InstructionTextTokenKind {
569 pub(crate) fn from_raw(value: &BNInstructionTextToken) -> Self {
570 match value.type_ {
571 BNInstructionTextTokenType::TextToken => Self::Text,
572 BNInstructionTextTokenType::InstructionToken => Self::Instruction,
573 BNInstructionTextTokenType::OperandSeparatorToken => Self::OperandSeparator,
574 BNInstructionTextTokenType::RegisterToken => Self::Register,
575 BNInstructionTextTokenType::IntegerToken => Self::Integer {
576 value: value.value,
577 size: match value.size {
578 0 => None,
579 size => Some(size),
580 },
581 },
582 BNInstructionTextTokenType::PossibleAddressToken => Self::PossibleAddress {
583 value: value.value,
584 size: match value.size {
585 0 => None,
586 size => Some(size),
587 },
588 },
589 BNInstructionTextTokenType::BeginMemoryOperandToken => Self::BeginMemoryOperand,
590 BNInstructionTextTokenType::EndMemoryOperandToken => Self::EndMemoryOperand,
591 BNInstructionTextTokenType::FloatingPointToken => Self::FloatingPoint {
592 value: value.value as f64,
593 size: match value.size {
594 0 => None,
595 size => Some(size),
596 },
597 },
598 BNInstructionTextTokenType::AnnotationToken => Self::Annotation,
599 BNInstructionTextTokenType::CodeRelativeAddressToken => Self::CodeRelativeAddress {
600 value: value.value,
601 size: match value.size {
602 0 => None,
603 size => Some(size),
604 },
605 },
606 BNInstructionTextTokenType::ArgumentNameToken => {
607 Self::ArgumentName { value: value.value }
608 }
609 BNInstructionTextTokenType::HexDumpByteValueToken => Self::HexDumpByteValue {
610 value: value.value as u8,
611 },
612 BNInstructionTextTokenType::HexDumpSkippedByteToken => Self::HexDumpSkippedByte,
613 BNInstructionTextTokenType::HexDumpInvalidByteToken => Self::HexDumpInvalidByte,
614 BNInstructionTextTokenType::HexDumpTextToken => {
615 Self::HexDumpText { width: value.value }
616 }
617 BNInstructionTextTokenType::OpcodeToken => Self::Opcode,
618 BNInstructionTextTokenType::StringToken => match value.context {
619 BNInstructionTextTokenContext::StringReferenceTokenContext
620 | BNInstructionTextTokenContext::StringDisplayTokenContext => {
621 match value.value {
622 0 => Self::StringContent {
623 ty: StringType::AsciiString,
624 },
625 1 => Self::StringContent {
626 ty: StringType::Utf8String,
627 },
628 2 => Self::StringContent {
629 ty: StringType::Utf16String,
630 },
631 3 => Self::StringContent {
632 ty: StringType::Utf32String,
633 },
634 value => Self::String { value },
638 }
639 }
640 _ => Self::String { value: value.value },
641 },
642 BNInstructionTextTokenType::CharacterConstantToken => Self::CharacterConstant,
643 BNInstructionTextTokenType::KeywordToken => Self::Keyword { value: value.value },
644 BNInstructionTextTokenType::TypeNameToken => Self::TypeName,
645 BNInstructionTextTokenType::FieldNameToken => Self::FieldName {
646 offset: value.value,
647 type_names: {
648 let raw_names =
650 unsafe { std::slice::from_raw_parts(value.typeNames, value.namesCount) };
651 raw_names.iter().filter_map(|&r| raw_to_string(r)).collect()
652 },
653 },
654 BNInstructionTextTokenType::NameSpaceToken => Self::NameSpace,
655 BNInstructionTextTokenType::NameSpaceSeparatorToken => Self::NameSpaceSeparator,
656 BNInstructionTextTokenType::TagToken => Self::Tag,
657 BNInstructionTextTokenType::StructOffsetToken => Self::StructOffset {
658 offset: value.value,
659 type_names: {
660 let raw_names =
662 unsafe { std::slice::from_raw_parts(value.typeNames, value.namesCount) };
663 raw_names.iter().filter_map(|&r| raw_to_string(r)).collect()
664 },
665 },
666 BNInstructionTextTokenType::StructOffsetByteValueToken => Self::StructOffsetByteValue,
667 BNInstructionTextTokenType::StructureHexDumpTextToken => {
668 Self::StructureHexDumpText { width: value.value }
669 }
670 BNInstructionTextTokenType::GotoLabelToken => Self::GotoLabel {
671 target: value.value,
672 },
673 BNInstructionTextTokenType::CommentToken => Self::Comment {
674 target: value.value,
675 },
676 BNInstructionTextTokenType::PossibleValueToken => {
677 Self::PossibleValue { value: value.value }
678 }
679 BNInstructionTextTokenType::PossibleValueTypeToken => Self::PossibleValueType,
681 BNInstructionTextTokenType::ArrayIndexToken => Self::ArrayIndex { index: value.value },
682 BNInstructionTextTokenType::IndentationToken => Self::Indentation,
683 BNInstructionTextTokenType::UnknownMemoryToken => Self::UnknownMemory,
684 BNInstructionTextTokenType::EnumerationMemberToken => Self::EnumerationMember {
685 value: value.value,
686 type_id: {
687 let raw_names =
690 unsafe { std::slice::from_raw_parts(value.typeNames, value.namesCount) };
691 raw_names.iter().filter_map(|&r| raw_to_string(r)).next()
692 },
693 },
694 BNInstructionTextTokenType::OperationToken => Self::Operation,
695 BNInstructionTextTokenType::BaseStructureNameToken => Self::BaseStructureName,
696 BNInstructionTextTokenType::BaseStructureSeparatorToken => Self::BaseStructureSeparator,
697 BNInstructionTextTokenType::BraceToken => Self::Brace {
698 hash: match value.value {
699 0 => None,
700 hash => Some(hash),
701 },
702 },
703 BNInstructionTextTokenType::CodeSymbolToken => Self::CodeSymbol {
704 value: value.value,
705 size: value.size,
706 },
707 BNInstructionTextTokenType::DataSymbolToken => Self::DataSymbol {
708 value: value.value,
709 size: value.size,
710 },
711 BNInstructionTextTokenType::LocalVariableToken => Self::LocalVariable {
712 variable_id: value.value,
713 ssa_version: value.operand,
714 },
715 BNInstructionTextTokenType::ImportToken => Self::Import {
716 target: value.value,
717 },
718 BNInstructionTextTokenType::AddressDisplayToken => Self::AddressDisplay {
719 address: value.value,
720 },
721 BNInstructionTextTokenType::IndirectImportToken => Self::IndirectImport {
722 target: value.value,
723 size: value.size,
724 source_operand: value.operand,
725 },
726 BNInstructionTextTokenType::ExternalSymbolToken => {
727 Self::ExternalSymbol { value: value.value }
728 }
729 BNInstructionTextTokenType::StackVariableToken => Self::StackVariable {
730 variable_id: value.value,
731 },
732 BNInstructionTextTokenType::AddressSeparatorToken => Self::AddressSeparator,
733 BNInstructionTextTokenType::CollapsedInformationToken => Self::CollapsedInformation,
734 BNInstructionTextTokenType::CollapseStateIndicatorToken => {
735 Self::CollapseStateIndicator {
736 hash: match value.value {
737 0 => None,
738 hash => Some(hash),
739 },
740 }
741 }
742 BNInstructionTextTokenType::NewLineToken => Self::NewLine { value: value.value },
743 }
744 }
745
746 fn try_value(&self) -> Option<u64> {
748 match self {
750 InstructionTextTokenKind::Integer { value, .. } => Some(*value),
751 InstructionTextTokenKind::PossibleAddress { value, .. } => Some(*value),
752 InstructionTextTokenKind::PossibleValue { value, .. } => Some(*value),
753 InstructionTextTokenKind::FloatingPoint { value, .. } => Some(*value as u64),
754 InstructionTextTokenKind::CodeRelativeAddress { value, .. } => Some(*value),
755 InstructionTextTokenKind::ArgumentName { value, .. } => Some(*value),
756 InstructionTextTokenKind::HexDumpByteValue { value, .. } => Some(*value as u64),
757 InstructionTextTokenKind::HexDumpText { width, .. } => Some(*width),
758 InstructionTextTokenKind::String { value, .. } => Some(*value),
759 InstructionTextTokenKind::StringContent { ty, .. } => Some(*ty as u64),
760 InstructionTextTokenKind::Keyword { value, .. } => Some(*value),
761 InstructionTextTokenKind::FieldName { offset, .. } => Some(*offset),
762 InstructionTextTokenKind::StructOffset { offset, .. } => Some(*offset),
763 InstructionTextTokenKind::StructureHexDumpText { width, .. } => Some(*width),
764 InstructionTextTokenKind::GotoLabel { target, .. } => Some(*target),
765 InstructionTextTokenKind::Comment { target, .. } => Some(*target),
766 InstructionTextTokenKind::ArrayIndex { index, .. } => Some(*index),
767 InstructionTextTokenKind::EnumerationMember { value, .. } => Some(*value),
768 InstructionTextTokenKind::LocalVariable { variable_id, .. } => Some(*variable_id),
769 InstructionTextTokenKind::Import { target, .. } => Some(*target),
770 InstructionTextTokenKind::AddressDisplay { address, .. } => Some(*address),
771 InstructionTextTokenKind::IndirectImport { target, .. } => Some(*target),
772 InstructionTextTokenKind::Brace { hash, .. } => *hash,
773 InstructionTextTokenKind::CodeSymbol { value, .. } => Some(*value),
774 InstructionTextTokenKind::DataSymbol { value, .. } => Some(*value),
775 InstructionTextTokenKind::ExternalSymbol { value, .. } => Some(*value),
776 InstructionTextTokenKind::StackVariable { variable_id, .. } => Some(*variable_id),
777 InstructionTextTokenKind::CollapseStateIndicator { hash, .. } => *hash,
778 InstructionTextTokenKind::NewLine { value, .. } => Some(*value),
779 _ => None,
780 }
781 }
782
783 fn try_size(&self) -> Option<usize> {
785 match self {
786 InstructionTextTokenKind::Integer { size, .. } => *size,
787 InstructionTextTokenKind::FloatingPoint { size, .. } => *size,
788 InstructionTextTokenKind::PossibleAddress { size, .. } => *size,
789 InstructionTextTokenKind::CodeRelativeAddress { size, .. } => *size,
790 InstructionTextTokenKind::CodeSymbol { size, .. } => Some(*size),
791 InstructionTextTokenKind::DataSymbol { size, .. } => Some(*size),
792 InstructionTextTokenKind::IndirectImport { size, .. } => Some(*size),
793 _ => None,
794 }
795 }
796
797 fn try_operand(&self) -> Option<usize> {
799 match self {
800 InstructionTextTokenKind::LocalVariable { ssa_version, .. } => Some(*ssa_version),
801 InstructionTextTokenKind::IndirectImport { source_operand, .. } => {
802 Some(*source_operand)
803 }
804 _ => None,
805 }
806 }
807
808 fn try_type_names(&self) -> Option<Vec<String>> {
810 match self {
811 InstructionTextTokenKind::FieldName { type_names, .. } => Some(type_names.clone()),
812 InstructionTextTokenKind::StructOffset { type_names, .. } => Some(type_names.clone()),
813 InstructionTextTokenKind::EnumerationMember { type_id, .. } => {
814 Some(vec![type_id.clone()?])
815 }
816 _ => None,
817 }
818 }
819}
820
821impl From<InstructionTextTokenKind> for BNInstructionTextTokenType {
822 fn from(value: InstructionTextTokenKind) -> Self {
823 match value {
824 InstructionTextTokenKind::Text => BNInstructionTextTokenType::TextToken,
825 InstructionTextTokenKind::Instruction => BNInstructionTextTokenType::InstructionToken,
826 InstructionTextTokenKind::OperandSeparator => {
827 BNInstructionTextTokenType::OperandSeparatorToken
828 }
829 InstructionTextTokenKind::Register => BNInstructionTextTokenType::RegisterToken,
830 InstructionTextTokenKind::Integer { .. } => BNInstructionTextTokenType::IntegerToken,
831 InstructionTextTokenKind::PossibleAddress { .. } => {
832 BNInstructionTextTokenType::PossibleAddressToken
833 }
834 InstructionTextTokenKind::BeginMemoryOperand => {
835 BNInstructionTextTokenType::BeginMemoryOperandToken
836 }
837 InstructionTextTokenKind::EndMemoryOperand => {
838 BNInstructionTextTokenType::EndMemoryOperandToken
839 }
840 InstructionTextTokenKind::FloatingPoint { .. } => {
841 BNInstructionTextTokenType::FloatingPointToken
842 }
843 InstructionTextTokenKind::Annotation => BNInstructionTextTokenType::AnnotationToken,
844 InstructionTextTokenKind::CodeRelativeAddress { .. } => {
845 BNInstructionTextTokenType::CodeRelativeAddressToken
846 }
847 InstructionTextTokenKind::ArgumentName { .. } => {
848 BNInstructionTextTokenType::ArgumentNameToken
849 }
850 InstructionTextTokenKind::HexDumpByteValue { .. } => {
851 BNInstructionTextTokenType::HexDumpByteValueToken
852 }
853 InstructionTextTokenKind::HexDumpSkippedByte => {
854 BNInstructionTextTokenType::HexDumpSkippedByteToken
855 }
856 InstructionTextTokenKind::HexDumpInvalidByte => {
857 BNInstructionTextTokenType::HexDumpInvalidByteToken
858 }
859 InstructionTextTokenKind::HexDumpText { .. } => {
860 BNInstructionTextTokenType::HexDumpTextToken
861 }
862 InstructionTextTokenKind::Opcode => BNInstructionTextTokenType::OpcodeToken,
863 InstructionTextTokenKind::String { .. } => BNInstructionTextTokenType::StringToken,
864 InstructionTextTokenKind::StringContent { .. } => {
865 BNInstructionTextTokenType::StringToken
866 }
867 InstructionTextTokenKind::CharacterConstant => {
868 BNInstructionTextTokenType::CharacterConstantToken
869 }
870 InstructionTextTokenKind::Keyword { .. } => BNInstructionTextTokenType::KeywordToken,
871 InstructionTextTokenKind::TypeName => BNInstructionTextTokenType::TypeNameToken,
872 InstructionTextTokenKind::FieldName { .. } => {
873 BNInstructionTextTokenType::FieldNameToken
874 }
875 InstructionTextTokenKind::NameSpace => BNInstructionTextTokenType::NameSpaceToken,
876 InstructionTextTokenKind::NameSpaceSeparator => {
877 BNInstructionTextTokenType::NameSpaceSeparatorToken
878 }
879 InstructionTextTokenKind::Tag => BNInstructionTextTokenType::TagToken,
880 InstructionTextTokenKind::StructOffset { .. } => {
881 BNInstructionTextTokenType::StructOffsetToken
882 }
883 InstructionTextTokenKind::StructOffsetByteValue => {
884 BNInstructionTextTokenType::StructOffsetByteValueToken
885 }
886 InstructionTextTokenKind::StructureHexDumpText { .. } => {
887 BNInstructionTextTokenType::StructureHexDumpTextToken
888 }
889 InstructionTextTokenKind::GotoLabel { .. } => {
890 BNInstructionTextTokenType::GotoLabelToken
891 }
892 InstructionTextTokenKind::Comment { .. } => BNInstructionTextTokenType::CommentToken,
893 InstructionTextTokenKind::PossibleValue { .. } => {
894 BNInstructionTextTokenType::PossibleValueToken
895 }
896 InstructionTextTokenKind::PossibleValueType => {
897 BNInstructionTextTokenType::PossibleValueTypeToken
898 }
899 InstructionTextTokenKind::ArrayIndex { .. } => {
900 BNInstructionTextTokenType::ArrayIndexToken
901 }
902 InstructionTextTokenKind::Indentation => BNInstructionTextTokenType::IndentationToken,
903 InstructionTextTokenKind::UnknownMemory => {
904 BNInstructionTextTokenType::UnknownMemoryToken
905 }
906 InstructionTextTokenKind::EnumerationMember { .. } => {
907 BNInstructionTextTokenType::EnumerationMemberToken
908 }
909 InstructionTextTokenKind::Operation => BNInstructionTextTokenType::OperationToken,
910 InstructionTextTokenKind::BaseStructureName => {
911 BNInstructionTextTokenType::BaseStructureNameToken
912 }
913 InstructionTextTokenKind::BaseStructureSeparator => {
914 BNInstructionTextTokenType::BaseStructureSeparatorToken
915 }
916 InstructionTextTokenKind::Brace { .. } => BNInstructionTextTokenType::BraceToken,
917 InstructionTextTokenKind::CodeSymbol { .. } => {
918 BNInstructionTextTokenType::CodeSymbolToken
919 }
920 InstructionTextTokenKind::DataSymbol { .. } => {
921 BNInstructionTextTokenType::DataSymbolToken
922 }
923 InstructionTextTokenKind::LocalVariable { .. } => {
924 BNInstructionTextTokenType::LocalVariableToken
925 }
926 InstructionTextTokenKind::Import { .. } => BNInstructionTextTokenType::ImportToken,
927 InstructionTextTokenKind::AddressDisplay { .. } => {
928 BNInstructionTextTokenType::AddressDisplayToken
929 }
930 InstructionTextTokenKind::IndirectImport { .. } => {
931 BNInstructionTextTokenType::IndirectImportToken
932 }
933 InstructionTextTokenKind::ExternalSymbol { .. } => {
934 BNInstructionTextTokenType::ExternalSymbolToken
935 }
936 InstructionTextTokenKind::StackVariable { .. } => {
937 BNInstructionTextTokenType::StackVariableToken
938 }
939 InstructionTextTokenKind::AddressSeparator => {
940 BNInstructionTextTokenType::AddressSeparatorToken
941 }
942 InstructionTextTokenKind::CollapsedInformation => {
943 BNInstructionTextTokenType::CollapsedInformationToken
944 }
945 InstructionTextTokenKind::CollapseStateIndicator { .. } => {
946 BNInstructionTextTokenType::CollapseStateIndicatorToken
947 }
948 InstructionTextTokenKind::NewLine { .. } => BNInstructionTextTokenType::NewLineToken,
949 }
950 }
951}
952
953impl Eq for InstructionTextTokenKind {}
954
955#[derive(Clone, Copy, PartialEq, Eq, Debug)]
956pub enum InstructionTextTokenContext {
957 Normal,
958 LocalVariable,
959 DataVariable,
960 FunctionReturn,
961 InstructionAddress,
962 ILInstructionIndex,
963 ConstData,
964 ConstStringData,
966 StringReference,
968 StringDataVariable,
970 StringDisplay,
974 Collapsed,
976 Expanded,
978 CollapsiblePadding,
980 DerivedStringReference,
982}
983
984impl From<BNInstructionTextTokenContext> for InstructionTextTokenContext {
985 fn from(value: BNInstructionTextTokenContext) -> Self {
986 match value {
987 BNInstructionTextTokenContext::NoTokenContext => Self::Normal,
988 BNInstructionTextTokenContext::LocalVariableTokenContext => Self::LocalVariable,
989 BNInstructionTextTokenContext::DataVariableTokenContext => Self::DataVariable,
990 BNInstructionTextTokenContext::FunctionReturnTokenContext => Self::FunctionReturn,
991 BNInstructionTextTokenContext::InstructionAddressTokenContext => {
992 Self::InstructionAddress
993 }
994 BNInstructionTextTokenContext::ILInstructionIndexTokenContext => {
995 Self::ILInstructionIndex
996 }
997 BNInstructionTextTokenContext::ConstDataTokenContext => Self::ConstData,
998 BNInstructionTextTokenContext::ConstStringDataTokenContext => Self::ConstStringData,
1000 BNInstructionTextTokenContext::StringReferenceTokenContext => Self::StringReference,
1001 BNInstructionTextTokenContext::StringDataVariableTokenContext => {
1002 Self::StringDataVariable
1003 }
1004 BNInstructionTextTokenContext::StringDisplayTokenContext => Self::StringDisplay,
1005 BNInstructionTextTokenContext::ContentCollapsedContext => Self::Collapsed,
1007 BNInstructionTextTokenContext::ContentExpandedContext => Self::Expanded,
1008 BNInstructionTextTokenContext::ContentCollapsiblePadding => Self::CollapsiblePadding,
1009 BNInstructionTextTokenContext::DerivedStringReferenceTokenContext => {
1010 Self::DerivedStringReference
1011 }
1012 }
1013 }
1014}
1015
1016impl From<InstructionTextTokenContext> for BNInstructionTextTokenContext {
1017 fn from(value: InstructionTextTokenContext) -> Self {
1018 match value {
1019 InstructionTextTokenContext::Normal => Self::NoTokenContext,
1020 InstructionTextTokenContext::LocalVariable => Self::LocalVariableTokenContext,
1021 InstructionTextTokenContext::DataVariable => Self::DataVariableTokenContext,
1022 InstructionTextTokenContext::FunctionReturn => Self::FunctionReturnTokenContext,
1023 InstructionTextTokenContext::InstructionAddress => Self::InstructionAddressTokenContext,
1024 InstructionTextTokenContext::ILInstructionIndex => Self::ILInstructionIndexTokenContext,
1025 InstructionTextTokenContext::ConstData => Self::ConstDataTokenContext,
1026 InstructionTextTokenContext::ConstStringData => Self::ConstStringDataTokenContext,
1027 InstructionTextTokenContext::StringReference => Self::StringReferenceTokenContext,
1028 InstructionTextTokenContext::StringDataVariable => Self::StringDataVariableTokenContext,
1029 InstructionTextTokenContext::StringDisplay => Self::StringDisplayTokenContext,
1030 InstructionTextTokenContext::Collapsed => Self::ContentCollapsedContext,
1031 InstructionTextTokenContext::Expanded => Self::ContentExpandedContext,
1032 InstructionTextTokenContext::CollapsiblePadding => Self::ContentCollapsiblePadding,
1033 InstructionTextTokenContext::DerivedStringReference => {
1034 Self::DerivedStringReferenceTokenContext
1035 }
1036 }
1037 }
1038}
1039
1040#[repr(transparent)]
1041pub struct DisassemblyTextRenderer {
1042 handle: NonNull<BNDisassemblyTextRenderer>,
1043}
1044
1045impl DisassemblyTextRenderer {
1046 pub unsafe fn ref_from_raw(handle: NonNull<BNDisassemblyTextRenderer>) -> Ref<Self> {
1047 Ref::new(Self { handle })
1048 }
1049
1050 pub fn from_function(func: &Function, settings: Option<&DisassemblySettings>) -> Ref<Self> {
1051 let settings_ptr = settings.map(|s| s.handle).unwrap_or(ptr::null_mut());
1052 let result = unsafe { BNCreateDisassemblyTextRenderer(func.handle, settings_ptr) };
1053 unsafe { Self::ref_from_raw(NonNull::new(result).unwrap()) }
1054 }
1055
1056 pub fn from_llil<M: FunctionMutability, F: FunctionForm>(
1057 func: &LowLevelILFunction<M, F>,
1058 settings: Option<&DisassemblySettings>,
1059 ) -> Ref<Self> {
1060 let settings_ptr = settings.map(|s| s.handle).unwrap_or(ptr::null_mut());
1061 let result =
1062 unsafe { BNCreateLowLevelILDisassemblyTextRenderer(func.handle, settings_ptr) };
1063 unsafe { Self::ref_from_raw(NonNull::new(result).unwrap()) }
1064 }
1065
1066 pub fn from_mlil(
1067 func: &MediumLevelILFunction,
1068 settings: Option<&DisassemblySettings>,
1069 ) -> Ref<Self> {
1070 let settings_ptr = settings.map(|s| s.handle).unwrap_or(ptr::null_mut());
1071 let result =
1072 unsafe { BNCreateMediumLevelILDisassemblyTextRenderer(func.handle, settings_ptr) };
1073 unsafe { Self::ref_from_raw(NonNull::new(result).unwrap()) }
1074 }
1075
1076 pub fn from_hlil(
1077 func: &HighLevelILFunction,
1078 settings: Option<&DisassemblySettings>,
1079 ) -> Ref<Self> {
1080 let settings_ptr = settings.map(|s| s.handle).unwrap_or(ptr::null_mut());
1081 let result =
1082 unsafe { BNCreateHighLevelILDisassemblyTextRenderer(func.handle, settings_ptr) };
1083 unsafe { Self::ref_from_raw(NonNull::new(result).unwrap()) }
1084 }
1085
1086 pub fn function(&self) -> Ref<Function> {
1087 let result = unsafe { BNGetDisassemblyTextRendererFunction(self.handle.as_ptr()) };
1088 assert!(!result.is_null());
1089 unsafe { Function::ref_from_raw(result) }
1090 }
1091
1092 pub fn llil<M: FunctionMutability, F: FunctionForm>(&self) -> Ref<LowLevelILFunction<M, F>> {
1093 let result =
1094 unsafe { BNGetDisassemblyTextRendererLowLevelILFunction(self.handle.as_ptr()) };
1095 assert!(!result.is_null());
1096 unsafe { LowLevelILFunction::ref_from_raw(result) }
1097 }
1098
1099 pub fn mlil(&self) -> Ref<MediumLevelILFunction> {
1100 let result =
1101 unsafe { BNGetDisassemblyTextRendererMediumLevelILFunction(self.handle.as_ptr()) };
1102 assert!(!result.is_null());
1103 unsafe { MediumLevelILFunction::ref_from_raw(result) }
1104 }
1105
1106 pub fn hlil(&self) -> Ref<HighLevelILFunction> {
1107 let result =
1108 unsafe { BNGetDisassemblyTextRendererHighLevelILFunction(self.handle.as_ptr()) };
1109 assert!(!result.is_null());
1110 unsafe { HighLevelILFunction::ref_from_raw(result, true) }
1111 }
1112
1113 pub fn basic_block(&self) -> Option<Ref<BasicBlock<NativeBlock>>> {
1114 let result = unsafe { BNGetDisassemblyTextRendererBasicBlock(self.handle.as_ptr()) };
1115 if result.is_null() {
1116 return None;
1117 }
1118 Some(unsafe { Ref::new(BasicBlock::from_raw(result, NativeBlock::new())) })
1119 }
1120
1121 pub fn set_basic_block(&self, value: Option<&BasicBlock<NativeBlock>>) {
1122 let block_ptr = value.map(|b| b.handle).unwrap_or(ptr::null_mut());
1123 unsafe { BNSetDisassemblyTextRendererBasicBlock(self.handle.as_ptr(), block_ptr) }
1124 }
1125
1126 pub fn arch(&self) -> CoreArchitecture {
1127 let result = unsafe { BNGetDisassemblyTextRendererArchitecture(self.handle.as_ptr()) };
1128 assert!(!result.is_null());
1129 unsafe { CoreArchitecture::from_raw(result) }
1130 }
1131
1132 pub fn set_arch(&self, value: CoreArchitecture) {
1133 unsafe { BNSetDisassemblyTextRendererArchitecture(self.handle.as_ptr(), value.handle) }
1134 }
1135
1136 pub fn settings(&self) -> Ref<DisassemblySettings> {
1137 let result = unsafe { BNGetDisassemblyTextRendererSettings(self.handle.as_ptr()) };
1138 unsafe { DisassemblySettings::ref_from_raw(result) }
1139 }
1140
1141 pub fn set_settings(&self, settings: Option<&DisassemblySettings>) {
1142 let settings_ptr = settings.map(|s| s.handle).unwrap_or(ptr::null_mut());
1143 unsafe { BNSetDisassemblyTextRendererSettings(self.handle.as_ptr(), settings_ptr) }
1144 }
1145
1146 pub fn is_il(&self) -> bool {
1147 unsafe { BNIsILDisassemblyTextRenderer(self.handle.as_ptr()) }
1148 }
1149
1150 pub fn has_data_flow(&self) -> bool {
1151 unsafe { BNDisassemblyTextRendererHasDataFlow(self.handle.as_ptr()) }
1152 }
1153
1154 pub fn instruction_annotations(&self, addr: u64) -> Array<InstructionTextToken> {
1156 let mut count = 0;
1157 let result = unsafe {
1158 BNGetDisassemblyTextRendererInstructionAnnotations(
1159 self.handle.as_ptr(),
1160 addr,
1161 &mut count,
1162 )
1163 };
1164 assert!(!result.is_null());
1165 unsafe { Array::new(result, count, ()) }
1166 }
1167
1168 pub fn instruction_text(&self, addr: u64) -> Option<(Array<DisassemblyTextLine>, usize)> {
1170 let mut count = 0;
1171 let mut length = 0;
1172 let mut lines: *mut BNDisassemblyTextLine = ptr::null_mut();
1173 let result = unsafe {
1174 BNGetDisassemblyTextRendererInstructionText(
1175 self.handle.as_ptr(),
1176 addr,
1177 &mut length,
1178 &mut lines,
1179 &mut count,
1180 )
1181 };
1182 result.then(|| (unsafe { Array::new(lines, count, ()) }, length))
1183 }
1184
1185 pub fn disassembly_text(&self, addr: u64) -> Option<(Array<DisassemblyTextLine>, usize)> {
1187 let mut count = 0;
1188 let mut length = 0;
1189 let mut lines: *mut BNDisassemblyTextLine = ptr::null_mut();
1190 let result = unsafe {
1191 BNGetDisassemblyTextRendererLines(
1192 self.handle.as_ptr(),
1193 addr,
1194 &mut length,
1195 &mut lines,
1196 &mut count,
1197 )
1198 };
1199 result.then(|| (unsafe { Array::new(lines, count, ()) }, length))
1200 }
1201
1202 pub fn is_integer_token(token_type: InstructionTextTokenType) -> bool {
1205 unsafe { BNIsIntegerToken(token_type) }
1206 }
1207
1208 pub fn reset_deduplicated_comments(&self) {
1209 unsafe { BNResetDisassemblyTextRendererDeduplicatedComments(self.handle.as_ptr()) }
1210 }
1211
1212 pub fn symbol_tokens(
1213 &self,
1214 addr: u64,
1215 size: usize,
1216 operand: Option<usize>,
1217 ) -> Option<Array<InstructionTextToken>> {
1218 let operand = operand.unwrap_or(0xffffffff);
1219 let mut count = 0;
1220 let mut tokens: *mut BNInstructionTextToken = ptr::null_mut();
1221 let result = unsafe {
1222 BNGetDisassemblyTextRendererSymbolTokens(
1223 self.handle.as_ptr(),
1224 addr,
1225 size,
1226 operand,
1227 &mut tokens,
1228 &mut count,
1229 )
1230 };
1231 result.then(|| unsafe { Array::new(tokens, count, ()) })
1232 }
1233
1234 pub fn stack_var_reference_tokens(
1235 &self,
1236 stack_ref: StackVariableReference,
1237 ) -> Array<InstructionTextToken> {
1238 let mut stack_ref_raw = StackVariableReference::into_raw(stack_ref);
1239 let mut count = 0;
1240 let tokens = unsafe {
1241 BNGetDisassemblyTextRendererStackVariableReferenceTokens(
1242 self.handle.as_ptr(),
1243 &mut stack_ref_raw,
1244 &mut count,
1245 )
1246 };
1247 StackVariableReference::free_raw(stack_ref_raw);
1248 assert!(!tokens.is_null());
1249 unsafe { Array::new(tokens, count, ()) }
1250 }
1251
1252 pub fn integer_token(
1253 &self,
1254 int_token: InstructionTextToken,
1255 location: impl Into<Location>,
1256 ) -> Array<InstructionTextToken> {
1257 let location = location.into();
1258 let arch = location
1259 .arch
1260 .map(|a| a.handle)
1261 .unwrap_or_else(std::ptr::null_mut);
1262 let mut count = 0;
1263 let mut int_token_raw = InstructionTextToken::into_raw(int_token);
1264 let tokens = unsafe {
1265 BNGetDisassemblyTextRendererIntegerTokens(
1266 self.handle.as_ptr(),
1267 &mut int_token_raw,
1268 arch,
1269 location.addr,
1270 &mut count,
1271 )
1272 };
1273 InstructionTextToken::free_raw(int_token_raw);
1274 assert!(!tokens.is_null());
1275 unsafe { Array::new(tokens, count, ()) }
1276 }
1277
1278 pub fn wrap_comment(
1279 &self,
1280 cur_line: DisassemblyTextLine,
1281 comment: &str,
1282 has_auto_annotations: bool,
1283 leading_spaces: &str,
1284 indent_spaces: &str,
1285 ) -> Array<DisassemblyTextLine> {
1286 let cur_line_raw = DisassemblyTextLine::into_raw(cur_line);
1287 let comment_raw = comment.to_cstr();
1288 let leading_spaces_raw = leading_spaces.to_cstr();
1289 let indent_spaces_raw = indent_spaces.to_cstr();
1290 let mut count = 0;
1291 let lines = unsafe {
1292 BNDisassemblyTextRendererWrapComment(
1293 self.handle.as_ptr(),
1294 &cur_line_raw,
1295 &mut count,
1296 comment_raw.as_ref().as_ptr() as *const ffi::c_char,
1297 has_auto_annotations,
1298 leading_spaces_raw.as_ref().as_ptr() as *const ffi::c_char,
1299 indent_spaces_raw.as_ref().as_ptr() as *const ffi::c_char,
1300 )
1301 };
1302 DisassemblyTextLine::free_raw(cur_line_raw);
1303 assert!(!lines.is_null());
1304 unsafe { Array::new(lines, count, ()) }
1305 }
1306}
1307
1308impl ToOwned for DisassemblyTextRenderer {
1309 type Owned = Ref<Self>;
1310
1311 fn to_owned(&self) -> Self::Owned {
1312 unsafe { RefCountable::inc_ref(self) }
1313 }
1314}
1315
1316unsafe impl RefCountable for DisassemblyTextRenderer {
1317 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
1318 Ref::new(Self {
1319 handle: NonNull::new(BNNewDisassemblyTextRendererReference(
1320 handle.handle.as_ptr(),
1321 ))
1322 .unwrap(),
1323 })
1324 }
1325
1326 unsafe fn dec_ref(handle: &Self) {
1327 BNFreeDisassemblyTextRenderer(handle.handle.as_ptr());
1328 }
1329}
1330
1331#[derive(PartialEq, Eq, Hash)]
1333pub struct DisassemblySettings {
1334 pub(crate) handle: *mut BNDisassemblySettings,
1335}
1336
1337impl DisassemblySettings {
1338 pub fn ref_from_raw(handle: *mut BNDisassemblySettings) -> Ref<Self> {
1339 debug_assert!(!handle.is_null());
1340 unsafe { Ref::new(Self { handle }) }
1341 }
1342
1343 pub fn new() -> Ref<Self> {
1344 let handle = unsafe { BNCreateDisassemblySettings() };
1345 Self::ref_from_raw(handle)
1346 }
1347
1348 pub fn set_option(&self, option: DisassemblyOption, state: bool) {
1349 unsafe { BNSetDisassemblySettingsOption(self.handle, option, state) }
1350 }
1351
1352 pub fn is_option_set(&self, option: DisassemblyOption) -> bool {
1353 unsafe { BNIsDisassemblySettingsOptionSet(self.handle, option) }
1354 }
1355}
1356
1357impl ToOwned for DisassemblySettings {
1358 type Owned = Ref<Self>;
1359
1360 fn to_owned(&self) -> Self::Owned {
1361 unsafe { RefCountable::inc_ref(self) }
1362 }
1363}
1364
1365unsafe impl RefCountable for DisassemblySettings {
1366 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
1367 Ref::new(Self {
1368 handle: BNNewDisassemblySettingsReference(handle.handle),
1369 })
1370 }
1371
1372 unsafe fn dec_ref(handle: &Self) {
1373 BNFreeDisassemblySettings(handle.handle);
1374 }
1375}