dynamic_protobuf/
lib.rs

1pub mod macros;
2
3use std::collections::HashMap;
4use std::default::Default;
5
6use bytes::{Bytes};
7
8#[derive(Default)]
9pub struct DynamicMessage {
10    inner: HashMap<u64, DynamicMessageNode>,
11}
12
13impl DynamicMessage {
14    pub fn new() -> Self {
15        Self::default()
16    }
17
18    pub fn encode(self) -> Bytes {
19        let mut encoder = DynamicMessageEncoder::new();
20
21        self._encode(&mut encoder);
22
23        encoder.into_bytes()
24    }
25
26    pub fn encode_to_vec(self) -> Vec<u8> {
27        let mut encoder = DynamicMessageEncoder::new();
28
29        self._encode(&mut encoder);
30
31        encoder.into_vec()
32    }
33
34    fn _encode(self,encoder: &mut DynamicMessageEncoder) {
35        for (id, msg) in self.inner {
36            let key = id << 3;
37
38            match msg {
39                DynamicMessageNode::I64(val) => {
40                    encoder.put_uvarint(key);
41                    encoder.put_svarint(val)
42                }
43                DynamicMessageNode::U64(val) => {
44                    encoder.put_uvarint(key);
45                    encoder.put_uvarint(val);
46                }
47                DynamicMessageNode::F32(val) => {
48                    encoder.put_uvarint(key | 5);
49                    encoder.put_u32_bits(val.to_bits())
50                }
51                DynamicMessageNode::F64(val) => {
52                    encoder.put_uvarint(key | 1);
53                    encoder.put_u64_bits(val.to_bits());
54                }
55                DynamicMessageNode::RepeatU64(vec) => {
56                    for val in vec {
57                        encoder.put_uvarint(key);
58                        encoder.put_uvarint(val);
59                    }
60                }
61                DynamicMessageNode::Bytes(b) => {
62                    encoder.put_uvarint(key | 2);
63                    encoder.put_uvarint(b.len() as _);
64                    encoder.buf.extend(b);
65                }
66            }
67        }
68    }
69
70    pub fn set<M: Into<DynamicMessageNode>>(&mut self, k: u64, v: M) {
71        self.inner.insert(k, v.into());
72    }
73}
74
75struct DynamicMessageEncoder {
76    buf: Vec<u8>,
77}
78
79impl DynamicMessageEncoder {
80    //const MAX_VARINT_LEN16: usize = 3;
81    //const MAX_VARINT_LEN32: usize = 5;
82    const MAX_VARINT_LEN64: usize = 10;
83
84    pub fn new() -> Self {
85        Self {
86            buf: Vec::new(),
87        }
88    }
89
90    pub fn put_uvarint(&mut self, v: u64) {
91        let mut b = [0; Self::MAX_VARINT_LEN64];
92        let n = _put_uvarint(&mut b, v);
93        self.buf.extend(&b[..n]);
94    }
95
96    pub fn put_svarint(&mut self, v: i64) {
97        self.put_uvarint((v as u64) << 1 ^ ((v >> 63) as u64))
98    }
99
100    pub fn put_u32_bits(&mut self, v: u32) {
101        self.buf.extend(v.to_le_bytes())
102    }
103
104    pub fn put_u64_bits(&mut self, v: u64) {
105        self.buf.extend(v.to_le_bytes())
106    }
107
108    pub fn into_bytes(self) -> Bytes {
109        Bytes::from(self.buf)
110    }
111
112    pub fn into_vec(self) -> Vec<u8> {
113        self.buf
114    }
115}
116
117fn _put_uvarint(buf: &mut [u8], mut x: u64) -> usize {
118    let mut i = 0;
119    while x >= 0x80 {
120        buf[i] = (x as u8) | 0x80;
121        x >>= 7;
122        i += 1;
123    }
124    buf[i] = x as u8;
125    i + 1
126}
127
128pub enum DynamicMessageNode {
129    I64(i64),
130    U64(u64),
131    F32(f32),
132    F64(f64),
133    Bytes(Bytes),
134    RepeatU64(Vec<u64>),
135}
136
137impl From<bool> for DynamicMessageNode {
138    fn from(val: bool) -> Self {
139        Self::U64(if val { 1 } else { 0 })
140    }
141}
142
143impl From<String> for DynamicMessageNode {
144    fn from(s: String) -> Self {
145        Self::Bytes(s.into())
146    }
147}
148
149impl From<DynamicMessage> for DynamicMessageNode {
150    fn from(msg: DynamicMessage) -> Self {
151        let b = msg.encode();
152        Self::Bytes(b)
153    }
154}
155
156macro_rules! into_node_impl {
157    ($($x:ty as $variant:ident);* $(;)?) => {
158        $(
159        impl From<$x> for DynamicMessageNode {
160            fn from(val: $x) -> Self {
161                Self::$variant(val as _) // compiler will optimize this
162            }
163        }
164        )*
165    };
166}
167
168into_node_impl! {
169    i32 as I64;
170    u32 as U64;
171    i64 as I64;
172    u64 as U64;
173    f32 as F32;
174    f64 as F64;
175    Bytes as Bytes;
176    Vec<u64> as RepeatU64;
177}
178
179#[cfg(test)]
180mod tests {
181    use crate::dynamic_message;
182
183    #[test]
184    fn message() {
185        let msg = dynamic_message! {
186            1 => 23u32,
187        }
188        .encode();
189
190        assert_eq!(*msg, [8, 23]);
191    }
192}