repr_offset/
struct_field_offset.rs

1// All the uses of usize as isize are for struct offsets,
2// which as far as I am aware are all smaller than isize::MAX
3#![allow(clippy::ptr_offset_with_cast)]
4
5#[macro_use]
6mod impl_fieldoffset_methods;
7
8mod repr_offset_ext_impls;
9
10////////////////////////////////////////////////////////////////////////////////
11
12use crate::{
13    alignment::{Aligned, Alignment, CombineAlignment, CombineAlignmentOut, Unaligned},
14    offset_calc::GetNextFieldOffset,
15    utils::Mem,
16};
17
18use crate::get_field_offset::FieldOffsetWithVis;
19
20use core::{
21    fmt::{self, Debug},
22    marker::PhantomData,
23    ops::Add,
24};
25
26/// Represents the offset of a (potentially nested) field inside a type.
27///
28/// # Type parameters
29///
30/// The type parameters are:
31///
32/// - `S`(for `struct`): the struct that contains the field that this is an offset for.
33///
34/// - `F`(for field): the type of the field this is an offset for.
35///
36/// - `A`(for alignment):
37/// Is [`Aligned`] if this offset is for [an aligned field](#alignment-guidelines)
38/// within the `S` struct,
39/// [`Unaligned`] if it is for [an unaligned field](#alignment-guidelines).
40/// This changes which methods are available,and the implementation of many of them.
41///
42/// # Safety
43///
44/// ### Alignment
45///
46/// All the unsafe methods for `FieldOffset<_, _, Aligned>`
47/// that move/copy the field require that
48/// the passed in pointers are aligned,
49/// while the ones for `FieldOffset<_, _, Unaligned>` do not.
50///
51/// Because passing unaligned pointers to `FieldOffset<_, _, Aligned>` methods
52/// causes undefined behavior,
53/// you must be careful when accessing a nested field in `#[repr(C, packed)]` structs.
54///
55/// For an example of how to correctly access nested fields inside of
56/// `#[repr(C, packed)]` structs [look here](#nested-field-in-packed).
57///
58/// <span id="alignment-guidelines"></span>
59/// # Field alignment guidelines
60///
61/// A non-nested field is:
62///
63/// - Aligned: if the type that contains the field is
64/// `#[repr(C)]`/`#[repr(C, align(...))]`/`#[repr(transparent)]`.
65///
66/// - Unaligned: if the type that contains the field is `#[repr(C, packed(....))]`,
67/// and the packing is smaller than the alignment of the field type.<br>
68/// Note that type alignment can vary across platforms,
69/// so `FieldOffset<S, F, Unaligned>`(as opposed to `FieldOffset<S, F, Aligned>`)
70/// is safest when `S` is a `#[repr(C, packed)]` type.
71///
72/// A nested field is unaligned if any field in the chain of field accesses to the
73/// nested field (ie: `foo` and `bar` and `baz` in `foo.bar.baz`)
74/// is unaligned according to the rules for non-nested fields described in this section.
75///
76///
77/// # Examples
78///
79/// ### No Macros
80///
81/// This example demonstrates how you can construct `FieldOffset` without macros.
82///
83/// You can use the [`ReprOffset`] derive macro or [`unsafe_struct_field_offsets`] macro
84/// to construct the constants more conveniently (and in a less error-prone way).
85///
86/// ```rust
87/// # #![deny(safe_packed_borrows)]
88/// use repr_offset::{Aligned, FieldOffset};
89///
90/// use std::mem;
91///
92///
93/// fn main(){
94///     let mut foo = Foo{ first: 3u16, second: 5, third: None };
95///
96///     *Foo::OFFSET_FIRST.get_mut(&mut foo) = 13;
97///     *Foo::OFFSET_SECOND.get_mut(&mut foo) = 21;
98///     *Foo::OFFSET_THIRD.get_mut(&mut foo) = Some(34);
99///
100///     assert_eq!( foo, Foo{ first: 13, second: 21, third: Some(34) } );
101/// }
102///
103///
104/// #[repr(C)]
105/// #[derive(Debug,PartialEq)]
106/// struct Foo<T>{
107///     first: T,
108///     second: u32,
109///     third: Option<T>,
110/// }
111///
112/// impl<T> Foo<T>{
113///     const OFFSET_FIRST: FieldOffset<Self, T, Aligned> = unsafe{ FieldOffset::new(0) };
114///
115///     const OFFSET_SECOND: FieldOffset<Self, u32, Aligned> = unsafe{
116///         Self::OFFSET_FIRST.next_field_offset()
117///     };
118///
119///     const OFFSET_THIRD: FieldOffset<Self, Option<T>, Aligned> = unsafe{
120///         Self::OFFSET_SECOND.next_field_offset()
121///     };
122/// }
123///
124/// ```
125///
126/// <span id="nested-field-in-packed"></span>
127/// ### Accessing Nested Fields
128///
129/// This example demonstrates how to access nested fields in a `#[repr(C, packed)]` struct,
130/// using the [`GetFieldOffset`] trait implemented by the [`ReprOffset`] derive,
131/// through the [`off`](./macro.off.html) macro.
132///
133/// ```rust
134/// # #![deny(safe_packed_borrows)]
135#[cfg_attr(feature = "derive", doc = "use repr_offset::ReprOffset;")]
136#[cfg_attr(not(feature = "derive"), doc = "use repr_offset_derive::ReprOffset;")]
137/// use repr_offset::{
138///     alignment::{Aligned, Unaligned},
139///     off,
140///     FieldOffset,
141/// };
142///
143/// #[repr(C, packed)]
144/// #[derive(ReprOffset)]
145/// struct Pack{
146///     x: u8,
147///     y: NestedC,
148/// }
149///
150/// #[repr(C)]
151/// #[derive(ReprOffset)]
152/// struct NestedC{
153///     name: &'static str,
154///     years: usize,
155/// }
156///
157/// let this = Pack{
158///     x: 0,
159///     y: NestedC{ name: "John", years: 13 },
160/// };
161///
162/// let off_y: FieldOffset<Pack, NestedC, Unaligned> = off!(y);
163///
164/// let off_name: FieldOffset<Pack, &'static str, Unaligned> = off!(y.name);
165///
166/// // You can also get the FieldOffset for a nested field like this.
167/// let off_years: FieldOffset<Pack, usize, Unaligned> = off_y.add(off!(years));
168///
169/// // The this argument is required to call FieldOffset methods,
170/// // infering the S type parameter of FieldOffset from `this`.
171/// let _ = off!(this; y.years);
172///
173/// assert_eq!(off_name.get_copy(&this), "John" );
174/// assert_eq!(off_years.get_copy(&this), 13 );
175///
176/// unsafe{
177///     let nested_ptr: *const NestedC = off_y.get_ptr(&this);
178///
179///     // This code is undefined behavior,
180///     // because `NestedC`'s offsets require the passed in pointer to be aligned.
181///     //
182///     // assert_eq!(NestedC::OFFSET_NAME.read(nested_ptr), "John" );
183///     // assert_eq!(NestedC::OFFSET_YEARS.read(nested_ptr), 13 );
184///
185///     // This is fine though,because the offsets were turned into
186///     // `FieldOffset<_, _, Unaligned>` with `.to_unaligned()`.
187///     assert_eq!( NestedC::OFFSET_NAME.to_unaligned().read(nested_ptr), "John" );
188///     assert_eq!( NestedC::OFFSET_YEARS.to_unaligned().read(nested_ptr), 13 );
189///
190/// }
191/// ```
192///
193/// [`Aligned`]: ./alignment/struct.Aligned.html
194/// [`Unaligned`]: ./alignment/struct.Unaligned.html
195///
196/// [`ReprOffset`]: ./derive.ReprOffset.html
197/// [`unsafe_struct_field_offsets`]: ./macro.unsafe_struct_field_offsets.html
198/// [`GetFieldOffset`]: ./get_field_offset/trait.GetFieldOffset.html
199///
200#[repr(transparent)]
201pub struct FieldOffset<S, F, A> {
202    offset: usize,
203    #[doc(hidden)]
204    pub tys: FOGhosts<S, F, A>,
205}
206
207//////////////////////
208
209#[doc(hidden)]
210pub struct FOGhosts<S, F, A> {
211    pub struct_: PhantomData<fn() -> S>,
212    pub field: PhantomData<fn() -> F>,
213    pub alignment: PhantomData<fn() -> A>,
214}
215
216impl<S, F, A> Copy for FOGhosts<S, F, A> {}
217
218impl<S, F, A> Clone for FOGhosts<S, F, A> {
219    #[inline(always)]
220    fn clone(&self) -> Self {
221        *self
222    }
223}
224
225impl<S, F, A> FOGhosts<S, F, A> {
226    const NEW: Self = Self {
227        struct_: PhantomData,
228        field: PhantomData,
229        alignment: PhantomData,
230    };
231}
232
233//////////////////////
234
235#[doc(hidden)]
236#[repr(transparent)]
237pub struct FOAssertStruct<S, F, A> {
238    pub offset: FieldOffset<S, F, A>,
239    pub struct_: PhantomData<fn() -> S>,
240}
241
242//////////////////////
243
244impl_cmp_traits_for_offset! {
245    impl[S, F, A] FieldOffset<S, F, A>
246}
247
248impl<S, F, A> Debug for FieldOffset<S, F, A> {
249    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
250        f.debug_struct("FieldOffset")
251            .field("offset", &self.offset)
252            .finish()
253    }
254}
255
256impl<S, F, A> Copy for FieldOffset<S, F, A> {}
257
258impl<S, F, A> Clone for FieldOffset<S, F, A> {
259    #[inline(always)]
260    fn clone(&self) -> Self {
261        *self
262    }
263}
264
265impl<S, F, A> FieldOffset<S, F, A> {
266    /// Constructs this `FieldOffset` from the offset of the field.
267    ///
268    /// # Safety
269    ///
270    /// Callers must ensure all of these:
271    ///
272    /// - `S` must be a `#[repr(C)]` or `#[repr(transparent)]` struct
273    /// (optionally with `align` or `packed` attributes).
274    ///
275    /// - `offset` must be the byte offset of a field of type `F` inside the struct `S`.
276    ///
277    /// - The `A` type parameter must be [`Unaligned`]
278    /// if the field [is unaligned](#alignment-guidelines),
279    /// or [`Aligned`] if [it is aligned](#alignment-guidelines).
280    ///
281    /// # Example
282    ///
283    /// Constructing the `FieldOffset`s of a packed struct.
284    ///
285    /// ```rust
286    /// # #![deny(safe_packed_borrows)]
287    /// use repr_offset::{Aligned, FieldOffset, Unaligned};
288    ///
289    /// let this = Packed{ x: 3, y: 5, z: "huh" };
290    ///
291    /// assert_eq!( OFFSET_X.get_copy(&this), 3 );
292    /// assert_eq!( OFFSET_Y.get_copy(&this), 5 );
293    /// assert_eq!( OFFSET_Z.get_copy(&this), "huh" );
294    ///
295    /// #[repr(C, packed)]
296    /// struct Packed{
297    ///     x: u8,
298    ///     y: u32,
299    ///     z: &'static str,
300    /// }
301    ///
302    /// // `u8` is always aligned.
303    /// const OFFSET_X: FieldOffset<Packed, u8, Aligned> = unsafe{
304    ///     FieldOffset::new(0)
305    /// };
306    /// const OFFSET_Y: FieldOffset<Packed, u32, Unaligned> = unsafe{
307    ///     OFFSET_X.next_field_offset()
308    /// };
309    /// const OFFSET_Z: FieldOffset<Packed, &'static str, Unaligned> = unsafe{
310    ///     OFFSET_Y.next_field_offset()
311    /// };
312    ///
313    /// ```
314    /// [`Aligned`]: ./alignment/struct.Aligned.html
315    /// [`Unaligned`]: ./alignment/struct.Unaligned.html
316    #[inline(always)]
317    pub const unsafe fn new(offset: usize) -> Self {
318        Self {
319            offset,
320            tys: FOGhosts::NEW,
321        }
322    }
323
324    // This must be kept private
325    #[inline(always)]
326    const fn priv_new(offset: usize) -> Self {
327        Self {
328            offset,
329            tys: FOGhosts::NEW,
330        }
331    }
332
333    /// Constructs a `FieldOffset` by calculating the offset of the next field.
334    ///
335    /// # Safety
336    ///
337    /// Callers must ensure that:
338    ///
339    /// - `Next` is the type of the field after the one that this is an offset for.
340    ///
341    /// - `NextA` must be [`Unaligned`] if the field [is unaligned](#alignment-guidelines),
342    /// or [`Aligned`] if [it is aligned](#alignment-guidelines).
343    ///
344    /// # Example
345    ///
346    /// Constructing the `FieldOffset`s of a `#[repr(C, align(16))]` struct.
347    ///
348    /// ```rust
349    /// # #![deny(safe_packed_borrows)]
350    /// use repr_offset::{Aligned, FieldOffset};
351    ///
352    /// let this = ReprAligned{ foo: true, bar: Some('8'), baz: 55 };
353    ///
354    /// assert_eq!( OFFSET_FOO.get_copy(&this), true );
355    /// assert_eq!( OFFSET_BAR.get_copy(&this), Some('8') );
356    /// assert_eq!( OFFSET_BAZ.get_copy(&this), 55 );
357    ///
358    ///
359    /// #[repr(C, align(16))]
360    /// struct ReprAligned{
361    ///     foo: bool,
362    ///     bar: Option<char>,
363    ///     baz: u64,
364    /// }
365    ///
366    /// const OFFSET_FOO: FieldOffset<ReprAligned, bool, Aligned> = unsafe{
367    ///     FieldOffset::new(0)
368    /// };
369    /// const OFFSET_BAR: FieldOffset<ReprAligned, Option<char>, Aligned> = unsafe{
370    ///     OFFSET_FOO.next_field_offset()
371    /// };
372    /// const OFFSET_BAZ: FieldOffset<ReprAligned, u64, Aligned> = unsafe{
373    ///     OFFSET_BAR.next_field_offset()
374    /// };
375    ///
376    /// ```
377    ///
378    /// [`Aligned`]: ./alignment/struct.Aligned.html
379    /// [`Unaligned`]: ./alignment/struct.Unaligned.html
380    pub const unsafe fn next_field_offset<Next, NextA>(self) -> FieldOffset<S, Next, NextA> {
381        let offset = GetNextFieldOffset {
382            previous_offset: self.offset,
383            previous_size: Mem::<F>::SIZE,
384            container_alignment: Mem::<S>::ALIGN,
385            next_alignment: Mem::<Next>::ALIGN,
386        }
387        .call();
388
389        FieldOffset {
390            offset,
391            tys: FOGhosts::NEW,
392        }
393    }
394}
395
396impl FieldOffset<(), (), Aligned> {
397    /// Constructs a `FieldOffset` where `T` is the struct and the field type.
398    pub const fn identity<T>() -> FieldOffset<T, T, Aligned> {
399        FieldOffset {
400            offset: 0,
401            tys: FOGhosts::NEW,
402        }
403    }
404}
405
406impl<S, F> FieldOffset<S, F, Aligned> {
407    /// Combines this `FieldOffset` with another one, to access a nested field.
408    ///
409    /// Note that the resulting `FieldOffset` has the
410    /// alignment type parameter (the third one) of `other`.
411    ///
412    /// # Example
413    ///
414    /// ```rust
415    /// # #![deny(safe_packed_borrows)]
416    /// use repr_offset::{Aligned, FieldOffset, Unaligned};
417    /// use repr_offset::for_examples::{ReprC, ReprPacked};
418    ///
419    /// type This = ReprC<char, ReprC<u8, u16>, ReprPacked<u32, u64>>;
420    ///
421    /// let this: This = ReprC {
422    ///     a: '3',
423    ///     b: ReprC{ a: 5u8, b: 8u16, c: (), d: () },
424    ///     c: ReprPacked{ a: 13u32, b: 21u64, c: (), d: () },
425    ///     d: (),
426    /// };
427    ///
428    /// assert_eq!( OFFSET_B_A.get_copy(&this), 5 );
429    /// assert_eq!( OFFSET_C_A.get_copy(&this), 13 );
430    ///
431    /// // This is the FieldOffset of the `.b.a` nested field.
432    /// const OFFSET_B_A: FieldOffset<This, u8, Aligned> =
433    ///     ReprC::OFFSET_B.add(ReprC::OFFSET_A);
434    ///
435    /// // This is the FieldOffset of the `.c.a` nested field.
436    /// //
437    /// // The alignment type parameter of the combined FieldOffset is`Unaligned` if
438    /// // either FieldOffset has `Unaligned` as the `A` type parameter.
439    /// const OFFSET_C_A: FieldOffset<This, u32, Unaligned> =
440    ///     ReprC::OFFSET_C.add(ReprPacked::OFFSET_A);
441    ///
442    /// ```
443    ///
444    #[inline(always)]
445    pub const fn add<F2, A2>(self, other: FieldOffset<F, F2, A2>) -> FieldOffset<S, F2, A2> {
446        FieldOffset::priv_new(self.offset + other.offset)
447    }
448}
449
450impl<S, F> FieldOffset<S, F, Unaligned> {
451    /// Combines this `FieldOffset` with another one, to access a nested field.
452    ///
453    /// # Example
454    ///
455    /// ```rust
456    /// # #![deny(safe_packed_borrows)]
457    /// use repr_offset::{FieldOffset, Unaligned};
458    /// use repr_offset::for_examples::{ReprC, ReprPacked};
459    ///
460    /// type This = ReprPacked<char, ReprC<u8, u16>, ReprPacked<u32, u64>>;
461    ///
462    /// let this: This = ReprPacked {
463    ///     a: '3',
464    ///     b: ReprC{ a: 34u8, b: 55u16, c: (), d: () },
465    ///     c: ReprPacked{ a: 89u32, b: 144u64, c: (), d: () },
466    ///     d: (),
467    /// };
468    ///
469    /// assert_eq!( OFFSET_B_A.get_copy(&this), 34 );
470    /// assert_eq!( OFFSET_C_A.get_copy(&this), 89 );
471    ///
472    /// // This is the FieldOffset of the `.b.a` nested field.
473    /// const OFFSET_B_A: FieldOffset<This, u8, Unaligned> =
474    ///     ReprPacked::OFFSET_B.add(ReprC::OFFSET_A);
475    ///
476    /// // This is the FieldOffset of the `.c.a` nested field.
477    /// const OFFSET_C_A: FieldOffset<This, u32, Unaligned> =
478    ///     ReprPacked::OFFSET_C.add(ReprPacked::OFFSET_A);
479    ///
480    /// ```
481    ///
482    #[inline(always)]
483    pub const fn add<F2, A2>(self, other: FieldOffset<F, F2, A2>) -> FieldOffset<S, F2, Unaligned> {
484        FieldOffset::priv_new(self.offset + other.offset)
485    }
486}
487
488/// Equivalent to the inherent `FieldOffset::add` method,
489/// that one can be ran at compile-time(this one can't).
490///
491/// # Example
492///
493/// ```rust
494/// # #![deny(safe_packed_borrows)]
495/// use repr_offset::{Aligned, FieldOffset, Unaligned};
496/// use repr_offset::for_examples::{ReprC, ReprPacked};
497///
498/// type This = ReprC<char, ReprC<u8, u16>, ReprPacked<u32, u64>>;
499///
500/// let this: This = ReprC {
501///     a: '3',
502///     b: ReprC{ a: 5u8, b: 8u16, c: (), d: () },
503///     c: ReprPacked{ a: 13u32, b: 21u64, c: (), d: () },
504///     d: (),
505/// };
506///
507/// // This is the FieldOffset of the `.b.a` nested field.
508/// let offset_b_b = ReprC::OFFSET_B + ReprC::OFFSET_B;
509///
510/// // This is the FieldOffset of the `.c.a` nested field.
511/// let offset_c_b = ReprC::OFFSET_C + ReprPacked::OFFSET_B;
512///
513/// assert_eq!( offset_b_b.get_copy(&this), 8 );
514/// assert_eq!( offset_c_b.get_copy(&this), 21 );
515///
516/// ```
517///
518impl<S, F, A, F2, A2> Add<FieldOffset<F, F2, A2>> for FieldOffset<S, F, A>
519where
520    A: CombineAlignment<A2>,
521    A2: Alignment,
522{
523    type Output = FieldOffset<S, F2, CombineAlignmentOut<A, A2>>;
524
525    #[inline(always)]
526    fn add(self, other: FieldOffset<F, F2, A2>) -> Self::Output {
527        FieldOffset::priv_new(self.offset + other.offset)
528    }
529}
530
531impl<S, F, A> FieldOffset<S, F, A> {
532    /// The offset (in bytes) of the `F` field in the `S` struct.
533    ///
534    /// # Example
535    ///
536    /// This example demonstrates this method with a `#[repr(C, packed)]` struct.
537    ///
538    /// ```rust
539    /// # #![deny(safe_packed_borrows)]
540    /// use repr_offset::for_examples::ReprPacked;
541    ///
542    /// type Normal = ReprPacked<u8, u16, u32, u64>;
543    /// type Reversed = ReprPacked<u64, u32, u16, u8>;
544    ///
545    /// assert_eq!( Normal::OFFSET_A.offset(), 0 );
546    /// assert_eq!( Normal::OFFSET_B.offset(), 1 );
547    /// assert_eq!( Normal::OFFSET_C.offset(), 3 );
548    /// assert_eq!( Normal::OFFSET_D.offset(), 7 );
549    ///
550    /// assert_eq!( Reversed::OFFSET_A.offset(), 0 );
551    /// assert_eq!( Reversed::OFFSET_B.offset(), 8 );
552    /// assert_eq!( Reversed::OFFSET_C.offset(), 12 );
553    /// assert_eq!( Reversed::OFFSET_D.offset(), 14 );
554    ///
555    ///
556    /// ```
557    #[inline(always)]
558    pub const fn offset(self) -> usize {
559        self.offset
560    }
561}
562
563impl<S, F, A> FieldOffset<S, F, A> {
564    /// Converts this FieldOffset into a [`FieldOffsetWithVis`].
565    ///
566    /// # Safety
567    ///
568    /// The `V` type parameter must be:
569    /// - `[`IsPublic`]`: When the field is `pub`.
570    ///
571    /// - [`IsPrivate`]: When the field has the default (private) visibility,
572    /// or has a visibility smaller or equal to `pub(crate)`.
573    ///
574    /// The `FN` type parameter must be the name of the field using the
575    /// `repr_offset::tstr::TS` macro,
576    /// eg: `TS!(foo)` for the `foo` field.
577    ///
578    /// [`IsPublic`]: ./privacy/struct.IsPublic.html
579    /// [`IsPrivate`]: ./privacy/struct.IsPrivate.html
580    ///
581    /// [`FieldOffsetWithVis`] ./get_field_offset/struct.FieldOffsetWithVis.html
582    ///
583    #[inline(always)]
584    pub const unsafe fn with_vis<V, FN>(self) -> FieldOffsetWithVis<S, V, FN, F, A> {
585        FieldOffsetWithVis::from_fieldoffset(self)
586    }
587}
588
589impl<S, F, A> FieldOffset<S, F, A> {
590    /// Changes the `S` type parameter, most useful for `#[repr(transparent)]` wrappers.
591    ///
592    /// # Safety
593    ///
594    /// Callers must ensure that there is a field of type `F` at the same offset
595    /// inside the `S2` type,
596    /// and is at least as public as this `FieldOffset`.
597    ///
598    /// If the `A` type parameter is [`Aligned`],
599    /// then the field [must be aligned](#alignment-guidelines)
600    ///
601    /// # Example
602    ///
603    /// ```rust
604    /// # #![deny(safe_packed_borrows)]
605    /// use repr_offset::FieldOffset;
606    /// use repr_offset::for_examples::ReprC;
607    ///
608    /// let this = Wrapper(ReprC{
609    ///     a: false,
610    ///     b: 3u8,
611    ///     c: Some('5'),
612    ///     d: [8u32, 13u32],
613    /// });
614    ///
615    /// assert_eq!( cast_offset(ReprC::OFFSET_A).get(&this), &false );
616    /// assert_eq!( cast_offset(ReprC::OFFSET_B).get(&this), &3u8 );
617    /// assert_eq!( cast_offset(ReprC::OFFSET_C).get(&this), &Some('5') );
618    /// assert_eq!( cast_offset(ReprC::OFFSET_D).get(&this), &[8u32, 13u32] );
619    ///
620    ///
621    /// #[repr(transparent)]
622    /// pub struct Wrapper<T>(pub T);
623    ///
624    /// pub const fn cast_offset<T,F,A>(offset: FieldOffset<T,F,A>) -> FieldOffset<Wrapper<T>,F,A>{
625    ///     // safety: This case is safe because this is a
626    ///     // `#[repr(transparent)]` wrapper around `T`
627    ///     // where `T` is a public field in the wrapper
628    ///     unsafe{ offset.cast_struct() }
629    /// }
630    ///
631    ///
632    ///
633    /// ```
634    ///
635    /// [`Aligned`]: ./alignment/struct.Aligned.html
636    /// [`Unaligned`]: ./alignment/struct.Unaligned.html
637    #[inline(always)]
638    pub const unsafe fn cast_struct<S2>(self) -> FieldOffset<S2, F, A> {
639        FieldOffset::new(self.offset)
640    }
641
642    /// Changes the `F` type parameter.
643    ///
644    /// # Safety
645    ///
646    /// Callers must ensure that the `F2` type is compatible with the `F` type,
647    /// including size,alignment, and internal layout.
648    ///
649    /// If the `F` type encodes an invariant,
650    /// then callers must ensure that if the field is used as the `F` type
651    /// (including the destructor for the type)
652    /// that the invariants for that type must be upheld.
653    ///
654    /// The same applies if the field is used as the `F2` type
655    /// (if the returned FieldOffset isn't used,then it would not be used as the `F2` type)
656    ///
657    /// # Example
658    ///
659    /// ```rust
660    /// # #![deny(safe_packed_borrows)]
661    ///
662    /// use repr_offset::{Aligned, FieldOffset};
663    /// use repr_offset::for_examples::ReprC;
664    ///
665    /// type This = ReprC<u8, u64, (), ()>;
666    ///
667    /// let this: This = ReprC{ a: 3, b: 5, c: (), d: () };
668    ///
669    /// unsafe{
670    ///     assert_eq!( This::OFFSET_A.cast_field::<i8>().get(&this), &3i8 );
671    ///     assert_eq!( This::OFFSET_B.cast_field::<i64>().get(&this), &5i64 );
672    /// }
673    ///
674    /// ```
675    /// [safe and valid]:
676    /// https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#validity-and-safety-invariant
677    #[inline(always)]
678    pub const unsafe fn cast_field<F2>(self) -> FieldOffset<S, F2, A> {
679        FieldOffset::new(self.offset)
680    }
681
682    /// Changes this `FieldOffset` to be for a (potentially) unaligned field.
683    ///
684    /// This is useful if you want to get a nested field from an unaligned pointer to a
685    /// `#[repr(C)]`/`#[repr(C,align())]` struct.
686    ///
687    /// # Example
688    ///
689    /// This example demonstrates how you can copy a field
690    /// from an unaligned pointer to a `#[repr(C)]` struct.
691    ///
692    /// ```rust
693    /// # #![deny(safe_packed_borrows)]
694    /// use repr_offset::for_examples::{ReprC, ReprPacked};
695    ///
696    /// type Inner = ReprC<usize, &'static str>;
697    /// type Outer = ReprPacked<u8, Inner>;
698    ///
699    /// let inner = ReprC { a: 3, b: "5", c: (), d: () };
700    /// let outer: Outer = ReprPacked{ a: 21, b: inner, c: (), d: () };
701    ///
702    /// let inner_ptr: *const Inner = Outer::OFFSET_B.get_ptr(&outer);
703    /// unsafe{
704    ///     assert_eq!( Inner::OFFSET_A.to_unaligned().read_copy(inner_ptr), 3 );
705    ///     assert_eq!( Inner::OFFSET_B.to_unaligned().read_copy(inner_ptr), "5" );
706    ///
707    ///     // This is undefined behavior,
708    ///     // because ReprC's FieldOFfsets require the pointer to be aligned.
709    ///     //
710    ///     // assert_eq!( Inner::OFFSET_A.read_copy(inner_ptr), 3 );
711    ///     // assert_eq!( Inner::OFFSET_B.read_copy(inner_ptr), "5" );
712    /// }
713    ///
714    /// ```
715    ///
716    #[inline(always)]
717    pub const fn to_unaligned(self) -> FieldOffset<S, F, Unaligned> {
718        FieldOffset {
719            offset: self.offset,
720            tys: FOGhosts::NEW,
721        }
722    }
723
724    /// Changes this `FieldOffset` to be for an aligned field.
725    ///
726    /// # Safety
727    ///
728    /// Callers must ensure that [the field is aligned](#alignment-guidelines)
729    /// within the `S` type.
730    ///
731    /// # Example
732    ///
733    /// ```rust
734    /// # #![deny(safe_packed_borrows)]
735    /// use repr_offset::{Aligned, FieldOffset, Unaligned};
736    ///
737    /// // ReprPacked2 is aligned to 2 bytes.
738    /// use repr_offset::for_examples::ReprPacked2;
739    ///
740    /// type This = ReprPacked2<u8, u16, (), ()>;
741    ///
742    /// let _: FieldOffset<This, u8, Unaligned> = This::OFFSET_A;
743    /// let _: FieldOffset<This, u16, Unaligned> = This::OFFSET_B;
744    ///
745    /// let this: This = ReprPacked2{ a: 89, b: 144, c: (), d: () };
746    ///
747    /// unsafe{
748    ///     assert_eq!( This::OFFSET_A.to_aligned().get(&this), &89 );
749    ///     assert_eq!( This::OFFSET_B.to_aligned().get(&this), &144 );
750    /// }
751    /// ```
752    #[inline(always)]
753    pub const unsafe fn to_aligned(self) -> FieldOffset<S, F, Aligned> {
754        FieldOffset::new(self.offset)
755    }
756}
757
758impl<S, F> FieldOffset<S, F, Aligned> {
759    /// Gets a reference to the field that this is an offset for.
760    ///
761    /// # Example
762    ///
763    /// ```rust
764    /// # #![deny(safe_packed_borrows)]
765    /// use repr_offset::for_examples::ReprC;
766    ///
767    /// let this = ReprC{ a: '@', b: 21u8, c: (), d: () };
768    ///
769    /// assert_eq!( ReprC::OFFSET_A.get(&this), &'@' );
770    /// assert_eq!( ReprC::OFFSET_B.get(&this), &21u8 );
771    ///
772    /// ```
773    #[inline(always)]
774    pub fn get(self, base: &S) -> &F {
775        unsafe { impl_fo!(fn get<S, F, Aligned>(self, base)) }
776    }
777
778    /// Gets a mutable reference to the field that this is an offset for.
779    ///
780    /// # Example
781    ///
782    /// ```rust
783    /// # #![deny(safe_packed_borrows)]
784    /// use repr_offset::for_examples::ReprC;
785    ///
786    /// let mut this = ReprC{ a: "what", b: '?', c: (), d: () };
787    ///
788    /// assert_eq!( ReprC::OFFSET_A.get_mut(&mut this), &mut "what" );
789    /// assert_eq!( ReprC::OFFSET_B.get_mut(&mut this), &mut '?' );
790    ///
791    /// ```
792    #[inline(always)]
793    pub fn get_mut(self, base: &mut S) -> &mut F {
794        unsafe { impl_fo!(fn get_mut<S, F, Aligned>(self, base)) }
795    }
796
797    /// Copies the aligned field that this is an offset for.
798    ///
799    /// # Example
800    ///
801    /// ```rust
802    /// # #![deny(safe_packed_borrows)]
803    /// use repr_offset::for_examples::ReprC;
804    ///
805    /// let this = ReprC{ a: Some(false), b: [8i32, 13, 21], c: (), d: () };
806    ///
807    /// assert_eq!( ReprC::OFFSET_A.get_copy(&this), Some(false) );
808    /// assert_eq!( ReprC::OFFSET_B.get_copy(&this), [8i32, 13, 21] );
809    ///
810    /// ```
811    ///
812    /// This method can't be called for non-Copy fields.
813    /// ```compile_fail
814    /// # #![deny(safe_packed_borrows)]
815    /// use repr_offset::for_examples::ReprC;
816    ///
817    /// let this = ReprC{ a: vec![0, 1, 2, 3], b: (), c: (), d: () };
818    ///
819    /// let _ = ReprC::OFFSET_A.get_copy(&this);
820    /// ```
821    #[inline(always)]
822    pub fn get_copy(self, base: &S) -> F
823    where
824        F: Copy,
825    {
826        unsafe { impl_fo!(fn get_copy<S, F, Aligned>(self, base)) }
827    }
828}
829
830impl<S, F, A> FieldOffset<S, F, A> {
831    /// Gets a raw pointer to a field from a reference to the `S` struct.
832    ///
833    /// # Example
834    ///
835    /// ```rust
836    /// # #![deny(safe_packed_borrows)]
837    /// use repr_offset::FieldOffset;
838    /// use repr_offset::for_examples::ReprPacked;
839    ///
840    /// let this = ReprPacked{ a: 3u8, b: 5u16, c: (), d: () };
841    ///
842    /// let ptr_a = ReprPacked::OFFSET_A.get_ptr(&this);
843    /// // A `u8` is always aligned,so a `.read()` is fine.
844    /// assert_eq!( unsafe{ ptr_a.read() }, 3u8 );
845    ///
846    /// let ptr_b = ReprPacked::OFFSET_B.get_ptr(&this);
847    /// // ReprPacked has an alignment of 1,
848    /// // so this u16 field has to be copied with `.read_unaligned()`.
849    /// assert_eq!( unsafe{ ptr_b.read_unaligned() }, 5u16 );
850    ///
851    /// ```
852    #[inline(always)]
853    pub fn get_ptr(self, base: &S) -> *const F {
854        unsafe { impl_fo!(fn get_ptr<S, F, A>(self, base)) }
855    }
856
857    /// Gets a mutable raw pointer to a field from a mutable reference to the `S` struct.
858    ///
859    /// # Example
860    ///
861    /// ```rust
862    /// # #![deny(safe_packed_borrows)]
863    /// use repr_offset::FieldOffset;
864    /// use repr_offset::for_examples::ReprPacked;
865    ///
866    /// let mut this = ReprPacked{ a: 3u8, b: 5u16, c: (), d: () };
867    ///
868    /// let ptr_a = ReprPacked::OFFSET_A.get_mut_ptr(&mut this);
869    /// unsafe{
870    ///     // A `u8` is always aligned,so a `.read()` is fine.
871    ///     assert_eq!( ptr_a.read(), 3u8 );
872    ///     ptr_a.write(103);
873    ///     assert_eq!( ptr_a.read(), 103 );
874    /// }
875    ///
876    /// let ptr_b = ReprPacked::OFFSET_B.get_mut_ptr(&mut this);
877    /// unsafe{
878    ///     // ReprPacked has an alignment of 1,
879    ///     // so this u16 field has to be read with `.read_unaligned()`.
880    ///     assert_eq!( ptr_b.read_unaligned(), 5u16 );
881    ///     ptr_b.write_unaligned(105);
882    ///     assert_eq!( ptr_b.read_unaligned(), 105 );
883    /// }
884    ///
885    /// ```
886    #[inline(always)]
887    pub fn get_mut_ptr(self, base: &mut S) -> *mut F {
888        unsafe { impl_fo!(fn get_mut_ptr<S, F, A>(self, base)) }
889    }
890
891    /// Gets a raw pointer to a field from a pointer to the `S` struct.
892    ///
893    /// # Safety
894    ///
895    /// This has the same safety requirements as the [`<*const T>::offset`] method.
896    ///
897    /// [`<*const T>::offset`]:
898    /// https://doc.rust-lang.org/std/primitive.pointer.html#method.offset
899    ///
900    /// # Example
901    ///
902    /// ```rust
903    /// # #![deny(safe_packed_borrows)]
904    /// use repr_offset::FieldOffset;
905    /// use repr_offset::for_examples::ReprPacked;
906    ///
907    /// let this = ReprPacked{ a: 3u8, b: 5u16, c: (), d: () };
908    ///
909    /// let ptr: *const _ = &this;
910    ///
911    /// unsafe{
912    ///     // A `u8` is always aligned,so a `.read()` is fine.
913    ///     assert_eq!( ReprPacked::OFFSET_A.raw_get(ptr).read(), 3u8 );
914    ///     
915    ///     // ReprPacked has an alignment of 1,
916    ///     // so this u16 field has to be copied with `.read_unaligned()`.
917    ///     assert_eq!( ReprPacked::OFFSET_B.raw_get(ptr).read_unaligned(), 5u16 );
918    /// }
919    ///
920    /// ```
921    #[inline(always)]
922    pub unsafe fn raw_get(self, base: *const S) -> *const F {
923        impl_fo!(fn raw_get<S, F, A>(self, base))
924    }
925
926    /// Gets a mutable raw pointer to a field from a pointer to the `S` struct.
927    ///
928    /// # Safety
929    ///
930    /// This has the same safety requirements as the [`<*mut T>::offset`] method.
931    ///
932    /// [`<*mut T>::offset`]:
933    /// https://doc.rust-lang.org/std/primitive.pointer.html#method.offset-1
934    ///
935    /// # Example
936    ///
937    /// ```rust
938    /// # #![deny(safe_packed_borrows)]
939    /// use repr_offset::FieldOffset;
940    /// use repr_offset::for_examples::ReprPacked;
941    ///
942    /// let mut this = ReprPacked{ a: 3u8, b: 5u16, c: (), d: () };
943    ///
944    /// let ptr: *mut _ = &mut this;
945    ///
946    /// unsafe{
947    ///     let ptr_a = ReprPacked::OFFSET_A.raw_get_mut(ptr);
948    ///
949    ///     // A `u8` is always aligned,so a `.read()` is fine.
950    ///     assert_eq!( ptr_a.read(), 3u8 );
951    ///     ptr_a.write(103);
952    ///     assert_eq!( ptr_a.read(), 103 );
953    ///
954    ///
955    ///     let ptr_b = ReprPacked::OFFSET_B.raw_get_mut(ptr);
956    ///
957    ///     // ReprPacked has an alignment of 1,
958    ///     // so this u16 field has to be read with `.read_unaligned()`.
959    ///     assert_eq!( ptr_b.read_unaligned(), 5u16 );
960    ///     ptr_b.write_unaligned(105);
961    ///     assert_eq!( ptr_b.read_unaligned(), 105 );
962    /// }
963    ///
964    /// ```
965    #[inline(always)]
966    pub unsafe fn raw_get_mut(self, base: *mut S) -> *mut F {
967        impl_fo!(fn raw_get_mut<S, F, A>(self, base))
968    }
969
970    /// Gets a raw pointer to a field from a pointer to the `S` struct.
971    ///
972    /// # Safety
973    ///
974    /// While calling this method is not by itself unsafe,
975    /// using the pointer returned by this method has the same safety requirements
976    /// as the [`<*const T>::wrapping_offset`] method.
977    ///
978    /// [`<*const T>::wrapping_offset`]:
979    /// https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_offset
980    ///
981    /// # Example
982    ///
983    /// ```rust
984    /// # #![deny(safe_packed_borrows)]
985    /// use repr_offset::FieldOffset;
986    /// use repr_offset::for_examples::ReprPacked;
987    ///
988    /// let this = ReprPacked{ a: 3u8, b: 5u16, c: (), d: () };
989    ///
990    /// let ptr_a = ReprPacked::OFFSET_A.wrapping_raw_get(&this);
991    /// // A `u8` is always aligned,so a `.read()` is fine.
992    /// assert_eq!( unsafe{ ptr_a.read() }, 3u8 );
993    ///
994    /// let ptr_b = ReprPacked::OFFSET_B.wrapping_raw_get(&this);
995    /// // ReprPacked has an alignment of 1,
996    /// // so this u16 field has to be copied with `.read_unaligned()`.
997    /// assert_eq!( unsafe{ ptr_b.read_unaligned() }, 5u16 );
998    ///
999    /// ```
1000    #[inline(always)]
1001    pub fn wrapping_raw_get(self, base: *const S) -> *const F {
1002        (base as *const u8).wrapping_offset(self.offset as isize) as *const F
1003    }
1004
1005    /// Gets a mutable raw pointer to a field from a pointer to the `S` struct.
1006    ///
1007    /// # Safety
1008    ///
1009    /// While calling this method is not by itself unsafe,
1010    /// using the pointer returned by this method has the same safety requirements
1011    /// as the [`<*mut T>::wrapping_offset`] method.
1012    ///
1013    /// [`<*mut T>::wrapping_offset`]:
1014    /// https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_offset-1
1015    ///
1016    /// # Example
1017    ///
1018    /// ```rust
1019    /// # #![deny(safe_packed_borrows)]
1020    /// use repr_offset::FieldOffset;
1021    /// use repr_offset::for_examples::ReprPacked;
1022    ///
1023    /// let mut this = ReprPacked{ a: 3u8, b: 5u16, c: (), d: () };
1024    ///
1025    /// let ptr: *mut _ = &mut this;
1026    ///
1027    /// let ptr_a = ReprPacked::OFFSET_A.wrapping_raw_get_mut(ptr);
1028    /// unsafe{
1029    ///
1030    ///     // A `u8` is always aligned,so a `.read()` is fine.
1031    ///     assert_eq!( ptr_a.read(), 3u8 );
1032    ///     ptr_a.write(103);
1033    ///     assert_eq!( ptr_a.read(), 103 );
1034    /// }
1035    ///
1036    /// let ptr_b = ReprPacked::OFFSET_B.wrapping_raw_get_mut(ptr);
1037    /// unsafe{
1038    ///
1039    ///     // ReprPacked has an alignment of 1,
1040    ///     // so this u16 field has to be read with `.read_unaligned()`.
1041    ///     assert_eq!( ptr_b.read_unaligned(), 5u16 );
1042    ///     ptr_b.write_unaligned(105);
1043    ///     assert_eq!( ptr_b.read_unaligned(), 105 );
1044    /// }
1045    ///
1046    /// ```
1047    #[inline(always)]
1048    pub fn wrapping_raw_get_mut(self, base: *mut S) -> *mut F {
1049        (base as *mut u8).wrapping_offset(self.offset as isize) as *mut F
1050    }
1051}
1052
1053impl<S, F> FieldOffset<S, F, Aligned> {
1054    /// Copies the aligned field that this is an offset for.
1055    ///
1056    /// # Safety
1057    ///
1058    /// This function has the same safety requirements as
1059    /// [`std::ptr::read`](https://doc.rust-lang.org/std/ptr/fn.read.html).
1060    ///
1061    /// Those safety requirements only apply to the field that this is an offset for,
1062    /// fields after it or before it don't need to be valid to call this method.
1063    ///
1064    /// # Example
1065    ///
1066    /// ```rust
1067    /// # #![deny(safe_packed_borrows)]
1068    /// use repr_offset::for_examples::ReprC;
1069    ///
1070    /// let this = ReprC{ a: 10u8, b: "20", c: (), d: () };
1071    ///
1072    /// let ptr: *const _ = &this;
1073    /// unsafe{
1074    ///     assert_eq!( ReprC::OFFSET_A.read_copy(ptr), 10u8 );
1075    ///     assert_eq!( ReprC::OFFSET_B.read_copy(ptr), "20" );
1076    /// }
1077    /// ```
1078    ///
1079    /// This method can't be called for non-Copy fields.
1080    /// ```compile_fail
1081    /// # #![deny(safe_packed_borrows)]
1082    /// use repr_offset::for_examples::ReprC;
1083    ///
1084    /// let this = ReprC{ a: vec![0, 1, 2, 3], b: (), c: (), d: () };
1085    /// unsafe{
1086    ///     let _ = ReprC::OFFSET_A.read_copy(&this);
1087    /// }
1088    /// ```
1089    ///
1090    #[inline(always)]
1091    pub unsafe fn read_copy(self, base: *const S) -> F
1092    where
1093        F: Copy,
1094    {
1095        impl_fo!(fn read_copy<S, F, Aligned>(self, base))
1096    }
1097
1098    /// Reads the value from the field in `source` without moving it.
1099    ///
1100    /// # Safety
1101    ///
1102    /// This function has the same safety requirements as
1103    /// [`std::ptr::read`](https://doc.rust-lang.org/std/ptr/fn.read.html).
1104    ///
1105    /// Those safety requirements only apply to the field that this is an offset for,
1106    /// fields after it or before it don't need to be valid to call this method.
1107    ///
1108    /// # Example
1109    ///
1110    /// ```rust
1111    /// # #![deny(safe_packed_borrows)]
1112    /// use repr_offset::for_examples::ReprC;
1113    ///
1114    /// use std::mem::ManuallyDrop;
1115    ///
1116    /// let this = ManuallyDrop::new(ReprC{
1117    ///     a: vec![0, 1, 2],
1118    ///     b: "20".to_string(),
1119    ///     c: (),
1120    ///     d: (),
1121    /// });
1122    ///
1123    /// let ptr: *const _ = &*this;
1124    /// unsafe{
1125    ///     assert_eq!( ReprC::OFFSET_A.read(ptr), vec![0, 1, 2] );
1126    ///     assert_eq!( ReprC::OFFSET_B.read(ptr), "20".to_string() );
1127    /// }
1128    ///
1129    /// ```
1130    #[inline(always)]
1131    pub unsafe fn read(self, source: *const S) -> F {
1132        impl_fo!(fn read<S, F, Aligned>(self, source))
1133    }
1134
1135    /// Writes `value` ìnto the field in `destination` without dropping the old value of the field.
1136    ///
1137    /// This allows uninitialized fields to be initialized,since doing
1138    /// `*OFFSET_FOO.raw_get_mut(ptr) = value;` would drop uninitialized memory.
1139    ///
1140    /// # Safety
1141    ///
1142    /// This function has the same safety requirements as
1143    /// [`std::ptr::write`](https://doc.rust-lang.org/std/ptr/fn.write.html).
1144    ///
1145    /// Those safety requirements only apply to the field that this is an offset for,
1146    /// fields after it or before it don't need to be valid to call this method.
1147    ///
1148    /// # Example
1149    ///
1150    /// ```rust
1151    /// # #![deny(safe_packed_borrows)]
1152    /// use repr_offset::for_examples::ReprC;
1153    ///
1154    /// let mut this = ReprC{ a: 10u8, b: "20", c: (), d: () };
1155    ///
1156    /// let ptr: *mut _ = &mut this;
1157    /// unsafe{
1158    ///     ReprC::OFFSET_A.write(ptr, 13u8);
1159    ///     ReprC::OFFSET_B.write(ptr, "21");
1160    /// }
1161    /// assert_eq!( this.a, 13u8 );
1162    /// assert_eq!( this.b, "21" );
1163    ///
1164    /// ```
1165    #[inline(always)]
1166    pub unsafe fn write(self, destination: *mut S, value: F) {
1167        impl_fo!(fn write<S, F, Aligned>(self, destination, value))
1168    }
1169
1170    /// Copies the field in `source` into `destination`.
1171    ///
1172    /// # Safety
1173    ///
1174    /// This function has the same safety requirements as
1175    /// [`std::ptr::copy`](https://doc.rust-lang.org/std/ptr/fn.copy.html).
1176    ///
1177    /// Those safety requirements only apply to the field that this is an offset for,
1178    /// fields after it or before it don't need to be valid to call this method.
1179    ///
1180    /// # Example
1181    ///
1182    /// ```rust
1183    /// # #![deny(safe_packed_borrows)]
1184    /// use repr_offset::for_examples::ReprC;
1185    ///
1186    /// let this = ReprC{ a: 10u8, b: "20", c: (), d: () };
1187    /// let mut other = ReprC{ a: 0u8, b: "", c: (), d: () };
1188    ///
1189    /// let this_ptr: *const _ = &this;
1190    /// let other_ptr: *mut _ = &mut other;
1191    /// unsafe{
1192    ///     ReprC::OFFSET_A.copy(this_ptr, other_ptr);
1193    ///     ReprC::OFFSET_B.copy(this_ptr, other_ptr);
1194    /// }
1195    /// assert_eq!( this.a, 10u8 );
1196    /// assert_eq!( this.b, "20" );
1197    ///
1198    /// assert_eq!( other.a, 10u8 );
1199    /// assert_eq!( other.b, "20" );
1200    ///
1201    /// ```
1202    #[inline(always)]
1203    pub unsafe fn copy(self, source: *const S, destination: *mut S) {
1204        impl_fo!(fn copy<S, F, Aligned>(self, source, destination))
1205    }
1206
1207    /// Copies the field in `source` into `destination`,
1208    /// `source` and `destination` must not overlap.
1209    ///
1210    /// # Safety
1211    ///
1212    /// This function has the same safety requirements as
1213    /// [`std::ptr::copy_nonoverlapping`
1214    /// ](https://doc.rust-lang.org/std/ptr/fn.copy_nonoverlapping.html).
1215    ///
1216    /// Those safety requirements only apply to the field that this is an offset for,
1217    /// fields after it or before it don't need to be valid to call this method.
1218    ///
1219    /// # Example
1220    ///
1221    /// ```rust
1222    /// # #![deny(safe_packed_borrows)]
1223    /// use repr_offset::for_examples::ReprC;
1224    ///
1225    /// let this = ReprC{ a: '#', b: 81, c: (), d: () };
1226    /// let mut other = ReprC{ a: '_', b: 0, c: (), d: () };
1227    ///
1228    /// let this_ptr: *const _ = &this;
1229    /// let other_ptr: *mut _ = &mut other;
1230    /// unsafe{
1231    ///     ReprC::OFFSET_A.copy_nonoverlapping(this_ptr, other_ptr);
1232    ///     ReprC::OFFSET_B.copy_nonoverlapping(this_ptr, other_ptr);
1233    /// }
1234    /// assert_eq!( this.a, '#' );
1235    /// assert_eq!( this.b, 81 );
1236    ///
1237    /// assert_eq!( other.a, '#' );
1238    /// assert_eq!( other.b, 81 );
1239    ///
1240    /// ```
1241    #[inline(always)]
1242    pub unsafe fn copy_nonoverlapping(self, source: *const S, destination: *mut S) {
1243        impl_fo!(fn copy_nonoverlapping<S, F, Aligned>(self, source, destination))
1244    }
1245
1246    /// Replaces the value of a field in `destination` with `value`,
1247    /// returning the old value of the field.
1248    ///
1249    /// # Safety
1250    ///
1251    /// This function has the same safety requirements as
1252    /// [`std::ptr::replace`](https://doc.rust-lang.org/std/ptr/fn.replace.html).
1253    ///
1254    /// Those safety requirements only apply to the field that this is an offset for,
1255    /// fields after it or before it don't need to be valid to call this method.
1256    ///
1257    /// # Example
1258    ///
1259    /// ```rust
1260    /// # #![deny(safe_packed_borrows)]
1261    /// use repr_offset::for_examples::ReprC;
1262    ///
1263    /// let mut this = ReprC{ a: [0u8, 1], b: false, c: (), d: () };
1264    ///
1265    /// let ptr: *mut _ = &mut this;
1266    /// unsafe{
1267    ///     assert_eq!( ReprC::OFFSET_A.replace(ptr, [2, 3]), [0u8, 1] );
1268    ///     assert_eq!( ReprC::OFFSET_B.replace(ptr, true), false );
1269    /// }
1270    ///
1271    /// assert_eq!( this.a, [2u8, 3] );
1272    /// assert_eq!( this.b, true );
1273    ///
1274    /// ```
1275    #[inline(always)]
1276    pub unsafe fn replace(self, destination: *mut S, value: F) -> F {
1277        impl_fo!(fn replace<S, F, Aligned>(self, destination, value))
1278    }
1279
1280    /// Replaces the value of a field in `destination` with `value`,
1281    /// returning the old value of the field.
1282    ///
1283    /// # Example
1284    ///
1285    /// ```rust
1286    /// # #![deny(safe_packed_borrows)]
1287    /// use repr_offset::for_examples::ReprC;
1288    ///
1289    /// let mut this = ReprC{ a: [0u8, 1], b: false, c: (), d: () };
1290    ///
1291    /// assert_eq!( ReprC::OFFSET_A.replace_mut(&mut this, [2, 3]), [0u8, 1] );
1292    /// assert_eq!( ReprC::OFFSET_B.replace_mut(&mut this, true), false );
1293    ///
1294    /// assert_eq!( this.a, [2u8, 3] );
1295    /// assert_eq!( this.b, true );
1296    ///
1297    /// ```
1298    #[inline(always)]
1299    pub fn replace_mut(self, destination: &mut S, value: F) -> F {
1300        unsafe { impl_fo!(fn replace_mut<S, F, Aligned>(self, destination, value)) }
1301    }
1302
1303    /// Swaps the values of a field between the `left` and `right` pointers.
1304    ///
1305    /// # Safety
1306    ///
1307    /// This function has the same safety requirements as
1308    /// [`std::ptr::swap`](https://doc.rust-lang.org/std/ptr/fn.swap.html).
1309    ///
1310    /// Those safety requirements only apply to the field that this is an offset for,
1311    /// fields after it or before it don't need to be valid to call this method.
1312    ///
1313    /// # Example
1314    ///
1315    /// ```rust
1316    /// # #![deny(safe_packed_borrows)]
1317    /// use repr_offset::for_examples::ReprC;
1318    ///
1319    /// let mut this = ReprC{ a: '=', b: 64u16, c: (), d: () };
1320    /// let mut other = ReprC{ a: '!', b: 255u16, c: (), d: () };
1321    ///
1322    /// let this_ptr: *mut _ = &mut this;
1323    /// let other_ptr: *mut _ = &mut other;
1324    /// unsafe{
1325    ///     ReprC::OFFSET_A.swap(this_ptr, other_ptr);
1326    ///     ReprC::OFFSET_B.swap(this_ptr, other_ptr);
1327    /// }
1328    /// assert_eq!( this.a, '!' );
1329    /// assert_eq!( this.b, 255 );
1330    ///
1331    /// assert_eq!( other.a, '=' );
1332    /// assert_eq!( other.b, 64 );
1333    ///
1334    /// ```
1335    #[inline(always)]
1336    pub unsafe fn swap(self, left: *mut S, right: *mut S) {
1337        impl_fo!(fn swap<S, F, Aligned>(self, left, right))
1338    }
1339
1340    /// Swaps the values of a field between the `left` and `right` non-overlapping pointers.
1341    ///
1342    /// # Safety
1343    ///
1344    /// This function has the same safety requirements as
1345    /// [`std::ptr::swap_nonoverlapping`
1346    /// ](https://doc.rust-lang.org/std/ptr/fn.swap_nonoverlapping.html).
1347    ///
1348    /// Those safety requirements only apply to the field that this is an offset for,
1349    /// fields after it or before it don't need to be valid to call this method.
1350    ///
1351    /// # Example
1352    ///
1353    /// ```rust
1354    /// # #![deny(safe_packed_borrows)]
1355    /// use repr_offset::for_examples::ReprC;
1356    ///
1357    /// let mut this = ReprC{ a: [false, true], b: &27u32, c: (), d: () };
1358    /// let mut other = ReprC{ a: [true, false], b: &81u32, c: (), d: () };
1359    ///
1360    /// let this_ptr: *mut _ = &mut this;
1361    /// let other_ptr: *mut _ = &mut other;
1362    /// unsafe{
1363    ///     ReprC::OFFSET_A.swap_nonoverlapping(this_ptr, other_ptr);
1364    ///     ReprC::OFFSET_B.swap_nonoverlapping(this_ptr, other_ptr);
1365    /// }
1366    /// assert_eq!( this.a, [true, false] );
1367    /// assert_eq!( this.b, &81 );
1368    ///
1369    /// assert_eq!( other.a, [false, true] );
1370    /// assert_eq!( other.b, &27 );
1371    ///
1372    /// ```
1373    ///
1374    #[inline(always)]
1375    pub unsafe fn swap_nonoverlapping(self, left: *mut S, right: *mut S) {
1376        impl_fo!(fn swap_nonoverlapping<S, F, Aligned>(self, left, right))
1377    }
1378
1379    /// Swaps the values of a field between `left` and `right`.
1380    ///
1381    /// # Example
1382    ///
1383    /// ```rust
1384    /// # #![deny(safe_packed_borrows)]
1385    /// use repr_offset::for_examples::ReprC;
1386    ///
1387    /// let mut this = ReprC{ a: [true, true], b: 0x0Fu8, c: (), d: () };
1388    /// let mut other = ReprC{ a: [false, false], b: 0xF0u8, c: (), d: () };
1389    ///
1390    /// ReprC::OFFSET_A.swap_mut(&mut this, &mut other);
1391    /// ReprC::OFFSET_B.swap_mut(&mut this, &mut other);
1392    ///
1393    /// assert_eq!( this.a, [false, false] );
1394    /// assert_eq!( this.b, 0xF0u8 );
1395    ///
1396    /// assert_eq!( other.a, [true, true] );
1397    /// assert_eq!( other.b, 0x0Fu8 );
1398    ///
1399    /// ```
1400    ///
1401    #[inline(always)]
1402    pub fn swap_mut(self, left: &mut S, right: &mut S) {
1403        unsafe { impl_fo!(fn swap_mut<S, F, Aligned>(self, left, right)) }
1404    }
1405}
1406
1407impl<S, F> FieldOffset<S, F, Unaligned> {
1408    /// Copies the unaligned field that this is an offset for.
1409    ///
1410    /// # Example
1411    ///
1412    /// ```rust
1413    /// # #![deny(safe_packed_borrows)]
1414    /// use repr_offset::for_examples::ReprPacked;
1415    ///
1416    /// let this = ReprPacked{ a: Some(false), b: [8i32, 13, 21], c: (), d: () };
1417    ///
1418    /// assert_eq!( ReprPacked::OFFSET_A.get_copy(&this), Some(false) );
1419    /// assert_eq!( ReprPacked::OFFSET_B.get_copy(&this), [8i32, 13, 21] );
1420    ///
1421    /// ```
1422    ///
1423    /// This method can't be called for non-Copy fields.
1424    /// ```compile_fail
1425    /// # #![deny(safe_packed_borrows)]
1426    /// use repr_offset::for_examples::ReprPacked;
1427    ///
1428    /// let this = ReprPacked{ a: vec![0, 1, 2], b: (), c: (), d: () };
1429    ///
1430    /// let _ = ReprPacked::OFFSET_A.get_copy(&this);
1431    ///
1432    /// ```
1433    #[inline(always)]
1434    pub fn get_copy(self, base: &S) -> F
1435    where
1436        F: Copy,
1437    {
1438        unsafe { impl_fo!(fn get_copy<S, F, Unaligned>(self, base)) }
1439    }
1440
1441    /// Copies the unaligned field that this is an offset for.
1442    ///
1443    /// # Safety
1444    ///
1445    /// This function has the same safety requirements as
1446    /// [`std::ptr::read_unaligned`](https://doc.rust-lang.org/std/ptr/fn.read_unaligned.html).
1447    ///
1448    /// Those safety requirements only apply to the field that this is an offset for,
1449    /// fields after it or before it don't need to be valid to call this method.
1450    ///
1451    /// # Example
1452    ///
1453    /// ```rust
1454    /// # #![deny(safe_packed_borrows)]
1455    /// use repr_offset::for_examples::ReprPacked;
1456    ///
1457    /// let this = ReprPacked{ a: 10u8, b: "20", c: (), d: () };
1458    ///
1459    /// let ptr: *const _ = &this;
1460    /// unsafe{
1461    ///     assert_eq!( ReprPacked::OFFSET_A.read_copy(ptr), 10u8 );
1462    ///     assert_eq!( ReprPacked::OFFSET_B.read_copy(ptr), "20" );
1463    /// }
1464    /// ```
1465    ///
1466    /// This method can't be called for non-Copy fields.
1467    /// ```compile_fail
1468    /// # #![deny(safe_packed_borrows)]
1469    /// use repr_offset::for_examples::ReprPacked;
1470    ///
1471    /// let this = ReprPacked{ a: vec![0, 1, 2], b: "20", c: (), d: () };
1472    ///
1473    /// unsafe{
1474    ///     let _ = ReprPacked::OFFSET_A.read_copy(&this);
1475    /// }
1476    /// ```
1477    #[inline(always)]
1478    pub unsafe fn read_copy(self, base: *const S) -> F
1479    where
1480        F: Copy,
1481    {
1482        impl_fo!(fn read_copy<S, F, Unaligned>(self, base))
1483    }
1484
1485    /// Reads the value from the field in `source` without moving it.
1486    ///
1487    /// # Safety
1488    ///
1489    /// This function has the same safety requirements as
1490    /// [`std::ptr::read_unaligned`](https://doc.rust-lang.org/std/ptr/fn.read_unaligned.html).
1491    ///
1492    /// Those safety requirements only apply to the field that this is an offset for,
1493    /// fields after it or before it don't need to be valid to call this method.
1494    ///
1495    /// # Example
1496    ///
1497    /// ```rust
1498    /// # #![deny(safe_packed_borrows)]
1499    /// use repr_offset::for_examples::ReprPacked;
1500    ///
1501    /// use std::mem::ManuallyDrop;
1502    ///
1503    /// let this = ManuallyDrop::new(ReprPacked{
1504    ///     a: vec![0, 1, 2],
1505    ///     b: "20".to_string(),
1506    ///     c: (),
1507    ///     d: (),
1508    /// });
1509    ///
1510    /// let ptr: *const _ = &*this;
1511    /// unsafe{
1512    ///     assert_eq!( ReprPacked::OFFSET_A.read(ptr), vec![0, 1, 2] );
1513    ///     assert_eq!( ReprPacked::OFFSET_B.read(ptr), "20".to_string() );
1514    /// }
1515    ///
1516    /// ```
1517    #[inline(always)]
1518    pub unsafe fn read(self, source: *const S) -> F {
1519        impl_fo!(fn read<S, F, Unaligned>(self, source))
1520    }
1521
1522    /// Writes `value` ìnto the field in `source` without dropping the old value of the field.
1523    ///
1524    /// # Safety
1525    ///
1526    /// This function has the same safety requirements as
1527    /// [`std::ptr::write_unaligned`](https://doc.rust-lang.org/std/ptr/fn.write_unaligned.html).
1528    ///
1529    /// Those safety requirements only apply to the field that this is an offset for,
1530    /// fields after it or before it don't need to be valid to call this method.
1531    ///
1532    ///
1533    /// # Example
1534    ///
1535    /// ```rust
1536    /// # #![deny(safe_packed_borrows)]
1537    /// use repr_offset::for_examples::ReprPacked;
1538    /// use repr_offset::utils::moved;
1539    ///
1540    /// let mut this = ReprPacked{ a: 10u8, b: "20", c: (), d: () };
1541    ///
1542    /// let ptr: *mut _ = &mut this;
1543    /// unsafe{
1544    ///     ReprPacked::OFFSET_A.write(ptr, 13u8);
1545    ///     ReprPacked::OFFSET_B.write(ptr, "21");
1546    /// }
1547    /// assert_eq!( moved(this.a), 13u8 );
1548    /// assert_eq!( moved(this.b), "21" );
1549    ///
1550    /// ```
1551    #[inline(always)]
1552    pub unsafe fn write(self, source: *mut S, value: F) {
1553        impl_fo!(fn write<S, F, Unaligned>(self, source, value))
1554    }
1555
1556    /// Copies the field in `source` into `destination`.
1557    ///
1558    /// # Safety
1559    ///
1560    /// This function has the same safety requirements as
1561    /// [`std::ptr::copy`](https://doc.rust-lang.org/std/ptr/fn.copy.html),
1562    /// except that `source` and `destination` do not need to be properly aligned.
1563    ///
1564    /// Those safety requirements only apply to the field that this is an offset for,
1565    /// fields after it or before it don't need to be valid to call this method.
1566    ///
1567    /// # Example
1568    ///
1569    /// ```rust
1570    /// # #![deny(safe_packed_borrows)]
1571    /// use repr_offset::for_examples::ReprPacked;
1572    /// use repr_offset::utils::moved;
1573    ///
1574    ///
1575    /// let this = ReprPacked{ a: 10u8, b: "20", c: (), d: () };
1576    /// let mut other = ReprPacked{ a: 0u8, b: "", c: (), d: () };
1577    ///
1578    /// let this_ptr: *const _ = &this;
1579    /// let other_ptr: *mut _ = &mut other;
1580    /// unsafe{
1581    ///     ReprPacked::OFFSET_A.copy(this_ptr, other_ptr);
1582    ///     ReprPacked::OFFSET_B.copy(this_ptr, other_ptr);
1583    /// }
1584    /// assert_eq!( moved(this.a), 10u8 );
1585    /// assert_eq!( moved(this.b), "20" );
1586    ///
1587    /// assert_eq!( moved(other.a), 10u8 );
1588    /// assert_eq!( moved(other.b), "20" );
1589    ///
1590    /// ```
1591    #[inline(always)]
1592    pub unsafe fn copy(self, source: *const S, destination: *mut S) {
1593        impl_fo!(fn copy<S, F, Unaligned>(self, source, destination))
1594    }
1595
1596    /// Copies the field in `source` into `destination`,
1597    /// `source` and `destination` must not overlap.
1598    ///
1599    /// # Safety
1600    ///
1601    /// This function has the same safety requirements as
1602    /// [`std::ptr::copy_nonoverlapping`
1603    /// ](https://doc.rust-lang.org/std/ptr/fn.copy_nonoverlapping.html),
1604    /// except that `source` and `destination` do not need to be properly aligned.
1605    ///
1606    /// Those safety requirements only apply to the field that this is an offset for,
1607    /// fields after it or before it don't need to be valid to call this method.
1608    ///
1609    /// # Example
1610    ///
1611    /// ```rust
1612    /// # #![deny(safe_packed_borrows)]
1613    /// use repr_offset::for_examples::ReprPacked;
1614    /// use repr_offset::utils::moved;
1615    ///
1616    /// let this = ReprPacked{ a: '#', b: 81, c: (), d: () };
1617    /// let mut other = ReprPacked{ a: '_', b: 0, c: (), d: () };
1618    ///
1619    /// let this_ptr: *const _ = &this;
1620    /// let other_ptr: *mut _ = &mut other;
1621    /// unsafe{
1622    ///     ReprPacked::OFFSET_A.copy_nonoverlapping(this_ptr, other_ptr);
1623    ///     ReprPacked::OFFSET_B.copy_nonoverlapping(this_ptr, other_ptr);
1624    /// }
1625    /// assert_eq!( moved(this.a), '#' );
1626    /// assert_eq!( moved(this.b), 81 );
1627    ///
1628    /// assert_eq!( moved(other.a), '#' );
1629    /// assert_eq!( moved(other.b), 81 );
1630    ///
1631    /// ```
1632    #[inline(always)]
1633    pub unsafe fn copy_nonoverlapping(self, source: *const S, destination: *mut S) {
1634        impl_fo!(fn copy_nonoverlapping<S, F, Unaligned>(self, source, destination))
1635    }
1636}
1637
1638impl<S, F> FieldOffset<S, F, Unaligned> {
1639    /// Replaces the value of a field in `dest` with `value`,
1640    /// returning the old value of the field.
1641    ///
1642    /// # Safety
1643    ///
1644    /// This function has the same safety requirements as
1645    /// [`std::ptr::replace`](https://doc.rust-lang.org/std/ptr/fn.replace.html),
1646    /// except that `dest` does not need to be properly aligned.
1647    ///
1648    /// Those safety requirements only apply to the field that this is an offset for,
1649    /// fields after it or before it don't need to be valid to call this method.
1650    ///
1651    /// # Example
1652    ///
1653    /// ```rust
1654    /// # #![deny(safe_packed_borrows)]
1655    /// use repr_offset::for_examples::ReprPacked;
1656    /// use repr_offset::utils::moved;
1657    ///
1658    /// let mut this = ReprPacked{ a: [0u8, 1], b: false, c: (), d: () };
1659    ///
1660    /// let ptr: *mut _ = &mut this;
1661    /// unsafe{
1662    ///     assert_eq!( ReprPacked::OFFSET_A.replace(ptr, [2, 3]), [0u8, 1] );
1663    ///     assert_eq!( ReprPacked::OFFSET_B.replace(ptr, true), false );
1664    /// }
1665    ///
1666    /// assert_eq!( moved(this.a), [2u8, 3] );
1667    /// assert_eq!( moved(this.b), true );
1668    ///
1669    /// ```
1670    #[inline(always)]
1671    pub unsafe fn replace(self, dest: *mut S, value: F) -> F {
1672        impl_fo!(fn replace<S, F, Unaligned>(self, dest, value))
1673    }
1674
1675    /// Replaces the value of a field in `dest` with `value`,
1676    /// returning the old value of the field.
1677    ///
1678    ///
1679    /// # Example
1680    ///
1681    /// ```rust
1682    /// # #![deny(safe_packed_borrows)]
1683    /// use repr_offset::for_examples::ReprPacked;
1684    /// use repr_offset::utils::moved;
1685    ///
1686    /// let mut this = ReprPacked{ a: [0u8, 1], b: false, c: (), d: () };
1687    ///
1688    /// assert_eq!( ReprPacked::OFFSET_A.replace_mut(&mut this, [2, 3]), [0u8, 1] );
1689    /// assert_eq!( ReprPacked::OFFSET_B.replace_mut(&mut this, true), false );
1690    ///
1691    /// assert_eq!( moved(this.a), [2u8, 3] );
1692    /// assert_eq!( moved(this.b), true );
1693    ///
1694    /// ```
1695    pub fn replace_mut(self, dest: &mut S, value: F) -> F {
1696        unsafe { impl_fo!(fn replace_mut<S, F, Unaligned>(self, dest, value)) }
1697    }
1698}
1699
1700impl<S, F> FieldOffset<S, F, Unaligned> {
1701    /// Swaps the values of a field between the `left` and `right` pointers.
1702    ///
1703    /// # Safety
1704    ///
1705    /// This function has the same safety requirements as
1706    /// [`std::ptr::swap`](https://doc.rust-lang.org/std/ptr/fn.swap.html),
1707    /// except that it does not require aligned pointers.
1708    ///
1709    /// Those safety requirements only apply to the field that this is an offset for,
1710    /// fields after it or before it don't need to be valid to call this method.
1711    ///
1712    /// # Example
1713    ///
1714    /// ```rust
1715    /// # #![deny(safe_packed_borrows)]
1716    /// use repr_offset::for_examples::ReprPacked;
1717    /// use repr_offset::utils::moved;
1718    ///
1719    /// let mut this = ReprPacked{ a: '=', b: 64u16, c: (), d: () };
1720    /// let mut other = ReprPacked{ a: '!', b: 255u16, c: (), d: () };
1721    ///
1722    /// let this_ptr: *mut _ = &mut this;
1723    /// let other_ptr: *mut _ = &mut other;
1724    /// unsafe{
1725    ///     ReprPacked::OFFSET_A.swap(this_ptr, other_ptr);
1726    ///     ReprPacked::OFFSET_B.swap(this_ptr, other_ptr);
1727    /// }
1728    /// assert_eq!( moved(this.a), '!' );
1729    /// assert_eq!( moved(this.b), 255 );
1730    ///
1731    /// assert_eq!( moved(other.a), '=' );
1732    /// assert_eq!( moved(other.b), 64 );
1733    ///
1734    /// ```
1735    #[inline(always)]
1736    pub unsafe fn swap(self, left: *mut S, right: *mut S) {
1737        impl_fo!(fn swap<S, F, Unaligned>(self, left, right))
1738    }
1739
1740    /// Swaps the values of a field between the non-overlapping `left` and `right` pointers.
1741    ///
1742    /// # Safety
1743    ///
1744    /// This function has the same safety requirements as
1745    /// [`std::ptr::swap_nonoverlapping`
1746    /// ](https://doc.rust-lang.org/std/ptr/fn.swap_nonoverlapping.html)
1747    /// except that it does not require aligned pointers.
1748    ///
1749    /// Those safety requirements only apply to the field that this is an offset for,
1750    /// fields after it or before it don't need to be valid to call this method.
1751    ///
1752    /// # Example
1753    ///
1754    /// ```rust
1755    /// # #![deny(safe_packed_borrows)]
1756    /// use repr_offset::for_examples::ReprPacked;
1757    /// use repr_offset::utils::moved;
1758    ///
1759    /// let mut this = ReprPacked{ a: [false, true], b: &27u32, c: (), d: () };
1760    /// let mut other = ReprPacked{ a: [true, false], b: &81u32, c: (), d: () };
1761    ///
1762    /// let this_ptr: *mut _ = &mut this;
1763    /// let other_ptr: *mut _ = &mut other;
1764    /// unsafe{
1765    ///     ReprPacked::OFFSET_A.swap_nonoverlapping(this_ptr, other_ptr);
1766    ///     ReprPacked::OFFSET_B.swap_nonoverlapping(this_ptr, other_ptr);
1767    /// }
1768    /// assert_eq!( moved(this.a), [true, false] );
1769    /// assert_eq!( moved(this.b), &81 );
1770    ///
1771    /// assert_eq!( moved(other.a), [false, true] );
1772    /// assert_eq!( moved(other.b), &27 );
1773    ///
1774    /// ```
1775    ///
1776    #[inline(always)]
1777    pub unsafe fn swap_nonoverlapping(self, left: *mut S, right: *mut S) {
1778        impl_fo!(fn swap_nonoverlapping<S, F, Unaligned>(self, left, right))
1779    }
1780
1781    /// Swaps the values of a field between `left` and `right`.
1782    ///
1783    /// # Example
1784    ///
1785    /// ```rust
1786    /// # #![deny(safe_packed_borrows)]
1787    /// use repr_offset::for_examples::ReprPacked;
1788    /// use repr_offset::utils::moved;
1789    ///
1790    /// let mut this = ReprPacked{ a: [true, true], b: 0x0Fu8, c: (), d: () };
1791    /// let mut other = ReprPacked{ a: [false, false], b: 0xF0u8, c: (), d: () };
1792    ///
1793    /// ReprPacked::OFFSET_A.swap_mut(&mut this, &mut other);
1794    /// ReprPacked::OFFSET_B.swap_mut(&mut this, &mut other);
1795    ///
1796    /// assert_eq!( moved(this.a), [false, false] );
1797    /// assert_eq!( moved(this.b), 0xF0u8 );
1798    ///
1799    /// assert_eq!( moved(other.a), [true, true] );
1800    /// assert_eq!( moved(other.b), 0x0Fu8 );
1801    ///
1802    /// ```
1803    ///
1804    #[inline(always)]
1805    pub fn swap_mut(self, left: &mut S, right: &mut S) {
1806        unsafe { impl_fo!(fn swap_mut<S, F, Unaligned>(self, left, right)) }
1807    }
1808}
1809
1810#[cfg(test)]
1811mod tests {
1812    use super::*;
1813
1814    use crate::types_for_tests::StructPacked;
1815
1816    use core::mem;
1817
1818    #[test]
1819    fn test_constructor_offset() {
1820        unsafe {
1821            let field_0 = FieldOffset::<(u128,), u8, Aligned>::new(0);
1822            let field_1 = field_0.next_field_offset::<u32, Aligned>();
1823            assert_eq!(field_0.offset(), 0);
1824            assert_eq!(field_1.offset(), mem::align_of::<u32>());
1825        }
1826        unsafe {
1827            let field_0 = FieldOffset::<StructPacked<u128, (), (), ()>, u8, Unaligned>::new(0);
1828            let field_1 = field_0.next_field_offset::<u32, Unaligned>();
1829            let field_2 = field_1.next_field_offset::<&'static str, Unaligned>();
1830            assert_eq!(field_0.offset(), 0);
1831            assert_eq!(field_1.offset(), 1);
1832            assert_eq!(field_2.offset(), 5);
1833        }
1834    }
1835}