add LEB128 types
This commit is contained in:
parent
1a9030267c
commit
33e770e04a
5 changed files with 430 additions and 17 deletions
318
androscalpel_serializer/src/core/leb.rs
Normal file
318
androscalpel_serializer/src/core/leb.rs
Normal file
|
|
@ -0,0 +1,318 @@
|
|||
//! The implementation of serializable for LEB128 types.
|
||||
|
||||
use std::io::Write;
|
||||
|
||||
use crate::{Error, ReadSeek, Result, Serializable};
|
||||
|
||||
/// Signed LEB128, variable-length
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Sleb128(i32);
|
||||
|
||||
/// Unsigned LEB128, variable-length
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Uleb128(u32);
|
||||
|
||||
/// Unsigned LEB128 plus 1, variable-length
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Uleb128p1(u32);
|
||||
|
||||
impl Sleb128 {
|
||||
fn get_serialized_bytes(&self) -> Vec<u8> {
|
||||
let Self(mut val) = self;
|
||||
let mut bytes = vec![];
|
||||
loop {
|
||||
let byte = val as u8 & 0b0111_1111;
|
||||
val /= 64;
|
||||
if val == 0 || val == -1 {
|
||||
bytes.push(byte);
|
||||
return bytes;
|
||||
} else {
|
||||
val /= 2;
|
||||
}
|
||||
bytes.push(byte | 0b1000_0000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Serializable for Sleb128 {
|
||||
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
|
||||
output
|
||||
.write_all(&self.get_serialized_bytes())
|
||||
.map_err(|err| {
|
||||
Error::SerializationError(format!(
|
||||
"Failed to write serialize Sleb128 to output: {err}"
|
||||
))
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
|
||||
let mut shift = 0;
|
||||
let mut uvalue: u64 = 0;
|
||||
let mut buffer = [0u8; 1];
|
||||
for _ in 0..5 {
|
||||
input.read_exact(&mut buffer).map_err(|_| {
|
||||
Error::InputTooSmall("Failed to read all bytes for Sleb128 from the input".into())
|
||||
})?;
|
||||
let byte = buffer[0];
|
||||
let is_last_byte = byte & 0b1000_0000 == 0;
|
||||
|
||||
if is_last_byte {
|
||||
uvalue += ((byte & 0b0011_1111) as u64) << shift;
|
||||
let sign = ((byte & 0b0100_0000) as u64) << shift;
|
||||
let value = uvalue as i64 - sign as i64;
|
||||
let value: i32 = value.try_into().map_err(|err| Error::DeserializationError(
|
||||
format!("Failed to parse the Sleb128 value, the encoded value is supposed to fit in 32 bits: {err}")
|
||||
))?;
|
||||
return Ok(Self(value));
|
||||
} else {
|
||||
uvalue |= ((byte & 0b0111_1111) as u64) << shift;
|
||||
shift += 7;
|
||||
}
|
||||
}
|
||||
Err(Error::DeserializationError(
|
||||
"Malfored LEB128 encoding: the value cannot be longer than 5 bytes".into(),
|
||||
))
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
self.get_serialized_bytes().len()
|
||||
}
|
||||
}
|
||||
|
||||
impl Uleb128 {
|
||||
fn get_serialized_bytes(&self) -> Vec<u8> {
|
||||
let Self(mut val) = self;
|
||||
let mut bytes = vec![];
|
||||
loop {
|
||||
let byte = val as u8 & 0b0111_1111;
|
||||
val /= 128;
|
||||
if val == 0 {
|
||||
bytes.push(byte);
|
||||
return bytes;
|
||||
}
|
||||
bytes.push(byte | 0b1000_0000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Serializable for Uleb128 {
|
||||
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
|
||||
output
|
||||
.write_all(&self.get_serialized_bytes())
|
||||
.map_err(|err| {
|
||||
Error::SerializationError(format!(
|
||||
"Failed to write serialize Uleb128 to output: {err}"
|
||||
))
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
|
||||
let mut shift = 0;
|
||||
let mut value: u32 = 0;
|
||||
let mut buffer = [0u8; 1];
|
||||
for _ in 0..5 {
|
||||
input.read_exact(&mut buffer).map_err(|_| {
|
||||
Error::InputTooSmall("Failed to read all bytes for Uleb128 from the input".into())
|
||||
})?;
|
||||
let byte = buffer[0];
|
||||
let is_last_byte = byte & 0b1000_0000 == 0;
|
||||
|
||||
value += ((byte & 0b0111_1111) as u32) << shift;
|
||||
if is_last_byte {
|
||||
return Ok(Self(value));
|
||||
}
|
||||
shift += 7;
|
||||
}
|
||||
Err(Error::DeserializationError(
|
||||
"Malfored LEB128 encoding: the value cannot be longer than 5 bytes".into(),
|
||||
))
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
self.get_serialized_bytes().len()
|
||||
}
|
||||
}
|
||||
|
||||
impl Uleb128p1 {
|
||||
pub const MINUS_ONE: Uleb128p1 = Uleb128p1(0xFFFFFFFF);
|
||||
}
|
||||
|
||||
impl Serializable for Uleb128p1 {
|
||||
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
|
||||
let Self(val) = self;
|
||||
Uleb128(val.overflowing_add(1).0).serialize(output)
|
||||
}
|
||||
|
||||
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
|
||||
let Uleb128(val) = Uleb128::deserialize(input)?;
|
||||
Ok(Self(val.overflowing_sub(1).0))
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
let Self(val) = self;
|
||||
Uleb128(val.overflowing_add(1).0).size()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i32> for Sleb128 {
|
||||
fn from(item: i32) -> Self {
|
||||
Self(item)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for Uleb128 {
|
||||
fn from(item: u32) -> Self {
|
||||
Self(item)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for Uleb128p1 {
|
||||
fn from(item: u32) -> Self {
|
||||
Self(item)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Sleb128> for i32 {
|
||||
fn from(item: Sleb128) -> Self {
|
||||
item.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Uleb128> for u32 {
|
||||
fn from(item: Uleb128) -> Self {
|
||||
item.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Uleb128p1> for u32 {
|
||||
fn from(item: Uleb128p1) -> Self {
|
||||
item.0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn serialize_sleb128() {
|
||||
assert_eq!(Sleb128(0).serialize_to_vec().unwrap(), vec![0x00u8]);
|
||||
assert_eq!(Sleb128(1).serialize_to_vec().unwrap(), vec![0x01u8]);
|
||||
assert_eq!(Sleb128(-1).serialize_to_vec().unwrap(), vec![0x7Fu8]);
|
||||
assert_eq!(
|
||||
Sleb128(-128).serialize_to_vec().unwrap(),
|
||||
vec![0x80u8, 0x7F]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_sleb128() {
|
||||
assert_eq!(
|
||||
Sleb128::deserialize_from_slice(&[0x00u8]).unwrap(),
|
||||
Sleb128(0)
|
||||
);
|
||||
assert_eq!(
|
||||
Sleb128::deserialize_from_slice(&[0x01u8]).unwrap(),
|
||||
Sleb128(1)
|
||||
);
|
||||
assert_eq!(
|
||||
Sleb128::deserialize_from_slice(&[0x7Fu8]).unwrap(),
|
||||
Sleb128(-1)
|
||||
);
|
||||
assert_eq!(
|
||||
Sleb128::deserialize_from_slice(&[0x80u8, 0x7Fu8]).unwrap(),
|
||||
Sleb128(-128)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn size_sleb128() {
|
||||
assert_eq!(Sleb128(0).size(), 1);
|
||||
assert_eq!(Sleb128(1).size(), 1);
|
||||
assert_eq!(Sleb128(-1).size(), 1);
|
||||
assert_eq!(Sleb128(-128).size(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serialize_uleb128() {
|
||||
assert_eq!(Uleb128(0).serialize_to_vec().unwrap(), vec![0x00u8]);
|
||||
assert_eq!(Uleb128(1).serialize_to_vec().unwrap(), vec![0x01u8]);
|
||||
assert_eq!(Uleb128(127).serialize_to_vec().unwrap(), vec![0x7Fu8]);
|
||||
assert_eq!(
|
||||
Uleb128(16256).serialize_to_vec().unwrap(),
|
||||
vec![0x80u8, 0x7F]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_uleb128() {
|
||||
assert_eq!(
|
||||
Uleb128::deserialize_from_slice(&[0x00u8]).unwrap(),
|
||||
Uleb128(0)
|
||||
);
|
||||
assert_eq!(
|
||||
Uleb128::deserialize_from_slice(&[0x01u8]).unwrap(),
|
||||
Uleb128(1)
|
||||
);
|
||||
assert_eq!(
|
||||
Uleb128::deserialize_from_slice(&[0x7Fu8]).unwrap(),
|
||||
Uleb128(127)
|
||||
);
|
||||
assert_eq!(
|
||||
Uleb128::deserialize_from_slice(&[0x80u8, 0x7Fu8]).unwrap(),
|
||||
Uleb128(16256)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn size_uleb128() {
|
||||
assert_eq!(Uleb128(0).size(), 1);
|
||||
assert_eq!(Uleb128(1).size(), 1);
|
||||
assert_eq!(Uleb128(127).size(), 1);
|
||||
assert_eq!(Uleb128(16256).size(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serialize_uleb128p1() {
|
||||
assert_eq!(
|
||||
Uleb128p1::MINUS_ONE.serialize_to_vec().unwrap(),
|
||||
vec![0x00u8]
|
||||
);
|
||||
assert_eq!(Uleb128p1(0).serialize_to_vec().unwrap(), vec![0x01u8]);
|
||||
assert_eq!(Uleb128p1(126).serialize_to_vec().unwrap(), vec![0x7Fu8]);
|
||||
assert_eq!(
|
||||
Uleb128p1(16255).serialize_to_vec().unwrap(),
|
||||
vec![0x80u8, 0x7F]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_uleb128p1() {
|
||||
assert_eq!(
|
||||
Uleb128p1::deserialize_from_slice(&[0x00u8]).unwrap(),
|
||||
Uleb128p1::MINUS_ONE
|
||||
);
|
||||
assert_eq!(
|
||||
Uleb128p1::deserialize_from_slice(&[0x01u8]).unwrap(),
|
||||
Uleb128p1(0)
|
||||
);
|
||||
assert_eq!(
|
||||
Uleb128p1::deserialize_from_slice(&[0x7Fu8]).unwrap(),
|
||||
Uleb128p1(126)
|
||||
);
|
||||
assert_eq!(
|
||||
Uleb128p1::deserialize_from_slice(&[0x80u8, 0x7Fu8]).unwrap(),
|
||||
Uleb128p1(16255)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn size_uleb128p1() {
|
||||
assert_eq!(Uleb128p1::MINUS_ONE.size(), 1);
|
||||
assert_eq!(Uleb128p1(0).size(), 1);
|
||||
assert_eq!(Uleb128p1(126).size(), 1);
|
||||
assert_eq!(Uleb128p1(16255).size(), 2);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue