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