add encoded scalar values
This commit is contained in:
parent
49d6094d6f
commit
6020b173a0
4 changed files with 713 additions and 0 deletions
18
androscalpel_serializer/src/annotation.rs
Normal file
18
androscalpel_serializer/src/annotation.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
use crate::{ReadSeek, Result, Serializable};
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct EncodedAnnotation;
|
||||||
|
|
||||||
|
impl Serializable for EncodedAnnotation {
|
||||||
|
fn serialize(&self, _output: &mut dyn Write) -> Result<()> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
fn deserialize(_input: &mut dyn ReadSeek) -> Result<Self> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size(&self) -> usize {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
18
androscalpel_serializer/src/array.rs
Normal file
18
androscalpel_serializer/src/array.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
use crate::{ReadSeek, Result, Serializable};
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct EncodedArray;
|
||||||
|
|
||||||
|
impl Serializable for EncodedArray {
|
||||||
|
fn serialize(&self, _output: &mut dyn Write) -> Result<()> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
fn deserialize(_input: &mut dyn ReadSeek) -> Result<Self> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size(&self) -> usize {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,13 @@
|
||||||
|
pub mod annotation;
|
||||||
|
pub mod array;
|
||||||
pub mod constant;
|
pub mod constant;
|
||||||
pub mod core;
|
pub mod core;
|
||||||
|
pub mod value;
|
||||||
|
|
||||||
pub use androscalpel_serializer_derive::*;
|
pub use androscalpel_serializer_derive::*;
|
||||||
|
|
||||||
pub use crate::core::*;
|
pub use crate::core::*;
|
||||||
|
pub use annotation::*;
|
||||||
|
pub use array::*;
|
||||||
pub use constant::*;
|
pub use constant::*;
|
||||||
|
pub use value::*;
|
||||||
|
|
|
||||||
671
androscalpel_serializer/src/value.rs
Normal file
671
androscalpel_serializer/src/value.rs
Normal file
|
|
@ -0,0 +1,671 @@
|
||||||
|
//! 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<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 & 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<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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue