From 4cff697c58856c11832f356f6a94e4ef6896d257 Mon Sep 17 00:00:00 2001 From: Woshiluo Luo Date: Thu, 20 Feb 2025 23:35:30 +0800 Subject: [PATCH 01/10] feat: init serialize support Signed-off-by: Woshiluo Luo --- src/lib.rs | 1 + src/ser.rs | 589 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 590 insertions(+) create mode 100644 src/ser.rs diff --git a/src/lib.rs b/src/lib.rs index c5333c3..42eefee 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,6 +20,7 @@ extern crate alloc; pub mod de; pub mod error; +pub mod ser; pub mod utils; mod common; diff --git a/src/ser.rs b/src/ser.rs new file mode 100644 index 0000000..00d00b9 --- /dev/null +++ b/src/ser.rs @@ -0,0 +1,589 @@ +use crate::common::*; + +pub struct Pointer<'de> { + pub offset: usize, + pub data: &'de mut [u8], +} + +pub struct StringBlock<'de> { + pub end: usize, + pub data: &'de mut [u8], +} + +impl<'de> StringBlock<'de> { + pub fn new(dst: &'de mut [u8]) -> StringBlock<'de> { + StringBlock { data: dst, end: 0 } + } + + /// Will panic when len > end + /// TODO: show as error + /// Return (Result String, End Offset) + pub fn get_str_by_offset<'a>(&'a self, offset: usize) -> (&'a str, usize) { + if offset > self.end { + panic!("invalid read"); + } + let current_slice = &self.data[offset..]; + let pos = current_slice + .iter() + .position(|&x| x == b'\0') + .unwrap_or(self.data.len()); + let (a, _) = current_slice.split_at(pos + 1); + let result = unsafe { core::str::from_utf8_unchecked(&a[..a.len() - 1]) }; + (result, pos + offset + 1) + } + + fn insert_u8(&mut self, data: u8) { + self.data[self.end] = data; + self.end += 1; + } + /// Return the start offset of inserted string. + pub fn insert_str(&mut self, name: &str) -> usize { + let result = self.end; + name.bytes().for_each(|x| { + self.insert_u8(x); + }); + self.insert_u8(0); + result + } + + pub fn find_or_insert(&mut self, name: &str) -> usize { + let mut current_pos = 0; + while current_pos < self.end { + let (result, new_pos) = self.get_str_by_offset(current_pos); + if result == name { + return current_pos; + } + current_pos = new_pos; + } + + self.insert_str(name) + } +} + +impl<'de> Pointer<'de> { + pub fn new(dst: &'de mut [u8]) -> Pointer<'de> { + Pointer { + offset: 0, + data: dst, + } + } + + pub fn write_to_offset_u32(&mut self, offset: usize, value: u32) { + self.data[offset..offset + 4].copy_from_slice(&u32::to_be_bytes(value)); + } + + pub fn step_by_prop(&mut self) -> usize { + self.step_by_u32(FDT_PROP); + let offset = self.offset; + self.step_by_u32(FDT_NOP); // When create prop header, we do not know how long of the prop value. + self.step_by_u32(FDT_NOP); // We can not assume this is a prop, so nop for default. + offset + } + + pub fn step_by_len(&mut self, len: usize) { + self.offset += len + } + + pub fn step_by_u32(&mut self, value: u32) { + self.data[self.offset..self.offset + 4].copy_from_slice(&u32::to_be_bytes(value)); + self.step_by_len(4); + } + + pub fn step_by_u8(&mut self, value: u8) { + self.data[self.offset] = value; + self.step_by_len(1); + } + + pub fn step_align(&mut self) { + while self.offset % 4 != 0 { + self.data[self.offset] = 0; + self.offset += 1; + } + } + + pub fn step_by_name(&mut self, name: &str) { + name.bytes().for_each(|x| { + self.step_by_u8(x); + }); + self.step_by_u8(0); + self.step_align(); + } +} + +#[derive(Clone, Copy)] +pub enum ValueType { + Node, + Prop, +} + +pub struct Serializer<'de> { + dst: &'de mut Pointer<'de>, + string_block: &'de mut StringBlock<'de>, + value_type: ValueType, +} + +impl<'de> Serializer<'de> { + pub fn new(dst: &'de mut Pointer<'de>, cache: &'de mut StringBlock<'de>) -> Serializer<'de> { + Serializer { + dst, + string_block: cache, + value_type: ValueType::Node, + } + } +} + +impl<'a, 'de> serde::ser::SerializeMap for &'a mut Serializer<'de> { + type Ok = (); + type Error = Error; + + fn serialize_key(&mut self, _input: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize + ?Sized, + { + todo!("map_key"); + } + + fn serialize_value(&mut self, _value: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize + ?Sized, + { + todo!("map_value"); + } + + fn end(self) -> Result { + todo!("map_end"); + } +} + +impl<'a, 'de> serde::ser::SerializeStruct for &'a mut Serializer<'de> { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize + ?Sized, + { + let prop_header_offset = self.dst.step_by_prop(); + let old_value_type = self.value_type; + value.serialize(&mut **self)?; + // We now know how long the prop value. + // TODO: make we have some better way than put nop, like move this block ahead. + if let ValueType::Node = self.value_type { + self.dst + .write_to_offset_u32(prop_header_offset - 4, FDT_NOP); + } else { + self.dst.write_to_offset_u32( + prop_header_offset, + (self.dst.offset - prop_header_offset - 8) as u32, + ); + self.dst.write_to_offset_u32( + prop_header_offset + 4, + self.string_block.find_or_insert(key) as u32, + ); + } + self.value_type = old_value_type; + self.dst.step_align(); + Ok(()) + } + + fn end(self) -> Result { + self.dst.step_by_u32(FDT_END_NODE); + Ok(()) + } +} + +impl<'a, 'de> serde::ser::SerializeStructVariant for &'a mut Serializer<'de> { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, _key: &'static str, _value: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize + ?Sized, + { + todo!("struct_field"); + } + + fn end(self) -> Result { + todo!("struct_end"); + } +} + +impl<'a, 'de> serde::ser::SerializeSeq for &'a mut Serializer<'de> { + type Ok = (); + type Error = Error; + // TODO: make sure there are no node seq serialize over this function. + fn serialize_element(&mut self, value: &T) -> Result<(), Error> + where + T: ?Sized + serde::ser::Serialize, + { + value.serialize(&mut **self) + } + + // Close the sequence. + fn end(self) -> Result<(), Error> { + Ok(()) + } +} + +impl<'a, 'de> serde::ser::SerializeTuple for &'a mut Serializer<'de> { + type Ok = (); + type Error = Error; + + fn serialize_element(&mut self, value: &T) -> Result<(), Error> + where + T: ?Sized + serde::ser::Serialize, + { + value.serialize(&mut **self) + } + + // Close the sequence. + fn end(self) -> Result<(), Error> { + Ok(()) + } +} + +impl<'a, 'de> serde::ser::SerializeTupleVariant for &'a mut Serializer<'de> { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, _value: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize + ?Sized, + { + todo!("tuple_variant_field"); + } + + fn end(self) -> Result<(), Error> { + todo!("tuple_variant_end"); + } +} + +impl<'a, 'de> serde::ser::SerializeTupleStruct for &'a mut Serializer<'de> { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, _value: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize + ?Sized, + { + todo!("tuple_struct_field"); + } + + fn end(self) -> Result<(), Error> { + todo!("tuple_struct_end"); + } +} + +#[derive(Debug)] +pub enum Error { + Unknown, +} + +impl core::fmt::Display for Error { + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "{:?}", self) + } +} + +impl core::error::Error for Error {} + +impl serde::ser::Error for Error { + fn custom(_msg: T) -> Self + where + T: std::fmt::Display, + { + Self::Unknown + } +} + +impl<'a, 'de> serde::ser::Serializer for &'a mut Serializer<'de> { + type Ok = (); + type Error = Error; + type SerializeSeq = Self; + type SerializeMap = Self; + type SerializeStruct = Self; + type SerializeTuple = Self; + type SerializeTupleStruct = Self; + type SerializeTupleVariant = Self; + type SerializeStructVariant = Self; + + fn serialize_bool(self, _v: bool) -> Result { + todo!("bool"); + } + + fn serialize_i8(self, _v: i8) -> Result { + todo!("i8"); + } + + fn serialize_i16(self, _v: i16) -> Result { + todo!("i16"); + } + + fn serialize_i32(self, _v: i32) -> Result { + todo!("i32"); + } + + fn serialize_i64(self, _v: i64) -> Result { + todo!("i64"); + } + + fn serialize_u8(self, _v: u8) -> Result { + todo!("u8"); + } + + fn serialize_u16(self, _v: u16) -> Result { + todo!("u16"); + } + + fn serialize_u32(self, v: u32) -> Result { + self.value_type = ValueType::Prop; + self.dst.step_by_u32(v); + Ok(()) + } + + fn serialize_u64(self, _v: u64) -> Result { + todo!("u64"); + } + + fn serialize_f32(self, _v: f32) -> Result { + todo!("f32"); + } + + fn serialize_f64(self, _v: f64) -> Result { + todo!("f64"); + } + + fn serialize_char(self, _v: char) -> Result { + todo!("char"); + } + + fn serialize_str(self, v: &str) -> Result { + self.value_type = ValueType::Prop; + v.bytes().for_each(|x| { + self.dst.step_by_u8(x); + }); + self.dst.step_by_u8(0); + Ok(()) + } + + fn serialize_bytes(self, _v: &[u8]) -> Result { + todo!("bytes"); + } + + fn serialize_none(self) -> Result { + todo!("none"); + } + + fn serialize_some(self, _v: &T) -> Result + where + T: serde::ser::Serialize + ?Sized, + { + todo!("some"); + } + + fn serialize_unit(self) -> Result { + todo!("unit"); + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result { + todo!("unit struct"); + } + + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + ) -> Result { + todo!("unit struct variant"); + } + + fn serialize_newtype_struct( + self, + _name: &'static str, + _v: &T, + ) -> Result + where + T: serde::ser::Serialize + ?Sized, + { + todo!("newtype struct"); + } + + fn serialize_newtype_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _value: &T, + ) -> Result + where + T: serde::ser::Serialize + ?Sized, + { + todo!("newtype struct variant"); + } + + fn serialize_seq(self, _len: Option) -> Result { + self.value_type = ValueType::Prop; + Ok(self) + } + + fn serialize_tuple(self, len: usize) -> Result { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result { + todo!("tuple struct"); + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + todo!("tuple variant"); + } + + fn serialize_map(self, _len: Option) -> Result { + todo!("map"); + } + + fn serialize_struct( + self, + name: &'static str, + _len: usize, + ) -> Result { + self.dst.step_by_u32(FDT_BEGIN_NODE); + self.dst.step_by_name(name); + self.value_type = ValueType::Node; + Ok(self) + } + + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + todo!("struct variant"); + } +} + +#[cfg(test)] +mod tests { + use crate::common::*; + use serde::ser::Serialize; + use serde_derive::Serialize; + const MAX_SIZE: usize = 128; + #[test] + fn base_ser_test() { + #[derive(Serialize)] + struct Base { + pub hello: u32, + } + let mut buf1 = [0u8; MAX_SIZE]; + let mut buf2 = [0u8; MAX_SIZE]; + + { + let mut dst = crate::ser::Pointer::new(&mut buf1); + let mut block = crate::ser::StringBlock::new(&mut buf2); + let mut ser = crate::ser::Serializer::new(&mut dst, &mut block); + let base = Base { hello: 0xdeedbeef }; + base.serialize(&mut ser).unwrap(); + // TODO: write end, this should be write by other thing. + ser.dst.step_by_u32(FDT_END); + } + // TODO: check buf1 buf2 + } + #[test] + fn rev_ser_test() { + #[derive(Serialize)] + struct Base { + pub hello: u32, + pub base1: Base1, + } + #[derive(Serialize)] + struct Base1 { + pub hello: u32, + } + let mut buf1 = [0u8; MAX_SIZE]; + let mut buf2 = [0u8; MAX_SIZE]; + + { + let mut dst = crate::ser::Pointer::new(&mut buf1); + let mut block = crate::ser::StringBlock::new(&mut buf2); + let mut ser = crate::ser::Serializer::new(&mut dst, &mut block); + let base = Base { + hello: 0xdeedbeef, + base1: Base1 { hello: 0x10000001 }, + }; + base.serialize(&mut ser).unwrap(); + ser.dst.step_by_u32(FDT_END); + } + // TODO: check buf1 buf2 + // println!("{:x?} {:x?}", buf1, buf2); + // assert!(false); + } + #[test] + fn rev_str_ser_test() { + #[derive(Serialize)] + struct Base { + pub hello: u32, + pub base1: Base1, + } + #[derive(Serialize)] + struct Base1 { + pub hello: &'static str, + } + let mut buf1 = [0u8; MAX_SIZE]; + let mut buf2 = [0u8; MAX_SIZE]; + + { + let mut dst = crate::ser::Pointer::new(&mut buf1); + let mut block = crate::ser::StringBlock::new(&mut buf2); + let mut ser = crate::ser::Serializer::new(&mut dst, &mut block); + let base = Base { + hello: 0xdeedbeef, + base1: Base1 { + hello: "Hello, World!", + }, + }; + base.serialize(&mut ser).unwrap(); + ser.dst.step_by_u32(FDT_END); + } + // TODO: check buf1 buf2 + // println!("{:x?} {:x?}", buf1, buf2); + // assert!(false); + } + #[test] + fn seq_str_ser_test() { + #[derive(Serialize)] + struct Base { + pub hello: u32, + pub base1: [&'static str; 3], + } + let mut buf1 = [0u8; MAX_SIZE]; + let mut buf2 = [0u8; MAX_SIZE]; + + { + let mut dst = crate::ser::Pointer::new(&mut buf1); + let mut block = crate::ser::StringBlock::new(&mut buf2); + let mut ser = crate::ser::Serializer::new(&mut dst, &mut block); + let base = Base { + hello: 0xdeedbeef, + base1: ["Hello", "World!", "Again"], + }; + base.serialize(&mut ser).unwrap(); + ser.dst.step_by_u32(FDT_END); + } + // TODO: check buf1 buf2 + println!("{:x?} {:x?}", buf1, buf2); + assert!(false); + } +} From 613a4cdbb442c1bd6eedb375aafc3d5356cea060 Mon Sep 17 00:00:00 2001 From: Woshiluo Luo Date: Sat, 22 Feb 2025 12:52:15 +0800 Subject: [PATCH 02/10] feat: patch(replace) support Signed-off-by: Woshiluo Luo --- .gitignore | 1 + Cargo.toml | 3 +- src/{ser.rs => ser/mod.rs} | 322 +++++++++++++++++++++---------------- src/ser/patch.rs | 81 ++++++++++ src/ser/pointer.rs | 56 +++++++ src/ser/string_block.rs | 54 +++++++ 6 files changed, 379 insertions(+), 138 deletions(-) rename src/{ser.rs => ser/mod.rs} (69%) create mode 100644 src/ser/patch.rs create mode 100644 src/ser/pointer.rs create mode 100644 src/ser/string_block.rs diff --git a/.gitignore b/.gitignore index b5f7d1d..c994933 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ Cargo.lock # Visual Studio Code configuration files .vscode/ +*.dts diff --git a/Cargo.toml b/Cargo.toml index d772b15..aa63f25 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,12 +9,13 @@ description = "A Device Tree blob serialization file format" readme = "README.md" keywords = ["serde", "serialization"] categories = ["no-std", "encoding"] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] serde = { version = "1.0", default-features = false } +erased-serde = "0.4" [dev-dependencies] serde_derive = "1.0" diff --git a/src/ser.rs b/src/ser/mod.rs similarity index 69% rename from src/ser.rs rename to src/ser/mod.rs index 00d00b9..6d1dc20 100644 --- a/src/ser.rs +++ b/src/ser/mod.rs @@ -1,133 +1,60 @@ +pub mod patch; +pub mod pointer; +pub mod string_block; + use crate::common::*; +use patch::PatchList; +use pointer::Pointer; +use string_block::StringBlock; -pub struct Pointer<'de> { - pub offset: usize, - pub data: &'de mut [u8], +#[derive(Clone, Copy)] +pub enum ValueType { + Node, + Prop, } -pub struct StringBlock<'de> { - pub end: usize, - pub data: &'de mut [u8], +#[derive(Debug)] +pub enum Error { + Unknown, } -impl<'de> StringBlock<'de> { - pub fn new(dst: &'de mut [u8]) -> StringBlock<'de> { - StringBlock { data: dst, end: 0 } - } - - /// Will panic when len > end - /// TODO: show as error - /// Return (Result String, End Offset) - pub fn get_str_by_offset<'a>(&'a self, offset: usize) -> (&'a str, usize) { - if offset > self.end { - panic!("invalid read"); - } - let current_slice = &self.data[offset..]; - let pos = current_slice - .iter() - .position(|&x| x == b'\0') - .unwrap_or(self.data.len()); - let (a, _) = current_slice.split_at(pos + 1); - let result = unsafe { core::str::from_utf8_unchecked(&a[..a.len() - 1]) }; - (result, pos + offset + 1) - } - - fn insert_u8(&mut self, data: u8) { - self.data[self.end] = data; - self.end += 1; - } - /// Return the start offset of inserted string. - pub fn insert_str(&mut self, name: &str) -> usize { - let result = self.end; - name.bytes().for_each(|x| { - self.insert_u8(x); - }); - self.insert_u8(0); - result - } - - pub fn find_or_insert(&mut self, name: &str) -> usize { - let mut current_pos = 0; - while current_pos < self.end { - let (result, new_pos) = self.get_str_by_offset(current_pos); - if result == name { - return current_pos; - } - current_pos = new_pos; - } - - self.insert_str(name) +impl core::fmt::Display for Error { + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "{:?}", self) } } -impl<'de> Pointer<'de> { - pub fn new(dst: &'de mut [u8]) -> Pointer<'de> { - Pointer { - offset: 0, - data: dst, - } - } - - pub fn write_to_offset_u32(&mut self, offset: usize, value: u32) { - self.data[offset..offset + 4].copy_from_slice(&u32::to_be_bytes(value)); - } - - pub fn step_by_prop(&mut self) -> usize { - self.step_by_u32(FDT_PROP); - let offset = self.offset; - self.step_by_u32(FDT_NOP); // When create prop header, we do not know how long of the prop value. - self.step_by_u32(FDT_NOP); // We can not assume this is a prop, so nop for default. - offset - } - - pub fn step_by_len(&mut self, len: usize) { - self.offset += len - } - - pub fn step_by_u32(&mut self, value: u32) { - self.data[self.offset..self.offset + 4].copy_from_slice(&u32::to_be_bytes(value)); - self.step_by_len(4); - } - - pub fn step_by_u8(&mut self, value: u8) { - self.data[self.offset] = value; - self.step_by_len(1); - } - - pub fn step_align(&mut self) { - while self.offset % 4 != 0 { - self.data[self.offset] = 0; - self.offset += 1; - } - } +impl core::error::Error for Error {} - pub fn step_by_name(&mut self, name: &str) { - name.bytes().for_each(|x| { - self.step_by_u8(x); - }); - self.step_by_u8(0); - self.step_align(); +impl serde::ser::Error for Error { + fn custom(_msg: T) -> Self + where + T: std::fmt::Display, + { + Self::Unknown } } -#[derive(Clone, Copy)] -pub enum ValueType { - Node, - Prop, -} - pub struct Serializer<'de> { dst: &'de mut Pointer<'de>, string_block: &'de mut StringBlock<'de>, value_type: ValueType, + current_dep: usize, + patch_list: &'de mut PatchList<'de>, } impl<'de> Serializer<'de> { - pub fn new(dst: &'de mut Pointer<'de>, cache: &'de mut StringBlock<'de>) -> Serializer<'de> { + pub fn new( + dst: &'de mut Pointer<'de>, + cache: &'de mut StringBlock<'de>, + patch_list: &'de mut PatchList<'de>, + ) -> Serializer<'de> { Serializer { dst, string_block: cache, + current_dep: 0, value_type: ValueType::Node, + patch_list, } } } @@ -165,7 +92,18 @@ impl<'a, 'de> serde::ser::SerializeStruct for &'a mut Serializer<'de> { { let prop_header_offset = self.dst.step_by_prop(); let old_value_type = self.value_type; - value.serialize(&mut **self)?; + self.current_dep += 1; + let matched_patch = self.patch_list.step_forward(key, self.current_dep); + + match matched_patch { + Some(data) => { + data.serialize(&mut **self); + } + None => { + value.serialize(&mut **self)?; + } + } + // We now know how long the prop value. // TODO: make we have some better way than put nop, like move this block ahead. if let ValueType::Node = self.value_type { @@ -181,12 +119,17 @@ impl<'a, 'de> serde::ser::SerializeStruct for &'a mut Serializer<'de> { self.string_block.find_or_insert(key) as u32, ); } + self.value_type = old_value_type; self.dst.step_align(); + self.patch_list.step_back(self.current_dep); + self.current_dep -= 1; + Ok(()) } fn end(self) -> Result { + // TODO: patch type add self.dst.step_by_u32(FDT_END_NODE); Ok(()) } @@ -274,28 +217,6 @@ impl<'a, 'de> serde::ser::SerializeTupleStruct for &'a mut Serializer<'de> { } } -#[derive(Debug)] -pub enum Error { - Unknown, -} - -impl core::fmt::Display for Error { - fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "{:?}", self) - } -} - -impl core::error::Error for Error {} - -impl serde::ser::Error for Error { - fn custom(_msg: T) -> Self - where - T: std::fmt::Display, - { - Self::Unknown - } -} - impl<'a, 'de> serde::ser::Serializer for &'a mut Serializer<'de> { type Ok = (); type Error = Error; @@ -366,8 +287,10 @@ impl<'a, 'de> serde::ser::Serializer for &'a mut Serializer<'de> { Ok(()) } - fn serialize_bytes(self, _v: &[u8]) -> Result { - todo!("bytes"); + fn serialize_bytes(self, v: &[u8]) -> Result { + self.value_type = ValueType::Prop; + v.iter().for_each(|x| self.dst.step_by_u8(*x)); + Ok(()) } fn serialize_none(self) -> Result { @@ -459,7 +382,12 @@ impl<'a, 'de> serde::ser::Serializer for &'a mut Serializer<'de> { _len: usize, ) -> Result { self.dst.step_by_u32(FDT_BEGIN_NODE); - self.dst.step_by_name(name); + if self.current_dep == 0 { + // The name of root node should be empty. + self.dst.step_by_u32(0); + } else { + self.dst.step_by_name(name); + } self.value_type = ValueType::Node; Ok(self) } @@ -480,7 +408,7 @@ mod tests { use crate::common::*; use serde::ser::Serialize; use serde_derive::Serialize; - const MAX_SIZE: usize = 128; + const MAX_SIZE: usize = 128 + 64; #[test] fn base_ser_test() { #[derive(Serialize)] @@ -493,7 +421,8 @@ mod tests { { let mut dst = crate::ser::Pointer::new(&mut buf1); let mut block = crate::ser::StringBlock::new(&mut buf2); - let mut ser = crate::ser::Serializer::new(&mut dst, &mut block); + let mut patch_list = crate::ser::PatchList::new(&mut []); + let mut ser = crate::ser::Serializer::new(&mut dst, &mut block, &mut patch_list); let base = Base { hello: 0xdeedbeef }; base.serialize(&mut ser).unwrap(); // TODO: write end, this should be write by other thing. @@ -518,7 +447,8 @@ mod tests { { let mut dst = crate::ser::Pointer::new(&mut buf1); let mut block = crate::ser::StringBlock::new(&mut buf2); - let mut ser = crate::ser::Serializer::new(&mut dst, &mut block); + let mut patch_list = crate::ser::PatchList::new(&mut []); + let mut ser = crate::ser::Serializer::new(&mut dst, &mut block, &mut patch_list); let base = Base { hello: 0xdeedbeef, base1: Base1 { hello: 0x10000001 }, @@ -547,7 +477,8 @@ mod tests { { let mut dst = crate::ser::Pointer::new(&mut buf1); let mut block = crate::ser::StringBlock::new(&mut buf2); - let mut ser = crate::ser::Serializer::new(&mut dst, &mut block); + let mut patch_list = crate::ser::PatchList::new(&mut []); + let mut ser = crate::ser::Serializer::new(&mut dst, &mut block, &mut patch_list); let base = Base { hello: 0xdeedbeef, base1: Base1 { @@ -574,7 +505,8 @@ mod tests { { let mut dst = crate::ser::Pointer::new(&mut buf1); let mut block = crate::ser::StringBlock::new(&mut buf2); - let mut ser = crate::ser::Serializer::new(&mut dst, &mut block); + let mut patch_list = crate::ser::PatchList::new(&mut []); + let mut ser = crate::ser::Serializer::new(&mut dst, &mut block, &mut patch_list); let base = Base { hello: 0xdeedbeef, base1: ["Hello", "World!", "Again"], @@ -583,6 +515,122 @@ mod tests { ser.dst.step_by_u32(FDT_END); } // TODO: check buf1 buf2 + // println!("{:x?} {:x?}", buf1, buf2); + // assert!(false); + } + #[test] + fn node_prop_ser_test() { + #[derive(Serialize)] + struct Base { + pub hello: u32, + pub base1: Base1, + pub hello2: u32, + pub base2: Base1, + } + #[derive(Serialize)] + struct Base1 { + pub hello: &'static str, + } + let mut buf1 = [0u8; MAX_SIZE]; + let mut buf2 = [0u8; MAX_SIZE]; + + { + let mut dst = crate::ser::Pointer::new(&mut buf1); + let mut block = crate::ser::StringBlock::new(&mut buf2); + let mut patch_list = crate::ser::PatchList::new(&mut []); + let mut ser = crate::ser::Serializer::new(&mut dst, &mut block, &mut patch_list); + let base = Base { + hello: 0xdeedbeef, + base1: Base1 { + hello: "Hello, World!", + }, + hello2: 0x11223344, + base2: Base1 { hello: "Roger" }, + }; + base.serialize(&mut ser).unwrap(); + ser.dst.step_by_u32(FDT_END); + } + // TODO: check buf1 buf2 + // println!("{:x?} {:x?}", buf1, buf2); + // assert!(false); + } + #[test] + fn replace_prop_ser_test() { + #[derive(Serialize)] + struct Base { + pub hello: u32, + pub base1: Base1, + pub hello2: u32, + pub base2: Base1, + } + #[derive(Serialize)] + struct Base1 { + pub hello: &'static str, + } + let mut buf1 = [0u8; MAX_SIZE]; + let mut buf2 = [0u8; MAX_SIZE]; + + { + let mut dst = crate::ser::Pointer::new(&mut buf1); + let mut block = crate::ser::StringBlock::new(&mut buf2); + let number = 0x55667788u32; + let patch = crate::ser::patch::Patch::new("/hello", &number as _); + let mut list = [patch]; + let mut patch_list = crate::ser::PatchList::new(&mut list); + let mut ser = crate::ser::Serializer::new(&mut dst, &mut block, &mut patch_list); + let base = Base { + hello: 0xdeedbeef, + base1: Base1 { + hello: "Hello, World!", + }, + hello2: 0x11223344, + base2: Base1 { hello: "Roger" }, + }; + base.serialize(&mut ser).unwrap(); + ser.dst.step_by_u32(FDT_END); + } + // TODO: check buf1 buf2 + // println!("{:x?} {:x?}", buf1, buf2); + // assert!(false); + } + #[test] + fn replace_node_ser_test() { + #[derive(Serialize)] + struct Base { + pub hello: u32, + pub base1: Base1, + pub hello2: u32, + pub base2: Base1, + } + #[derive(Serialize)] + struct Base1 { + pub hello: &'static str, + } + let mut buf1 = [0u8; MAX_SIZE]; + let mut buf2 = [0u8; MAX_SIZE]; + + { + let mut dst = crate::ser::Pointer::new(&mut buf1); + let mut block = crate::ser::StringBlock::new(&mut buf2); + let new_base = Base1 { + hello: "replacement", + }; + let patch = crate::ser::patch::Patch::new("/hello", &new_base as _); + let mut list = [patch]; + let mut patch_list = crate::ser::PatchList::new(&mut list); + let mut ser = crate::ser::Serializer::new(&mut dst, &mut block, &mut patch_list); + let base = Base { + hello: 0xdeedbeef, + base1: Base1 { + hello: "Hello, World!", + }, + hello2: 0x11223344, + base2: Base1 { hello: "Roger" }, + }; + base.serialize(&mut ser).unwrap(); + ser.dst.step_by_u32(FDT_END); + } + // TODO: check buf1 buf2 println!("{:x?} {:x?}", buf1, buf2); assert!(false); } diff --git a/src/ser/patch.rs b/src/ser/patch.rs new file mode 100644 index 0000000..648d5e3 --- /dev/null +++ b/src/ser/patch.rs @@ -0,0 +1,81 @@ +use core::cell::Cell; + +pub struct Patch<'de> { + name: &'de str, + pub data: &'de dyn erased_serde::Serialize, + matched_depth: Cell, + parsed: Cell, +} + +impl<'de> Patch<'de> { + pub fn new(name: &'de str, data: &'de dyn erased_serde::Serialize) -> Patch<'de> { + Patch { + name, + data, + matched_depth: Cell::new(0), + parsed: Cell::new(false), + } + } + + pub fn init(&self) { + self.matched_depth.set(0); + self.parsed.set(false); + } + + pub fn get_depth(&self) -> usize { + self.name.split('/').count() - 1 + } + + pub fn get_depth_path(&self, x: usize) -> &'de str { + if x == 0 { + return ""; + } + match self.name.split('/').nth(x) { + Some(result) => result, + None => "", + } + } + + // I hope to impl serde::ser::Serializer, but erase_serialize's return value is different from + // normal serialize, so we do this. + pub fn serialize(&self, serializer: &mut crate::ser::Serializer<'de>) { + self.parsed.set(true); + self.data + .erased_serialize(&mut ::erase(serializer)) + .unwrap(); + } +} + +pub struct PatchList<'de> { + list: &'de [Patch<'de>], +} + +impl<'de> PatchList<'de> { + pub fn new(list: &'de [Patch<'de>]) -> PatchList<'de> { + PatchList { list } + } + + pub fn step_forward(&self, name: &'de str, depth: usize) -> Option<&'de Patch<'de>> { + let mut matched_patch = None; + self.list.iter().for_each(|patch| { + if patch.matched_depth.get() == depth - 1 && patch.get_depth_path(depth) == name { + patch.matched_depth.set(patch.matched_depth.get() + 1); + if patch.get_depth() == depth { + if let Some(_) = matched_patch { + panic!("More than one replace data on a same path"); + } + matched_patch = Some(patch); + } + } + }); + matched_patch + } + + pub fn step_back(&self, depth: usize) { + self.list.iter().for_each(|patch| { + if patch.matched_depth.get() == depth { + patch.matched_depth.set(patch.matched_depth.get() - 1); + } + }); + } +} diff --git a/src/ser/pointer.rs b/src/ser/pointer.rs new file mode 100644 index 0000000..638b100 --- /dev/null +++ b/src/ser/pointer.rs @@ -0,0 +1,56 @@ +use crate::common::*; + +pub struct Pointer<'de> { + pub offset: usize, + pub data: &'de mut [u8], +} + +impl<'de> Pointer<'de> { + pub fn new(dst: &'de mut [u8]) -> Pointer<'de> { + Pointer { + offset: 0, + data: dst, + } + } + + pub fn write_to_offset_u32(&mut self, offset: usize, value: u32) { + self.data[offset..offset + 4].copy_from_slice(&u32::to_be_bytes(value)); + } + + pub fn step_by_prop(&mut self) -> usize { + self.step_by_u32(FDT_PROP); + let offset = self.offset; + self.step_by_u32(FDT_NOP); // When create prop header, we do not know how long of the prop value. + self.step_by_u32(FDT_NOP); // We can not assume this is a prop, so nop for default. + offset + } + + pub fn step_by_len(&mut self, len: usize) { + self.offset += len + } + + pub fn step_by_u32(&mut self, value: u32) { + self.data[self.offset..self.offset + 4].copy_from_slice(&u32::to_be_bytes(value)); + self.step_by_len(4); + } + + pub fn step_by_u8(&mut self, value: u8) { + self.data[self.offset] = value; + self.step_by_len(1); + } + + pub fn step_align(&mut self) { + while self.offset % 4 != 0 { + self.data[self.offset] = 0; + self.offset += 1; + } + } + + pub fn step_by_name(&mut self, name: &str) { + name.bytes().for_each(|x| { + self.step_by_u8(x); + }); + self.step_by_u8(0); + self.step_align(); + } +} diff --git a/src/ser/string_block.rs b/src/ser/string_block.rs new file mode 100644 index 0000000..ddf59b9 --- /dev/null +++ b/src/ser/string_block.rs @@ -0,0 +1,54 @@ +pub struct StringBlock<'de> { + pub end: usize, + pub data: &'de mut [u8], +} + +impl<'de> StringBlock<'de> { + pub fn new(dst: &'de mut [u8]) -> StringBlock<'de> { + StringBlock { data: dst, end: 0 } + } + + /// Will panic when len > end + /// TODO: show as error + /// Return (Result String, End Offset) + pub fn get_str_by_offset<'a>(&'a self, offset: usize) -> (&'a str, usize) { + if offset > self.end { + panic!("invalid read"); + } + let current_slice = &self.data[offset..]; + let pos = current_slice + .iter() + .position(|&x| x == b'\0') + .unwrap_or(self.data.len()); + let (a, _) = current_slice.split_at(pos + 1); + let result = unsafe { core::str::from_utf8_unchecked(&a[..a.len() - 1]) }; + (result, pos + offset + 1) + } + + fn insert_u8(&mut self, data: u8) { + self.data[self.end] = data; + self.end += 1; + } + /// Return the start offset of inserted string. + pub fn insert_str(&mut self, name: &str) -> usize { + let result = self.end; + name.bytes().for_each(|x| { + self.insert_u8(x); + }); + self.insert_u8(0); + result + } + + pub fn find_or_insert(&mut self, name: &str) -> usize { + let mut current_pos = 0; + while current_pos < self.end { + let (result, new_pos) = self.get_str_by_offset(current_pos); + if result == name { + return current_pos; + } + current_pos = new_pos; + } + + self.insert_str(name) + } +} From abdce550456943ac7ad2da7001ce16196ddb9fd8 Mon Sep 17 00:00:00 2001 From: Woshiluo Luo Date: Sat, 22 Feb 2025 14:56:25 +0800 Subject: [PATCH 03/10] feat: patch add support Signed-off-by: Woshiluo Luo --- src/ser/mod.rs | 113 ++++++++++++++++++++++++++++++++++++----------- src/ser/patch.rs | 6 +++ 2 files changed, 92 insertions(+), 27 deletions(-) diff --git a/src/ser/mod.rs b/src/ser/mod.rs index 6d1dc20..ce22a8d 100644 --- a/src/ser/mod.rs +++ b/src/ser/mod.rs @@ -59,34 +59,14 @@ impl<'de> Serializer<'de> { } } -impl<'a, 'de> serde::ser::SerializeMap for &'a mut Serializer<'de> { - type Ok = (); - type Error = Error; - - fn serialize_key(&mut self, _input: &T) -> Result<(), Self::Error> +trait SerializeDynamicField<'de> { + fn serialize_dynamic_field(&mut self, key: &'de str, value: &T) -> Result<(), Error> where - T: serde::ser::Serialize + ?Sized, - { - todo!("map_key"); - } - - fn serialize_value(&mut self, _value: &T) -> Result<(), Self::Error> - where - T: serde::ser::Serialize + ?Sized, - { - todo!("map_value"); - } - - fn end(self) -> Result { - todo!("map_end"); - } + T: serde::ser::Serialize + ?Sized; } -impl<'a, 'de> serde::ser::SerializeStruct for &'a mut Serializer<'de> { - type Ok = (); - type Error = Error; - - fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> +impl<'a, 'de> SerializeDynamicField<'de> for &'a mut Serializer<'de> { + fn serialize_dynamic_field(&mut self, key: &'de str, value: &T) -> Result<(), Error> where T: serde::ser::Serialize + ?Sized, { @@ -127,9 +107,49 @@ impl<'a, 'de> serde::ser::SerializeStruct for &'a mut Serializer<'de> { Ok(()) } +} + +impl<'a, 'de> serde::ser::SerializeMap for &'a mut Serializer<'de> { + type Ok = (); + type Error = Error; + + fn serialize_key(&mut self, _input: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize + ?Sized, + { + todo!("map_key"); + } + + fn serialize_value(&mut self, _value: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize + ?Sized, + { + todo!("map_value"); + } fn end(self) -> Result { - // TODO: patch type add + todo!("map_end"); + } +} + +impl<'a, 'de> serde::ser::SerializeStruct for &'a mut Serializer<'de> { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize + ?Sized, + { + self.serialize_dynamic_field(key, value)?; + + Ok(()) + } + + fn end(mut self) -> Result { + for patch in self.patch_list.add_list(self.current_dep) { + let key = patch.get_depth_path(self.current_dep + 1); + self.serialize_dynamic_field(key, patch.data)?; + } self.dst.step_by_u32(FDT_END_NODE); Ok(()) } @@ -408,7 +428,7 @@ mod tests { use crate::common::*; use serde::ser::Serialize; use serde_derive::Serialize; - const MAX_SIZE: usize = 128 + 64; + const MAX_SIZE: usize = 128 + 64 + 32; #[test] fn base_ser_test() { #[derive(Serialize)] @@ -631,6 +651,45 @@ mod tests { ser.dst.step_by_u32(FDT_END); } // TODO: check buf1 buf2 + // println!("{:x?} {:x?}", buf1, buf2); + // assert!(false); + } + #[test] + fn add_node_ser_test() { + #[derive(Serialize)] + struct Base { + pub hello: u32, + pub base1: Base1, + pub hello2: u32, + pub base2: Base1, + } + #[derive(Serialize)] + struct Base1 { + pub hello: &'static str, + } + let mut buf1 = [0u8; MAX_SIZE]; + let mut buf2 = [0u8; MAX_SIZE]; + + { + let mut dst = crate::ser::Pointer::new(&mut buf1); + let mut block = crate::ser::StringBlock::new(&mut buf2); + let new_base = Base1 { hello: "added" }; + let patch = crate::ser::patch::Patch::new("/base3", &new_base as _); + let mut list = [patch]; + let mut patch_list = crate::ser::PatchList::new(&mut list); + let mut ser = crate::ser::Serializer::new(&mut dst, &mut block, &mut patch_list); + let base = Base { + hello: 0xdeedbeef, + base1: Base1 { + hello: "Hello, World!", + }, + hello2: 0x11223344, + base2: Base1 { hello: "Roger" }, + }; + base.serialize(&mut ser).unwrap(); + ser.dst.step_by_u32(FDT_END); + } + // TODO: check buf1 buf2 println!("{:x?} {:x?}", buf1, buf2); assert!(false); } diff --git a/src/ser/patch.rs b/src/ser/patch.rs index 648d5e3..702e07f 100644 --- a/src/ser/patch.rs +++ b/src/ser/patch.rs @@ -78,4 +78,10 @@ impl<'de> PatchList<'de> { } }); } + + pub fn add_list(&self, depth: usize) -> impl Iterator> + use<'de> { + self.list.iter().filter(move |x| { + x.matched_depth.get() == depth && x.get_depth() == depth + 1 && x.parsed.get() == false + }) + } } From c69ea217c930292bf6543c843dda65e9eff0b347 Mon Sep 17 00:00:00 2001 From: Woshiluo Luo Date: Mon, 24 Feb 2025 09:13:27 +0800 Subject: [PATCH 04/10] feat: add `to_dtb` function to avoid two split slice refactor: use 'se lifetime for serialzer Signed-off-by: Woshiluo Luo --- src/ser/mod.rs | 705 +++------------------------------------- src/ser/patch.rs | 27 +- src/ser/pointer.rs | 52 ++- src/ser/serializer.rs | 620 +++++++++++++++++++++++++++++++++++ src/ser/string_block.rs | 22 +- 5 files changed, 726 insertions(+), 700 deletions(-) create mode 100644 src/ser/serializer.rs diff --git a/src/ser/mod.rs b/src/ser/mod.rs index ce22a8d..54e50e9 100644 --- a/src/ser/mod.rs +++ b/src/ser/mod.rs @@ -1,16 +1,47 @@ pub mod patch; pub mod pointer; +pub mod serializer; pub mod string_block; use crate::common::*; -use patch::PatchList; -use pointer::Pointer; -use string_block::StringBlock; +use crate::ser::patch::Patch; + +/// We do run-twice on convert, first time to generate string block, second time todo real +/// structure. +pub fn to_dtb<'se, T>(data: &T, list: &'se [Patch<'se>], writer: &'se mut [u8]) -> Result<(), Error> +where + T: serde::ser::Serialize, +{ + let mut offset: usize = 0; + { + let mut dst = crate::ser::pointer::Pointer::new(None); + let mut patch_list = crate::ser::patch::PatchList::new(list); + let mut block = crate::ser::string_block::StringBlock::new(writer, &mut offset); + let mut ser = + crate::ser::serializer::Serializer::new(&mut dst, &mut block, &mut patch_list); + data.serialize(&mut ser)?; + }; + list.iter().for_each(|patch| patch.init()); + { + // Write from bottom to top, to avoid overlap. + for i in (0..offset).rev() { + writer[writer.len() - offset + i] = writer[i]; + writer[i] = 0; + } + // TODO: make sure no out of bound. -#[derive(Clone, Copy)] -pub enum ValueType { - Node, - Prop, + // -1 for end zero. + let (data_block, string_block) = writer.split_at_mut(writer.len() - offset); + let (_, data_block) = data_block.split_at_mut(size_of::()); + let mut patch_list = crate::ser::patch::PatchList::new(list); + let mut block = crate::ser::string_block::StringBlock::new(string_block, &mut offset); + let mut dst = crate::ser::pointer::Pointer::new(Some(data_block)); + let mut ser = + crate::ser::serializer::Serializer::new(&mut dst, &mut block, &mut patch_list); + ser.dst.step_by_u32(FDT_END); + data.serialize(&mut ser)?; + } + Ok(()) } #[derive(Debug)] @@ -34,663 +65,3 @@ impl serde::ser::Error for Error { Self::Unknown } } - -pub struct Serializer<'de> { - dst: &'de mut Pointer<'de>, - string_block: &'de mut StringBlock<'de>, - value_type: ValueType, - current_dep: usize, - patch_list: &'de mut PatchList<'de>, -} - -impl<'de> Serializer<'de> { - pub fn new( - dst: &'de mut Pointer<'de>, - cache: &'de mut StringBlock<'de>, - patch_list: &'de mut PatchList<'de>, - ) -> Serializer<'de> { - Serializer { - dst, - string_block: cache, - current_dep: 0, - value_type: ValueType::Node, - patch_list, - } - } -} - -trait SerializeDynamicField<'de> { - fn serialize_dynamic_field(&mut self, key: &'de str, value: &T) -> Result<(), Error> - where - T: serde::ser::Serialize + ?Sized; -} - -impl<'a, 'de> SerializeDynamicField<'de> for &'a mut Serializer<'de> { - fn serialize_dynamic_field(&mut self, key: &'de str, value: &T) -> Result<(), Error> - where - T: serde::ser::Serialize + ?Sized, - { - let prop_header_offset = self.dst.step_by_prop(); - let old_value_type = self.value_type; - self.current_dep += 1; - let matched_patch = self.patch_list.step_forward(key, self.current_dep); - - match matched_patch { - Some(data) => { - data.serialize(&mut **self); - } - None => { - value.serialize(&mut **self)?; - } - } - - // We now know how long the prop value. - // TODO: make we have some better way than put nop, like move this block ahead. - if let ValueType::Node = self.value_type { - self.dst - .write_to_offset_u32(prop_header_offset - 4, FDT_NOP); - } else { - self.dst.write_to_offset_u32( - prop_header_offset, - (self.dst.offset - prop_header_offset - 8) as u32, - ); - self.dst.write_to_offset_u32( - prop_header_offset + 4, - self.string_block.find_or_insert(key) as u32, - ); - } - - self.value_type = old_value_type; - self.dst.step_align(); - self.patch_list.step_back(self.current_dep); - self.current_dep -= 1; - - Ok(()) - } -} - -impl<'a, 'de> serde::ser::SerializeMap for &'a mut Serializer<'de> { - type Ok = (); - type Error = Error; - - fn serialize_key(&mut self, _input: &T) -> Result<(), Self::Error> - where - T: serde::ser::Serialize + ?Sized, - { - todo!("map_key"); - } - - fn serialize_value(&mut self, _value: &T) -> Result<(), Self::Error> - where - T: serde::ser::Serialize + ?Sized, - { - todo!("map_value"); - } - - fn end(self) -> Result { - todo!("map_end"); - } -} - -impl<'a, 'de> serde::ser::SerializeStruct for &'a mut Serializer<'de> { - type Ok = (); - type Error = Error; - - fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> - where - T: serde::ser::Serialize + ?Sized, - { - self.serialize_dynamic_field(key, value)?; - - Ok(()) - } - - fn end(mut self) -> Result { - for patch in self.patch_list.add_list(self.current_dep) { - let key = patch.get_depth_path(self.current_dep + 1); - self.serialize_dynamic_field(key, patch.data)?; - } - self.dst.step_by_u32(FDT_END_NODE); - Ok(()) - } -} - -impl<'a, 'de> serde::ser::SerializeStructVariant for &'a mut Serializer<'de> { - type Ok = (); - type Error = Error; - - fn serialize_field(&mut self, _key: &'static str, _value: &T) -> Result<(), Self::Error> - where - T: serde::ser::Serialize + ?Sized, - { - todo!("struct_field"); - } - - fn end(self) -> Result { - todo!("struct_end"); - } -} - -impl<'a, 'de> serde::ser::SerializeSeq for &'a mut Serializer<'de> { - type Ok = (); - type Error = Error; - // TODO: make sure there are no node seq serialize over this function. - fn serialize_element(&mut self, value: &T) -> Result<(), Error> - where - T: ?Sized + serde::ser::Serialize, - { - value.serialize(&mut **self) - } - - // Close the sequence. - fn end(self) -> Result<(), Error> { - Ok(()) - } -} - -impl<'a, 'de> serde::ser::SerializeTuple for &'a mut Serializer<'de> { - type Ok = (); - type Error = Error; - - fn serialize_element(&mut self, value: &T) -> Result<(), Error> - where - T: ?Sized + serde::ser::Serialize, - { - value.serialize(&mut **self) - } - - // Close the sequence. - fn end(self) -> Result<(), Error> { - Ok(()) - } -} - -impl<'a, 'de> serde::ser::SerializeTupleVariant for &'a mut Serializer<'de> { - type Ok = (); - type Error = Error; - - fn serialize_field(&mut self, _value: &T) -> Result<(), Self::Error> - where - T: serde::ser::Serialize + ?Sized, - { - todo!("tuple_variant_field"); - } - - fn end(self) -> Result<(), Error> { - todo!("tuple_variant_end"); - } -} - -impl<'a, 'de> serde::ser::SerializeTupleStruct for &'a mut Serializer<'de> { - type Ok = (); - type Error = Error; - - fn serialize_field(&mut self, _value: &T) -> Result<(), Self::Error> - where - T: serde::ser::Serialize + ?Sized, - { - todo!("tuple_struct_field"); - } - - fn end(self) -> Result<(), Error> { - todo!("tuple_struct_end"); - } -} - -impl<'a, 'de> serde::ser::Serializer for &'a mut Serializer<'de> { - type Ok = (); - type Error = Error; - type SerializeSeq = Self; - type SerializeMap = Self; - type SerializeStruct = Self; - type SerializeTuple = Self; - type SerializeTupleStruct = Self; - type SerializeTupleVariant = Self; - type SerializeStructVariant = Self; - - fn serialize_bool(self, _v: bool) -> Result { - todo!("bool"); - } - - fn serialize_i8(self, _v: i8) -> Result { - todo!("i8"); - } - - fn serialize_i16(self, _v: i16) -> Result { - todo!("i16"); - } - - fn serialize_i32(self, _v: i32) -> Result { - todo!("i32"); - } - - fn serialize_i64(self, _v: i64) -> Result { - todo!("i64"); - } - - fn serialize_u8(self, _v: u8) -> Result { - todo!("u8"); - } - - fn serialize_u16(self, _v: u16) -> Result { - todo!("u16"); - } - - fn serialize_u32(self, v: u32) -> Result { - self.value_type = ValueType::Prop; - self.dst.step_by_u32(v); - Ok(()) - } - - fn serialize_u64(self, _v: u64) -> Result { - todo!("u64"); - } - - fn serialize_f32(self, _v: f32) -> Result { - todo!("f32"); - } - - fn serialize_f64(self, _v: f64) -> Result { - todo!("f64"); - } - - fn serialize_char(self, _v: char) -> Result { - todo!("char"); - } - - fn serialize_str(self, v: &str) -> Result { - self.value_type = ValueType::Prop; - v.bytes().for_each(|x| { - self.dst.step_by_u8(x); - }); - self.dst.step_by_u8(0); - Ok(()) - } - - fn serialize_bytes(self, v: &[u8]) -> Result { - self.value_type = ValueType::Prop; - v.iter().for_each(|x| self.dst.step_by_u8(*x)); - Ok(()) - } - - fn serialize_none(self) -> Result { - todo!("none"); - } - - fn serialize_some(self, _v: &T) -> Result - where - T: serde::ser::Serialize + ?Sized, - { - todo!("some"); - } - - fn serialize_unit(self) -> Result { - todo!("unit"); - } - - fn serialize_unit_struct(self, _name: &'static str) -> Result { - todo!("unit struct"); - } - - fn serialize_unit_variant( - self, - _name: &'static str, - _variant_index: u32, - _variant: &'static str, - ) -> Result { - todo!("unit struct variant"); - } - - fn serialize_newtype_struct( - self, - _name: &'static str, - _v: &T, - ) -> Result - where - T: serde::ser::Serialize + ?Sized, - { - todo!("newtype struct"); - } - - fn serialize_newtype_variant( - self, - _name: &'static str, - _variant_index: u32, - _variant: &'static str, - _value: &T, - ) -> Result - where - T: serde::ser::Serialize + ?Sized, - { - todo!("newtype struct variant"); - } - - fn serialize_seq(self, _len: Option) -> Result { - self.value_type = ValueType::Prop; - Ok(self) - } - - fn serialize_tuple(self, len: usize) -> Result { - self.serialize_seq(Some(len)) - } - - fn serialize_tuple_struct( - self, - _name: &'static str, - _len: usize, - ) -> Result { - todo!("tuple struct"); - } - - fn serialize_tuple_variant( - self, - _name: &'static str, - _variant_index: u32, - _variant: &'static str, - _len: usize, - ) -> Result { - todo!("tuple variant"); - } - - fn serialize_map(self, _len: Option) -> Result { - todo!("map"); - } - - fn serialize_struct( - self, - name: &'static str, - _len: usize, - ) -> Result { - self.dst.step_by_u32(FDT_BEGIN_NODE); - if self.current_dep == 0 { - // The name of root node should be empty. - self.dst.step_by_u32(0); - } else { - self.dst.step_by_name(name); - } - self.value_type = ValueType::Node; - Ok(self) - } - - fn serialize_struct_variant( - self, - _name: &'static str, - _variant_index: u32, - _variant: &'static str, - _len: usize, - ) -> Result { - todo!("struct variant"); - } -} - -#[cfg(test)] -mod tests { - use crate::common::*; - use serde::ser::Serialize; - use serde_derive::Serialize; - const MAX_SIZE: usize = 128 + 64 + 32; - #[test] - fn base_ser_test() { - #[derive(Serialize)] - struct Base { - pub hello: u32, - } - let mut buf1 = [0u8; MAX_SIZE]; - let mut buf2 = [0u8; MAX_SIZE]; - - { - let mut dst = crate::ser::Pointer::new(&mut buf1); - let mut block = crate::ser::StringBlock::new(&mut buf2); - let mut patch_list = crate::ser::PatchList::new(&mut []); - let mut ser = crate::ser::Serializer::new(&mut dst, &mut block, &mut patch_list); - let base = Base { hello: 0xdeedbeef }; - base.serialize(&mut ser).unwrap(); - // TODO: write end, this should be write by other thing. - ser.dst.step_by_u32(FDT_END); - } - // TODO: check buf1 buf2 - } - #[test] - fn rev_ser_test() { - #[derive(Serialize)] - struct Base { - pub hello: u32, - pub base1: Base1, - } - #[derive(Serialize)] - struct Base1 { - pub hello: u32, - } - let mut buf1 = [0u8; MAX_SIZE]; - let mut buf2 = [0u8; MAX_SIZE]; - - { - let mut dst = crate::ser::Pointer::new(&mut buf1); - let mut block = crate::ser::StringBlock::new(&mut buf2); - let mut patch_list = crate::ser::PatchList::new(&mut []); - let mut ser = crate::ser::Serializer::new(&mut dst, &mut block, &mut patch_list); - let base = Base { - hello: 0xdeedbeef, - base1: Base1 { hello: 0x10000001 }, - }; - base.serialize(&mut ser).unwrap(); - ser.dst.step_by_u32(FDT_END); - } - // TODO: check buf1 buf2 - // println!("{:x?} {:x?}", buf1, buf2); - // assert!(false); - } - #[test] - fn rev_str_ser_test() { - #[derive(Serialize)] - struct Base { - pub hello: u32, - pub base1: Base1, - } - #[derive(Serialize)] - struct Base1 { - pub hello: &'static str, - } - let mut buf1 = [0u8; MAX_SIZE]; - let mut buf2 = [0u8; MAX_SIZE]; - - { - let mut dst = crate::ser::Pointer::new(&mut buf1); - let mut block = crate::ser::StringBlock::new(&mut buf2); - let mut patch_list = crate::ser::PatchList::new(&mut []); - let mut ser = crate::ser::Serializer::new(&mut dst, &mut block, &mut patch_list); - let base = Base { - hello: 0xdeedbeef, - base1: Base1 { - hello: "Hello, World!", - }, - }; - base.serialize(&mut ser).unwrap(); - ser.dst.step_by_u32(FDT_END); - } - // TODO: check buf1 buf2 - // println!("{:x?} {:x?}", buf1, buf2); - // assert!(false); - } - #[test] - fn seq_str_ser_test() { - #[derive(Serialize)] - struct Base { - pub hello: u32, - pub base1: [&'static str; 3], - } - let mut buf1 = [0u8; MAX_SIZE]; - let mut buf2 = [0u8; MAX_SIZE]; - - { - let mut dst = crate::ser::Pointer::new(&mut buf1); - let mut block = crate::ser::StringBlock::new(&mut buf2); - let mut patch_list = crate::ser::PatchList::new(&mut []); - let mut ser = crate::ser::Serializer::new(&mut dst, &mut block, &mut patch_list); - let base = Base { - hello: 0xdeedbeef, - base1: ["Hello", "World!", "Again"], - }; - base.serialize(&mut ser).unwrap(); - ser.dst.step_by_u32(FDT_END); - } - // TODO: check buf1 buf2 - // println!("{:x?} {:x?}", buf1, buf2); - // assert!(false); - } - #[test] - fn node_prop_ser_test() { - #[derive(Serialize)] - struct Base { - pub hello: u32, - pub base1: Base1, - pub hello2: u32, - pub base2: Base1, - } - #[derive(Serialize)] - struct Base1 { - pub hello: &'static str, - } - let mut buf1 = [0u8; MAX_SIZE]; - let mut buf2 = [0u8; MAX_SIZE]; - - { - let mut dst = crate::ser::Pointer::new(&mut buf1); - let mut block = crate::ser::StringBlock::new(&mut buf2); - let mut patch_list = crate::ser::PatchList::new(&mut []); - let mut ser = crate::ser::Serializer::new(&mut dst, &mut block, &mut patch_list); - let base = Base { - hello: 0xdeedbeef, - base1: Base1 { - hello: "Hello, World!", - }, - hello2: 0x11223344, - base2: Base1 { hello: "Roger" }, - }; - base.serialize(&mut ser).unwrap(); - ser.dst.step_by_u32(FDT_END); - } - // TODO: check buf1 buf2 - // println!("{:x?} {:x?}", buf1, buf2); - // assert!(false); - } - #[test] - fn replace_prop_ser_test() { - #[derive(Serialize)] - struct Base { - pub hello: u32, - pub base1: Base1, - pub hello2: u32, - pub base2: Base1, - } - #[derive(Serialize)] - struct Base1 { - pub hello: &'static str, - } - let mut buf1 = [0u8; MAX_SIZE]; - let mut buf2 = [0u8; MAX_SIZE]; - - { - let mut dst = crate::ser::Pointer::new(&mut buf1); - let mut block = crate::ser::StringBlock::new(&mut buf2); - let number = 0x55667788u32; - let patch = crate::ser::patch::Patch::new("/hello", &number as _); - let mut list = [patch]; - let mut patch_list = crate::ser::PatchList::new(&mut list); - let mut ser = crate::ser::Serializer::new(&mut dst, &mut block, &mut patch_list); - let base = Base { - hello: 0xdeedbeef, - base1: Base1 { - hello: "Hello, World!", - }, - hello2: 0x11223344, - base2: Base1 { hello: "Roger" }, - }; - base.serialize(&mut ser).unwrap(); - ser.dst.step_by_u32(FDT_END); - } - // TODO: check buf1 buf2 - // println!("{:x?} {:x?}", buf1, buf2); - // assert!(false); - } - #[test] - fn replace_node_ser_test() { - #[derive(Serialize)] - struct Base { - pub hello: u32, - pub base1: Base1, - pub hello2: u32, - pub base2: Base1, - } - #[derive(Serialize)] - struct Base1 { - pub hello: &'static str, - } - let mut buf1 = [0u8; MAX_SIZE]; - let mut buf2 = [0u8; MAX_SIZE]; - - { - let mut dst = crate::ser::Pointer::new(&mut buf1); - let mut block = crate::ser::StringBlock::new(&mut buf2); - let new_base = Base1 { - hello: "replacement", - }; - let patch = crate::ser::patch::Patch::new("/hello", &new_base as _); - let mut list = [patch]; - let mut patch_list = crate::ser::PatchList::new(&mut list); - let mut ser = crate::ser::Serializer::new(&mut dst, &mut block, &mut patch_list); - let base = Base { - hello: 0xdeedbeef, - base1: Base1 { - hello: "Hello, World!", - }, - hello2: 0x11223344, - base2: Base1 { hello: "Roger" }, - }; - base.serialize(&mut ser).unwrap(); - ser.dst.step_by_u32(FDT_END); - } - // TODO: check buf1 buf2 - // println!("{:x?} {:x?}", buf1, buf2); - // assert!(false); - } - #[test] - fn add_node_ser_test() { - #[derive(Serialize)] - struct Base { - pub hello: u32, - pub base1: Base1, - pub hello2: u32, - pub base2: Base1, - } - #[derive(Serialize)] - struct Base1 { - pub hello: &'static str, - } - let mut buf1 = [0u8; MAX_SIZE]; - let mut buf2 = [0u8; MAX_SIZE]; - - { - let mut dst = crate::ser::Pointer::new(&mut buf1); - let mut block = crate::ser::StringBlock::new(&mut buf2); - let new_base = Base1 { hello: "added" }; - let patch = crate::ser::patch::Patch::new("/base3", &new_base as _); - let mut list = [patch]; - let mut patch_list = crate::ser::PatchList::new(&mut list); - let mut ser = crate::ser::Serializer::new(&mut dst, &mut block, &mut patch_list); - let base = Base { - hello: 0xdeedbeef, - base1: Base1 { - hello: "Hello, World!", - }, - hello2: 0x11223344, - base2: Base1 { hello: "Roger" }, - }; - base.serialize(&mut ser).unwrap(); - ser.dst.step_by_u32(FDT_END); - } - // TODO: check buf1 buf2 - println!("{:x?} {:x?}", buf1, buf2); - assert!(false); - } -} diff --git a/src/ser/patch.rs b/src/ser/patch.rs index 702e07f..e99744d 100644 --- a/src/ser/patch.rs +++ b/src/ser/patch.rs @@ -1,14 +1,15 @@ +use super::serializer::Serializer; use core::cell::Cell; -pub struct Patch<'de> { - name: &'de str, - pub data: &'de dyn erased_serde::Serialize, +pub struct Patch<'se> { + name: &'se str, + pub data: &'se dyn erased_serde::Serialize, matched_depth: Cell, parsed: Cell, } -impl<'de> Patch<'de> { - pub fn new(name: &'de str, data: &'de dyn erased_serde::Serialize) -> Patch<'de> { +impl<'se> Patch<'se> { + pub fn new(name: &'se str, data: &'se dyn erased_serde::Serialize) -> Patch<'se> { Patch { name, data, @@ -26,7 +27,7 @@ impl<'de> Patch<'de> { self.name.split('/').count() - 1 } - pub fn get_depth_path(&self, x: usize) -> &'de str { + pub fn get_depth_path(&self, x: usize) -> &'se str { if x == 0 { return ""; } @@ -38,7 +39,7 @@ impl<'de> Patch<'de> { // I hope to impl serde::ser::Serializer, but erase_serialize's return value is different from // normal serialize, so we do this. - pub fn serialize(&self, serializer: &mut crate::ser::Serializer<'de>) { + pub fn serialize(&self, serializer: &mut Serializer<'se>) { self.parsed.set(true); self.data .erased_serialize(&mut ::erase(serializer)) @@ -46,16 +47,16 @@ impl<'de> Patch<'de> { } } -pub struct PatchList<'de> { - list: &'de [Patch<'de>], +pub struct PatchList<'se> { + list: &'se [Patch<'se>], } -impl<'de> PatchList<'de> { - pub fn new(list: &'de [Patch<'de>]) -> PatchList<'de> { +impl<'se> PatchList<'se> { + pub fn new(list: &'se [Patch<'se>]) -> PatchList<'se> { PatchList { list } } - pub fn step_forward(&self, name: &'de str, depth: usize) -> Option<&'de Patch<'de>> { + pub fn step_forward(&self, name: &'se str, depth: usize) -> Option<&'se Patch<'se>> { let mut matched_patch = None; self.list.iter().for_each(|patch| { if patch.matched_depth.get() == depth - 1 && patch.get_depth_path(depth) == name { @@ -79,7 +80,7 @@ impl<'de> PatchList<'de> { }); } - pub fn add_list(&self, depth: usize) -> impl Iterator> + use<'de> { + pub fn add_list(&self, depth: usize) -> impl Iterator> + use<'se> { self.list.iter().filter(move |x| { x.matched_depth.get() == depth && x.get_depth() == depth + 1 && x.parsed.get() == false }) diff --git a/src/ser/pointer.rs b/src/ser/pointer.rs index 638b100..03fba7b 100644 --- a/src/ser/pointer.rs +++ b/src/ser/pointer.rs @@ -1,22 +1,40 @@ use crate::common::*; -pub struct Pointer<'de> { - pub offset: usize, - pub data: &'de mut [u8], +pub struct Pointer<'se> { + offset: usize, + data: Option<&'se mut [u8]>, } -impl<'de> Pointer<'de> { - pub fn new(dst: &'de mut [u8]) -> Pointer<'de> { +impl<'se> Pointer<'se> { + #[inline(always)] + pub fn new(dst: Option<&'se mut [u8]>) -> Pointer<'se> { Pointer { offset: 0, data: dst, } } + #[inline(always)] + pub fn update_data(&mut self, data: Option<&'se mut [u8]>) { + self.data = data; + } + + #[inline(always)] + pub fn get_offset(&self) -> usize { + self.offset + } + + #[inline(always)] pub fn write_to_offset_u32(&mut self, offset: usize, value: u32) { - self.data[offset..offset + 4].copy_from_slice(&u32::to_be_bytes(value)); + match self.data { + Some(ref mut data) => { + data[offset..offset + 4].copy_from_slice(&u32::to_be_bytes(value)) + } + None => {} + } } + #[inline(always)] pub fn step_by_prop(&mut self) -> usize { self.step_by_u32(FDT_PROP); let offset = self.offset; @@ -25,27 +43,43 @@ impl<'de> Pointer<'de> { offset } + #[inline(always)] pub fn step_by_len(&mut self, len: usize) { self.offset += len } + #[inline(always)] pub fn step_by_u32(&mut self, value: u32) { - self.data[self.offset..self.offset + 4].copy_from_slice(&u32::to_be_bytes(value)); + match self.data { + Some(ref mut data) => { + data[self.offset..self.offset + 4].copy_from_slice(&u32::to_be_bytes(value)) + } + None => {} + } self.step_by_len(4); } + #[inline(always)] pub fn step_by_u8(&mut self, value: u8) { - self.data[self.offset] = value; + match self.data { + Some(ref mut data) => data[self.offset] = value, + None => {} + } self.step_by_len(1); } + #[inline(always)] pub fn step_align(&mut self) { while self.offset % 4 != 0 { - self.data[self.offset] = 0; + match self.data { + Some(ref mut data) => data[self.offset] = 0, + None => {} + } self.offset += 1; } } + #[inline(always)] pub fn step_by_name(&mut self, name: &str) { name.bytes().for_each(|x| { self.step_by_u8(x); diff --git a/src/ser/serializer.rs b/src/ser/serializer.rs new file mode 100644 index 0000000..008b62f --- /dev/null +++ b/src/ser/serializer.rs @@ -0,0 +1,620 @@ +use super::patch::PatchList; +use super::pointer::Pointer; +use super::string_block::StringBlock; +use super::Error; +use crate::common::*; + +#[derive(Clone, Copy)] +enum ValueType { + Node, + Prop, +} + +pub struct Serializer<'se> { + pub dst: &'se mut Pointer<'se>, + string_block: &'se mut StringBlock<'se>, + value_type: ValueType, + current_dep: usize, + patch_list: &'se mut PatchList<'se>, +} + +impl<'se> Serializer<'se> { + pub fn new( + dst: &'se mut Pointer<'se>, + cache: &'se mut StringBlock<'se>, + patch_list: &'se mut PatchList<'se>, + ) -> Serializer<'se> { + Serializer { + dst, + string_block: cache, + current_dep: 0, + value_type: ValueType::Node, + patch_list, + } + } +} + +trait SerializeDynamicField<'se> { + fn serialize_dynamic_field(&mut self, key: &'se str, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize + ?Sized; +} + +impl<'a, 'se> SerializeDynamicField<'se> for &'a mut Serializer<'se> { + fn serialize_dynamic_field(&mut self, key: &'se str, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize + ?Sized, + { + let prop_header_offset = self.dst.step_by_prop(); + let old_value_type = self.value_type; + self.current_dep += 1; + let matched_patch = self.patch_list.step_forward(key, self.current_dep); + + match matched_patch { + Some(data) => { + data.serialize(&mut **self); + } + None => { + value.serialize(&mut **self)?; + } + } + + // We now know how long the prop value. + // TODO: make we have some better way than put nop, like move this block ahead. + if let ValueType::Node = self.value_type { + self.dst + .write_to_offset_u32(prop_header_offset - 4, FDT_NOP); + } else { + self.dst.write_to_offset_u32( + prop_header_offset, + (self.dst.get_offset() - prop_header_offset - 8) as u32, + ); + self.dst.write_to_offset_u32( + prop_header_offset + 4, + self.string_block.find_or_insert(key) as u32, + ); + } + + self.value_type = old_value_type; + self.dst.step_align(); + self.patch_list.step_back(self.current_dep); + self.current_dep -= 1; + + Ok(()) + } +} + +impl<'a, 'se> serde::ser::SerializeMap for &'a mut Serializer<'se> { + type Ok = (); + type Error = Error; + + fn serialize_key(&mut self, _input: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize + ?Sized, + { + todo!("map_key"); + } + + fn serialize_value(&mut self, _value: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize + ?Sized, + { + todo!("map_value"); + } + + fn end(self) -> Result { + todo!("map_end"); + } +} + +impl<'a, 'se> serde::ser::SerializeStruct for &'a mut Serializer<'se> { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize + ?Sized, + { + self.serialize_dynamic_field(key, value)?; + + Ok(()) + } + + fn end(mut self) -> Result { + for patch in self.patch_list.add_list(self.current_dep) { + let key = patch.get_depth_path(self.current_dep + 1); + self.serialize_dynamic_field(key, patch.data)?; + } + self.dst.step_by_u32(FDT_END_NODE); + Ok(()) + } +} + +impl<'a, 'se> serde::ser::SerializeStructVariant for &'a mut Serializer<'se> { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, _key: &'static str, _value: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize + ?Sized, + { + todo!("struct_field"); + } + + fn end(self) -> Result { + todo!("struct_end"); + } +} + +impl<'a, 'se> serde::ser::SerializeSeq for &'a mut Serializer<'se> { + type Ok = (); + type Error = Error; + // TODO: make sure there are no node seq serialize over this function. + fn serialize_element(&mut self, value: &T) -> Result<(), Error> + where + T: ?Sized + serde::ser::Serialize, + { + value.serialize(&mut **self) + } + + // Close the sequence. + fn end(self) -> Result<(), Error> { + Ok(()) + } +} + +impl<'a, 'se> serde::ser::SerializeTuple for &'a mut Serializer<'se> { + type Ok = (); + type Error = Error; + + fn serialize_element(&mut self, value: &T) -> Result<(), Error> + where + T: ?Sized + serde::ser::Serialize, + { + value.serialize(&mut **self) + } + + // Close the sequence. + fn end(self) -> Result<(), Error> { + Ok(()) + } +} + +impl<'a, 'se> serde::ser::SerializeTupleVariant for &'a mut Serializer<'se> { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, _value: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize + ?Sized, + { + todo!("tuple_variant_field"); + } + + fn end(self) -> Result<(), Error> { + todo!("tuple_variant_end"); + } +} + +impl<'a, 'se> serde::ser::SerializeTupleStruct for &'a mut Serializer<'se> { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, _value: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize + ?Sized, + { + todo!("tuple_struct_field"); + } + + fn end(self) -> Result<(), Error> { + todo!("tuple_struct_end"); + } +} + +impl<'a, 'se> serde::ser::Serializer for &'a mut Serializer<'se> { + type Ok = (); + type Error = Error; + type SerializeSeq = Self; + type SerializeMap = Self; + type SerializeStruct = Self; + type SerializeTuple = Self; + type SerializeTupleStruct = Self; + type SerializeTupleVariant = Self; + type SerializeStructVariant = Self; + + fn serialize_bool(self, _v: bool) -> Result { + todo!("bool"); + } + + fn serialize_i8(self, _v: i8) -> Result { + todo!("i8"); + } + + fn serialize_i16(self, _v: i16) -> Result { + todo!("i16"); + } + + fn serialize_i32(self, _v: i32) -> Result { + todo!("i32"); + } + + fn serialize_i64(self, _v: i64) -> Result { + todo!("i64"); + } + + fn serialize_u8(self, _v: u8) -> Result { + todo!("u8"); + } + + fn serialize_u16(self, _v: u16) -> Result { + todo!("u16"); + } + + fn serialize_u32(self, v: u32) -> Result { + self.value_type = ValueType::Prop; + self.dst.step_by_u32(v); + Ok(()) + } + + fn serialize_u64(self, _v: u64) -> Result { + todo!("u64"); + } + + fn serialize_f32(self, _v: f32) -> Result { + todo!("f32"); + } + + fn serialize_f64(self, _v: f64) -> Result { + todo!("f64"); + } + + fn serialize_char(self, _v: char) -> Result { + todo!("char"); + } + + fn serialize_str(self, v: &str) -> Result { + self.value_type = ValueType::Prop; + v.bytes().for_each(|x| { + self.dst.step_by_u8(x); + }); + self.dst.step_by_u8(0); + Ok(()) + } + + fn serialize_bytes(self, v: &[u8]) -> Result { + self.value_type = ValueType::Prop; + v.iter().for_each(|x| self.dst.step_by_u8(*x)); + Ok(()) + } + + fn serialize_none(self) -> Result { + todo!("none"); + } + + fn serialize_some(self, _v: &T) -> Result + where + T: serde::ser::Serialize + ?Sized, + { + todo!("some"); + } + + fn serialize_unit(self) -> Result { + todo!("unit"); + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result { + todo!("unit struct"); + } + + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + ) -> Result { + todo!("unit struct variant"); + } + + fn serialize_newtype_struct( + self, + _name: &'static str, + _v: &T, + ) -> Result + where + T: serde::ser::Serialize + ?Sized, + { + todo!("newtype struct"); + } + + fn serialize_newtype_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _value: &T, + ) -> Result + where + T: serde::ser::Serialize + ?Sized, + { + todo!("newtype struct variant"); + } + + fn serialize_seq(self, _len: Option) -> Result { + self.value_type = ValueType::Prop; + Ok(self) + } + + fn serialize_tuple(self, len: usize) -> Result { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result { + todo!("tuple struct"); + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + todo!("tuple variant"); + } + + fn serialize_map(self, _len: Option) -> Result { + todo!("map"); + } + + fn serialize_struct( + self, + name: &'static str, + _len: usize, + ) -> Result { + self.dst.step_by_u32(FDT_BEGIN_NODE); + if self.current_dep == 0 { + // The name of root node should be empty. + self.dst.step_by_u32(0); + } else { + self.dst.step_by_name(name); + } + self.value_type = ValueType::Node; + Ok(self) + } + + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + todo!("struct variant"); + } +} + +#[cfg(test)] +mod tests { + use serde_derive::Serialize; + const MAX_SIZE: usize = 256; + #[test] + fn base_ser_test() { + #[derive(Serialize)] + struct Base { + pub hello: u32, + } + let mut buf1 = [0u8; MAX_SIZE]; + + { + let base = Base { hello: 0xdeedbeef }; + crate::ser::to_dtb(&base, &mut [], &mut buf1).unwrap(); + } + // TODO: check buf1 buf2 + } + #[test] + fn rev_ser_test() { + #[derive(Serialize)] + struct Base { + pub hello: u32, + pub base1: Base1, + } + #[derive(Serialize)] + struct Base1 { + pub hello: u32, + } + let mut buf1 = [0u8; MAX_SIZE]; + + { + let base = Base { + hello: 0xdeedbeef, + base1: Base1 { hello: 0x10000001 }, + }; + crate::ser::to_dtb(&base, &mut [], &mut buf1).unwrap(); + } + // TODO: check buf1 buf2 + // println!("{:x?} {:x?}", buf1, buf2); + // assert!(false); + } + #[test] + fn rev_str_ser_test() { + #[derive(Serialize)] + struct Base { + pub hello: u32, + pub base1: Base1, + } + #[derive(Serialize)] + struct Base1 { + pub hello: &'static str, + } + let mut buf1 = [0u8; MAX_SIZE]; + + { + let base = Base { + hello: 0xdeedbeef, + base1: Base1 { + hello: "Hello, World!", + }, + }; + crate::ser::to_dtb(&base, &mut [], &mut buf1).unwrap(); + } + // TODO: check buf1 buf2 + // println!("{:x?} {:x?}", buf1, buf2); + // assert!(false); + } + #[test] + fn seq_str_ser_test() { + #[derive(Serialize)] + struct Base { + pub hello: u32, + pub base1: [&'static str; 3], + } + let mut buf1 = [0u8; MAX_SIZE]; + + { + let base = Base { + hello: 0xdeedbeef, + base1: ["Hello", "World!", "Again"], + }; + crate::ser::to_dtb(&base, &mut [], &mut buf1).unwrap(); + } + // TODO: check buf1 buf2 + // println!("{:x?} {:x?}", buf1, buf2); + // assert!(false); + } + #[test] + fn node_prop_ser_test() { + #[derive(Serialize)] + struct Base { + pub hello: u32, + pub base1: Base1, + pub hello2: u32, + pub base2: Base1, + } + #[derive(Serialize)] + struct Base1 { + pub hello: &'static str, + } + let mut buf1 = [0u8; MAX_SIZE]; + + { + let base = Base { + hello: 0xdeedbeef, + base1: Base1 { + hello: "Hello, World!", + }, + hello2: 0x11223344, + base2: Base1 { hello: "Roger" }, + }; + crate::ser::to_dtb(&base, &mut [], &mut buf1).unwrap(); + } + // TODO: check buf1 buf2 + // println!("{:x?} {:x?}", buf1, buf2); + // assert!(false); + } + #[test] + fn replace_prop_ser_test() { + #[derive(Serialize)] + struct Base { + pub hello: u32, + pub base1: Base1, + pub hello2: u32, + pub base2: Base1, + } + #[derive(Serialize)] + struct Base1 { + pub hello: &'static str, + } + let mut buf1 = [0u8; MAX_SIZE]; + + { + let number = 0x55667788u32; + let patch = crate::ser::patch::Patch::new("/hello", &number as _); + let mut list = [patch]; + let base = Base { + hello: 0xdeedbeef, + base1: Base1 { + hello: "Hello, World!", + }, + hello2: 0x11223344, + base2: Base1 { hello: "Roger" }, + }; + crate::ser::to_dtb(&base, &mut list, &mut buf1).unwrap(); + } + // TODO: check buf1 buf2 + // println!("{:x?} {:x?}", buf1, buf2); + // assert!(false); + } + #[test] + fn replace_node_ser_test() { + #[derive(Serialize)] + struct Base { + pub hello: u32, + pub base1: Base1, + pub hello2: u32, + pub base2: Base1, + } + #[derive(Serialize)] + struct Base1 { + pub hello: &'static str, + } + let mut buf1 = [0u8; MAX_SIZE]; + + { + let new_base = Base1 { + hello: "replacement", + }; + let patch = crate::ser::patch::Patch::new("/hello", &new_base as _); + let mut list = [patch]; + let base = Base { + hello: 0xdeedbeef, + base1: Base1 { + hello: "Hello, World!", + }, + hello2: 0x11223344, + base2: Base1 { hello: "Roger" }, + }; + crate::ser::to_dtb(&base, &mut list, &mut buf1).unwrap(); + } + // TODO: check buf1 buf2 + // println!("{:x?} {:x?}", buf1, buf2); + // assert!(false); + } + #[test] + fn add_node_ser_test() { + #[derive(Serialize)] + struct Base { + pub hello: u32, + pub base1: Base1, + pub hello2: u32, + pub base2: Base1, + } + #[derive(Serialize)] + struct Base1 { + pub hello: &'static str, + } + let mut buf1 = [0u8; MAX_SIZE]; + + { + let new_base = Base1 { hello: "added" }; + let patch = crate::ser::patch::Patch::new("/base3", &new_base as _); + let mut list = [patch]; + let base = Base { + hello: 0xdeedbeef, + base1: Base1 { + hello: "Hello, World!", + }, + hello2: 0x11223344, + base2: Base1 { hello: "Roger" }, + }; + crate::ser::to_dtb(&base, &mut list, &mut buf1).unwrap(); + } + // TODO: check buf1 buf2 + println!("{:x?}", buf1); + assert!(false); + } +} diff --git a/src/ser/string_block.rs b/src/ser/string_block.rs index ddf59b9..579063a 100644 --- a/src/ser/string_block.rs +++ b/src/ser/string_block.rs @@ -1,18 +1,18 @@ -pub struct StringBlock<'de> { - pub end: usize, - pub data: &'de mut [u8], +pub struct StringBlock<'se> { + end: &'se mut usize, + data: &'se mut [u8], } -impl<'de> StringBlock<'de> { - pub fn new(dst: &'de mut [u8]) -> StringBlock<'de> { - StringBlock { data: dst, end: 0 } +impl<'se> StringBlock<'se> { + pub fn new(dst: &'se mut [u8], end: &'se mut usize) -> StringBlock<'se> { + StringBlock { data: dst, end } } /// Will panic when len > end /// TODO: show as error /// Return (Result String, End Offset) pub fn get_str_by_offset<'a>(&'a self, offset: usize) -> (&'a str, usize) { - if offset > self.end { + if offset > *self.end { panic!("invalid read"); } let current_slice = &self.data[offset..]; @@ -26,12 +26,12 @@ impl<'de> StringBlock<'de> { } fn insert_u8(&mut self, data: u8) { - self.data[self.end] = data; - self.end += 1; + self.data[*self.end] = data; + *self.end += 1; } /// Return the start offset of inserted string. pub fn insert_str(&mut self, name: &str) -> usize { - let result = self.end; + let result = *self.end; name.bytes().for_each(|x| { self.insert_u8(x); }); @@ -41,7 +41,7 @@ impl<'de> StringBlock<'de> { pub fn find_or_insert(&mut self, name: &str) -> usize { let mut current_pos = 0; - while current_pos < self.end { + while current_pos < *self.end { let (result, new_pos) = self.get_str_by_offset(current_pos); if result == name { return current_pos; From e388a591983917512fa19543e7bfca0d4a82c634 Mon Sep 17 00:00:00 2001 From: Woshiluo Luo Date: Mon, 24 Feb 2025 12:44:25 +0800 Subject: [PATCH 05/10] feat: add support for serialize Signed-off-by: Woshiluo Luo --- examples/serialize.rs | 36 ++++++++++++++++++++++++++++++++++++ src/common.rs | 2 +- src/ser/mod.rs | 39 ++++++++++++++++++++++++++++----------- src/ser/serializer.rs | 15 ++++++++++----- 4 files changed, 75 insertions(+), 17 deletions(-) create mode 100644 examples/serialize.rs diff --git a/examples/serialize.rs b/examples/serialize.rs new file mode 100644 index 0000000..9f0db6d --- /dev/null +++ b/examples/serialize.rs @@ -0,0 +1,36 @@ +use serde_derive::Serialize; +use std::io::prelude::*; + +const MAX_SIZE: usize = 256 + 32; + +fn main() { + #[derive(Serialize)] + struct Base { + pub hello: u32, + pub base1: Base1, + pub hello2: u32, + pub base2: Base1, + } + #[derive(Serialize)] + struct Base1 { + pub hello: &'static str, + } + let mut buf1 = [0u8; MAX_SIZE]; + + { + let new_base = Base1 { hello: "added" }; + let patch = serde_device_tree::ser::patch::Patch::new("/base3", &new_base as _); + let mut list = [patch]; + let base = Base { + hello: 0xdeedbeef, + base1: Base1 { + hello: "Hello, World!", + }, + hello2: 0x11223344, + base2: Base1 { hello: "Roger" }, + }; + serde_device_tree::ser::to_dtb(&base, &mut list, &mut buf1).unwrap(); + } + let mut file = std::fs::File::create("gen.dtb").unwrap(); + file.write_all(&buf1).unwrap(); +} diff --git a/src/common.rs b/src/common.rs index 2f99ff6..3086efd 100644 --- a/src/common.rs +++ b/src/common.rs @@ -15,7 +15,7 @@ pub(crate) struct Header { pub size_dt_struct: u32, } -const DEVICE_TREE_MAGIC: u32 = 0xD00DFEED; +pub const DEVICE_TREE_MAGIC: u32 = 0xD00DFEED; const U32_LEN: u32 = core::mem::size_of::() as _; pub(crate) const ALIGN: usize = core::mem::align_of::(); diff --git a/src/ser/mod.rs b/src/ser/mod.rs index 54e50e9..1c0712b 100644 --- a/src/ser/mod.rs +++ b/src/ser/mod.rs @@ -6,12 +6,16 @@ pub mod string_block; use crate::common::*; use crate::ser::patch::Patch; +const RSVMAP_LEN: usize = 16; + /// We do run-twice on convert, first time to generate string block, second time todo real /// structure. pub fn to_dtb<'se, T>(data: &T, list: &'se [Patch<'se>], writer: &'se mut [u8]) -> Result<(), Error> where T: serde::ser::Serialize, { + writer.iter_mut().for_each(|x| *x = 0); + let mut offset: usize = 0; { let mut dst = crate::ser::pointer::Pointer::new(None); @@ -22,24 +26,37 @@ where data.serialize(&mut ser)?; }; list.iter().for_each(|patch| patch.init()); - { - // Write from bottom to top, to avoid overlap. - for i in (0..offset).rev() { - writer[writer.len() - offset + i] = writer[i]; - writer[i] = 0; - } - // TODO: make sure no out of bound. + // Write from bottom to top, to avoid overlap. + for i in (0..offset).rev() { + writer[writer.len() - offset + i] = writer[i]; + writer[i] = 0; + } + // TODO: make sure no out of bound. - // -1 for end zero. - let (data_block, string_block) = writer.split_at_mut(writer.len() - offset); - let (_, data_block) = data_block.split_at_mut(size_of::()); + let writer_len = writer.len(); + let (data_block, string_block) = writer.split_at_mut(writer.len() - offset); + let (header, data_block) = data_block.split_at_mut(HEADER_LEN as usize + RSVMAP_LEN); + { let mut patch_list = crate::ser::patch::PatchList::new(list); let mut block = crate::ser::string_block::StringBlock::new(string_block, &mut offset); let mut dst = crate::ser::pointer::Pointer::new(Some(data_block)); let mut ser = crate::ser::serializer::Serializer::new(&mut dst, &mut block, &mut patch_list); - ser.dst.step_by_u32(FDT_END); data.serialize(&mut ser)?; + ser.dst.step_by_u32(FDT_END); + } + { + let header = unsafe { &mut *(header.as_mut_ptr() as *mut Header) }; + header.magic = u32::from_be(DEVICE_TREE_MAGIC); + header.total_size = u32::from_be(writer_len as u32); + header.off_dt_struct = u32::from_be(HEADER_LEN + RSVMAP_LEN as u32); + header.off_dt_strings = u32::from_be((writer_len - offset) as u32); + header.off_mem_rsvmap = u32::from_be(HEADER_LEN); + header.version = u32::from_be(SUPPORTED_VERSION); + header.last_comp_version = u32::from_be(SUPPORTED_VERSION); // TODO: maybe 16 + header.boot_cpuid_phys = 0; // TODO: wtf is this prop + header.size_dt_strings = u32::from_be(offset as u32); + header.size_dt_struct = u32::from_be(data_block.len() as u32); // TODO: correct? } Ok(()) } diff --git a/src/ser/serializer.rs b/src/ser/serializer.rs index 008b62f..180382c 100644 --- a/src/ser/serializer.rs +++ b/src/ser/serializer.rs @@ -14,6 +14,7 @@ pub struct Serializer<'se> { pub dst: &'se mut Pointer<'se>, string_block: &'se mut StringBlock<'se>, value_type: ValueType, + current_name: &'se str, current_dep: usize, patch_list: &'se mut PatchList<'se>, } @@ -28,6 +29,7 @@ impl<'se> Serializer<'se> { dst, string_block: cache, current_dep: 0, + current_name: "", value_type: ValueType::Node, patch_list, } @@ -46,8 +48,10 @@ impl<'a, 'se> SerializeDynamicField<'se> for &'a mut Serializer<'se> { T: serde::ser::Serialize + ?Sized, { let prop_header_offset = self.dst.step_by_prop(); - let old_value_type = self.value_type; + let prev_type = self.value_type; + let prev_name = self.current_name; self.current_dep += 1; + self.current_name = key; let matched_patch = self.patch_list.step_forward(key, self.current_dep); match matched_patch { @@ -75,7 +79,8 @@ impl<'a, 'se> SerializeDynamicField<'se> for &'a mut Serializer<'se> { ); } - self.value_type = old_value_type; + self.value_type = prev_type; + self.current_name = prev_name; self.dst.step_align(); self.patch_list.step_back(self.current_dep); self.current_dep -= 1; @@ -373,7 +378,7 @@ impl<'a, 'se> serde::ser::Serializer for &'a mut Serializer<'se> { fn serialize_struct( self, - name: &'static str, + _name: &'static str, _len: usize, ) -> Result { self.dst.step_by_u32(FDT_BEGIN_NODE); @@ -381,7 +386,7 @@ impl<'a, 'se> serde::ser::Serializer for &'a mut Serializer<'se> { // The name of root node should be empty. self.dst.step_by_u32(0); } else { - self.dst.step_by_name(name); + self.dst.step_by_name(self.current_name); } self.value_type = ValueType::Node; Ok(self) @@ -401,7 +406,7 @@ impl<'a, 'se> serde::ser::Serializer for &'a mut Serializer<'se> { #[cfg(test)] mod tests { use serde_derive::Serialize; - const MAX_SIZE: usize = 256; + const MAX_SIZE: usize = 256 + 32; #[test] fn base_ser_test() { #[derive(Serialize)] From 2b09d12783d95255bebcaf65c6765c624211c2d6 Mon Sep 17 00:00:00 2001 From: Woshiluo Luo Date: Mon, 24 Feb 2025 12:59:59 +0800 Subject: [PATCH 06/10] fix: rustfmt Signed-off-by: Woshiluo Luo --- examples/qemu-virt.rs | 3 ++- rustfmt.toml | 4 ++++ src/de_mut/cursor.rs | 2 +- src/de_mut/data.rs | 4 ++-- src/de_mut/mod.rs | 4 ++-- src/de_mut/node.rs | 6 +++--- src/de_mut/node_seq.rs | 2 +- src/de_mut/reg.rs | 2 +- src/de_mut/structs.rs | 4 ++-- src/lib.rs | 2 +- src/ser/serializer.rs | 6 +++--- src/utils/mod.rs | 3 ++- src/value/compatible.rs | 2 +- tests/qemu-virt.rs | 3 ++- 14 files changed, 27 insertions(+), 20 deletions(-) create mode 100644 rustfmt.toml diff --git a/examples/qemu-virt.rs b/examples/qemu-virt.rs index dd3acd9..dbfcff1 100644 --- a/examples/qemu-virt.rs +++ b/examples/qemu-virt.rs @@ -11,9 +11,10 @@ use serde_derive::Deserialize; // - `NodeSeq`: name@... 区分的一组同级同类的连续节点,这个类型要求可变的内存。 // - `StrSeq`: '\0' 分隔的一组字符串,设备树中一种常见的属性类型,这个类型要求可变的内存。 use serde_device_tree::{ + Dtb, DtbPtr, buildin::{Node, NodeSeq, Reg, StrSeq}, error::Error, - from_raw_mut, Dtb, DtbPtr, + from_raw_mut, }; const RAW_DEVICE_TREE: &[u8] = include_bytes!("qemu-virt.dtb"); diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..7a255b9 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,4 @@ +# Use rustfmt to format code + +edition = "2024" +# Empty file. diff --git a/src/de_mut/cursor.rs b/src/de_mut/cursor.rs index d0dca23..fecd8a6 100644 --- a/src/de_mut/cursor.rs +++ b/src/de_mut/cursor.rs @@ -1,4 +1,4 @@ -use super::{DtError, RefDtb, StructureBlock, BLOCK_LEN}; +use super::{BLOCK_LEN, DtError, RefDtb, StructureBlock}; use core::marker::PhantomData; #[derive(Clone, Copy, Debug)] diff --git a/src/de_mut/data.rs b/src/de_mut/data.rs index e4053ae..9cf062c 100644 --- a/src/de_mut/data.rs +++ b/src/de_mut/data.rs @@ -1,9 +1,9 @@ -use super::cursor::MultiNodeCursor; +use super::cursor::MultiNodeCursor; use super::{BodyCursor, Cursor}; use super::{DtError, PropCursor, RefDtb, RegConfig}; use core::marker::PhantomData; -use serde::{de, Deserialize}; +use serde::{Deserialize, de}; #[derive(Clone, Copy, Debug)] pub(super) enum ValueCursor { diff --git a/src/de_mut/mod.rs b/src/de_mut/mod.rs index 2e310a3..1d2a475 100644 --- a/src/de_mut/mod.rs +++ b/src/de_mut/mod.rs @@ -1,4 +1,4 @@ -//! Deserialize device tree data to a Rust data structure, +//! Deserialize device tree data to a Rust data structure, //! the memory region contains dtb file should be mutable. use crate::error::Error as DtError; @@ -26,7 +26,7 @@ use cursor::{BodyCursor, Cursor, PropCursor}; use data::{ValueCursor, ValueDeserializer}; use reg::RegConfig; use struct_access::{StructAccess, StructAccessType, Temp}; -use structs::{RefDtb, StructureBlock, BLOCK_LEN}; +use structs::{BLOCK_LEN, RefDtb, StructureBlock}; /// 从 [`RefDtb`] 反序列化一个描述设备树的 `T` 类型实例。 /// diff --git a/src/de_mut/node.rs b/src/de_mut/node.rs index 2ff632f..57f0da0 100644 --- a/src/de_mut/node.rs +++ b/src/de_mut/node.rs @@ -1,8 +1,8 @@ -use super::{BodyCursor, Cursor, PropCursor, RefDtb, RegConfig, ValueCursor, ValueDeserializer}; +use super::{BodyCursor, Cursor, PropCursor, RefDtb, RegConfig, ValueCursor, ValueDeserializer}; use core::fmt::Debug; use core::marker::PhantomData; use serde::de::MapAccess; -use serde::{de, Deserialize}; +use serde::{Deserialize, de}; // TODO: Spec 2.3.5 said that we should not inherited from ancestors and the size-cell & // address-cells should only used for current node's children. @@ -293,7 +293,7 @@ impl<'de> PropItem<'de> { #[cfg(test)] mod tests { - use crate::{buildin::Node, from_raw_mut, Dtb, DtbPtr}; + use crate::{Dtb, DtbPtr, buildin::Node, from_raw_mut}; const RAW_DEVICE_TREE: &[u8] = include_bytes!("../../examples/hifive-unmatched-a00.dtb"); const BUFFER_SIZE: usize = RAW_DEVICE_TREE.len(); #[repr(align(8))] diff --git a/src/de_mut/node_seq.rs b/src/de_mut/node_seq.rs index 1247803..b7b58c7 100644 --- a/src/de_mut/node_seq.rs +++ b/src/de_mut/node_seq.rs @@ -1,7 +1,7 @@ use super::{BodyCursor, Cursor, RefDtb, RegConfig, ValueCursor, ValueDeserializer}; use core::{fmt::Debug, marker::PhantomData}; use serde::de::SeqAccess; -use serde::{de, Deserialize}; +use serde::{Deserialize, de}; /// 一组名字以 `@...` 区分,同类、同级且连续的节点的映射。 /// diff --git a/src/de_mut/reg.rs b/src/de_mut/reg.rs index b29cb93..20eeb0b 100644 --- a/src/de_mut/reg.rs +++ b/src/de_mut/reg.rs @@ -1,4 +1,4 @@ -use super::{PropCursor, RefDtb, ValueCursor, BLOCK_LEN}; +use super::{BLOCK_LEN, PropCursor, RefDtb, ValueCursor}; use core::{fmt::Debug, ops::Range}; use serde::Deserialize; diff --git a/src/de_mut/structs.rs b/src/de_mut/structs.rs index b31d038..48b3e3f 100644 --- a/src/de_mut/structs.rs +++ b/src/de_mut/structs.rs @@ -1,5 +1,5 @@ -use crate::{ - common::{Header, ALIGN}, +use crate::{ + common::{ALIGN, Header}, error::Error as DtError, }; use core::{cell::RefCell, fmt::Display}; diff --git a/src/lib.rs b/src/lib.rs index 42eefee..b7aeadc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,7 +34,7 @@ pub use value::compatible::Compatible; pub use de::from_raw; #[doc(inline)] -pub use de_mut::{buildin, from_raw_mut, Dtb, DtbPtr}; +pub use de_mut::{Dtb, DtbPtr, buildin, from_raw_mut}; #[doc(inline)] pub use error::Result; diff --git a/src/ser/serializer.rs b/src/ser/serializer.rs index 180382c..43e09fc 100644 --- a/src/ser/serializer.rs +++ b/src/ser/serializer.rs @@ -1,7 +1,7 @@ +use super::Error; use super::patch::PatchList; use super::pointer::Pointer; use super::string_block::StringBlock; -use super::Error; use crate::common::*; #[derive(Clone, Copy)] @@ -619,7 +619,7 @@ mod tests { crate::ser::to_dtb(&base, &mut list, &mut buf1).unwrap(); } // TODO: check buf1 buf2 - println!("{:x?}", buf1); - assert!(false); + // println!("{:x?}", buf1); + // assert!(false); } } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index c71c673..beaf1c1 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -70,8 +70,9 @@ impl<'de> Node<'de> { #[cfg(test)] mod tests { use crate::{ + Dtb, DtbPtr, buildin::{Node, StrSeq}, - from_raw_mut, Dtb, DtbPtr, + from_raw_mut, }; const RAW_DEVICE_TREE: &[u8] = include_bytes!("../../examples/hifive-unmatched-a00.dtb"); const BUFFER_SIZE: usize = RAW_DEVICE_TREE.len(); diff --git a/src/value/compatible.rs b/src/value/compatible.rs index 3102e45..a9de660 100644 --- a/src/value/compatible.rs +++ b/src/value/compatible.rs @@ -1,5 +1,5 @@ use core::{fmt, marker::PhantomData}; -use serde::{de::Visitor, Deserialize}; +use serde::{Deserialize, de::Visitor}; /// Field representing compatability of a certain device in the tree. /// diff --git a/tests/qemu-virt.rs b/tests/qemu-virt.rs index 0fdc5ad..43c15b3 100644 --- a/tests/qemu-virt.rs +++ b/tests/qemu-virt.rs @@ -2,9 +2,10 @@ use serde_derive::Deserialize; use serde_device_tree::{ + Dtb, DtbPtr, buildin::{NodeSeq, Reg}, error::Error, - from_raw_mut, Dtb, DtbPtr, + from_raw_mut, }; const RAW_DEVICE_TREE: &[u8] = include_bytes!("../examples/qemu-virt.dtb"); From 32f3a1e347b66e73709e4cd4c681c290889ad9a8 Mon Sep 17 00:00:00 2001 From: Woshiluo Luo Date: Mon, 24 Feb 2025 13:06:03 +0800 Subject: [PATCH 07/10] fix: clippy Signed-off-by: Woshiluo Luo --- examples/serialize.rs | 4 ++-- src/de.rs | 36 +++++++++++++++++++----------------- src/de_mut/node_seq.rs | 2 +- src/ser/patch.rs | 9 +++------ src/ser/pointer.rs | 24 ++++++++---------------- src/ser/serializer.rs | 38 +++++++++++++++++++------------------- src/ser/string_block.rs | 2 +- src/utils/chosen.rs | 2 +- tests/bl808.rs | 2 +- 9 files changed, 55 insertions(+), 64 deletions(-) diff --git a/examples/serialize.rs b/examples/serialize.rs index 9f0db6d..d046307 100644 --- a/examples/serialize.rs +++ b/examples/serialize.rs @@ -20,7 +20,7 @@ fn main() { { let new_base = Base1 { hello: "added" }; let patch = serde_device_tree::ser::patch::Patch::new("/base3", &new_base as _); - let mut list = [patch]; + let list = [patch]; let base = Base { hello: 0xdeedbeef, base1: Base1 { @@ -29,7 +29,7 @@ fn main() { hello2: 0x11223344, base2: Base1 { hello: "Roger" }, }; - serde_device_tree::ser::to_dtb(&base, &mut list, &mut buf1).unwrap(); + serde_device_tree::ser::to_dtb(&base, &list, &mut buf1).unwrap(); } let mut file = std::fs::File::create("gen.dtb").unwrap(); file.write_all(&buf1).unwrap(); diff --git a/src/de.rs b/src/de.rs index 93b9c1a..3efd43d 100644 --- a/src/de.rs +++ b/src/de.rs @@ -68,23 +68,25 @@ pub unsafe fn from_raw<'de, T>(ptr: *const u8) -> Result where T: de::Deserialize<'de>, { - // read header - if (ptr as usize) & (ALIGN - 1) != 0 { - return Err(Error::unaligned(ptr as usize)); - } - let header = &*(ptr as *const Header); - header.verify()?; - - let total_size = u32::from_be(header.total_size); - let raw_data_len = (total_size - HEADER_LEN) as usize; - let ans_ptr = core::ptr::from_raw_parts(ptr, raw_data_len); - let device_tree: &DeviceTree = &*ans_ptr; - let tags = device_tree.tags(); - let mut d = Deserializer { - tags: tags.peekable(), - }; - let ret = T::deserialize(&mut d)?; - Ok(ret) + unsafe { + // read header + if (ptr as usize) & (ALIGN - 1) != 0 { + return Err(Error::unaligned(ptr as usize)); + } + let header = &*(ptr as *const Header); + header.verify()?; + + let total_size = u32::from_be(header.total_size); + let raw_data_len = (total_size - HEADER_LEN) as usize; + let ans_ptr = core::ptr::from_raw_parts(ptr, raw_data_len); + let device_tree: &DeviceTree = &*ans_ptr; + let tags = device_tree.tags(); + let mut d = Deserializer { + tags: tags.peekable(), + }; + let ret = T::deserialize(&mut d)?; + Ok(ret) + } } #[derive(Debug)] diff --git a/src/de_mut/node_seq.rs b/src/de_mut/node_seq.rs index b7b58c7..4e63e62 100644 --- a/src/de_mut/node_seq.rs +++ b/src/de_mut/node_seq.rs @@ -177,7 +177,7 @@ impl<'de> NodeSeqItem<'de> { #[cfg(test)] mod tests { use crate::buildin::{NodeSeq, Reg}; - use crate::{from_raw_mut, Dtb, DtbPtr}; + use crate::{Dtb, DtbPtr, from_raw_mut}; use serde_derive::Deserialize; const RAW_DEVICE_TREE: &[u8] = include_bytes!("../../examples/bl808.dtb"); diff --git a/src/ser/patch.rs b/src/ser/patch.rs index e99744d..80d05ae 100644 --- a/src/ser/patch.rs +++ b/src/ser/patch.rs @@ -31,10 +31,7 @@ impl<'se> Patch<'se> { if x == 0 { return ""; } - match self.name.split('/').nth(x) { - Some(result) => result, - None => "", - } + self.name.split('/').nth(x).unwrap_or_default() } // I hope to impl serde::ser::Serializer, but erase_serialize's return value is different from @@ -62,7 +59,7 @@ impl<'se> PatchList<'se> { if patch.matched_depth.get() == depth - 1 && patch.get_depth_path(depth) == name { patch.matched_depth.set(patch.matched_depth.get() + 1); if patch.get_depth() == depth { - if let Some(_) = matched_patch { + if matched_patch.is_some() { panic!("More than one replace data on a same path"); } matched_patch = Some(patch); @@ -82,7 +79,7 @@ impl<'se> PatchList<'se> { pub fn add_list(&self, depth: usize) -> impl Iterator> + use<'se> { self.list.iter().filter(move |x| { - x.matched_depth.get() == depth && x.get_depth() == depth + 1 && x.parsed.get() == false + x.matched_depth.get() == depth && x.get_depth() == depth + 1 && !x.parsed.get() }) } } diff --git a/src/ser/pointer.rs b/src/ser/pointer.rs index 03fba7b..45871e6 100644 --- a/src/ser/pointer.rs +++ b/src/ser/pointer.rs @@ -26,11 +26,8 @@ impl<'se> Pointer<'se> { #[inline(always)] pub fn write_to_offset_u32(&mut self, offset: usize, value: u32) { - match self.data { - Some(ref mut data) => { - data[offset..offset + 4].copy_from_slice(&u32::to_be_bytes(value)) - } - None => {} + if let Some(ref mut data) = self.data { + data[offset..offset + 4].copy_from_slice(&u32::to_be_bytes(value)) } } @@ -50,20 +47,16 @@ impl<'se> Pointer<'se> { #[inline(always)] pub fn step_by_u32(&mut self, value: u32) { - match self.data { - Some(ref mut data) => { - data[self.offset..self.offset + 4].copy_from_slice(&u32::to_be_bytes(value)) - } - None => {} + if let Some(ref mut data) = self.data { + data[self.offset..self.offset + 4].copy_from_slice(&u32::to_be_bytes(value)) } self.step_by_len(4); } #[inline(always)] pub fn step_by_u8(&mut self, value: u8) { - match self.data { - Some(ref mut data) => data[self.offset] = value, - None => {} + if let Some(ref mut data) = self.data { + data[self.offset] = value } self.step_by_len(1); } @@ -71,9 +64,8 @@ impl<'se> Pointer<'se> { #[inline(always)] pub fn step_align(&mut self) { while self.offset % 4 != 0 { - match self.data { - Some(ref mut data) => data[self.offset] = 0, - None => {} + if let Some(ref mut data) = self.data { + data[self.offset] = 0 } self.offset += 1; } diff --git a/src/ser/serializer.rs b/src/ser/serializer.rs index 43e09fc..b3da307 100644 --- a/src/ser/serializer.rs +++ b/src/ser/serializer.rs @@ -42,7 +42,7 @@ trait SerializeDynamicField<'se> { T: serde::ser::Serialize + ?Sized; } -impl<'a, 'se> SerializeDynamicField<'se> for &'a mut Serializer<'se> { +impl<'se> SerializeDynamicField<'se> for &mut Serializer<'se> { fn serialize_dynamic_field(&mut self, key: &'se str, value: &T) -> Result<(), Error> where T: serde::ser::Serialize + ?Sized, @@ -56,7 +56,7 @@ impl<'a, 'se> SerializeDynamicField<'se> for &'a mut Serializer<'se> { match matched_patch { Some(data) => { - data.serialize(&mut **self); + data.serialize(self); } None => { value.serialize(&mut **self)?; @@ -89,7 +89,7 @@ impl<'a, 'se> SerializeDynamicField<'se> for &'a mut Serializer<'se> { } } -impl<'a, 'se> serde::ser::SerializeMap for &'a mut Serializer<'se> { +impl serde::ser::SerializeMap for &mut Serializer<'_> { type Ok = (); type Error = Error; @@ -112,7 +112,7 @@ impl<'a, 'se> serde::ser::SerializeMap for &'a mut Serializer<'se> { } } -impl<'a, 'se> serde::ser::SerializeStruct for &'a mut Serializer<'se> { +impl serde::ser::SerializeStruct for &mut Serializer<'_> { type Ok = (); type Error = Error; @@ -135,7 +135,7 @@ impl<'a, 'se> serde::ser::SerializeStruct for &'a mut Serializer<'se> { } } -impl<'a, 'se> serde::ser::SerializeStructVariant for &'a mut Serializer<'se> { +impl serde::ser::SerializeStructVariant for &mut Serializer<'_> { type Ok = (); type Error = Error; @@ -151,7 +151,7 @@ impl<'a, 'se> serde::ser::SerializeStructVariant for &'a mut Serializer<'se> { } } -impl<'a, 'se> serde::ser::SerializeSeq for &'a mut Serializer<'se> { +impl serde::ser::SerializeSeq for &mut Serializer<'_> { type Ok = (); type Error = Error; // TODO: make sure there are no node seq serialize over this function. @@ -168,7 +168,7 @@ impl<'a, 'se> serde::ser::SerializeSeq for &'a mut Serializer<'se> { } } -impl<'a, 'se> serde::ser::SerializeTuple for &'a mut Serializer<'se> { +impl serde::ser::SerializeTuple for &mut Serializer<'_> { type Ok = (); type Error = Error; @@ -185,7 +185,7 @@ impl<'a, 'se> serde::ser::SerializeTuple for &'a mut Serializer<'se> { } } -impl<'a, 'se> serde::ser::SerializeTupleVariant for &'a mut Serializer<'se> { +impl serde::ser::SerializeTupleVariant for &mut Serializer<'_> { type Ok = (); type Error = Error; @@ -201,7 +201,7 @@ impl<'a, 'se> serde::ser::SerializeTupleVariant for &'a mut Serializer<'se> { } } -impl<'a, 'se> serde::ser::SerializeTupleStruct for &'a mut Serializer<'se> { +impl serde::ser::SerializeTupleStruct for &mut Serializer<'_> { type Ok = (); type Error = Error; @@ -217,7 +217,7 @@ impl<'a, 'se> serde::ser::SerializeTupleStruct for &'a mut Serializer<'se> { } } -impl<'a, 'se> serde::ser::Serializer for &'a mut Serializer<'se> { +impl serde::ser::Serializer for &mut Serializer<'_> { type Ok = (); type Error = Error; type SerializeSeq = Self; @@ -417,7 +417,7 @@ mod tests { { let base = Base { hello: 0xdeedbeef }; - crate::ser::to_dtb(&base, &mut [], &mut buf1).unwrap(); + crate::ser::to_dtb(&base, &[], &mut buf1).unwrap(); } // TODO: check buf1 buf2 } @@ -439,7 +439,7 @@ mod tests { hello: 0xdeedbeef, base1: Base1 { hello: 0x10000001 }, }; - crate::ser::to_dtb(&base, &mut [], &mut buf1).unwrap(); + crate::ser::to_dtb(&base, &[], &mut buf1).unwrap(); } // TODO: check buf1 buf2 // println!("{:x?} {:x?}", buf1, buf2); @@ -465,7 +465,7 @@ mod tests { hello: "Hello, World!", }, }; - crate::ser::to_dtb(&base, &mut [], &mut buf1).unwrap(); + crate::ser::to_dtb(&base, &[], &mut buf1).unwrap(); } // TODO: check buf1 buf2 // println!("{:x?} {:x?}", buf1, buf2); @@ -539,7 +539,7 @@ mod tests { { let number = 0x55667788u32; let patch = crate::ser::patch::Patch::new("/hello", &number as _); - let mut list = [patch]; + let list = [patch]; let base = Base { hello: 0xdeedbeef, base1: Base1 { @@ -548,7 +548,7 @@ mod tests { hello2: 0x11223344, base2: Base1 { hello: "Roger" }, }; - crate::ser::to_dtb(&base, &mut list, &mut buf1).unwrap(); + crate::ser::to_dtb(&base, &list, &mut buf1).unwrap(); } // TODO: check buf1 buf2 // println!("{:x?} {:x?}", buf1, buf2); @@ -574,7 +574,7 @@ mod tests { hello: "replacement", }; let patch = crate::ser::patch::Patch::new("/hello", &new_base as _); - let mut list = [patch]; + let list = [patch]; let base = Base { hello: 0xdeedbeef, base1: Base1 { @@ -583,7 +583,7 @@ mod tests { hello2: 0x11223344, base2: Base1 { hello: "Roger" }, }; - crate::ser::to_dtb(&base, &mut list, &mut buf1).unwrap(); + crate::ser::to_dtb(&base, &list, &mut buf1).unwrap(); } // TODO: check buf1 buf2 // println!("{:x?} {:x?}", buf1, buf2); @@ -607,7 +607,7 @@ mod tests { { let new_base = Base1 { hello: "added" }; let patch = crate::ser::patch::Patch::new("/base3", &new_base as _); - let mut list = [patch]; + let list = [patch]; let base = Base { hello: 0xdeedbeef, base1: Base1 { @@ -616,7 +616,7 @@ mod tests { hello2: 0x11223344, base2: Base1 { hello: "Roger" }, }; - crate::ser::to_dtb(&base, &mut list, &mut buf1).unwrap(); + crate::ser::to_dtb(&base, &list, &mut buf1).unwrap(); } // TODO: check buf1 buf2 // println!("{:x?}", buf1); diff --git a/src/ser/string_block.rs b/src/ser/string_block.rs index 579063a..e589e70 100644 --- a/src/ser/string_block.rs +++ b/src/ser/string_block.rs @@ -11,7 +11,7 @@ impl<'se> StringBlock<'se> { /// Will panic when len > end /// TODO: show as error /// Return (Result String, End Offset) - pub fn get_str_by_offset<'a>(&'a self, offset: usize) -> (&'a str, usize) { + pub fn get_str_by_offset(&self, offset: usize) -> (&str, usize) { if offset > *self.end { panic!("invalid read"); } diff --git a/src/utils/chosen.rs b/src/utils/chosen.rs index 52170bb..5afd6e6 100644 --- a/src/utils/chosen.rs +++ b/src/utils/chosen.rs @@ -38,7 +38,7 @@ impl<'de> Node<'de> { #[cfg(test)] mod tests { - use crate::{buildin::Node, from_raw_mut, Dtb, DtbPtr}; + use crate::{Dtb, DtbPtr, buildin::Node, from_raw_mut}; const RAW_DEVICE_TREE: &[u8] = include_bytes!("../../examples/bl808.dtb"); const BUFFER_SIZE: usize = RAW_DEVICE_TREE.len(); diff --git a/tests/bl808.rs b/tests/bl808.rs index 3eaac1d..33afb63 100644 --- a/tests/bl808.rs +++ b/tests/bl808.rs @@ -1,7 +1,7 @@ // 在实际使用中,将这里的 `serde_derive::Deserialize` 改为 `serde::Deserialize`。 use serde_derive::Deserialize; -use serde_device_tree::{buildin::NodeSeq, error::Error, from_raw_mut, Dtb, DtbPtr}; +use serde_device_tree::{Dtb, DtbPtr, buildin::NodeSeq, error::Error, from_raw_mut}; const RAW_DEVICE_TREE: &[u8] = include_bytes!("../examples/bl808.dtb"); const BUFFER_SIZE: usize = RAW_DEVICE_TREE.len(); From 6fff089bc45b46d6e66fde10bb75b63978fd2e9e Mon Sep 17 00:00:00 2001 From: Woshiluo Luo Date: Mon, 24 Feb 2025 13:09:37 +0800 Subject: [PATCH 08/10] feat: inline always hint for some method Signed-off-by: Woshiluo Luo --- src/ser/patch.rs | 9 +++++++++ src/ser/serializer.rs | 1 + src/ser/string_block.rs | 6 ++++++ 3 files changed, 16 insertions(+) diff --git a/src/ser/patch.rs b/src/ser/patch.rs index 80d05ae..df26a1b 100644 --- a/src/ser/patch.rs +++ b/src/ser/patch.rs @@ -9,6 +9,7 @@ pub struct Patch<'se> { } impl<'se> Patch<'se> { + #[inline(always)] pub fn new(name: &'se str, data: &'se dyn erased_serde::Serialize) -> Patch<'se> { Patch { name, @@ -18,15 +19,18 @@ impl<'se> Patch<'se> { } } + #[inline(always)] pub fn init(&self) { self.matched_depth.set(0); self.parsed.set(false); } + #[inline(always)] pub fn get_depth(&self) -> usize { self.name.split('/').count() - 1 } + #[inline(always)] pub fn get_depth_path(&self, x: usize) -> &'se str { if x == 0 { return ""; @@ -36,6 +40,7 @@ impl<'se> Patch<'se> { // I hope to impl serde::ser::Serializer, but erase_serialize's return value is different from // normal serialize, so we do this. + #[inline(always)] pub fn serialize(&self, serializer: &mut Serializer<'se>) { self.parsed.set(true); self.data @@ -49,10 +54,12 @@ pub struct PatchList<'se> { } impl<'se> PatchList<'se> { + #[inline(always)] pub fn new(list: &'se [Patch<'se>]) -> PatchList<'se> { PatchList { list } } + #[inline(always)] pub fn step_forward(&self, name: &'se str, depth: usize) -> Option<&'se Patch<'se>> { let mut matched_patch = None; self.list.iter().for_each(|patch| { @@ -69,6 +76,7 @@ impl<'se> PatchList<'se> { matched_patch } + #[inline(always)] pub fn step_back(&self, depth: usize) { self.list.iter().for_each(|patch| { if patch.matched_depth.get() == depth { @@ -77,6 +85,7 @@ impl<'se> PatchList<'se> { }); } + #[inline(always)] pub fn add_list(&self, depth: usize) -> impl Iterator> + use<'se> { self.list.iter().filter(move |x| { x.matched_depth.get() == depth && x.get_depth() == depth + 1 && !x.parsed.get() diff --git a/src/ser/serializer.rs b/src/ser/serializer.rs index b3da307..33f4755 100644 --- a/src/ser/serializer.rs +++ b/src/ser/serializer.rs @@ -20,6 +20,7 @@ pub struct Serializer<'se> { } impl<'se> Serializer<'se> { + #[inline(always)] pub fn new( dst: &'se mut Pointer<'se>, cache: &'se mut StringBlock<'se>, diff --git a/src/ser/string_block.rs b/src/ser/string_block.rs index e589e70..39324ef 100644 --- a/src/ser/string_block.rs +++ b/src/ser/string_block.rs @@ -4,6 +4,7 @@ pub struct StringBlock<'se> { } impl<'se> StringBlock<'se> { + #[inline(always)] pub fn new(dst: &'se mut [u8], end: &'se mut usize) -> StringBlock<'se> { StringBlock { data: dst, end } } @@ -11,6 +12,7 @@ impl<'se> StringBlock<'se> { /// Will panic when len > end /// TODO: show as error /// Return (Result String, End Offset) + #[inline(always)] pub fn get_str_by_offset(&self, offset: usize) -> (&str, usize) { if offset > *self.end { panic!("invalid read"); @@ -25,11 +27,14 @@ impl<'se> StringBlock<'se> { (result, pos + offset + 1) } + #[inline(always)] fn insert_u8(&mut self, data: u8) { self.data[*self.end] = data; *self.end += 1; } + /// Return the start offset of inserted string. + #[inline(always)] pub fn insert_str(&mut self, name: &str) -> usize { let result = *self.end; name.bytes().for_each(|x| { @@ -39,6 +44,7 @@ impl<'se> StringBlock<'se> { result } + #[inline(always)] pub fn find_or_insert(&mut self, name: &str) -> usize { let mut current_pos = 0; while current_pos < *self.end { From 9bc3c291f0a3022005ead0ae35c4f8796c0a41d9 Mon Sep 17 00:00:00 2001 From: Woshiluo Luo Date: Mon, 24 Feb 2025 22:13:58 +0800 Subject: [PATCH 09/10] docs: add docs for patch and string_block Signed-off-by: Woshiluo Luo --- src/ser/mod.rs | 3 +++ src/ser/patch.rs | 12 +++++++++++- src/ser/serializer.rs | 33 +++++++++++++++++++++------------ src/ser/string_block.rs | 14 +++++++++++--- 4 files changed, 46 insertions(+), 16 deletions(-) diff --git a/src/ser/mod.rs b/src/ser/mod.rs index 1c0712b..d7e899c 100644 --- a/src/ser/mod.rs +++ b/src/ser/mod.rs @@ -8,6 +8,8 @@ use crate::ser::patch::Patch; const RSVMAP_LEN: usize = 16; +/// Serialize the data to dtb, with a list fof Patch, write to the `writer`. +/// /// We do run-twice on convert, first time to generate string block, second time todo real /// structure. pub fn to_dtb<'se, T>(data: &T, list: &'se [Patch<'se>], writer: &'se mut [u8]) -> Result<(), Error> @@ -45,6 +47,7 @@ where data.serialize(&mut ser)?; ser.dst.step_by_u32(FDT_END); } + // Make header { let header = unsafe { &mut *(header.as_mut_ptr() as *mut Header) }; header.magic = u32::from_be(DEVICE_TREE_MAGIC); diff --git a/src/ser/patch.rs b/src/ser/patch.rs index df26a1b..8210180 100644 --- a/src/ser/patch.rs +++ b/src/ser/patch.rs @@ -1,10 +1,15 @@ use super::serializer::Serializer; use core::cell::Cell; +/// Since this crate is mostly work with `noalloc`, we use `Patch` and `PatchList` for change or +/// add on a dtb. pub struct Patch<'se> { - name: &'se str, pub data: &'se dyn erased_serde::Serialize, + name: &'se str, + + /// This patch match how many item between its path and serializer. matched_depth: Cell, + /// Show this patch have been parsed. parsed: Cell, } @@ -20,6 +25,7 @@ impl<'se> Patch<'se> { } #[inline(always)] + /// Reset the status of patch. pub fn init(&self) { self.matched_depth.set(0); self.parsed.set(false); @@ -40,6 +46,7 @@ impl<'se> Patch<'se> { // I hope to impl serde::ser::Serializer, but erase_serialize's return value is different from // normal serialize, so we do this. + /// Serialize this patch with serializer. #[inline(always)] pub fn serialize(&self, serializer: &mut Serializer<'se>) { self.parsed.set(true); @@ -49,6 +56,7 @@ impl<'se> Patch<'se> { } } +/// Here is a list of `Patch`, and have some methods for update `Patch` status. pub struct PatchList<'se> { list: &'se [Patch<'se>], } @@ -86,6 +94,8 @@ impl<'se> PatchList<'se> { } #[inline(always)] + /// Return a list which is on this level, but haven't been parsed, which usually means this + /// patch is for adding. pub fn add_list(&self, depth: usize) -> impl Iterator> + use<'se> { self.list.iter().filter(move |x| { x.matched_depth.get() == depth && x.get_depth() == depth + 1 && !x.parsed.get() diff --git a/src/ser/serializer.rs b/src/ser/serializer.rs index 33f4755..a8c6630 100644 --- a/src/ser/serializer.rs +++ b/src/ser/serializer.rs @@ -5,18 +5,23 @@ use super::string_block::StringBlock; use crate::common::*; #[derive(Clone, Copy)] +// The enum for current parsing type. enum ValueType { Node, Prop, } +/// Serializer +/// - `dst`: Pointer of distance &[u8] and the ref of &[u8]. +/// - `current_value_type`, `current_name`, `current_dep`: For recursive. pub struct Serializer<'se> { pub dst: &'se mut Pointer<'se>, string_block: &'se mut StringBlock<'se>, - value_type: ValueType, + patch_list: &'se mut PatchList<'se>, + + current_value_type: ValueType, current_name: &'se str, current_dep: usize, - patch_list: &'se mut PatchList<'se>, } impl<'se> Serializer<'se> { @@ -31,7 +36,7 @@ impl<'se> Serializer<'se> { string_block: cache, current_dep: 0, current_name: "", - value_type: ValueType::Node, + current_value_type: ValueType::Node, patch_list, } } @@ -49,7 +54,9 @@ impl<'se> SerializeDynamicField<'se> for &mut Serializer<'se> { T: serde::ser::Serialize + ?Sized, { let prop_header_offset = self.dst.step_by_prop(); - let prev_type = self.value_type; + + // Save prev + let prev_type = self.current_value_type; let prev_name = self.current_name; self.current_dep += 1; self.current_name = key; @@ -66,7 +73,7 @@ impl<'se> SerializeDynamicField<'se> for &mut Serializer<'se> { // We now know how long the prop value. // TODO: make we have some better way than put nop, like move this block ahead. - if let ValueType::Node = self.value_type { + if let ValueType::Node = self.current_value_type { self.dst .write_to_offset_u32(prop_header_offset - 4, FDT_NOP); } else { @@ -80,10 +87,12 @@ impl<'se> SerializeDynamicField<'se> for &mut Serializer<'se> { ); } - self.value_type = prev_type; - self.current_name = prev_name; self.dst.step_align(); + + // Load prev self.patch_list.step_back(self.current_dep); + self.current_value_type = prev_type; + self.current_name = prev_name; self.current_dep -= 1; Ok(()) @@ -258,7 +267,7 @@ impl serde::ser::Serializer for &mut Serializer<'_> { } fn serialize_u32(self, v: u32) -> Result { - self.value_type = ValueType::Prop; + self.current_value_type = ValueType::Prop; self.dst.step_by_u32(v); Ok(()) } @@ -280,7 +289,7 @@ impl serde::ser::Serializer for &mut Serializer<'_> { } fn serialize_str(self, v: &str) -> Result { - self.value_type = ValueType::Prop; + self.current_value_type = ValueType::Prop; v.bytes().for_each(|x| { self.dst.step_by_u8(x); }); @@ -289,7 +298,7 @@ impl serde::ser::Serializer for &mut Serializer<'_> { } fn serialize_bytes(self, v: &[u8]) -> Result { - self.value_type = ValueType::Prop; + self.current_value_type = ValueType::Prop; v.iter().for_each(|x| self.dst.step_by_u8(*x)); Ok(()) } @@ -347,7 +356,7 @@ impl serde::ser::Serializer for &mut Serializer<'_> { } fn serialize_seq(self, _len: Option) -> Result { - self.value_type = ValueType::Prop; + self.current_value_type = ValueType::Prop; Ok(self) } @@ -389,7 +398,7 @@ impl serde::ser::Serializer for &mut Serializer<'_> { } else { self.dst.step_by_name(self.current_name); } - self.value_type = ValueType::Node; + self.current_value_type = ValueType::Node; Ok(self) } diff --git a/src/ser/string_block.rs b/src/ser/string_block.rs index 39324ef..af86434 100644 --- a/src/ser/string_block.rs +++ b/src/ser/string_block.rs @@ -1,17 +1,24 @@ +/// StringBlock +/// As spec said, dtb have a block called string block for saving prop names. pub struct StringBlock<'se> { end: &'se mut usize, data: &'se mut [u8], } impl<'se> StringBlock<'se> { + /// Make a new string block. + /// + /// For get how long is string block, we make `end` as a mut ref. #[inline(always)] pub fn new(dst: &'se mut [u8], end: &'se mut usize) -> StringBlock<'se> { StringBlock { data: dst, end } } - /// Will panic when len > end - /// TODO: show as error - /// Return (Result String, End Offset) + // TODO: show as error + /// Assume the passing `offset` is the start of a string, and return this string. + /// Return (Result String, End Offset). + /// + /// Will panic when len > end. #[inline(always)] pub fn get_str_by_offset(&self, offset: usize) -> (&str, usize) { if offset > *self.end { @@ -44,6 +51,7 @@ impl<'se> StringBlock<'se> { result } + /// Find a string. If not found, insert it. #[inline(always)] pub fn find_or_insert(&mut self, name: &str) -> usize { let mut current_pos = 0; From 7d58543ae6cb91f50b2662bccaa1b893091c3080 Mon Sep 17 00:00:00 2001 From: Woshiluo Luo Date: Tue, 25 Feb 2025 10:46:00 +0800 Subject: [PATCH 10/10] feat: add StrSeq Reg Node serialize feat: add re_encode example Signed-off-by: Woshiluo Luo --- examples/re_encode.rs | 30 ++++++++++++++++++ src/de_mut/cursor.rs | 14 +++++---- src/de_mut/data.rs | 12 ++++--- src/de_mut/mod.rs | 14 +++++++-- src/de_mut/node.rs | 62 ++++++++++++++++++++++++++++++------- src/de_mut/node_seq.rs | 4 +-- src/de_mut/reg.rs | 12 ++++++- src/de_mut/str_seq.rs | 12 ++++++- src/de_mut/struct_access.rs | 13 +++++--- src/ser/mod.rs | 1 + src/ser/serializer.rs | 45 ++++++++++++++++++++++++--- 11 files changed, 180 insertions(+), 39 deletions(-) create mode 100644 examples/re_encode.rs diff --git a/examples/re_encode.rs b/examples/re_encode.rs new file mode 100644 index 0000000..eed52cd --- /dev/null +++ b/examples/re_encode.rs @@ -0,0 +1,30 @@ +use serde_device_tree::{Dtb, DtbPtr, buildin::Node, error::Error, from_raw_mut}; + +use std::io::prelude::*; + +const RAW_DEVICE_TREE: &[u8] = include_bytes!("qemu-virt.dtb"); +const BUFFER_SIZE: usize = RAW_DEVICE_TREE.len(); + +#[repr(align(8))] +struct AlignedBuffer { + pub data: [u8; RAW_DEVICE_TREE.len()], +} + +fn main() -> Result<(), Error> { + let mut aligned_data: Box = Box::new(AlignedBuffer { + data: [0; BUFFER_SIZE], + }); + aligned_data.data[..BUFFER_SIZE].clone_from_slice(RAW_DEVICE_TREE); + let mut buf = [0u8; RAW_DEVICE_TREE.len() * 2]; + let mut slice = aligned_data.data.to_vec(); + let ptr = DtbPtr::from_raw(slice.as_mut_ptr())?; + let dtb = Dtb::from(ptr).share(); + + let root: Node = from_raw_mut(&dtb).unwrap(); + serde_device_tree::ser::to_dtb(&root, &[], &mut buf).unwrap(); + + let mut file = std::fs::File::create("gen.dtb").unwrap(); + file.write_all(&buf).unwrap(); + + Ok(()) +} diff --git a/src/de_mut/cursor.rs b/src/de_mut/cursor.rs index fecd8a6..5b52bb6 100644 --- a/src/de_mut/cursor.rs +++ b/src/de_mut/cursor.rs @@ -29,10 +29,10 @@ pub enum MoveResult { } #[derive(Clone, Copy, Debug)] -pub(super) struct MultiNodeCursor { +pub(crate) struct MultiNodeCursor { pub start_cursor: BodyCursor, - pub next_cursor: BodyCursor, pub skip_cursor: BodyCursor, + pub data_cursor: BodyCursor, #[allow(unused)] pub node_count: u32, } @@ -51,6 +51,7 @@ impl AnyCursor { impl BodyCursor { pub const ROOT: Self = Self(2, PhantomData); + pub const STARTER: Self = Self(0, PhantomData); /// 移动到下一个项目。 pub fn move_on(&mut self, dtb: RefDtb) -> Cursor { @@ -82,6 +83,7 @@ impl BodyCursor { } todo!() } + /// 移动指针至下一块 pub fn move_next(&mut self, dtb: RefDtb) -> MoveResult { use StructureBlock as B; @@ -183,8 +185,8 @@ impl TitleCursor { } MultiNodeCursor { start_cursor: group, - next_cursor: body, - skip_cursor: title_body, + skip_cursor: body, + data_cursor: title_body, node_count: len, } } @@ -201,8 +203,8 @@ impl TitleCursor { body.escape_from(dtb); MultiNodeCursor { start_cursor: origin, - next_cursor: body, - skip_cursor: node, + skip_cursor: body, + data_cursor: node, node_count: 1, } } diff --git a/src/de_mut/data.rs b/src/de_mut/data.rs index 9cf062c..a85ccb6 100644 --- a/src/de_mut/data.rs +++ b/src/de_mut/data.rs @@ -10,6 +10,7 @@ pub(super) enum ValueCursor { Body(BodyCursor), Prop(BodyCursor, PropCursor), Node(MultiNodeCursor), + NodeIn(MultiNodeCursor), } #[derive(Clone, Copy)] @@ -208,8 +209,9 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> { visitor.visit_some(self) } } - ValueCursor::Node(_) => visitor.visit_some(self), + ValueCursor::NodeIn(_) => visitor.visit_some(self), ValueCursor::Body(_) => visitor.visit_some(self), + ValueCursor::Node(_) => unreachable!("Node to option(NodeIn instead)"), } } @@ -251,7 +253,7 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> { { use super::{StructAccess, StructAccessType, Temp}; match self.cursor { - ValueCursor::Node(result) => { + ValueCursor::NodeIn(result) => { let mut start_cursor = result.start_cursor; match start_cursor.move_on(self.dtb) { Cursor::Title(c) => { @@ -302,7 +304,7 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> { { use super::{StructAccess, StructAccessType, Temp}; match self.cursor { - ValueCursor::Node(_) => visitor.visit_map(StructAccess { + ValueCursor::NodeIn(_) => visitor.visit_map(StructAccess { access_type: StructAccessType::Map(false), temp: Temp::Uninit, de: self, @@ -313,6 +315,7 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> { de: self, }), ValueCursor::Prop(_, _) => unreachable!("Prop -> map"), + ValueCursor::Node(_) => unreachable!("Node -> map (Use NodeIn instead)"), } } @@ -327,7 +330,7 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> { { use super::{StructAccess, StructAccessType, Temp}; match self.cursor { - ValueCursor::Node(_) => visitor.visit_map(StructAccess { + ValueCursor::NodeIn(_) => visitor.visit_map(StructAccess { access_type: StructAccessType::Struct(fields), temp: Temp::Uninit, de: self, @@ -338,6 +341,7 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> { de: self, }), ValueCursor::Prop(_, _) => unreachable!("Prop -> struct {_name}"), + ValueCursor::Node(_) => unreachable!("Node -> struct {_name} (Use NodeIn instead)"), } } diff --git a/src/de_mut/mod.rs b/src/de_mut/mod.rs index 1d2a475..e3c7641 100644 --- a/src/de_mut/mod.rs +++ b/src/de_mut/mod.rs @@ -7,7 +7,7 @@ use serde::de; mod cursor; mod data; // mod group; -mod node; +pub(crate) mod node; mod node_seq; mod reg; mod str_seq; @@ -16,13 +16,16 @@ mod struct_access; mod structs; const VALUE_DESERIALIZER_NAME: &str = "$serde_device_tree$de_mut$ValueDeserializer"; +pub(crate) const NODE_NAME: &str = "$serde_device_tree$de_mut$Node"; +pub(crate) const NODE_NODE_ITEM_NAME: &str = "$serde_device_tree$de_mut$Node$NodeItem"; +pub(crate) const NODE_PROP_ITEM_NAME: &str = "$serde_device_tree$de_mut$Node$PropItem"; pub use structs::{Dtb, DtbPtr}; pub mod buildin { pub use super::{node::Node, node_seq::NodeSeq, reg::Reg, str_seq::StrSeq}; } -use cursor::{BodyCursor, Cursor, PropCursor}; +use cursor::{BodyCursor, Cursor, MultiNodeCursor, PropCursor}; use data::{ValueCursor, ValueDeserializer}; use reg::RegConfig; use struct_access::{StructAccess, StructAccessType, Temp}; @@ -41,7 +44,12 @@ where let mut d = ValueDeserializer { dtb, reg: RegConfig::DEFAULT, - cursor: ValueCursor::Body(BodyCursor::ROOT), + cursor: ValueCursor::NodeIn(MultiNodeCursor { + start_cursor: BodyCursor::STARTER, + skip_cursor: BodyCursor::ROOT, // This item will never be used. + data_cursor: BodyCursor::ROOT, + node_count: 1, + }), }; T::deserialize(&mut d).and_then(|t| { // 解析必须完成 diff --git a/src/de_mut/node.rs b/src/de_mut/node.rs index 57f0da0..7ff6e48 100644 --- a/src/de_mut/node.rs +++ b/src/de_mut/node.rs @@ -1,8 +1,11 @@ -use super::{BodyCursor, Cursor, PropCursor, RefDtb, RegConfig, ValueCursor, ValueDeserializer}; +use super::{ + BodyCursor, Cursor, MultiNodeCursor, PropCursor, RefDtb, RegConfig, ValueCursor, + ValueDeserializer, +}; use core::fmt::Debug; use core::marker::PhantomData; use serde::de::MapAccess; -use serde::{Deserialize, de}; +use serde::{Deserialize, Serialize, de}; // TODO: Spec 2.3.5 said that we should not inherited from ancestors and the size-cell & // address-cells should only used for current node's children. @@ -27,7 +30,7 @@ pub struct NodeIter<'de, 'b> { pub struct NodeItem<'de> { dtb: RefDtb<'de>, reg: RegConfig, - node: BodyCursor, + node: MultiNodeCursor, name: &'de str, } @@ -81,6 +84,16 @@ impl<'de> Node<'de> { pub fn get_prop<'b>(&'b self, name: &str) -> Option> { self.props().find(|prop| prop.get_name() == name) } + + pub fn name(&self) -> &'de str { + let cursor = self.cursor.clone().move_on(self.dtb); + if let Cursor::Title(c) = cursor { + let (name, _) = c.split_on(self.dtb); + name + } else { + todo!(); + } + } } impl Debug for Node<'_> { @@ -128,10 +141,10 @@ impl<'de> Iterator for NodeIter<'de, '_> { let res = Some(Self::Item { dtb, reg: self.node.reg, - node: node_cursor.skip_cursor, + node: node_cursor, name, }); - *cursor = node_cursor.next_cursor; + *cursor = node_cursor.skip_cursor; res } else { None @@ -200,10 +213,9 @@ impl<'de> Deserialize<'de> for Node<'_> { reg = Some(value.reg); if key == "/" { self_cursor = match value.cursor { - ValueCursor::Body(cursor) => Some(cursor), - ValueCursor::Node(result) => Some(result.next_cursor), + ValueCursor::NodeIn(result) => Some(result.start_cursor), _ => { - unreachable!("root of NodeSeq shouble be body cursor") + unreachable!("root of NodeSeq shouble be NodeIn cursor") } }; continue; @@ -214,7 +226,7 @@ impl<'de> Deserialize<'de> for Node<'_> { props_start = Some(cursor); } } - ValueCursor::Node(cursor) => { + ValueCursor::NodeIn(cursor) => { if nodes_start.is_none() { nodes_start = Some(cursor.start_cursor); } @@ -249,7 +261,7 @@ impl<'de> NodeItem<'de> { T::deserialize(&mut ValueDeserializer { dtb: self.dtb, reg: self.reg, - cursor: ValueCursor::Body(self.node), + cursor: ValueCursor::NodeIn(self.node), }) .unwrap() } @@ -271,13 +283,13 @@ impl<'de> NodeItem<'de> { } } - pub fn get_full_name(&self) -> &str { + pub fn get_full_name(&self) -> &'de str { self.name } } impl<'de> PropItem<'de> { - pub fn get_name(&self) -> &str { + pub fn get_name(&self) -> &'de str { self.name } pub fn deserialize>(&self) -> T { @@ -290,6 +302,32 @@ impl<'de> PropItem<'de> { .unwrap() } } +impl<'se> Serialize for NodeItem<'se> { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_newtype_struct(crate::de_mut::NODE_NODE_ITEM_NAME, self) + } +} + +impl<'se> Serialize for PropItem<'se> { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_bytes(self.prop.data_on(self.dtb)) + } +} + +impl<'se> Serialize for Node<'se> { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_newtype_struct(crate::de_mut::NODE_NAME, self) + } +} #[cfg(test)] mod tests { diff --git a/src/de_mut/node_seq.rs b/src/de_mut/node_seq.rs index 4e63e62..a7b2331 100644 --- a/src/de_mut/node_seq.rs +++ b/src/de_mut/node_seq.rs @@ -140,12 +140,12 @@ impl<'de> Iterator for NodeSeqIter<'de, '_> { return None; } - self.de.cursor = ValueCursor::Body(node_reuslt.next_cursor); + self.de.cursor = ValueCursor::Body(node_reuslt.skip_cursor); Some(Self::Item { dtb: self.de.dtb, reg: self.de.reg, - body: node_reuslt.skip_cursor, + body: node_reuslt.data_cursor, at: suf_name, }) } diff --git a/src/de_mut/reg.rs b/src/de_mut/reg.rs index 20eeb0b..2d1106a 100644 --- a/src/de_mut/reg.rs +++ b/src/de_mut/reg.rs @@ -1,6 +1,6 @@ use super::{BLOCK_LEN, PropCursor, RefDtb, ValueCursor}; use core::{fmt::Debug, ops::Range}; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; /// 节点地址空间。 pub struct Reg<'de>(Inner<'de>); @@ -116,3 +116,13 @@ impl Iterator for RegIter<'_> { } } } + +impl<'se> Serialize for Reg<'se> { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + // Pass bytes directly for Reg. + serializer.serialize_bytes(self.0.cursor.data_on(self.0.dtb)) + } +} diff --git a/src/de_mut/str_seq.rs b/src/de_mut/str_seq.rs index 7af38a3..d0a4c48 100644 --- a/src/de_mut/str_seq.rs +++ b/src/de_mut/str_seq.rs @@ -1,6 +1,6 @@ use super::{PropCursor, RefDtb, ValueCursor}; use core::fmt::Debug; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; /// 一组 '\0' 分隔字符串的映射。 /// @@ -90,3 +90,13 @@ impl<'de> Iterator for StrSeqIter<'de> { } } } + +impl<'se> Serialize for StrSeq<'se> { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + // Pass bytes directly for StrSeq. + serializer.serialize_bytes(self.0.cursor.data_on(self.0.dtb)) + } +} diff --git a/src/de_mut/struct_access.rs b/src/de_mut/struct_access.rs index ce2d928..640f3fe 100644 --- a/src/de_mut/struct_access.rs +++ b/src/de_mut/struct_access.rs @@ -50,14 +50,17 @@ impl<'de> de::MapAccess<'de> for StructAccess<'de, '_> { let origin_cursor = match self.de.cursor { ValueCursor::Body(cursor) => cursor, ValueCursor::Node(result) => result.skip_cursor, + ValueCursor::NodeIn(result) => result.data_cursor, _ => unreachable!("map access's cursor should always be body cursor"), }; self.de.cursor = ValueCursor::Body(origin_cursor); let name = loop { let origin_cursor = match self.de.cursor { ValueCursor::Body(cursor) => cursor, + ValueCursor::Node(result) => result.skip_cursor, _ => unreachable!("map access's cursor should always be body cursor"), }; + self.de.cursor = ValueCursor::Body(origin_cursor); match self.de.move_on() { // 子节点名字 Cursor::Title(c) => { @@ -67,7 +70,7 @@ impl<'de> de::MapAccess<'de> for StructAccess<'de, '_> { // 子节点名字不带 @ 或正在解析 Node 类型 if pre_name == name || check_contains(name) { let take_result = c.take_node_on(self.de.dtb, name); - self.de.cursor = ValueCursor::Body(take_result.next_cursor); + self.de.cursor = ValueCursor::Node(take_result); if check_contains(name) { self.temp = Temp::Nodes(take_result); break name; @@ -76,7 +79,7 @@ impl<'de> de::MapAccess<'de> for StructAccess<'de, '_> { // @ 之前的部分是真正的名字,用这个名字搜索连续的一组 else { let take_result = c.take_group_on(self.de.dtb, pre_name); - self.de.cursor = ValueCursor::Body(take_result.next_cursor); + self.de.cursor = ValueCursor::Node(take_result); if check_contains(pre_name) { self.temp = Temp::Nodes(take_result); break pre_name; @@ -133,12 +136,12 @@ impl<'de> de::MapAccess<'de> for StructAccess<'de, '_> { StructAccessType::Map(_) => seed.deserialize(&mut ValueDeserializer { dtb: self.de.dtb, reg: self.de.reg, - cursor: ValueCursor::Node(*result), + cursor: ValueCursor::NodeIn(*result), }), StructAccessType::Struct(_) => seed.deserialize(&mut ValueDeserializer { dtb: self.de.dtb, reg: self.de.reg, - cursor: ValueCursor::Node(*result), + cursor: ValueCursor::NodeIn(*result), }), _ => unreachable!(), } @@ -170,7 +173,7 @@ impl<'de> de::SeqAccess<'de> for StructAccess<'de, '_> { // 子节点名字 Cursor::Title(c) => { let (name, _) = c.split_on(self.de.dtb); - let next = c.take_node_on(self.de.dtb, name).next_cursor; + let next = c.take_node_on(self.de.dtb, name).skip_cursor; let prev_cursor = match self.de.cursor { ValueCursor::Body(cursor) => cursor, _ => unreachable!(), diff --git a/src/ser/mod.rs b/src/ser/mod.rs index d7e899c..e54bca3 100644 --- a/src/ser/mod.rs +++ b/src/ser/mod.rs @@ -6,6 +6,7 @@ pub mod string_block; use crate::common::*; use crate::ser::patch::Patch; +// TODO: set reverse map const RSVMAP_LEN: usize = 16; /// Serialize the data to dtb, with a list fof Patch, write to the `writer`. diff --git a/src/ser/serializer.rs b/src/ser/serializer.rs index a8c6630..88bd22b 100644 --- a/src/ser/serializer.rs +++ b/src/ser/serializer.rs @@ -227,7 +227,7 @@ impl serde::ser::SerializeTupleStruct for &mut Serializer<'_> { } } -impl serde::ser::Serializer for &mut Serializer<'_> { +impl<'se> serde::ser::Serializer for &mut Serializer<'se> { type Ok = (); type Error = Error; type SerializeSeq = Self; @@ -332,14 +332,48 @@ impl serde::ser::Serializer for &mut Serializer<'_> { } fn serialize_newtype_struct( - self, - _name: &'static str, - _v: &T, + mut self, + name: &'static str, + v: &T, ) -> Result where T: serde::ser::Serialize + ?Sized, { - todo!("newtype struct"); + use crate::de_mut::node::{Node, NodeItem}; + use crate::de_mut::{NODE_NAME, NODE_NODE_ITEM_NAME}; + use core::ptr::addr_of; + match name { + NODE_NAME => { + // TODO: match level + self.current_value_type = ValueType::Node; + let v = unsafe { &*(addr_of!(v) as *const &Node<'se>) }; + self.dst.step_by_u32(FDT_BEGIN_NODE); + if self.current_dep == 0 { + // The name of root node should be empty. + self.dst.step_by_u32(0); + } else { + self.dst.step_by_name(v.name()); + self.dst.step_align(); + } + for prop in v.props() { + self.serialize_dynamic_field(prop.get_name(), &prop)?; + } + for node in v.nodes() { + self.serialize_dynamic_field( + node.get_full_name(), + &node.deserialize::(), + )?; + } + self.dst.step_by_u32(FDT_END_NODE); + Ok(()) + } + NODE_NODE_ITEM_NAME => { + self.current_value_type = ValueType::Node; + let v = unsafe { &*(addr_of!(v) as *const &NodeItem<'se>) }; + self.serialize_newtype_struct(NODE_NAME, &v.deserialize::()) + } + _ => todo!(), + } } fn serialize_newtype_variant( @@ -398,6 +432,7 @@ impl serde::ser::Serializer for &mut Serializer<'_> { } else { self.dst.step_by_name(self.current_name); } + self.dst.step_align(); self.current_value_type = ValueType::Node; Ok(self) }