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}