qudit_core/utils/
storage.rs1use serde::{Serialize, de::DeserializeOwned};
2
3pub trait CompactStorage: Copy + 'static {
8 type InlineType: Copy + Default + 'static + Serialize + DeserializeOwned;
10 const CONVERSION_INFALLIBLE: bool;
12
13 fn to_inline(value: Self) -> Result<Self::InlineType, Self>;
16 fn from_inline(value: Self::InlineType) -> Self;
19
20 fn to_inline_unchecked(value: Self) -> Self::InlineType;
26}
27
28impl CompactStorage for i8 {
30 type InlineType = i8;
31 const CONVERSION_INFALLIBLE: bool = true;
32
33 #[inline(always)]
34 fn to_inline(value: Self) -> Result<Self::InlineType, Self> {
35 Ok(value)
36 }
37
38 #[inline(always)]
39 fn from_inline(value: Self::InlineType) -> Self {
40 value
41 }
42
43 #[inline(always)]
44 fn to_inline_unchecked(value: Self) -> Self::InlineType {
45 value
46 }
47}
48
49impl CompactStorage for i16 {
50 type InlineType = i8;
51 const CONVERSION_INFALLIBLE: bool = false;
52
53 #[inline]
54 fn to_inline(value: Self) -> Result<Self::InlineType, Self> {
55 if value >= i8::MIN as i16 && value <= i8::MAX as i16 {
56 Ok(value as i8)
57 } else {
58 Err(value)
59 }
60 }
61
62 #[inline(always)]
63 fn from_inline(value: Self::InlineType) -> Self {
64 value as i16
65 }
66
67 #[inline(always)]
68 fn to_inline_unchecked(value: Self) -> Self::InlineType {
69 value as i8
70 }
71}
72
73impl CompactStorage for i32 {
74 type InlineType = i8;
75 const CONVERSION_INFALLIBLE: bool = false;
76
77 #[inline]
78 fn to_inline(value: Self) -> Result<Self::InlineType, Self> {
79 if value >= i8::MIN as i32 && value <= i8::MAX as i32 {
80 Ok(value as i8)
81 } else {
82 Err(value)
83 }
84 }
85 #[inline(always)]
86 fn from_inline(value: Self::InlineType) -> Self {
87 value as i32
88 }
89
90 #[inline(always)]
91 fn to_inline_unchecked(value: Self) -> Self::InlineType {
92 value as i8
93 }
94}
95
96impl CompactStorage for i64 {
97 type InlineType = i8;
98 const CONVERSION_INFALLIBLE: bool = false;
99
100 #[inline]
101 fn to_inline(value: Self) -> Result<Self::InlineType, Self> {
102 if value >= i8::MIN as i64 && value <= i8::MAX as i64 {
103 Ok(value as i8)
104 } else {
105 Err(value)
106 }
107 }
108
109 #[inline(always)]
110 fn from_inline(value: Self::InlineType) -> Self {
111 value as i64
112 }
113
114 #[inline(always)]
115 fn to_inline_unchecked(value: Self) -> Self::InlineType {
116 value as i8
117 }
118}
119
120impl CompactStorage for i128 {
121 type InlineType = i8;
122 const CONVERSION_INFALLIBLE: bool = false;
123
124 #[inline]
125 fn to_inline(value: Self) -> Result<Self::InlineType, Self> {
126 if value >= i8::MIN as i128 && value <= i8::MAX as i128 {
127 Ok(value as i8)
128 } else {
129 Err(value)
130 }
131 }
132
133 #[inline(always)]
134 fn from_inline(value: Self::InlineType) -> Self {
135 value as i128
136 }
137
138 #[inline(always)]
139 fn to_inline_unchecked(value: Self) -> Self::InlineType {
140 value as i8
141 }
142}
143
144impl CompactStorage for isize {
145 type InlineType = i8;
146 const CONVERSION_INFALLIBLE: bool = false;
147
148 #[inline]
149 fn to_inline(value: Self) -> Result<Self::InlineType, Self> {
150 if value >= i8::MIN as isize && value <= i8::MAX as isize {
151 Ok(value as i8)
152 } else {
153 Err(value)
154 }
155 }
156
157 #[inline(always)]
158 fn from_inline(value: Self::InlineType) -> Self {
159 value as isize
160 }
161
162 #[inline(always)]
163 fn to_inline_unchecked(value: Self) -> Self::InlineType {
164 value as i8
165 }
166}
167
168impl CompactStorage for u8 {
170 type InlineType = u8;
171 const CONVERSION_INFALLIBLE: bool = true;
172
173 #[inline(always)]
174 fn to_inline(value: Self) -> Result<Self::InlineType, Self> {
175 Ok(value)
176 }
177
178 #[inline(always)]
179 fn from_inline(value: Self::InlineType) -> Self {
180 value
181 }
182
183 #[inline(always)]
184 fn to_inline_unchecked(value: Self) -> Self::InlineType {
185 value
186 }
187}
188
189impl CompactStorage for u16 {
190 type InlineType = u8;
191 const CONVERSION_INFALLIBLE: bool = false;
192
193 #[inline]
194 fn to_inline(value: Self) -> Result<Self::InlineType, Self> {
195 if value <= u8::MAX as u16 {
196 Ok(value as u8)
197 } else {
198 Err(value)
199 }
200 }
201
202 #[inline(always)]
203 fn from_inline(value: Self::InlineType) -> Self {
204 value as u16
205 }
206
207 #[inline(always)]
208 fn to_inline_unchecked(value: Self) -> Self::InlineType {
209 value as u8
210 }
211}
212
213impl CompactStorage for u32 {
214 type InlineType = u8;
215 const CONVERSION_INFALLIBLE: bool = false;
216
217 #[inline]
218 fn to_inline(value: Self) -> Result<Self::InlineType, Self> {
219 if value <= u8::MAX as u32 {
220 Ok(value as u8)
221 } else {
222 Err(value)
223 }
224 }
225
226 #[inline(always)]
227 fn from_inline(value: Self::InlineType) -> Self {
228 value as u32
229 }
230
231 #[inline(always)]
232 fn to_inline_unchecked(value: Self) -> Self::InlineType {
233 value as u8
234 }
235}
236
237impl CompactStorage for u64 {
238 type InlineType = u8;
239 const CONVERSION_INFALLIBLE: bool = false;
240
241 #[inline]
242 fn to_inline(value: Self) -> Result<Self::InlineType, Self> {
243 if value <= u8::MAX as u64 {
244 Ok(value as u8)
245 } else {
246 Err(value)
247 }
248 }
249
250 #[inline(always)]
251 fn from_inline(value: Self::InlineType) -> Self {
252 value as u64
253 }
254
255 #[inline(always)]
256 fn to_inline_unchecked(value: Self) -> Self::InlineType {
257 value as u8
258 }
259}
260
261impl CompactStorage for u128 {
262 type InlineType = u8;
263 const CONVERSION_INFALLIBLE: bool = false;
264
265 #[inline]
266 fn to_inline(value: Self) -> Result<Self::InlineType, Self> {
267 if value <= u8::MAX as u128 {
268 Ok(value as u8)
269 } else {
270 Err(value)
271 }
272 }
273
274 #[inline(always)]
275 fn from_inline(value: Self::InlineType) -> Self {
276 value as u128
277 }
278
279 #[inline(always)]
280 fn to_inline_unchecked(value: Self) -> Self::InlineType {
281 value as u8
282 }
283}
284
285impl CompactStorage for usize {
286 type InlineType = u8;
287 const CONVERSION_INFALLIBLE: bool = false;
288
289 #[inline]
290 fn to_inline(value: Self) -> Result<Self::InlineType, Self> {
291 if value <= u8::MAX as usize {
292 Ok(value as u8)
293 } else {
294 Err(value)
295 }
296 }
297
298 #[inline(always)]
299 fn from_inline(value: Self::InlineType) -> Self {
300 value as usize
301 }
302
303 #[inline(always)]
304 fn to_inline_unchecked(value: Self) -> Self::InlineType {
305 value as u8
306 }
307}
308
309#[cfg(test)]
310mod tests {
311 use super::*;
312
313 #[test]
315 fn test_infallible_conversions() {
316 #![allow(clippy::assertions_on_constants)]
317 assert!(i8::CONVERSION_INFALLIBLE);
318 assert!(u8::CONVERSION_INFALLIBLE);
319 assert_eq!(i8::to_inline(42), Ok(42));
320 assert_eq!(u8::to_inline(42), Ok(42));
321 }
322
323 #[test]
325 fn test_signed_conversions() {
326 assert_eq!(i16::to_inline(42), Ok(42));
328 assert_eq!(i32::to_inline(-42), Ok(-42));
329 assert_eq!(i64::to_inline(127), Ok(127));
330 assert_eq!(i128::to_inline(-128), Ok(-128));
331
332 assert!(i16::to_inline(200).is_err());
334 assert!(i32::to_inline(1000).is_err());
335 assert!(i64::to_inline(i64::MAX).is_err());
336 assert!(i128::to_inline(i128::MAX).is_err());
337 }
338
339 #[test]
341 fn test_unsigned_conversions() {
342 assert_eq!(u16::to_inline(42), Ok(42));
344 assert_eq!(u32::to_inline(255), Ok(255));
345 assert_eq!(u64::to_inline(100), Ok(100));
346 assert_eq!(u128::to_inline(200), Ok(200));
347
348 assert!(u16::to_inline(300).is_err());
350 assert!(u32::to_inline(1000).is_err());
351 assert!(u64::to_inline(u64::MAX).is_err());
352 assert!(u128::to_inline(u128::MAX).is_err());
353 }
354
355 #[test]
357 fn test_round_trip() {
358 assert_eq!(i128::from_inline(42), 42i128);
359 assert_eq!(u128::from_inline(255), 255u128);
360 }
361}