1use core::convert::{AsRef, From};
2use core::result;
3
4use crate::ctx::TryFromCtx;
5use crate::{Pread, error};
6
7#[derive(Debug, PartialEq, Copy, Clone)]
8pub struct Uleb128 {
10 value: u64,
11 count: usize,
12}
13
14impl Uleb128 {
15 #[inline]
16 pub fn size(&self) -> usize {
18 self.count
19 }
20 #[inline]
21 pub fn read(bytes: &[u8], offset: &mut usize) -> error::Result<u64> {
23 let tmp = bytes.pread::<Uleb128>(*offset)?;
24 *offset += tmp.size();
25 Ok(tmp.into())
26 }
27}
28
29impl AsRef<u64> for Uleb128 {
30 fn as_ref(&self) -> &u64 {
31 &self.value
32 }
33}
34
35impl From<Uleb128> for u64 {
36 #[inline]
37 fn from(uleb128: Uleb128) -> u64 {
38 uleb128.value
39 }
40}
41
42#[derive(Debug, PartialEq, Copy, Clone)]
43pub struct Sleb128 {
45 value: i64,
46 count: usize,
47}
48
49impl Sleb128 {
50 #[inline]
51 pub fn size(&self) -> usize {
53 self.count
54 }
55 #[inline]
56 pub fn read(bytes: &[u8], offset: &mut usize) -> error::Result<i64> {
58 let tmp = bytes.pread::<Sleb128>(*offset)?;
59 *offset += tmp.size();
60 Ok(tmp.into())
61 }
62}
63
64impl AsRef<i64> for Sleb128 {
65 fn as_ref(&self) -> &i64 {
66 &self.value
67 }
68}
69
70impl From<Sleb128> for i64 {
71 #[inline]
72 fn from(sleb128: Sleb128) -> i64 {
73 sleb128.value
74 }
75}
76
77const CONTINUATION_BIT: u8 = 1 << 7;
79const SIGN_BIT: u8 = 1 << 6;
80
81#[inline]
82fn mask_continuation(byte: u8) -> u8 {
83 byte & !CONTINUATION_BIT
84}
85
86impl<'a> TryFromCtx<'a> for Uleb128 {
93 type Error = error::Error;
94 #[inline]
95 fn try_from_ctx(src: &'a [u8], _ctx: ()) -> result::Result<(Self, usize), Self::Error> {
96 let mut result = 0;
97 let mut shift = 0;
98 let mut count = 0;
99 loop {
100 let byte: u8 = src.pread(count)?;
101
102 if shift == 63 && byte != 0x00 && byte != 0x01 {
103 return Err(error::Error::BadInput {
104 size: src.len(),
105 msg: "failed to parse",
106 });
107 }
108
109 let low_bits = u64::from(mask_continuation(byte));
110 result |= low_bits << shift;
111
112 count += 1;
113 shift += 7;
114
115 if byte & CONTINUATION_BIT == 0 {
116 return Ok((
117 Uleb128 {
118 value: result,
119 count,
120 },
121 count,
122 ));
123 }
124 }
125 }
126}
127
128impl<'a> TryFromCtx<'a> for Sleb128 {
129 type Error = error::Error;
130 #[inline]
131 fn try_from_ctx(src: &'a [u8], _ctx: ()) -> result::Result<(Self, usize), Self::Error> {
132 let o = 0;
133 let offset = &mut 0;
134 let mut result = 0;
135 let mut shift = 0;
136 let size = 64;
137 let mut byte: u8;
138 loop {
139 byte = src.gread(offset)?;
140
141 if shift == 63 && byte != 0x00 && byte != 0x7f {
142 return Err(error::Error::BadInput {
143 size: src.len(),
144 msg: "failed to parse",
145 });
146 }
147
148 let low_bits = i64::from(mask_continuation(byte));
149 result |= low_bits << shift;
150 shift += 7;
151
152 if byte & CONTINUATION_BIT == 0 {
153 break;
154 }
155 }
156
157 if shift < size && (SIGN_BIT & byte) == SIGN_BIT {
158 result |= !0 << shift;
160 }
161 let count = *offset - o;
162 Ok((
163 Sleb128 {
164 value: result,
165 count,
166 },
167 count,
168 ))
169 }
170}
171
172#[cfg(test)]
173mod tests {
174 use super::super::LE;
175 use super::{Sleb128, Uleb128};
176
177 const CONTINUATION_BIT: u8 = 1 << 7;
178 #[test]
181 fn uleb_size() {
182 use super::super::Pread;
183 let buf = [2u8 | CONTINUATION_BIT, 1];
184 let bytes = &buf[..];
185 let num = bytes.pread::<Uleb128>(0).unwrap();
186 #[cfg(feature = "std")]
187 println!("num: {num:?}");
188 assert_eq!(130u64, num.into());
189 assert_eq!(num.size(), 2);
190
191 let buf = [0x00, 0x01];
192 let bytes = &buf[..];
193 let num = bytes.pread::<Uleb128>(0).unwrap();
194 #[cfg(feature = "std")]
195 println!("num: {num:?}");
196 assert_eq!(0u64, num.into());
197 assert_eq!(num.size(), 1);
198
199 let buf = [0x21];
200 let bytes = &buf[..];
201 let num = bytes.pread::<Uleb128>(0).unwrap();
202 #[cfg(feature = "std")]
203 println!("num: {num:?}");
204 assert_eq!(0x21u64, num.into());
205 assert_eq!(num.size(), 1);
206 }
207
208 #[test]
209 fn uleb128() {
210 use super::super::Pread;
211 let buf = [2u8 | CONTINUATION_BIT, 1];
212 let bytes = &buf[..];
213 let num = bytes.pread::<Uleb128>(0).expect("Should read Uleb128");
214 assert_eq!(130u64, num.into());
215 assert_eq!(
216 386,
217 bytes.pread_with::<u16>(0, LE).expect("Should read number")
218 );
219 }
220
221 #[test]
222 fn uleb128_overflow() {
223 use super::super::Pread;
224 let buf = [
225 2u8 | 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,
233 2 | CONTINUATION_BIT,
234 2 | CONTINUATION_BIT,
235 1,
236 ];
237 let bytes = &buf[..];
238 assert!(bytes.pread::<Uleb128>(0).is_err());
239 }
240
241 #[test]
242 fn sleb128() {
243 use super::super::Pread;
244 let bytes = [0x7fu8 | CONTINUATION_BIT, 0x7e];
245 let num: i64 = bytes
246 .pread::<Sleb128>(0)
247 .expect("Should read Sleb128")
248 .into();
249 assert_eq!(-129, num);
250 }
251}