1#![allow(missing_docs)]
2
3use std::any::{Any, TypeId};
6use std::cmp;
7use std::fmt::Debug;
8use std::ops::{Add, Div, Mul, Sub};
9use typenum::{self, Diff, Max, Maximum, Min, Minimum, Prod, Quot, Sum, Unsigned};
10
11#[cfg(feature = "rkyv-serialize")]
12use rkyv::bytecheck;
13#[cfg(feature = "serde-serialize-no-std")]
14use serde::{Deserialize, Deserializer, Serialize, Serializer};
15
16#[derive(Clone, Copy, Eq, PartialEq, Debug)]
18#[cfg_attr(
19 feature = "rkyv-serialize-no-std",
20 derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
21)]
22#[cfg_attr(
23 feature = "rkyv-serialize",
24 archive_attr(derive(bytecheck::CheckBytes))
25)]
26pub struct Dyn(pub usize);
27
28#[deprecated(note = "use Dyn instead.")]
29pub type Dynamic = Dyn;
30
31impl Dyn {
32 #[inline]
34 #[deprecated(note = "use Dyn(value) instead.")]
35 pub const fn new(value: usize) -> Self {
36 Self(value)
37 }
38}
39
40#[cfg(feature = "serde-serialize-no-std")]
41impl Serialize for Dyn {
42 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
43 where
44 S: Serializer,
45 {
46 self.0.serialize(serializer)
47 }
48}
49
50#[cfg(feature = "serde-serialize-no-std")]
51impl<'de> Deserialize<'de> for Dyn {
52 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
53 where
54 D: Deserializer<'de>,
55 {
56 usize::deserialize(deserializer).map(|x| Dyn(x))
57 }
58}
59
60pub trait IsDynamic {}
62pub trait IsNotStaticOne {}
64
65impl IsDynamic for Dyn {}
66impl IsNotStaticOne for Dyn {}
67
68pub unsafe trait Dim: Any + Debug + Copy + PartialEq + Send + Sync {
75 #[inline(always)]
76 fn is<D: Dim>() -> bool {
77 TypeId::of::<Self>() == TypeId::of::<D>()
78 }
79
80 fn try_to_usize() -> Option<usize>;
83
84 fn value(&self) -> usize;
87
88 fn from_usize(dim: usize) -> Self;
91}
92
93unsafe impl Dim for Dyn {
94 #[inline]
95 fn try_to_usize() -> Option<usize> {
96 None
97 }
98
99 #[inline]
100 fn from_usize(dim: usize) -> Self {
101 Self(dim)
102 }
103
104 #[inline]
105 fn value(&self) -> usize {
106 self.0
107 }
108}
109
110impl Add<usize> for Dyn {
111 type Output = Dyn;
112
113 #[inline]
114 fn add(self, rhs: usize) -> Self {
115 Self(self.0 + rhs)
116 }
117}
118
119impl Sub<usize> for Dyn {
120 type Output = Dyn;
121
122 #[inline]
123 fn sub(self, rhs: usize) -> Self {
124 Self(self.0 - rhs)
125 }
126}
127
128macro_rules! dim_ops(
135 ($($DimOp: ident, $DimNameOp: ident,
136 $Op: ident, $op: ident, $op_path: path,
137 $DimResOp: ident, $DimNameResOp: ident,
138 $ResOp: ident);* $(;)*) => {$(
139 pub type $DimResOp<D1, D2> = <D1 as $DimOp<D2>>::Output;
140
141 pub trait $DimOp<D: Dim>: Dim {
142 type Output: Dim;
143
144 fn $op(self, other: D) -> Self::Output;
145 }
146
147 impl<const A: usize, const B: usize> $DimOp<Const<B>> for Const<A>
148 where
149 Const<A>: ToTypenum,
150 Const<B>: ToTypenum,
151 <Const<A> as ToTypenum>::Typenum: $Op<<Const<B> as ToTypenum>::Typenum>,
152 $ResOp<<Const<A> as ToTypenum>::Typenum, <Const<B> as ToTypenum>::Typenum>: ToConst,
153 {
154 type Output =
155 <$ResOp<<Const<A> as ToTypenum>::Typenum, <Const<B> as ToTypenum>::Typenum> as ToConst>::Const;
156
157 fn $op(self, _: Const<B>) -> Self::Output {
158 Self::Output::name()
159 }
160 }
161
162 impl<D: Dim> $DimOp<D> for Dyn {
163 type Output = Dyn;
164
165 #[inline]
166 fn $op(self, other: D) -> Dyn {
167 Dyn($op_path(self.value(), other.value()))
168 }
169 }
170
171 impl<D: DimName> $DimOp<Dyn> for D {
173 type Output = Dyn;
174
175 #[inline]
176 fn $op(self, other: Dyn) -> Dyn {
177 Dyn($op_path(self.value(), other.value()))
178 }
179 }
180
181 pub type $DimNameResOp<D1, D2> = <D1 as $DimNameOp<D2>>::Output;
182
183 pub trait $DimNameOp<D: DimName>: DimName {
184 type Output: DimName;
185
186 fn $op(self, other: D) -> Self::Output;
187 }
188
189 impl<const A: usize, const B: usize> $DimNameOp<Const<B>> for Const<A>
190 where
191 Const<A>: ToTypenum,
192 Const<B>: ToTypenum,
193 <Const<A> as ToTypenum>::Typenum: $Op<<Const<B> as ToTypenum>::Typenum>,
194 $ResOp<<Const<A> as ToTypenum>::Typenum, <Const<B> as ToTypenum>::Typenum>: ToConst,
195 {
196 type Output =
197 <$ResOp<<Const<A> as ToTypenum>::Typenum, <Const<B> as ToTypenum>::Typenum> as ToConst>::Const;
198
199 fn $op(self, _: Const<B>) -> Self::Output {
200 Self::Output::name()
201 }
202 }
203 )*}
204);
205
206dim_ops!(
207 DimAdd, DimNameAdd, Add, add, Add::add, DimSum, DimNameSum, Sum;
208 DimMul, DimNameMul, Mul, mul, Mul::mul, DimProd, DimNameProd, Prod;
209 DimSub, DimNameSub, Sub, sub, Sub::sub, DimDiff, DimNameDiff, Diff;
210 DimDiv, DimNameDiv, Div, div, Div::div, DimQuot, DimNameQuot, Quot;
211 DimMin, DimNameMin, Min, min, cmp::min, DimMinimum, DimNameMinimum, Minimum;
212 DimMax, DimNameMax, Max, max, cmp::max, DimMaximum, DimNameMaximum, Maximum;
213);
214
215#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
216#[cfg_attr(
217 feature = "rkyv-serialize-no-std",
218 derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize),
219 archive(as = "Self")
220)]
221#[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))]
222pub struct Const<const R: usize>;
223
224pub trait DimName: Dim {
226 const USIZE: usize;
227
228 fn name() -> Self;
230
231 fn dim() -> usize;
234}
235
236#[cfg(feature = "serde-serialize-no-std")]
237impl<const D: usize> Serialize for Const<D> {
238 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
239 where
240 S: Serializer,
241 {
242 ().serialize(serializer)
243 }
244}
245
246#[cfg(feature = "serde-serialize-no-std")]
247impl<'de, const D: usize> Deserialize<'de> for Const<D> {
248 fn deserialize<Des>(deserializer: Des) -> Result<Self, Des::Error>
249 where
250 Des: Deserializer<'de>,
251 {
252 <()>::deserialize(deserializer).map(|_| Const::<D>)
253 }
254}
255
256pub trait ToConst {
257 type Const: DimName;
258}
259
260pub trait ToTypenum {
261 type Typenum: Unsigned;
262}
263
264unsafe impl<const T: usize> Dim for Const<T> {
265 #[inline]
266 fn try_to_usize() -> Option<usize> {
267 Some(T)
268 }
269
270 #[inline]
271 fn value(&self) -> usize {
272 T
273 }
274
275 #[inline]
276 fn from_usize(dim: usize) -> Self {
277 assert_eq!(dim, T);
278 Self
279 }
280}
281
282impl<const T: usize> DimName for Const<T> {
283 const USIZE: usize = T;
284
285 #[inline]
286 fn name() -> Self {
287 Self
288 }
289
290 #[inline]
291 fn dim() -> usize {
292 T
293 }
294}
295
296pub type U1 = Const<1>;
297
298impl ToTypenum for Const<1> {
299 type Typenum = typenum::U1;
300}
301
302impl ToConst for typenum::U1 {
303 type Const = Const<1>;
304}
305
306macro_rules! from_to_typenum (
307 ($($D: ident, $VAL: expr);* $(;)*) => {$(
308 pub type $D = Const<$VAL>;
309
310 impl ToTypenum for Const<$VAL> {
311 type Typenum = typenum::$D;
312 }
313
314 impl ToConst for typenum::$D {
315 type Const = Const<$VAL>;
316 }
317
318 impl IsNotStaticOne for $D { }
319
320 #[doc = stringify!($VAL)]
322 pub const $D: $D = Const::<$VAL>;
324 )*}
325);
326
327from_to_typenum!(
328 U0, 0; U2, 2; U3, 3; U4, 4; U5, 5; U6, 6; U7, 7; U8, 8; U9, 9; U10, 10; U11, 11; U12, 12; U13, 13; U14, 14; U15, 15; U16, 16; U17, 17; U18, 18;
329 U19, 19; U20, 20; U21, 21; U22, 22; U23, 23; U24, 24; U25, 25; U26, 26; U27, 27; U28, 28; U29, 29; U30, 30; U31, 31; U32, 32; U33, 33; U34, 34; U35, 35; U36, 36; U37, 37;
330 U38, 38; U39, 39; U40, 40; U41, 41; U42, 42; U43, 43; U44, 44; U45, 45; U46, 46; U47, 47; U48, 48; U49, 49; U50, 50; U51, 51; U52, 52; U53, 53; U54, 54; U55, 55; U56, 56;
331 U57, 57; U58, 58; U59, 59; U60, 60; U61, 61; U62, 62; U63, 63; U64, 64; U65, 65; U66, 66; U67, 67; U68, 68; U69, 69; U70, 70; U71, 71; U72, 72; U73, 73; U74, 74; U75, 75;
332 U76, 76; U77, 77; U78, 78; U79, 79; U80, 80; U81, 81; U82, 82; U83, 83; U84, 84; U85, 85; U86, 86; U87, 87; U88, 88; U89, 89; U90, 90; U91, 91; U92, 92; U93, 93; U94, 94;
333 U95, 95; U96, 96; U97, 97; U98, 98; U99, 99; U100, 100; U101, 101; U102, 102; U103, 103; U104, 104; U105, 105; U106, 106; U107, 107; U108, 108; U109, 109; U110, 110;
334 U111, 111; U112, 112; U113, 113; U114, 114; U115, 115; U116, 116; U117, 117; U118, 118; U119, 119; U120, 120; U121, 121; U122, 122; U123, 123; U124, 124; U125, 125; U126, 126;
335 U127, 127
336);
337
338pub const U1: U1 = Const::<1>;