encoding_asn1/
marshal.rs

1use crate::common;
2pub use encoding_asn1_derive::Marshal;
3
4pub trait Encoder {
5    fn len(&self) -> usize {
6        self.encode().len()
7    }
8    fn encode(&self) -> Vec<u8>;
9}
10
11pub struct TaggedEncoder<E1: Encoder, E2: Encoder> {
12    pub tag: E1,
13    pub body: E2,
14}
15
16impl<E1, E2> Encoder for TaggedEncoder<E1, E2>
17where
18    E1: Encoder,
19    E2: Encoder,
20{
21    fn encode(&self) -> Vec<u8> {
22        let mut v = self.tag.encode();
23        v.append(&mut self.body.encode());
24        v
25    }
26}
27
28fn base128_int_length(mut n: i64) -> i32 {
29    if n == 0 {
30        return 1;
31    }
32
33    let mut l = 0;
34    while n > 0 {
35        l += 1;
36        n >>= 7;
37    }
38
39    return l;
40}
41
42fn encode_int_using_base128(n: i64) -> Vec<u8> {
43    let mut v = vec![];
44
45    let l = base128_int_length(n);
46
47    for i in (0..l).rev() {
48        let mut o = (n >> ((i * 7) as u32)) as u8;
49        o &= 0x7f;
50        if i != 0 {
51            o |= 0x80;
52        }
53
54        v.push(o);
55    }
56
57    v
58}
59
60fn length_length(mut i: i32) -> i32 {
61    let mut num_bytes = 1;
62    while i > 255 {
63        num_bytes += 1;
64        i >>= 8;
65    }
66    num_bytes
67}
68
69fn encode_length(i: i32) -> Vec<u8> {
70    let mut v = vec![];
71    let mut n = length_length(i);
72
73    while n > 0 {
74        v.push((i >> ((n - 1) * 8)) as u8);
75        n -= 1;
76    }
77    v
78}
79
80impl Encoder for common::TagAndLength {
81    fn encode(&self) -> Vec<u8> {
82        let mut v = vec![];
83
84        let mut b = (self.class as u8) << 6;
85        if self.is_compound {
86            b |= 0x20;
87        }
88        if self.tag >= 31 {
89            b |= 0x1f;
90            v.push(b);
91            v.append(&mut encode_int_using_base128(self.tag as i64));
92        } else {
93            b |= self.tag as u8;
94            v.push(b);
95        }
96
97        if self.length >= 128 {
98            let l = length_length(self.length as i32);
99            v.push(0x80 | l as u8);
100            v.append(&mut encode_length(self.length as i32));
101        } else {
102            v.push(self.length as u8);
103        }
104
105        v
106    }
107}
108
109impl Encoder for i32 {
110    fn len(&self) -> usize {
111        let mut i = *self;
112        let mut n = 1;
113
114        while i > 127 {
115            n += 1;
116            i >>= 8;
117        }
118
119        while i < -128 {
120            n += 1;
121            i >>= 8;
122        }
123
124        return n;
125    }
126
127    fn encode(&self) -> Vec<u8> {
128        let mut v = vec![];
129        let n = self.len();
130        let i = *self;
131
132        for j in 0..n {
133            v.push((i >> ((n - 1 - j) * 8)) as u8);
134        }
135
136        v
137    }
138}
139
140impl Encoder for Vec<u8> {
141    fn len(&self) -> usize {
142        self.len()
143    }
144
145    fn encode(&self) -> Vec<u8> {
146        self.to_vec()
147    }
148}
149
150pub trait Marshaler {
151    fn marshal(&self) -> Vec<u8> {
152        self.marshal_with_params(&common::FieldParameters::default())
153    }
154    fn marshal_with_params(&self, params: &common::FieldParameters) -> Vec<u8>;
155}
156
157impl Marshaler for i32 {
158    fn marshal_with_params(&self, params: &common::FieldParameters) -> Vec<u8> {
159        let mut class = common::CLASS_UNIVERSAL;
160        let mut tag = common::TAG_INTEGER;
161        if let Some(v) = params.tag {
162            if params.application {
163                class = common::CLASS_APPLICATION;
164            } else if params.private {
165                class = common::CLASS_PRIVATE
166            } else {
167                class = common::CLASS_CONTEXT_SPECIFIC
168            }
169
170            if params.explicit {
171                let mut t = TaggedEncoder {
172                    tag: common::TagAndLength {
173                        class: class,
174                        is_compound: true,
175                        length: 0,
176                        tag: v,
177                    },
178                    body: TaggedEncoder {
179                        tag: common::TagAndLength {
180                            class: 0,
181                            is_compound: false,
182                            length: self.len(),
183                            tag: common::TAG_INTEGER,
184                        },
185                        body: self.encode(),
186                    },
187                };
188
189                t.tag.length = t.body.len();
190
191                return t.encode();
192            }
193
194            // implicit tag.
195            tag = v;
196        }
197
198        let t = TaggedEncoder {
199            tag: common::TagAndLength {
200                class: class,
201                is_compound: false,
202                length: self.len(),
203                tag: tag,
204            },
205            body: self.encode(),
206        };
207
208        t.encode()
209    }
210}
211
212impl Marshaler for Vec<u8> {
213    fn marshal_with_params(&self, _params: &common::FieldParameters) -> Vec<u8> {
214        let t = TaggedEncoder {
215            tag: common::TagAndLength {
216                class: 0,
217                is_compound: false,
218                length: self.len(),
219                tag: common::TAG_OCTET_STRING,
220            },
221            body: self.encode(),
222        };
223
224        t.encode()
225    }
226}
227
228pub fn marshal<M: Marshaler>(m: &M) -> Vec<u8> {
229    m.marshal()
230}
231
232pub fn marshal_with_params<M: Marshaler>(m: &M, params: &common::FieldParameters) -> Vec<u8> {
233    m.marshal_with_params(params)
234}
235
236#[cfg(test)]
237mod tests {
238    use super::*;
239
240    #[derive(Marshal)]
241    struct IntStruct {
242        a: i32,
243    }
244
245    #[derive(Marshal)]
246    struct TwoIntStruct {
247        a: i32,
248        b: i32,
249    }
250
251    #[derive(Marshal)]
252    struct NestedStruct {
253        a: IntStruct,
254    }
255
256    #[derive(Marshal)]
257    struct ImplicitTagTest {
258        #[asn1(implicit, tag = 5)]
259        a: i32,
260    }
261
262    #[derive(Marshal)]
263    struct ExplicitTagTest {
264        #[asn1(explicit, tag = 5)]
265        a: i32,
266    }
267
268    #[test]
269    fn it_works() {
270        assert_eq!(marshal(&10), vec![0x02, 0x01, 0x0a]);
271        assert_eq!(marshal(&127), vec![0x02, 0x01, 0x7f]);
272        assert_eq!(marshal(&128), vec![0x02, 0x02, 0x00, 0x80]);
273        assert_eq!(marshal(&-128), vec![0x02, 0x01, 0x80]);
274        assert_eq!(marshal(&-129), vec![0x02, 0x02, 0xff, 0x7f]);
275        assert_eq!(
276            marshal(&IntStruct { a: 64 }),
277            vec![0x30, 0x03, 0x02, 0x01, 0x40]
278        );
279        assert_eq!(
280            marshal(&TwoIntStruct { a: 64, b: 65 }),
281            vec![0x30, 0x06, 0x02, 0x01, 0x40, 0x02, 0x01, 0x41]
282        );
283        assert_eq!(
284            marshal(&NestedStruct {
285                a: IntStruct { a: 127 }
286            }),
287            vec![0x30, 0x05, 0x30, 0x03, 0x02, 0x01, 0x7f]
288        );
289        assert_eq!(marshal(&vec![1, 2, 3]), vec![0x04, 0x03, 0x01, 0x02, 0x03]);
290        assert_eq!(
291            marshal(&ImplicitTagTest { a: 64 }),
292            vec![0x30, 0x03, 0x85, 0x01, 0x40]
293        );
294        assert_eq!(
295            marshal(&ExplicitTagTest { a: 64 }),
296            vec![0x30, 0x05, 0xa5, 0x03, 0x02, 0x01, 0x40]
297        );
298        assert_eq!(
299            marshal(&crate::types::RawValue {
300                tag: 1,
301                class: 2,
302                is_compound: false,
303                bytes: vec![0x01, 0x02, 0x03],
304                full_bytes: vec![],
305            }),
306            vec![0x81, 0x03, 0x01, 0x02, 0x03]
307        );
308    }
309}