androscalpel/androscalpel_serializer/src/value.rs
2024-02-07 17:31:09 +01:00

865 lines
33 KiB
Rust

//! The encoded value format: <https://source.android.com/docs/core/runtime/dex-format#encoding>
use crate::{EncodedAnnotation, EncodedArray, Error, ReadSeek, Result, Serializable};
use std::io::Write;
/// An encoded value of arbitrary hierachically structured data:
/// <https://source.android.com/docs/core/runtime/dex-format#encoding>
#[derive(Debug, Clone)]
pub enum EncodedValue {
Byte(i8),
Short(i16),
Char(u16),
Int(i32),
Long(i64),
Float(f32),
Double(f64),
/// Index of a [`crate::ProtoIdItem`] in `proto_ids`
MethodType(u32),
/// Index of a [`crate::MethodHandleItem`] in `method_handles`
MethodHandle(u32),
/// Index of a [`crate::StringIdItem`] in `string_ids`
String(u32),
/// Index of a [`crate::TypeIdItem`] in `type_ids`
Type(u32),
/// Index of a [`crate::FieldIdItem`] in `field_ids`
Field(u32),
/// Index of a [`crate::MethodIdItem`] in `method_ids`
Method(u32),
/// Index of a [`crate::FieldIdItem`] in `field_ids` representing an enum.
Enum(u32),
Array(EncodedArray),
Annotation(EncodedAnnotation),
Null,
Boolean(bool),
}
/// The id of a type used by a value.
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
struct ValueType(u8);
const VALUE_BYTE: ValueType = ValueType(0x00);
const VALUE_SHORT: ValueType = ValueType(0x02);
const VALUE_CHAR: ValueType = ValueType(0x03);
const VALUE_INT: ValueType = ValueType(0x04);
const VALUE_LONG: ValueType = ValueType(0x06);
const VALUE_FLOAT: ValueType = ValueType(0x10);
const VALUE_DOUBLE: ValueType = ValueType(0x11);
const VALUE_METHOD_TYPE: ValueType = ValueType(0x15);
const VALUE_METHOD_HANDLE: ValueType = ValueType(0x16);
const VALUE_STRING: ValueType = ValueType(0x17);
const VALUE_TYPE: ValueType = ValueType(0x18);
const VALUE_FIELD: ValueType = ValueType(0x19);
const VALUE_METHOD: ValueType = ValueType(0x1a);
const VALUE_ENUM: ValueType = ValueType(0x1b);
const VALUE_ARRAY: ValueType = ValueType(0x1c);
const VALUE_ANNOTATION: ValueType = ValueType(0x1d);
const VALUE_NULL: ValueType = ValueType(0x1e);
const VALUE_BOOLEAN: ValueType = ValueType(0x1f);
impl PartialEq for EncodedValue {
fn eq(&self, item: &Self) -> bool {
match (self, item) {
(Self::Byte(val1), Self::Byte(val2)) => val1 == val2,
(Self::Short(val1), Self::Short(val2)) => val1 == val2,
(Self::Char(val1), Self::Char(val2)) => val1 == val2,
(Self::Int(val1), Self::Int(val2)) => val1 == val2,
(Self::Long(val1), Self::Long(val2)) => val1 == val2,
(Self::Float(val1), Self::Float(val2)) => val1.to_be_bytes() == val2.to_be_bytes(),
(Self::Double(val1), Self::Double(val2)) => val1.to_be_bytes() == val2.to_be_bytes(),
(Self::MethodType(val1), Self::MethodType(val2)) => val1 == val2,
(Self::MethodHandle(val1), Self::MethodHandle(val2)) => val1 == val2,
(Self::String(val1), Self::String(val2)) => val1 == val2,
(Self::Type(val1), Self::Type(val2)) => val1 == val2,
(Self::Field(val1), Self::Field(val2)) => val1 == val2,
(Self::Method(val1), Self::Method(val2)) => val1 == val2,
(Self::Enum(val1), Self::Enum(val2)) => val1 == val2,
(Self::Array(val1), Self::Array(val2)) => val1 == val2,
(Self::Annotation(val1), Self::Annotation(val2)) => val1 == val2,
(Self::Null, Self::Null) => true,
(Self::Boolean(val1), Self::Boolean(val2)) => val1 == val2,
_ => false,
}
}
}
impl Eq for EncodedValue {}
impl Serializable for EncodedValue {
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
match self {
Self::Byte(byte) => {
let bytes = byte.to_be_bytes();
output.write_all(&[VALUE_BYTE.0]).map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Byte to output: {err}"
))
})?;
output.write_all(&bytes).map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Byte to output: {err}"
))
})?;
Ok(())
}
Self::Short(val) => {
let size = self.size();
let bytes: [u8; 2] = val.to_le_bytes();
output
.write_all(&[((size as u8 - 2) << 5) | VALUE_SHORT.0])
.map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Short to output: {err}"
))
})?;
output.write_all(&bytes[..(size - 1)]).map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Short to output: {err}"
))
})?;
Ok(())
}
Self::Char(val) => {
let size = self.size();
let bytes: [u8; 2] = val.to_le_bytes();
output
.write_all(&[((size as u8 - 2) << 5) | VALUE_CHAR.0])
.map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Char to output: {err}"
))
})?;
output.write_all(&bytes[..(size - 1)]).map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Char to output: {err}"
))
})?;
Ok(())
}
Self::Int(val) => {
let size = self.size();
let bytes: [u8; 4] = val.to_le_bytes();
output
.write_all(&[((size as u8 - 2) << 5) | VALUE_INT.0])
.map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Int to output: {err}"
))
})?;
output.write_all(&bytes[..(size - 1)]).map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Int to output: {err}"
))
})?;
Ok(())
}
Self::Long(val) => {
let size = self.size();
let bytes: [u8; 8] = val.to_le_bytes();
output
.write_all(&[((size as u8 - 2) << 5) | VALUE_LONG.0])
.map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Long to output: {err}"
))
})?;
output.write_all(&bytes[..(size - 1)]).map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Long to output: {err}"
))
})?;
Ok(())
}
Self::Float(val) => {
let size = self.size();
let bytes = val.to_le_bytes(); // TODO: check LE/BE
output
.write_all(&[((size as u8 - 2) << 5) | VALUE_FLOAT.0])
.map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Float to output: {err}"
))
})?;
output.write_all(&bytes[..(size - 1)]).map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Float to output: {err}"
))
})?;
Ok(())
}
Self::Double(val) => {
let size = self.size();
let bytes = val.to_le_bytes(); // TODO: check LE/BE
output
.write_all(&[((size as u8 - 2) << 5) | VALUE_DOUBLE.0])
.map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Double to output: {err}"
))
})?;
output.write_all(&bytes[..(size - 1)]).map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Double to output: {err}"
))
})?;
Ok(())
}
Self::MethodType(idx) => Idx(*idx, VALUE_METHOD_TYPE).serialize(output),
Self::MethodHandle(idx) => Idx(*idx, VALUE_METHOD_HANDLE).serialize(output),
Self::String(idx) => Idx(*idx, VALUE_STRING).serialize(output),
Self::Type(idx) => Idx(*idx, VALUE_TYPE).serialize(output),
Self::Field(idx) => Idx(*idx, VALUE_FIELD).serialize(output),
Self::Method(idx) => Idx(*idx, VALUE_METHOD).serialize(output),
Self::Enum(idx) => Idx(*idx, VALUE_ENUM).serialize(output),
Self::Array(arr) => {
output.write_all(&[VALUE_ARRAY.0]).map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Array to output: {err}"
))
})?;
arr.serialize(output)
}
Self::Annotation(ann) => {
output.write_all(&[VALUE_ANNOTATION.0]).map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Annotation to output: {err}"
))
})?;
ann.serialize(output)
}
Self::Null => {
output.write_all(&[VALUE_NULL.0]).map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Null to output: {err}"
))
})?;
Ok(())
}
Self::Boolean(b) => {
let val = if *b { 1 } else { 0 };
output
.write_all(&[(val << 5) | VALUE_BOOLEAN.0])
.map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Bool to output: {err}"
))
})?;
Ok(())
}
}
}
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
let mut buffer = [0u8; 1];
input.read_exact(&mut buffer).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue from the input".into(),
)
})?;
let [byte] = buffer;
let arg = (byte & 0b1110_0000) >> 5;
match ValueType(byte & 0b0001_1111) {
VALUE_BYTE => {
if arg != 0 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0 for VALUE_BYTE"
)))
} else {
let mut buffer = [0u8; 1];
input.read_exact(&mut buffer).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (Byte) from the input"
.into(),
)
})?;
Ok(Self::Byte(i8::from_be_bytes(buffer)))
}
}
VALUE_SHORT => {
if arg >= 2 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0 or 1 for VALUE_SHORT"
)))
} else {
let mut buffer = [0x00u8; 2];
let size = (arg + 1) as usize;
input.read_exact(&mut buffer[..size]).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (Short) from the input"
.into(),
)
})?;
// Sign extention
if (buffer[size - 1] & 0b1000_0000) != 0 {
for b in buffer.iter_mut().skip(size) {
*b = 0xff;
}
}
Ok(Self::Short(i16::from_le_bytes(buffer)))
}
}
VALUE_CHAR => {
if arg >= 2 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0 or 1 for VALUE_CHAR"
)))
} else {
let mut buffer = [0x00u8; 2];
let size = (arg + 1) as usize;
input.read_exact(&mut buffer[..size]).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (Char) from the input"
.into(),
)
})?;
Ok(Self::Char(u16::from_le_bytes(buffer)))
}
}
VALUE_INT => {
if arg >= 4 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0, 1, 2 or 3 for VALUE_INT"
)))
} else {
let mut buffer = [0x00u8; 4];
let size = (arg + 1) as usize;
input.read_exact(&mut buffer[..size]).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (Int) from the input"
.into(),
)
})?;
// Sign extention
if (buffer[size - 1] & 0b1000_0000) != 0 {
for b in buffer.iter_mut().skip(size) {
*b = 0xff;
}
}
Ok(Self::Int(i32::from_le_bytes(buffer)))
}
}
VALUE_LONG => {
if arg >= 8 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0 to 7 for VALUE_LONG"
)))
} else {
let mut buffer = [0x00u8; 8];
let size = (arg + 1) as usize;
input.read_exact(&mut buffer[..size]).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (Long) from the input"
.into(),
)
})?;
// Sign extention
if (buffer[size - 1] & 0b1000_0000) != 0 {
for b in buffer.iter_mut().skip(size) {
*b = 0xff;
}
}
Ok(Self::Long(i64::from_le_bytes(buffer)))
}
}
VALUE_FLOAT => {
if arg >= 4 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0, 1, 2 or 3 for VALUE_FLOAT"
)))
} else {
let mut buffer = [0x00u8; 4];
let size = (arg + 1) as usize;
input.read_exact(&mut buffer[..size]).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (Float) from the input"
.into(),
)
})?;
Ok(Self::Float(f32::from_le_bytes(buffer)))
}
}
VALUE_DOUBLE => {
if arg >= 8 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0 to 7 for VALUE_DOUBLE"
)))
} else {
let mut buffer = [0x00u8; 8];
let size = (arg + 1) as usize;
input.read_exact(&mut buffer[..size]).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (Double) from the input"
.into(),
)
})?;
Ok(Self::Double(f64::from_le_bytes(buffer)))
}
}
VALUE_METHOD_TYPE => {
if arg >= 4 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0, 1, 2 or 3 for VALUE_METHOD_TYPE"
)))
} else {
let mut buffer = [0x00u8; 4];
let size = (arg + 1) as usize;
input.read_exact(&mut buffer[..size]).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (MethodType) from the input"
.into(),
)
})?;
Ok(Self::MethodType(u32::from_le_bytes(buffer)))
}
}
VALUE_METHOD_HANDLE => {
if arg >= 4 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0, 1, 2 or 3 for VALUE_METHOD_HANDLE"
)))
} else {
let mut buffer = [0x00u8; 4];
let size = (arg + 1) as usize;
input.read_exact(&mut buffer[..size]).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (MethodHandle) from the input"
.into(),
)
})?;
Ok(Self::MethodHandle(u32::from_le_bytes(buffer)))
}
}
VALUE_STRING => {
if arg >= 4 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0, 1, 2 or 3 for VALUE_STRING"
)))
} else {
let mut buffer = [0x00u8; 4];
let size = (arg + 1) as usize;
input.read_exact(&mut buffer[..size]).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (String) from the input"
.into(),
)
})?;
Ok(Self::String(u32::from_le_bytes(buffer)))
}
}
VALUE_TYPE => {
if arg >= 4 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0, 1, 2 or 3 for VALUE_TYPE"
)))
} else {
let mut buffer = [0x00u8; 4];
let size = (arg + 1) as usize;
input.read_exact(&mut buffer[..size]).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (Type) from the input"
.into(),
)
})?;
Ok(Self::Type(u32::from_le_bytes(buffer)))
}
}
VALUE_FIELD => {
if arg >= 4 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0, 1, 2 or 3 for VALUE_FIELD"
)))
} else {
let mut buffer = [0x00u8; 4];
let size = (arg + 1) as usize;
input.read_exact(&mut buffer[..size]).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (Field) from the input"
.into(),
)
})?;
Ok(Self::Field(u32::from_le_bytes(buffer)))
}
}
VALUE_METHOD => {
if arg >= 4 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0, 1, 2 or 3 for VALUE_METHOD"
)))
} else {
let mut buffer = [0x00u8; 4];
let size = (arg + 1) as usize;
input.read_exact(&mut buffer[..size]).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (Method) from the input"
.into(),
)
})?;
Ok(Self::Method(u32::from_le_bytes(buffer)))
}
}
VALUE_ENUM => {
if arg >= 4 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0, 1, 2 or 3 for VALUE_ENUM"
)))
} else {
let mut buffer = [0x00u8; 4];
let size = (arg + 1) as usize;
input.read_exact(&mut buffer[..size]).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (Enum) from the input"
.into(),
)
})?;
Ok(Self::Enum(u32::from_le_bytes(buffer)))
}
}
VALUE_ARRAY => {
if arg != 0 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0 for VALUE_ARRAY"
)))
} else {
Ok(Self::Array(EncodedArray::deserialize(input)?))
}
}
VALUE_ANNOTATION => {
if arg != 0 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0 for VALUE_ANNOTATION"
)))
} else {
Ok(Self::Annotation(EncodedAnnotation::deserialize(input)?))
}
}
VALUE_NULL => {
if arg != 0 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0 for VALUE_NULL"
)))
} else {
Ok(Self::Null)
}
}
VALUE_BOOLEAN => {
if arg == 0 {
Ok(Self::Boolean(false))
} else if arg == 1 {
Ok(Self::Boolean(true))
} else {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0 or 1 for VALUE_BOOLEAN"
)))
}
}
ValueType(vt) => Err(Error::DeserializationError(format!(
"Unknown Value Type: 0x{vt:02x}"
))),
}
}
fn size(&self) -> usize {
match self {
Self::Byte(_) => 2,
Self::Short(val) => 1 + if *val <= 0x7f && *val >= -0x80 { 1 } else { 2 },
Self::Char(val) => 1 + if *val <= 0xff { 1 } else { 2 },
Self::Int(val) => {
1 + if *val <= 0x7f && *val >= -0x80 {
1
} else if *val <= 0x7f_ff && *val >= -0x80_00 {
2
} else if *val <= 0x7f_ff_ff && *val >= -0x80_00_00 {
3
} else {
4
}
}
Self::Long(val) => {
1 + if *val <= 0x7f && *val >= -0x80 {
1
} else if *val <= 0x7f_ff && *val >= -0x80_00 {
2
} else if *val <= 0x7f_ff_ff && *val >= -0x80_00_00 {
3
} else if *val <= 0x7f_ff_ff_ff && *val >= -0x80_00_00_00 {
4
} else if *val <= 0x7f_ff_ff_ff_ff && *val >= -0x80_00_00_00_00 {
5
} else if *val <= 0x7f_ff_ff_ff_ff_ff && *val >= -0x80_00_00_00_00_00 {
6
} else if *val <= 0x7f_ff_ff_ff_ff_ff_ff && *val >= -0x80_00_00_00_00_00 {
7
} else {
8
}
}
Self::Float(val) => {
let trailing_zeros = val
.to_be_bytes()
.iter()
.rev()
.take_while(|b| **b == 0)
.count();
std::cmp::max(1 + 4 - trailing_zeros, 2)
}
Self::Double(val) => {
let trailing_zeros = val
.to_be_bytes()
.iter()
.rev()
.take_while(|b| **b == 0)
.count();
std::cmp::max(1 + 8 - trailing_zeros, 2)
}
Self::MethodType(idx) => Idx(*idx, VALUE_TYPE).size(),
Self::MethodHandle(idx) => Idx(*idx, VALUE_METHOD_HANDLE).size(),
Self::String(idx) => Idx(*idx, VALUE_STRING).size(),
Self::Type(idx) => Idx(*idx, VALUE_TYPE).size(),
Self::Field(idx) => Idx(*idx, VALUE_FIELD).size(),
Self::Method(idx) => Idx(*idx, VALUE_METHOD).size(),
Self::Enum(idx) => Idx(*idx, VALUE_ENUM).size(),
Self::Array(arr) => 1 + arr.size(),
Self::Annotation(ann) => 1 + ann.size(),
Self::Null => 1,
Self::Boolean(_) => 1,
}
}
}
/// Utility type to encode/decode an Idx.
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
struct Idx(u32, ValueType);
impl Serializable for Idx {
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
let Idx(idx, ValueType(vt)) = self;
let size = self.size() - 2;
let bytes: [u8; 4] = idx.to_le_bytes();
let vec = &bytes[..(size + 1)];
output
.write_all(&[((size as u8) << 5) | vt])
.map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Idx to output: {err}"
))
})?;
output.write_all(vec).map_err(|err| {
Error::SerializationError(format!("Failed to write serialized Idx to output: {err}"))
})?;
Ok(())
}
/// unimplemented, not used because the ValueType must be known before deserializing the idx.
fn deserialize(_input: &mut dyn ReadSeek) -> Result<Self> {
unimplemented!()
}
fn size(&self) -> usize {
let Idx(idx, _) = *self;
1 + if idx <= 0xff {
1
} else if idx <= 0xffff {
2
} else if idx <= 0xffffff {
3
} else {
4
}
}
}
// TODO: more TESTS!!!
#[cfg(test)]
mod test {
use super::*;
use crate::*;
#[test]
fn boolean_deserialize() {
assert_eq!(
EncodedValue::deserialize_from_slice(&[0b0001_1111]).unwrap(),
EncodedValue::Boolean(false)
);
assert_eq!(
EncodedValue::deserialize_from_slice(&[0b0011_1111]).unwrap(),
EncodedValue::Boolean(true)
);
assert!(EncodedValue::deserialize_from_slice(&[0b0101_1111]).is_err());
}
#[test]
fn boolean_serialize() {
assert_eq!(
EncodedValue::Boolean(false).serialize_to_vec().unwrap(),
vec![0b0001_1111]
);
assert_eq!(
EncodedValue::Boolean(true).serialize_to_vec().unwrap(),
vec![0b0011_1111]
);
}
#[test]
fn annotation_deserialize() {
assert_eq!(
EncodedValue::deserialize_from_slice(&[0x1d, 0xf6, 0x33, 0x01, 0xd3, 0xe8, 0x02, 0x3f])
.unwrap(),
EncodedValue::Annotation(EncodedAnnotation {
type_idx: Uleb128(6646),
elements: vec![AnnotationElement {
name_idx: Uleb128(46163),
value: EncodedValue::Boolean(true)
}]
})
);
}
#[test]
fn annotation_serialize() {
assert_eq!(
vec![0x1d, 0xf6, 0x33, 0x01, 0xd3, 0xe8, 0x02, 0x3f],
EncodedValue::Annotation(EncodedAnnotation {
type_idx: Uleb128(6646),
elements: vec![AnnotationElement {
name_idx: Uleb128(46163),
value: EncodedValue::Boolean(true)
}]
})
.serialize_to_vec()
.unwrap()
);
}
#[test]
fn long_serialize() {
assert_eq!(
vec![
0x06 | 7 << 5,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x80
],
EncodedValue::Long(-9223372036854775808)
.serialize_to_vec()
.unwrap(),
);
assert_eq!(
vec![0x06 | 0 << 5, 0xff],
EncodedValue::Long(-1).serialize_to_vec().unwrap(),
);
assert_eq!(
vec![0x06 | 0 << 5, 0x01],
EncodedValue::Long(1).serialize_to_vec().unwrap(),
);
assert_eq!(
vec![0x06 | 1 << 5, 0x23, 0x01],
EncodedValue::Long(0x0123).serialize_to_vec().unwrap(),
);
}
#[test]
fn long_deserialize() {
assert_eq!(
EncodedValue::deserialize_from_slice(&[
0x06 | 7 << 5,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x80
])
.unwrap(),
EncodedValue::Long(-9223372036854775808),
);
assert_eq!(
EncodedValue::deserialize_from_slice(&[0x06 | 0 << 5, 0xff]).unwrap(),
EncodedValue::Long(-1),
);
assert_eq!(
EncodedValue::deserialize_from_slice(&[0x06 | 0 << 5, 0x01]).unwrap(),
EncodedValue::Long(1),
);
assert_eq!(
EncodedValue::deserialize_from_slice(&[0x06 | 1 << 5, 0x23, 0x01]).unwrap(),
EncodedValue::Long(0x0123),
);
}
#[test]
fn short_serialize() {
assert_eq!(
vec![0x02 | 0 << 5, 0xff],
EncodedValue::Short(-1).serialize_to_vec().unwrap(),
);
assert_eq!(
vec![0x02 | 0 << 5, 0x01],
EncodedValue::Short(1).serialize_to_vec().unwrap(),
);
assert_eq!(
vec![0x02 | 1 << 5, 0x23, 0x01],
EncodedValue::Short(0x0123).serialize_to_vec().unwrap(),
);
}
#[test]
fn short_deserialize() {
assert_eq!(
EncodedValue::deserialize_from_slice(&[0x02 | 0 << 5, 0xff]).unwrap(),
EncodedValue::Short(-1),
);
assert_eq!(
EncodedValue::deserialize_from_slice(&[0x02 | 0 << 5, 0x01]).unwrap(),
EncodedValue::Short(1),
);
assert_eq!(
EncodedValue::deserialize_from_slice(&[0x02 | 1 << 5, 0x23, 0x01]).unwrap(),
EncodedValue::Short(0x0123),
);
}
#[test]
fn int_serialize() {
assert_eq!(
vec![0x04 | 3 << 5, 0x00, 0x00, 0x00, 0x80],
EncodedValue::Int(-2147483648).serialize_to_vec().unwrap(),
);
assert_eq!(
vec![0x04 | 0 << 5, 0xff],
EncodedValue::Int(-1).serialize_to_vec().unwrap(),
);
assert_eq!(
vec![0x04 | 0 << 5, 0x01],
EncodedValue::Int(1).serialize_to_vec().unwrap(),
);
assert_eq!(
vec![0x04 | 1 << 5, 0x23, 0x01],
EncodedValue::Int(0x0123).serialize_to_vec().unwrap(),
);
}
#[test]
fn int_deserialize() {
assert_eq!(
EncodedValue::deserialize_from_slice(&[0x04 | 3 << 5, 0x00, 0x00, 0x00, 0x80]).unwrap(),
EncodedValue::Int(-2147483648),
);
assert_eq!(
EncodedValue::deserialize_from_slice(&[0x04 | 0 << 5, 0xff]).unwrap(),
EncodedValue::Int(-1),
);
assert_eq!(
EncodedValue::deserialize_from_slice(&[0x04 | 0 << 5, 0x01]).unwrap(),
EncodedValue::Int(1),
);
assert_eq!(
EncodedValue::deserialize_from_slice(&[0x04 | 1 << 5, 0x23, 0x01]).unwrap(),
EncodedValue::Int(0x0123),
);
}
}