1use crate::consts::*;
2use crate::RawTerm;
3use nom::Err;
4
5#[cfg(feature = "zlib")]
6use flate2::Decompress;
7use nom::branch::alt;
8use nom::bytes::complete::{tag, take};
9use nom::combinator::all_consuming;
10use nom::error::Error;
11use nom::error::ErrorKind;
12use nom::multi::{many0, many_m_n};
13use nom::sequence::{preceded, tuple};
14use nom::{Err as NomErr, IResult};
15use num_bigint::{BigInt, Sign};
16
17use std::convert::TryInto;
18
19pub fn from_bytes(input: &[u8]) -> Result<RawTerm, NomErr<Error<&[u8]>>> {
20 let (_, mut output) = parser(input)?;
21
22 Ok(output.remove(0))
23}
24
25pub fn parser(input: &[u8]) -> IResult<&[u8], Vec<RawTerm>> {
26 all_consuming(preceded(tag(&[REVISION]), many0(term)))(input)
27}
28
29#[cfg(not(feature = "zlib"))]
30fn term(input: &[u8]) -> IResult<&[u8], RawTerm> {
31 if input.is_empty() {
32 return Err(Err::Error(nom::error::Error::new(input, ErrorKind::Eof)));
33 }
34 let funcs = match input[0] {
35 SMALL_INTEGER_EXT => small_int,
36 INTEGER_EXT => int,
37 NEW_FLOAT_EXT => float,
38 ATOM_EXT_DEPRECATED => atom_deprecated,
39 SMALL_ATOM_UTF8_EXT => small_atom,
40 NIL_EXT => empty_list,
41 BINARY_EXT => binary,
42 BIT_BINARY_EXT => bitstring,
43 STRING_EXT => string,
44 LIST_EXT => list,
45 MAP_EXT => map,
46 SMALL_TUPLE_EXT => small_tuple,
47 LARGE_TUPLE_EXT => large_tuple,
48 SMALL_BIG_EXT => small_big_int,
49 LARGE_BIG_EXT => large_big_int,
50 PID_EXT => pid,
51 NEW_PID_EXT => new_pid,
52 PORT_EXT => port,
53 NEW_PORT_EXT => new_port,
54 NEW_REFERENCE_EXT => reference_new,
55 NEWER_REFERENCE_EXT => reference_newer,
56 NEW_FUN_EXT => function,
57 _ => {
58 return Err(Err::Error(nom::error::Error::new(input, ErrorKind::NoneOf)));
59 }
60 };
61 funcs(input)
62}
63
64#[cfg(feature = "zlib")]
65fn term(input: &[u8]) -> IResult<&[u8], RawTerm> {
66 if input.is_empty() {
67 return Err(Err::Error(nom::error::Error::new(input, ErrorKind::Eof)));
68 }
69 let funcs = match input[0] {
70 SMALL_INTEGER_EXT => small_int,
71 INTEGER_EXT => int,
72 NEW_FLOAT_EXT => float,
73 ATOM_EXT_DEPRECATED => atom_deprecated,
74 SMALL_ATOM_UTF8_EXT => small_atom,
75 NIL_EXT => empty_list,
76 BINARY_EXT => binary,
77 BIT_BINARY_EXT => bitstring,
78 STRING_EXT => string,
79 LIST_EXT => list,
80 MAP_EXT => map,
81 SMALL_TUPLE_EXT => small_tuple,
82 LARGE_TUPLE_EXT => large_tuple,
83 SMALL_BIG_EXT => small_big_int,
84 LARGE_BIG_EXT => large_big_int,
85 PID_EXT => pid,
86 NEW_PID_EXT => new_pid,
87 PORT_EXT => port,
88 NEW_PORT_EXT => new_port,
89 NEW_REFERENCE_EXT => reference_new,
90 NEWER_REFERENCE_EXT => reference_newer,
91 NEW_FUN_EXT => function,
92 ZLIB => gzip,
93 _ => {
94 return Err(Err::Error(nom::error::Error::new(input, ErrorKind::NoneOf)));
95 }
96 };
97 funcs(input)
98}
99
100#[cfg(feature = "zlib")]
101fn gzip(input: &[u8]) -> IResult<&[u8], RawTerm> {
102 let (i, t) = preceded(tag(&[ZLIB]), take(4usize))(input)?;
103 let amount = slice_to_u32(t) as usize;
104 let mut decompressor = Decompress::new(true);
105
106 let data = {
107 let mut data = Vec::with_capacity(amount);
108 decompressor
109 .decompress_vec(i, &mut data, flate2::FlushDecompress::None)
110 .map_err(|_| NomErr::Incomplete(nom::Needed::Unknown))?;
111 data
112 };
113
114 let (_a, x) = term(&data).map_err(|_| NomErr::Incomplete(nom::Needed::Unknown))?;
117 Ok((&[], x))
118}
119
120fn small_atom(input: &[u8]) -> IResult<&[u8], RawTerm> {
121 let (i, t) = preceded(tag(&[SMALL_ATOM_UTF8_EXT]), take(1usize))(input)?;
122 let length = t[0] as usize;
123 let (i, t) = take(length)(i)?;
124 Ok((
125 i,
126 RawTerm::SmallAtom(String::from_utf8(t.to_vec()).expect("atom name was not valid")),
127 ))
128}
129
130fn small_tuple(input: &[u8]) -> IResult<&[u8], RawTerm> {
131 let (i, t) = preceded(tag(&[SMALL_TUPLE_EXT]), take(1usize))(input)?;
132 let length = t[0] as usize;
133 let (i, t) = many_m_n(length, length, term)(i)?;
134 Ok((i, RawTerm::SmallTuple(t)))
135}
136fn large_tuple(input: &[u8]) -> IResult<&[u8], RawTerm> {
137 let (i, t) = preceded(tag(&[LARGE_TUPLE_EXT]), take(4usize))(input)?;
138 let length = slice_to_u32(t) as usize;
139 let (i, t) = many_m_n(length, length, term)(i)?;
140 Ok((i, RawTerm::LargeTuple(t)))
141}
142fn atom_deprecated(input: &[u8]) -> IResult<&[u8], RawTerm> {
143 let (i, t) = preceded(tag(&[ATOM_EXT_DEPRECATED]), take(2usize))(input)?;
144
145 let length = slice_to_u16(t) as usize;
146
147 let (i, t) = take(length)(i)?;
148
149 Ok((
150 i,
151 RawTerm::AtomDeprecated(String::from_utf8(t.to_vec()).expect("atom name was not valid")),
152 ))
153}
154
155fn node_or_module(input: &[u8]) -> IResult<&[u8], RawTerm> {
156 alt((
157 small_atom,
158 atom_deprecated,
159 ))(input)
162}
163
164fn small_int_or_int(input: &[u8]) -> IResult<&[u8], RawTerm> {
165 alt((small_int, int))(input)
166}
167fn pid_or_new_pid(input: &[u8]) -> IResult<&[u8], RawTerm> {
168 let func = match input[0] {
169 NEW_PID_EXT => new_pid,
170 PID_EXT => pid,
171 _ => {
172 return Err(Err::Error(nom::error::Error::new(input, ErrorKind::NoneOf)));
173 }
174 };
175 func(input)
176}
177fn new_pid(input: &[u8]) -> IResult<&[u8], RawTerm> {
178 let get_data = tuple((node_or_module, take(4usize), take(4usize), take(4usize)));
179 let (i, (node, id, serial, creation)) = preceded(tag(&[NEW_PID_EXT]), get_data)(input)?;
180 let id = slice_to_u32(id);
181 let serial = slice_to_u32(serial);
182 let creation = slice_to_u32(creation);
183
184 Ok((
185 i,
186 RawTerm::NewPid {
187 node: Box::new(node),
188 id,
189 serial,
190 creation,
191 },
192 ))
193}
194fn pid(input: &[u8]) -> IResult<&[u8], RawTerm> {
195 let get_data = tuple((node_or_module, take(4usize), take(4usize), take(1usize)));
196
197 let (i, (node, id, serial, creation)) = preceded(tag(&[PID_EXT]), get_data)(input)?;
198 let id = slice_to_u32(id);
199 let serial = slice_to_u32(serial);
200 let creation = slice_to_u8(creation);
201
202 Ok((
203 i,
204 RawTerm::Pid {
205 node: Box::new(node),
206 id,
207 serial,
208 creation,
209 },
210 ))
211}
212
213fn port(input: &[u8]) -> IResult<&[u8], RawTerm> {
214 let get_data = tuple((node_or_module, take(4usize), take(1usize)));
215
216 let (i, (node, id, creation)) = preceded(tag(&[PORT_EXT]), get_data)(input)?;
217 let id = slice_to_u32(id);
218 let creation = slice_to_u8(creation);
219
220 Ok((
221 i,
222 RawTerm::Port {
223 node: Box::new(node),
224 id,
225 creation,
226 },
227 ))
228}
229
230fn new_port(input: &[u8]) -> IResult<&[u8], RawTerm> {
231 let get_data = tuple((node_or_module, take(4usize), take(4usize)));
232
233 let (i, (node, id, creation)) = preceded(tag(&[NEW_PORT_EXT]), get_data)(input)?;
234 let id = slice_to_u32(id);
235 let creation = slice_to_u32(creation);
236
237 Ok((
238 i,
239 RawTerm::NewPort {
240 node: Box::new(node),
241 id,
242 creation,
243 },
244 ))
245}
246
247fn reference_new(input: &[u8]) -> IResult<&[u8], RawTerm> {
248 let get_data = tuple((take(2usize), node_or_module, take(1usize)));
249 let (i, (length, node, creation)) = preceded(tag(&[NEW_REFERENCE_EXT]), get_data)(input)?;
250 let length = slice_to_u16(length) as usize;
251 let (i, id_bytes) = take(4 * length)(i)?;
252 let creation = slice_to_u8(creation);
253 let id: Vec<u32> = id_bytes.chunks(4).map(slice_to_u32).collect();
254 Ok((
255 i,
256 RawTerm::Ref {
257 node: Box::new(node),
258 id,
259 creation,
260 },
261 ))
262}
263
264fn reference_newer(input: &[u8]) -> IResult<&[u8], RawTerm> {
265 let get_data = tuple((take(2usize), node_or_module, take(4usize)));
266 let (i, (length, node, creation)) = preceded(tag(&[NEWER_REFERENCE_EXT]), get_data)(input)?;
267 let length = slice_to_u16(length) as usize;
268 let (i, id_bytes) = take(4 * length)(i)?;
269 let creation = slice_to_u32(creation);
270 let id: Vec<u32> = id_bytes.chunks(4).map(slice_to_u32).collect();
271 Ok((
272 i,
273 RawTerm::NewerRef {
274 node: Box::new(node),
275 id,
276 creation,
277 },
278 ))
279}
280
281fn function(input: &[u8]) -> IResult<&[u8], RawTerm> {
282 let get_data = tuple((
283 take(4usize), take(1usize), take(16usize), take(4usize), take(4usize), node_or_module,
289 small_int_or_int,
290 small_int_or_int,
291 pid_or_new_pid,
292 ));
293
294 let (i, (size, arity, uniq, index, num_free, module, old_index, old_uniq, pid)) =
295 preceded(tag(&[NEW_FUN_EXT]), get_data)(input)?;
296 let size = slice_to_u32(size);
297 let arity = slice_to_u8(arity);
298 let index = slice_to_u32(index);
299 let num_free = slice_to_u32(num_free) as usize;
300 let uniq: [u8; 16] = uniq.try_into().unwrap();
301
302 let (i, free_vars) = many_m_n(num_free, num_free, term)(i)?;
303
304 Ok((
305 i,
306 RawTerm::Function {
307 size,
308 arity,
309 uniq,
310 index,
311 module: Box::new(module),
312 old_index: Box::new(old_index),
313 old_uniq: Box::new(old_uniq),
314 pid: Box::new(pid),
315 free_var: free_vars,
316 },
317 ))
318}
319
320fn list(input: &[u8]) -> IResult<&[u8], RawTerm> {
321 let (i, t) = preceded(tag(&[LIST_EXT]), take(4usize))(input)?;
322 let length = slice_to_u32(t) as usize;
323 let (i, mut t) = many_m_n(length + 1, length + 1, term)(i)?;
324
325 if let Some(x) = t.pop() {
326 match x {
327 RawTerm::Nil => (),
328 y => t.push(RawTerm::Improper(Box::new(y))),
329 }
330 }
331
332 Ok((i, RawTerm::List(t)))
333}
334
335fn binary(input: &[u8]) -> IResult<&[u8], RawTerm> {
336 let (i, t) = preceded(tag(&[BINARY_EXT]), take(4usize))(input)?;
337
338 let length = slice_to_u32(t) as usize;
339
340 let (i, t) = take(length)(i)?;
341 Ok((i, RawTerm::Binary(t.to_vec())))
342}
343
344fn bitstring(input: &[u8]) -> IResult<&[u8], RawTerm> {
345 let (i, t) = preceded(tag(&[BIT_BINARY_EXT]), take(4usize))(input)?;
346 let binary_length = (slice_to_u32(t) as usize).saturating_sub(1);
347 let (i, t) = take(1usize)(i)?;
348 let bit_length = t[0];
349 let (i, binary_data) = take(binary_length)(i)?;
350 let (i, t) = take(1usize)(i)?;
351 let move_bits = 8u8.saturating_sub(bit_length);
352 let bit_data = t[0] >> move_bits;
353
354 Ok((
355 i,
356 RawTerm::BitBinary {
357 binary: binary_data.to_vec(),
358 bit: bit_data,
359 bits: bit_length,
360 },
361 ))
362}
363
364fn string(input: &[u8]) -> IResult<&[u8], RawTerm> {
365 let (i, t) = preceded(tag(&[STRING_EXT]), take(2usize))(input)?;
366
367 let length = slice_to_u16(t) as usize;
368
369 let (i, t) = take(length)(i)?;
370 Ok((i, RawTerm::String(t.to_vec())))
371}
372
373fn small_int(input: &[u8]) -> IResult<&[u8], RawTerm> {
374 let (i, t) = preceded(tag(&[SMALL_INTEGER_EXT]), take(1usize))(input)?;
375 Ok((i, RawTerm::SmallInt(t[0])))
376}
377
378fn int(input: &[u8]) -> IResult<&[u8], RawTerm> {
379 let (i, t) = preceded(tag(&[INTEGER_EXT]), take(4usize))(input)?;
380 let new_int = slice_to_i32(t);
381
382 Ok((i, RawTerm::Int(new_int)))
383}
384
385fn float(input: &[u8]) -> IResult<&[u8], RawTerm> {
386 let (i, t) = preceded(tag(&[NEW_FLOAT_EXT]), take(8usize))(input)?;
387 let new_float: [u8; 8] = t.try_into().unwrap();
388 Ok((i, RawTerm::Float(f64::from_be_bytes(new_float).into())))
389}
390
391fn empty_list(input: &[u8]) -> IResult<&[u8], RawTerm> {
392 let (i, _) = tag(&[NIL_EXT])(input)?;
393
394 Ok((i, RawTerm::Nil))
395}
396
397fn map(input: &[u8]) -> IResult<&[u8], RawTerm> {
398 let (i, t) = preceded(tag(&[MAP_EXT]), take(4usize))(input)?;
399 let length = slice_to_u32(t) as usize;
400
401 let (i, t) = many_m_n(2 * length, 2 * length, term)(i)?;
402
403 let mut keyword = Vec::new();
404
405 for ch in t.chunks(2) {
406 keyword.push((ch[0].clone(), ch[1].clone()));
408 }
409
410 Ok((i, RawTerm::Map(keyword)))
411}
412
413fn small_big_int(input: &[u8]) -> IResult<&[u8], RawTerm> {
414 let (i, (length, sign)) =
415 preceded(tag(&[SMALL_BIG_EXT]), tuple((take(1usize), take(1usize))))(input)?;
416
417 let (i, t) = take(length[0])(i)?;
418 let sign = match sign[0] {
419 1 => Sign::Minus,
420 0 => Sign::Plus,
421 _ => unreachable!(),
422 };
423
424 Ok((i, RawTerm::SmallBigInt(BigInt::from_bytes_le(sign, t))))
425}
426
427fn large_big_int(input: &[u8]) -> IResult<&[u8], RawTerm> {
428 let (i, (length, sign)) =
429 preceded(tag(&[LARGE_BIG_EXT]), tuple((take(4usize), take(1usize))))(input)?;
430 let length = slice_to_u32(length) as usize;
431
432 let (i, t) = take(length)(i)?;
433 let sign = match sign[0] {
434 1 => Sign::Minus,
435 0 => Sign::Plus,
436 _ => unreachable!(),
437 };
438
439 Ok((i, RawTerm::LargeBigInt(BigInt::from_bytes_le(sign, t))))
440}
441
442fn slice_to_i32(input: &[u8]) -> i32 {
443 let new_int: [u8; 4] = input.try_into().unwrap();
444 i32::from_be_bytes(new_int)
445}
446
447fn slice_to_u32(input: &[u8]) -> u32 {
448 let new_int: [u8; 4] = input.try_into().unwrap();
449 u32::from_be_bytes(new_int)
450}
451
452fn slice_to_u16(input: &[u8]) -> u16 {
453 let new_int: [u8; 2] = input.try_into().unwrap();
454 u16::from_be_bytes(new_int)
455}
456
457fn slice_to_u8(input: &[u8]) -> u8 {
458 let new_int: [u8; 1] = input.try_into().unwrap();
459 new_int[0]
460}