partial_ref/
lib.rs

1//! Type checked partial references.
2//!
3//! This crate provides type checked partial references for rust. Type checked partial references
4//! are one solution to solve [interprocedural borrowing conflicts][interprocedural-conflicts].
5//!
6//! # Tutorial
7//!
8//! With this crate it is possible to declare typed parts (using the [`part`] macro) and to assign
9//! struct fields to these parts (by [deriving `PartialRefTarget`](partial_ref_derive)).
10//!
11//! ```
12//! use partial_ref::{part, PartialRefTarget};
13//!
14//! part!(pub Neighbors: Vec<Vec<usize>>);
15//! part!(pub Colors: Vec<usize>);
16//! part!(pub Weights: Vec<f32>);
17//!
18//! #[derive(PartialRefTarget, Default)]
19//! pub struct Graph {
20//!     #[part(Neighbors)]
21//!     pub neighbors: Vec<Vec<usize>>,
22//!     #[part(Colors)]
23//!     pub colors: Vec<usize>,
24//!     #[part(Weights)]
25//!     pub weights: Vec<f32>,
26//! }
27//! ```
28//!
29//! It is then possible to convert a reference to a value using the [`IntoPartialRef`] and
30//! [`IntoPartialRefMut`] traits, which are derived alongside PartialRefTarget. Note that a mutable
31//! partial reference must itself be mutable for mutable access.
32//!
33//! ```
34//! # use partial_ref::{part, PartialRefTarget};
35//! # use partial_ref_tests::doctest_helpers::*;
36//! use partial_ref::IntoPartialRefMut;
37//!
38//! let mut g = Graph::default();
39//!
40//! let mut g_ref = g.into_partial_ref_mut();
41//! ```
42//!
43//! You can access parts using the [`part`](PartialRef::part) and [`part_mut`](PartialRef::part_mut)
44//! methods.
45//!
46//! ```
47//! # use partial_ref::{part, PartialRefTarget, IntoPartialRefMut};
48//! # use partial_ref_tests::doctest_helpers::*;
49//! # let mut g = Graph::default();
50//! # let mut g_ref = g.into_partial_ref_mut();
51//! use partial_ref::PartialRef;
52//!
53//! g_ref.part_mut(Colors).extend(&[0, 1, 0]);
54//! g_ref.part_mut(Weights).extend(&[0.25, 0.5, 0.75]);
55//!
56//! g_ref.part_mut(Neighbors).push(vec![1, 2]);
57//! g_ref.part_mut(Neighbors).push(vec![0, 2]);
58//! g_ref.part_mut(Neighbors).push(vec![0, 1]);
59//!
60//! assert_eq!(g_ref.part(Colors).len(), g_ref.part(Neighbors).len());
61//! assert_eq!(g_ref.part(Colors).len(), g_ref.part(Weights).len());
62//! ```
63//!
64//! We can now write a function that takes parts of a reference. The type of such a partial
65//! reference can be written using the [`partial`] macro, which expands to a combination of [`Mut`],
66//! [`Const`] and [`Ref`]. Again the parameter `g` here must be mutable to allow mutable access to
67//! the referenced value. To call such a function we use the [`borrow`](PartialRef::borrow) method,
68//! which will re-borrow just the required parts.
69//!
70//! ```
71//! # use partial_ref::{part, PartialRefTarget, IntoPartialRefMut, PartialRef};
72//! # use partial_ref_tests::doctest_helpers::*;
73//! # let mut g = example_graph();
74//! # let mut g_ref = g.into_partial_ref_mut();
75//! use partial_ref::partial;
76//!
77//! pub fn add_color_to_weight(
78//!     mut g: partial!(Graph, mut Weights, Colors),
79//!     index: usize,
80//! ) {
81//!     g.part_mut(Weights)[index] += g.part(Colors)[index] as f32;
82//! }
83//!
84//! add_color_to_weight(g_ref.borrow(), 1);
85//!
86//! assert_eq!(g_ref.part(Weights)[1], 1.5);
87//! ```
88//!
89//! So far everything could have been written using plain built-in references. This changes as soon
90//! as we want to iterate over the neighbors while invoking our function. Usually we couldn't pass a
91//! mutable reference to the graph while holding the iterator over the neighbors.
92//!
93//! This can be easily done using partial references which support splitting. Splitting means
94//! turning a single reference into two references where each has a subset of parts, so that each
95//! mutably referenced part belongs only to a single reference. This is done by the
96//! [`split_borrow`](PartialRef::borrow) and [`split_part`](PartialRef::split_part) methods.
97//!
98//! ```
99//! # use partial_ref::{part, PartialRefTarget, IntoPartialRefMut, PartialRef, partial};
100//! # use partial_ref_tests::doctest_helpers::*;
101//! # let mut g = example_graph();
102//! # let mut g_ref = g.into_partial_ref_mut();
103//! let (neighbors, mut g_ref) = g_ref.split_part_mut(Neighbors);
104//! let (colors, mut g_ref) = g_ref.split_part(Colors);
105//!
106//! for (edges, &color) in neighbors.iter_mut().zip(colors.iter()) {
107//!     edges.retain(|&neighbor| colors[neighbor] != color);
108//!
109//!     for &neighbor in edges.iter() {
110//!         add_color_to_weight(g_ref.borrow(), neighbor);
111//!     }
112//! }
113//! ```
114//!
115//! This covers the basic functionality of this library. Beyond that this library also supports:
116//!
117//! * Partial references to nested structs using [`Nested`] and [`nested_part`].
118//! * Generic functions with bounds on available parts using [`HasPart`].
119//!
120//! # Notes
121//!
122//! Some documented items are marked with *(internal)*. Typical code using this library doesn't
123//! explicitly refer to them. Nevertheless they often appear in error messages and are thus part of
124//! this documentation. These items also have to be public for the inference driven meta programming
125//! to work. Code that is generic over parts of partial references might also need them.
126//!
127//! Many traits in this crate are marked as unsafe without documenting any requirements for
128//! implementations. This does not mean they are safe to implement, but rather means that they are
129//! not intended to be implemented outside of this library. Feel free to file an issue if you have a
130//! good reason to implement them so the requirements can be documented.
131//!
132//! [interprocedural-conflicts]: http://smallcultfollowing.com/babysteps/blog/2018/11/01/after-nll-interprocedural-conflicts/
133
134#[macro_use]
135mod macros;
136
137pub use partial_ref_derive::PartialRefTarget;
138
139use std::marker::PhantomData;
140
141/// A type that can be the target of partial references.
142///
143/// Implementations for this trait should be derived, see [`partial_ref_derive`].
144pub trait PartialRefTarget {
145    /// A partial reference will be represented by a pointer to this associated type.
146    ///
147    /// In most cases this is the implementing type itself. This is not a requirement though. In the
148    /// future, some features will introduce PartialRefTargets that have a different associated
149    /// `RawTarget` type.
150    type RawTarget: ?Sized;
151}
152
153/// Helper trait to associate the target type with a [`PartialRef`] without needing a lifetime.
154pub trait HasTarget {
155    /// The referenced type.
156    ///
157    // TODO add a warning that Target::RawTarget could be != Target when such a feature lands)
158    type Target: PartialRefTarget + ?Sized;
159}
160
161/// A partial reference.
162///
163/// This is implemented by variants of [`Ref`], [`Mut`] and [`Const`]. This is only implemented if the
164/// parts of any contained [`Mut`] or [`Const`] are valid for the referenced type.
165pub trait PartialRef<'a>: HasTarget + Sized {
166    /// Create a partial reference from a raw pointer.
167    ///
168    /// # Safety
169    /// This is unsafe for two reasons. It can be used to dereference a raw pointer, which is
170    /// already unsafe on its own, and it can be used to construct invalid partial references, for
171    /// example containing the same mutable part twice. Thus extra care is required when calling
172    /// this.
173    unsafe fn from_raw(ptr: *mut <Self::Target as PartialRefTarget>::RawTarget) -> Self;
174
175    /// Access to the underlying raw pointer.
176    ///
177    /// Beware that this can be used even for an empty reference with no parts. Doing anything with
178    /// the resulting pointer is very likely unsafe, even if the partial reference is still in
179    /// scope.
180    fn get_raw(&self) -> *mut <Self::Target as PartialRefTarget>::RawTarget;
181
182    /// Partially re-borrows a partial reference.
183    ///
184    /// This returns a new partial reference to the same value. The returned reference can have a
185    /// subset of the original reference's parts.
186    ///
187    /// A typical use case is passing a reference to a function that requires fewer parts than the
188    /// caller.
189    ///
190    /// Usually the type parameters can be inferred.
191    #[inline(always)]
192    fn borrow<BorrowedRef, SubsetIndex>(&'a mut self) -> BorrowedRef
193    where
194        BorrowedRef: PartialRef<'a, Target = Self::Target>,
195        Self: HasSubset<'a, BorrowedRef, SubsetIndex>,
196    {
197        unsafe { BorrowedRef::from_raw(self.get_raw()) }
198    }
199
200    /// Access a part of the referenced value.
201    ///
202    /// This returns a plain reference to a single part.
203    ///
204    /// The parameter is only present for type inference, its value is ignored. As all parts
205    /// implement [`Default`] it is always possible to pass a default value, which is useful in
206    /// generic code.
207    ///
208    /// Usually the type parameters can be inferred.
209    #[inline(always)]
210    fn part<FieldPartSpec, FieldPart, PartIndex, FieldType>(
211        &'a self,
212        _part: FieldPartSpec,
213    ) -> &'a FieldType
214    where
215        FieldType: ?Sized,
216        FieldPart: Part<PartType = Field<FieldType>>,
217        FieldPartSpec: PartSpec<FieldPart>,
218        Self: PluckConst<'a, FieldPart, PartIndex>,
219        Self::Target: HasPart<FieldPart> + 'a,
220    {
221        unsafe {
222            <Const<FieldPart, Ref<'a, Self::Target>> as PartialRef<'a>>::from_raw(self.get_raw())
223                .get_part()
224        }
225    }
226
227    /// Mutable access to a part of the referenced value.
228    ///
229    /// This returns a plain mutable reference to a single part.
230    ///
231    /// The parameter is only present for type inference, its value is ignored. As all parts
232    /// implement [`Default`] it is always possible to pass a default value, which is useful in
233    /// generic code.
234    ///
235    /// Usually the type parameters can be inferred.
236    #[inline(always)]
237    fn part_mut<FieldPartSpec, FieldPart, PartIndex, FieldType>(
238        &'a mut self,
239        _part: FieldPartSpec,
240    ) -> &'a mut FieldType
241    where
242        FieldType: ?Sized,
243        FieldPart: Part<PartType = Field<FieldType>>,
244        FieldPartSpec: PartSpec<FieldPart>,
245        Self: PluckMut<'a, FieldPart, PartIndex>,
246        Self::Target: HasPart<FieldPart> + 'a,
247    {
248        unsafe {
249            <Mut<FieldPart, Ref<'a, Self::Target>> as PartialRef<'a>>::from_raw(self.get_raw())
250                .get_part_mut()
251        }
252    }
253
254    /// Partially re-borrows a partial reference, splitting off the remaining parts.
255    ///
256    /// This is equivalent to [`borrow`](PartialRef::borrow) but also returns a second partial
257    /// reference that contains all parts that can be used simultaneously with the re-borrowed
258    /// reference.
259    ///
260    /// This means that constant parts are contained in both references, while mutable parts that
261    /// are re-borrowed are missing from the second partial reference. Mutable parts that are
262    /// re-borrowed as constant parts are constant parts of both references.
263    ///
264    /// Usually the type parameters can be inferred.
265    #[inline(always)]
266    fn split_borrow<BorrowedRef, SubsetIndex>(&'a mut self) -> (BorrowedRef, Self::Remainder)
267    where
268        BorrowedRef: PartialRef<'a, Target = Self::Target>,
269        Self: HasSubset<'a, BorrowedRef, SubsetIndex>,
270    {
271        let ptr = self.get_raw();
272        unsafe { (BorrowedRef::from_raw(ptr), Self::Remainder::from_raw(ptr)) }
273    }
274
275    /// Access a part of the referenced value, splitting off the remaining parts.
276    ///
277    /// This is equivalent to [`part`](PartialRef::part) but also returns a partial reference as
278    /// described in [`split_borrow`](PartialRef::split_borrow).
279    #[inline(always)]
280    fn split_part<FieldPartSpec, FieldPart, PartIndex, FieldType>(
281        &'a mut self,
282        _part: FieldPartSpec,
283    ) -> (&'a FieldType, Self::Remainder)
284    where
285        FieldType: ?Sized,
286        FieldPart: Part<PartType = Field<FieldType>>,
287        FieldPartSpec: PartSpec<FieldPart>,
288        Self: PluckConst<'a, FieldPart, PartIndex>,
289        Self::Target: HasPart<FieldPart> + 'a,
290    {
291        let ptr = self.get_raw();
292        unsafe {
293            (
294                <Const<FieldPart, Ref<'a, Self::Target>> as PartialRef<'a>>::from_raw(ptr)
295                    .get_part(),
296                Self::Remainder::from_raw(ptr),
297            )
298        }
299    }
300
301    /// Mutable access to a part of the referenced value, splitting off the remaining parts.
302    ///
303    /// This is equivalent to [`part_mut`](PartialRef::part_mut) but also returns a partial
304    /// reference as described in [`split_borrow`](PartialRef::split_borrow).
305    #[inline(always)]
306    fn split_part_mut<FieldPartSpec, FieldPart, PartIndex, FieldType>(
307        &'a mut self,
308        _part: FieldPartSpec,
309    ) -> (&'a mut FieldType, Self::Remainder)
310    where
311        FieldType: ?Sized,
312        FieldPart: Part<PartType = Field<FieldType>>,
313        FieldPartSpec: PartSpec<FieldPart>,
314        Self: PluckMut<'a, FieldPart, PartIndex>,
315        Self::Target: HasPart<FieldPart> + 'a,
316    {
317        let ptr = self.get_raw();
318        unsafe {
319            (
320                <Mut<FieldPart, Ref<'a, Self::Target>> as PartialRef<'a>>::from_raw(ptr)
321                    .get_part_mut(),
322                Self::Remainder::from_raw(ptr),
323            )
324        }
325    }
326}
327
328/// Construction of partial references.
329///
330/// See also [`IntoPartialRefMut`].
331///
332/// This trait gets an automatic implementation for references (mutable or immutable) to any type
333/// that has a derive statement for [`PartialRefTarget`]. Usually there is no need to implement this
334/// trait manually.
335pub trait IntoPartialRef<'a> {
336    type Ref: PartialRef<'a>;
337
338    /// Convert a mutable or immutable reference into a partial reference.
339    fn into_partial_ref(self) -> Self::Ref;
340}
341
342/// Construction of partial references from mutable references.
343///
344/// This has an implementation for mutable references that implement [`IntoPartialRefMut`]. It
345/// performs the same operation as [`IntoPartialRefMut`] but is only implemented for mutable
346/// references. This is useful as it allows writing `value.into_partial_ref_mut()` instead of `(&mut
347/// value).into_partial_ref_mut()` using auto referencing of method calls. Using just
348/// [`value.into_partial_ref()`] would result in an immutable reference.
349pub trait IntoPartialRefMut<'a>: IntoPartialRef<'a> {
350    /// Convert a mutable reference into a partial reference.
351    fn into_partial_ref_mut(self) -> Self::Ref;
352}
353
354impl<'a, T> IntoPartialRefMut<'a> for &'a mut T
355where
356    Self: IntoPartialRef<'a>,
357{
358    fn into_partial_ref_mut(self) -> Self::Ref {
359        self.into_partial_ref()
360    }
361}
362
363/// *(internal)* Split a part into nested parts.
364///
365/// This is used to implement splitting of nested parts.
366pub unsafe trait SplitIntoParts<'a, ContainingPart, Reference: PartialRef<'a>> {
367    /// A partial reference that has all the parts `Reference` and all parts of `Self` nested in
368    /// `ContainingPart` as constant parts.
369    type Result: PartialRef<'a, Target = Reference::Target>;
370    /// A partial reference that has all the parts `Reference` and all parts of `Self` nested in
371    /// `ContainingPart` as mutable parts.
372    type ResultMut: PartialRef<'a, Target = Reference::Target>;
373}
374
375/// An empty partial reference borrowing no parts.
376///
377/// Partial references with a non-empty set of borrowed parts are built by nesting this type within
378/// the [`Mut`] and [`Const`] types.
379#[repr(transparent)]
380pub struct Ref<'a, Target: PartialRefTarget + ?Sized> {
381    ptr: *mut Target::RawTarget,
382    phantom: PhantomData<&'a mut Target>,
383}
384
385impl<'a, Target: PartialRefTarget + ?Sized> HasTarget for Ref<'a, Target> {
386    type Target = Target;
387}
388
389/// An empty reference to a valid target is a valid reference.
390impl<'a, 'b: 'a, Target: PartialRefTarget + ?Sized> PartialRef<'a> for Ref<'b, Target> {
391    #[inline(always)]
392    unsafe fn from_raw(ptr: *mut <Self::Target as PartialRefTarget>::RawTarget) -> Self {
393        Ref {
394            ptr,
395            phantom: PhantomData,
396        }
397    }
398
399    #[inline(always)]
400    fn get_raw(&self) -> *mut <Self::Target as PartialRefTarget>::RawTarget {
401        self.ptr
402    }
403}
404
405/// An empty reference contains no mutable parts and thus is safe to clone.
406impl<'a, Target: PartialRefTarget> Copy for Ref<'a, Target> {}
407
408/// An empty reference contains no mutable parts and thus is safe to clone.
409impl<'a, Target: PartialRefTarget> Clone for Ref<'a, Target> {
410    #[inline(always)]
411    fn clone(&self) -> Self {
412        *self
413    }
414}
415
416/// A mutable part of a partial reference.
417#[repr(transparent)]
418pub struct Mut<Part, Reference: HasTarget> {
419    ptr: *mut <<Reference as HasTarget>::Target as PartialRefTarget>::RawTarget,
420    phantom: PhantomData<(Reference, Part)>,
421}
422
423impl<'a, SomePart: Part, Reference: PartialRef<'a>> HasTarget for Mut<SomePart, Reference>
424where
425    Reference::Target: HasPart<SomePart>,
426{
427    type Target = Reference::Target;
428}
429
430/// Extending a valid reference by a mutable part is still a valid reference when the reference
431/// target has such a part.
432impl<'a, SomePart: Part, Reference: PartialRef<'a>> PartialRef<'a> for Mut<SomePart, Reference>
433where
434    Reference::Target: HasPart<SomePart>,
435{
436    #[inline(always)]
437    unsafe fn from_raw(ptr: *mut <Self::Target as PartialRefTarget>::RawTarget) -> Self {
438        Mut {
439            ptr,
440            phantom: PhantomData,
441        }
442    }
443
444    #[inline(always)]
445    fn get_raw(&self) -> *mut <Self::Target as PartialRefTarget>::RawTarget {
446        self.ptr
447    }
448}
449
450/// A constant (immutable) part of a partial reference.
451#[repr(transparent)]
452pub struct Const<Part, Reference: HasTarget> {
453    ptr: *mut <<Reference as HasTarget>::Target as PartialRefTarget>::RawTarget,
454    phantom: PhantomData<(Reference, Part)>,
455}
456
457impl<'a, SomePart: Part, Reference: PartialRef<'a>> HasTarget for Const<SomePart, Reference>
458where
459    Reference::Target: HasPart<SomePart>,
460{
461    type Target = Reference::Target;
462}
463
464/// Extending a valid reference by a constant part is still a valid reference when the reference
465/// target has such a part.
466impl<'a, SomePart: Part, Reference: PartialRef<'a>> PartialRef<'a> for Const<SomePart, Reference>
467where
468    Reference::Target: HasPart<SomePart>,
469{
470    #[inline(always)]
471    unsafe fn from_raw(ptr: *mut <Self::Target as PartialRefTarget>::RawTarget) -> Self {
472        Const {
473            ptr,
474            phantom: PhantomData,
475        }
476    }
477
478    #[inline(always)]
479    fn get_raw(&self) -> *mut <Self::Target as PartialRefTarget>::RawTarget {
480        self.ptr
481    }
482}
483
484/// A reference containing just constant parts is safe to clone.
485impl<SomePart, Reference: Copy + HasTarget> Copy for Const<SomePart, Reference> {}
486
487/// A reference containing just constant parts is safe to clone.
488impl<SomePart, Reference: Copy + HasTarget> Clone for Const<SomePart, Reference> {
489    #[inline(always)]
490    fn clone(&self) -> Self {
491        *self
492    }
493}
494
495impl<'a, SomePart, Target, FieldType> Const<SomePart, Ref<'a, Target>>
496where
497    FieldType: ?Sized,
498    SomePart: Part<PartType = Field<FieldType>>,
499    Target: ?Sized,
500    Target: HasPart<SomePart>,
501{
502    /// Only available on single part references, used to implement the more general
503    /// [`part`](PartialRef::part) method of [`PartialRef`].
504    #[inline(always)]
505    fn get_part(self) -> &'a FieldType {
506        unsafe { &*Target::part_ptr(self.get_raw() as *const _) }
507    }
508}
509
510impl<'a, SomePart, Target, FieldType> Mut<SomePart, Ref<'a, Target>>
511where
512    FieldType: ?Sized,
513    SomePart: Part<PartType = Field<FieldType>>,
514    Target: ?Sized,
515    Target: HasPart<SomePart>,
516{
517    /// Only available on single part references, used to implement the more general
518    /// [`part_mut`](PartialRef::part_mut) method of [`PartialRef`]
519    #[inline(always)]
520    fn get_part_mut(self) -> &'a mut FieldType {
521        unsafe { &mut *Target::part_ptr_mut(self.get_raw()) }
522    }
523}
524
525// Parts
526
527/// Marker types for a part of a type.
528///
529/// Types implementing this trait are usually created using the [`part`] macro.
530///
531/// A type implementing this trait is used to identify a part of a reference target. Multiple
532/// different reference targets can have a part identified by the same [`Part`] (see also
533/// [`HasPart`]). A part has an associated [`PartType`], which determines what can be done with a
534/// part.
535pub trait Part: Default {
536    type PartType: PartType;
537}
538
539/// Helper trait to strip lifetimes from a part.
540///
541/// Every part `SomePart<'a, ...>` should implement `PartSpec<SomePart<'b, ...>>`. This is used by
542/// the [`part`](PartialRef::part), [`part_mut`](PartialRef::part_mut),
543/// [`split_part`](PartialRef::split_part) and [`split_part_mut`](PartialRef::split_part_mut)
544/// functions. This allows the passed parameter to have a different lifetime than the accessed part.
545/// This in turn enables part selection using globals with static lifetimes as declared by the
546/// [`part`] macro.
547pub trait PartSpec<Part> {}
548
549/// Implemented when a reference target has a part.
550///
551/// This trait provides methods for unchecked access to a part of a reference target.
552/// Implementations for this are automatically created when deriving PartialRefTarget.
553pub trait HasPart<SomePart: Part>: PartialRefTarget {
554    /// Given a constant pointer to a target, produce a constant pointer to a part of it.
555    ///
556    /// # Safety
557    /// Implementations may construct a temporary reference to ptr, which thus must be valid.
558    unsafe fn part_ptr(ptr: *const Self::RawTarget) -> <SomePart::PartType as PartType>::Ptr;
559    /// Given a mutable pointer to a target, produce a mutable pointer to a part of it.
560    ///
561    /// # Safety
562    /// Implementations may construct a temporary reference to ptr, which thus must be valid.
563    unsafe fn part_ptr_mut(ptr: *mut Self::RawTarget) -> <SomePart::PartType as PartType>::PtrMut;
564}
565
566/// Type of a part, determines what can be done with a part.
567///
568/// Common part types are [`Field`] and [`AbstractPart`].
569pub trait PartType {
570    /// Type that can be produced from a constant pointer to a reference target.
571    type Ptr;
572    /// Type that can be produced from a mutable pointer to a reference target.
573    type PtrMut;
574}
575
576/// Type of a part that corresponds to a struct field.
577///
578/// Partial references containing a part of this type provide access to that field.
579pub struct Field<FieldType: ?Sized>(PhantomData<FieldType>);
580
581impl<FieldType: ?Sized> PartType for Field<FieldType> {
582    type Ptr = *const FieldType;
583    type PtrMut = *mut FieldType;
584}
585
586/// Type of an abstract part.
587///
588/// Partial reference keep track of an abstract part, without providing any operations on it.
589pub struct AbstractPart;
590
591impl PartType for AbstractPart {
592    type Ptr = ();
593    type PtrMut = ();
594}
595
596/// A nested part.
597///
598/// A nested part can be constructed from an outer part and an inner part. The outer part must be a
599/// [`Field`] part, and the field's type must be a [`PartialRefTarget`] having the the inner part
600/// ([`HasPart`]).
601///
602/// When nesting multiple times, the nested part should always be the outer part. This isn't
603/// enforced, but some operations are only supported in that case.
604#[derive(Default)]
605pub struct Nested<Outer, Inner>(Outer, Inner);
606
607/// Create default values for nested parts.
608///
609/// These are useful as parameters to pass to [`PartialRef`]'s part functions.
610impl<NewInnerPart: Part, Outer: Part, Inner: Part> std::ops::BitOr<NewInnerPart>
611    for Nested<Outer, Inner>
612{
613    type Output = Nested<Nested<Outer, Inner>, NewInnerPart>;
614
615    fn bitor(self, _rhs: NewInnerPart) -> Self::Output {
616        std::default::Default::default()
617    }
618}
619
620/// A nested part is itself a part.
621impl<Outer, OuterFieldType, Inner> Part for Nested<Outer, Inner>
622where
623    Outer: Part<PartType = Field<OuterFieldType>>,
624    Inner: Part,
625    OuterFieldType: ?Sized,
626    OuterFieldType: HasPart<Inner>,
627    OuterFieldType: PartialRefTarget<RawTarget = OuterFieldType>,
628{
629    type PartType = Inner::PartType;
630}
631
632impl<Outer, Inner, OuterS, InnerS> PartSpec<Nested<OuterS, InnerS>> for Nested<Outer, Inner>
633where
634    Outer: PartSpec<OuterS>,
635    Inner: PartSpec<InnerS>,
636{
637}
638
639/// A reference has a nested part if it has the outer part and the nested part is valid.
640impl<Reference, Outer, OuterFieldType, Inner> HasPart<Nested<Outer, Inner>> for Reference
641where
642    Reference: ?Sized,
643    Reference: HasPart<Outer>,
644    Outer: Part<PartType = Field<OuterFieldType>>,
645    Inner: Part,
646    OuterFieldType: ?Sized,
647    OuterFieldType: HasPart<Inner>,
648    OuterFieldType: PartialRefTarget<RawTarget = OuterFieldType>,
649{
650    #[inline(always)]
651    unsafe fn part_ptr(ptr: *const Self::RawTarget) -> <Inner::PartType as PartType>::Ptr {
652        <OuterFieldType as HasPart<Inner>>::part_ptr(<Self as HasPart<Outer>>::part_ptr(ptr))
653    }
654
655    #[inline(always)]
656    unsafe fn part_ptr_mut(ptr: *mut Self::RawTarget) -> <Inner::PartType as PartType>::PtrMut {
657        <OuterFieldType as HasPart<Inner>>::part_ptr_mut(<Self as HasPart<Outer>>::part_ptr_mut(
658            ptr,
659        ))
660    }
661}
662
663// Type level logic for subsetting
664// This is inspired by the `frunk` crate
665
666/// *(internal)* Select the first part.
667pub struct IndexHere;
668
669/// *(internal)* Skip the first part.
670pub struct IndexNext<Index>(Index);
671
672/// *(internal)* Split the first part.
673pub struct IndexSplit<NestedPartIndex, Index>(NestedPartIndex, Index);
674
675/// *(internal)* Extracts the constant part `PluckedPart` at position `Index` from the partial
676/// reference having this trait, leaving `Self::Remainder`.
677///
678/// Plucking a constant part still leaves the part in the remaining reference, but will change it
679/// from mutable to constant.
680///
681/// The `Index` type can be inferred.
682pub unsafe trait PluckConst<'a, PluckedPart, Index>: PartialRef<'a> {
683    /// The partial reference left after plucking.
684    type Remainder: PartialRef<'a, Target = Self::Target>;
685}
686
687/// *(internal)* Extracts the mutable part `PluckedPart` at position `Index` from the partial
688/// reference having this trait, leaving `Self::Remainder`.
689///
690/// Plucking a mutable part removes it from the remaining reference.
691///
692/// The `Index` type can be inferred.
693pub unsafe trait PluckMut<'a, PluckedPart, Index>: PartialRef<'a> {
694    /// The partial reference left after plucking.
695    type Remainder: PartialRef<'a, Target = Self::Target>;
696}
697
698/// *(internal)* Plucks the outermost constant part.
699unsafe impl<'a, PluckedPart, Reference> PluckConst<'a, PluckedPart, IndexHere>
700    for Const<PluckedPart, Reference>
701where
702    PluckedPart: Part,
703    Reference: PartialRef<'a>,
704    Reference::Target: HasPart<PluckedPart>,
705{
706    type Remainder = Const<PluckedPart, Reference>;
707}
708
709/// *(internal)* Plucks the first part, converting it from mutable to constant.
710unsafe impl<'a, PluckedPart, Reference> PluckConst<'a, PluckedPart, IndexHere>
711    for Mut<PluckedPart, Reference>
712where
713    PluckedPart: Part,
714    Reference: PartialRef<'a>,
715    Reference::Target: HasPart<PluckedPart>,
716{
717    type Remainder = Const<PluckedPart, Reference>;
718}
719
720/// *(internal)* Plucks the first mutable part.
721unsafe impl<'a, PluckedPart, Reference> PluckMut<'a, PluckedPart, IndexHere>
722    for Mut<PluckedPart, Reference>
723where
724    PluckedPart: Part,
725    Reference: PartialRef<'a>,
726    Reference::Target: HasPart<PluckedPart>,
727{
728    type Remainder = Reference;
729}
730
731/// *(internal)* Skips the constant first part while plucking a constant part.
732unsafe impl<'a, PluckedPart, SkippedPart, Reference, Index>
733    PluckConst<'a, PluckedPart, IndexNext<Index>> for Const<SkippedPart, Reference>
734where
735    PluckedPart: Part,
736    SkippedPart: Part,
737    Reference::Target: HasPart<PluckedPart>,
738    Reference::Target: HasPart<SkippedPart>,
739    Reference: PluckConst<'a, PluckedPart, Index>,
740{
741    type Remainder = Const<SkippedPart, Reference::Remainder>;
742}
743
744/// *(internal)* Skips the mutable first part while plucking a constant part.
745unsafe impl<'a, PluckedPart, SkippedPart, Reference, Index>
746    PluckConst<'a, PluckedPart, IndexNext<Index>> for Mut<SkippedPart, Reference>
747where
748    PluckedPart: Part,
749    SkippedPart: Part,
750    Reference::Target: HasPart<PluckedPart>,
751    Reference::Target: HasPart<SkippedPart>,
752    Reference: PluckConst<'a, PluckedPart, Index>,
753{
754    type Remainder = Mut<SkippedPart, Reference::Remainder>;
755}
756
757/// *(internal)* Skips the constant first part while plucking a mutable part.
758unsafe impl<'a, PluckedPart, SkippedPart, Reference, Index>
759    PluckMut<'a, PluckedPart, IndexNext<Index>> for Const<SkippedPart, Reference>
760where
761    PluckedPart: Part,
762    SkippedPart: Part,
763    Reference::Target: HasPart<PluckedPart>,
764    Reference::Target: HasPart<SkippedPart>,
765    Reference: PluckMut<'a, PluckedPart, Index>,
766{
767    type Remainder = Const<SkippedPart, Reference::Remainder>;
768}
769
770/// *(internal)* Skips the mutable first part while plucking a mutable part.
771unsafe impl<'a, PluckedPart, SkippedPart, Reference, Index>
772    PluckMut<'a, PluckedPart, IndexNext<Index>> for Mut<SkippedPart, Reference>
773where
774    PluckedPart: Part,
775    SkippedPart: Part,
776    Reference::Target: HasPart<PluckedPart>,
777    Reference::Target: HasPart<SkippedPart>,
778    Reference: PluckMut<'a, PluckedPart, Index>,
779{
780    type Remainder = Mut<SkippedPart, Reference::Remainder>;
781}
782
783/// *(internal)* Pluck a mutable nested subpart of the mutable first part.
784///
785/// This leaves all other subparts in the remaining reference.
786unsafe impl<
787        'a,
788        ContainingPart,
789        PluckedOuter,
790        PluckedInner,
791        Reference,
792        NestedPartIndex,
793        Index,
794        OuterFieldType,
795        ContainingFieldType,
796    > PluckMut<'a, Nested<PluckedOuter, PluckedInner>, IndexSplit<NestedPartIndex, Index>>
797    for Mut<ContainingPart, Reference>
798where
799    PluckedOuter: Part<PartType = Field<OuterFieldType>>,
800    PluckedInner: Part,
801    ContainingPart: Part<PartType = Field<ContainingFieldType>>,
802    ContainingFieldType: SplitIntoParts<'a, ContainingPart, Reference>,
803    ContainingFieldType: ?Sized,
804    ContainingFieldType::ResultMut: PluckMut<'a, Nested<PluckedOuter, PluckedInner>, Index>,
805    OuterFieldType: ?Sized,
806    OuterFieldType: HasPart<PluckedInner>,
807    OuterFieldType: PartialRefTarget<RawTarget = OuterFieldType>,
808    Reference: PartialRef<'a>,
809    Reference::Target: HasPart<ContainingPart>,
810    ContainingPart: ContainsNestedPart<PluckedOuter, NestedPartIndex>,
811{
812    type Remainder = <ContainingFieldType::ResultMut as PluckMut<
813        'a,
814        Nested<PluckedOuter, PluckedInner>,
815        Index,
816    >>::Remainder;
817}
818
819/// *(internal)* Pluck a constant nested subpart of the mutable first part.
820///
821/// This leaves all other subparts as mutable in the remaining reference.
822unsafe impl<
823        'a,
824        ContainingPart,
825        PluckedOuter,
826        PluckedInner,
827        Reference,
828        NestedPartIndex,
829        Index,
830        OuterFieldType,
831        ContainingFieldType,
832    > PluckConst<'a, Nested<PluckedOuter, PluckedInner>, IndexSplit<NestedPartIndex, Index>>
833    for Mut<ContainingPart, Reference>
834where
835    PluckedOuter: Part<PartType = Field<OuterFieldType>>,
836    PluckedInner: Part,
837    ContainingPart: Part<PartType = Field<ContainingFieldType>>,
838    ContainingFieldType: SplitIntoParts<'a, ContainingPart, Reference>,
839    ContainingFieldType: ?Sized,
840    ContainingFieldType::ResultMut: PluckConst<'a, Nested<PluckedOuter, PluckedInner>, Index>,
841    OuterFieldType: ?Sized,
842    OuterFieldType: HasPart<PluckedInner>,
843    OuterFieldType: PartialRefTarget<RawTarget = OuterFieldType>,
844    Reference: PartialRef<'a>,
845    Reference::Target: HasPart<ContainingPart>,
846    ContainingPart: ContainsNestedPart<PluckedOuter, NestedPartIndex>,
847{
848    type Remainder = <ContainingFieldType::ResultMut as PluckConst<
849        'a,
850        Nested<PluckedOuter, PluckedInner>,
851        Index,
852    >>::Remainder;
853}
854
855/// *(internal)* Pluck a constant nested subpart of the constant first part.
856unsafe impl<
857        'a,
858        ContainingPart,
859        PluckedOuter,
860        PluckedInner,
861        Reference,
862        NestedPartIndex,
863        Index,
864        OuterFieldType,
865        ContainingFieldType,
866    > PluckConst<'a, Nested<PluckedOuter, PluckedInner>, IndexSplit<NestedPartIndex, Index>>
867    for Const<ContainingPart, Reference>
868where
869    PluckedOuter: Part<PartType = Field<OuterFieldType>>,
870    PluckedInner: Part,
871    ContainingPart: Part<PartType = Field<ContainingFieldType>>,
872    ContainingFieldType: SplitIntoParts<'a, ContainingPart, Reference>,
873    ContainingFieldType: ?Sized,
874    ContainingFieldType::ResultMut: PluckConst<'a, Nested<PluckedOuter, PluckedInner>, Index>,
875    OuterFieldType: ?Sized,
876    OuterFieldType: HasPart<PluckedInner>,
877    OuterFieldType: PartialRefTarget<RawTarget = OuterFieldType>,
878    Reference: PartialRef<'a>,
879    Reference::Target: HasPart<ContainingPart>,
880    ContainingPart: ContainsNestedPart<PluckedOuter, NestedPartIndex>,
881{
882    type Remainder = Const<ContainingPart, Reference>;
883}
884
885/// *(internal)* Index for the empty subset.
886pub struct SubsetIndexEnd;
887
888/// *(internal)* Construct a subset index from a part index and another subset index.
889pub struct SubsetIndexCons<PartIndex, TailIndex>(PartIndex, TailIndex);
890
891/// *(internal)* Asserts that the parts of the partial reference `Reference` are a subset of the
892/// parts of the partial reference having this trait.
893///
894/// A list of parts is considered a subset if they can be plucked in sequence.
895pub unsafe trait HasSubset<'a, Reference, SubsetIndex>: PartialRef<'a> {
896    type Remainder: PartialRef<'a, Target = Self::Target>;
897}
898
899/// *(internal)* Every reference has the empty reference as subset.
900unsafe impl<'a, Reference> HasSubset<'a, Ref<'a, Reference::Target>, SubsetIndexEnd> for Reference
901where
902    Reference: PartialRef<'a>,
903{
904    type Remainder = Reference;
905}
906
907/// *(internal)* To have a reference with a constant first part as subset, pluck that part and make
908/// sure the remaining references are in a subset relation.
909unsafe impl<'a, SubsetPart, Reference, PluckedRef, PartIndex, TailIndex>
910    HasSubset<'a, Const<SubsetPart, Reference>, SubsetIndexCons<PartIndex, TailIndex>>
911    for PluckedRef
912where
913    PluckedRef: PluckConst<'a, SubsetPart, PartIndex>,
914    <PluckedRef as PluckConst<'a, SubsetPart, PartIndex>>::Remainder:
915        HasSubset<'a, Reference, TailIndex>,
916    Reference: HasTarget,
917{
918    type Remainder =
919        <<PluckedRef as PluckConst<'a, SubsetPart, PartIndex>>::Remainder as HasSubset<
920            'a,
921            Reference,
922            TailIndex,
923        >>::Remainder;
924}
925
926/// *(internal)* To have a reference with a mutable first part as subset, pluck that part and make
927/// sure the remaining references are in a subset relation.
928unsafe impl<'a, SubsetPart, Reference, PluckedRef, PartIndex, TailIndex>
929    HasSubset<'a, Mut<SubsetPart, Reference>, SubsetIndexCons<PartIndex, TailIndex>> for PluckedRef
930where
931    PluckedRef: PluckMut<'a, SubsetPart, PartIndex>,
932    <PluckedRef as PluckMut<'a, SubsetPart, PartIndex>>::Remainder:
933        HasSubset<'a, Reference, TailIndex>,
934    Reference: HasTarget,
935{
936    type Remainder =
937        <<PluckedRef as PluckMut<'a, SubsetPart, PartIndex>>::Remainder as HasSubset<
938            'a,
939            Reference,
940            TailIndex,
941        >>::Remainder;
942}
943
944// Nesting helpers
945
946/// *(internal)* Check whether a part is nested inside another part.
947pub trait ContainsNestedPart<NestedPart, Index>: Part {}
948
949/// *(internal)* A part contains itself as a nested part.
950impl<NestedPart> ContainsNestedPart<NestedPart, IndexHere> for NestedPart where NestedPart: Part {}
951
952/// *(internal)* A part contains a nested part if it contains the outer part of the nested part.
953impl<NestedPart, Outer, Inner, OuterFieldType, Index>
954    ContainsNestedPart<Nested<Outer, Inner>, IndexNext<Index>> for NestedPart
955where
956    NestedPart: Part,
957    Inner: Part,
958    NestedPart: ContainsNestedPart<Outer, Index>,
959    Outer: Part<PartType = Field<OuterFieldType>>,
960    OuterFieldType: ?Sized,
961    OuterFieldType: HasPart<Inner>,
962    OuterFieldType: PartialRefTarget<RawTarget = OuterFieldType>,
963{
964}