size_trait/lib.rs
1#![doc = include_str!("../README.md")]
2#![allow(incomplete_features)]
3#![feature(generic_const_exprs)]
4#![no_std]
5
6mod sealed {
7 pub trait SizeLessThan<const SIZE: usize, const CHECK: bool> {}
8
9 impl<const SIZE: usize, T> SizeLessThan<SIZE, { core::mem::size_of::<T>() < SIZE }> for T {}
10
11 pub trait SizeGreaterThan<const SIZE: usize, const CHECK: bool> {}
12
13 impl<const SIZE: usize, T> SizeGreaterThan<SIZE, { core::mem::size_of::<T>() > SIZE }> for T {}
14
15 pub trait Size<const SIZE: usize> {}
16
17 impl<T> Size<{ core::mem::size_of::<T>() }> for T {}
18
19 pub trait ZeroSize<const ZERO: bool> {}
20
21 impl<T> ZeroSize<{ core::mem::size_of::<T>() == 0 }> for T {}
22}
23
24/// Describes a type whose size is less than `SIZE` bytes.
25///
26/// # Examples
27///
28/// ```
29/// #![feature(generic_const_exprs)]
30/// struct LessThan10Bytes<T: size_trait::SizeLessThan<10, true>>(T);
31/// let _ = LessThan10Bytes([0u8; 5]);
32/// ```
33///
34/// ```
35/// #![feature(generic_const_exprs)]
36/// struct NotLessThan2Bytes<T: size_trait::SizeLessThan<2, false>>(T);
37/// let _ = NotLessThan2Bytes([0u8; 20]);
38/// ```
39///
40/// # Compilation Errors
41///
42/// ```compile_fail,E0308
43/// #![feature(generic_const_exprs)]
44/// struct LessThan10Bytes<T: size_trait::SizeLessThan<10, true>>(T);
45/// let _ = LessThan10Bytes([0u8; 11]);
46/// ```
47///
48/// ```compile_fail,E0308
49/// #![feature(generic_const_exprs)]
50/// struct NotLessThan2Bytes<T: size_trait::SizeLessThan<2, false>>(T);
51/// let _ = NotLessThan2Bytes(());
52/// ```
53///
54/// ```compile_fail,E0308
55/// #![feature(generic_const_exprs)]
56/// struct ElevenBytes([u8; 11]);
57/// impl size_trait::SizeLessThan<10, true> for ElevenBytes {}
58/// ```
59///
60/// ```compile_fail,E0308
61/// #![feature(generic_const_exprs)]
62/// struct OneByte(u8);
63/// impl size_trait::SizeLessThan<10, false> for OneByte {}
64/// ```
65pub trait SizeLessThan<const SIZE: usize, const CHECK: bool>:
66 sealed::SizeLessThan<SIZE, CHECK>
67{
68}
69
70impl<const SIZE: usize, const CHECK: bool, T: sealed::SizeLessThan<SIZE, CHECK>>
71 SizeLessThan<SIZE, CHECK> for T
72{
73}
74
75/// Describes a type whose size is greater than `SIZE` bytes.
76///
77/// # Examples
78///
79/// ```
80/// #![feature(generic_const_exprs)]
81/// struct GreaterThan10Bytes<T: size_trait::SizeGreaterThan<10, true>>(T);
82/// let _ = GreaterThan10Bytes([0u8; 11]);
83/// ```
84///
85/// ```
86/// #![feature(generic_const_exprs)]
87/// struct NotGreaterThan1Byte<T: size_trait::SizeGreaterThan<1, false>>(T);
88/// let _ = NotGreaterThan1Byte([0u8; 1]);
89/// let _ = NotGreaterThan1Byte(());
90/// ```
91///
92/// # Compilation Errors
93///
94/// ```compile_fail,E0308
95/// #![feature(generic_const_exprs)]
96/// struct GreaterThan10Bytes<T: size_trait::SizeGreaterThan<10, true>>(T);
97/// let _ = GreaterThan10Bytes(());
98/// ```
99///
100/// ```compile_fail,E0308
101/// #![feature(generic_const_exprs)]
102/// struct NotGreaterThan1Byte<T: size_trait::SizeGreaterThan<1, false>>(T);
103/// let _ = NotGreaterThan1Byte([0u8; 2]);
104/// ```
105///
106/// ```compile_fail,E0308
107/// #![feature(generic_const_exprs)]
108/// struct NineBytes([u8; 9]);
109/// impl size_trait::SizeGreaterThan<10, true> for NineBytes {}
110/// ```
111///
112/// ```compile_fail,E0308
113/// #![feature(generic_const_exprs)]
114/// struct OneByte(u8);
115/// impl size_trait::SizeGreaterThan<0, false> for OneByte {}
116/// ```
117pub trait SizeGreaterThan<const SIZE: usize, const CHECK: bool>:
118 sealed::SizeGreaterThan<SIZE, CHECK>
119{
120}
121
122impl<const SIZE: usize, const CHECK: bool, T: sealed::SizeGreaterThan<SIZE, CHECK>>
123 SizeGreaterThan<SIZE, CHECK> for T
124{
125}
126
127/// Describes a type whose size is at most `SIZE` bytes.
128///
129/// # Examples
130///
131/// ```
132/// #![feature(generic_const_exprs)]
133/// struct MaxSize10Bytes<T: size_trait::MaxSize<10>>(T);
134/// let _ = MaxSize10Bytes(());
135/// let _ = MaxSize10Bytes([0u8; 9]);
136/// ```
137///
138/// # Compilation Errors
139///
140/// ```compile_fail,E0308
141/// #![feature(generic_const_exprs)]
142/// struct MaxSize10Bytes<T: size_trait::MaxSize<10>>(T);
143/// let _ = MaxSize10Bytes([0u8; 11]);
144/// ```
145///
146/// ```compile_fail,E0308
147/// #![feature(generic_const_exprs)]
148/// struct TenBytes([u8; 10]);
149/// impl size_trait::MaxSize<5> for TenBytes {}
150/// ```
151pub trait MaxSize<const SIZE: usize>: SizeGreaterThan<SIZE, false> {}
152
153impl<const SIZE: usize, T: SizeGreaterThan<SIZE, false>> MaxSize<SIZE> for T {}
154
155/// Describes a type whose size is at least `SIZE` bytes.
156///
157/// # Examples
158///
159/// ```
160/// #![feature(generic_const_exprs)]
161/// struct MinSize10Bytes<T: size_trait::MinSize<10>>(T);
162/// let _ = MinSize10Bytes([0u8; 10]);
163/// let _ = MinSize10Bytes(0u128);
164/// ```
165///
166/// # Compilation Errors
167///
168/// ```compile_fail,E0308
169/// #![feature(generic_const_exprs)]
170/// struct MinSize10Bytes<T: size_trait::MinSize<10>>(T);
171/// let _ = MinSize10Bytes(());
172/// ```
173///
174/// ```compile_fail,E0308
175/// #![feature(generic_const_exprs)]
176/// struct TenBytes([u8; 10]);
177/// impl size_trait::MinSize<15> for TenBytes {}
178/// ```
179pub trait MinSize<const SIZE: usize>: SizeLessThan<SIZE, false> {}
180
181impl<const SIZE: usize, T: SizeLessThan<SIZE, false>> MinSize<SIZE> for T {}
182
183/// Describes a type whose size is between `MIN` and `MAX` bytes (inclusive).
184///
185/// # Examples
186///
187/// ```
188/// #![feature(generic_const_exprs)]
189/// struct Bounded10Bytes<T: size_trait::BoundedSize<1, 10>>(T);
190/// let _ = Bounded10Bytes(0u8);
191/// let _ = Bounded10Bytes([0u8; 9]);
192/// ```
193///
194/// # Compilation Errors
195///
196/// ```compile_fail,E0308
197/// #![feature(generic_const_exprs)]
198/// struct Bounded10Bytes<T: size_trait::BoundedSize<1, 10>>(T);
199/// let _ = Bounded10Bytes(());
200/// ```
201///
202/// ```compile_fail,E0308
203/// #![feature(generic_const_exprs)]
204/// struct Bounded10Bytes<T: size_trait::BoundedSize<1, 10>>(T);
205/// let _ = Bounded10Bytes([0u8; 11]);
206/// ```
207///
208/// ```compile_fail,E0308
209/// #![feature(generic_const_exprs)]
210/// struct TwoBytes([u8; 2]);
211/// impl size_trait::BoundedSize<15, 100> for TwoBytes {}
212/// ```
213pub trait BoundedSize<const MIN: usize, const MAX: usize>: MinSize<MIN> + MaxSize<MAX> {}
214
215impl<const MIN: usize, const MAX: usize, T: MinSize<MIN> + MaxSize<MAX>> BoundedSize<MIN, MAX>
216 for T
217{
218}
219
220/// Describes a type whose size is exactly `SIZE` bytes.
221///
222/// # Examples
223///
224/// ```
225/// #![feature(generic_const_exprs)]
226/// struct OneByte<T: size_trait::Size<1>>(T);
227/// let _ = OneByte(0u8);
228///
229/// struct FourBytes<T: size_trait::Size<4>>(T);
230/// let _ = FourBytes([0u8; 4]);
231/// let _ = FourBytes(0u32);
232/// ```
233///
234/// # Compilation Errors
235///
236/// ```compile_fail,E0308
237/// #![feature(generic_const_exprs)]
238/// struct OneByte(u8);
239/// impl size_trait::Size<0> for OneByte {}
240/// ```
241///
242/// ```compile_fail,E0308
243/// #![feature(generic_const_exprs)]
244/// struct ZeroBytes;
245/// impl size_trait::Size<1> for ZeroBytes {}
246/// ```
247///
248/// ```compile_fail,E0308
249/// #![feature(generic_const_exprs)]
250/// struct ZeroBytes<T: size_trait::Size<0>>(T);
251/// let _ = ZeroBytes(0u8);
252/// ```
253///
254/// ```compile_fail,E0308
255/// #![feature(generic_const_exprs)]
256/// struct TwoBytes<T: size_trait::Size<2>>(T);
257/// let _ = TwoBytes(0u8);
258/// ```
259pub trait Size<const SIZE: usize>: sealed::Size<SIZE> {}
260
261impl<const SIZE: usize, T: sealed::Size<SIZE>> Size<SIZE> for T {}
262
263/// Describes a type whose size is zero.
264///
265/// # Examples
266///
267/// ```
268/// #![feature(generic_const_exprs)]
269/// struct Zst<T: size_trait::ZeroSize<true>>(T);
270/// let _ = Zst(());
271/// let _ = Zst(core::marker::PhantomData::<u8>);
272/// let _ = Zst([] as [u64; 0]);
273/// let _ = Zst(Zst(Zst(Zst((Zst(()), Zst(()))))));
274///
275/// struct NonZst<T: size_trait::ZeroSize<false>>(T);
276/// let _ = NonZst(0);
277/// let _ = NonZst(true);
278/// let _ = NonZst(&[] as &[u64]);
279/// let _ = NonZst([0u8; 100]);
280/// let _ = NonZst(NonZst(NonZst(NonZst((NonZst(0u8), NonZst(0u8))))));
281/// ```
282///
283/// # Compilation Errors
284///
285/// ```compile_fail,E0308
286/// #![feature(generic_const_exprs)]
287/// struct OneByte(u8);
288/// impl size_trait::ZeroSize<true> for OneByte {}
289/// ```
290///
291/// ```compile_fail,E0308
292/// #![feature(generic_const_exprs)]
293/// struct ZeroBytes;
294/// impl size_trait::ZeroSize<false> for ZeroBytes {}
295/// ```
296///
297/// ```compile_fail,E0308
298/// #![feature(generic_const_exprs)]
299/// struct Nothing<T: size_trait::ZeroSize<true>>(T);
300/// let _ = Nothing(0u8);
301/// ```
302///
303/// ```compile_fail,E0308
304/// #![feature(generic_const_exprs)]
305/// struct Something<T: size_trait::ZeroSize<false>>(T);
306/// let _ = Something(());
307/// ```
308pub trait ZeroSize<const ZERO: bool>: sealed::ZeroSize<ZERO> {}
309
310impl<const ZERO: bool, T: sealed::ZeroSize<ZERO>> ZeroSize<ZERO> for T {}
311
312#[cfg(test)]
313mod tests {
314 use crate::{BoundedSize, MaxSize, MinSize, Size, SizeGreaterThan, SizeLessThan, ZeroSize};
315
316 #[test]
317 fn zero_size() {
318 struct Nothing<T: ZeroSize<true>>(T);
319 struct Something<T: ZeroSize<false>>(T);
320
321 let _ = Nothing(());
322 let _ = Nothing(core::marker::PhantomData::<u8>);
323 let _ = Nothing([] as [u64; 0]);
324 let _ = Nothing(Nothing(Nothing(Nothing((Nothing(()), Nothing(()))))));
325 // let _ = Nothing(0u8); // error!
326
327 let _ = Something(0);
328 let _ = Something(true);
329 let _ = Something(&[] as &[u64]);
330 let _ = Something([0u8; 100]);
331 // let _ = Something(()); // error!
332 }
333
334 #[test]
335 fn size() {
336 struct ZeroBytes<T: Size<0>>(T);
337 let _ = ZeroBytes(());
338 let _ = ZeroBytes(core::marker::PhantomData::<u8>);
339 let _ = ZeroBytes([] as [u64; 0]);
340
341 struct TwoBytes<T: Size<2>>(T);
342 let _ = TwoBytes([0u8; 2]);
343 let _ = TwoBytes(0u16);
344 let _ = TwoBytes((0u8, 0u8));
345 }
346
347 #[test]
348 fn size_less_than() {
349 struct LessThan10Bytes<T: SizeLessThan<10, true>>(T);
350 let _ = LessThan10Bytes(());
351 let _ = LessThan10Bytes([0u8; 9]);
352
353 struct LessThan1Byte<T: SizeLessThan<1, true>>(T);
354 let _ = LessThan1Byte(());
355
356 struct NotLessThan2Bytes<T: SizeLessThan<2, false>>(T);
357 let _ = NotLessThan2Bytes((0u8, 0u8));
358 let _ = NotLessThan2Bytes([0u8; 20]);
359 }
360
361 #[test]
362 fn size_greater_than() {
363 struct GreaterThan10Bytes<T: SizeGreaterThan<10, true>>(T);
364 let _ = GreaterThan10Bytes([0u8; 11]);
365 let _ = GreaterThan10Bytes(0u128);
366
367 struct NotGreaterThan1Byte<T: SizeGreaterThan<1, false>>(T);
368 let _ = NotGreaterThan1Byte(());
369 let _ = NotGreaterThan1Byte(0u8);
370 }
371
372 #[test]
373 fn min_size() {
374 struct MinSize10Bytes<T: MinSize<10>>(T);
375 let _ = MinSize10Bytes([0u8; 10]);
376 let _ = MinSize10Bytes(0u128);
377
378 struct MinSize1Byte<T: MinSize<1>>(T);
379 let _ = MinSize1Byte([0u8; 10]);
380 let _ = MinSize1Byte(0u8);
381 }
382
383 #[test]
384 fn max_size() {
385 struct MaxSize10Bytes<T: MaxSize<10>>(T);
386 let _ = MaxSize10Bytes(());
387 let _ = MaxSize10Bytes([0u8; 9]);
388
389 struct MaxSize1Byte<T: MaxSize<1>>(T);
390 let _ = MaxSize1Byte(());
391 let _ = MaxSize1Byte(0u8);
392 }
393
394 #[test]
395 fn bounded() {
396 struct Bounded10Bytes<T: BoundedSize<1, 10>>(T);
397 let _ = Bounded10Bytes(0u8);
398 let _ = Bounded10Bytes([0u8; 9]);
399
400 struct Bounded1Byte<T: BoundedSize<1, 1>>(T);
401 let _ = Bounded1Byte(0u8);
402 }
403}