//! 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; // TODO: TESTS!!! /// 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), MethodType(u32), MethodHandle(u32), String(u32), Type(u32), Field(u32), Method(u32), 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_be_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[(2 - 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_be_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[(2 - 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_be_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[(2 - 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_be_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[(2 - 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_be_bytes(); 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_be_bytes(); 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 { 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 & 0b0011_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; let first_byte = 2 - size; input.read_exact(&mut buffer[first_byte..]).map_err(|_| { Error::InputTooSmall( "Failed to read all bytes for the EncodedValue (Short) from the input" .into(), ) })?; // Sign extention if (buffer[first_byte] & 0b1000_0000) != 0 { for b in buffer.iter_mut().take(first_byte - 1) { *b = 0xff; } } Ok(Self::Short(i16::from_be_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; let first_byte = 2 - size; input.read_exact(&mut buffer[first_byte..]).map_err(|_| { Error::InputTooSmall( "Failed to read all bytes for the EncodedValue (Char) from the input" .into(), ) })?; Ok(Self::Char(u16::from_be_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; let first_byte = 4 - size; input.read_exact(&mut buffer[first_byte..]).map_err(|_| { Error::InputTooSmall( "Failed to read all bytes for the EncodedValue (Int) from the input" .into(), ) })?; // Sign extention if (buffer[first_byte] & 0b1000_0000) != 0 { for b in buffer.iter_mut().take(first_byte - 1) { *b = 0xff; } } Ok(Self::Int(i32::from_be_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; let first_byte = 8 - size; input.read_exact(&mut buffer[first_byte..]).map_err(|_| { Error::InputTooSmall( "Failed to read all bytes for the EncodedValue (Long) from the input" .into(), ) })?; // Sign extention if (buffer[first_byte] & 0b1000_0000) != 0 { for b in buffer.iter_mut().take(first_byte - 1) { *b = 0xff; } } Ok(Self::Long(i64::from_be_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_be_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_be_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; let first_byte = 4 - size; input.read_exact(&mut buffer[first_byte..]).map_err(|_| { Error::InputTooSmall( "Failed to read all bytes for the EncodedValue (MethodType) from the input" .into(), ) })?; Ok(Self::MethodType(u32::from_be_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; let first_byte = 4 - size; input.read_exact(&mut buffer[first_byte..]).map_err(|_| { Error::InputTooSmall( "Failed to read all bytes for the EncodedValue (MethodHandle) from the input" .into(), ) })?; Ok(Self::MethodHandle(u32::from_be_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; let first_byte = 4 - size; input.read_exact(&mut buffer[first_byte..]).map_err(|_| { Error::InputTooSmall( "Failed to read all bytes for the EncodedValue (String) from the input" .into(), ) })?; Ok(Self::String(u32::from_be_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; let first_byte = 4 - size; input.read_exact(&mut buffer[first_byte..]).map_err(|_| { Error::InputTooSmall( "Failed to read all bytes for the EncodedValue (Type) from the input" .into(), ) })?; Ok(Self::Type(u32::from_be_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; let first_byte = 4 - size; input.read_exact(&mut buffer[first_byte..]).map_err(|_| { Error::InputTooSmall( "Failed to read all bytes for the EncodedValue (Field) from the input" .into(), ) })?; Ok(Self::Field(u32::from_be_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; let first_byte = 4 - size; input.read_exact(&mut buffer[first_byte..]).map_err(|_| { Error::InputTooSmall( "Failed to read all bytes for the EncodedValue (Method) from the input" .into(), ) })?; Ok(Self::Method(u32::from_be_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; let first_byte = 4 - size; input.read_exact(&mut buffer[first_byte..]).map_err(|_| { Error::InputTooSmall( "Failed to read all bytes for the EncodedValue (Enum) from the input" .into(), ) })?; Ok(Self::Enum(u32::from_be_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::Array(EncodedArray::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(); 1 + 4 - trailing_zeros } Self::Double(val) => { let trailing_zeros = val .to_be_bytes() .iter() .rev() .take_while(|b| **b == 0) .count(); 1 + 8 - trailing_zeros } 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_be_bytes(); let vec = &bytes[(4 - 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 { 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 } } }