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}