summaryrefslogtreecommitdiff
path: root/rust/src
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2025-12-11 14:45:23 -0500
committerMason Reed <35282038+emesare@users.noreply.github.com>2025-12-15 19:29:56 -0500
commitca0e32efb1e5b9eba157e9fd2eef178d9367c578 (patch)
tree12f9eab134807a4b2821e04ada4795e6611ea45f /rust/src
parenta83f2082799695b85b732987adb21112d042b152 (diff)
[Rust] Restructure type APIs into `types` module
This helps with documentation, giving a single module for those working with types to find related APIs Also split out enumeration and structure APIs into their own file, since they have their own backing data separate from `Type`.
Diffstat (limited to 'rust/src')
-rw-r--r--rust/src/binary_view.rs11
-rw-r--r--rust/src/collaboration/sync.rs2
-rw-r--r--rust/src/component.rs23
-rw-r--r--rust/src/data_notification.rs3
-rw-r--r--rust/src/language_representation.rs3
-rw-r--r--rust/src/lib.rs5
-rw-r--r--rust/src/platform.rs8
-rw-r--r--rust/src/string.rs9
-rw-r--r--rust/src/types.rs923
-rw-r--r--rust/src/types/archive.rs (renamed from rust/src/type_archive.rs)15
-rw-r--r--rust/src/types/container.rs (renamed from rust/src/type_container.rs)3
-rw-r--r--rust/src/types/enumeration.rs201
-rw-r--r--rust/src/types/library.rs (renamed from rust/src/type_library.rs)0
-rw-r--r--rust/src/types/parser.rs (renamed from rust/src/type_parser.rs)3
-rw-r--r--rust/src/types/printer.rs (renamed from rust/src/type_printer.rs)3
-rw-r--r--rust/src/types/structure.rs696
16 files changed, 970 insertions, 938 deletions
diff --git a/rust/src/binary_view.rs b/rust/src/binary_view.rs
index a48d0264..459253b9 100644
--- a/rust/src/binary_view.rs
+++ b/rust/src/binary_view.rs
@@ -30,10 +30,12 @@ pub use crate::workflow::AnalysisContext;
use crate::architecture::{Architecture, CoreArchitecture};
use crate::base_detection::BaseAddressDetection;
use crate::basic_block::BasicBlock;
+use crate::binary_view::search::SearchQuery;
use crate::component::Component;
use crate::confidence::Conf;
use crate::data_buffer::DataBuffer;
use crate::debuginfo::DebugInfo;
+use crate::disassembly::DisassemblySettings;
use crate::external_library::{ExternalLibrary, ExternalLocation};
use crate::file_accessor::{Accessor, FileAccessor};
use crate::file_metadata::FileMetadata;
@@ -53,12 +55,12 @@ use crate::settings::Settings;
use crate::string::*;
use crate::symbol::{Symbol, SymbolType};
use crate::tags::{Tag, TagType};
-use crate::type_container::TypeContainer;
-use crate::type_library::TypeLibrary;
use crate::types::{
NamedTypeReference, QualifiedName, QualifiedNameAndType, QualifiedNameTypeAndId, Type,
+ TypeArchive, TypeArchiveId, TypeContainer, TypeLibrary,
};
use crate::variable::DataVariable;
+use crate::workflow::Workflow;
use crate::{Endianness, BN_FULL_CONFIDENCE};
use std::collections::HashMap;
use std::ffi::{c_char, c_void, CString};
@@ -67,17 +69,12 @@ use std::ops::Range;
use std::path::{Path, PathBuf};
use std::ptr::NonNull;
use std::{result, slice};
-// TODO : general reorg of modules related to bv
pub mod memory_map;
pub mod reader;
pub mod search;
pub mod writer;
-use crate::binary_view::search::SearchQuery;
-use crate::disassembly::DisassemblySettings;
-use crate::type_archive::{TypeArchive, TypeArchiveId};
-use crate::workflow::Workflow;
pub use memory_map::MemoryMap;
pub use reader::BinaryReader;
pub use writer::BinaryWriter;
diff --git a/rust/src/collaboration/sync.rs b/rust/src/collaboration/sync.rs
index a8006b8b..72c57a46 100644
--- a/rust/src/collaboration/sync.rs
+++ b/rust/src/collaboration/sync.rs
@@ -13,7 +13,7 @@ use crate::progress::{NoProgressCallback, ProgressCallback};
use crate::project::file::ProjectFile;
use crate::rc::Ref;
use crate::string::{raw_to_string, BnString, IntoCStr};
-use crate::type_archive::{TypeArchive, TypeArchiveMergeConflict};
+use crate::types::archive::{TypeArchive, TypeArchiveMergeConflict};
/// Get the default directory path for a remote Project. This is based off the Setting for
/// collaboration.directory, the project's id, and the project's remote's id.
diff --git a/rust/src/component.rs b/rust/src/component.rs
index 4c5d5992..f038d5c3 100644
--- a/rust/src/component.rs
+++ b/rust/src/component.rs
@@ -2,7 +2,7 @@ use crate::binary_view::{BinaryView, BinaryViewExt};
use crate::function::Function;
use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable};
use crate::string::{BnString, IntoCStr};
-use crate::types::ComponentReferencedType;
+use crate::types::Type;
use std::ffi::c_char;
use std::fmt::Debug;
use std::ptr::NonNull;
@@ -304,3 +304,24 @@ unsafe impl CoreArrayProviderInner for Component {
Guard::new(Self::from_raw(raw_ptr), context)
}
}
+
+// TODO: Remove this struct, or make it not a ZST with a terrible array provider.
+/// ZST used only for `Array<ComponentReferencedType>`.
+pub struct ComponentReferencedType;
+
+impl CoreArrayProvider for ComponentReferencedType {
+ type Raw = *mut BNType;
+ type Context = ();
+ type Wrapped<'a> = &'a Type;
+}
+
+unsafe impl CoreArrayProviderInner for ComponentReferencedType {
+ unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
+ BNComponentFreeReferencedTypes(raw, count)
+ }
+
+ unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
+ // SAFETY: &*mut BNType == &Type (*mut BNType == Type)
+ std::mem::transmute(raw)
+ }
+}
diff --git a/rust/src/data_notification.rs b/rust/src/data_notification.rs
index 7749e792..d01a5ed3 100644
--- a/rust/src/data_notification.rs
+++ b/rust/src/data_notification.rs
@@ -15,8 +15,7 @@ use crate::section::Section;
use crate::segment::Segment;
use crate::symbol::Symbol;
use crate::tags::{TagReference, TagType};
-use crate::type_archive::TypeArchive;
-use crate::types::{QualifiedName, Type};
+use crate::types::{QualifiedName, Type, TypeArchive};
use crate::variable::DataVariable;
macro_rules! trait_handler {
diff --git a/rust/src/language_representation.rs b/rust/src/language_representation.rs
index 34524b96..d39cb95f 100644
--- a/rust/src/language_representation.rs
+++ b/rust/src/language_representation.rs
@@ -14,8 +14,7 @@ use crate::high_level_il::{HighLevelExpressionIndex, HighLevelILFunction};
use crate::line_formatter::CoreLineFormatter;
use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref, RefCountable};
use crate::string::{BnString, IntoCStr};
-use crate::type_parser::CoreTypeParser;
-use crate::type_printer::CoreTypePrinter;
+use crate::types::{CoreTypeParser, CoreTypePrinter};
pub type InstructionTextTokenContext = BNInstructionTextTokenContext;
pub type ScopeType = BNScopeType;
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index f3166033..2d9cab27 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -81,11 +81,6 @@ pub mod string;
pub mod symbol;
pub mod tags;
pub mod template_simplifier;
-pub mod type_archive;
-pub mod type_container;
-pub mod type_library;
-pub mod type_parser;
-pub mod type_printer;
pub mod types;
pub mod update;
pub mod variable;
diff --git a/rust/src/platform.rs b/rust/src/platform.rs
index 609f4edc..ed4f49f4 100644
--- a/rust/src/platform.rs
+++ b/rust/src/platform.rs
@@ -14,15 +14,15 @@
//! Contains all information related to the execution environment of the binary, mainly the calling conventions used
-use crate::type_container::TypeContainer;
-use crate::type_parser::{TypeParserError, TypeParserErrorSeverity, TypeParserResult};
use crate::{
architecture::{Architecture, CoreArchitecture},
calling_convention::CoreCallingConvention,
rc::*,
string::*,
- type_library::TypeLibrary,
- types::QualifiedNameAndType,
+ types::{
+ QualifiedNameAndType, TypeContainer, TypeLibrary, TypeParserError, TypeParserErrorSeverity,
+ TypeParserResult,
+ },
};
use binaryninjacore_sys::*;
use std::fmt::Debug;
diff --git a/rust/src/string.rs b/rust/src/string.rs
index c7d541ce..8505cbf5 100644
--- a/rust/src/string.rs
+++ b/rust/src/string.rs
@@ -24,7 +24,6 @@ use std::ops::Deref;
use std::path::{Path, PathBuf};
use crate::rc::*;
-use crate::type_archive::TypeArchiveSnapshotId;
use crate::types::QualifiedName;
// TODO: Remove or refactor this.
@@ -288,14 +287,6 @@ impl IntoCStr for &Path {
}
}
-impl IntoCStr for TypeArchiveSnapshotId {
- type Result = CString;
-
- fn to_cstr(self) -> Self::Result {
- self.to_string().to_cstr()
- }
-}
-
pub trait IntoJson {
type Output: IntoCStr;
diff --git a/rust/src/types.rs b/rust/src/types.rs
index 1387ffb3..cfdc865b 100644
--- a/rust/src/types.rs
+++ b/rust/src/types.rs
@@ -11,16 +11,19 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-#![allow(unused)]
-// TODO : More widely enforce the use of ref_from_raw vs just from_raw to simplify internal binding usage? Perhaps remove from_raw functions?
-// TODO : Add documentation and fix examples
-// TODO : Test the get_enumeration and get_structure methods
+pub mod archive;
+pub mod container;
+pub mod enumeration;
+pub mod library;
+pub mod parser;
+pub mod printer;
+pub mod structure;
use binaryninjacore_sys::*;
use crate::{
- architecture::{Architecture, CoreArchitecture},
+ architecture::Architecture,
binary_view::{BinaryView, BinaryViewExt},
calling_convention::CoreCallingConvention,
rc::*,
@@ -29,19 +32,30 @@ use crate::{
use crate::confidence::{Conf, MAX_CONFIDENCE, MIN_CONFIDENCE};
use crate::string::{raw_to_string, strings_to_string_list};
-use crate::type_container::TypeContainer;
use crate::variable::{Variable, VariableSourceType};
use std::borrow::Cow;
use std::num::NonZeroUsize;
use std::ops::{Index, IndexMut};
use std::{
collections::HashSet,
- ffi::CStr,
fmt::{Debug, Display, Formatter},
hash::{Hash, Hasher},
iter::IntoIterator,
};
+pub use archive::{TypeArchive, TypeArchiveId, TypeArchiveSnapshotId};
+pub use container::TypeContainer;
+pub use enumeration::{Enumeration, EnumerationBuilder, EnumerationMember};
+pub use library::TypeLibrary;
+pub use parser::{
+ CoreTypeParser, ParsedType, TypeParser, TypeParserError, TypeParserErrorSeverity,
+ TypeParserResult,
+};
+pub use printer::{CoreTypePrinter, TypePrinter};
+pub use structure::{
+ BaseStructure, InheritedStructureMember, Structure, StructureBuilder, StructureMember,
+};
+
pub type StructureType = BNStructureVariant;
pub type ReferenceType = BNReferenceType;
pub type TypeClass = BNTypeClass;
@@ -970,7 +984,7 @@ impl Debug for Type {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
// You might be tempted to rip this atrocity out and make this more "sensible". READ BELOW!
// Type is a one-size fits all structure, these are actually its fields! If we wanted to
- // omit some fields for different type classes what you really want to do is implement your
+ // omit some fields for different type classes, what you really want to do is implement your
// own formatter. This is supposed to represent the structure entirely, it's not supposed to be pretty!
f.debug_struct("Type")
.field("type_class", &self.type_class())
@@ -1048,27 +1062,6 @@ unsafe impl CoreArrayProviderInner for Type {
}
}
-// TODO: Remove this struct, or make it not a ZST with a terrible array provider.
-/// ZST used only for `Array<ComponentReferencedType>`.
-pub struct ComponentReferencedType;
-
-impl CoreArrayProvider for ComponentReferencedType {
- type Raw = *mut BNType;
- type Context = ();
- type Wrapped<'a> = &'a Type;
-}
-
-unsafe impl CoreArrayProviderInner for ComponentReferencedType {
- unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
- BNComponentFreeReferencedTypes(raw, count)
- }
-
- unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
- // SAFETY: &*mut BNType == &Type (*mut BNType == Type)
- std::mem::transmute(raw)
- }
-}
-
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct FunctionParameter {
pub ty: Conf<Ref<Type>>,
@@ -1105,6 +1098,7 @@ impl FunctionParameter {
}
}
+ #[allow(unused)]
pub(crate) fn from_owned_raw(value: BNFunctionParameter) -> Self {
let owned = Self::from_raw(&value);
Self::free_raw(value);
@@ -1136,875 +1130,6 @@ impl FunctionParameter {
}
}
-#[derive(Debug, Clone, Hash, PartialEq, Eq)]
-pub struct EnumerationMember {
- pub name: String,
- /// The associated constant value for the member.
- pub value: u64,
- /// Whether this is the default member for the associated [`Enumeration`].
- pub default: bool,
-}
-
-impl EnumerationMember {
- pub(crate) fn from_raw(value: &BNEnumerationMember) -> Self {
- Self {
- name: raw_to_string(value.name).unwrap(),
- value: value.value,
- default: value.isDefault,
- }
- }
-
- pub(crate) fn from_owned_raw(value: BNEnumerationMember) -> Self {
- let owned = Self::from_raw(&value);
- Self::free_raw(value);
- owned
- }
-
- pub(crate) fn into_raw(value: Self) -> BNEnumerationMember {
- let bn_name = BnString::new(value.name);
- BNEnumerationMember {
- name: BnString::into_raw(bn_name),
- value: value.value,
- isDefault: value.default,
- }
- }
-
- pub(crate) fn free_raw(value: BNEnumerationMember) {
- unsafe { BnString::free_raw(value.name) };
- }
-
- pub fn new(name: String, value: u64, default: bool) -> Self {
- Self {
- name,
- value,
- default,
- }
- }
-}
-
-#[derive(PartialEq, Eq, Hash)]
-pub struct EnumerationBuilder {
- pub(crate) handle: *mut BNEnumerationBuilder,
-}
-
-impl EnumerationBuilder {
- pub fn new() -> Self {
- Self {
- handle: unsafe { BNCreateEnumerationBuilder() },
- }
- }
-
- pub(crate) unsafe fn from_raw(handle: *mut BNEnumerationBuilder) -> Self {
- Self { handle }
- }
-
- pub fn finalize(&self) -> Ref<Enumeration> {
- unsafe { Enumeration::ref_from_raw(BNFinalizeEnumerationBuilder(self.handle)) }
- }
-
- pub fn append(&mut self, name: &str) -> &mut Self {
- let name = name.to_cstr();
- unsafe {
- BNAddEnumerationBuilderMember(self.handle, name.as_ref().as_ptr() as _);
- }
- self
- }
-
- pub fn insert(&mut self, name: &str, value: u64) -> &mut Self {
- let name = name.to_cstr();
- unsafe {
- BNAddEnumerationBuilderMemberWithValue(self.handle, name.as_ref().as_ptr() as _, value);
- }
- self
- }
-
- pub fn replace(&mut self, id: usize, name: &str, value: u64) -> &mut Self {
- let name = name.to_cstr();
- unsafe {
- BNReplaceEnumerationBuilderMember(self.handle, id, name.as_ref().as_ptr() as _, value);
- }
- self
- }
-
- pub fn remove(&mut self, id: usize) -> &mut Self {
- unsafe {
- BNRemoveEnumerationBuilderMember(self.handle, id);
- }
-
- self
- }
-
- pub fn members(&self) -> Vec<EnumerationMember> {
- unsafe {
- let mut count = 0;
- let members_raw_ptr = BNGetEnumerationBuilderMembers(self.handle, &mut count);
- let members_raw: &[BNEnumerationMember] =
- std::slice::from_raw_parts(members_raw_ptr, count);
- let members = members_raw
- .iter()
- .map(EnumerationMember::from_raw)
- .collect();
- BNFreeEnumerationMemberList(members_raw_ptr, count);
- members
- }
- }
-}
-
-impl Default for EnumerationBuilder {
- fn default() -> Self {
- Self::new()
- }
-}
-
-impl From<&Enumeration> for EnumerationBuilder {
- fn from(enumeration: &Enumeration) -> Self {
- unsafe {
- Self::from_raw(BNCreateEnumerationBuilderFromEnumeration(
- enumeration.handle,
- ))
- }
- }
-}
-
-impl Drop for EnumerationBuilder {
- fn drop(&mut self) {
- unsafe { BNFreeEnumerationBuilder(self.handle) };
- }
-}
-
-#[derive(PartialEq, Eq, Hash)]
-pub struct Enumeration {
- pub(crate) handle: *mut BNEnumeration,
-}
-
-impl Enumeration {
- pub(crate) unsafe fn ref_from_raw(handle: *mut BNEnumeration) -> Ref<Self> {
- debug_assert!(!handle.is_null());
- Ref::new(Self { handle })
- }
-
- pub fn builder() -> EnumerationBuilder {
- EnumerationBuilder::new()
- }
-
- pub fn members(&self) -> Vec<EnumerationMember> {
- unsafe {
- let mut count = 0;
- let members_raw_ptr = BNGetEnumerationMembers(self.handle, &mut count);
- debug_assert!(!members_raw_ptr.is_null());
- let members_raw: &[BNEnumerationMember] =
- std::slice::from_raw_parts(members_raw_ptr, count);
- let members = members_raw
- .iter()
- .map(EnumerationMember::from_raw)
- .collect();
- BNFreeEnumerationMemberList(members_raw_ptr, count);
- members
- }
- }
-}
-
-impl Debug for Enumeration {
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- f.debug_struct("Enumeration")
- .field("members", &self.members())
- .finish()
- }
-}
-
-unsafe impl RefCountable for Enumeration {
- unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
- Self::ref_from_raw(BNNewEnumerationReference(handle.handle))
- }
-
- unsafe fn dec_ref(handle: &Self) {
- BNFreeEnumeration(handle.handle);
- }
-}
-
-impl ToOwned for Enumeration {
- type Owned = Ref<Self>;
-
- fn to_owned(&self) -> Self::Owned {
- unsafe { RefCountable::inc_ref(self) }
- }
-}
-
-#[derive(PartialEq, Eq, Hash)]
-pub struct StructureBuilder {
- pub(crate) handle: *mut BNStructureBuilder,
-}
-
-/// ```no_run
-/// // Includes
-/// # use binaryninja::binary_view::BinaryViewExt;
-/// use binaryninja::types::{MemberAccess, MemberScope, Structure, StructureBuilder, Type};
-///
-/// // Types to use in the members
-/// let field_1_ty = Type::named_int(5, false, "my_weird_int_type");
-/// let field_2_ty = Type::int(4, false);
-/// let field_3_ty = Type::int(8, false);
-///
-/// // Assign those fields
-/// let mut my_custom_struct = StructureBuilder::new();
-/// my_custom_struct
-/// .insert(
-/// &field_1_ty,
-/// "field_1",
-/// 0,
-/// false,
-/// MemberAccess::PublicAccess,
-/// MemberScope::NoScope,
-/// )
-/// .insert(
-/// &field_2_ty,
-/// "field_2",
-/// 5,
-/// false,
-/// MemberAccess::PublicAccess,
-/// MemberScope::NoScope,
-/// )
-/// .insert(
-/// &field_3_ty,
-/// "field_3",
-/// 9,
-/// false,
-/// MemberAccess::PublicAccess,
-/// MemberScope::NoScope,
-/// )
-/// .append(
-/// &field_1_ty,
-/// "field_4",
-/// MemberAccess::PublicAccess,
-/// MemberScope::NoScope,
-/// );
-///
-/// // Convert structure to type
-/// let my_custom_structure_type = Type::structure(&my_custom_struct.finalize());
-///
-/// // Add the struct to the binary view to use in analysis
-/// let bv = binaryninja::load("example").unwrap();
-/// bv.define_user_type("my_custom_struct", &my_custom_structure_type);
-/// ```
-impl StructureBuilder {
- pub fn new() -> Self {
- Self {
- handle: unsafe { BNCreateStructureBuilder() },
- }
- }
-
- pub(crate) unsafe fn from_raw(handle: *mut BNStructureBuilder) -> Self {
- debug_assert!(!handle.is_null());
- Self { handle }
- }
-
- // TODO: Document the width adjustment with alignment.
- pub fn finalize(&self) -> Ref<Structure> {
- let raw_struct_ptr = unsafe { BNFinalizeStructureBuilder(self.handle) };
- unsafe { Structure::ref_from_raw(raw_struct_ptr) }
- }
-
- /// Sets the width of the [`StructureBuilder`] to the new width.
- ///
- /// This will remove all previously inserted members outside the new width. This is done by computing
- /// the member access range (member offset + member width) and if it is larger than the new width
- /// it will be removed.
- pub fn width(&mut self, width: u64) -> &mut Self {
- unsafe {
- BNSetStructureBuilderWidth(self.handle, width);
- }
- self
- }
-
- pub fn alignment(&mut self, alignment: usize) -> &mut Self {
- unsafe {
- BNSetStructureBuilderAlignment(self.handle, alignment);
- }
- self
- }
-
- /// Sets whether the [`StructureBuilder`] is packed.
- ///
- /// If set the alignment of the structure will be `1`. You do not need to set the alignment to `1`.
- pub fn packed(&mut self, packed: bool) -> &mut Self {
- unsafe {
- BNSetStructureBuilderPacked(self.handle, packed);
- }
- self
- }
-
- pub fn structure_type(&mut self, t: StructureType) -> &mut Self {
- unsafe { BNSetStructureBuilderType(self.handle, t) };
- self
- }
-
- pub fn pointer_offset(&mut self, offset: i64) -> &mut Self {
- unsafe { BNSetStructureBuilderPointerOffset(self.handle, offset) };
- self
- }
-
- pub fn propagates_data_var_refs(&mut self, propagates: bool) -> &mut Self {
- unsafe { BNSetStructureBuilderPropagatesDataVariableReferences(self.handle, propagates) };
- self
- }
-
- pub fn base_structures(&mut self, bases: &[BaseStructure]) -> &mut Self {
- let raw_base_structs: Vec<BNBaseStructure> =
- bases.iter().map(BaseStructure::into_owned_raw).collect();
- unsafe {
- BNSetBaseStructuresForStructureBuilder(
- self.handle,
- raw_base_structs.as_ptr() as *mut _,
- raw_base_structs.len(),
- )
- };
- self
- }
-
- /// Append a member at the next available byte offset.
- ///
- /// Otherwise, consider using:
- ///
- /// - [`StructureBuilder::insert_member`]
- /// - [`StructureBuilder::insert`]
- /// - [`StructureBuilder::insert_bitwise`]
- pub fn append<'a, T: Into<Conf<&'a Type>>>(
- &mut self,
- ty: T,
- name: &str,
- access: MemberAccess,
- scope: MemberScope,
- ) -> &mut Self {
- let name = name.to_cstr();
- let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
- unsafe {
- BNAddStructureBuilderMember(
- self.handle,
- &owned_raw_ty,
- name.as_ref().as_ptr() as _,
- access,
- scope,
- );
- }
- self
- }
-
- /// Insert an already constructed [`StructureMember`].
- ///
- /// Otherwise, consider using:
- ///
- /// - [`StructureBuilder::append`]
- /// - [`StructureBuilder::insert`]
- /// - [`StructureBuilder::insert_bitwise`]
- pub fn insert_member(
- &mut self,
- member: StructureMember,
- overwrite_existing: bool,
- ) -> &mut Self {
- self.insert_bitwise(
- &member.ty,
- &member.name,
- member.bit_offset(),
- member.bit_width,
- overwrite_existing,
- member.access,
- member.scope,
- );
- self
- }
-
- /// Inserts a member at the `offset` (in bytes).
- ///
- /// If you need to insert a member at a specific bit within a given byte (like a bitfield), you
- /// can use [`StructureBuilder::insert_bitwise`].
- pub fn insert<'a, T: Into<Conf<&'a Type>>>(
- &mut self,
- ty: T,
- name: &str,
- offset: u64,
- overwrite_existing: bool,
- access: MemberAccess,
- scope: MemberScope,
- ) -> &mut Self {
- self.insert_bitwise(
- ty,
- name,
- offset * 8,
- None,
- overwrite_existing,
- access,
- scope,
- )
- }
-
- /// Inserts a member at `bit_offset` with an optional `bit_width`.
- ///
- /// NOTE: The `bit_offset` is relative to the start of the structure, for example, passing `8` will place
- /// the field at the start of the byte `0x1`.
- pub fn insert_bitwise<'a, T: Into<Conf<&'a Type>>>(
- &mut self,
- ty: T,
- name: &str,
- bit_offset: u64,
- bit_width: Option<u8>,
- overwrite_existing: bool,
- access: MemberAccess,
- scope: MemberScope,
- ) -> &mut Self {
- let name = name.to_cstr();
- let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
- let byte_offset = bit_offset / 8;
- let bit_position = bit_offset % 8;
- unsafe {
- BNAddStructureBuilderMemberAtOffset(
- self.handle,
- &owned_raw_ty,
- name.as_ref().as_ptr() as _,
- byte_offset,
- overwrite_existing,
- access,
- scope,
- bit_position as u8,
- bit_width.unwrap_or(0),
- );
- }
- self
- }
-
- pub fn replace<'a, T: Into<Conf<&'a Type>>>(
- &mut self,
- index: usize,
- ty: T,
- name: &str,
- overwrite_existing: bool,
- ) -> &mut Self {
- let name = name.to_cstr();
- let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
- unsafe {
- BNReplaceStructureBuilderMember(
- self.handle,
- index,
- &owned_raw_ty,
- name.as_ref().as_ptr() as _,
- overwrite_existing,
- )
- }
- self
- }
-
- /// Removes the member at a given index.
- pub fn remove(&mut self, index: usize) -> &mut Self {
- unsafe { BNRemoveStructureBuilderMember(self.handle, index) };
- self
- }
-
- // TODO: We should add BNGetStructureBuilderAlignedWidth
- /// Gets the current **unaligned** width of the structure.
- ///
- /// This cannot be used to accurately get the width of a non-packed structure.
- pub fn current_width(&self) -> u64 {
- unsafe { BNGetStructureBuilderWidth(self.handle) }
- }
-}
-
-impl From<&Structure> for StructureBuilder {
- fn from(structure: &Structure) -> StructureBuilder {
- unsafe { Self::from_raw(BNCreateStructureBuilderFromStructure(structure.handle)) }
- }
-}
-
-impl From<Vec<StructureMember>> for StructureBuilder {
- fn from(members: Vec<StructureMember>) -> StructureBuilder {
- let mut builder = StructureBuilder::new();
- for member in members {
- builder.insert_member(member, false);
- }
- builder
- }
-}
-
-impl Drop for StructureBuilder {
- fn drop(&mut self) {
- unsafe { BNFreeStructureBuilder(self.handle) };
- }
-}
-
-impl Default for StructureBuilder {
- fn default() -> Self {
- Self::new()
- }
-}
-
-#[derive(PartialEq, Eq, Hash)]
-pub struct Structure {
- pub(crate) handle: *mut BNStructure,
-}
-
-impl Structure {
- pub(crate) unsafe fn ref_from_raw(handle: *mut BNStructure) -> Ref<Self> {
- debug_assert!(!handle.is_null());
- Ref::new(Self { handle })
- }
-
- pub fn builder() -> StructureBuilder {
- StructureBuilder::new()
- }
-
- pub fn width(&self) -> u64 {
- unsafe { BNGetStructureWidth(self.handle) }
- }
-
- pub fn structure_type(&self) -> StructureType {
- unsafe { BNGetStructureType(self.handle) }
- }
-
- /// Retrieve the members that are accessible at a given offset.
- ///
- /// The reason for this being plural is that members may overlap and the offset is in bytes
- /// where a bitfield may contain multiple members at the given byte.
- ///
- /// Unions are also represented as structures and will cause this function to return
- /// **all** members that can reach that offset.
- ///
- /// We must pass a [`TypeContainer`] here so that we can resolve base structure members, as they
- /// are treated as members through this function. Typically, you get the [`TypeContainer`]
- /// through the binary view with [`BinaryViewExt::type_container`].
- pub fn members_at_offset(
- &self,
- container: &TypeContainer,
- offset: u64,
- ) -> Vec<StructureMember> {
- self.members_including_inherited(container)
- .into_iter()
- .filter(|m| m.member.is_offset_valid(offset))
- .map(|m| m.member)
- .collect()
- }
-
- /// Return the list of non-inherited structure members.
- ///
- /// If you want to get all members, including ones inherited from base structures,
- /// use [`Structure::members_including_inherited`] instead.
- pub fn members(&self) -> Vec<StructureMember> {
- unsafe {
- let mut count = 0;
- let members_raw_ptr: *mut BNStructureMember =
- BNGetStructureMembers(self.handle, &mut count);
- debug_assert!(!members_raw_ptr.is_null());
- let members_raw = std::slice::from_raw_parts(members_raw_ptr, count);
- let members = members_raw.iter().map(StructureMember::from_raw).collect();
- BNFreeStructureMemberList(members_raw_ptr, count);
- members
- }
- }
-
- /// Returns the list of all structure members, including inherited ones.
- ///
- /// Because we must traverse through base structures, we have to provide the [`TypeContainer`];
- /// in most cases it is ok to provide the binary views container via [`BinaryViewExt::type_container`].
- pub fn members_including_inherited(
- &self,
- container: &TypeContainer,
- ) -> Vec<InheritedStructureMember> {
- unsafe {
- let mut count = 0;
- let members_raw_ptr: *mut BNInheritedStructureMember =
- BNGetStructureMembersIncludingInherited(
- self.handle,
- container.handle.as_ptr(),
- &mut count,
- );
- debug_assert!(!members_raw_ptr.is_null());
- let members_raw = std::slice::from_raw_parts(members_raw_ptr, count);
- let members = members_raw
- .iter()
- .map(InheritedStructureMember::from_raw)
- .collect();
- BNFreeInheritedStructureMemberList(members_raw_ptr, count);
- members
- }
- }
-
- /// Retrieve the list of base structures for the structure. These base structures are what give
- /// a structure inherited members.
- pub fn base_structures(&self) -> Vec<BaseStructure> {
- let mut count = 0;
- let bases_raw_ptr = unsafe { BNGetBaseStructuresForStructure(self.handle, &mut count) };
- debug_assert!(!bases_raw_ptr.is_null());
- let bases_raw = unsafe { std::slice::from_raw_parts(bases_raw_ptr, count) };
- let bases = bases_raw.iter().map(BaseStructure::from_raw).collect();
- unsafe { BNFreeBaseStructureList(bases_raw_ptr, count) };
- bases
- }
-
- /// Whether the structure is packed or not.
- pub fn is_packed(&self) -> bool {
- unsafe { BNIsStructurePacked(self.handle) }
- }
-
- pub fn alignment(&self) -> usize {
- unsafe { BNGetStructureAlignment(self.handle) }
- }
-}
-
-impl Debug for Structure {
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- f.debug_struct("Structure")
- .field("width", &self.width())
- .field("alignment", &self.alignment())
- .field("packed", &self.is_packed())
- .field("structure_type", &self.structure_type())
- .field("base_structures", &self.base_structures())
- .field("members", &self.members())
- .finish()
- }
-}
-
-unsafe impl RefCountable for Structure {
- unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
- Self::ref_from_raw(BNNewStructureReference(handle.handle))
- }
-
- unsafe fn dec_ref(handle: &Self) {
- BNFreeStructure(handle.handle);
- }
-}
-
-impl ToOwned for Structure {
- type Owned = Ref<Self>;
-
- fn to_owned(&self) -> Self::Owned {
- unsafe { RefCountable::inc_ref(self) }
- }
-}
-
-#[derive(Debug, Clone, Hash, PartialEq, Eq)]
-pub struct StructureMember {
- pub ty: Conf<Ref<Type>>,
- // TODO: Shouldnt this be a QualifiedName? The ffi says no...
- pub name: String,
- /// The byte offset of the member.
- pub offset: u64,
- pub access: MemberAccess,
- pub scope: MemberScope,
- /// The bit position relative to the byte offset.
- pub bit_position: Option<u8>,
- pub bit_width: Option<u8>,
-}
-
-impl StructureMember {
- pub(crate) fn from_raw(value: &BNStructureMember) -> Self {
- Self {
- ty: Conf::new(
- unsafe { Type::from_raw(value.type_) }.to_owned(),
- value.typeConfidence,
- ),
- // TODO: I dislike using this function here.
- name: raw_to_string(value.name as *mut _).unwrap(),
- offset: value.offset,
- access: value.access,
- scope: value.scope,
- bit_position: match value.bitPosition {
- 0 => None,
- _ => Some(value.bitPosition),
- },
- bit_width: match value.bitWidth {
- 0 => None,
- _ => Some(value.bitWidth),
- },
- }
- }
-
- pub(crate) fn from_owned_raw(value: BNStructureMember) -> Self {
- let owned = Self::from_raw(&value);
- Self::free_raw(value);
- owned
- }
-
- pub(crate) fn into_raw(value: Self) -> BNStructureMember {
- let bn_name = BnString::new(value.name);
- BNStructureMember {
- type_: unsafe { Ref::into_raw(value.ty.contents) }.handle,
- name: BnString::into_raw(bn_name),
- offset: value.offset,
- typeConfidence: value.ty.confidence,
- access: value.access,
- scope: value.scope,
- bitPosition: value.bit_position.unwrap_or(0),
- bitWidth: value.bit_width.unwrap_or(0),
- }
- }
-
- pub(crate) fn free_raw(value: BNStructureMember) {
- let _ = unsafe { Type::ref_from_raw(value.type_) };
- unsafe { BnString::free_raw(value.name) };
- }
-
- pub fn new(
- ty: Conf<Ref<Type>>,
- name: String,
- offset: u64,
- access: MemberAccess,
- scope: MemberScope,
- ) -> Self {
- Self {
- ty,
- name,
- offset,
- access,
- scope,
- bit_position: None,
- bit_width: None,
- }
- }
-
- pub fn new_bitfield(
- ty: Conf<Ref<Type>>,
- name: String,
- bit_offset: u64,
- bit_width: u8,
- access: MemberAccess,
- scope: MemberScope,
- ) -> Self {
- Self {
- ty,
- name,
- offset: bit_offset / 8,
- access,
- scope,
- bit_position: Some((bit_offset % 8) as u8),
- bit_width: Some(bit_width),
- }
- }
-
- // TODO: Do we count bitwidth here?
- /// Whether the offset within the accessible range of the member.
- pub fn is_offset_valid(&self, offset: u64) -> bool {
- self.offset <= offset && offset < self.offset + self.ty.contents.width()
- }
-
- /// Member offset in bits.
- pub fn bit_offset(&self) -> u64 {
- (self.offset * 8) + self.bit_position.unwrap_or(0) as u64
- }
-}
-
-impl CoreArrayProvider for StructureMember {
- type Raw = BNStructureMember;
- type Context = ();
- type Wrapped<'a> = Self;
-}
-
-unsafe impl CoreArrayProviderInner for StructureMember {
- unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
- BNFreeStructureMemberList(raw, count)
- }
-
- unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
- Self::from_raw(raw)
- }
-}
-
-#[derive(Debug, Clone, Hash, PartialEq, Eq)]
-pub struct InheritedStructureMember {
- pub base: Ref<NamedTypeReference>,
- pub base_offset: u64,
- pub member: StructureMember,
- pub member_index: usize,
-}
-
-impl InheritedStructureMember {
- pub(crate) fn from_raw(value: &BNInheritedStructureMember) -> Self {
- Self {
- base: unsafe { NamedTypeReference::from_raw(value.base) }.to_owned(),
- base_offset: value.baseOffset,
- member: StructureMember::from_raw(&value.member),
- member_index: value.memberIndex,
- }
- }
-
- pub(crate) fn from_owned_raw(value: BNInheritedStructureMember) -> Self {
- let owned = Self::from_raw(&value);
- Self::free_raw(value);
- owned
- }
-
- pub(crate) fn into_raw(value: Self) -> BNInheritedStructureMember {
- BNInheritedStructureMember {
- base: unsafe { Ref::into_raw(value.base) }.handle,
- baseOffset: value.base_offset,
- member: StructureMember::into_raw(value.member),
- memberIndex: value.member_index,
- }
- }
-
- pub(crate) fn free_raw(value: BNInheritedStructureMember) {
- let _ = unsafe { NamedTypeReference::ref_from_raw(value.base) };
- StructureMember::free_raw(value.member);
- }
-
- pub fn new(
- base: Ref<NamedTypeReference>,
- base_offset: u64,
- member: StructureMember,
- member_index: usize,
- ) -> Self {
- Self {
- base,
- base_offset,
- member,
- member_index,
- }
- }
-}
-
-#[derive(Debug, Clone, Hash, PartialEq, Eq)]
-pub struct BaseStructure {
- pub ty: Ref<NamedTypeReference>,
- pub offset: u64,
- pub width: u64,
-}
-
-impl BaseStructure {
- pub(crate) fn from_raw(value: &BNBaseStructure) -> Self {
- Self {
- ty: unsafe { NamedTypeReference::from_raw(value.type_) }.to_owned(),
- offset: value.offset,
- width: value.width,
- }
- }
-
- pub(crate) fn from_owned_raw(value: BNBaseStructure) -> Self {
- let owned = Self::from_raw(&value);
- Self::free_raw(value);
- owned
- }
-
- pub(crate) fn into_raw(value: Self) -> BNBaseStructure {
- BNBaseStructure {
- type_: unsafe { Ref::into_raw(value.ty) }.handle,
- offset: value.offset,
- width: value.width,
- }
- }
-
- pub(crate) fn into_owned_raw(value: &Self) -> BNBaseStructure {
- BNBaseStructure {
- type_: value.ty.handle,
- offset: value.offset,
- width: value.width,
- }
- }
-
- pub(crate) fn free_raw(value: BNBaseStructure) {
- let _ = unsafe { NamedTypeReference::ref_from_raw(value.type_) };
- }
-
- pub fn new(ty: Ref<NamedTypeReference>, offset: u64, width: u64) -> Self {
- Self { ty, offset, width }
- }
-}
-
#[derive(PartialEq, Eq, Hash)]
pub struct NamedTypeReference {
pub(crate) handle: *mut BNNamedTypeReference,
@@ -2435,6 +1560,7 @@ impl QualifiedNameTypeAndId {
}
}
+ #[allow(unused)]
pub(crate) fn from_owned_raw(value: BNQualifiedNameTypeAndId) -> Self {
let owned = Self::from_raw(&value);
Self::free_raw(value);
@@ -2495,6 +1621,7 @@ impl NameAndType {
}
}
+ #[allow(unused)]
pub(crate) fn from_owned_raw(value: BNNameAndType) -> Self {
let owned = Self::from_raw(&value);
Self::free_raw(value);
diff --git a/rust/src/type_archive.rs b/rust/src/types/archive.rs
index 4a047205..15f4cbfe 100644
--- a/rust/src/type_archive.rs
+++ b/rust/src/types/archive.rs
@@ -1,6 +1,6 @@
use crate::progress::{NoProgressCallback, ProgressCallback};
use binaryninjacore_sys::*;
-use std::ffi::{c_char, c_void, CStr};
+use std::ffi::{c_char, c_void, CStr, CString};
use std::fmt::{Debug, Display, Formatter};
use std::hash::Hash;
use std::path::{Path, PathBuf};
@@ -11,8 +11,9 @@ use crate::metadata::Metadata;
use crate::platform::Platform;
use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable};
use crate::string::{raw_to_string, BnString, IntoCStr};
-use crate::type_container::TypeContainer;
-use crate::types::{QualifiedName, QualifiedNameAndType, QualifiedNameTypeAndId, Type};
+use crate::types::{
+ QualifiedName, QualifiedNameAndType, QualifiedNameTypeAndId, Type, TypeContainer,
+};
#[repr(transparent)]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -57,6 +58,14 @@ unsafe impl CoreArrayProviderInner for TypeArchiveSnapshotId {
}
}
+impl IntoCStr for TypeArchiveSnapshotId {
+ type Result = CString;
+
+ fn to_cstr(self) -> Self::Result {
+ self.to_string().to_cstr()
+ }
+}
+
/// Type Archives are a collection of types which can be shared between different analysis
/// sessions and are backed by a database file on disk. Their types can be modified, and
/// a history of previous versions of types is stored in snapshots in the archive.
diff --git a/rust/src/type_container.rs b/rust/src/types/container.rs
index e8c915df..5096ac78 100644
--- a/rust/src/type_container.rs
+++ b/rust/src/types/container.rs
@@ -12,8 +12,7 @@ use crate::platform::Platform;
use crate::progress::{NoProgressCallback, ProgressCallback};
use crate::rc::{Array, Ref};
use crate::string::{raw_to_string, BnString, IntoCStr};
-use crate::type_parser::{TypeParserError, TypeParserResult};
-use crate::types::{QualifiedName, QualifiedNameAndType, Type};
+use crate::types::{QualifiedName, QualifiedNameAndType, Type, TypeParserError, TypeParserResult};
use binaryninjacore_sys::*;
use std::collections::HashMap;
use std::ffi::{c_char, c_void};
diff --git a/rust/src/types/enumeration.rs b/rust/src/types/enumeration.rs
new file mode 100644
index 00000000..70c266e1
--- /dev/null
+++ b/rust/src/types/enumeration.rs
@@ -0,0 +1,201 @@
+use crate::rc::{Ref, RefCountable};
+use crate::string::{raw_to_string, BnString, IntoCStr};
+use binaryninjacore_sys::*;
+use std::fmt::{Debug, Formatter};
+
+#[derive(PartialEq, Eq, Hash)]
+pub struct EnumerationBuilder {
+ pub(crate) handle: *mut BNEnumerationBuilder,
+}
+
+impl EnumerationBuilder {
+ pub fn new() -> Self {
+ Self {
+ handle: unsafe { BNCreateEnumerationBuilder() },
+ }
+ }
+
+ pub(crate) unsafe fn from_raw(handle: *mut BNEnumerationBuilder) -> Self {
+ Self { handle }
+ }
+
+ pub fn finalize(&self) -> Ref<Enumeration> {
+ unsafe { Enumeration::ref_from_raw(BNFinalizeEnumerationBuilder(self.handle)) }
+ }
+
+ pub fn append(&mut self, name: &str) -> &mut Self {
+ let name = name.to_cstr();
+ unsafe {
+ BNAddEnumerationBuilderMember(self.handle, name.as_ref().as_ptr() as _);
+ }
+ self
+ }
+
+ pub fn insert(&mut self, name: &str, value: u64) -> &mut Self {
+ let name = name.to_cstr();
+ unsafe {
+ BNAddEnumerationBuilderMemberWithValue(self.handle, name.as_ref().as_ptr() as _, value);
+ }
+ self
+ }
+
+ pub fn replace(&mut self, id: usize, name: &str, value: u64) -> &mut Self {
+ let name = name.to_cstr();
+ unsafe {
+ BNReplaceEnumerationBuilderMember(self.handle, id, name.as_ref().as_ptr() as _, value);
+ }
+ self
+ }
+
+ pub fn remove(&mut self, id: usize) -> &mut Self {
+ unsafe {
+ BNRemoveEnumerationBuilderMember(self.handle, id);
+ }
+
+ self
+ }
+
+ pub fn members(&self) -> Vec<EnumerationMember> {
+ unsafe {
+ let mut count = 0;
+ let members_raw_ptr = BNGetEnumerationBuilderMembers(self.handle, &mut count);
+ let members_raw: &[BNEnumerationMember] =
+ std::slice::from_raw_parts(members_raw_ptr, count);
+ let members = members_raw
+ .iter()
+ .map(EnumerationMember::from_raw)
+ .collect();
+ BNFreeEnumerationMemberList(members_raw_ptr, count);
+ members
+ }
+ }
+}
+
+impl Default for EnumerationBuilder {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl From<&Enumeration> for EnumerationBuilder {
+ fn from(enumeration: &Enumeration) -> Self {
+ unsafe {
+ Self::from_raw(BNCreateEnumerationBuilderFromEnumeration(
+ enumeration.handle,
+ ))
+ }
+ }
+}
+
+impl Drop for EnumerationBuilder {
+ fn drop(&mut self) {
+ unsafe { BNFreeEnumerationBuilder(self.handle) };
+ }
+}
+
+#[derive(PartialEq, Eq, Hash)]
+pub struct Enumeration {
+ pub(crate) handle: *mut BNEnumeration,
+}
+
+impl Enumeration {
+ pub(crate) unsafe fn ref_from_raw(handle: *mut BNEnumeration) -> Ref<Self> {
+ debug_assert!(!handle.is_null());
+ Ref::new(Self { handle })
+ }
+
+ pub fn builder() -> EnumerationBuilder {
+ EnumerationBuilder::new()
+ }
+
+ pub fn members(&self) -> Vec<EnumerationMember> {
+ unsafe {
+ let mut count = 0;
+ let members_raw_ptr = BNGetEnumerationMembers(self.handle, &mut count);
+ debug_assert!(!members_raw_ptr.is_null());
+ let members_raw: &[BNEnumerationMember] =
+ std::slice::from_raw_parts(members_raw_ptr, count);
+ let members = members_raw
+ .iter()
+ .map(EnumerationMember::from_raw)
+ .collect();
+ BNFreeEnumerationMemberList(members_raw_ptr, count);
+ members
+ }
+ }
+}
+
+impl Debug for Enumeration {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("Enumeration")
+ .field("members", &self.members())
+ .finish()
+ }
+}
+
+unsafe impl RefCountable for Enumeration {
+ unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
+ Self::ref_from_raw(BNNewEnumerationReference(handle.handle))
+ }
+
+ unsafe fn dec_ref(handle: &Self) {
+ BNFreeEnumeration(handle.handle);
+ }
+}
+
+impl ToOwned for Enumeration {
+ type Owned = Ref<Self>;
+
+ fn to_owned(&self) -> Self::Owned {
+ unsafe { RefCountable::inc_ref(self) }
+ }
+}
+
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
+pub struct EnumerationMember {
+ pub name: String,
+ /// The associated constant value for the member.
+ pub value: u64,
+ /// Whether this is the default member for the associated [`Enumeration`].
+ pub default: bool,
+}
+
+impl EnumerationMember {
+ pub(crate) fn from_raw(value: &BNEnumerationMember) -> Self {
+ Self {
+ name: raw_to_string(value.name).unwrap(),
+ value: value.value,
+ default: value.isDefault,
+ }
+ }
+
+ #[allow(unused)]
+ pub(crate) fn from_owned_raw(value: BNEnumerationMember) -> Self {
+ let owned = Self::from_raw(&value);
+ Self::free_raw(value);
+ owned
+ }
+
+ #[allow(unused)]
+ pub(crate) fn into_raw(value: Self) -> BNEnumerationMember {
+ let bn_name = BnString::new(value.name);
+ BNEnumerationMember {
+ name: BnString::into_raw(bn_name),
+ value: value.value,
+ isDefault: value.default,
+ }
+ }
+
+ #[allow(unused)]
+ pub(crate) fn free_raw(value: BNEnumerationMember) {
+ unsafe { BnString::free_raw(value.name) };
+ }
+
+ pub fn new(name: String, value: u64, default: bool) -> Self {
+ Self {
+ name,
+ value,
+ default,
+ }
+ }
+}
diff --git a/rust/src/type_library.rs b/rust/src/types/library.rs
index 89f5e48f..89f5e48f 100644
--- a/rust/src/type_library.rs
+++ b/rust/src/types/library.rs
diff --git a/rust/src/type_parser.rs b/rust/src/types/parser.rs
index 8ad0725f..1ee07188 100644
--- a/rust/src/type_parser.rs
+++ b/rust/src/types/parser.rs
@@ -7,8 +7,7 @@ use std::ptr::NonNull;
use crate::platform::Platform;
use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref};
use crate::string::{raw_to_string, BnString, IntoCStr};
-use crate::type_container::TypeContainer;
-use crate::types::{QualifiedName, QualifiedNameAndType, Type};
+use crate::types::{QualifiedName, QualifiedNameAndType, Type, TypeContainer};
pub type TypeParserErrorSeverity = BNTypeParserErrorSeverity;
pub type TypeParserOption = BNTypeParserOption;
diff --git a/rust/src/type_printer.rs b/rust/src/types/printer.rs
index a7495f1c..d168434e 100644
--- a/rust/src/type_printer.rs
+++ b/rust/src/types/printer.rs
@@ -5,8 +5,7 @@ use crate::disassembly::InstructionTextToken;
use crate::platform::Platform;
use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref};
use crate::string::{raw_to_string, BnString, IntoCStr};
-use crate::type_container::TypeContainer;
-use crate::types::{NamedTypeReference, QualifiedName, QualifiedNameAndType, Type};
+use crate::types::{NamedTypeReference, QualifiedName, QualifiedNameAndType, Type, TypeContainer};
use binaryninjacore_sys::*;
use std::ffi::{c_char, c_int, c_void};
use std::ptr::NonNull;
diff --git a/rust/src/types/structure.rs b/rust/src/types/structure.rs
new file mode 100644
index 00000000..7de466a4
--- /dev/null
+++ b/rust/src/types/structure.rs
@@ -0,0 +1,696 @@
+use crate::confidence::Conf;
+use crate::rc::{CoreArrayProvider, CoreArrayProviderInner, Ref, RefCountable};
+use crate::string::{raw_to_string, BnString, IntoCStr};
+use crate::types::{
+ MemberAccess, MemberScope, NamedTypeReference, StructureType, Type, TypeContainer,
+};
+use binaryninjacore_sys::*;
+use std::fmt::{Debug, Formatter};
+
+// Needed for doc comments
+#[allow(unused)]
+use crate::binary_view::BinaryViewExt;
+
+#[derive(PartialEq, Eq, Hash)]
+pub struct StructureBuilder {
+ pub(crate) handle: *mut BNStructureBuilder,
+}
+
+/// ```no_run
+/// // Includes
+/// # use binaryninja::binary_view::BinaryViewExt;
+/// use binaryninja::types::{MemberAccess, MemberScope, Structure, StructureBuilder, Type};
+///
+/// // Types to use in the members
+/// let field_1_ty = Type::named_int(5, false, "my_weird_int_type");
+/// let field_2_ty = Type::int(4, false);
+/// let field_3_ty = Type::int(8, false);
+///
+/// // Assign those fields
+/// let mut my_custom_struct = StructureBuilder::new();
+/// my_custom_struct
+/// .insert(
+/// &field_1_ty,
+/// "field_1",
+/// 0,
+/// false,
+/// MemberAccess::PublicAccess,
+/// MemberScope::NoScope,
+/// )
+/// .insert(
+/// &field_2_ty,
+/// "field_2",
+/// 5,
+/// false,
+/// MemberAccess::PublicAccess,
+/// MemberScope::NoScope,
+/// )
+/// .insert(
+/// &field_3_ty,
+/// "field_3",
+/// 9,
+/// false,
+/// MemberAccess::PublicAccess,
+/// MemberScope::NoScope,
+/// )
+/// .append(
+/// &field_1_ty,
+/// "field_4",
+/// MemberAccess::PublicAccess,
+/// MemberScope::NoScope,
+/// );
+///
+/// // Convert structure to type
+/// let my_custom_structure_type = Type::structure(&my_custom_struct.finalize());
+///
+/// // Add the struct to the binary view to use in analysis
+/// let bv = binaryninja::load("example").unwrap();
+/// bv.define_user_type("my_custom_struct", &my_custom_structure_type);
+/// ```
+impl StructureBuilder {
+ pub fn new() -> Self {
+ Self {
+ handle: unsafe { BNCreateStructureBuilder() },
+ }
+ }
+
+ pub(crate) unsafe fn from_raw(handle: *mut BNStructureBuilder) -> Self {
+ debug_assert!(!handle.is_null());
+ Self { handle }
+ }
+
+ // TODO: Document the width adjustment with alignment.
+ pub fn finalize(&self) -> Ref<Structure> {
+ let raw_struct_ptr = unsafe { BNFinalizeStructureBuilder(self.handle) };
+ unsafe { Structure::ref_from_raw(raw_struct_ptr) }
+ }
+
+ /// Sets the width of the [`StructureBuilder`] to the new width.
+ ///
+ /// This will remove all previously inserted members outside the new width. This is done by computing
+ /// the member access range (member offset + member width) and if it is larger than the new width
+ /// it will be removed.
+ pub fn width(&mut self, width: u64) -> &mut Self {
+ unsafe {
+ BNSetStructureBuilderWidth(self.handle, width);
+ }
+ self
+ }
+
+ pub fn alignment(&mut self, alignment: usize) -> &mut Self {
+ unsafe {
+ BNSetStructureBuilderAlignment(self.handle, alignment);
+ }
+ self
+ }
+
+ /// Sets whether the [`StructureBuilder`] is packed.
+ ///
+ /// If set the alignment of the structure will be `1`. You do not need to set the alignment to `1`.
+ pub fn packed(&mut self, packed: bool) -> &mut Self {
+ unsafe {
+ BNSetStructureBuilderPacked(self.handle, packed);
+ }
+ self
+ }
+
+ pub fn structure_type(&mut self, t: StructureType) -> &mut Self {
+ unsafe { BNSetStructureBuilderType(self.handle, t) };
+ self
+ }
+
+ pub fn pointer_offset(&mut self, offset: i64) -> &mut Self {
+ unsafe { BNSetStructureBuilderPointerOffset(self.handle, offset) };
+ self
+ }
+
+ pub fn propagates_data_var_refs(&mut self, propagates: bool) -> &mut Self {
+ unsafe { BNSetStructureBuilderPropagatesDataVariableReferences(self.handle, propagates) };
+ self
+ }
+
+ pub fn base_structures(&mut self, bases: &[BaseStructure]) -> &mut Self {
+ let raw_base_structs: Vec<BNBaseStructure> =
+ bases.iter().map(BaseStructure::into_owned_raw).collect();
+ unsafe {
+ BNSetBaseStructuresForStructureBuilder(
+ self.handle,
+ raw_base_structs.as_ptr() as *mut _,
+ raw_base_structs.len(),
+ )
+ };
+ self
+ }
+
+ /// Append a member at the next available byte offset.
+ ///
+ /// Otherwise, consider using:
+ ///
+ /// - [`StructureBuilder::insert_member`]
+ /// - [`StructureBuilder::insert`]
+ /// - [`StructureBuilder::insert_bitwise`]
+ pub fn append<'a, T: Into<Conf<&'a Type>>>(
+ &mut self,
+ ty: T,
+ name: &str,
+ access: MemberAccess,
+ scope: MemberScope,
+ ) -> &mut Self {
+ let name = name.to_cstr();
+ let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
+ unsafe {
+ BNAddStructureBuilderMember(
+ self.handle,
+ &owned_raw_ty,
+ name.as_ref().as_ptr() as _,
+ access,
+ scope,
+ );
+ }
+ self
+ }
+
+ /// Insert an already constructed [`StructureMember`].
+ ///
+ /// Otherwise, consider using:
+ ///
+ /// - [`StructureBuilder::append`]
+ /// - [`StructureBuilder::insert`]
+ /// - [`StructureBuilder::insert_bitwise`]
+ pub fn insert_member(
+ &mut self,
+ member: StructureMember,
+ overwrite_existing: bool,
+ ) -> &mut Self {
+ self.insert_bitwise(
+ &member.ty,
+ &member.name,
+ member.bit_offset(),
+ member.bit_width,
+ overwrite_existing,
+ member.access,
+ member.scope,
+ );
+ self
+ }
+
+ /// Inserts a member at the `offset` (in bytes).
+ ///
+ /// If you need to insert a member at a specific bit within a given byte (like a bitfield), you
+ /// can use [`StructureBuilder::insert_bitwise`].
+ pub fn insert<'a, T: Into<Conf<&'a Type>>>(
+ &mut self,
+ ty: T,
+ name: &str,
+ offset: u64,
+ overwrite_existing: bool,
+ access: MemberAccess,
+ scope: MemberScope,
+ ) -> &mut Self {
+ self.insert_bitwise(
+ ty,
+ name,
+ offset * 8,
+ None,
+ overwrite_existing,
+ access,
+ scope,
+ )
+ }
+
+ /// Inserts a member at `bit_offset` with an optional `bit_width`.
+ ///
+ /// NOTE: The `bit_offset` is relative to the start of the structure, for example, passing `8` will place
+ /// the field at the start of the byte `0x1`.
+ pub fn insert_bitwise<'a, T: Into<Conf<&'a Type>>>(
+ &mut self,
+ ty: T,
+ name: &str,
+ bit_offset: u64,
+ bit_width: Option<u8>,
+ overwrite_existing: bool,
+ access: MemberAccess,
+ scope: MemberScope,
+ ) -> &mut Self {
+ let name = name.to_cstr();
+ let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
+ let byte_offset = bit_offset / 8;
+ let bit_position = bit_offset % 8;
+ unsafe {
+ BNAddStructureBuilderMemberAtOffset(
+ self.handle,
+ &owned_raw_ty,
+ name.as_ref().as_ptr() as _,
+ byte_offset,
+ overwrite_existing,
+ access,
+ scope,
+ bit_position as u8,
+ bit_width.unwrap_or(0),
+ );
+ }
+ self
+ }
+
+ pub fn replace<'a, T: Into<Conf<&'a Type>>>(
+ &mut self,
+ index: usize,
+ ty: T,
+ name: &str,
+ overwrite_existing: bool,
+ ) -> &mut Self {
+ let name = name.to_cstr();
+ let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
+ unsafe {
+ BNReplaceStructureBuilderMember(
+ self.handle,
+ index,
+ &owned_raw_ty,
+ name.as_ref().as_ptr() as _,
+ overwrite_existing,
+ )
+ }
+ self
+ }
+
+ /// Removes the member at a given index.
+ pub fn remove(&mut self, index: usize) -> &mut Self {
+ unsafe { BNRemoveStructureBuilderMember(self.handle, index) };
+ self
+ }
+
+ // TODO: We should add BNGetStructureBuilderAlignedWidth
+ /// Gets the current **unaligned** width of the structure.
+ ///
+ /// This cannot be used to accurately get the width of a non-packed structure.
+ pub fn current_width(&self) -> u64 {
+ unsafe { BNGetStructureBuilderWidth(self.handle) }
+ }
+}
+
+impl From<&Structure> for StructureBuilder {
+ fn from(structure: &Structure) -> StructureBuilder {
+ unsafe { Self::from_raw(BNCreateStructureBuilderFromStructure(structure.handle)) }
+ }
+}
+
+impl From<Vec<StructureMember>> for StructureBuilder {
+ fn from(members: Vec<StructureMember>) -> StructureBuilder {
+ let mut builder = StructureBuilder::new();
+ for member in members {
+ builder.insert_member(member, false);
+ }
+ builder
+ }
+}
+
+impl Drop for StructureBuilder {
+ fn drop(&mut self) {
+ unsafe { BNFreeStructureBuilder(self.handle) };
+ }
+}
+
+impl Default for StructureBuilder {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+#[derive(PartialEq, Eq, Hash)]
+pub struct Structure {
+ pub(crate) handle: *mut BNStructure,
+}
+
+impl Structure {
+ pub(crate) unsafe fn ref_from_raw(handle: *mut BNStructure) -> Ref<Self> {
+ debug_assert!(!handle.is_null());
+ Ref::new(Self { handle })
+ }
+
+ pub fn builder() -> StructureBuilder {
+ StructureBuilder::new()
+ }
+
+ pub fn width(&self) -> u64 {
+ unsafe { BNGetStructureWidth(self.handle) }
+ }
+
+ pub fn structure_type(&self) -> StructureType {
+ unsafe { BNGetStructureType(self.handle) }
+ }
+
+ /// Retrieve the members that are accessible at a given offset.
+ ///
+ /// The reason for this being plural is that members may overlap and the offset is in bytes
+ /// where a bitfield may contain multiple members at the given byte.
+ ///
+ /// Unions are also represented as structures and will cause this function to return
+ /// **all** members that can reach that offset.
+ ///
+ /// We must pass a [`TypeContainer`] here so that we can resolve base structure members, as they
+ /// are treated as members through this function. Typically, you get the [`TypeContainer`]
+ /// through the binary view with [`BinaryViewExt::type_container`].
+ pub fn members_at_offset(
+ &self,
+ container: &TypeContainer,
+ offset: u64,
+ ) -> Vec<StructureMember> {
+ self.members_including_inherited(container)
+ .into_iter()
+ .filter(|m| m.member.is_offset_valid(offset))
+ .map(|m| m.member)
+ .collect()
+ }
+
+ /// Return the list of non-inherited structure members.
+ ///
+ /// If you want to get all members, including ones inherited from base structures,
+ /// use [`Structure::members_including_inherited`] instead.
+ pub fn members(&self) -> Vec<StructureMember> {
+ unsafe {
+ let mut count = 0;
+ let members_raw_ptr: *mut BNStructureMember =
+ BNGetStructureMembers(self.handle, &mut count);
+ debug_assert!(!members_raw_ptr.is_null());
+ let members_raw = std::slice::from_raw_parts(members_raw_ptr, count);
+ let members = members_raw.iter().map(StructureMember::from_raw).collect();
+ BNFreeStructureMemberList(members_raw_ptr, count);
+ members
+ }
+ }
+
+ /// Returns the list of all structure members, including inherited ones.
+ ///
+ /// Because we must traverse through base structures, we have to provide the [`TypeContainer`];
+ /// in most cases it is ok to provide the binary views container via [`BinaryViewExt::type_container`].
+ pub fn members_including_inherited(
+ &self,
+ container: &TypeContainer,
+ ) -> Vec<InheritedStructureMember> {
+ unsafe {
+ let mut count = 0;
+ let members_raw_ptr: *mut BNInheritedStructureMember =
+ BNGetStructureMembersIncludingInherited(
+ self.handle,
+ container.handle.as_ptr(),
+ &mut count,
+ );
+ debug_assert!(!members_raw_ptr.is_null());
+ let members_raw = std::slice::from_raw_parts(members_raw_ptr, count);
+ let members = members_raw
+ .iter()
+ .map(InheritedStructureMember::from_raw)
+ .collect();
+ BNFreeInheritedStructureMemberList(members_raw_ptr, count);
+ members
+ }
+ }
+
+ /// Retrieve the list of base structures for the structure. These base structures are what give
+ /// a structure inherited members.
+ pub fn base_structures(&self) -> Vec<BaseStructure> {
+ let mut count = 0;
+ let bases_raw_ptr = unsafe { BNGetBaseStructuresForStructure(self.handle, &mut count) };
+ debug_assert!(!bases_raw_ptr.is_null());
+ let bases_raw = unsafe { std::slice::from_raw_parts(bases_raw_ptr, count) };
+ let bases = bases_raw.iter().map(BaseStructure::from_raw).collect();
+ unsafe { BNFreeBaseStructureList(bases_raw_ptr, count) };
+ bases
+ }
+
+ /// Whether the structure is packed or not.
+ pub fn is_packed(&self) -> bool {
+ unsafe { BNIsStructurePacked(self.handle) }
+ }
+
+ pub fn alignment(&self) -> usize {
+ unsafe { BNGetStructureAlignment(self.handle) }
+ }
+}
+
+impl Debug for Structure {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("Structure")
+ .field("width", &self.width())
+ .field("alignment", &self.alignment())
+ .field("packed", &self.is_packed())
+ .field("structure_type", &self.structure_type())
+ .field("base_structures", &self.base_structures())
+ .field("members", &self.members())
+ .finish()
+ }
+}
+
+unsafe impl RefCountable for Structure {
+ unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
+ Self::ref_from_raw(BNNewStructureReference(handle.handle))
+ }
+
+ unsafe fn dec_ref(handle: &Self) {
+ BNFreeStructure(handle.handle);
+ }
+}
+
+impl ToOwned for Structure {
+ type Owned = Ref<Self>;
+
+ fn to_owned(&self) -> Self::Owned {
+ unsafe { RefCountable::inc_ref(self) }
+ }
+}
+
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
+pub struct StructureMember {
+ pub ty: Conf<Ref<Type>>,
+ // TODO: Shouldnt this be a QualifiedName? The ffi says no...
+ pub name: String,
+ /// The byte offset of the member.
+ pub offset: u64,
+ pub access: MemberAccess,
+ pub scope: MemberScope,
+ /// The bit position relative to the byte offset.
+ pub bit_position: Option<u8>,
+ pub bit_width: Option<u8>,
+}
+
+impl StructureMember {
+ pub(crate) fn from_raw(value: &BNStructureMember) -> Self {
+ Self {
+ ty: Conf::new(
+ unsafe { Type::from_raw(value.type_) }.to_owned(),
+ value.typeConfidence,
+ ),
+ // TODO: I dislike using this function here.
+ name: raw_to_string(value.name as *mut _).unwrap(),
+ offset: value.offset,
+ access: value.access,
+ scope: value.scope,
+ bit_position: match value.bitPosition {
+ 0 => None,
+ _ => Some(value.bitPosition),
+ },
+ bit_width: match value.bitWidth {
+ 0 => None,
+ _ => Some(value.bitWidth),
+ },
+ }
+ }
+
+ #[allow(unused)]
+ pub(crate) fn from_owned_raw(value: BNStructureMember) -> Self {
+ let owned = Self::from_raw(&value);
+ Self::free_raw(value);
+ owned
+ }
+
+ #[allow(unused)]
+ pub(crate) fn into_raw(value: Self) -> BNStructureMember {
+ let bn_name = BnString::new(value.name);
+ BNStructureMember {
+ type_: unsafe { Ref::into_raw(value.ty.contents) }.handle,
+ name: BnString::into_raw(bn_name),
+ offset: value.offset,
+ typeConfidence: value.ty.confidence,
+ access: value.access,
+ scope: value.scope,
+ bitPosition: value.bit_position.unwrap_or(0),
+ bitWidth: value.bit_width.unwrap_or(0),
+ }
+ }
+
+ #[allow(unused)]
+ pub(crate) fn free_raw(value: BNStructureMember) {
+ let _ = unsafe { Type::ref_from_raw(value.type_) };
+ unsafe { BnString::free_raw(value.name) };
+ }
+
+ pub fn new(
+ ty: Conf<Ref<Type>>,
+ name: String,
+ offset: u64,
+ access: MemberAccess,
+ scope: MemberScope,
+ ) -> Self {
+ Self {
+ ty,
+ name,
+ offset,
+ access,
+ scope,
+ bit_position: None,
+ bit_width: None,
+ }
+ }
+
+ pub fn new_bitfield(
+ ty: Conf<Ref<Type>>,
+ name: String,
+ bit_offset: u64,
+ bit_width: u8,
+ access: MemberAccess,
+ scope: MemberScope,
+ ) -> Self {
+ Self {
+ ty,
+ name,
+ offset: bit_offset / 8,
+ access,
+ scope,
+ bit_position: Some((bit_offset % 8) as u8),
+ bit_width: Some(bit_width),
+ }
+ }
+
+ // TODO: Do we count bitwidth here?
+ /// Whether the offset within the accessible range of the member.
+ pub fn is_offset_valid(&self, offset: u64) -> bool {
+ self.offset <= offset && offset < self.offset + self.ty.contents.width()
+ }
+
+ /// Member offset in bits.
+ pub fn bit_offset(&self) -> u64 {
+ (self.offset * 8) + self.bit_position.unwrap_or(0) as u64
+ }
+}
+
+impl CoreArrayProvider for StructureMember {
+ type Raw = BNStructureMember;
+ type Context = ();
+ type Wrapped<'a> = Self;
+}
+
+unsafe impl CoreArrayProviderInner for StructureMember {
+ unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
+ BNFreeStructureMemberList(raw, count)
+ }
+
+ unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
+ Self::from_raw(raw)
+ }
+}
+
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
+pub struct InheritedStructureMember {
+ pub base: Ref<NamedTypeReference>,
+ pub base_offset: u64,
+ pub member: StructureMember,
+ pub member_index: usize,
+}
+
+impl InheritedStructureMember {
+ pub(crate) fn from_raw(value: &BNInheritedStructureMember) -> Self {
+ Self {
+ base: unsafe { NamedTypeReference::from_raw(value.base) }.to_owned(),
+ base_offset: value.baseOffset,
+ member: StructureMember::from_raw(&value.member),
+ member_index: value.memberIndex,
+ }
+ }
+
+ #[allow(unused)]
+ pub(crate) fn from_owned_raw(value: BNInheritedStructureMember) -> Self {
+ let owned = Self::from_raw(&value);
+ Self::free_raw(value);
+ owned
+ }
+
+ #[allow(unused)]
+ pub(crate) fn into_raw(value: Self) -> BNInheritedStructureMember {
+ BNInheritedStructureMember {
+ base: unsafe { Ref::into_raw(value.base) }.handle,
+ baseOffset: value.base_offset,
+ member: StructureMember::into_raw(value.member),
+ memberIndex: value.member_index,
+ }
+ }
+
+ #[allow(unused)]
+ pub(crate) fn free_raw(value: BNInheritedStructureMember) {
+ let _ = unsafe { NamedTypeReference::ref_from_raw(value.base) };
+ StructureMember::free_raw(value.member);
+ }
+
+ pub fn new(
+ base: Ref<NamedTypeReference>,
+ base_offset: u64,
+ member: StructureMember,
+ member_index: usize,
+ ) -> Self {
+ Self {
+ base,
+ base_offset,
+ member,
+ member_index,
+ }
+ }
+}
+
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
+pub struct BaseStructure {
+ pub ty: Ref<NamedTypeReference>,
+ pub offset: u64,
+ pub width: u64,
+}
+
+impl BaseStructure {
+ pub(crate) fn from_raw(value: &BNBaseStructure) -> Self {
+ Self {
+ ty: unsafe { NamedTypeReference::from_raw(value.type_) }.to_owned(),
+ offset: value.offset,
+ width: value.width,
+ }
+ }
+
+ #[allow(unused)]
+ pub(crate) fn from_owned_raw(value: BNBaseStructure) -> Self {
+ let owned = Self::from_raw(&value);
+ Self::free_raw(value);
+ owned
+ }
+
+ #[allow(unused)]
+ pub(crate) fn into_raw(value: Self) -> BNBaseStructure {
+ BNBaseStructure {
+ type_: unsafe { Ref::into_raw(value.ty) }.handle,
+ offset: value.offset,
+ width: value.width,
+ }
+ }
+
+ pub(crate) fn into_owned_raw(value: &Self) -> BNBaseStructure {
+ BNBaseStructure {
+ type_: value.ty.handle,
+ offset: value.offset,
+ width: value.width,
+ }
+ }
+
+ #[allow(unused)]
+ pub(crate) fn free_raw(value: BNBaseStructure) {
+ let _ = unsafe { NamedTypeReference::ref_from_raw(value.type_) };
+ }
+
+ pub fn new(ty: Ref<NamedTypeReference>, offset: u64, width: u64) -> Self {
+ Self { ty, offset, width }
+ }
+}