1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
use crate::{
    abi_stability::{GetStaticEquivalent, GetStaticEquivalent_, PrefixStableAbi, StableAbi},
    pointer_trait::{GetPointerKind, PK_Reference},
    prefix_type::{FieldAccessibility, PTStructLayout, PrefixRefTrait, WithMetadata_},
    reexports::True,
    reflection::ModReflMode,
    sabi_types::StaticRef,
    std_types::RSlice,
    type_layout::{
        CompTLField, GenericTLData, LifetimeRange, MonoTLData, MonoTypeLayout, ReprAttr, TypeLayout,
    },
    utils::Transmuter,
};

use std::{
    fmt::{self, Debug},
    ptr::NonNull,
};

/// A reference to a prefix type.
///
/// This is the type that all `*_Ref` pointer types generated by `StableAbi` wrap.
///
/// # Example
///
/// ```rust
/// use abi_stable::{
///     prefix_type::{PrefixRef, PrefixTypeTrait, WithMetadata},
///     staticref, StableAbi,
/// };
///
/// fn main() {
///     // `Module_Ref`'s constructor can also be called at compile-time
///     asserts(Module_Ref(PREFIX_A));
///     asserts(Module_Ref(PREFIX_B));
/// }
///
/// fn asserts(module: Module_Ref) {
///     assert_eq!(module.first(), 5);
///     assert_eq!(module.second(), 8);
///
///     // If this Module_Ref had come from a previous version of the library without a
///     // `third` field it would return `None`.
///     assert_eq!(module.third(), Some(13));
/// }
///
/// #[repr(C)]
/// #[derive(StableAbi)]
/// #[sabi(kind(Prefix(prefix_ref = Module_Ref, prefix_fields = Module_Prefix)))]
/// struct Module {
///     first: usize,
///     // The `#[sabi(last_prefix_field)]` attribute here means that this is
///     // the last field in this struct that was defined in the
///     // first compatible version of the library,
///     // requiring new fields to always be added after it.
///     // Moving this attribute is a breaking change, it can only be done in a
///     // major version bump..
///     #[sabi(last_prefix_field)]
///     second: usize,
///     third: usize,
/// }
///
/// const MOD_VAL: Module = Module {
///     first: 5,
///     second: 8,
///     third: 13,
/// };
///
/// /////////////////////////////////////////
/// // First way to construct a PrefixRef
/// // This is a way that PrefixRef can be constructed in statics
///
/// const PREFIX_A: PrefixRef<Module_Prefix> = {
///     const S: &WithMetadata<Module> = &WithMetadata::new(MOD_VAL);
///
///     S.static_as_prefix()
/// };
///
/// /////////////////////////////////////////
/// // Second way to construct a PrefixRef
/// // This is a way that PrefixRef can be constructed in associated constants,
///
/// struct WithAssoc;
///
/// impl WithAssoc {
///     // This macro declares a `StaticRef` pointing to the assigned `WithMetadata`.
///     staticref!{const MOD_WM: WithMetadata<Module> = WithMetadata::new(MOD_VAL)}
/// }
///
/// const PREFIX_B: PrefixRef<Module_Prefix> = WithAssoc::MOD_WM.as_prefix();
///
/// /////////////////////////////////////////
///
/// ```
#[repr(transparent)]
pub struct PrefixRef<P> {
    ptr: NonNull<WithMetadata_<P, P>>,
}

impl<P> Clone for PrefixRef<P> {
    #[inline]
    fn clone(&self) -> Self {
        *self
    }
}

impl<P> Copy for PrefixRef<P> {}

unsafe impl<'a, P: 'a> Sync for PrefixRef<P> where &'a WithMetadata_<P, P>: Sync {}

unsafe impl<'a, P: 'a> Send for PrefixRef<P> where &'a WithMetadata_<P, P>: Send {}

impl<P> Debug for PrefixRef<P> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("PrefixRef")
            .field("type_layout", &self.type_layout())
            .field("field_accessibility", &self.field_accessibility())
            .field("value_type", &std::any::type_name::<P>())
            .finish()
    }
}

impl<P> PrefixRef<P> {
    /// Constructs a `PrefixRef` from a raw pointer.
    ///
    /// # Safety
    ///
    /// The pointer must be a non-dangling pointer to a valid, initialized instance of `T`,
    /// and live for the rest of the program's lifetime
    /// (if called at compile-time it means live for the entire program).
    ///
    /// `T` must implement `PrefixTypeTrait<Fields = P>`,
    /// this is automatically true if this is called with
    /// `&WithMetadata::new(<value>)`.
    ///
    /// # Example
    ///
    /// ```rust
    /// use abi_stable::{
    ///     for_examples::{Module, Module_Prefix, Module_Ref},
    ///     prefix_type::{PrefixRef, PrefixTypeTrait, WithMetadata},
    ///     rstr,
    ///     std_types::*,
    /// };
    ///
    /// const MOD_WM: &WithMetadata<Module> = {
    ///     &WithMetadata::new(
    ///         Module {
    ///             first: RSome(3),
    ///             second: rstr!("hello"),
    ///             third: 8,
    ///         },
    ///     )
    /// };
    ///
    /// const PREFIX: PrefixRef<Module_Prefix> = unsafe { PrefixRef::from_raw(MOD_WM) };
    ///
    /// const MODULE: Module_Ref = Module_Ref(PREFIX);
    ///
    /// assert_eq!(MODULE.first(), RSome(3));
    ///
    /// assert_eq!(MODULE.second().as_str(), "hello");
    ///
    /// // The accessor returns an `Option` because the field comes after the prefix,
    /// // and returning an Option is the default for those.
    /// assert_eq!(MODULE.third(), Some(8));
    ///
    /// ```
    #[inline(always)]
    pub const unsafe fn from_raw<T>(ptr: *const WithMetadata_<T, P>) -> Self {
        Self {
            ptr: unsafe {
                NonNull::new_unchecked(
                    ptr as *const WithMetadata_<P, P> as *mut WithMetadata_<P, P>,
                )
            },
        }
    }

    /// Constructs a `PrefixRef` from a [`StaticRef`].
    ///
    /// # Example
    ///
    /// ```rust
    /// use abi_stable::{
    ///     for_examples::{Module, Module_Prefix, Module_Ref},
    ///     prefix_type::{PrefixRef, PrefixTypeTrait, WithMetadata},
    ///     rstr, staticref,
    ///     std_types::*,
    /// };
    ///
    /// struct Foo {}
    ///
    /// impl Foo {
    ///     // This macro declares a `StaticRef` pointing to the assigned `WithMetadata`.
    ///     staticref! {const MOD_WM: WithMetadata<Module> =
    ///         WithMetadata::new(Module{
    ///             first: RNone,
    ///             second: rstr!("world"),
    ///             third: 13,
    ///         })
    ///     }
    /// }
    ///
    /// const PREFIX: PrefixRef<Module_Prefix> = PrefixRef::from_staticref(Foo::MOD_WM);
    ///
    /// const MODULE: Module_Ref = Module_Ref(PREFIX);
    ///
    /// assert_eq!(MODULE.first(), RNone);
    ///
    /// assert_eq!(MODULE.second().as_str(), "world");
    ///
    /// // The accessor returns an `Option` because the field comes after the prefix,
    /// // and returning an Option is the default for those.
    /// assert_eq!(MODULE.third(), Some(13));
    ///
    /// ```
    ///
    /// [`StaticRef`]: ../sabi_types/struct.StaticRef.html
    #[inline]
    pub const fn from_staticref<T>(ptr: StaticRef<WithMetadata_<T, P>>) -> Self {
        unsafe { Self::from_raw(ptr.as_ptr()) }
    }

    /// Constructs a `PrefixRef` from a static reference.
    ///
    /// # Example
    ///
    /// ```rust
    /// use abi_stable::{
    ///     for_examples::{Module, Module_Prefix, Module_Ref},
    ///     prefix_type::{PrefixRef, PrefixTypeTrait, WithMetadata},
    ///     rstr,
    ///     std_types::*,
    /// };
    ///
    /// const MOD_WM: &WithMetadata<Module> = {
    ///     &WithMetadata::new(
    ///         Module {
    ///             first: RNone,
    ///             second: rstr!("foo"),
    ///             third: 21,
    ///         },
    ///     )
    /// };
    ///
    /// const PREFIX: PrefixRef<Module_Prefix> = PrefixRef::from_ref(MOD_WM);
    ///
    /// const MODULE: Module_Ref = Module_Ref(PREFIX);
    ///
    /// assert_eq!(MODULE.first(), RNone);
    ///
    /// assert_eq!(MODULE.second().as_str(), "foo");
    ///
    /// // The accessor returns an `Option` because the field comes after the prefix,
    /// // and returning an Option is the default for those.
    /// assert_eq!(MODULE.third(), Some(21));
    ///
    /// ```
    ///
    #[inline]
    pub const fn from_ref<T>(ptr: &'static WithMetadata_<T, P>) -> Self {
        unsafe { Self::from_raw(ptr) }
    }

    /// A bit array that describes the accessibility of each field in `P`.
    ///
    /// # Example
    ///
    /// ```rust
    /// use abi_stable::{
    ///     for_examples::{Module, Module_Prefix},
    ///     prefix_type::{PrefixRef, PrefixTypeTrait, WithMetadata},
    ///     std_types::*,
    /// };
    ///
    /// const MOD_WM: &WithMetadata<Module> = {
    ///     &WithMetadata::new(
    ///         Module {
    ///             first: RNone,
    ///             second: RStr::empty(),
    ///             third: 0,
    ///         },
    ///     )
    /// };
    ///
    /// const PREFIX: PrefixRef<Module_Prefix> = PrefixRef::from_ref(MOD_WM);
    ///
    /// let accessibility = PREFIX.field_accessibility();
    ///
    /// assert!(accessibility.at(0).is_accessible()); // The `first` field
    /// assert!(accessibility.at(1).is_accessible()); // The `second` field
    /// assert!(accessibility.at(2).is_accessible()); // The `third` field
    /// assert!(!accessibility.at(3).is_accessible()); // There's no field after `third`
    ///
    /// ```
    ///
    pub const fn field_accessibility(&self) -> FieldAccessibility {
        let ptr: *const _ = self.ptr.as_ptr();
        unsafe { (*ptr).field_accessibility }
    }

    /// The basic layout of the prefix type, for error messages.
    pub const fn type_layout(&self) -> &'static PTStructLayout {
        let ptr: *const _ = self.ptr.as_ptr();
        unsafe { (*ptr).type_layout }
    }

    /// Gets a reference to the pointed-to prefix.
    ///
    /// # Example
    ///
    /// ```rust
    /// use abi_stable::{
    ///     for_examples::{Module, Module_Prefix},
    ///     prefix_type::{PrefixRef, PrefixTypeTrait, WithMetadata},
    ///     rstr,
    ///     std_types::*,
    /// };
    ///
    /// const MOD_WM: &WithMetadata<Module> = {
    ///     &WithMetadata::new(
    ///         Module {
    ///             first: RNone,
    ///             second: rstr!("foo"),
    ///             third: 21,
    ///         },
    ///     )
    /// };
    ///
    /// const PREFIX_REF: PrefixRef<Module_Prefix> = PrefixRef::from_ref(MOD_WM);
    ///
    /// let prefix: &Module_Prefix = PREFIX_REF.prefix();
    ///
    /// assert_eq!(prefix.first, RNone);
    ///
    /// assert_eq!(prefix.second.as_str(), "foo");
    ///
    /// // The `third` field is not in the prefix, so it can't be accessed here.
    /// // prefix.third;
    ///
    /// ```
    ///
    #[inline]
    pub const fn prefix<'a>(self) -> &'a P {
        let ptr: *const _ = self.ptr.as_ptr();
        unsafe { &(*ptr).value.0 }
    }

    /// Converts this PrefixRef into a raw pointer.
    #[inline(always)]
    pub const fn to_raw_ptr(self) -> *const WithMetadata_<P, P> {
        unsafe { Transmuter { from: self }.to }
    }

    /// Casts the pointed-to prefix to another type.
    ///
    /// # Safety
    ///
    /// This function is intended for casting the `PrefixRef<P>` to `PrefixRef<U>`,
    /// and then cast back to `PrefixRef<P>` to use it again.
    ///
    /// The prefix in the returned `PrefixRef<U>` must only be accessed
    /// when this `PrefixRef` was originally cosntructed with a `ẀithMetadata_<_, U>`.
    /// access includes calling `prefix`, and reading the `value` field in the `WithMetadata`
    /// that this points to.
    ///
    pub const unsafe fn cast<U>(self) -> PrefixRef<U> {
        PrefixRef {
            ptr: self.ptr.cast(),
        }
    }
}

unsafe impl<P> GetStaticEquivalent_ for PrefixRef<P>
where
    P: GetStaticEquivalent_,
{
    type StaticEquivalent = PrefixRef<GetStaticEquivalent<P>>;
}

unsafe impl<P> StableAbi for PrefixRef<P>
where
    P: PrefixStableAbi,
{
    type IsNonZeroType = True;

    const LAYOUT: &'static TypeLayout = {
        const MONO_TYPE_LAYOUT: &MonoTypeLayout = &MonoTypeLayout::new(
            *mono_shared_vars,
            rstr!("PrefixRef"),
            make_item_info!(),
            MonoTLData::struct_(rslice![]),
            tl_genparams!('a;0;),
            ReprAttr::Transparent,
            ModReflMode::DelegateDeref { layout_index: 0 },
            {
                const S: &[CompTLField] =
                    &[CompTLField::std_field(field0, LifetimeRange::EMPTY, 0)];
                RSlice::from_slice(S)
            },
        );

        make_shared_vars! {
            impl[P] PrefixRef<P>
            where [P: PrefixStableAbi];

            let (mono_shared_vars,shared_vars)={
                strings={ field0:"0", },
                prefix_type_layouts=[P],
            };
        }

        &TypeLayout::from_std::<Self>(
            shared_vars,
            MONO_TYPE_LAYOUT,
            Self::ABI_CONSTS,
            GenericTLData::Struct,
        )
    };
}

unsafe impl<P> GetPointerKind for PrefixRef<P> {
    type PtrTarget = WithMetadata_<P, P>;
    type Kind = PK_Reference;
}

unsafe impl<P> PrefixRefTrait for PrefixRef<P> {
    type PrefixFields = P;
}