-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathenum_like_tuple.rs
104 lines (90 loc) · 3.58 KB
/
enum_like_tuple.rs
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
mod unittest;
use byteserde::prelude::*;
use byteserde_derive::{ByteDeserializeSlice, ByteSerializeHeap, ByteSerializeStack, ByteSerializedLenOf};
use log::info;
use unittest::setup;
/// To be used as a common section in the byte stream that can be used to identify the variant during deserialization.
#[rustfmt::skip]
#[derive(ByteSerializeStack, ByteSerializeHeap, ByteDeserializeSlice, ByteSerializedLenOf, Debug, PartialEq)]
struct Header(u16);
#[rustfmt::skip]
#[derive(ByteSerializeStack, ByteSerializeHeap, ByteDeserializeSlice, ByteSerializedLenOf, Debug, PartialEq)]
struct Variant1 {
#[byteserde(replace(Header(Variant1::tag())))] // this ensures that header always gets a Variant1 value during serialization
header: Header, // note that this field need to be positioned consistently across all variants
data: u32,
}
#[rustfmt::skip]
impl Variant1 { fn tag() -> u16 { 1 } }
#[rustfmt::skip]
#[derive(ByteSerializeStack, ByteSerializeHeap, ByteDeserializeSlice, ByteSerializedLenOf, Debug, PartialEq)]
struct Variant2a {
#[byteserde(replace(Header(Variant2a::tag())))] // this ensures that header always gets a Variant2a value during serialization
header: Header, // note that this field need to be positioned consistently across all variants
data: u64,
}
#[rustfmt::skip]
impl Variant2a { fn tag() -> u16 { 2 } }
#[rustfmt::skip]
#[derive(ByteSerializeStack, ByteSerializeHeap, ByteDeserializeSlice, ByteSerializedLenOf,Debug, PartialEq)]
struct Variant2b {
data: u128,
}
#[rustfmt::skip]
#[derive(ByteSerializeStack, ByteSerializeHeap, ByteDeserializeSlice, ByteSerializedLenOf,Debug, PartialEq)]
struct Variant3 {
#[byteserde(replace(Header(Variant3::tag())))]
header: Header,
data: u128,
}
#[rustfmt::skip]
impl Variant3 { fn tag() -> u16 { 3 } }
#[rustfmt::skip]
#[derive(ByteSerializeStack, ByteSerializeHeap, ByteDeserializeSlice, ByteSerializedLenOf,Debug, PartialEq)]
#[byteserde(peek(0, 2))]
enum Variants {
#[byteserde(eq(Variant1::tag().to_ne_bytes()))]
V1(Variant1),
#[byteserde(eq(Variant2a::tag().to_ne_bytes()))]
V2(Variant2a, Variant2b), // note that only Variant2a has the header field and it is positioned consistently both Variant1 and Variant2a as a member
// #[byteserde(eq(3_u16.to_ne_bytes()))] // TODO add fail test
// V3 { x: Variant3 },
}
#[test]
fn test_enum_like_tuple() {
enum_tuple_like()
}
fn enum_tuple_like() {
setup::log::configure();
#[rustfmt::skip]
let msg_inp = vec![
Variants::V1( Variant1{header: Header(Variant1::tag()), data: 1}),
Variants::V2( Variant2a{header: Header(Variant2a::tag()), data: 2}, Variant2b {data: 2},),
];
for msg in &msg_inp {
info!("msg.byte_len(): {:?}", msg.byte_len());
}
let mut iter = msg_inp.iter();
assert_eq!(iter.next().unwrap().byte_len(), 6);
assert_eq!(iter.next().unwrap().byte_len(), 26);
let mut ser_stck = ByteSerializerStack::<1024>::default();
let mut ser_heap = ByteSerializerHeap::default();
for msg in &msg_inp {
info!("ser: {:?}", msg);
let _ = msg.byte_serialize_stack(&mut ser_stck).unwrap();
let _ = msg.byte_serialize_heap(&mut ser_heap).unwrap();
}
info!("ser_stck: {:#x}", ser_stck);
assert_eq!(ser_stck.as_slice(), ser_heap.as_slice());
let mut des = ByteDeserializerSlice::new(ser_stck.as_slice());
let mut msg_out: Vec<Variants> = vec![];
while !des.is_empty() {
let msg = des.deserialize::<Variants>().unwrap();
info!("msg: {:?}", msg);
msg_out.push(msg);
}
assert_eq!(msg_inp, msg_out);
}
fn main() {
enum_tuple_like();
}