Skip to main content

jlrs/data/managed/
type_name.rs

1//! Managed type for `TypeName`.
2//!
3//! The documentation for this module has been slightly adapted from the comments for this struct
4//! in [`julia.h`]
5//!
6//! [`julia.h`]: https://github.com/JuliaLang/julia/blob/96786e22ccabfdafd073122abb1fb69cea921e17/src/julia.h#L380
7
8use std::{marker::PhantomData, ptr::NonNull};
9
10use jl_sys::{
11    jl_array_typename, jl_llvmpointer_typename, jl_namedtuple_typename, jl_pointer_typename,
12    jl_tuple_typename, jl_type_typename, jl_typename_t, jl_typename_type, jl_vecelement_typename,
13};
14use jlrs_macros::julia_version;
15use jlrs_sys::{
16    jlrs_typename_abstract, jlrs_typename_atomicfields, jlrs_typename_constfields,
17    jlrs_typename_mayinlinealloc, jlrs_typename_module, jlrs_typename_mutable, jlrs_typename_name,
18    jlrs_typename_names, jlrs_typename_wrapper,
19};
20
21use super::{Weak, simple_vector::SimpleVector, value::Value};
22use crate::{
23    data::managed::{module::Module, private::ManagedPriv, symbol::Symbol},
24    impl_julia_typecheck,
25    memory::target::{Target, TargetResult},
26    private::Private,
27};
28
29/// Describes the syntactic structure of a type and stores all data common to different
30/// instantiations of the type.
31#[derive(Copy, Clone, PartialEq)]
32#[repr(transparent)]
33pub struct TypeName<'scope>(NonNull<jl_typename_t>, PhantomData<&'scope ()>);
34
35impl<'scope> TypeName<'scope> {
36    /// The `name` field.
37    #[inline]
38    pub fn name(self) -> Symbol<'scope> {
39        // Safety: the pointer points to valid data
40        unsafe {
41            let name = jlrs_typename_name(self.unwrap(Private));
42            Symbol::wrap_non_null(NonNull::new_unchecked(name), Private)
43        }
44    }
45
46    /// The `name` field.
47    #[inline]
48    pub fn names(self) -> SimpleVector<'scope> {
49        // Safety: the pointer points to valid data
50        unsafe {
51            let names = jlrs_typename_names(self.unwrap(Private));
52            SimpleVector::wrap_non_null(NonNull::new_unchecked(names), Private)
53        }
54    }
55
56    /// The `module` field.
57    #[inline]
58    pub fn module(self) -> Module<'scope> {
59        // Safety: the pointer points to valid data
60        unsafe {
61            let module = jlrs_typename_module(self.unwrap(Private));
62            Module::wrap_non_null(NonNull::new_unchecked(module), Private)
63        }
64    }
65
66    /// The `module` field.
67    #[inline]
68    pub fn wrapper(self) -> Value<'scope, 'static> {
69        // Safety: the pointer points to valid data
70        unsafe {
71            let module = jlrs_typename_wrapper(self.unwrap(Private));
72            Value::wrap_non_null(NonNull::new_unchecked(module), Private)
73        }
74    }
75
76    /// The `atomicfields` field.
77    #[inline]
78    pub fn atomicfields(self) -> *const u32 {
79        // Safety: the pointer points to valid data
80        unsafe { jlrs_typename_atomicfields(self.unwrap(Private)) }
81    }
82
83    /// The `atomicfields` field.
84    #[inline]
85    pub fn constfields(self) -> *const u32 {
86        // Safety: the pointer points to valid data
87        unsafe { jlrs_typename_constfields(self.unwrap(Private)) }
88    }
89
90    /// The `abstract` field.
91    #[inline]
92    pub fn is_abstract(self) -> bool {
93        // Safety: the pointer points to valid data
94        unsafe { jlrs_typename_abstract(self.unwrap(Private)) != 0 }
95    }
96
97    /// The `mutabl` field.
98    #[inline]
99    pub fn is_mutable(self) -> bool {
100        // Safety: the pointer points to valid data
101        unsafe { jlrs_typename_mutable(self.unwrap(Private)) != 0 }
102    }
103
104    /// The `mayinlinealloc` field.
105    #[inline]
106    pub fn mayinlinealloc(self) -> bool {
107        // Safety: the pointer points to valid data
108        unsafe { jlrs_typename_mayinlinealloc(self.unwrap(Private)) != 0 }
109    }
110}
111
112impl<'base> TypeName<'base> {
113    /// The typename of the `UnionAll` `Type`.
114    #[inline]
115    pub fn of_type<Tgt>(_: &Tgt) -> Self
116    where
117        Tgt: Target<'base>,
118    {
119        // Safety: global constant
120        unsafe { Self::wrap_non_null(NonNull::new_unchecked(jl_type_typename), Private) }
121    }
122
123    /// The typename of the `DataType` `Tuple`.
124    #[inline]
125    pub fn of_tuple<Tgt>(_: &Tgt) -> Self
126    where
127        Tgt: Target<'base>,
128    {
129        // Safety: global constant
130        unsafe { Self::wrap_non_null(NonNull::new_unchecked(jl_tuple_typename), Private) }
131    }
132
133    /// The typename of the `UnionAll` `VecElement`.
134    #[inline]
135    pub fn of_vecelement<Tgt>(_: &Tgt) -> Self
136    where
137        Tgt: Target<'base>,
138    {
139        // Safety: global constant
140        unsafe { Self::wrap_non_null(NonNull::new_unchecked(jl_vecelement_typename), Private) }
141    }
142
143    /// The typename of the `UnionAll` `Array`.
144    #[inline]
145    pub fn of_array<Tgt>(_: &Tgt) -> Self
146    where
147        Tgt: Target<'base>,
148    {
149        // Safety: global constant
150        unsafe { Self::wrap_non_null(NonNull::new_unchecked(jl_array_typename), Private) }
151    }
152
153    /// The typename of the `UnionAll` `Ptr`.
154    #[inline]
155    pub fn of_pointer<Tgt>(_: &Tgt) -> Self
156    where
157        Tgt: Target<'base>,
158    {
159        // Safety: global constant
160        unsafe { Self::wrap_non_null(NonNull::new_unchecked(jl_pointer_typename), Private) }
161    }
162
163    /// The typename of the `UnionAll` `LLVMPtr`.
164    #[inline]
165    pub fn of_llvmpointer<Tgt>(_: &Tgt) -> Self
166    where
167        Tgt: Target<'base>,
168    {
169        // Safety: global constant
170        unsafe { Self::wrap_non_null(NonNull::new_unchecked(jl_llvmpointer_typename), Private) }
171    }
172
173    /// The typename of the `UnionAll` `NamedTuple`.
174    #[inline]
175    pub fn of_namedtuple<Tgt>(_: &Tgt) -> Self
176    where
177        Tgt: Target<'base>,
178    {
179        // Safety: global constant
180        unsafe { Self::wrap_non_null(NonNull::new_unchecked(jl_namedtuple_typename), Private) }
181    }
182
183    #[julia_version(since = "1.11")]
184    /// The typename of the `UnionAll` `GenericMemory`.
185    #[inline]
186    pub fn of_genericmemory<Tgt>(_: &Tgt) -> Self
187    where
188        Tgt: Target<'base>,
189    {
190        // Safety: global constant
191        unsafe {
192            Self::wrap_non_null(
193                NonNull::new_unchecked(jl_sys::jl_genericmemory_typename),
194                Private,
195            )
196        }
197    }
198
199    #[julia_version(since = "1.11")]
200    /// The typename of the `UnionAll` `GenericMemoryRef`.
201    #[inline]
202    pub fn of_genericmemoryref<Tgt>(_: &Tgt) -> Self
203    where
204        Tgt: Target<'base>,
205    {
206        // Safety: global constant
207        unsafe {
208            Self::wrap_non_null(
209                NonNull::new_unchecked(jl_sys::jl_genericmemoryref_typename),
210                Private,
211            )
212        }
213    }
214}
215
216impl_julia_typecheck!(TypeName<'scope>, jl_typename_type, 'scope);
217impl_debug!(TypeName<'_>);
218
219impl<'scope> ManagedPriv<'scope, '_> for TypeName<'scope> {
220    type Wraps = jl_typename_t;
221    type WithLifetimes<'target, 'da> = TypeName<'target>;
222    const NAME: &'static str = "TypeName";
223
224    // Safety: `inner` must not have been freed yet, the result must never be
225    // used after the GC might have freed it.
226    #[inline]
227    unsafe fn wrap_non_null(inner: NonNull<Self::Wraps>, _: Private) -> Self {
228        Self(inner, PhantomData)
229    }
230
231    #[inline]
232    fn unwrap_non_null(self, _: Private) -> NonNull<Self::Wraps> {
233        self.0
234    }
235}
236
237impl_construct_type_managed!(TypeName, 1, jl_typename_type);
238
239/// A [`TypeName`] that has not been explicitly rooted.
240pub type WeakTypeName<'scope> = Weak<'scope, 'static, TypeName<'scope>>;
241
242/// A [`WeakTypeName`] with static lifetimes. This is a useful shorthand for signatures of
243/// `ccall`able functions that return a [`TypeName`].
244pub type TypeNameRet = WeakTypeName<'static>;
245
246impl_valid_layout!(WeakTypeName, TypeName, jl_typename_type);
247
248use crate::memory::target::TargetType;
249
250/// `TypeName` or `WeakTypeName`, depending on the target type `Tgt`.
251pub type TypeNameData<'target, Tgt> =
252    <Tgt as TargetType<'target>>::Data<'static, TypeName<'target>>;
253
254/// `JuliaResult<TypeName>` or `WeakJuliaResult<WeakTypeName>`, depending on the target type `Tgt`.
255pub type TypeNameResult<'target, Tgt> = TargetResult<'target, 'static, TypeName<'target>, Tgt>;
256
257impl_ccall_arg_managed!(TypeName, 1);
258impl_into_typed!(TypeName);