postcard/
max_size.rs
1#[cfg(feature = "alloc")]
2extern crate alloc;
3
4#[cfg(feature = "alloc")]
5use alloc::{boxed::Box, rc::Rc};
6
7#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))]
8use alloc::sync::Arc;
9
10use crate::varint::varint_max;
11use core::{
12 marker::PhantomData,
13 num::{
14 NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128,
15 NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize,
16 },
17};
18
19pub trait MaxSize {
22 const POSTCARD_MAX_SIZE: usize;
25}
26
27impl MaxSize for bool {
28 const POSTCARD_MAX_SIZE: usize = 1;
29}
30
31impl MaxSize for i8 {
32 const POSTCARD_MAX_SIZE: usize = 1;
33}
34
35impl MaxSize for i16 {
36 const POSTCARD_MAX_SIZE: usize = varint_max::<Self>();
37}
38
39impl MaxSize for i32 {
40 const POSTCARD_MAX_SIZE: usize = varint_max::<Self>();
41}
42
43impl MaxSize for i64 {
44 const POSTCARD_MAX_SIZE: usize = varint_max::<Self>();
45}
46
47impl MaxSize for i128 {
48 const POSTCARD_MAX_SIZE: usize = varint_max::<Self>();
49}
50
51impl MaxSize for isize {
52 const POSTCARD_MAX_SIZE: usize = varint_max::<Self>();
53}
54
55impl MaxSize for u8 {
56 const POSTCARD_MAX_SIZE: usize = 1;
57}
58
59impl MaxSize for u16 {
60 const POSTCARD_MAX_SIZE: usize = varint_max::<Self>();
61}
62
63impl MaxSize for u32 {
64 const POSTCARD_MAX_SIZE: usize = varint_max::<Self>();
65}
66
67impl MaxSize for u64 {
68 const POSTCARD_MAX_SIZE: usize = varint_max::<Self>();
69}
70
71impl MaxSize for u128 {
72 const POSTCARD_MAX_SIZE: usize = varint_max::<Self>();
73}
74
75impl MaxSize for usize {
76 const POSTCARD_MAX_SIZE: usize = varint_max::<Self>();
77}
78
79impl MaxSize for f32 {
80 const POSTCARD_MAX_SIZE: usize = 4;
81}
82
83impl MaxSize for f64 {
84 const POSTCARD_MAX_SIZE: usize = 8;
85}
86
87impl MaxSize for char {
88 const POSTCARD_MAX_SIZE: usize = 5;
89}
90
91impl<T: MaxSize> MaxSize for Option<T> {
92 const POSTCARD_MAX_SIZE: usize = T::POSTCARD_MAX_SIZE + 1;
93}
94
95impl<T: MaxSize, E: MaxSize> MaxSize for Result<T, E> {
96 const POSTCARD_MAX_SIZE: usize = max(T::POSTCARD_MAX_SIZE, E::POSTCARD_MAX_SIZE) + 1;
97}
98
99impl MaxSize for () {
100 const POSTCARD_MAX_SIZE: usize = 0;
101}
102
103impl<T: MaxSize, const N: usize> MaxSize for [T; N] {
104 const POSTCARD_MAX_SIZE: usize = T::POSTCARD_MAX_SIZE * N;
105}
106
107impl<T: MaxSize> MaxSize for &'_ T {
108 const POSTCARD_MAX_SIZE: usize = T::POSTCARD_MAX_SIZE;
109}
110
111impl<T: MaxSize> MaxSize for &'_ mut T {
112 const POSTCARD_MAX_SIZE: usize = T::POSTCARD_MAX_SIZE;
113}
114
115impl MaxSize for NonZeroI8 {
116 const POSTCARD_MAX_SIZE: usize = i8::POSTCARD_MAX_SIZE;
117}
118
119impl MaxSize for NonZeroI16 {
120 const POSTCARD_MAX_SIZE: usize = i16::POSTCARD_MAX_SIZE;
121}
122
123impl MaxSize for NonZeroI32 {
124 const POSTCARD_MAX_SIZE: usize = i32::POSTCARD_MAX_SIZE;
125}
126
127impl MaxSize for NonZeroI64 {
128 const POSTCARD_MAX_SIZE: usize = i64::POSTCARD_MAX_SIZE;
129}
130
131impl MaxSize for NonZeroI128 {
132 const POSTCARD_MAX_SIZE: usize = i128::POSTCARD_MAX_SIZE;
133}
134
135impl MaxSize for NonZeroIsize {
136 const POSTCARD_MAX_SIZE: usize = isize::POSTCARD_MAX_SIZE;
137}
138
139impl MaxSize for NonZeroU8 {
140 const POSTCARD_MAX_SIZE: usize = u8::POSTCARD_MAX_SIZE;
141}
142
143impl MaxSize for NonZeroU16 {
144 const POSTCARD_MAX_SIZE: usize = u16::POSTCARD_MAX_SIZE;
145}
146
147impl MaxSize for NonZeroU32 {
148 const POSTCARD_MAX_SIZE: usize = u32::POSTCARD_MAX_SIZE;
149}
150
151impl MaxSize for NonZeroU64 {
152 const POSTCARD_MAX_SIZE: usize = u64::POSTCARD_MAX_SIZE;
153}
154
155impl MaxSize for NonZeroU128 {
156 const POSTCARD_MAX_SIZE: usize = u128::POSTCARD_MAX_SIZE;
157}
158
159impl MaxSize for NonZeroUsize {
160 const POSTCARD_MAX_SIZE: usize = usize::POSTCARD_MAX_SIZE;
161}
162
163impl<T> MaxSize for PhantomData<T> {
164 const POSTCARD_MAX_SIZE: usize = 0;
165}
166
167impl<A: MaxSize> MaxSize for (A,) {
168 const POSTCARD_MAX_SIZE: usize = A::POSTCARD_MAX_SIZE;
169}
170
171impl<A: MaxSize, B: MaxSize> MaxSize for (A, B) {
172 const POSTCARD_MAX_SIZE: usize = A::POSTCARD_MAX_SIZE + B::POSTCARD_MAX_SIZE;
173}
174
175impl<A: MaxSize, B: MaxSize, C: MaxSize> MaxSize for (A, B, C) {
176 const POSTCARD_MAX_SIZE: usize =
177 A::POSTCARD_MAX_SIZE + B::POSTCARD_MAX_SIZE + C::POSTCARD_MAX_SIZE;
178}
179
180impl<A: MaxSize, B: MaxSize, C: MaxSize, D: MaxSize> MaxSize for (A, B, C, D) {
181 const POSTCARD_MAX_SIZE: usize =
182 A::POSTCARD_MAX_SIZE + B::POSTCARD_MAX_SIZE + C::POSTCARD_MAX_SIZE + D::POSTCARD_MAX_SIZE;
183}
184
185impl<A: MaxSize, B: MaxSize, C: MaxSize, D: MaxSize, E: MaxSize> MaxSize for (A, B, C, D, E) {
186 const POSTCARD_MAX_SIZE: usize = A::POSTCARD_MAX_SIZE
187 + B::POSTCARD_MAX_SIZE
188 + C::POSTCARD_MAX_SIZE
189 + D::POSTCARD_MAX_SIZE
190 + E::POSTCARD_MAX_SIZE;
191}
192
193impl<A: MaxSize, B: MaxSize, C: MaxSize, D: MaxSize, E: MaxSize, F: MaxSize> MaxSize
194 for (A, B, C, D, E, F)
195{
196 const POSTCARD_MAX_SIZE: usize = A::POSTCARD_MAX_SIZE
197 + B::POSTCARD_MAX_SIZE
198 + C::POSTCARD_MAX_SIZE
199 + D::POSTCARD_MAX_SIZE
200 + E::POSTCARD_MAX_SIZE
201 + F::POSTCARD_MAX_SIZE;
202}
203
204#[cfg(feature = "alloc")]
205#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
206impl<T: MaxSize> MaxSize for Box<T> {
207 const POSTCARD_MAX_SIZE: usize = T::POSTCARD_MAX_SIZE;
208}
209
210#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))]
211#[cfg_attr(docsrs, doc(cfg(all(feature = "alloc", target_has_atomic = "ptr"))))]
212impl<T: MaxSize> MaxSize for Arc<T> {
213 const POSTCARD_MAX_SIZE: usize = T::POSTCARD_MAX_SIZE;
214}
215
216#[cfg(feature = "alloc")]
217#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
218impl<T: MaxSize> MaxSize for Rc<T> {
219 const POSTCARD_MAX_SIZE: usize = T::POSTCARD_MAX_SIZE;
220}
221
222#[cfg(feature = "heapless")]
223#[cfg_attr(docsrs, doc(cfg(feature = "heapless")))]
224impl<T: MaxSize, const N: usize> MaxSize for heapless::Vec<T, N> {
225 const POSTCARD_MAX_SIZE: usize = <[T; N]>::POSTCARD_MAX_SIZE + varint_size(N);
226}
227
228#[cfg(feature = "heapless")]
229#[cfg_attr(docsrs, doc(cfg(feature = "heapless")))]
230impl<const N: usize> MaxSize for heapless::String<N> {
231 const POSTCARD_MAX_SIZE: usize = <[u8; N]>::POSTCARD_MAX_SIZE + varint_size(N);
232}
233
234#[cfg(feature = "heapless")]
235const fn varint_size(max_n: usize) -> usize {
236 const BITS_PER_BYTE: usize = 8;
237 const BITS_PER_VARINT_BYTE: usize = 7;
238
239 if max_n == 0 {
240 return 1;
241 }
242
243 let bits = core::mem::size_of::<usize>() * BITS_PER_BYTE - max_n.leading_zeros() as usize;
245
246 let roundup_bits = bits + (BITS_PER_VARINT_BYTE - 1);
250
251 roundup_bits / BITS_PER_VARINT_BYTE
253}
254
255const fn max(lhs: usize, rhs: usize) -> usize {
256 if lhs > rhs {
257 lhs
258 } else {
259 rhs
260 }
261}
262
263#[cfg(any(feature = "alloc", feature = "use-std"))]
264#[cfg(test)]
265mod tests {
266 extern crate alloc;
267
268 use super::*;
269 use alloc::rc::Rc;
270
271 #[cfg(target_has_atomic = "ptr")]
272 use alloc::sync::Arc;
273
274 #[test]
275 fn box_max_size() {
276 assert_eq!(Box::<u8>::POSTCARD_MAX_SIZE, 1);
277 assert_eq!(Box::<u32>::POSTCARD_MAX_SIZE, 5);
278 assert_eq!(Box::<(u128, [u8; 8])>::POSTCARD_MAX_SIZE, 27);
279 }
280
281 #[test]
282 #[cfg(target_has_atomic = "ptr")]
283 fn arc_max_size() {
284 assert_eq!(Arc::<u8>::POSTCARD_MAX_SIZE, 1);
285 assert_eq!(Arc::<u32>::POSTCARD_MAX_SIZE, 5);
286 assert_eq!(Arc::<(u128, [u8; 8])>::POSTCARD_MAX_SIZE, 27);
287 }
288
289 #[test]
290 fn rc_max_size() {
291 assert_eq!(Rc::<u8>::POSTCARD_MAX_SIZE, 1);
292 assert_eq!(Rc::<u32>::POSTCARD_MAX_SIZE, 5);
293 assert_eq!(Rc::<(u128, [u8; 8])>::POSTCARD_MAX_SIZE, 27);
294 }
295}