epserde 0.12.6

ε-serde is an ε-copy (i.e., almost zero-copy) serialization/deserialization framework
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
/*
 * SPDX-FileCopyrightText: 2025 Sebastiano Vigna
 *
 * SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
 */

use epserde::prelude::*;
use epserde::ser::SerType;
use std::collections::hash_map::DefaultHasher;
use std::hash::Hasher;

fn get_type_hash<T: TypeHash + ?Sized>() -> u64 {
    let mut hasher = DefaultHasher::new();
    T::type_hash(&mut hasher);
    hasher.finish()
}

fn get_align_hash<T: AlignHash + ?Sized>() -> u64 {
    let mut hasher = DefaultHasher::new();
    let mut offset = 0;
    T::align_hash(&mut hasher, &mut offset);
    hasher.finish()
}

#[derive(Epserde, Debug, PartialEq)]
struct MyStruct {
    a: i32,
    b: f64,
}

#[derive(Epserde, Debug, PartialEq, Eq)]
struct MyStructGeneric<T: PartialEq> {
    a: T,
}

#[derive(Epserde, Debug, PartialEq)]
enum MyEnum {
    A,
    B(i32),
    C { a: i32, b: f64 },
}

#[derive(Epserde, Debug, PartialEq, Eq)]
struct MyStructConst<const N: usize> {
    a: [i32; N],
}

#[derive(Epserde, Debug, PartialEq, Eq)]
struct MyStructMixed<T: PartialEq, const N: usize> {
    a: T,
    b: [i32; N],
}

#[derive(Epserde, Debug, PartialEq, Eq)]
struct MyStructConstThenType<const N: usize, T: PartialEq> {
    a: [i32; N],
    b: T,
}

// x86_64 / aarch64 regression tests

#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
#[test]
fn test_primitive_types() {
    assert_eq!(get_type_hash::<isize>(), 0xad77ef2a0c071b87);
    assert_eq!(get_align_hash::<isize>(), 0xd3eed631c35c21cf);
    assert_eq!(get_type_hash::<i8>(), 0x1bb527fe1af58754);
    assert_eq!(get_align_hash::<i8>(), 0x7359aa1156ce877a);
    assert_eq!(get_type_hash::<i16>(), 0x568b3e81c4910f1b);
    assert_eq!(get_align_hash::<i16>(), 0xeaf7d87e9d1ee4bc);
    assert_eq!(get_type_hash::<i32>(), 0x19b22886e521147a);
    assert_eq!(get_align_hash::<i32>(), 0x6881f435bc0ca85f);
    assert_eq!(get_type_hash::<i64>(), 0xba3703df82fb4e98);
    assert_eq!(get_align_hash::<i64>(), 0xd3eed631c35c21cf);
    assert_eq!(get_type_hash::<i128>(), 0x29a957130a3bc847);
    assert_eq!(get_align_hash::<i128>(), 0x6c9b3167d412086c);
    assert_eq!(get_type_hash::<usize>(), 0xa12462c6d36e68b0);
    assert_eq!(get_align_hash::<usize>(), 0xd3eed631c35c21cf);
    assert_eq!(get_type_hash::<u8>(), 0xbc9d6eeaea22ffb5);
    assert_eq!(get_align_hash::<u8>(), 0x7359aa1156ce877a);
    assert_eq!(get_type_hash::<u16>(), 0x704072ef7f3dd44);
    assert_eq!(get_align_hash::<u16>(), 0xeaf7d87e9d1ee4bc);
    assert_eq!(get_type_hash::<u32>(), 0x20aa0c10687491ad);
    assert_eq!(get_align_hash::<u32>(), 0x6881f435bc0ca85f);
    assert_eq!(get_type_hash::<u64>(), 0xaee7f05a097ffa16);
    assert_eq!(get_align_hash::<u64>(), 0xd3eed631c35c21cf);
    assert_eq!(get_type_hash::<u128>(), 0x19c3bfd795ae2ec8);
    assert_eq!(get_align_hash::<u128>(), 0x6c9b3167d412086c);
    assert_eq!(get_type_hash::<f32>(), 0xc80e25fc3a1c97d8);
    assert_eq!(get_align_hash::<f32>(), 0x6881f435bc0ca85f);
    assert_eq!(get_type_hash::<f64>(), 0x7b785833ec3cc6e8);
    assert_eq!(get_align_hash::<f64>(), 0xd3eed631c35c21cf);
    assert_eq!(get_type_hash::<bool>(), 0x947c0c03c59c6f07);
    assert_eq!(get_align_hash::<bool>(), 0x7359aa1156ce877a);
    assert_eq!(get_type_hash::<char>(), 0x80aa991b46310ff6);
    assert_eq!(get_align_hash::<char>(), 0x6881f435bc0ca85f);
    assert_eq!(get_type_hash::<()>(), 0x2439715d39cd513);
    assert_eq!(get_align_hash::<()>(), 0x76be999e3e25b2a0);
}

#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
#[test]
fn test_option() {
    assert_eq!(get_type_hash::<Option<i32>>(), 0x36d9437e00a00833);
    assert_eq!(get_align_hash::<Option<i32>>(), 0xd1fba762150c532c);
}

#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
#[test]
fn test_string_types() {
    assert_eq!(get_type_hash::<String>(), 0xe4297f5be0f5dd50);
    assert_eq!(get_type_hash::<str>(), 0x393e833de113cd8c);
    assert_eq!(get_type_hash::<Box<str>>(), 0x19aa1d67f7ad7a3e);
    assert_eq!(get_align_hash::<Box<str>>(), 0xd1fba762150c532c);
}

#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
#[test]
fn test_array_types() {
    assert_eq!(get_type_hash::<[i32; 5]>(), 0xff020632241e51b0);
    assert_eq!(get_align_hash::<[i32; 5]>(), 0x6881f435bc0ca85f);
}

#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
#[test]
fn test_slice_types() {
    assert_eq!(get_type_hash::<[i32]>(), 0xe053d268c8ad5c04);
    assert_eq!(get_type_hash::<SerType<&[i32]>>(), 0x400f9211e94c1834);
    assert_eq!(get_align_hash::<SerType<&[i32]>>(), 0x6881f435bc0ca85f);
}

#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
#[test]
fn test_boxed_slice_types() {
    assert_eq!(get_type_hash::<Box<[i32]>>(), 0x400f9211e94c1834);
    assert_eq!(get_align_hash::<Box<[i32]>>(), 0x6881f435bc0ca85f);
}

#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
#[test]
fn test_tuple_types() {
    assert_eq!(get_type_hash::<(i32,)>(), 0x4c6eb7a52a31e7b9);
    assert_eq!(get_align_hash::<(i32,)>(), 0x6881f435bc0ca85f);
    assert_eq!(get_type_hash::<(i32, f64)>(), 0x6c1bf8932e12dc1);
}

#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
#[test]
fn test_vec_types() {
    assert_eq!(get_type_hash::<Vec<i32>>(), 0x400f9211e94c1834);
}

#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
#[test]
fn test_stdlib_types() {
    use core::ops::{
        Bound, ControlFlow, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
    };
    #[cfg(feature = "std")]
    use std::collections::hash_map::DefaultHasher;
    #[cfg(feature = "std")]
    assert_eq!(get_type_hash::<DefaultHasher>(), 0x216366ce6df79e86);

    assert_eq!(get_type_hash::<Range<i32>>(), 0x837a1968d53dcff1);
    assert_eq!(get_align_hash::<Range<i32>>(), 0xde0fd80637b3a4da);
    assert_eq!(get_type_hash::<RangeFrom<i32>>(), 0xad8267db843d93b8);
    assert_eq!(get_align_hash::<RangeFrom<i32>>(), 0x6881f435bc0ca85f);
    assert_eq!(get_type_hash::<RangeInclusive<i32>>(), 0xf90fab627ecbd1a6);
    assert_eq!(get_align_hash::<RangeInclusive<i32>>(), 0xf875a366be1ab169);
    assert_eq!(get_type_hash::<RangeTo<i32>>(), 0xd889856367fa2fe3);
    assert_eq!(get_align_hash::<RangeTo<i32>>(), 0x6881f435bc0ca85f);
    assert_eq!(get_type_hash::<RangeToInclusive<i32>>(), 0xc3682b190d94704d);
    assert_eq!(
        get_align_hash::<RangeToInclusive<i32>>(),
        0x6881f435bc0ca85f
    );
    assert_eq!(get_type_hash::<RangeFull>(), 0x1d5d4cc6e963d594);
    assert_eq!(get_align_hash::<RangeFull>(), 0xd1fba762150c532c);
    assert_eq!(get_type_hash::<Bound<i32>>(), 0x1f77c5db6e0be477);
    assert_eq!(get_align_hash::<Bound<i32>>(), 0xd1fba762150c532c);
    assert_eq!(get_type_hash::<ControlFlow<i32, f64>>(), 0x5f4feceae713afe0);
    assert_eq!(
        get_align_hash::<ControlFlow<i32, f64>>(),
        0xd1fba762150c532c
    );
}

#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
#[test]
fn test_derive_struct() {
    assert_eq!(get_type_hash::<MyStruct>(), 0x65125c7b120befff);
    assert_eq!(get_align_hash::<MyStruct>(), 0xc3caaeef7aa4605a);
}

#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
#[test]
fn test_derive_struct_generic() {
    assert_eq!(get_type_hash::<MyStructGeneric<i32>>(), 0x6dced006dd1acb8f);
    assert_eq!(get_align_hash::<MyStructGeneric<i32>>(), 0x6881f435bc0ca85f);
}

#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
#[test]
fn test_derive_enum() {
    assert_eq!(get_type_hash::<MyEnum>(), 0xf5e19aa69f2d9fac);
    assert_eq!(get_align_hash::<MyEnum>(), 0x7c4ea1189a62724c);
}

#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
#[test]
fn test_derive_struct_const() {
    assert_eq!(get_type_hash::<MyStructConst<5>>(), 0x87c97042d431cbf7);
    assert_eq!(get_align_hash::<MyStructConst<5>>(), 0x6881f435bc0ca85f);
}

#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
#[test]
fn test_derive_struct_mixed() {
    assert_eq!(get_type_hash::<MyStructMixed<i32, 5>>(), 0xa8a943379dbe6ea7);
    assert_eq!(
        get_align_hash::<MyStructMixed<i32, 5>>(),
        0xde0fd80637b3a4da
    );
}

#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
#[test]
fn test_derive_struct_const_then_type() {
    assert_eq!(
        get_type_hash::<MyStructConstThenType<5, i32>>(),
        0xba025cd70e024ad5
    );
    assert_eq!(
        get_align_hash::<MyStructConstThenType<5, i32>>(),
        0xde0fd80637b3a4da
    );
}

// i686 regression tests

#[cfg(target_arch = "x86")]
#[test]
fn test_primitive_types() {
    assert_eq!(get_type_hash::<isize>(), 0xad77ef2a0c071b87);
    assert_eq!(get_align_hash::<isize>(), 0x832178dce3dc2030);
    assert_eq!(get_type_hash::<i8>(), 0x1bb527fe1af58754);
    assert_eq!(get_align_hash::<i8>(), 0x609ada9fcd0d4297);
    assert_eq!(get_type_hash::<i16>(), 0x568b3e81c4910f1b);
    assert_eq!(get_align_hash::<i16>(), 0xfac4ea0239a7e51f);
    assert_eq!(get_type_hash::<i32>(), 0x19b22886e521147a);
    assert_eq!(get_align_hash::<i32>(), 0x832178dce3dc2030);
    assert_eq!(get_type_hash::<i64>(), 0xba3703df82fb4e98);
    assert_eq!(get_align_hash::<i64>(), 0x5cef13c907be3ad0);
    assert_eq!(get_type_hash::<i128>(), 0x29a957130a3bc847);
    assert_eq!(get_align_hash::<i128>(), 0x612e9a0b5fc8d4f6);
    assert_eq!(get_type_hash::<usize>(), 0xa12462c6d36e68b0);
    assert_eq!(get_align_hash::<usize>(), 0x832178dce3dc2030);
    assert_eq!(get_type_hash::<u8>(), 0xbc9d6eeaea22ffb5);
    assert_eq!(get_align_hash::<u8>(), 0x609ada9fcd0d4297);
    assert_eq!(get_type_hash::<u16>(), 0x704072ef7f3dd44);
    assert_eq!(get_align_hash::<u16>(), 0xfac4ea0239a7e51f);
    assert_eq!(get_type_hash::<u32>(), 0x20aa0c10687491ad);
    assert_eq!(get_align_hash::<u32>(), 0x832178dce3dc2030);
    assert_eq!(get_type_hash::<u64>(), 0xaee7f05a097ffa16);
    assert_eq!(get_align_hash::<u64>(), 0x5cef13c907be3ad0);
    assert_eq!(get_type_hash::<u128>(), 0x19c3bfd795ae2ec8);
    assert_eq!(get_align_hash::<u128>(), 0x612e9a0b5fc8d4f6);
    assert_eq!(get_type_hash::<f32>(), 0xc80e25fc3a1c97d8);
    assert_eq!(get_align_hash::<f32>(), 0x832178dce3dc2030);
    assert_eq!(get_type_hash::<f64>(), 0x7b785833ec3cc6e8);
    assert_eq!(get_align_hash::<f64>(), 0x5cef13c907be3ad0);
    assert_eq!(get_type_hash::<bool>(), 0x947c0c03c59c6f07);
    assert_eq!(get_align_hash::<bool>(), 0x609ada9fcd0d4297);
    assert_eq!(get_type_hash::<char>(), 0x80aa991b46310ff6);
    assert_eq!(get_align_hash::<char>(), 0x832178dce3dc2030);
    assert_eq!(get_type_hash::<()>(), 0x2439715d39cd513);
    assert_eq!(get_align_hash::<()>(), 0xbd60acb658c79e45);
}

#[cfg(target_arch = "x86")]
#[test]
fn test_option() {
    assert_eq!(get_type_hash::<Option<i32>>(), 0x36d9437e00a00833);
    assert_eq!(get_align_hash::<Option<i32>>(), 0xd1fba762150c532c);
}

#[cfg(target_arch = "x86")]
#[test]
fn test_string_types() {
    assert_eq!(get_type_hash::<String>(), 0xe4297f5be0f5dd50);
    assert_eq!(get_type_hash::<str>(), 0x393e833de113cd8c);
    assert_eq!(get_type_hash::<Box<str>>(), 0x19aa1d67f7ad7a3e);
    assert_eq!(get_align_hash::<Box<str>>(), 0xd1fba762150c532c);
}

#[cfg(target_arch = "x86")]
#[test]
fn test_array_types() {
    assert_eq!(get_type_hash::<[i32; 5]>(), 0x269a95634f2c1c51);
    assert_eq!(get_align_hash::<[i32; 5]>(), 0x832178dce3dc2030);
}

#[cfg(target_arch = "x86")]
#[test]
fn test_slice_types() {
    assert_eq!(get_type_hash::<[i32]>(), 0xe053d268c8ad5c04);
    assert_eq!(get_type_hash::<SerType<&[i32]>>(), 0x400f9211e94c1834);
    assert_eq!(get_align_hash::<SerType<&[i32]>>(), 0x832178dce3dc2030);
}

#[cfg(target_arch = "x86")]
#[test]
fn test_boxed_slice_types() {
    assert_eq!(get_type_hash::<Box<[i32]>>(), 0x400f9211e94c1834);
    assert_eq!(get_align_hash::<Box<[i32]>>(), 0x832178dce3dc2030);
}

#[cfg(target_arch = "x86")]
#[test]
fn test_tuple_types() {
    assert_eq!(get_type_hash::<(i32,)>(), 0x4c6eb7a52a31e7b9);
    assert_eq!(get_align_hash::<(i32,)>(), 0x832178dce3dc2030);
    assert_eq!(get_type_hash::<(i32, f64)>(), 0x6c1bf8932e12dc1);
}

#[cfg(target_arch = "x86")]
#[test]
fn test_vec_types() {
    assert_eq!(get_type_hash::<Vec<i32>>(), 0x400f9211e94c1834);
}

#[cfg(target_arch = "x86")]
#[test]
fn test_stdlib_types() {
    use core::ops::{
        Bound, ControlFlow, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
    };
    #[cfg(feature = "std")]
    use std::collections::hash_map::DefaultHasher;
    #[cfg(feature = "std")]
    assert_eq!(get_type_hash::<DefaultHasher>(), 0x216366ce6df79e86);

    assert_eq!(get_type_hash::<Range<i32>>(), 0x837a1968d53dcff1);
    assert_eq!(get_align_hash::<Range<i32>>(), 0x896839ed01ec9b9);
    assert_eq!(get_type_hash::<RangeFrom<i32>>(), 0xad8267db843d93b8);
    assert_eq!(get_align_hash::<RangeFrom<i32>>(), 0x832178dce3dc2030);
    assert_eq!(get_type_hash::<RangeInclusive<i32>>(), 0xf90fab627ecbd1a6);
    assert_eq!(get_align_hash::<RangeInclusive<i32>>(), 0xf6991b1bbbd78c8a);
    assert_eq!(get_type_hash::<RangeTo<i32>>(), 0xd889856367fa2fe3);
    assert_eq!(get_align_hash::<RangeTo<i32>>(), 0x832178dce3dc2030);
    assert_eq!(get_type_hash::<RangeToInclusive<i32>>(), 0xc3682b190d94704d);
    assert_eq!(
        get_align_hash::<RangeToInclusive<i32>>(),
        0x832178dce3dc2030
    );
    assert_eq!(get_type_hash::<RangeFull>(), 0x1d5d4cc6e963d594);
    assert_eq!(get_align_hash::<RangeFull>(), 0xd1fba762150c532c);
    assert_eq!(get_type_hash::<Bound<i32>>(), 0x1f77c5db6e0be477);
    assert_eq!(get_align_hash::<Bound<i32>>(), 0xd1fba762150c532c);
    assert_eq!(get_type_hash::<ControlFlow<i32, f64>>(), 0x5f4feceae713afe0);
    assert_eq!(
        get_align_hash::<ControlFlow<i32, f64>>(),
        0xd1fba762150c532c
    );
}

#[cfg(target_arch = "x86")]
#[test]
fn test_derive_struct() {
    assert_eq!(get_type_hash::<MyStruct>(), 0x65125c7b120befff);
    assert_eq!(get_align_hash::<MyStruct>(), 0x7bc9c77917deb867);
}

#[cfg(target_arch = "x86")]
#[test]
fn test_derive_struct_generic() {
    assert_eq!(get_type_hash::<MyStructGeneric<i32>>(), 0x6dced006dd1acb8f);
    assert_eq!(get_align_hash::<MyStructGeneric<i32>>(), 0x832178dce3dc2030);
}

#[cfg(target_arch = "x86")]
#[test]
fn test_derive_enum() {
    assert_eq!(get_type_hash::<MyEnum>(), 0xf5e19aa69f2d9fac);
    assert_eq!(get_align_hash::<MyEnum>(), 0x8aa3c35a7ab6a4c);
}

#[cfg(target_arch = "x86")]
#[test]
fn test_derive_struct_const() {
    assert_eq!(get_type_hash::<MyStructConst<5>>(), 0x33e7076b1820eeb2);
    assert_eq!(get_align_hash::<MyStructConst<5>>(), 0x832178dce3dc2030);
}

#[cfg(target_arch = "x86")]
#[test]
fn test_derive_struct_mixed() {
    assert_eq!(get_type_hash::<MyStructMixed<i32, 5>>(), 0xb46248f37fa83bd0);
    assert_eq!(get_align_hash::<MyStructMixed<i32, 5>>(), 0x896839ed01ec9b9);
}

#[cfg(target_arch = "x86")]
#[test]
fn test_derive_struct_const_then_type() {
    assert_eq!(
        get_type_hash::<MyStructConstThenType<5, i32>>(),
        0x1001f80a4db7423a
    );
    assert_eq!(
        get_align_hash::<MyStructConstThenType<5, i32>>(),
        0x896839ed01ec9b9
    );
}