rm_lines/
page.rs

1use crate::{Header, Layer, Parse, Version};
2
3use nom::{combinator::map, multi::length_count, number::complete::le_u32, sequence::tuple};
4
5/// Data representation of a page in a reMarkable document
6///
7/// This is the type used to represent a parsed `.rm` file
8#[derive(Debug, PartialEq)]
9pub struct Page {
10    pub version: Version,
11    pub layers: Vec<Layer>,
12}
13
14impl<'i> Parse<'i> for Page {
15    /// Attempts to parse a `Page` from a byte sequence
16    ///
17    /// A page is represented by a 44-byte, ASCII formatted header,
18    /// followed by a little-endian, 32-bit layer count, followed by
19    /// the raw [Layer] values themselves
20    fn parse(input: &'i [u8]) -> nom::IResult<&'i [u8], Self> {
21        map(
22            tuple((Header::parse, length_count(le_u32, Layer::parse))),
23            |(header, layers)| Page {
24                layers,
25                version: header.0,
26            },
27        )(input)
28    }
29}
30
31#[cfg(test)]
32mod tests {
33    use super::*;
34
35    #[test]
36    fn test_parse() {
37        let file = include_bytes!("../data/test.rm");
38
39        let res = Page::parse(file);
40        assert!(res.is_ok());
41
42        let (rest, page) = res.unwrap();
43        assert_eq!(rest, &[][..]);
44        assert_eq!(page.layers.len(), 2);
45    }
46}