clockwork_tuples/traits/
has.rs

1use crate::{
2    index::{Here, Index, There},
3    traits::{as_cons_tuple::AsConsTuple, flat::ToFlat},
4};
5
6/// Provides indexed access to an element within a tuple.
7///
8/// # Invariants
9/// - `Idx` uniquely identifies an element position.
10/// - Access preserves the relative order of remaining elements.
11pub trait Has<T, Idx> {
12    /// Tuple remainder after element removal.
13    type Plucked;
14
15    /// Deconstructs the original tuple and gets the element
16    fn get(self) -> T;
17    /// Deconstructs this tuple into a plucked element and the rest of the tuple
18    fn plucked(self) -> (T, Self::Plucked);
19    /// Gets a reference to the element in this tuple
20    fn get_ref(&self) -> &T;
21    /// Gets a mutable reference to the element in this tuple
22    fn get_mut(&mut self) -> &mut T;
23}
24
25impl<Tuple, T, Idx> Has<T, Idx> for Tuple
26where
27    Tuple: AsConsTuple,
28    Tuple::As: ConsHas<T, Idx>,
29    <Tuple::As as ConsHas<T, Idx>>::Plucked: ToFlat,
30    for<'a> Tuple::AsRefs<'a>: ConsHas<&'a T, Idx>,
31    for<'a> Tuple::AsMuts<'a>: ConsHas<&'a mut T, Idx>,
32{
33    type Plucked = <<Tuple::As as ConsHas<T, Idx>>::Plucked as ToFlat>::Flattened;
34
35    fn get(self) -> T { self.to_cons_tuple().cons_get() }
36    fn plucked(self) -> (T, Self::Plucked) {
37        let (target, plucked) = self.to_cons_tuple().cons_pluck();
38        (target, plucked.flatten())
39    }
40    fn get_ref(&self) -> &T { self.to_cons_ref_tuple().cons_get() }
41    fn get_mut(&mut self) -> &mut T { self.to_cons_mut_tuple().cons_get() }
42}
43
44/// Indexed access over a cons-style tuple representation.
45pub trait ConsHas<T, Idx> {
46    /// Remaining tail after element removal.
47    type Plucked;
48
49    /// Deconstructs the cons tuple and gets the element
50    fn cons_get(self) -> T;
51    /// Deconstructs the cons tuple into a plucked element and the rest of the tuple
52    fn cons_pluck(self) -> (T, Self::Plucked);
53    /// Gets a reference to the element in this cons tuple
54    fn cons_get_ref(&self) -> &T;
55    /// Gets a mutable reference to the element in this cons tuple
56    fn cons_get_mut(&mut self) -> &mut T;
57}
58
59impl<Target, Tail> ConsHas<Target, Here> for (Target, Tail) {
60    type Plucked = Tail;
61
62    fn cons_get(self) -> Target { self.0 }
63    fn cons_pluck(self) -> (Target, Self::Plucked) { self }
64    fn cons_get_ref(&self) -> &Target { &self.0 }
65    fn cons_get_mut(&mut self) -> &mut Target { &mut self.0 }
66}
67
68impl<Head, Tail, Target, Idx: Index> ConsHas<Target, There<Idx>> for (Head, Tail)
69where
70    Tail: ConsHas<Target, Idx>,
71{
72    type Plucked = (Head, Tail::Plucked);
73
74    fn cons_get(self) -> Target { self.1.cons_get() }
75    fn cons_pluck(self) -> (Target, Self::Plucked) {
76        let (target, plucked) = self.1.cons_pluck();
77        (target, (self.0, plucked))
78    }
79    fn cons_get_ref(&self) -> &Target { self.1.cons_get_ref() }
80    fn cons_get_mut(&mut self) -> &mut Target { self.1.cons_get_mut() }
81}