bulks/adapters/
rev.rs

1use core::{marker::Destruct, ptr::Pointee};
2
3use array_trait::length::{self, Length, LengthValue};
4
5use crate::{Bulk, DoubleEndedBulk, SplitBulk};
6
7
8/// A double-ended bulk with the direction inverted.
9///
10/// This `struct` is created by the [`rev`](Bulk::rev) method on [`Bulk`]. See its
11/// documentation for more.
12#[derive(Clone, Debug)]
13#[must_use = "bulks are lazy and do nothing unless consumed"]
14pub struct Rev<I>
15where
16    I: DoubleEndedBulk
17{
18    bulk: I,
19}
20
21impl<I> Rev<I>
22where
23    I: DoubleEndedBulk
24{
25    pub(crate) const fn new(bulk: I) -> Self
26    {
27        Self {
28            bulk
29        }
30    }
31
32    /// Consumes the `Rev`, returning the inner bulk.
33    ///
34    /// # Examples
35    ///
36    /// ```rust
37    /// use bulks::*;
38    ///
39    /// let s = b"foobar";
40    /// let mut s2: [_; _] = s.bulk()
41    ///     .copied()
42    ///     .rev()
43    ///     .into_inner()
44    ///     .collect();
45    /// assert_eq!(&s2, b"foobar");
46    /// ```
47    pub const fn into_inner(self) -> I
48    {
49        let Self { bulk } = self;
50        bulk
51    }
52}
53
54impl<I> const Default for Rev<I>
55where
56    I: ~const Bulk + DoubleEndedBulk + ~const Default
57{
58    fn default() -> Self
59    {
60        I::default().rev()
61    }
62}
63
64impl<I> IntoIterator for Rev<I>
65where
66    I: DoubleEndedBulk
67{
68    type IntoIter = core::iter::Rev<I::IntoIter>;
69    type Item = I::Item;
70
71    fn into_iter(self) -> Self::IntoIter
72    {
73        self.into_inner().into_iter().rev()
74    }
75}
76impl<I> const Bulk for Rev<I>
77where
78    I: ~const Bulk + ~const DoubleEndedBulk
79{
80    type MinLength = I::MinLength;
81    type MaxLength = I::MaxLength;
82    
83    fn len(&self) -> usize
84    {
85        let Self { bulk } = self;
86        bulk.len()
87    }
88    fn is_empty(&self) -> bool
89    {
90        let Self { bulk } = self;
91        bulk.is_empty()
92    }
93    fn for_each<F>(self, f: F)
94    where
95        Self: Sized,
96        F: ~const FnMut(Self::Item) + ~const Destruct
97    {
98        let Self { bulk } = self;
99        bulk.rev_for_each(f);
100    }
101    fn try_for_each<F, R>(self, f: F) -> R
102    where
103        Self: Sized,
104        Self::Item: ~const Destruct,
105        F: ~const FnMut(Self::Item) -> R + ~const Destruct,
106        R: ~const core::ops::Try<Output = (), Residual: ~const Destruct>
107    {
108        let Self { bulk } = self;
109        bulk.try_rev_for_each(f)
110    }
111}
112impl<I> const DoubleEndedBulk for Rev<I>
113where
114    I: ~const Bulk + DoubleEndedBulk
115{
116    fn rev_for_each<F>(self, f: F)
117    where
118        Self: Sized,
119        F: ~const FnMut(Self::Item) + ~const Destruct
120    {
121        let Self { bulk } = self;
122        bulk.for_each(f);
123    }
124    fn try_rev_for_each<F, R>(self, f: F) -> R
125    where
126        Self: Sized,
127        Self::Item: ~const Destruct,
128        F: ~const FnMut(Self::Item) -> R + ~const Destruct,
129        R: ~const core::ops::Try<Output = (), Residual: ~const Destruct>
130    {
131        let Self { bulk } = self;
132        bulk.try_for_each(f)
133    }
134}
135impl<I, N, L, R> const SplitBulk<L> for Rev<I>
136where
137    I: ~const SplitBulk<R, Left: ~const Bulk + DoubleEndedBulk, Right: ~const Bulk + DoubleEndedBulk> + ~const Bulk<Length: Length<Value = N> + Pointee<Metadata = N::Metadata>> + DoubleEndedBulk,
138    N: LengthValue<SaturatingSub<L> = R>,
139    L: LengthValue,
140    R: LengthValue
141{
142    type Left = Rev<I::Right>;
143    type Right = Rev<I::Left>;
144
145    fn split_at(self, m: L) -> (Self::Left, Self::Right)
146    where
147        Self: Sized
148    {
149        let Self { bulk } = self;
150        let n = N::or_len(bulk.len());
151        let (left, right) = bulk.split_at(length::value::saturating_sub(n, m));
152        (
153            right.rev(),
154            left.rev()
155        )
156    }
157}
158
159#[cfg(test)]
160mod test
161{
162    use crate::*;
163
164    #[test]
165    fn it_works()
166    {
167        let a = [1, 2, 3, 4, 5, 6];
168        let (a, b) = a.into_bulk()
169            .rev()
170            .split_at([(); 2]);
171        let a = a.collect_array();
172        let b = b.collect_array();
173
174        println!("a = {a:?}");
175        println!("b = {b:?}");
176    }
177}