fix stuff, add class annotation
This commit is contained in:
parent
b8b4e28f2d
commit
cf55766653
10 changed files with 164 additions and 117 deletions
|
|
@ -5,18 +5,14 @@ use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::{dex_id::IdType, value::DexValue, DexString};
|
use crate::{dex_id::IdType, value::DexValue, DexString};
|
||||||
|
|
||||||
/// An annotation.
|
/// Annotation with a visibility
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Annotation {
|
pub struct DexAnnotationItem {
|
||||||
// TODO: check the relation between type and encoded_value.
|
|
||||||
/// The type of the annotation.
|
|
||||||
#[pyo3(get, set)]
|
|
||||||
pub type_: IdType,
|
|
||||||
// TODO: the get/set will probably be wonky on the python side when edditing
|
// TODO: the get/set will probably be wonky on the python side when edditing
|
||||||
/// The annotation elements.
|
/// The actual annotation
|
||||||
#[pyo3(get, set)]
|
#[pyo3(get, set)]
|
||||||
pub elements: HashMap<DexString, DexValue>, // TODO: check MemberName syntax?
|
pub annotation: DexAnnotation,
|
||||||
// TODO: enforce exclusivity
|
// TODO: enforce exclusivity
|
||||||
/// If the annotation visibility is set to build
|
/// If the annotation visibility is set to build
|
||||||
#[pyo3(get, set)]
|
#[pyo3(get, set)]
|
||||||
|
|
@ -30,12 +26,11 @@ pub struct Annotation {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl Annotation {
|
impl DexAnnotationItem {
|
||||||
#[new]
|
#[new]
|
||||||
pub fn new(type_: IdType, elements: HashMap<DexString, DexValue>) -> Self {
|
pub fn new(annotation: DexAnnotation) -> Self {
|
||||||
Self {
|
Self {
|
||||||
type_,
|
annotation,
|
||||||
elements,
|
|
||||||
visibility_build: false,
|
visibility_build: false,
|
||||||
visibility_runtime: false,
|
visibility_runtime: false,
|
||||||
visibility_system: false,
|
visibility_system: false,
|
||||||
|
|
@ -47,7 +42,6 @@ impl Annotation {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn __repr__(&self) -> String {
|
pub fn __repr__(&self) -> String {
|
||||||
let type_ = self.type_.__str__();
|
|
||||||
let visibility =
|
let visibility =
|
||||||
if !(self.visibility_build || self.visibility_runtime || self.visibility_system) {
|
if !(self.visibility_build || self.visibility_runtime || self.visibility_system) {
|
||||||
"none".into()
|
"none".into()
|
||||||
|
|
@ -64,11 +58,43 @@ impl Annotation {
|
||||||
}
|
}
|
||||||
visibility
|
visibility
|
||||||
};
|
};
|
||||||
|
let annotation = self.annotation.__repr__();
|
||||||
|
format!("AnnotationItem(visibility: {visibility}, {annotation})")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An annotation.
|
||||||
|
#[pyclass]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct DexAnnotation {
|
||||||
|
// TODO: check the relation between type and encoded_value.
|
||||||
|
/// The type of the annotation.
|
||||||
|
#[pyo3(get, set)]
|
||||||
|
pub type_: IdType,
|
||||||
|
// TODO: the get/set will probably be wonky on the python side when edditing
|
||||||
|
/// The annotation elements.
|
||||||
|
#[pyo3(get, set)]
|
||||||
|
pub elements: HashMap<DexString, DexValue>, // TODO: check MemberName syntax?
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pymethods]
|
||||||
|
impl DexAnnotation {
|
||||||
|
#[new]
|
||||||
|
pub fn new(type_: IdType, elements: HashMap<DexString, DexValue>) -> Self {
|
||||||
|
Self { type_, elements }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __str__(&self) -> String {
|
||||||
|
self.__repr__()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __repr__(&self) -> String {
|
||||||
|
let type_ = self.type_.__str__();
|
||||||
let mut elts: String = "{".into();
|
let mut elts: String = "{".into();
|
||||||
for (key, val) in self.elements.iter() {
|
for (key, val) in self.elements.iter() {
|
||||||
elts += &format!("{}: {}, ", key.__str__(), val.__str__());
|
elts += &format!("{}: {}, ", key.__str__(), val.__str__());
|
||||||
}
|
}
|
||||||
elts += "}";
|
elts += "}";
|
||||||
format!("Annotation({type_}, visibility: {visibility}, {elts})")
|
format!("Annotation({type_}, {elts})")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ impl Apk {
|
||||||
let mut annotations = vec![];
|
let mut annotations = vec![];
|
||||||
if let Some(annotations_directory) = annotations_directory {
|
if let Some(annotations_directory) = annotations_directory {
|
||||||
if annotations_directory.class_annotations_off != 0 {
|
if annotations_directory.class_annotations_off != 0 {
|
||||||
annotations = Self::get_annotations_from_annotation_set_off(
|
annotations = Self::get_annotation_items_from_annotation_set_off(
|
||||||
annotations_directory.class_annotations_off,
|
annotations_directory.class_annotations_off,
|
||||||
dex,
|
dex,
|
||||||
)?;
|
)?;
|
||||||
|
|
@ -164,10 +164,11 @@ impl Apk {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_annotations_from_annotation_set_off(
|
/// Return a [`Vec<DexAnnotationItem>`] for the offset of an [`AnnotationSet`].
|
||||||
|
pub fn get_annotation_items_from_annotation_set_off(
|
||||||
annotations_set_off: u32,
|
annotations_set_off: u32,
|
||||||
dex: &DexFileReader,
|
dex: &DexFileReader,
|
||||||
) -> Result<Vec<Annotation>> {
|
) -> Result<Vec<DexAnnotationItem>> {
|
||||||
let mut annotations = vec![];
|
let mut annotations = vec![];
|
||||||
for annotation_off in dex
|
for annotation_off in dex
|
||||||
.get_struct_at_offset::<AnnotationSetItem>(annotations_set_off)?
|
.get_struct_at_offset::<AnnotationSetItem>(annotations_set_off)?
|
||||||
|
|
@ -181,16 +182,9 @@ impl Apk {
|
||||||
AnnotationVisibility::Runtime => (false, true, false),
|
AnnotationVisibility::Runtime => (false, true, false),
|
||||||
AnnotationVisibility::System => (false, false, true),
|
AnnotationVisibility::System => (false, false, true),
|
||||||
};
|
};
|
||||||
let type_ = Self::get_id_type_from_idx(item.annotation.type_idx.0 as usize, dex)?;
|
let annotation = Self::get_annotations_from_encoded_annotation(&item.annotation, dex)?;
|
||||||
let mut elements = HashMap::new();
|
annotations.push(DexAnnotationItem {
|
||||||
for elt in item.annotation.elements {
|
annotation,
|
||||||
let name: DexString = dex.get_string(elt.name_idx.0)?.into();
|
|
||||||
let value = Self::encoded_value_to_dex_value(&elt.value, dex)?;
|
|
||||||
elements.insert(name, value);
|
|
||||||
}
|
|
||||||
annotations.push(Annotation {
|
|
||||||
type_,
|
|
||||||
elements,
|
|
||||||
visibility_build,
|
visibility_build,
|
||||||
visibility_runtime,
|
visibility_runtime,
|
||||||
visibility_system,
|
visibility_system,
|
||||||
|
|
@ -199,6 +193,21 @@ impl Apk {
|
||||||
Ok(annotations)
|
Ok(annotations)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return a [`DexAnnotation`] from [`EncodedAnnotation`]
|
||||||
|
pub fn get_annotations_from_encoded_annotation(
|
||||||
|
encoded_annotation: &EncodedAnnotation,
|
||||||
|
dex: &DexFileReader,
|
||||||
|
) -> Result<DexAnnotation> {
|
||||||
|
let type_ = Self::get_id_type_from_idx(encoded_annotation.type_idx.0 as usize, dex)?;
|
||||||
|
let mut elements = HashMap::new();
|
||||||
|
for elt in &encoded_annotation.elements {
|
||||||
|
let name: DexString = dex.get_string(elt.name_idx.0)?.into();
|
||||||
|
let value = Self::encoded_value_to_dex_value(&elt.value, dex)?;
|
||||||
|
elements.insert(name, value);
|
||||||
|
}
|
||||||
|
Ok(DexAnnotation { type_, elements })
|
||||||
|
}
|
||||||
|
|
||||||
/// Return a [`IdMethodType`] from its idx.
|
/// Return a [`IdMethodType`] from its idx.
|
||||||
pub fn get_id_method_type_from_idx(idx: usize, dex: &DexFileReader) -> Result<IdMethodType> {
|
pub fn get_id_method_type_from_idx(idx: usize, dex: &DexFileReader) -> Result<IdMethodType> {
|
||||||
let proto = dex.get_proto_id(idx)?;
|
let proto = dex.get_proto_id(idx)?;
|
||||||
|
|
@ -340,7 +349,9 @@ impl Apk {
|
||||||
.map(|val| Self::encoded_value_to_dex_value(val, dex))
|
.map(|val| Self::encoded_value_to_dex_value(val, dex))
|
||||||
.collect::<Result<_>>()?,
|
.collect::<Result<_>>()?,
|
||||||
))),
|
))),
|
||||||
EncodedValue::Annotation(_val) => todo!(), //Ok(DexValue::Annotation(DexAnnotation(*val))),
|
EncodedValue::Annotation(val) => Ok(DexValue::Annotation(
|
||||||
|
Self::get_annotations_from_encoded_annotation(val, dex)?,
|
||||||
|
)),
|
||||||
EncodedValue::Null => Ok(DexValue::Null(DexNull)),
|
EncodedValue::Null => Ok(DexValue::Null(DexNull)),
|
||||||
EncodedValue::Boolean(val) => Ok(DexValue::Boolean(DexBoolean(*val))),
|
EncodedValue::Boolean(val) => Ok(DexValue::Boolean(DexBoolean(*val))),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
use crate::{Annotation, DexString, Field, Method};
|
use crate::{DexAnnotationItem, DexString, Field, Method};
|
||||||
|
|
||||||
/// Represent an apk
|
/// Represent an apk
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
|
|
@ -61,7 +61,11 @@ pub struct Class {
|
||||||
pub virtual_methods: Vec<Method>,
|
pub virtual_methods: Vec<Method>,
|
||||||
// Do we need to distinguish direct and virtual (all the other) methods?
|
// Do we need to distinguish direct and virtual (all the other) methods?
|
||||||
// Maybe overlapping descriptor (same name, class and proto?)
|
// Maybe overlapping descriptor (same name, class and proto?)
|
||||||
pub annotations: Vec<Annotation>,
|
/// The annotation related to this class (note: this does not include the
|
||||||
|
/// methods/field/parameters annotations, they are stored in the methods and fields
|
||||||
|
/// structutres)
|
||||||
|
#[pyo3(get, set)]
|
||||||
|
pub annotations: Vec<DexAnnotationItem>,
|
||||||
// TODO: mix annotation data to fields / methods / class to make it more practicle
|
// TODO: mix annotation data to fields / methods / class to make it more practicle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -418,26 +418,3 @@ impl IdEnum {
|
||||||
format!("DexEnum({})", self.__str__())
|
format!("DexEnum({})", self.__str__())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyclass]
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub struct IdAnnotation;
|
|
||||||
#[pymethods]
|
|
||||||
impl IdAnnotation {
|
|
||||||
#[new]
|
|
||||||
pub fn _new() -> Self {
|
|
||||||
Self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_value(&self) {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __str__(&self) -> String {
|
|
||||||
self.__repr__()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __repr__(&self) -> String {
|
|
||||||
"DexAnnotation".into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
use std::collections::hash_map::DefaultHasher;
|
||||||
|
use std::hash::{Hash, Hasher};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use pyo3::class::basic::CompareOp;
|
use pyo3::class::basic::CompareOp;
|
||||||
|
|
@ -65,6 +68,13 @@ impl From<String> for DexString {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Hash for DexString {
|
||||||
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||||
|
self.get_utf16_size().hash(state);
|
||||||
|
self.get_bytes().hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl DexString {
|
impl DexString {
|
||||||
#[new]
|
#[new]
|
||||||
|
|
@ -99,12 +109,11 @@ impl DexString {
|
||||||
pub fn __repr__(&self) -> String {
|
pub fn __repr__(&self) -> String {
|
||||||
self.into()
|
self.into()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl std::hash::Hash for DexString {
|
fn __hash__(&self) -> u64 {
|
||||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
let mut hasher = DefaultHasher::new();
|
||||||
self.get_utf16_size().hash(state);
|
self.hash(&mut hasher);
|
||||||
self.get_bytes().hash(state);
|
hasher.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -139,9 +148,9 @@ fn androscalpel(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
m.add_class::<InvokeDirect>()?;
|
m.add_class::<InvokeDirect>()?;
|
||||||
m.add_class::<InvokeInterface>()?;
|
m.add_class::<InvokeInterface>()?;
|
||||||
|
|
||||||
m.add_class::<Annotation>()?;
|
m.add_class::<DexAnnotationItem>()?;
|
||||||
|
m.add_class::<DexAnnotation>()?;
|
||||||
m.add_class::<DexArray>()?;
|
m.add_class::<DexArray>()?;
|
||||||
m.add_class::<IdAnnotation>()?;
|
|
||||||
m.add_class::<FieldVisibility>()?;
|
m.add_class::<FieldVisibility>()?;
|
||||||
m.add_class::<Method>()?;
|
m.add_class::<Method>()?;
|
||||||
m.add_class::<Field>()?;
|
m.add_class::<Field>()?;
|
||||||
|
|
|
||||||
|
|
@ -259,6 +259,6 @@ impl DexArray {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn __repr__(&self) -> String {
|
pub fn __repr__(&self) -> String {
|
||||||
"DexArray()".into()
|
"DexArray(...)".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
use pyo3::exceptions::PyTypeError;
|
use pyo3::exceptions::PyTypeError;
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
use crate::{dex_id::*, scalar::*, DexString, MethodHandle};
|
use crate::{dex_id::*, scalar::*, DexAnnotation, DexString, MethodHandle};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum DexValue {
|
pub enum DexValue {
|
||||||
|
|
@ -22,7 +22,7 @@ pub enum DexValue {
|
||||||
Method(IdMethod),
|
Method(IdMethod),
|
||||||
Enum(IdEnum),
|
Enum(IdEnum),
|
||||||
Array(DexArray),
|
Array(DexArray),
|
||||||
Annotation(IdAnnotation),
|
Annotation(DexAnnotation),
|
||||||
Null(DexNull),
|
Null(DexNull),
|
||||||
Boolean(DexBoolean),
|
Boolean(DexBoolean),
|
||||||
}
|
}
|
||||||
|
|
@ -55,7 +55,7 @@ impl<'source> FromPyObject<'source> for DexValue {
|
||||||
Ok(Self::Enum(val))
|
Ok(Self::Enum(val))
|
||||||
} else if let Ok(val) = DexArray::extract(ob) {
|
} else if let Ok(val) = DexArray::extract(ob) {
|
||||||
Ok(Self::Array(val))
|
Ok(Self::Array(val))
|
||||||
} else if let Ok(val) = IdAnnotation::extract(ob) {
|
} else if let Ok(val) = DexAnnotation::extract(ob) {
|
||||||
Ok(Self::Annotation(val))
|
Ok(Self::Annotation(val))
|
||||||
} else if let Ok(val) = DexNull::extract(ob) {
|
} else if let Ok(val) = DexNull::extract(ob) {
|
||||||
Ok(Self::Null(val))
|
Ok(Self::Null(val))
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,7 @@ mod test {
|
||||||
0xbe, 0x37, 0x01, 0xa8, 0x9f, 0x03, 0x1d, 0xf6, 0x33, 0x01, 0xd3, 0xe8, 0x02, 0x3f,
|
0xbe, 0x37, 0x01, 0xa8, 0x9f, 0x03, 0x1d, 0xf6, 0x33, 0x01, 0xd3, 0xe8, 0x02, 0x3f,
|
||||||
];
|
];
|
||||||
const ENCODED_ANNOTATION_RAW_2: &[u8] = &[0xf6, 0x33, 0x01, 0xd3, 0xe8, 0x02, 0x3f];
|
const ENCODED_ANNOTATION_RAW_2: &[u8] = &[0xf6, 0x33, 0x01, 0xd3, 0xe8, 0x02, 0x3f];
|
||||||
|
const ENCODED_ANNOTATION_RAW_3: &[u8] = &[0xbf, 0x37, 0x01, 0xa8, 0x9f, 0x03, 0x38, 0x38, 0x02];
|
||||||
const ANNOTATION_ELEMENT_RAW: &[u8] = &[
|
const ANNOTATION_ELEMENT_RAW: &[u8] = &[
|
||||||
0xa8, 0x9f, 0x03, 0x1d, 0xf6, 0x33, 0x01, 0xd3, 0xe8, 0x02, 0x3f,
|
0xa8, 0x9f, 0x03, 0x1d, 0xf6, 0x33, 0x01, 0xd3, 0xe8, 0x02, 0x3f,
|
||||||
];
|
];
|
||||||
|
|
@ -94,6 +95,16 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn deserialize_encoded_annotation() {
|
fn deserialize_encoded_annotation() {
|
||||||
|
assert_eq!(
|
||||||
|
EncodedAnnotation::deserialize_from_slice(ENCODED_ANNOTATION_RAW_3).unwrap(),
|
||||||
|
EncodedAnnotation {
|
||||||
|
type_idx: Uleb128(7103),
|
||||||
|
elements: vec![AnnotationElement {
|
||||||
|
name_idx: Uleb128(53160),
|
||||||
|
value: EncodedValue::Type(0x0238)
|
||||||
|
}],
|
||||||
|
}
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
EncodedAnnotation::deserialize_from_slice(ENCODED_ANNOTATION_RAW_2).unwrap(),
|
EncodedAnnotation::deserialize_from_slice(ENCODED_ANNOTATION_RAW_2).unwrap(),
|
||||||
EncodedAnnotation {
|
EncodedAnnotation {
|
||||||
|
|
|
||||||
|
|
@ -241,6 +241,7 @@ mod test {
|
||||||
const ANNOTATION_ITEM: &[u8] = &[
|
const ANNOTATION_ITEM: &[u8] = &[
|
||||||
0x02, 0xbe, 0x37, 0x01, 0xa8, 0x9f, 0x03, 0x1d, 0xf6, 0x33, 0x01, 0xd3, 0xe8, 0x02, 0x3f,
|
0x02, 0xbe, 0x37, 0x01, 0xa8, 0x9f, 0x03, 0x1d, 0xf6, 0x33, 0x01, 0xd3, 0xe8, 0x02, 0x3f,
|
||||||
];
|
];
|
||||||
|
const ANNOTATION_ITEM_2: &[u8] = &[0x02, 0xbf, 0x37, 0x01, 0xa8, 0x9f, 0x03, 0x38, 0x38, 0x02];
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn deserialize_annotation_item() {
|
fn deserialize_annotation_item() {
|
||||||
|
|
@ -252,6 +253,14 @@ mod test {
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
AnnotationItem::deserialize_from_slice(ANNOTATION_ITEM_2).unwrap(),
|
||||||
|
AnnotationItem {
|
||||||
|
visibility: AnnotationVisibility::System,
|
||||||
|
annotation: EncodedAnnotation::deserialize_from_slice(&ANNOTATION_ITEM_2[1..])
|
||||||
|
.unwrap(),
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -267,5 +276,16 @@ mod test {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_slice()
|
.as_slice()
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
ANNOTATION_ITEM_2,
|
||||||
|
AnnotationItem {
|
||||||
|
visibility: AnnotationVisibility::System,
|
||||||
|
annotation: EncodedAnnotation::deserialize_from_slice(&ANNOTATION_ITEM_2[1..])
|
||||||
|
.unwrap(),
|
||||||
|
}
|
||||||
|
.serialize_to_vec()
|
||||||
|
.unwrap()
|
||||||
|
.as_slice()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ impl Serializable for EncodedValue {
|
||||||
}
|
}
|
||||||
Self::Short(val) => {
|
Self::Short(val) => {
|
||||||
let size = self.size();
|
let size = self.size();
|
||||||
let bytes: [u8; 2] = val.to_be_bytes();
|
let bytes: [u8; 2] = val.to_le_bytes();
|
||||||
output
|
output
|
||||||
.write_all(&[((size as u8 - 2) << 5) | VALUE_SHORT.0])
|
.write_all(&[((size as u8 - 2) << 5) | VALUE_SHORT.0])
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
|
|
@ -112,7 +112,7 @@ impl Serializable for EncodedValue {
|
||||||
"Failed to write serialized Short to output: {err}"
|
"Failed to write serialized Short to output: {err}"
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
output.write_all(&bytes[(2 - size + 1)..]).map_err(|err| {
|
output.write_all(&bytes[..(size - 1)]).map_err(|err| {
|
||||||
Error::SerializationError(format!(
|
Error::SerializationError(format!(
|
||||||
"Failed to write serialized Short to output: {err}"
|
"Failed to write serialized Short to output: {err}"
|
||||||
))
|
))
|
||||||
|
|
@ -121,7 +121,7 @@ impl Serializable for EncodedValue {
|
||||||
}
|
}
|
||||||
Self::Char(val) => {
|
Self::Char(val) => {
|
||||||
let size = self.size();
|
let size = self.size();
|
||||||
let bytes: [u8; 2] = val.to_be_bytes();
|
let bytes: [u8; 2] = val.to_le_bytes();
|
||||||
output
|
output
|
||||||
.write_all(&[((size as u8 - 2) << 5) | VALUE_CHAR.0])
|
.write_all(&[((size as u8 - 2) << 5) | VALUE_CHAR.0])
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
|
|
@ -129,7 +129,7 @@ impl Serializable for EncodedValue {
|
||||||
"Failed to write serialized Char to output: {err}"
|
"Failed to write serialized Char to output: {err}"
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
output.write_all(&bytes[(2 - size + 1)..]).map_err(|err| {
|
output.write_all(&bytes[..(size - 1)]).map_err(|err| {
|
||||||
Error::SerializationError(format!(
|
Error::SerializationError(format!(
|
||||||
"Failed to write serialized Char to output: {err}"
|
"Failed to write serialized Char to output: {err}"
|
||||||
))
|
))
|
||||||
|
|
@ -138,7 +138,7 @@ impl Serializable for EncodedValue {
|
||||||
}
|
}
|
||||||
Self::Int(val) => {
|
Self::Int(val) => {
|
||||||
let size = self.size();
|
let size = self.size();
|
||||||
let bytes: [u8; 4] = val.to_be_bytes();
|
let bytes: [u8; 4] = val.to_le_bytes();
|
||||||
output
|
output
|
||||||
.write_all(&[((size as u8 - 2) << 5) | VALUE_INT.0])
|
.write_all(&[((size as u8 - 2) << 5) | VALUE_INT.0])
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
|
|
@ -146,7 +146,7 @@ impl Serializable for EncodedValue {
|
||||||
"Failed to write serialized Int to output: {err}"
|
"Failed to write serialized Int to output: {err}"
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
output.write_all(&bytes[(2 - size + 1)..]).map_err(|err| {
|
output.write_all(&bytes[..(size - 1)]).map_err(|err| {
|
||||||
Error::SerializationError(format!(
|
Error::SerializationError(format!(
|
||||||
"Failed to write serialized Int to output: {err}"
|
"Failed to write serialized Int to output: {err}"
|
||||||
))
|
))
|
||||||
|
|
@ -155,7 +155,7 @@ impl Serializable for EncodedValue {
|
||||||
}
|
}
|
||||||
Self::Long(val) => {
|
Self::Long(val) => {
|
||||||
let size = self.size();
|
let size = self.size();
|
||||||
let bytes: [u8; 8] = val.to_be_bytes();
|
let bytes: [u8; 8] = val.to_le_bytes();
|
||||||
output
|
output
|
||||||
.write_all(&[((size as u8 - 2) << 5) | VALUE_LONG.0])
|
.write_all(&[((size as u8 - 2) << 5) | VALUE_LONG.0])
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
|
|
@ -163,7 +163,7 @@ impl Serializable for EncodedValue {
|
||||||
"Failed to write serialized Long to output: {err}"
|
"Failed to write serialized Long to output: {err}"
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
output.write_all(&bytes[(2 - size + 1)..]).map_err(|err| {
|
output.write_all(&bytes[..(size - 1)]).map_err(|err| {
|
||||||
Error::SerializationError(format!(
|
Error::SerializationError(format!(
|
||||||
"Failed to write serialized Long to output: {err}"
|
"Failed to write serialized Long to output: {err}"
|
||||||
))
|
))
|
||||||
|
|
@ -172,7 +172,7 @@ impl Serializable for EncodedValue {
|
||||||
}
|
}
|
||||||
Self::Float(val) => {
|
Self::Float(val) => {
|
||||||
let size = self.size();
|
let size = self.size();
|
||||||
let bytes = val.to_be_bytes();
|
let bytes = val.to_le_bytes(); // TODO: check LE/BE
|
||||||
output
|
output
|
||||||
.write_all(&[((size as u8 - 2) << 5) | VALUE_FLOAT.0])
|
.write_all(&[((size as u8 - 2) << 5) | VALUE_FLOAT.0])
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
|
|
@ -189,7 +189,7 @@ impl Serializable for EncodedValue {
|
||||||
}
|
}
|
||||||
Self::Double(val) => {
|
Self::Double(val) => {
|
||||||
let size = self.size();
|
let size = self.size();
|
||||||
let bytes = val.to_be_bytes();
|
let bytes = val.to_le_bytes(); // TODO: check LE/BE
|
||||||
output
|
output
|
||||||
.write_all(&[((size as u8 - 2) << 5) | VALUE_DOUBLE.0])
|
.write_all(&[((size as u8 - 2) << 5) | VALUE_DOUBLE.0])
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
|
|
@ -282,20 +282,19 @@ impl Serializable for EncodedValue {
|
||||||
} else {
|
} else {
|
||||||
let mut buffer = [0x00u8; 2];
|
let mut buffer = [0x00u8; 2];
|
||||||
let size = (arg + 1) as usize;
|
let size = (arg + 1) as usize;
|
||||||
let first_byte = 2 - size;
|
input.read_exact(&mut buffer[..size]).map_err(|_| {
|
||||||
input.read_exact(&mut buffer[first_byte..]).map_err(|_| {
|
|
||||||
Error::InputTooSmall(
|
Error::InputTooSmall(
|
||||||
"Failed to read all bytes for the EncodedValue (Short) from the input"
|
"Failed to read all bytes for the EncodedValue (Short) from the input"
|
||||||
.into(),
|
.into(),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
// Sign extention
|
// Sign extention
|
||||||
if (buffer[first_byte] & 0b1000_0000) != 0 {
|
if (buffer[size - 1] & 0b1000_0000) != 0 {
|
||||||
for b in buffer.iter_mut().take(first_byte - 1) {
|
for b in buffer.iter_mut().take(size) {
|
||||||
*b = 0xff;
|
*b = 0xff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Self::Short(i16::from_be_bytes(buffer)))
|
Ok(Self::Short(i16::from_le_bytes(buffer)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VALUE_CHAR => {
|
VALUE_CHAR => {
|
||||||
|
|
@ -306,14 +305,13 @@ impl Serializable for EncodedValue {
|
||||||
} else {
|
} else {
|
||||||
let mut buffer = [0x00u8; 2];
|
let mut buffer = [0x00u8; 2];
|
||||||
let size = (arg + 1) as usize;
|
let size = (arg + 1) as usize;
|
||||||
let first_byte = 2 - size;
|
input.read_exact(&mut buffer[..size]).map_err(|_| {
|
||||||
input.read_exact(&mut buffer[first_byte..]).map_err(|_| {
|
|
||||||
Error::InputTooSmall(
|
Error::InputTooSmall(
|
||||||
"Failed to read all bytes for the EncodedValue (Char) from the input"
|
"Failed to read all bytes for the EncodedValue (Char) from the input"
|
||||||
.into(),
|
.into(),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
Ok(Self::Char(u16::from_be_bytes(buffer)))
|
Ok(Self::Char(u16::from_le_bytes(buffer)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VALUE_INT => {
|
VALUE_INT => {
|
||||||
|
|
@ -324,20 +322,19 @@ impl Serializable for EncodedValue {
|
||||||
} else {
|
} else {
|
||||||
let mut buffer = [0x00u8; 4];
|
let mut buffer = [0x00u8; 4];
|
||||||
let size = (arg + 1) as usize;
|
let size = (arg + 1) as usize;
|
||||||
let first_byte = 4 - size;
|
input.read_exact(&mut buffer[..size]).map_err(|_| {
|
||||||
input.read_exact(&mut buffer[first_byte..]).map_err(|_| {
|
|
||||||
Error::InputTooSmall(
|
Error::InputTooSmall(
|
||||||
"Failed to read all bytes for the EncodedValue (Int) from the input"
|
"Failed to read all bytes for the EncodedValue (Int) from the input"
|
||||||
.into(),
|
.into(),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
// Sign extention
|
// Sign extention
|
||||||
if (buffer[first_byte] & 0b1000_0000) != 0 {
|
if (buffer[size - 1] & 0b1000_0000) != 0 {
|
||||||
for b in buffer.iter_mut().take(first_byte - 1) {
|
for b in buffer.iter_mut().take(size) {
|
||||||
*b = 0xff;
|
*b = 0xff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Self::Int(i32::from_be_bytes(buffer)))
|
Ok(Self::Int(i32::from_le_bytes(buffer)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VALUE_LONG => {
|
VALUE_LONG => {
|
||||||
|
|
@ -348,20 +345,19 @@ impl Serializable for EncodedValue {
|
||||||
} else {
|
} else {
|
||||||
let mut buffer = [0x00u8; 8];
|
let mut buffer = [0x00u8; 8];
|
||||||
let size = (arg + 1) as usize;
|
let size = (arg + 1) as usize;
|
||||||
let first_byte = 8 - size;
|
input.read_exact(&mut buffer[..size]).map_err(|_| {
|
||||||
input.read_exact(&mut buffer[first_byte..]).map_err(|_| {
|
|
||||||
Error::InputTooSmall(
|
Error::InputTooSmall(
|
||||||
"Failed to read all bytes for the EncodedValue (Long) from the input"
|
"Failed to read all bytes for the EncodedValue (Long) from the input"
|
||||||
.into(),
|
.into(),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
// Sign extention
|
// Sign extention
|
||||||
if (buffer[first_byte] & 0b1000_0000) != 0 {
|
if (buffer[size - 1] & 0b1000_0000) != 0 {
|
||||||
for b in buffer.iter_mut().take(first_byte - 1) {
|
for b in buffer.iter_mut().take(size) {
|
||||||
*b = 0xff;
|
*b = 0xff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Self::Long(i64::from_be_bytes(buffer)))
|
Ok(Self::Long(i64::from_le_bytes(buffer)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VALUE_FLOAT => {
|
VALUE_FLOAT => {
|
||||||
|
|
@ -378,7 +374,7 @@ impl Serializable for EncodedValue {
|
||||||
.into(),
|
.into(),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
Ok(Self::Float(f32::from_be_bytes(buffer)))
|
Ok(Self::Float(f32::from_le_bytes(buffer)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VALUE_DOUBLE => {
|
VALUE_DOUBLE => {
|
||||||
|
|
@ -395,7 +391,7 @@ impl Serializable for EncodedValue {
|
||||||
.into(),
|
.into(),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
Ok(Self::Double(f64::from_be_bytes(buffer)))
|
Ok(Self::Double(f64::from_le_bytes(buffer)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VALUE_METHOD_TYPE => {
|
VALUE_METHOD_TYPE => {
|
||||||
|
|
@ -406,14 +402,13 @@ impl Serializable for EncodedValue {
|
||||||
} else {
|
} else {
|
||||||
let mut buffer = [0x00u8; 4];
|
let mut buffer = [0x00u8; 4];
|
||||||
let size = (arg + 1) as usize;
|
let size = (arg + 1) as usize;
|
||||||
let first_byte = 4 - size;
|
input.read_exact(&mut buffer[..size]).map_err(|_| {
|
||||||
input.read_exact(&mut buffer[first_byte..]).map_err(|_| {
|
|
||||||
Error::InputTooSmall(
|
Error::InputTooSmall(
|
||||||
"Failed to read all bytes for the EncodedValue (MethodType) from the input"
|
"Failed to read all bytes for the EncodedValue (MethodType) from the input"
|
||||||
.into(),
|
.into(),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
Ok(Self::MethodType(u32::from_be_bytes(buffer)))
|
Ok(Self::MethodType(u32::from_le_bytes(buffer)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VALUE_METHOD_HANDLE => {
|
VALUE_METHOD_HANDLE => {
|
||||||
|
|
@ -424,14 +419,13 @@ impl Serializable for EncodedValue {
|
||||||
} else {
|
} else {
|
||||||
let mut buffer = [0x00u8; 4];
|
let mut buffer = [0x00u8; 4];
|
||||||
let size = (arg + 1) as usize;
|
let size = (arg + 1) as usize;
|
||||||
let first_byte = 4 - size;
|
input.read_exact(&mut buffer[..size]).map_err(|_| {
|
||||||
input.read_exact(&mut buffer[first_byte..]).map_err(|_| {
|
|
||||||
Error::InputTooSmall(
|
Error::InputTooSmall(
|
||||||
"Failed to read all bytes for the EncodedValue (MethodHandle) from the input"
|
"Failed to read all bytes for the EncodedValue (MethodHandle) from the input"
|
||||||
.into(),
|
.into(),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
Ok(Self::MethodHandle(u32::from_be_bytes(buffer)))
|
Ok(Self::MethodHandle(u32::from_le_bytes(buffer)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VALUE_STRING => {
|
VALUE_STRING => {
|
||||||
|
|
@ -442,14 +436,13 @@ impl Serializable for EncodedValue {
|
||||||
} else {
|
} else {
|
||||||
let mut buffer = [0x00u8; 4];
|
let mut buffer = [0x00u8; 4];
|
||||||
let size = (arg + 1) as usize;
|
let size = (arg + 1) as usize;
|
||||||
let first_byte = 4 - size;
|
input.read_exact(&mut buffer[..size]).map_err(|_| {
|
||||||
input.read_exact(&mut buffer[first_byte..]).map_err(|_| {
|
|
||||||
Error::InputTooSmall(
|
Error::InputTooSmall(
|
||||||
"Failed to read all bytes for the EncodedValue (String) from the input"
|
"Failed to read all bytes for the EncodedValue (String) from the input"
|
||||||
.into(),
|
.into(),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
Ok(Self::String(u32::from_be_bytes(buffer)))
|
Ok(Self::String(u32::from_le_bytes(buffer)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VALUE_TYPE => {
|
VALUE_TYPE => {
|
||||||
|
|
@ -460,14 +453,13 @@ impl Serializable for EncodedValue {
|
||||||
} else {
|
} else {
|
||||||
let mut buffer = [0x00u8; 4];
|
let mut buffer = [0x00u8; 4];
|
||||||
let size = (arg + 1) as usize;
|
let size = (arg + 1) as usize;
|
||||||
let first_byte = 4 - size;
|
input.read_exact(&mut buffer[..size]).map_err(|_| {
|
||||||
input.read_exact(&mut buffer[first_byte..]).map_err(|_| {
|
|
||||||
Error::InputTooSmall(
|
Error::InputTooSmall(
|
||||||
"Failed to read all bytes for the EncodedValue (Type) from the input"
|
"Failed to read all bytes for the EncodedValue (Type) from the input"
|
||||||
.into(),
|
.into(),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
Ok(Self::Type(u32::from_be_bytes(buffer)))
|
Ok(Self::Type(u32::from_le_bytes(buffer)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VALUE_FIELD => {
|
VALUE_FIELD => {
|
||||||
|
|
@ -478,14 +470,13 @@ impl Serializable for EncodedValue {
|
||||||
} else {
|
} else {
|
||||||
let mut buffer = [0x00u8; 4];
|
let mut buffer = [0x00u8; 4];
|
||||||
let size = (arg + 1) as usize;
|
let size = (arg + 1) as usize;
|
||||||
let first_byte = 4 - size;
|
input.read_exact(&mut buffer[..size]).map_err(|_| {
|
||||||
input.read_exact(&mut buffer[first_byte..]).map_err(|_| {
|
|
||||||
Error::InputTooSmall(
|
Error::InputTooSmall(
|
||||||
"Failed to read all bytes for the EncodedValue (Field) from the input"
|
"Failed to read all bytes for the EncodedValue (Field) from the input"
|
||||||
.into(),
|
.into(),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
Ok(Self::Field(u32::from_be_bytes(buffer)))
|
Ok(Self::Field(u32::from_le_bytes(buffer)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VALUE_METHOD => {
|
VALUE_METHOD => {
|
||||||
|
|
@ -496,14 +487,13 @@ impl Serializable for EncodedValue {
|
||||||
} else {
|
} else {
|
||||||
let mut buffer = [0x00u8; 4];
|
let mut buffer = [0x00u8; 4];
|
||||||
let size = (arg + 1) as usize;
|
let size = (arg + 1) as usize;
|
||||||
let first_byte = 4 - size;
|
input.read_exact(&mut buffer[..size]).map_err(|_| {
|
||||||
input.read_exact(&mut buffer[first_byte..]).map_err(|_| {
|
|
||||||
Error::InputTooSmall(
|
Error::InputTooSmall(
|
||||||
"Failed to read all bytes for the EncodedValue (Method) from the input"
|
"Failed to read all bytes for the EncodedValue (Method) from the input"
|
||||||
.into(),
|
.into(),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
Ok(Self::Method(u32::from_be_bytes(buffer)))
|
Ok(Self::Method(u32::from_le_bytes(buffer)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VALUE_ENUM => {
|
VALUE_ENUM => {
|
||||||
|
|
@ -514,14 +504,13 @@ impl Serializable for EncodedValue {
|
||||||
} else {
|
} else {
|
||||||
let mut buffer = [0x00u8; 4];
|
let mut buffer = [0x00u8; 4];
|
||||||
let size = (arg + 1) as usize;
|
let size = (arg + 1) as usize;
|
||||||
let first_byte = 4 - size;
|
input.read_exact(&mut buffer[..size]).map_err(|_| {
|
||||||
input.read_exact(&mut buffer[first_byte..]).map_err(|_| {
|
|
||||||
Error::InputTooSmall(
|
Error::InputTooSmall(
|
||||||
"Failed to read all bytes for the EncodedValue (Enum) from the input"
|
"Failed to read all bytes for the EncodedValue (Enum) from the input"
|
||||||
.into(),
|
.into(),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
Ok(Self::Enum(u32::from_be_bytes(buffer)))
|
Ok(Self::Enum(u32::from_le_bytes(buffer)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VALUE_ARRAY => {
|
VALUE_ARRAY => {
|
||||||
|
|
@ -643,8 +632,8 @@ impl Serializable for Idx {
|
||||||
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
|
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
|
||||||
let Idx(idx, ValueType(vt)) = self;
|
let Idx(idx, ValueType(vt)) = self;
|
||||||
let size = self.size() - 2;
|
let size = self.size() - 2;
|
||||||
let bytes: [u8; 4] = idx.to_be_bytes();
|
let bytes: [u8; 4] = idx.to_le_bytes();
|
||||||
let vec = &bytes[(4 - size + 1)..];
|
let vec = &bytes[..(size + 1)];
|
||||||
output
|
output
|
||||||
.write_all(&[((size as u8) << 5) | vt])
|
.write_all(&[((size as u8) << 5) | vt])
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue