erlang_term/
parse.rs

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    // error returns a reference to data owned by this function, which is not allowed
115    // map it to a blank error
116    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        // also atom
160        //      atom cache
161    ))(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),  // Size
284        take(1usize),  // Arity
285        take(16usize), // Uniq
286        take(4usize),  // Index
287        take(4usize),  // NumFree
288        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        // all_strings = all_strings && ch[0].is_string_like();
407        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}