abi_stable/prefix_type/
prefix_ref.rs

1use crate::{
2    abi_stability::{GetStaticEquivalent, GetStaticEquivalent_, PrefixStableAbi, StableAbi},
3    pointer_trait::{GetPointerKind, PK_Reference},
4    prefix_type::{FieldAccessibility, PTStructLayout, PrefixRefTrait, WithMetadata_},
5    reexports::True,
6    reflection::ModReflMode,
7    sabi_types::StaticRef,
8    std_types::RSlice,
9    type_layout::{
10        CompTLField, GenericTLData, LifetimeRange, MonoTLData, MonoTypeLayout, ReprAttr, TypeLayout,
11    },
12    utils::Transmuter,
13};
14
15use std::{
16    fmt::{self, Debug},
17    ptr::NonNull,
18};
19
20/// A reference to a prefix type.
21///
22/// This is the type that all `*_Ref` pointer types generated by `StableAbi` wrap.
23///
24/// # Example
25///
26/// ```rust
27/// use abi_stable::{
28///     prefix_type::{PrefixRef, PrefixTypeTrait, WithMetadata},
29///     staticref, StableAbi,
30/// };
31///
32/// fn main() {
33///     // `Module_Ref`'s constructor can also be called at compile-time
34///     asserts(Module_Ref(PREFIX_A));
35///     asserts(Module_Ref(PREFIX_B));
36/// }
37///
38/// fn asserts(module: Module_Ref) {
39///     assert_eq!(module.first(), 5);
40///     assert_eq!(module.second(), 8);
41///
42///     // If this Module_Ref had come from a previous version of the library without a
43///     // `third` field it would return `None`.
44///     assert_eq!(module.third(), Some(13));
45/// }
46///
47/// #[repr(C)]
48/// #[derive(StableAbi)]
49/// #[sabi(kind(Prefix(prefix_ref = Module_Ref, prefix_fields = Module_Prefix)))]
50/// struct Module {
51///     first: usize,
52///     // The `#[sabi(last_prefix_field)]` attribute here means that this is
53///     // the last field in this struct that was defined in the
54///     // first compatible version of the library,
55///     // requiring new fields to always be added after it.
56///     // Moving this attribute is a breaking change, it can only be done in a
57///     // major version bump..
58///     #[sabi(last_prefix_field)]
59///     second: usize,
60///     third: usize,
61/// }
62///
63/// const MOD_VAL: Module = Module {
64///     first: 5,
65///     second: 8,
66///     third: 13,
67/// };
68///
69/// /////////////////////////////////////////
70/// // First way to construct a PrefixRef
71/// // This is a way that PrefixRef can be constructed in statics
72///
73/// const PREFIX_A: PrefixRef<Module_Prefix> = {
74///     const S: &WithMetadata<Module> = &WithMetadata::new(MOD_VAL);
75///
76///     S.static_as_prefix()
77/// };
78///
79/// /////////////////////////////////////////
80/// // Second way to construct a PrefixRef
81/// // This is a way that PrefixRef can be constructed in associated constants,
82///
83/// struct WithAssoc;
84///
85/// impl WithAssoc {
86///     // This macro declares a `StaticRef` pointing to the assigned `WithMetadata`.
87///     staticref!{const MOD_WM: WithMetadata<Module> = WithMetadata::new(MOD_VAL)}
88/// }
89///
90/// const PREFIX_B: PrefixRef<Module_Prefix> = WithAssoc::MOD_WM.as_prefix();
91///
92/// /////////////////////////////////////////
93///
94/// ```
95#[repr(transparent)]
96pub struct PrefixRef<P> {
97    ptr: NonNull<WithMetadata_<P, P>>,
98}
99
100impl<P> Clone for PrefixRef<P> {
101    #[inline]
102    fn clone(&self) -> Self {
103        *self
104    }
105}
106
107impl<P> Copy for PrefixRef<P> {}
108
109unsafe impl<'a, P: 'a> Sync for PrefixRef<P> where &'a WithMetadata_<P, P>: Sync {}
110
111unsafe impl<'a, P: 'a> Send for PrefixRef<P> where &'a WithMetadata_<P, P>: Send {}
112
113impl<P> Debug for PrefixRef<P> {
114    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115        f.debug_struct("PrefixRef")
116            .field("type_layout", &self.type_layout())
117            .field("field_accessibility", &self.field_accessibility())
118            .field("value_type", &std::any::type_name::<P>())
119            .finish()
120    }
121}
122
123impl<P> PrefixRef<P> {
124    /// Constructs a `PrefixRef` from a raw pointer.
125    ///
126    /// # Safety
127    ///
128    /// The pointer must be a non-dangling pointer to a valid, initialized instance of `T`,
129    /// and live for the rest of the program's lifetime
130    /// (if called at compile-time it means live for the entire program).
131    ///
132    /// `T` must implement `PrefixTypeTrait<Fields = P>`,
133    /// this is automatically true if this is called with
134    /// `&WithMetadata::new(<value>)`.
135    ///
136    /// # Example
137    ///
138    /// ```rust
139    /// use abi_stable::{
140    ///     for_examples::{Module, Module_Prefix, Module_Ref},
141    ///     prefix_type::{PrefixRef, PrefixTypeTrait, WithMetadata},
142    ///     rstr,
143    ///     std_types::*,
144    /// };
145    ///
146    /// const MOD_WM: &WithMetadata<Module> = {
147    ///     &WithMetadata::new(
148    ///         Module {
149    ///             first: RSome(3),
150    ///             second: rstr!("hello"),
151    ///             third: 8,
152    ///         },
153    ///     )
154    /// };
155    ///
156    /// const PREFIX: PrefixRef<Module_Prefix> = unsafe { PrefixRef::from_raw(MOD_WM) };
157    ///
158    /// const MODULE: Module_Ref = Module_Ref(PREFIX);
159    ///
160    /// assert_eq!(MODULE.first(), RSome(3));
161    ///
162    /// assert_eq!(MODULE.second().as_str(), "hello");
163    ///
164    /// // The accessor returns an `Option` because the field comes after the prefix,
165    /// // and returning an Option is the default for those.
166    /// assert_eq!(MODULE.third(), Some(8));
167    ///
168    /// ```
169    #[inline(always)]
170    pub const unsafe fn from_raw<T>(ptr: *const WithMetadata_<T, P>) -> Self {
171        Self {
172            ptr: unsafe {
173                NonNull::new_unchecked(
174                    ptr as *const WithMetadata_<P, P> as *mut WithMetadata_<P, P>,
175                )
176            },
177        }
178    }
179
180    /// Constructs a `PrefixRef` from a [`StaticRef`].
181    ///
182    /// # Example
183    ///
184    /// ```rust
185    /// use abi_stable::{
186    ///     for_examples::{Module, Module_Prefix, Module_Ref},
187    ///     prefix_type::{PrefixRef, PrefixTypeTrait, WithMetadata},
188    ///     rstr, staticref,
189    ///     std_types::*,
190    /// };
191    ///
192    /// struct Foo {}
193    ///
194    /// impl Foo {
195    ///     // This macro declares a `StaticRef` pointing to the assigned `WithMetadata`.
196    ///     staticref! {const MOD_WM: WithMetadata<Module> =
197    ///         WithMetadata::new(Module{
198    ///             first: RNone,
199    ///             second: rstr!("world"),
200    ///             third: 13,
201    ///         })
202    ///     }
203    /// }
204    ///
205    /// const PREFIX: PrefixRef<Module_Prefix> = PrefixRef::from_staticref(Foo::MOD_WM);
206    ///
207    /// const MODULE: Module_Ref = Module_Ref(PREFIX);
208    ///
209    /// assert_eq!(MODULE.first(), RNone);
210    ///
211    /// assert_eq!(MODULE.second().as_str(), "world");
212    ///
213    /// // The accessor returns an `Option` because the field comes after the prefix,
214    /// // and returning an Option is the default for those.
215    /// assert_eq!(MODULE.third(), Some(13));
216    ///
217    /// ```
218    ///
219    /// [`StaticRef`]: ../sabi_types/struct.StaticRef.html
220    #[inline]
221    pub const fn from_staticref<T>(ptr: StaticRef<WithMetadata_<T, P>>) -> Self {
222        unsafe { Self::from_raw(ptr.as_ptr()) }
223    }
224
225    /// Constructs a `PrefixRef` from a static reference.
226    ///
227    /// # Example
228    ///
229    /// ```rust
230    /// use abi_stable::{
231    ///     for_examples::{Module, Module_Prefix, Module_Ref},
232    ///     prefix_type::{PrefixRef, PrefixTypeTrait, WithMetadata},
233    ///     rstr,
234    ///     std_types::*,
235    /// };
236    ///
237    /// const MOD_WM: &WithMetadata<Module> = {
238    ///     &WithMetadata::new(
239    ///         Module {
240    ///             first: RNone,
241    ///             second: rstr!("foo"),
242    ///             third: 21,
243    ///         },
244    ///     )
245    /// };
246    ///
247    /// const PREFIX: PrefixRef<Module_Prefix> = PrefixRef::from_ref(MOD_WM);
248    ///
249    /// const MODULE: Module_Ref = Module_Ref(PREFIX);
250    ///
251    /// assert_eq!(MODULE.first(), RNone);
252    ///
253    /// assert_eq!(MODULE.second().as_str(), "foo");
254    ///
255    /// // The accessor returns an `Option` because the field comes after the prefix,
256    /// // and returning an Option is the default for those.
257    /// assert_eq!(MODULE.third(), Some(21));
258    ///
259    /// ```
260    ///
261    #[inline]
262    pub const fn from_ref<T>(ptr: &'static WithMetadata_<T, P>) -> Self {
263        unsafe { Self::from_raw(ptr) }
264    }
265
266    /// A bit array that describes the accessibility of each field in `P`.
267    ///
268    /// # Example
269    ///
270    /// ```rust
271    /// use abi_stable::{
272    ///     for_examples::{Module, Module_Prefix},
273    ///     prefix_type::{PrefixRef, PrefixTypeTrait, WithMetadata},
274    ///     std_types::*,
275    /// };
276    ///
277    /// const MOD_WM: &WithMetadata<Module> = {
278    ///     &WithMetadata::new(
279    ///         Module {
280    ///             first: RNone,
281    ///             second: RStr::empty(),
282    ///             third: 0,
283    ///         },
284    ///     )
285    /// };
286    ///
287    /// const PREFIX: PrefixRef<Module_Prefix> = PrefixRef::from_ref(MOD_WM);
288    ///
289    /// let accessibility = PREFIX.field_accessibility();
290    ///
291    /// assert!(accessibility.at(0).is_accessible()); // The `first` field
292    /// assert!(accessibility.at(1).is_accessible()); // The `second` field
293    /// assert!(accessibility.at(2).is_accessible()); // The `third` field
294    /// assert!(!accessibility.at(3).is_accessible()); // There's no field after `third`
295    ///
296    /// ```
297    ///
298    pub const fn field_accessibility(&self) -> FieldAccessibility {
299        let ptr: *const _ = self.ptr.as_ptr();
300        unsafe { (*ptr).field_accessibility }
301    }
302
303    /// The basic layout of the prefix type, for error messages.
304    pub const fn type_layout(&self) -> &'static PTStructLayout {
305        let ptr: *const _ = self.ptr.as_ptr();
306        unsafe { (*ptr).type_layout }
307    }
308
309    /// Gets a reference to the pointed-to prefix.
310    ///
311    /// # Example
312    ///
313    /// ```rust
314    /// use abi_stable::{
315    ///     for_examples::{Module, Module_Prefix},
316    ///     prefix_type::{PrefixRef, PrefixTypeTrait, WithMetadata},
317    ///     rstr,
318    ///     std_types::*,
319    /// };
320    ///
321    /// const MOD_WM: &WithMetadata<Module> = {
322    ///     &WithMetadata::new(
323    ///         Module {
324    ///             first: RNone,
325    ///             second: rstr!("foo"),
326    ///             third: 21,
327    ///         },
328    ///     )
329    /// };
330    ///
331    /// const PREFIX_REF: PrefixRef<Module_Prefix> = PrefixRef::from_ref(MOD_WM);
332    ///
333    /// let prefix: &Module_Prefix = PREFIX_REF.prefix();
334    ///
335    /// assert_eq!(prefix.first, RNone);
336    ///
337    /// assert_eq!(prefix.second.as_str(), "foo");
338    ///
339    /// // The `third` field is not in the prefix, so it can't be accessed here.
340    /// // prefix.third;
341    ///
342    /// ```
343    ///
344    #[inline]
345    pub const fn prefix<'a>(self) -> &'a P {
346        let ptr: *const _ = self.ptr.as_ptr();
347        unsafe { &(*ptr).value.0 }
348    }
349
350    /// Converts this PrefixRef into a raw pointer.
351    #[inline(always)]
352    pub const fn to_raw_ptr(self) -> *const WithMetadata_<P, P> {
353        unsafe { Transmuter { from: self }.to }
354    }
355
356    /// Casts the pointed-to prefix to another type.
357    ///
358    /// # Safety
359    ///
360    /// This function is intended for casting the `PrefixRef<P>` to `PrefixRef<U>`,
361    /// and then cast back to `PrefixRef<P>` to use it again.
362    ///
363    /// The prefix in the returned `PrefixRef<U>` must only be accessed
364    /// when this `PrefixRef` was originally cosntructed with a `ẀithMetadata_<_, U>`.
365    /// access includes calling `prefix`, and reading the `value` field in the `WithMetadata`
366    /// that this points to.
367    ///
368    pub const unsafe fn cast<U>(self) -> PrefixRef<U> {
369        PrefixRef {
370            ptr: self.ptr.cast(),
371        }
372    }
373}
374
375unsafe impl<P> GetStaticEquivalent_ for PrefixRef<P>
376where
377    P: GetStaticEquivalent_,
378{
379    type StaticEquivalent = PrefixRef<GetStaticEquivalent<P>>;
380}
381
382unsafe impl<P> StableAbi for PrefixRef<P>
383where
384    P: PrefixStableAbi,
385{
386    type IsNonZeroType = True;
387
388    const LAYOUT: &'static TypeLayout = {
389        const MONO_TYPE_LAYOUT: &MonoTypeLayout = &MonoTypeLayout::new(
390            *mono_shared_vars,
391            rstr!("PrefixRef"),
392            make_item_info!(),
393            MonoTLData::struct_(rslice![]),
394            tl_genparams!('a;0;),
395            ReprAttr::Transparent,
396            ModReflMode::DelegateDeref { layout_index: 0 },
397            {
398                const S: &[CompTLField] =
399                    &[CompTLField::std_field(field0, LifetimeRange::EMPTY, 0)];
400                RSlice::from_slice(S)
401            },
402        );
403
404        make_shared_vars! {
405            impl[P] PrefixRef<P>
406            where [P: PrefixStableAbi];
407
408            let (mono_shared_vars,shared_vars)={
409                strings={ field0:"0", },
410                prefix_type_layouts=[P],
411            };
412        }
413
414        &TypeLayout::from_std::<Self>(
415            shared_vars,
416            MONO_TYPE_LAYOUT,
417            Self::ABI_CONSTS,
418            GenericTLData::Struct,
419        )
420    };
421}
422
423unsafe impl<P> GetPointerKind for PrefixRef<P> {
424    type PtrTarget = WithMetadata_<P, P>;
425    type Kind = PK_Reference;
426}
427
428unsafe impl<P> PrefixRefTrait for PrefixRef<P> {
429    type PrefixFields = P;
430}