1use crate::common;
2pub use encoding_asn1_derive::Unmarshal;
3use thiserror::Error;
4
5#[derive(Error, Debug)]
6pub enum Error {
7 #[error("structural error")]
8 StructuralError(String),
9
10 #[error("Syntax error")]
11 SyntaxError(String),
12}
13
14fn parse_base128_int(bytes: &[u8], init_offset: usize) -> Result<(i32, usize), Error> {
17 let mut offset = init_offset;
18 let mut ret64: i64 = 0;
19 let mut shifted = 0;
21 while offset < bytes.len() {
22 if shifted == 5 {
25 return Err(Error::StructuralError(
26 "base 128 integer too large".to_string(),
27 ));
28 }
29 ret64 <<= 7;
30 let b = bytes[offset];
31 if shifted == 0 && b == 0x80 {
34 return Err(Error::SyntaxError(
35 "integer is not minimally encoded".to_string(),
36 ));
37 }
38 ret64 |= (b & 0x7f) as i64;
39 offset += 1;
40 if b & 0x80 == 0 {
41 let ret = ret64 as i32;
42 if ret64 > i32::MAX.into() {
44 return Err(Error::SyntaxError("base 128 integer too large".to_string()));
45 }
46 return Ok((ret, offset));
47 }
48
49 shifted += 1;
50 }
51 return Err(Error::SyntaxError("truncated base 128 integer".to_string()));
52}
53
54pub fn parse_tag_and_length(bytes: &[u8]) -> Result<(common::TagAndLength, &[u8]), Error> {
59 let mut ret = common::TagAndLength::default();
60 let mut offset = 0;
61
62 let mut b = bytes[offset];
63 offset += 1;
64 ret.class = (b >> 6) as i32;
65 ret.is_compound = (b & 0x20) == 0x20;
66 ret.tag = (b & 0x1f) as i32;
67
68 if ret.tag == 0x1f {
71 let tmp = parse_base128_int(bytes, offset)?;
72 ret.tag = tmp.0;
73 offset = tmp.1;
74 if ret.tag < 0x1f {
76 return Err(Error::SyntaxError("non-minimal tag".to_string()));
77 }
78 }
79
80 b = bytes[offset];
81 offset += 1;
82 if b & 0x80 == 0 {
83 ret.length = (b & 0x7f) as usize;
85 } else {
86 let num_bytes = (b & 0x7f) as i32;
88 if num_bytes == 0 {
89 }
92 ret.length = 0;
93 for _i in 0..num_bytes {
95 b = bytes[offset];
100 offset += 1;
101 ret.length <<= 8;
108 ret.length |= b as usize;
109 }
115 if ret.length < 0x80 {
117 }
120 }
121
122 Ok((ret, &bytes[offset..]))
123}
124
125pub trait Unmarshaler<T> {
126 fn unmarshal(bytes: &[u8]) -> Result<(T, &[u8]), Error> {
127 Self::unmarshal_with_params(bytes, &common::FieldParameters::default())
128 }
129 fn unmarshal_with_params<'a>(
130 bytes: &'a [u8],
131 params: &common::FieldParameters,
132 ) -> Result<(T, &'a [u8]), Error>;
133}
134
135pub fn unmarshal<T: Unmarshaler<T>>(bytes: &[u8]) -> Result<(T, &[u8]), Error> {
136 T::unmarshal(bytes)
137}
138
139pub fn unmarshal_with_params<'a, T: Unmarshaler<T>>(
140 bytes: &'a [u8],
141 params: &common::FieldParameters,
142) -> Result<(T, &'a [u8]), Error> {
143 T::unmarshal_with_params(bytes, params)
144}
145
146pub fn parse_int32(bytes: &[u8]) -> i32 {
147 let mut ret = 0;
148 for bytes_read in 0..bytes.len() {
149 ret <<= 8;
150 ret |= bytes[bytes_read] as i32;
151 }
152
153 ret <<= 32 - (bytes.len() as u8) * 8;
155 ret >>= 32 - (bytes.len() as u8) * 8;
156 ret
157}
158
159impl Unmarshaler<i32> for i32 {
160 fn unmarshal_with_params<'a>(
161 bytes: &'a [u8],
162 _params: &common::FieldParameters,
163 ) -> Result<(i32, &'a [u8]), Error> {
164 println!("bytes: {:02X?}", bytes);
165
166 let (tag_and_length, bytes) = parse_tag_and_length(bytes)?;
167 println!("tag_and_length: {:?}", tag_and_length);
168 println!("bytes: {:02X?}", bytes);
169 let ret = parse_int32(&bytes[..tag_and_length.length as usize]);
170 Ok((ret, &bytes[(tag_and_length.length as usize)..]))
171 }
172}
173
174#[cfg(test)]
175mod tests {
176 use super::*;
177
178 #[derive(Debug, Unmarshal)]
179 struct IntStruct {
180 a: i32,
181 }
182
183 #[test]
184 fn it_works() {
185 assert_eq!(parse_int32(&vec![0x00]), 0);
186 assert_eq!(parse_int32(&vec![0x7f]), 127);
187 assert_eq!(parse_int32(&vec![0x00, 0x80]), 128);
188 assert_eq!(parse_int32(&vec![0x01, 0x00]), 256);
189 assert_eq!(parse_int32(&vec![0x80]), -128);
190 assert_eq!(parse_int32(&vec![0xff, 0x7f]), -129);
191 assert_eq!(parse_int32(&vec![0xff]), -1);
192 assert_eq!(parse_int32(&vec![0x80, 0x00, 0x00, 0x00]), -2147483648);
193
194 struct TagAndLengthTest {
195 bytes: Vec<u8>,
196 out: common::TagAndLength,
197 }
198
199 let tag_and_length_data = vec![
200 TagAndLengthTest {
201 bytes: vec![0x80, 0x01],
202 out: common::TagAndLength {
203 class: 2,
204 length: 1,
205 ..common::TagAndLength::default()
206 },
207 },
208 TagAndLengthTest {
209 bytes: vec![0xa0, 0x01],
210 out: common::TagAndLength {
211 class: 2,
212 length: 1,
213 is_compound: true,
214 ..common::TagAndLength::default()
215 },
216 },
217 TagAndLengthTest {
218 bytes: vec![0x02, 0x00],
219 out: common::TagAndLength {
220 class: 0,
221 tag: 2,
222 length: 0,
223 is_compound: false,
224 },
225 },
226 TagAndLengthTest {
227 bytes: vec![0xfe, 0x00],
228 out: common::TagAndLength {
229 class: 3,
230 tag: 30,
231 length: 0,
232 is_compound: true,
233 },
234 },
235 TagAndLengthTest {
236 bytes: vec![0x1f, 0x1f, 0x00],
237 out: common::TagAndLength {
238 class: 0,
239 tag: 31,
240 length: 0,
241 is_compound: false,
242 },
243 },
244 TagAndLengthTest {
245 bytes: vec![0x1f, 0x81, 0x00, 0x00],
246 out: common::TagAndLength {
247 class: 0,
248 tag: 128,
249 length: 0,
250 is_compound: false,
251 },
252 },
253 TagAndLengthTest {
254 bytes: vec![0x1f, 0x81, 0x80, 0x01, 0x00],
255 out: common::TagAndLength {
256 class: 0,
257 tag: 0x4001,
258 length: 0,
259 is_compound: false,
260 },
261 },
262 TagAndLengthTest {
263 bytes: vec![0x00, 0x81, 0x80],
264 out: common::TagAndLength {
265 class: 0,
266 tag: 0,
267 length: 128,
268 is_compound: false,
269 },
270 },
271 TagAndLengthTest {
272 bytes: vec![0x00, 0x82, 0x01, 0x00],
273 out: common::TagAndLength {
274 class: 0,
275 tag: 0,
276 length: 256,
277 is_compound: false,
278 },
279 },
280 TagAndLengthTest {
281 bytes: vec![0xa0, 0x84, 0x7f, 0xff, 0xff, 0xff],
282 out: common::TagAndLength {
283 class: 2,
284 tag: 0,
285 length: 0x7fffffff,
286 is_compound: true,
287 },
288 },
289 TagAndLengthTest {
290 bytes: vec![0x1f, 0x87, 0xFF, 0xFF, 0xFF, 0x7F, 0x00],
291 out: common::TagAndLength {
292 class: 0,
293 tag: i32::MAX,
294 length: 0,
295 is_compound: false,
296 },
297 },
298 ];
299
300 for test in &tag_and_length_data {
301 let (tl, _) = parse_tag_and_length(&test.bytes).unwrap();
302 assert_eq!(tl, test.out);
303 }
304
305 let bytes = vec![0x02, 0x01, 0x42];
306 let i = i32::unmarshal(&bytes).unwrap();
307 assert_eq!(i.0, 0x42);
308
309 let bytes = vec![0x30, 0x03, 0x02, 0x01, 0x40];
310 let is = IntStruct::unmarshal(&bytes);
311 println!("is: {:?}", is);
312 }
313}