slice_trait/
length.rs

1use core::{fmt, hash::Hash, marker::{Destruct, Freeze}};
2
3macro_rules! op {
4    ($trait:ident 1) => {
5        type $trait: LengthValue = <Self as ops::${concat(Length, $trait)}>::Output;
6    };
7    ($trait:ident 2) => {
8        type $trait<Rhs: LengthValue>: LengthValue = <Self as ops::${concat(Length, $trait)}<Rhs>>::Output;
9    };
10    ($trait:ident [1]) => {
11        type $trait: Length<Elem = Self::Elem> + ?Sized = value::Length<value::$trait<Self::Value>, Self::Elem>;
12    };
13    ($trait:ident [2]) => {
14        type $trait<Rhs: Length<Elem = Self::Elem> + ?Sized>: Length<Elem = Self::Elem> + ?Sized = value::Length<value::$trait<Self::Value, Rhs::Value>, Self::Elem>;
15    };
16    ($trait:ident::$fn:ident 1) => {
17        pub type $trait<X> = <X as LengthValue>::$trait;
18        pub const fn $fn<X>(x: X) -> $trait<X>
19        where
20            X: LengthValue
21        {
22            <X as ops::${concat(Length, $trait)}>::$fn(x)
23        }
24    };
25    ($trait:ident::$fn:ident 2) => {
26        pub type $trait<Lhs, Rhs> = <Lhs as LengthValue>::$trait<Rhs>;
27        pub const fn $fn<Lhs, Rhs>(lhs: Lhs, rhs: Rhs) -> $trait<Lhs, Rhs>
28        where
29            Lhs: LengthValue,
30            Rhs: LengthValue
31        {
32            <Lhs as ops::${concat(Length, $trait)}<Rhs>>::$fn(lhs, rhs)
33        }
34    };
35    (pub $trait:ident [1]) => {
36        pub type $trait<X> = <X as Length>::$trait;
37    };
38    (pub $trait:ident [2]) => {
39        pub type $trait<Lhs, Rhs> = <Lhs as Length>::$trait<Rhs>;
40    };
41}
42
43#[rustc_on_unimplemented(
44    message = "`{Self}` is not a valid bulk length",
45    label = "The only valid lengths are `[_]` or `[_; _]`",
46)]
47pub trait Length: private::Length<_Value = Self::Value>
48{
49    type Value: LengthValue<Length<Self::Elem> = Self, _Length<Self::Elem> = Self, Metadata = Self::Metadata, _Metadata = Self::Metadata>;
50    type Mapped<U>: Length<Elem = U, Value = Self::Value, _Value = Self::Value, Metadata = Self::Metadata> + ?Sized = value::Length<Self::Value, U>;
51
52    op!(Min [2]);
53    op!(Max [2]);
54    op!(Add [2]);
55    op!(Sub [2]);
56    op!(Mul [2]);
57    op!(Div [2]);
58    op!(Rem [2]);
59    op!(SaturatingAdd [2]);
60    op!(SaturatingSub [2]);
61    op!(SaturatingMul [2]);
62    op!(SaturatingDiv [2]);
63    op!(DivCeil [2]);
64    op!(DivFloor [2]);
65    op!(Windowed [2]);
66    op!(Interspersed [1]);
67}
68impl<T> Length for T
69where
70    T: private::Length + ?Sized
71{
72    type Value = Self::_Value;
73}
74
75op!(pub Min [2]);
76op!(pub Max [2]);
77op!(pub Add [2]);
78op!(pub Sub [2]);
79op!(pub Mul [2]);
80op!(pub Div [2]);
81op!(pub Rem [2]);
82op!(pub SaturatingAdd [2]);
83op!(pub SaturatingSub [2]);
84op!(pub SaturatingMul [2]);
85op!(pub SaturatingDiv [2]);
86op!(pub DivCeil [2]);
87op!(pub DivFloor [2]);
88op!(pub Windowed [2]);
89op!(pub Interspersed [1]);
90
91pub use crate::Elem;
92pub type Value<T> = <T as Length>::Value;
93pub type Mapped<T, U> = <T as Length>::Mapped<U>;
94
95pub mod value
96{
97    use core::cmp::Ordering;
98
99    use super::*;
100
101    pub type Length<T, U> = <T as LengthValue>::Length<U>;
102
103    pub const fn from_metadata<T>(n: T::Metadata) -> T
104    where
105        T: LengthValue
106    {
107        <T as private::LengthValue>::from_metadata(n)
108    }
109    pub const fn into_metadata<T>(len: T) -> T::Metadata
110    where
111        T: LengthValue
112    {
113        <T as private::LengthValue>::into_metadata(len)
114    }
115    pub const fn or_len<T>(n: usize) -> T
116    where
117        T: LengthValue
118    {
119        <T as private::LengthValue>::or_len(n)
120    }
121    pub const fn len<T>(len: T) -> usize
122    where
123        T: LengthValue
124    {
125        <T as private::LengthValue>::len(len)
126    }
127    pub const fn len_metadata<T>(len: T::Metadata) -> usize
128    where
129        T: LengthValue
130    {
131        self::len(from_metadata::<T>(len))
132    }
133
134    op!(Min::min 2);
135    op!(Max::max 2);
136    op!(Add::add 2);
137    op!(Sub::sub 2);
138    op!(Mul::mul 2);
139    op!(Div::div 2);
140    op!(Rem::rem 2);
141    op!(SaturatingAdd::saturating_add 2);
142    op!(SaturatingSub::saturating_sub 2);
143    op!(SaturatingMul::saturating_mul 2);
144    op!(SaturatingDiv::saturating_div 2);
145    op!(DivCeil::div_ceil 2);
146    op!(DivFloor::div_floor 2);
147    op!(Windowed::windowed 2);
148    op!(Interspersed::interspersed 1);
149
150    macro_rules! cmp_op {
151        ($($op:ident)* -> $ret:ty) => {
152            $(
153                pub const fn $op<L, R>(lhs: L, rhs: R) -> $ret
154                where
155                    L: LengthValue,
156                    R: LengthValue
157                {
158                    usize::$op(&len(lhs), &len(rhs))
159                }
160            )*
161        };
162    }
163    
164    cmp_op!(cmp -> Ordering);
165    cmp_op!(eq ne gt lt ge le -> bool);
166
167    macro_rules! checked_op {
168        ($($trait:ident::$fn:ident)*) => {
169            $(
170                pub const fn ${concat(checked_, $fn)}<L, R>(lhs: L, rhs: R) -> Option<$trait<L, R>>
171                where
172                    L: LengthValue,
173                    R: LengthValue
174                {
175                    match usize::${concat(checked_, $fn)}(len(lhs), len(rhs))
176                    {
177                        Some(_) => Some($fn(lhs, rhs)),
178                        None => None
179                    }
180                }
181            )*
182        };
183    }
184    checked_op!(Sub::sub Add::add Mul::mul Div::div Rem::rem);
185}
186
187pub const fn as_metadata<T>(len: &T) -> T::Metadata
188where
189    T: Length + ?Sized
190{
191    core::ptr::metadata(len)
192}
193pub const fn as_value<T>(len: &T) -> T::Value
194where
195    T: Length + ?Sized
196{
197    value::from_metadata(as_metadata(len))
198}
199pub const fn len<T>(len: &T) -> usize
200where
201    T: Length + ?Sized
202{
203    value::len(as_value(len))
204}
205pub const fn len_metadata<T>(metadata: T::Metadata) -> usize
206where
207    T: Length + ?Sized
208{
209    value::len_metadata::<T::Value>(metadata)
210}
211pub const fn from_raw_parts<'a, T>(ptr: *const T::Elem, metadata: T::Metadata) -> &'a T
212where
213    T: Length + ?Sized
214{
215    unsafe {
216        ptr_from_raw_parts::<T>(ptr, metadata).as_ref().unwrap()
217    }
218}
219pub const fn from_raw_parts_mut<'a, T>(ptr: *mut T::Elem, metadata: T::Metadata) -> &'a mut T
220where
221    T: Length + ?Sized
222{
223    unsafe {
224        ptr_from_raw_parts_mut::<T>(ptr, metadata).as_mut().unwrap()
225    }
226}
227pub const fn from_ptr_len<'a, T>(ptr: *const T::Elem, len: T::Value) -> &'a T
228where
229    T: Length + ?Sized
230{
231    unsafe {
232        ptr_from_ptr_len::<T>(ptr, len).as_ref().unwrap()
233    }
234}
235pub const fn from_mut_ptr_len<'a, T>(ptr: *mut T::Elem, len: T::Value) -> &'a mut T
236where
237    T: Length + ?Sized
238{
239    unsafe {
240        ptr_from_mut_ptr_len::<T>(ptr, len).as_mut().unwrap()
241    }
242}
243pub const fn ptr_from_raw_parts<T>(ptr: *const T::Elem, metadata: T::Metadata) -> *const T
244where
245    T: Length + ?Sized
246{
247    core::ptr::from_raw_parts::<T>(ptr, metadata)
248}
249pub const fn ptr_from_raw_parts_mut<T>(ptr: *mut T::Elem, metadata: T::Metadata) -> *mut T
250where
251    T: Length + ?Sized
252{
253    core::ptr::from_raw_parts_mut::<T>(ptr, metadata)
254}
255pub const fn ptr_from_ptr_len<T>(ptr: *const T::Elem, len: T::Value) -> *const T
256where
257    T: Length + ?Sized
258{
259    from_raw_parts(ptr, value::into_metadata(len))
260}
261pub const fn ptr_from_mut_ptr_len<T>(ptr: *mut T::Elem, len: T::Value) -> *mut T
262where
263    T: Length + ?Sized
264{
265    from_raw_parts_mut(ptr, value::into_metadata(len))
266}
267
268pub trait LengthValue: const private::LengthValue<_Length<()> = Self::Length<()>, _Metadata = Self::Metadata>
269{
270    type Length<T>: Length<Elem = T, Value = Self, _Value = Self, Metadata = Self::Metadata> + ?Sized;
271    type Metadata: fmt::Debug + Copy + Send + Sync + const Ord + Hash + Unpin + Freeze + const Default + const Destruct;
272
273    op!(Min 2);
274    op!(Max 2);
275    op!(Add 2);
276    op!(Sub 2);
277    op!(Mul 2);
278    op!(Div 2);
279    op!(Rem 2);
280    op!(SaturatingAdd 2);
281    op!(SaturatingSub 2);
282    op!(SaturatingMul 2);
283    op!(SaturatingDiv 2);
284    op!(DivCeil 2);
285    op!(DivFloor 2);
286    op!(Windowed 2);
287    op!(Interspersed 1);
288}
289impl<T> LengthValue for T
290where
291    T: const private::LengthValue
292{
293    type Length<U> = <Self as private::LengthValue>::_Length<U>;
294    type Metadata = <Self as private::LengthValue>::_Metadata;
295}
296
297mod ops
298{
299    use super::*;
300
301    use crate::same::Same;
302
303    macro_rules! op {
304        ($trait:ident::$fn:ident($x:ident) $expr:expr) => {
305            #[doc(hidden)]
306            pub const trait ${concat(Length, $trait)}: LengthValue
307            {
308                #[doc(hidden)]
309                type Output: LengthValue;
310
311                #[doc(hidden)]
312                fn $fn(x: Self) -> <Self as super::LengthValue>::$trait;
313            }
314            impl<L> const ${concat(Length, $trait)} for L
315            where
316                L: LengthValue
317            {
318                default type Output = usize;
319
320                default fn $fn(x: Self) -> Self::$trait
321                {
322                    let $x = L::len(x);
323                    $expr.same().ok().unwrap()
324                }
325            }
326            #[allow(non_upper_case_globals)]
327            impl<const $x: usize> const ${concat(Length, $trait)} for [(); $x]
328            where
329                [(); $expr]:
330            {
331                type Output = [(); $expr];
332
333                fn $fn(_: Self) -> Self::Output
334                {
335                    [(); $expr]
336                }
337            }
338        };
339        ($trait:ident::$fn:ident($lhs:ident, $rhs:ident) $expr:expr) => {
340            #[doc(hidden)]
341            pub const trait ${concat(Length, $trait)}<R>: LengthValue
342            where
343                R: LengthValue
344            {
345                #[doc(hidden)]
346                type Output: LengthValue;
347
348                #[doc(hidden)]
349                fn $fn(lhs: Self, rhs: R) -> <Self as super::LengthValue>::$trait<R>;
350            }
351            impl<L, R> const ${concat(Length, $trait)}<R> for L
352            where
353                L: LengthValue,
354                R: LengthValue
355            {
356                default type Output = usize;
357
358                default fn $fn(lhs: Self, rhs: R) -> Self::$trait<R>
359                {
360                    let $lhs = L::len(lhs);
361                    let $rhs = R::len(rhs);
362                    $expr.same().ok().unwrap()
363                }
364            }
365            #[allow(non_upper_case_globals)]
366            impl<const $lhs: usize, const $rhs: usize> const ${concat(Length, $trait)}<[(); $rhs]> for [(); $lhs]
367            where
368                [(); $expr]:
369            {
370                type Output = [(); $expr];
371
372                fn $fn(_: Self, _: [(); $rhs]) -> Self::Output
373                {
374                    [(); $expr]
375                }
376            }
377        };
378    }
379
380    op!(Min::min(a, b) Ord::min(a, b));
381    op!(Max::max(a, b) Ord::max(a, b));
382    op!(Add::add(a, b) a + b);
383    op!(Sub::sub(a, b) a - b);
384    op!(Mul::mul(a, b) a*b);
385    op!(Div::div(a, b) a/b);
386    op!(Rem::rem(a, b) a % b);
387    op!(SaturatingAdd::saturating_add(a, b) a.saturating_add(b));
388    op!(SaturatingSub::saturating_sub(a, b) a.saturating_sub(b));
389    op!(SaturatingMul::saturating_mul(a, b) a.saturating_mul(b));
390    op!(SaturatingDiv::saturating_div(a, b) a.saturating_div(b));
391    op!(DivCeil::div_ceil(a, b) a.div_ceil(b));
392    op!(DivFloor::div_floor(a, b) a.div_floor(b));
393    op!(Windowed::windowed(a, b) a.saturating_sub(b - 1));
394    op!(Interspersed::interspersed(a) a + a.saturating_sub(1));
395}
396
397mod private
398{
399    use core::fmt;
400    use core::hash::Hash;
401    use core::marker::Freeze;
402    use core::{marker::Destruct, ptr::Pointee};
403
404    use crate::AsSlice;
405
406    #[doc(hidden)]
407    #[rustc_on_unimplemented(
408        message = "`{Self}` is not a valid bulk length",
409        label = "The only valid lengths are `[_]` or `[_; _]`",
410    )]
411    pub trait Length: AsSlice + Pointee
412    {
413        #[doc(hidden)]
414        type _Value: const LengthValue<_Length<Self::Elem> = Self, _Metadata = Self::Metadata>;
415    }
416    impl<T> Length for [T]
417    {
418        type _Value = usize;
419    }
420    impl<T, const N: usize> Length for [T; N]
421    {
422        type _Value = [(); N];
423    }
424
425    #[doc(hidden)]
426    pub const trait LengthValue: Copy + const Destruct
427    {
428        #[doc(hidden)]
429        type _Length<T>: Length<Elem = T, _Value = Self, Metadata = Self::_Metadata> + ?Sized;
430        #[doc(hidden)]
431        type _Metadata: fmt::Debug + Copy + Send + Sync + const Ord + Hash + Unpin + Freeze + const Default + const Destruct;
432        
433        fn or_len(n: usize) -> Self;
434        fn from_metadata(n: Self::_Metadata) -> Self;
435        fn into_metadata(len: Self) -> Self::_Metadata;
436        fn len(len: Self) -> usize;
437    }
438    impl const LengthValue for usize
439    {
440        type _Length<T> = [T];
441        type _Metadata = usize;
442
443        fn or_len(n: usize) -> Self
444        {
445            n
446        }
447        fn from_metadata(n: Self::_Metadata) -> Self
448        {
449            n
450        }
451        fn into_metadata(len: Self) -> Self::_Metadata
452        {
453            len
454        }
455        fn len(len: Self) -> usize
456        {
457            len
458        }
459    }
460    impl<const N: usize> const LengthValue for [(); N]
461    {
462        type _Length<T> = [T; N];
463        type _Metadata = ();
464
465        fn or_len(_: usize) -> Self
466        {
467            [(); N]
468        }
469        fn from_metadata((): Self::_Metadata) -> Self
470        {
471            [(); N]
472        }
473        fn into_metadata(_len: Self) -> Self::_Metadata
474        {
475            
476        }
477        fn len(_len: Self) -> usize
478        {
479            N
480        }
481    }
482}
483
484#[cfg(test)]
485mod test
486{
487    use crate::length::Sub;
488
489    #[allow(unused)]
490    const TEST: Sub<[(); 5], [(); 2]> = [(), (), ()];
491}