binaryninja/
types.rs

1// Copyright 2021-2026 Vector 35 Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//! The model for representing types in Binary Ninja.
15//!
16//! [`Type`]'s are fundamental to analysis. With types, you can influence how decompilation resolves accesses,
17//! renders data, and tell the analysis of properties such as volatility and constness.
18//!
19//! Types are typically stored within a [`BinaryView`], [`TypeArchive`] or a [`TypeLibrary`].
20//!
21//! Types can be created using the [`TypeBuilder`] or one of the convenience functions. Another way
22//! to create a type is with a [`TypeParser`] if you have C type definitions.
23//!
24//! Some interfaces may expect to be passed a [`TypeContainer`] which itself does not store any type
25//! information, rather a generic interface to query for types by name or by id.
26
27pub mod archive;
28pub mod container;
29pub mod enumeration;
30pub mod library;
31pub mod parser;
32pub mod printer;
33pub mod structure;
34
35use binaryninjacore_sys::*;
36
37use crate::{
38    architecture::Architecture,
39    binary_view::{BinaryView, BinaryViewExt},
40    calling_convention::CoreCallingConvention,
41    rc::*,
42    string::{BnString, IntoCStr},
43};
44
45use crate::confidence::{Conf, MAX_CONFIDENCE, MIN_CONFIDENCE};
46use crate::string::raw_to_string;
47use crate::variable::{Variable, VariableSourceType};
48use std::num::NonZeroUsize;
49use std::{
50    collections::HashSet,
51    fmt::{Debug, Display, Formatter},
52    hash::{Hash, Hasher},
53    iter::IntoIterator,
54};
55
56pub use archive::{TypeArchive, TypeArchiveId, TypeArchiveSnapshotId};
57pub use container::TypeContainer;
58pub use enumeration::{Enumeration, EnumerationBuilder, EnumerationMember};
59pub use library::TypeLibrary;
60pub use parser::{
61    CoreTypeParser, ParsedType, TypeParser, TypeParserError, TypeParserErrorSeverity,
62    TypeParserResult,
63};
64pub use printer::{CoreTypePrinter, TypePrinter};
65pub use structure::{
66    BaseStructure, InheritedStructureMember, Structure, StructureBuilder, StructureMember,
67};
68
69#[deprecated(note = "Use crate::qualified_name::QualifiedName instead")]
70// Re-export QualifiedName so that we do not break public consumers.
71pub use crate::qualified_name::QualifiedName;
72
73pub type StructureType = BNStructureVariant;
74pub type ReferenceType = BNReferenceType;
75pub type TypeClass = BNTypeClass;
76pub type NamedTypeReferenceClass = BNNamedTypeReferenceClass;
77pub type MemberAccess = BNMemberAccess;
78pub type MemberScope = BNMemberScope;
79pub type IntegerDisplayType = BNIntegerDisplayType;
80pub type PointerBaseType = BNPointerBaseType;
81
82#[derive(PartialEq, Eq, Hash)]
83pub struct TypeBuilder {
84    pub(crate) handle: *mut BNTypeBuilder,
85}
86
87impl TypeBuilder {
88    pub fn new(t: &Type) -> Self {
89        unsafe { Self::from_raw(BNCreateTypeBuilderFromType(t.handle)) }
90    }
91
92    pub(crate) unsafe fn from_raw(handle: *mut BNTypeBuilder) -> Self {
93        debug_assert!(!handle.is_null());
94        Self { handle }
95    }
96
97    /// Turn the [`TypeBuilder`] into a [`Type`].
98    pub fn finalize(&self) -> Ref<Type> {
99        unsafe { Type::ref_from_raw(BNFinalizeTypeBuilder(self.handle)) }
100    }
101
102    pub fn set_can_return<T: Into<Conf<bool>>>(&self, value: T) -> &Self {
103        let mut bool_with_confidence = value.into().into();
104        unsafe { BNSetFunctionTypeBuilderCanReturn(self.handle, &mut bool_with_confidence) };
105        self
106    }
107
108    pub fn set_pure<T: Into<Conf<bool>>>(&self, value: T) -> &Self {
109        let mut bool_with_confidence = value.into().into();
110        unsafe { BNSetTypeBuilderPure(self.handle, &mut bool_with_confidence) };
111        self
112    }
113
114    pub fn set_const<T: Into<Conf<bool>>>(&self, value: T) -> &Self {
115        let mut bool_with_confidence = value.into().into();
116        unsafe { BNTypeBuilderSetConst(self.handle, &mut bool_with_confidence) };
117        self
118    }
119
120    pub fn set_volatile<T: Into<Conf<bool>>>(&self, value: T) -> &Self {
121        let mut bool_with_confidence = value.into().into();
122        unsafe { BNTypeBuilderSetVolatile(self.handle, &mut bool_with_confidence) };
123        self
124    }
125
126    pub fn set_pointer_base(&self, base_type: PointerBaseType, base_offset: i64) -> &Self {
127        unsafe { BNSetTypeBuilderPointerBase(self.handle, base_type, base_offset) }
128        self
129    }
130
131    pub fn set_child_type<'a, T: Into<Conf<&'a Type>>>(&self, ty: T) -> &Self {
132        let mut type_with_confidence = Conf::<&Type>::into_raw(ty.into());
133        unsafe { BNTypeBuilderSetChildType(self.handle, &mut type_with_confidence) };
134        self
135    }
136
137    /// This is an alias for [`Self::set_child_type`].
138    pub fn set_target<'a, T: Into<Conf<&'a Type>>>(&self, ty: T) -> &Self {
139        self.set_child_type(ty)
140    }
141
142    /// This is an alias for [`Self::set_child_type`].
143    pub fn set_element_type<'a, T: Into<Conf<&'a Type>>>(&self, ty: T) -> &Self {
144        self.set_child_type(ty)
145    }
146
147    /// This is an alias for [`Self::set_child_type`].
148    pub fn set_return_value<'a, T: Into<Conf<&'a Type>>>(&self, ty: T) -> &Self {
149        self.set_child_type(ty)
150    }
151
152    pub fn set_signed<T: Into<Conf<bool>>>(&self, value: T) -> &Self {
153        let mut bool_with_confidence = value.into().into();
154        unsafe { BNTypeBuilderSetSigned(self.handle, &mut bool_with_confidence) };
155        self
156    }
157
158    // Readable properties
159
160    pub fn type_class(&self) -> TypeClass {
161        unsafe { BNGetTypeBuilderClass(self.handle) }
162    }
163
164    pub fn width(&self) -> u64 {
165        unsafe { BNGetTypeBuilderWidth(self.handle) }
166    }
167
168    pub fn alignment(&self) -> usize {
169        unsafe { BNGetTypeBuilderAlignment(self.handle) }
170    }
171
172    pub fn is_signed(&self) -> Conf<bool> {
173        unsafe { BNIsTypeBuilderSigned(self.handle).into() }
174    }
175
176    pub fn is_const(&self) -> Conf<bool> {
177        unsafe { BNIsTypeBuilderConst(self.handle).into() }
178    }
179
180    pub fn is_volatile(&self) -> Conf<bool> {
181        unsafe { BNIsTypeBuilderVolatile(self.handle).into() }
182    }
183
184    pub fn is_floating_point(&self) -> bool {
185        unsafe { BNIsTypeBuilderFloatingPoint(self.handle) }
186    }
187
188    pub fn child_type(&self) -> Option<Conf<Ref<Type>>> {
189        let raw_target = unsafe { BNGetTypeBuilderChildType(self.handle) };
190        match raw_target.type_.is_null() {
191            false => Some(Conf::<Ref<Type>>::from_owned_raw(raw_target)),
192            true => None,
193        }
194    }
195
196    /// This is an alias for [`Self::child_type`].
197    pub fn target(&self) -> Option<Conf<Ref<Type>>> {
198        self.child_type()
199    }
200
201    /// This is an alias for [`Self::child_type`].
202    pub fn element_type(&self) -> Option<Conf<Ref<Type>>> {
203        self.child_type()
204    }
205
206    /// This is an alias for [`Self::child_type`].
207    pub fn return_value(&self) -> Option<Conf<Ref<Type>>> {
208        self.child_type()
209    }
210
211    pub fn calling_convention(&self) -> Option<Conf<Ref<CoreCallingConvention>>> {
212        let raw_convention_confidence = unsafe { BNGetTypeBuilderCallingConvention(self.handle) };
213        match raw_convention_confidence.convention.is_null() {
214            false => Some(Conf::<Ref<CoreCallingConvention>>::from_owned_raw(
215                raw_convention_confidence,
216            )),
217            true => None,
218        }
219    }
220
221    pub fn parameters(&self) -> Option<Vec<FunctionParameter>> {
222        unsafe {
223            let mut count = 0;
224            let raw_parameters_ptr = BNGetTypeBuilderParameters(self.handle, &mut count);
225            match raw_parameters_ptr.is_null() {
226                false => {
227                    let raw_parameters = std::slice::from_raw_parts(raw_parameters_ptr, count);
228                    let parameters = raw_parameters
229                        .iter()
230                        .map(FunctionParameter::from_raw)
231                        .collect();
232                    BNFreeTypeParameterList(raw_parameters_ptr, count);
233                    Some(parameters)
234                }
235                true => None,
236            }
237        }
238    }
239
240    pub fn has_variable_arguments(&self) -> Conf<bool> {
241        unsafe { BNTypeBuilderHasVariableArguments(self.handle).into() }
242    }
243
244    pub fn can_return(&self) -> Conf<bool> {
245        unsafe { BNFunctionTypeBuilderCanReturn(self.handle).into() }
246    }
247
248    pub fn pure(&self) -> Conf<bool> {
249        unsafe { BNIsTypeBuilderPure(self.handle).into() }
250    }
251
252    // TODO: This naming is problematic... rename to `as_structure`?
253    // TODO: We wouldn't need these sort of functions if we destructured `Type`...
254    pub fn get_structure(&self) -> Option<Ref<Structure>> {
255        let raw_struct_ptr = unsafe { BNGetTypeBuilderStructure(self.handle) };
256        match raw_struct_ptr.is_null() {
257            false => Some(unsafe { Structure::ref_from_raw(raw_struct_ptr) }),
258            true => None,
259        }
260    }
261
262    // TODO: This naming is problematic... rename to `as_enumeration`?
263    // TODO: We wouldn't need these sort of functions if we destructured `Type`...
264    pub fn get_enumeration(&self) -> Option<Ref<Enumeration>> {
265        let raw_enum_ptr = unsafe { BNGetTypeBuilderEnumeration(self.handle) };
266        match raw_enum_ptr.is_null() {
267            false => Some(unsafe { Enumeration::ref_from_raw(raw_enum_ptr) }),
268            true => None,
269        }
270    }
271
272    // TODO: This naming is problematic... rename to `as_named_type_reference`?
273    // TODO: We wouldn't need these sort of functions if we destructured `Type`...
274    pub fn get_named_type_reference(&self) -> Option<Ref<NamedTypeReference>> {
275        let raw_type_ref_ptr = unsafe { BNGetTypeBuilderNamedTypeReference(self.handle) };
276        match raw_type_ref_ptr.is_null() {
277            false => Some(unsafe { NamedTypeReference::ref_from_raw(raw_type_ref_ptr) }),
278            true => None,
279        }
280    }
281
282    pub fn count(&self) -> u64 {
283        unsafe { BNGetTypeBuilderElementCount(self.handle) }
284    }
285
286    pub fn offset(&self) -> u64 {
287        unsafe { BNGetTypeBuilderOffset(self.handle) }
288    }
289
290    pub fn stack_adjustment(&self) -> Conf<i64> {
291        unsafe { BNGetTypeBuilderStackAdjustment(self.handle).into() }
292    }
293
294    pub fn pointer_base_type(&self) -> PointerBaseType {
295        unsafe { BNTypeBuilderGetPointerBaseType(self.handle) }
296    }
297
298    pub fn pointer_base_offset(&self) -> i64 {
299        unsafe { BNTypeBuilderGetPointerBaseOffset(self.handle) }
300    }
301
302    // TODO : This and properties
303    // pub fn tokens(&self) -> ? {}
304
305    /// Create a void [`TypeBuilder`]. Analogous to [`Type::void`].
306    pub fn void() -> Self {
307        unsafe { Self::from_raw(BNCreateVoidTypeBuilder()) }
308    }
309
310    /// Create a bool [`TypeBuilder`]. Analogous to [`Type::bool`].
311    pub fn bool() -> Self {
312        unsafe { Self::from_raw(BNCreateBoolTypeBuilder()) }
313    }
314
315    /// Create a signed one byte integer [`TypeBuilder`]. Analogous to [`Type::char`].
316    pub fn char() -> Self {
317        Self::int(1, true)
318    }
319
320    /// Create an integer [`TypeBuilder`] with the given width and signedness. Analogous to [`Type::int`].
321    pub fn int(width: usize, is_signed: bool) -> Self {
322        let mut is_signed = Conf::new(is_signed, MAX_CONFIDENCE).into();
323
324        unsafe {
325            Self::from_raw(BNCreateIntegerTypeBuilder(
326                width,
327                &mut is_signed,
328                c"".as_ptr() as _,
329            ))
330        }
331    }
332
333    /// Create an integer [`TypeBuilder`] with the given width and signedness and an alternative name.
334    /// Analogous to [`Type::named_int`].
335    pub fn named_int(width: usize, is_signed: bool, alt_name: &str) -> Self {
336        let mut is_signed = Conf::new(is_signed, MAX_CONFIDENCE).into();
337        let alt_name = alt_name.to_cstr();
338
339        unsafe {
340            Self::from_raw(BNCreateIntegerTypeBuilder(
341                width,
342                &mut is_signed,
343                alt_name.as_ref().as_ptr() as _,
344            ))
345        }
346    }
347
348    /// Create a float [`TypeBuilder`] with the given width. Analogous to [`Type::float`].
349    pub fn float(width: usize) -> Self {
350        unsafe { Self::from_raw(BNCreateFloatTypeBuilder(width, c"".as_ptr())) }
351    }
352
353    /// Create a float [`TypeBuilder`] with the given width and alternative name. Analogous to [`Type::named_float`].
354    pub fn named_float(width: usize, alt_name: &str) -> Self {
355        let alt_name = alt_name.to_cstr();
356        unsafe { Self::from_raw(BNCreateFloatTypeBuilder(width, alt_name.as_ptr())) }
357    }
358
359    /// Create an array [`TypeBuilder`] with the given element type and count. Analogous to [`Type::array`].
360    pub fn array<'a, T: Into<Conf<&'a Type>>>(ty: T, count: u64) -> Self {
361        let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
362        unsafe { Self::from_raw(BNCreateArrayTypeBuilder(&owned_raw_ty, count)) }
363    }
364
365    /// Create an enumeration [`TypeBuilder`] with the given width and signedness. Analogous to [`Type::enumeration`].
366    ///
367    /// ## NOTE
368    ///
369    /// The C/C++ APIs require an associated architecture, but in the core we only query the default_int_size if the given width is 0.
370    ///
371    /// For simplicity's sake, that convention isn't followed, and you can query [`Architecture::default_integer_size`] if you need to.
372    pub fn enumeration<T: Into<Conf<bool>>>(
373        enumeration: &Enumeration,
374        width: NonZeroUsize,
375        is_signed: T,
376    ) -> Self {
377        unsafe {
378            Self::from_raw(BNCreateEnumerationTypeBuilder(
379                // TODO: We pass nullptr arch, really we should not even be passing arch.
380                std::ptr::null_mut(),
381                enumeration.handle,
382                width.get(),
383                &mut is_signed.into().into(),
384            ))
385        }
386    }
387
388    /// Create a structure [`TypeBuilder`]. Analogous to [`Type::structure`].
389    pub fn structure(structure_type: &Structure) -> Self {
390        unsafe { Self::from_raw(BNCreateStructureTypeBuilder(structure_type.handle)) }
391    }
392
393    /// Create a named type reference [`TypeBuilder`]. Analogous to [`Type::named_type`].
394    pub fn named_type(type_reference: NamedTypeReference) -> Self {
395        let mut is_const = Conf::new(false, MIN_CONFIDENCE).into();
396        let mut is_volatile = Conf::new(false, MIN_CONFIDENCE).into();
397        unsafe {
398            Self::from_raw(BNCreateNamedTypeReferenceBuilder(
399                type_reference.handle,
400                0,
401                1,
402                &mut is_const,
403                &mut is_volatile,
404            ))
405        }
406    }
407
408    /// Create a named type reference [`TypeBuilder`] from a type and name. Analogous to [`Type::named_type_from_type`].
409    pub fn named_type_from_type<T: Into<QualifiedName>>(name: T, t: &Type) -> Self {
410        let mut raw_name = QualifiedName::into_raw(name.into());
411        let id = c"";
412
413        let result = unsafe {
414            Self::from_raw(BNCreateNamedTypeReferenceBuilderFromTypeAndId(
415                id.as_ptr() as *mut _,
416                &mut raw_name,
417                t.handle,
418            ))
419        };
420        QualifiedName::free_raw(raw_name);
421        result
422    }
423
424    // TODO : BNCreateFunctionTypeBuilder
425
426    /// Create a pointer [`TypeBuilder`] with the given target type. Analogous to [`Type::pointer`].
427    pub fn pointer<'a, A: Architecture, T: Into<Conf<&'a Type>>>(arch: &A, ty: T) -> Self {
428        Self::pointer_with_options(arch, ty, false, false, None)
429    }
430
431    /// Create a const pointer [`TypeBuilder`] with the given target type. Analogous to [`Type::const_pointer`].
432    pub fn const_pointer<'a, A: Architecture, T: Into<Conf<&'a Type>>>(arch: &A, ty: T) -> Self {
433        Self::pointer_with_options(arch, ty, true, false, None)
434    }
435
436    pub fn pointer_with_options<'a, A: Architecture, T: Into<Conf<&'a Type>>>(
437        arch: &A,
438        ty: T,
439        is_const: bool,
440        is_volatile: bool,
441        ref_type: Option<ReferenceType>,
442    ) -> Self {
443        let arch_ptr_size = arch.address_size();
444        Self::pointer_of_width(ty, arch_ptr_size, is_const, is_volatile, ref_type)
445    }
446
447    pub fn pointer_of_width<'a, T: Into<Conf<&'a Type>>>(
448        ty: T,
449        size: usize,
450        is_const: bool,
451        is_volatile: bool,
452        ref_type: Option<ReferenceType>,
453    ) -> Self {
454        let mut is_const = Conf::new(is_const, MAX_CONFIDENCE).into();
455        let mut is_volatile = Conf::new(is_volatile, MAX_CONFIDENCE).into();
456        let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
457        unsafe {
458            Self::from_raw(BNCreatePointerTypeBuilderOfWidth(
459                size,
460                &owned_raw_ty,
461                &mut is_const,
462                &mut is_volatile,
463                ref_type.unwrap_or(ReferenceType::PointerReferenceType),
464            ))
465        }
466    }
467}
468
469impl Display for TypeBuilder {
470    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
471        write!(f, "{}", unsafe {
472            BnString::into_string(BNGetTypeBuilderString(self.handle, std::ptr::null_mut()))
473        })
474    }
475}
476
477impl Drop for TypeBuilder {
478    fn drop(&mut self) {
479        unsafe { BNFreeTypeBuilder(self.handle) };
480    }
481}
482
483/// The core model for types in Binary Ninja.
484///
485/// A [`Type`] is how we model the storage of a [`Variable`] or [`crate::variable::DataVariable`] as
486/// well as propagate information such as the constness of a variable. Types are also used to declare
487/// function signatures, such as the [`FunctionParameter`]'s and return type.
488///
489/// Types are immutable. To change a type, you must create a new one either using [`TypeBuilder`] or
490/// one of the helper functions:
491///
492/// - [`Type::void`]
493/// - [`Type::bool`]
494/// - [`Type::char`]
495/// - [`Type::wide_char`]
496/// - [`Type::int`], [`Type::named_int`]
497/// - [`Type::float`], [`Type::named_float`]
498/// - [`Type::array`]
499/// - [`Type::enumeration`]
500/// - [`Type::structure`]
501/// - [`Type::named_type`], [`Type::named_type_from_type`]
502/// - [`Type::function`], [`Type::function_with_opts`]
503/// - [`Type::pointer`], [`Type::const_pointer`], [`Type::pointer_of_width`], [`Type::pointer_with_options`]
504///
505/// # Example
506///
507/// As an example, defining a _named_ type within a [`BinaryView`]:
508///
509/// ```no_run
510/// # use crate::binaryninja::binary_view::BinaryViewExt;
511/// # use binaryninja::types::Type;
512/// let bv = binaryninja::load("example.bin").unwrap();
513/// let my_custom_type_1 = Type::named_int(5, false, "my_w");
514/// let my_custom_type_2 = Type::int(5, false);
515/// bv.define_user_type("int_1", &my_custom_type_1);
516/// bv.define_user_type("int_2", &my_custom_type_2);
517/// ```
518#[repr(transparent)]
519pub struct Type {
520    pub handle: *mut BNType,
521}
522
523impl Type {
524    pub unsafe fn from_raw(handle: *mut BNType) -> Self {
525        debug_assert!(!handle.is_null());
526        Self { handle }
527    }
528
529    pub unsafe fn ref_from_raw(handle: *mut BNType) -> Ref<Self> {
530        debug_assert!(!handle.is_null());
531        Ref::new(Self { handle })
532    }
533
534    pub fn to_builder(&self) -> TypeBuilder {
535        TypeBuilder::new(self)
536    }
537
538    pub fn type_class(&self) -> TypeClass {
539        unsafe { BNGetTypeClass(self.handle) }
540    }
541
542    // TODO: We need to decide on a public type to represent type width.
543    // TODO: The api uses both `u64` and `usize`, pick one or a new type!
544    pub fn width(&self) -> u64 {
545        unsafe { BNGetTypeWidth(self.handle) }
546    }
547
548    pub fn alignment(&self) -> usize {
549        unsafe { BNGetTypeAlignment(self.handle) }
550    }
551
552    pub fn is_signed(&self) -> Conf<bool> {
553        unsafe { BNIsTypeSigned(self.handle).into() }
554    }
555
556    pub fn is_const(&self) -> Conf<bool> {
557        unsafe { BNIsTypeConst(self.handle).into() }
558    }
559
560    pub fn is_volatile(&self) -> Conf<bool> {
561        unsafe { BNIsTypeVolatile(self.handle).into() }
562    }
563
564    pub fn is_floating_point(&self) -> bool {
565        unsafe { BNIsTypeFloatingPoint(self.handle) }
566    }
567
568    pub fn child_type(&self) -> Option<Conf<Ref<Type>>> {
569        let raw_target = unsafe { BNGetChildType(self.handle) };
570        match raw_target.type_.is_null() {
571            false => Some(Conf::<Ref<Type>>::from_owned_raw(raw_target)),
572            true => None,
573        }
574    }
575
576    /// This is an alias for [`Self::child_type`].
577    pub fn target(&self) -> Option<Conf<Ref<Type>>> {
578        self.child_type()
579    }
580
581    /// This is an alias for [`Self::child_type`].
582    pub fn element_type(&self) -> Option<Conf<Ref<Type>>> {
583        self.child_type()
584    }
585
586    /// This is an alias for [`Self::child_type`].
587    pub fn return_value(&self) -> Option<Conf<Ref<Type>>> {
588        self.child_type()
589    }
590
591    pub fn calling_convention(&self) -> Option<Conf<Ref<CoreCallingConvention>>> {
592        let convention_confidence = unsafe { BNGetTypeCallingConvention(self.handle) };
593        match convention_confidence.convention.is_null() {
594            false => Some(Conf::<Ref<CoreCallingConvention>>::from_owned_raw(
595                convention_confidence,
596            )),
597            true => None,
598        }
599    }
600
601    pub fn parameters(&self) -> Option<Vec<FunctionParameter>> {
602        unsafe {
603            let mut count = 0;
604            let raw_parameters_ptr = BNGetTypeParameters(self.handle, &mut count);
605            match raw_parameters_ptr.is_null() {
606                false => {
607                    let raw_parameters = std::slice::from_raw_parts(raw_parameters_ptr, count);
608                    let parameters = raw_parameters
609                        .iter()
610                        .map(FunctionParameter::from_raw)
611                        .collect();
612                    BNFreeTypeParameterList(raw_parameters_ptr, count);
613                    Some(parameters)
614                }
615                true => None,
616            }
617        }
618    }
619
620    pub fn has_variable_arguments(&self) -> Conf<bool> {
621        unsafe { BNTypeHasVariableArguments(self.handle).into() }
622    }
623
624    pub fn can_return(&self) -> Conf<bool> {
625        unsafe { BNFunctionTypeCanReturn(self.handle).into() }
626    }
627
628    pub fn pure(&self) -> Conf<bool> {
629        unsafe { BNIsTypePure(self.handle).into() }
630    }
631
632    // TODO: This naming is problematic... rename to `as_structure`?
633    // TODO: We wouldn't need these sort of functions if we destructured `Type`...
634    pub fn get_structure(&self) -> Option<Ref<Structure>> {
635        let raw_struct_ptr = unsafe { BNGetTypeStructure(self.handle) };
636        match raw_struct_ptr.is_null() {
637            false => Some(unsafe { Structure::ref_from_raw(raw_struct_ptr) }),
638            true => None,
639        }
640    }
641
642    // TODO: This naming is problematic... rename to `as_enumeration`?
643    // TODO: We wouldn't need these sort of functions if we destructured `Type`...
644    pub fn get_enumeration(&self) -> Option<Ref<Enumeration>> {
645        let raw_enum_ptr = unsafe { BNGetTypeEnumeration(self.handle) };
646        match raw_enum_ptr.is_null() {
647            false => Some(unsafe { Enumeration::ref_from_raw(raw_enum_ptr) }),
648            true => None,
649        }
650    }
651
652    // TODO: This naming is problematic... rename to `as_named_type_reference`?
653    // TODO: We wouldn't need these sort of functions if we destructured `Type`...
654    pub fn get_named_type_reference(&self) -> Option<Ref<NamedTypeReference>> {
655        let raw_type_ref_ptr = unsafe { BNGetTypeNamedTypeReference(self.handle) };
656        match raw_type_ref_ptr.is_null() {
657            false => Some(unsafe { NamedTypeReference::ref_from_raw(raw_type_ref_ptr) }),
658            true => None,
659        }
660    }
661
662    pub fn count(&self) -> u64 {
663        unsafe { BNGetTypeElementCount(self.handle) }
664    }
665
666    pub fn offset(&self) -> u64 {
667        unsafe { BNGetTypeOffset(self.handle) }
668    }
669
670    pub fn stack_adjustment(&self) -> Conf<i64> {
671        unsafe { BNGetTypeStackAdjustment(self.handle).into() }
672    }
673
674    pub fn registered_name(&self) -> Option<Ref<NamedTypeReference>> {
675        let raw_type_ref_ptr = unsafe { BNGetRegisteredTypeName(self.handle) };
676        match raw_type_ref_ptr.is_null() {
677            false => Some(unsafe { NamedTypeReference::ref_from_raw(raw_type_ref_ptr) }),
678            true => None,
679        }
680    }
681
682    pub fn pointer_base_type(&self) -> BNPointerBaseType {
683        unsafe { BNTypeGetPointerBaseType(self.handle) }
684    }
685
686    pub fn pointer_base_offset(&self) -> i64 {
687        unsafe { BNTypeGetPointerBaseOffset(self.handle) }
688    }
689
690    // TODO : This and properties
691    // pub fn tokens(&self) -> ? {}
692
693    pub fn void() -> Ref<Self> {
694        unsafe { Self::ref_from_raw(BNCreateVoidType()) }
695    }
696
697    pub fn bool() -> Ref<Self> {
698        unsafe { Self::ref_from_raw(BNCreateBoolType()) }
699    }
700
701    pub fn char() -> Ref<Self> {
702        Self::int(1, true)
703    }
704
705    pub fn wide_char(width: usize) -> Ref<Self> {
706        unsafe { Self::ref_from_raw(BNCreateWideCharType(width, c"".as_ptr())) }
707    }
708
709    pub fn int(width: usize, is_signed: bool) -> Ref<Self> {
710        let mut is_signed = Conf::new(is_signed, MAX_CONFIDENCE).into();
711        unsafe { Self::ref_from_raw(BNCreateIntegerType(width, &mut is_signed, c"".as_ptr())) }
712    }
713
714    pub fn named_int(width: usize, is_signed: bool, alt_name: &str) -> Ref<Self> {
715        let mut is_signed = Conf::new(is_signed, MAX_CONFIDENCE).into();
716        let alt_name = alt_name.to_cstr();
717
718        unsafe {
719            Self::ref_from_raw(BNCreateIntegerType(
720                width,
721                &mut is_signed,
722                alt_name.as_ptr(),
723            ))
724        }
725    }
726
727    pub fn float(width: usize) -> Ref<Self> {
728        unsafe { Self::ref_from_raw(BNCreateFloatType(width, c"".as_ptr())) }
729    }
730
731    pub fn named_float(width: usize, alt_name: &str) -> Ref<Self> {
732        let alt_name = alt_name.to_cstr();
733        unsafe { Self::ref_from_raw(BNCreateFloatType(width, alt_name.as_ptr())) }
734    }
735
736    pub fn array<'a, T: Into<Conf<&'a Type>>>(ty: T, count: u64) -> Ref<Self> {
737        let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
738        unsafe { Self::ref_from_raw(BNCreateArrayType(&owned_raw_ty, count)) }
739    }
740
741    /// ## NOTE
742    ///
743    /// The C/C++ APIs require an associated architecture, but in the core we only query the default_int_size if the given width is 0.
744    ///
745    /// For simplicity's sake, that convention isn't followed, and you can query [`Architecture::default_integer_size`] if you need to.
746    pub fn enumeration<T: Into<Conf<bool>>>(
747        enumeration: &Enumeration,
748        width: NonZeroUsize,
749        is_signed: T,
750    ) -> Ref<Self> {
751        unsafe {
752            Self::ref_from_raw(BNCreateEnumerationType(
753                // TODO: We pass nullptr arch, really we should not even be passing arch.
754                std::ptr::null_mut(),
755                enumeration.handle,
756                width.get(),
757                &mut is_signed.into().into(),
758            ))
759        }
760    }
761
762    pub fn structure(structure: &Structure) -> Ref<Self> {
763        unsafe { Self::ref_from_raw(BNCreateStructureType(structure.handle)) }
764    }
765
766    pub fn named_type(type_reference: &NamedTypeReference) -> Ref<Self> {
767        let mut is_const = Conf::new(false, MIN_CONFIDENCE).into();
768        let mut is_volatile = Conf::new(false, MIN_CONFIDENCE).into();
769        unsafe {
770            Self::ref_from_raw(BNCreateNamedTypeReference(
771                type_reference.handle,
772                0,
773                1,
774                &mut is_const,
775                &mut is_volatile,
776            ))
777        }
778    }
779
780    pub fn named_type_from_type<T: Into<QualifiedName>>(name: T, t: &Type) -> Ref<Self> {
781        let mut raw_name = QualifiedName::into_raw(name.into());
782        // TODO: No id is present for this call?
783        let id = c"";
784
785        let result = unsafe {
786            Self::ref_from_raw(BNCreateNamedTypeReferenceFromTypeAndId(
787                id.as_ptr(),
788                &mut raw_name,
789                t.handle,
790            ))
791        };
792        QualifiedName::free_raw(raw_name);
793        result
794    }
795
796    // TODO: FunctionBuilder
797    pub fn function<'a, T: Into<Conf<&'a Type>>>(
798        return_type: T,
799        parameters: Vec<FunctionParameter>,
800        variable_arguments: bool,
801    ) -> Ref<Self> {
802        let mut owned_raw_return_type = Conf::<&Type>::into_raw(return_type.into());
803        let mut variable_arguments = Conf::new(variable_arguments, MAX_CONFIDENCE).into();
804        let mut can_return = Conf::new(true, MIN_CONFIDENCE).into();
805        let mut pure = Conf::new(false, MIN_CONFIDENCE).into();
806
807        let mut raw_calling_convention: BNCallingConventionWithConfidence =
808            BNCallingConventionWithConfidence {
809                convention: std::ptr::null_mut(),
810                confidence: MIN_CONFIDENCE,
811            };
812
813        let mut stack_adjust = Conf::new(0, MIN_CONFIDENCE).into();
814        let mut raw_parameters = parameters
815            .into_iter()
816            .map(FunctionParameter::into_raw)
817            .collect::<Vec<_>>();
818        let reg_stack_adjust_regs = std::ptr::null_mut();
819        let reg_stack_adjust_values = std::ptr::null_mut();
820
821        let mut return_regs: BNRegisterSetWithConfidence = BNRegisterSetWithConfidence {
822            regs: std::ptr::null_mut(),
823            count: 0,
824            confidence: 0,
825        };
826
827        let result = unsafe {
828            Self::ref_from_raw(BNCreateFunctionType(
829                &mut owned_raw_return_type,
830                &mut raw_calling_convention,
831                raw_parameters.as_mut_ptr(),
832                raw_parameters.len(),
833                &mut variable_arguments,
834                &mut can_return,
835                &mut stack_adjust,
836                reg_stack_adjust_regs,
837                reg_stack_adjust_values,
838                0,
839                &mut return_regs,
840                BNNameType::NoNameType,
841                &mut pure,
842            ))
843        };
844
845        for raw_param in raw_parameters {
846            FunctionParameter::free_raw(raw_param);
847        }
848
849        result
850    }
851
852    // TODO: FunctionBuilder
853    pub fn function_with_opts<
854        'a,
855        T: Into<Conf<&'a Type>>,
856        C: Into<Conf<Ref<CoreCallingConvention>>>,
857    >(
858        return_type: T,
859        parameters: &[FunctionParameter],
860        variable_arguments: bool,
861        calling_convention: C,
862        stack_adjust: Conf<i64>,
863    ) -> Ref<Self> {
864        let mut owned_raw_return_type = Conf::<&Type>::into_raw(return_type.into());
865        let mut variable_arguments = Conf::new(variable_arguments, MAX_CONFIDENCE).into();
866        let mut can_return = Conf::new(true, MIN_CONFIDENCE).into();
867        let mut pure = Conf::new(false, MIN_CONFIDENCE).into();
868
869        let mut owned_raw_calling_convention =
870            Conf::<Ref<CoreCallingConvention>>::into_owned_raw(&calling_convention.into());
871
872        let mut stack_adjust = stack_adjust.into();
873        let mut raw_parameters = parameters
874            .iter()
875            .cloned()
876            .map(FunctionParameter::into_raw)
877            .collect::<Vec<_>>();
878
879        // TODO: Update type signature and include these (will be a breaking change)
880        let reg_stack_adjust_regs = std::ptr::null_mut();
881        let reg_stack_adjust_values = std::ptr::null_mut();
882
883        let mut return_regs: BNRegisterSetWithConfidence = BNRegisterSetWithConfidence {
884            regs: std::ptr::null_mut(),
885            count: 0,
886            confidence: 0,
887        };
888
889        let result = unsafe {
890            Self::ref_from_raw(BNCreateFunctionType(
891                &mut owned_raw_return_type,
892                &mut owned_raw_calling_convention,
893                raw_parameters.as_mut_ptr(),
894                raw_parameters.len(),
895                &mut variable_arguments,
896                &mut can_return,
897                &mut stack_adjust,
898                reg_stack_adjust_regs,
899                reg_stack_adjust_values,
900                0,
901                &mut return_regs,
902                BNNameType::NoNameType,
903                &mut pure,
904            ))
905        };
906
907        for raw_param in raw_parameters {
908            FunctionParameter::free_raw(raw_param);
909        }
910
911        result
912    }
913
914    pub fn pointer<'a, A: Architecture, T: Into<Conf<&'a Type>>>(arch: &A, ty: T) -> Ref<Self> {
915        Self::pointer_with_options(arch, ty, false, false, None)
916    }
917
918    pub fn const_pointer<'a, A: Architecture, T: Into<Conf<&'a Type>>>(
919        arch: &A,
920        ty: T,
921    ) -> Ref<Self> {
922        Self::pointer_with_options(arch, ty, true, false, None)
923    }
924
925    pub fn pointer_with_options<'a, A: Architecture, T: Into<Conf<&'a Type>>>(
926        arch: &A,
927        ty: T,
928        is_const: bool,
929        is_volatile: bool,
930        ref_type: Option<ReferenceType>,
931    ) -> Ref<Self> {
932        let arch_pointer_size = arch.address_size();
933        Self::pointer_of_width(ty, arch_pointer_size, is_const, is_volatile, ref_type)
934    }
935
936    pub fn pointer_of_width<'a, T: Into<Conf<&'a Type>>>(
937        ty: T,
938        size: usize,
939        is_const: bool,
940        is_volatile: bool,
941        ref_type: Option<ReferenceType>,
942    ) -> Ref<Self> {
943        let mut is_const = Conf::new(is_const, MAX_CONFIDENCE).into();
944        let mut is_volatile = Conf::new(is_volatile, MAX_CONFIDENCE).into();
945        let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
946        unsafe {
947            Self::ref_from_raw(BNCreatePointerTypeOfWidth(
948                size,
949                &owned_raw_ty,
950                &mut is_const,
951                &mut is_volatile,
952                ref_type.unwrap_or(ReferenceType::PointerReferenceType),
953            ))
954        }
955    }
956
957    pub fn generate_auto_demangled_type_id<T: Into<QualifiedName>>(name: T) -> String {
958        let mut raw_name = QualifiedName::into_raw(name.into());
959        let type_id =
960            unsafe { BnString::into_string(BNGenerateAutoDemangledTypeId(&mut raw_name)) };
961        QualifiedName::free_raw(raw_name);
962        type_id
963    }
964}
965
966impl Display for Type {
967    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
968        write!(f, "{}", unsafe {
969            BnString::into_string(BNGetTypeString(
970                self.handle,
971                std::ptr::null_mut(),
972                BNTokenEscapingType::NoTokenEscapingType,
973            ))
974        })
975    }
976}
977
978impl Debug for Type {
979    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
980        // You might be tempted to rip this atrocity out and make this more "sensible". READ BELOW!
981        // Type is a one-size fits all structure, these are actually its fields! If we wanted to
982        // omit some fields for different type classes, what you really want to do is implement your
983        // own formatter. This is supposed to represent the structure entirely, it's not supposed to be pretty!
984        f.debug_struct("Type")
985            .field("type_class", &self.type_class())
986            .field("width", &self.width())
987            .field("alignment", &self.alignment())
988            .field("is_signed", &self.is_signed())
989            .field("is_const", &self.is_const())
990            .field("is_volatile", &self.is_volatile())
991            .field("child_type", &self.child_type())
992            .field("calling_convention", &self.calling_convention())
993            .field("parameters", &self.parameters())
994            .field("has_variable_arguments", &self.has_variable_arguments())
995            .field("can_return", &self.can_return())
996            .field("pure", &self.pure())
997            .field("get_structure", &self.get_structure())
998            .field("get_enumeration", &self.get_enumeration())
999            .field("get_named_type_reference", &self.get_named_type_reference())
1000            .field("count", &self.count())
1001            .field("offset", &self.offset())
1002            .field("stack_adjustment", &self.stack_adjustment())
1003            .field("registered_name", &self.registered_name())
1004            .finish()
1005    }
1006}
1007
1008impl PartialEq for Type {
1009    fn eq(&self, other: &Self) -> bool {
1010        unsafe { BNTypesEqual(self.handle, other.handle) }
1011    }
1012}
1013
1014impl Eq for Type {}
1015
1016impl Hash for Type {
1017    fn hash<H: Hasher>(&self, state: &mut H) {
1018        self.handle.hash(state);
1019    }
1020}
1021
1022unsafe impl Send for Type {}
1023unsafe impl Sync for Type {}
1024
1025unsafe impl RefCountable for Type {
1026    unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
1027        Self::ref_from_raw(BNNewTypeReference(handle.handle))
1028    }
1029
1030    unsafe fn dec_ref(handle: &Self) {
1031        BNFreeType(handle.handle);
1032    }
1033}
1034
1035impl ToOwned for Type {
1036    type Owned = Ref<Self>;
1037
1038    fn to_owned(&self) -> Self::Owned {
1039        unsafe { RefCountable::inc_ref(self) }
1040    }
1041}
1042
1043impl CoreArrayProvider for Type {
1044    type Raw = *mut BNType;
1045    type Context = ();
1046    type Wrapped<'a> = &'a Self;
1047}
1048
1049unsafe impl CoreArrayProviderInner for Type {
1050    unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
1051        BNFreeTypeList(raw, count)
1052    }
1053
1054    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
1055        // TODO: This is assuming &'a Type is &*mut BNType
1056        std::mem::transmute(raw)
1057    }
1058}
1059
1060#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1061pub struct FunctionParameter {
1062    pub ty: Conf<Ref<Type>>,
1063    pub name: String,
1064    pub location: Option<Variable>,
1065}
1066
1067impl FunctionParameter {
1068    pub(crate) fn from_raw(value: &BNFunctionParameter) -> Self {
1069        // TODO: I copied this from the original `from_raw` function.
1070        // TODO: So this actually needs to be audited later.
1071        let name = if value.name.is_null() {
1072            if value.location.type_ == VariableSourceType::RegisterVariableSourceType {
1073                format!("reg_{}", value.location.storage)
1074            } else if value.location.type_ == VariableSourceType::StackVariableSourceType {
1075                format!("arg_{}", value.location.storage)
1076            } else {
1077                String::new()
1078            }
1079        } else {
1080            raw_to_string(value.name as *const _).unwrap()
1081        };
1082
1083        Self {
1084            ty: Conf::new(
1085                unsafe { Type::from_raw(value.type_).to_owned() },
1086                value.typeConfidence,
1087            ),
1088            name,
1089            location: match value.defaultLocation {
1090                false => Some(Variable::from(value.location)),
1091                true => None,
1092            },
1093        }
1094    }
1095
1096    #[allow(unused)]
1097    pub(crate) fn from_owned_raw(value: BNFunctionParameter) -> Self {
1098        let owned = Self::from_raw(&value);
1099        Self::free_raw(value);
1100        owned
1101    }
1102
1103    pub(crate) fn into_raw(value: Self) -> BNFunctionParameter {
1104        let bn_name = BnString::new(value.name);
1105        BNFunctionParameter {
1106            name: BnString::into_raw(bn_name),
1107            type_: unsafe { Ref::into_raw(value.ty.contents) }.handle,
1108            typeConfidence: value.ty.confidence,
1109            defaultLocation: value.location.is_none(),
1110            location: value.location.map(Into::into).unwrap_or_default(),
1111        }
1112    }
1113
1114    pub(crate) fn free_raw(value: BNFunctionParameter) {
1115        unsafe { BnString::free_raw(value.name) };
1116        let _ = unsafe { Type::ref_from_raw(value.type_) };
1117    }
1118
1119    pub fn new<T: Into<Conf<Ref<Type>>>>(ty: T, name: String, location: Option<Variable>) -> Self {
1120        Self {
1121            ty: ty.into(),
1122            name,
1123            location,
1124        }
1125    }
1126}
1127
1128#[derive(PartialEq, Eq, Hash)]
1129pub struct NamedTypeReference {
1130    pub(crate) handle: *mut BNNamedTypeReference,
1131}
1132
1133impl NamedTypeReference {
1134    pub(crate) unsafe fn from_raw(handle: *mut BNNamedTypeReference) -> Self {
1135        debug_assert!(!handle.is_null());
1136        Self { handle }
1137    }
1138
1139    pub(crate) unsafe fn ref_from_raw(handle: *mut BNNamedTypeReference) -> Ref<Self> {
1140        debug_assert!(!handle.is_null());
1141        Ref::new(Self { handle })
1142    }
1143
1144    /// Create an NTR to a type that did not come directly from a BinaryView's types list.
1145    /// That is to say, if you're referencing a new type you're GOING to add, use this.
1146    /// You should not assign type ids yourself, that is the responsibility of the BinaryView
1147    /// implementation after your types have been added. Just make sure the names match up and
1148    /// the core will do the id stuff for you.
1149    pub fn new<T: Into<QualifiedName>>(type_class: NamedTypeReferenceClass, name: T) -> Ref<Self> {
1150        let mut raw_name = QualifiedName::into_raw(name.into());
1151        let result = unsafe {
1152            Self::ref_from_raw(BNCreateNamedType(
1153                type_class,
1154                std::ptr::null(),
1155                &mut raw_name,
1156            ))
1157        };
1158        QualifiedName::free_raw(raw_name);
1159        result
1160    }
1161
1162    /// Create an NTR to a type with an existing type id, which generally means it came directly
1163    /// from a BinaryView's types list and its id was looked up using `BinaryView::get_type_id`.
1164    /// You should not assign type ids yourself: if you use this to reference a type you are going
1165    /// to create but have not yet created, you may run into problems when giving your types to
1166    /// a BinaryView.
1167    pub fn new_with_id<T: Into<QualifiedName>>(
1168        type_class: NamedTypeReferenceClass,
1169        type_id: &str,
1170        name: T,
1171    ) -> Ref<Self> {
1172        let type_id = type_id.to_cstr();
1173        let mut raw_name = QualifiedName::into_raw(name.into());
1174        let result = unsafe {
1175            Self::ref_from_raw(BNCreateNamedType(
1176                type_class,
1177                type_id.as_ref().as_ptr() as _,
1178                &mut raw_name,
1179            ))
1180        };
1181        QualifiedName::free_raw(raw_name);
1182        result
1183    }
1184
1185    pub fn name(&self) -> QualifiedName {
1186        let raw_name = unsafe { BNGetTypeReferenceName(self.handle) };
1187        QualifiedName::from_owned_raw(raw_name)
1188    }
1189
1190    pub fn id(&self) -> String {
1191        unsafe { BnString::into_string(BNGetTypeReferenceId(self.handle)) }
1192    }
1193
1194    pub fn class(&self) -> NamedTypeReferenceClass {
1195        unsafe { BNGetTypeReferenceClass(self.handle) }
1196    }
1197
1198    fn target_helper(&self, bv: &BinaryView, visited: &mut HashSet<String>) -> Option<Ref<Type>> {
1199        let ty = bv.type_by_id(&self.id())?;
1200        match ty.type_class() {
1201            TypeClass::NamedTypeReferenceClass => {
1202                // Recurse into the NTR type until we get the target type.
1203                let ntr = ty
1204                    .get_named_type_reference()
1205                    .expect("NTR type class should always have a valid NTR");
1206                match visited.insert(ntr.id()) {
1207                    true => ntr.target_helper(bv, visited),
1208                    // Cyclic reference, return None.
1209                    false => None,
1210                }
1211            }
1212            // Found target type
1213            _ => Some(ty),
1214        }
1215    }
1216
1217    /// Type referenced by this [`NamedTypeReference`].
1218    ///
1219    /// Will return `None` if the reference is cyclic, or the target type does not exist.
1220    pub fn target(&self, bv: &BinaryView) -> Option<Ref<Type>> {
1221        self.target_helper(bv, &mut HashSet::new())
1222    }
1223}
1224
1225impl ToOwned for NamedTypeReference {
1226    type Owned = Ref<Self>;
1227
1228    fn to_owned(&self) -> Self::Owned {
1229        unsafe { RefCountable::inc_ref(self) }
1230    }
1231}
1232
1233unsafe impl RefCountable for NamedTypeReference {
1234    unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
1235        Self::ref_from_raw(BNNewNamedTypeReference(handle.handle))
1236    }
1237
1238    unsafe fn dec_ref(handle: &Self) {
1239        BNFreeNamedTypeReference(handle.handle)
1240    }
1241}
1242
1243impl Debug for NamedTypeReference {
1244    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1245        write!(f, "{} (id: {})", self.name(), self.id())
1246    }
1247}
1248
1249#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1250pub struct QualifiedNameAndType {
1251    pub name: QualifiedName,
1252    pub ty: Ref<Type>,
1253}
1254
1255impl QualifiedNameAndType {
1256    pub(crate) fn from_raw(value: &BNQualifiedNameAndType) -> Self {
1257        Self {
1258            name: QualifiedName::from_raw(&value.name),
1259            ty: unsafe { Type::from_raw(value.type_).to_owned() },
1260        }
1261    }
1262
1263    pub(crate) fn from_owned_raw(value: BNQualifiedNameAndType) -> Self {
1264        let owned = Self::from_raw(&value);
1265        Self::free_raw(value);
1266        owned
1267    }
1268
1269    pub(crate) fn into_raw(value: Self) -> BNQualifiedNameAndType {
1270        BNQualifiedNameAndType {
1271            name: QualifiedName::into_raw(value.name),
1272            type_: unsafe { Ref::into_raw(value.ty).handle },
1273        }
1274    }
1275
1276    pub(crate) fn free_raw(value: BNQualifiedNameAndType) {
1277        QualifiedName::free_raw(value.name);
1278        let _ = unsafe { Type::ref_from_raw(value.type_) };
1279    }
1280
1281    pub fn new(name: QualifiedName, ty: Ref<Type>) -> Self {
1282        Self { name, ty }
1283    }
1284}
1285
1286impl<T> From<(T, Ref<Type>)> for QualifiedNameAndType
1287where
1288    T: Into<QualifiedName>,
1289{
1290    fn from(value: (T, Ref<Type>)) -> Self {
1291        Self {
1292            name: value.0.into(),
1293            ty: value.1,
1294        }
1295    }
1296}
1297
1298impl<T> From<(T, &Type)> for QualifiedNameAndType
1299where
1300    T: Into<QualifiedName>,
1301{
1302    fn from(value: (T, &Type)) -> Self {
1303        let ty = value.1.to_owned();
1304        Self {
1305            name: value.0.into(),
1306            ty,
1307        }
1308    }
1309}
1310
1311impl CoreArrayProvider for QualifiedNameAndType {
1312    type Raw = BNQualifiedNameAndType;
1313    type Context = ();
1314    type Wrapped<'a> = Self;
1315}
1316
1317unsafe impl CoreArrayProviderInner for QualifiedNameAndType {
1318    unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
1319        BNFreeTypeAndNameList(raw, count);
1320    }
1321
1322    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
1323        QualifiedNameAndType::from_raw(raw)
1324    }
1325}
1326
1327#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1328pub struct QualifiedNameTypeAndId {
1329    pub name: QualifiedName,
1330    pub ty: Ref<Type>,
1331    pub id: String,
1332}
1333
1334impl QualifiedNameTypeAndId {
1335    pub(crate) fn from_raw(value: &BNQualifiedNameTypeAndId) -> Self {
1336        Self {
1337            name: QualifiedName::from_raw(&value.name),
1338            ty: unsafe { Type::from_raw(value.type_) }.to_owned(),
1339            id: raw_to_string(value.id).unwrap(),
1340        }
1341    }
1342
1343    #[allow(unused)]
1344    pub(crate) fn from_owned_raw(value: BNQualifiedNameTypeAndId) -> Self {
1345        let owned = Self::from_raw(&value);
1346        Self::free_raw(value);
1347        owned
1348    }
1349
1350    pub(crate) fn into_raw(value: Self) -> BNQualifiedNameTypeAndId {
1351        let bn_id = BnString::new(value.id);
1352        BNQualifiedNameTypeAndId {
1353            name: QualifiedName::into_raw(value.name),
1354            id: BnString::into_raw(bn_id),
1355            type_: unsafe { Ref::into_raw(value.ty) }.handle,
1356        }
1357    }
1358
1359    pub(crate) fn free_raw(value: BNQualifiedNameTypeAndId) {
1360        QualifiedName::free_raw(value.name);
1361        let _ = unsafe { Type::ref_from_raw(value.type_) };
1362        let _ = unsafe { BnString::from_raw(value.id) };
1363    }
1364}
1365
1366impl CoreArrayProvider for QualifiedNameTypeAndId {
1367    type Raw = BNQualifiedNameTypeAndId;
1368    type Context = ();
1369    type Wrapped<'a> = QualifiedNameTypeAndId;
1370}
1371
1372unsafe impl CoreArrayProviderInner for QualifiedNameTypeAndId {
1373    unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
1374        BNFreeTypeIdList(raw, count);
1375    }
1376
1377    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
1378        QualifiedNameTypeAndId::from_raw(raw)
1379    }
1380}
1381
1382// TODO: Document how this type is used for many different purposes. (this is literally (string, type))
1383// TODO: Ex. the name might be the parser it came from
1384// TODO: Ex. the name might be the param name for an intrinsic input
1385// TODO: Should we make new types for each varying use case?
1386#[derive(Debug, Clone, Eq, PartialEq, Hash)]
1387pub struct NameAndType {
1388    pub name: String,
1389    pub ty: Conf<Ref<Type>>,
1390}
1391
1392impl NameAndType {
1393    pub(crate) fn from_raw(value: &BNNameAndType) -> Self {
1394        Self {
1395            // TODO: I dislike using this function here.
1396            name: raw_to_string(value.name as *mut _).unwrap(),
1397            ty: Conf::new(
1398                unsafe { Type::from_raw(value.type_).to_owned() },
1399                value.typeConfidence,
1400            ),
1401        }
1402    }
1403
1404    #[allow(unused)]
1405    pub(crate) fn from_owned_raw(value: BNNameAndType) -> Self {
1406        let owned = Self::from_raw(&value);
1407        Self::free_raw(value);
1408        owned
1409    }
1410
1411    pub(crate) fn into_raw(value: Self) -> BNNameAndType {
1412        let bn_name = BnString::new(value.name);
1413        BNNameAndType {
1414            name: BnString::into_raw(bn_name),
1415            type_: unsafe { Ref::into_raw(value.ty.contents) }.handle,
1416            typeConfidence: value.ty.confidence,
1417        }
1418    }
1419
1420    pub(crate) fn free_raw(value: BNNameAndType) {
1421        unsafe { BnString::free_raw(value.name) };
1422        let _ = unsafe { Type::ref_from_raw(value.type_) };
1423    }
1424
1425    pub fn new(name: impl Into<String>, ty: Conf<Ref<Type>>) -> Self {
1426        Self {
1427            name: name.into(),
1428            ty,
1429        }
1430    }
1431}
1432
1433impl CoreArrayProvider for NameAndType {
1434    type Raw = BNNameAndType;
1435    type Context = ();
1436    type Wrapped<'a> = Self;
1437}
1438
1439unsafe impl CoreArrayProviderInner for NameAndType {
1440    unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
1441        BNFreeNameAndTypeList(raw, count);
1442    }
1443
1444    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
1445        NameAndType::from_raw(raw)
1446    }
1447}