ordpath/
reader.rs

1use std::io::Read;
2
3use crate::enc::{Encoding, Stage};
4use crate::{Error, ErrorKind};
5
6/// The `Reader` struct allows reading ORDPATH encoded values directly from any source implementing [`Read`].
7pub struct Reader<R: Read + ?Sized, E: Encoding> {
8    acc: u64,
9    len: u8,
10    enc: E,
11    src: R,
12}
13
14impl<R: Read, E: Encoding> Reader<R, E> {
15    /// Creates a new `Reader` for the gives source.
16    pub fn new(src: R, enc: E) -> Self {
17        Self {
18            acc: 0,
19            len: 0,
20            enc,
21            src,
22        }
23    }
24
25    /// Reads the next value and provides the corresponding stage.
26    pub fn read(&mut self) -> Result<Option<(i64, &Stage)>, Error> {
27        let prefix = (self.acc >> 56) as u8;
28        let stage = self.enc.stage_by_prefix(prefix);
29
30        if let Some(stage) = stage {
31            if stage.bits() <= self.len {
32                let value = (self.acc << stage.prefix_bits()) >> (64 - stage.ordinal_bits());
33
34                self.acc <<= stage.bits();
35                self.len -= stage.bits();
36
37                let value = value as i64 + stage.ordinal_min();
38                return Ok(Some((value, stage)));
39            }
40        }
41
42        let mut buf = [0u8; 8];
43        let consumed = self.src.read(&mut buf)?;
44
45        if consumed > 0 {
46            let acc_next = u64::from_be_bytes(buf);
47            let acc = if self.len > 0 {
48                (acc_next >> self.len) | self.acc
49            } else {
50                acc_next
51            };
52
53            let len = self.len + consumed as u8 * 8;
54            let prefix = (acc >> 56) as u8;
55
56            if let Some(stage) = self.enc.stage_by_prefix(prefix) {
57                if stage.bits() <= len {
58                    self.acc = acc_next << (stage.bits() - self.len);
59                    self.len = len - stage.bits();
60
61                    let value = ((acc << stage.prefix_bits()) >> (64 - stage.ordinal_bits()))
62                        as i64
63                        + stage.ordinal_min();
64                    return Ok(Some((value, stage)));
65                }
66            }
67        }
68
69        if self.acc == 0 {
70            Ok(None)
71        } else {
72            Err(Error::new(ErrorKind::InvalidInput))
73        }
74    }
75}