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}