Skip to main content

nt_leb128/
read.rs

1use super::{CONTINUATION_BIT, SIGN_BIT, low_bits_of_byte};
2use std::fmt;
3use std::io;
4use bytes::Buf;
5
6/// Trait for reading signed and unsigned LEB128 encoded numbers
7pub trait LEB128Read {
8    /// Read a signed LEB128 number from the given `std::io::Read`able and
9    /// return it or an error if reading failed.
10    fn read_signed(&mut self) -> Result<(i64, usize), Error>;
11
12    /// Read an unsigned LEB128 number from the given `std::io::Read`able and
13    /// return it or an error if reading failed.
14    fn read_unsigned(&mut self) -> Result<(u64, usize), Error>;
15}
16
17/// An enumeration of the possible errors that can occur when reading a
18/// number encoded with LEB128.
19#[derive(Debug)]
20pub enum Error {
21    /// There was an underlying IO error.
22    IoError(io::Error),
23    /// The number being read is larger than can be represented.
24    Overflow,
25}
26
27impl From<io::Error> for Error {
28    fn from(e: io::Error) -> Self {
29        Error::IoError(e)
30    }
31}
32
33impl fmt::Display for Error {
34    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
35        write!(f,
36               "leb128::read::Error: {}",
37               ::std::error::Error::description(self))
38    }
39}
40
41impl ::std::error::Error for Error {
42    fn description(&self) -> &str {
43        match *self {
44            Error::IoError(ref e) => e.description(),
45            Error::Overflow => "The number being read is larger than can be represented",
46        }
47    }
48
49    fn cause(&self) -> Option<&::std::error::Error> {
50        match *self {
51            Error::IoError(ref e) => Some(e),
52            Error::Overflow => None,
53        }
54    }
55}
56
57impl<R> LEB128Read for R
58    where R: Buf
59{
60    fn read_signed(&mut self) -> Result<(i64, usize), Error> {
61        let mut result = 0;
62        let mut shift = 0;
63        let size = 64;
64        let mut byte;
65        let mut bytes_read = 0;
66
67        loop {
68            if !self.has_remaining() {
69                return Err(Error::IoError(io::Error::new(io::ErrorKind::UnexpectedEof, "Not enough data")))
70            }
71
72            byte = self.get_u8();
73            bytes_read += 1;
74            if shift == 63 && byte != 0x00 && byte != 0x7f {
75                return Err(Error::Overflow);
76            }
77
78            let low_bits = low_bits_of_byte(byte) as i64;
79            result |= low_bits << shift;
80            shift += 7;
81
82            if byte & CONTINUATION_BIT == 0 {
83                break;
84            }
85        }
86
87        if shift < size && (SIGN_BIT & byte) == SIGN_BIT {
88            // Sign extend the result.
89            result |= !0 << shift;
90        }
91
92        Ok((result, bytes_read))
93    }
94
95    fn read_unsigned(&mut self) -> Result<(u64, usize), Error> {
96        let mut result = 0;
97        let mut shift = 0;
98        let mut bytes_read = 0;
99
100        loop {
101            if !self.has_remaining() {
102                return Err(Error::IoError(io::Error::new(io::ErrorKind::UnexpectedEof, "Not enough data")))
103            }
104
105            let byte = self.get_u8();
106            bytes_read += 1;
107
108            if shift == 63 && byte != 0x00 && byte != 0x01 {
109                return Err(Error::Overflow);
110            }
111
112            let low_bits = low_bits_of_byte(byte) as u64;
113            result |= low_bits << shift;
114
115            if byte & CONTINUATION_BIT == 0 {
116                return Ok((result, bytes_read));
117            }
118
119            shift += 7;
120        }
121    }
122}