//! 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 { 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 { 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 { 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 { 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 { 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 for Sleb128 { fn from(item: i32) -> Self { Self(item) } } impl From for Uleb128 { fn from(item: u32) -> Self { Self(item) } } impl From for Uleb128p1 { fn from(item: u32) -> Self { Self(item) } } impl From for i32 { fn from(item: Sleb128) -> Self { item.0 } } impl From for u32 { fn from(item: Uleb128) -> Self { item.0 } } impl From 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); } }