1 use crate::ctx::TryFromCtx;
4 use core::convert::{AsRef, From};
8 #[derive(Debug, PartialEq, Copy, Clone)]
9 /// An unsigned leb128 integer
17 /// Return how many bytes this Uleb128 takes up in memory
18 pub fn size(&self) -> usize {
22 /// Read a variable length u64 from `bytes` at `offset`
23 pub fn read(bytes: &[u8], offset: &mut usize) -> error::Result<u64> {
24 let tmp = bytes.pread::<Uleb128>(*offset)?;
25 *offset += tmp.size();
30 impl AsRef<u64> for Uleb128 {
31 fn as_ref(&self) -> &u64 {
36 impl From<Uleb128> for u64 {
38 fn from(uleb128: Uleb128) -> u64 {
43 #[derive(Debug, PartialEq, Copy, Clone)]
44 /// An signed leb128 integer
52 /// Return how many bytes this Sleb128 takes up in memory
53 pub fn size(&self) -> usize {
57 /// Read a variable length i64 from `bytes` at `offset`
58 pub fn read(bytes: &[u8], offset: &mut usize) -> error::Result<i64> {
59 let tmp = bytes.pread::<Sleb128>(*offset)?;
60 *offset += tmp.size();
65 impl AsRef<i64> for Sleb128 {
66 fn as_ref(&self) -> &i64 {
71 impl From<Sleb128> for i64 {
73 fn from(sleb128: Sleb128) -> i64 {
78 // Below implementation heavily adapted from: https://github.com/fitzgen/leb128
79 const CONTINUATION_BIT: u8 = 1 << 7;
80 const SIGN_BIT: u8 = 1 << 6;
83 fn mask_continuation(byte: u8) -> u8 {
84 byte & !CONTINUATION_BIT
88 // fn mask_continuation_u64(val: u64) -> u8 {
89 // let byte = val & (u8::MAX as u64);
90 // mask_continuation(byte as u8)
93 impl<'a> TryFromCtx<'a> for Uleb128 {
94 type Error = error::Error;
96 fn try_from_ctx(src: &'a [u8], _ctx: ()) -> result::Result<(Self, usize), Self::Error> {
101 let byte: u8 = src.pread(count)?;
103 if shift == 63 && byte != 0x00 && byte != 0x01 {
104 return Err(error::Error::BadInput {
106 msg: "failed to parse",
110 let low_bits = u64::from(mask_continuation(byte));
111 result |= low_bits << shift;
116 if byte & CONTINUATION_BIT == 0 {
129 impl<'a> TryFromCtx<'a> for Sleb128 {
130 type Error = error::Error;
132 fn try_from_ctx(src: &'a [u8], _ctx: ()) -> result::Result<(Self, usize), Self::Error> {
140 byte = src.gread(offset)?;
142 if shift == 63 && byte != 0x00 && byte != 0x7f {
143 return Err(error::Error::BadInput {
145 msg: "failed to parse",
149 let low_bits = i64::from(mask_continuation(byte));
150 result |= low_bits << shift;
153 if byte & CONTINUATION_BIT == 0 {
158 if shift < size && (SIGN_BIT & byte) == SIGN_BIT {
159 // Sign extend the result.
160 result |= !0 << shift;
162 let count = *offset - o;
175 use super::super::LE;
176 use super::{Sleb128, Uleb128};
178 const CONTINUATION_BIT: u8 = 1 << 7;
179 //const SIGN_BIT: u8 = 1 << 6;
183 use super::super::Pread;
184 let buf = [2u8 | CONTINUATION_BIT, 1];
185 let bytes = &buf[..];
186 let num = bytes.pread::<Uleb128>(0).unwrap();
187 println!("num: {:?}", &num);
188 assert_eq!(130u64, num.into());
189 assert_eq!(num.size(), 2);
191 let buf = [0x00, 0x01];
192 let bytes = &buf[..];
193 let num = bytes.pread::<Uleb128>(0).unwrap();
194 println!("num: {:?}", &num);
195 assert_eq!(0u64, num.into());
196 assert_eq!(num.size(), 1);
199 let bytes = &buf[..];
200 let num = bytes.pread::<Uleb128>(0).unwrap();
201 println!("num: {:?}", &num);
202 assert_eq!(0x21u64, num.into());
203 assert_eq!(num.size(), 1);
208 use super::super::Pread;
209 let buf = [2u8 | CONTINUATION_BIT, 1];
210 let bytes = &buf[..];
211 let num = bytes.pread::<Uleb128>(0).expect("Should read Uleb128");
212 assert_eq!(130u64, num.into());
215 bytes.pread_with::<u16>(0, LE).expect("Should read number")
220 fn uleb128_overflow() {
221 use super::super::Pread;
223 2u8 | CONTINUATION_BIT,
224 2 | CONTINUATION_BIT,
225 2 | CONTINUATION_BIT,
226 2 | CONTINUATION_BIT,
227 2 | CONTINUATION_BIT,
228 2 | CONTINUATION_BIT,
229 2 | CONTINUATION_BIT,
230 2 | CONTINUATION_BIT,
231 2 | CONTINUATION_BIT,
232 2 | CONTINUATION_BIT,
235 let bytes = &buf[..];
236 assert!(bytes.pread::<Uleb128>(0).is_err());
241 use super::super::Pread;
242 let bytes = [0x7fu8 | CONTINUATION_BIT, 0x7e];
245 .expect("Should read Sleb128")
247 assert_eq!(-129, num);