diff --git a/examples/re_encode.rs b/examples/re_encode.rs index eed52cd..7fbaad7 100644 --- a/examples/re_encode.rs +++ b/examples/re_encode.rs @@ -1,3 +1,4 @@ +use serde_device_tree::ser::{patch::Patch, serializer::ValueType}; use serde_device_tree::{Dtb, DtbPtr, buildin::Node, error::Error, from_raw_mut}; use std::io::prelude::*; @@ -21,7 +22,8 @@ fn main() -> Result<(), Error> { 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 patch: Patch = Patch::new("/chosen/a", &"1", ValueType::Prop); + serde_device_tree::ser::to_dtb(&root, &[patch], &mut buf).unwrap(); let mut file = std::fs::File::create("gen.dtb").unwrap(); file.write_all(&buf).unwrap(); diff --git a/examples/serialize.rs b/examples/serialize.rs index ccf9352..14a6247 100644 --- a/examples/serialize.rs +++ b/examples/serialize.rs @@ -1,6 +1,8 @@ use serde::Serialize; use std::io::prelude::*; +use serde_device_tree::ser::serializer::ValueType; + const MAX_SIZE: usize = 256 + 32; fn main() { @@ -19,7 +21,8 @@ fn main() { { let new_base = Base1 { hello: "added" }; - let patch = serde_device_tree::ser::patch::Patch::new("/base3", &new_base as _); + let patch = + serde_device_tree::ser::patch::Patch::new("/base3", &new_base as _, ValueType::Node); let list = [patch]; let base = Base { hello: 0xdeedbeef, diff --git a/src/de_mut/node.rs b/src/de_mut/node.rs index 0b1ee11..54ca3b6 100644 --- a/src/de_mut/node.rs +++ b/src/de_mut/node.rs @@ -57,8 +57,8 @@ impl<'de> Node<'de> { let result = match self.cursor.clone().move_on(self.dtb) { Cursor::Title(c) => { let (name, _) = c.split_on(self.dtb); - let take_result = c.take_node_on(self.dtb, name); - take_result + + c.take_node_on(self.dtb, name) } _ => unreachable!("Node's cursor should on its start"), }; @@ -333,7 +333,15 @@ impl Serialize for Node<'_> { where S: serde::Serializer, { - serializer.serialize_newtype_struct(crate::de_mut::NODE_NAME, self) + use serde::ser::SerializeMap; + let mut map = serializer.serialize_map(None)?; + for prop in self.props() { + map.serialize_entry(prop.get_name(), &prop)?; + } + for node in self.nodes() { + map.serialize_entry(node.get_full_name(), &node.deserialize::())?; + } + map.end() } } diff --git a/src/ser/mod.rs b/src/ser/mod.rs index 6ba133e..3487562 100644 --- a/src/ser/mod.rs +++ b/src/ser/mod.rs @@ -25,8 +25,9 @@ where 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)?; + crate::ser::serializer::SerializerInner::new(&mut dst, &mut block, &mut patch_list); + let ser = crate::ser::serializer::Serializer::new(&mut ser); + data.serialize(ser)?; }; list.iter().for_each(|patch| patch.init()); // Write from bottom to top, to avoid overlap. @@ -44,11 +45,11 @@ where 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); - data.serialize(&mut ser)?; - ser.dst.step_by_u32(FDT_END); - ser.dst.get_offset() - }; + crate::ser::serializer::SerializerInner::new(&mut dst, &mut block, &mut patch_list); + let ser = crate::ser::serializer::Serializer::new(&mut ser); + data.serialize(ser)? + } + .1; // Make header { let header = unsafe { &mut *(header.as_mut_ptr() as *mut Header) }; diff --git a/src/ser/patch.rs b/src/ser/patch.rs index 2a31881..f6e4c52 100644 --- a/src/ser/patch.rs +++ b/src/ser/patch.rs @@ -1,11 +1,13 @@ use super::serializer::Serializer; +use super::serializer::ValueType; 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> { - pub data: &'se dyn dyn_serde::Serialize, name: &'se str, + pub data: &'se dyn dyn_serde::Serialize, + pub patch_type: ValueType, /// This patch match how many item between its path and serializer. matched_depth: Cell, @@ -13,13 +15,29 @@ pub struct Patch<'se> { parsed: Cell, } +impl core::fmt::Debug for Patch<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("") + .field("name", &self.name) + .field("patch_type", &self.patch_type) + .field("matched_depth", &self.matched_depth) + .field("parsed", &self.parsed) + .finish() + } +} + impl<'se> Patch<'se> { #[inline(always)] - pub fn new(name: &'se str, data: &'se dyn dyn_serde::Serialize) -> Patch<'se> { + pub fn new( + name: &'se str, + data: &'se dyn dyn_serde::Serialize, + patch_type: ValueType, + ) -> Patch<'se> { Patch { name, data, - matched_depth: Cell::new(0), + patch_type, + matched_depth: Cell::new(1), parsed: Cell::new(false), } } @@ -27,7 +45,7 @@ impl<'se> Patch<'se> { #[inline(always)] /// Reset the status of patch. pub fn init(&self) { - self.matched_depth.set(0); + self.matched_depth.set(1); self.parsed.set(false); } @@ -38,17 +56,14 @@ impl<'se> Patch<'se> { #[inline(always)] pub fn get_depth_path(&self, x: usize) -> &'se str { - if x == 0 { - return ""; - } - self.name.split('/').nth(x).unwrap_or_default() + self.name.split('/').nth(x - 1).unwrap_or_default() } // 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>) { + pub fn serialize(&self, serializer: Serializer<'_, 'se>) { self.parsed.set(true); self.data .serialize_dyn(&mut ::new(serializer)) @@ -57,6 +72,7 @@ impl<'se> Patch<'se> { } /// Here is a list of `Patch`, and have some methods for update `Patch` status. +#[derive(Debug)] pub struct PatchList<'se> { list: &'se [Patch<'se>], } @@ -64,11 +80,12 @@ pub struct PatchList<'se> { impl<'se> PatchList<'se> { #[inline(always)] pub fn new(list: &'se [Patch<'se>]) -> PatchList<'se> { + list.iter().for_each(|x| x.init()); PatchList { list } } #[inline(always)] - pub fn step_forward(&self, name: &'se str, depth: usize) -> Option<&'se Patch<'se>> { + pub fn step_forward(&self, name: &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 { diff --git a/src/ser/pointer.rs b/src/ser/pointer.rs index 45871e6..8bf300e 100644 --- a/src/ser/pointer.rs +++ b/src/ser/pointer.rs @@ -31,10 +31,12 @@ impl<'se> Pointer<'se> { } } + /// Create a PROP header with nop padding, return the offset of `FDT_PROP` token. #[inline(always)] pub fn step_by_prop(&mut self) -> usize { self.step_by_u32(FDT_PROP); let offset = self.offset; + // Put 2 nop as `name` and `nameoff`. 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 diff --git a/src/ser/serializer.rs b/src/ser/serializer.rs index 27c5da5..84fb0bf 100644 --- a/src/ser/serializer.rs +++ b/src/ser/serializer.rs @@ -1,152 +1,242 @@ -use super::patch::PatchList; +use super::patch::{Patch, PatchList}; use super::pointer::Pointer; use super::string_block::StringBlock; use crate::common::*; use crate::ser::Error; -#[derive(Clone, Copy)] // The enum for current parsing type. -enum ValueType { +#[derive(Clone, Copy, Debug)] +pub enum ValueType { Node, Prop, } -/// Serializer +/// SerializerInner /// - `dst`: Pointer of distance &[u8] and the ref of &[u8]. -/// - `current_value_type`, `current_name`, `current_dep`: For recursive. -pub struct Serializer<'se> { +pub struct SerializerInner<'se> { pub dst: &'se mut Pointer<'se>, string_block: &'se mut StringBlock<'se>, patch_list: &'se mut PatchList<'se>, +} + +/// Serializer +/// - `ser`: all mutable reference of result. +pub struct Serializer<'a, 'se> { + pub ser: &'a mut SerializerInner<'se>, - current_value_type: ValueType, + prop_token_offset: usize, + overwrite_patch: Option<&'se Patch<'se>>, current_name: &'se str, current_dep: usize, } -impl<'se> Serializer<'se> { +impl<'se> SerializerInner<'se> { #[inline(always)] pub fn new( dst: &'se mut Pointer<'se>, - cache: &'se mut StringBlock<'se>, + string_block: &'se mut StringBlock<'se>, patch_list: &'se mut PatchList<'se>, - ) -> Serializer<'se> { - Serializer { + ) -> Self { + Self { dst, - string_block: cache, + string_block, + patch_list, + } + } +} + +impl<'a, 'se> Serializer<'a, 'se> { + #[inline(always)] + pub fn new(inner: &'a mut SerializerInner<'se>) -> Self { + Serializer { + ser: inner, + current_dep: 0, current_name: "", - current_value_type: ValueType::Node, - patch_list, + prop_token_offset: 0, + overwrite_patch: None, + } + } + + #[inline(always)] + pub fn get_next(self) -> Serializer<'a, 'se> { + Serializer { + ser: self.ser, + current_dep: self.current_dep + 1, + current_name: self.current_name, + prop_token_offset: 0, + overwrite_patch: None, + } + } + + #[inline(always)] + pub fn get_next_ref<'b>(&'b mut self) -> Serializer<'b, 'se> { + Serializer { + ser: self.ser, + current_dep: self.current_dep + 1, + current_name: self.current_name, + prop_token_offset: 0, + overwrite_patch: None, } } } trait SerializeDynamicField<'se> { + fn start_node(&mut self) -> Result<(), Error>; + fn end_node(&mut self) -> Result<(), Error>; + fn serialize_field_meta(&mut self, key: &'se str) -> Result<(), Error>; + fn serialize_field_data(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize + ?Sized; fn serialize_dynamic_field(&mut self, key: &'se str, value: &T) -> Result<(), Error> where T: serde::ser::Serialize + ?Sized; } -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, - { - let prop_header_offset = self.dst.step_by_prop(); +impl<'se> SerializeDynamicField<'se> for Serializer<'_, 'se> { + fn start_node(&mut self) -> Result<(), Error> { + self.ser.dst.step_by_u32(FDT_BEGIN_NODE); + if self.current_dep == 1 { + // The name of root node should be empty. + self.ser.dst.step_by_u32(0); + } else { + self.ser.dst.step_by_name(self.current_name); + } + self.ser.dst.step_align(); + + Ok(()) + } + fn end_node(&mut self) -> Result<(), Error> { + for patch in self.ser.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.ser.dst.step_by_u32(FDT_END_NODE); + if self.current_dep == 1 { + self.ser.dst.step_by_u32(FDT_END); + } - // Save prev - let prev_type = self.current_value_type; - let prev_name = self.current_name; - self.current_dep += 1; + Ok(()) + } + fn serialize_field_meta(&mut self, key: &'se str) -> Result<(), Error> { + self.prop_token_offset = self.ser.dst.step_by_prop(); self.current_name = key; - let matched_patch = self.patch_list.step_forward(key, self.current_dep); + self.overwrite_patch = self.ser.patch_list.step_forward(key, self.current_dep); - match matched_patch { + Ok(()) + } + fn serialize_field_data(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize + ?Sized, + { + let value_type = match self.overwrite_patch { Some(data) => { - data.serialize(self); + let ser = self.get_next_ref(); + data.serialize(ser); + data.patch_type } None => { - value.serialize(&mut **self)?; + let ser = self.get_next_ref(); + value.serialize(ser)?.0 } - } + }; // 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.current_value_type { - self.dst - .write_to_offset_u32(prop_header_offset - 4, FDT_NOP); + if let ValueType::Node = value_type { + self.ser + .dst + .write_to_offset_u32(self.prop_token_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.ser.dst.write_to_offset_u32( + self.prop_token_offset, + (self.ser.dst.get_offset() - self.prop_token_offset - 8) as u32, ); - self.dst.write_to_offset_u32( - prop_header_offset + 4, - self.string_block.find_or_insert(key) as u32, + self.ser.dst.write_to_offset_u32( + self.prop_token_offset + 4, + self.ser.string_block.find_or_insert(self.current_name) as u32, ); } - self.dst.step_align(); + self.ser.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; + self.ser.patch_list.step_back(self.current_dep); Ok(()) } + fn serialize_dynamic_field(&mut self, key: &'se str, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize + ?Sized, + { + self.serialize_field_meta(key)?; + self.serialize_field_data(value)?; + Ok(()) + } } -impl serde::ser::SerializeMap for &mut Serializer<'_> { - type Ok = (); +impl serde::ser::SerializeMap for Serializer<'_, '_> { + type Ok = (ValueType, usize); type Error = Error; + fn serialize_entry(&mut self, key: &K, value: &V) -> Result<(), Self::Error> + where + K: ?Sized + serde::ser::Serialize, + V: ?Sized + serde::ser::Serialize, + { + if core::any::type_name::() != "str" { + panic!( + "map key must be a str, but here is {}", + core::any::type_name::() + ); + } + let key = unsafe { *(core::ptr::addr_of!(key) as *const &str) }; + let mut ser = self.get_next_ref(); + ser.serialize_field_meta(key)?; + ser.serialize_field_data(value)?; + Ok(()) + } fn serialize_key(&mut self, _input: &T) -> Result<(), Self::Error> where T: serde::ser::Serialize + ?Sized, { - todo!("map_key"); + todo!("only support serialize_entry") } fn serialize_value(&mut self, _value: &T) -> Result<(), Self::Error> where T: serde::ser::Serialize + ?Sized, { - todo!("map_value"); + todo!("only support serialize_entry") } - fn end(self) -> Result { - todo!("map_end"); + fn end(mut self) -> Result { + self.end_node()?; + Ok((ValueType::Node, self.ser.dst.get_offset())) } } -impl serde::ser::SerializeStruct for &mut Serializer<'_> { - type Ok = (); +impl serde::ser::SerializeStruct for Serializer<'_, '_> { + type Ok = (ValueType, usize); 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)?; + let mut ser = self.get_next_ref(); + ser.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(()) + self.end_node()?; + Ok((ValueType::Node, self.ser.dst.get_offset())) } } -impl serde::ser::SerializeStructVariant for &mut Serializer<'_> { - type Ok = (); +impl serde::ser::SerializeStructVariant for Serializer<'_, '_> { + type Ok = (ValueType, usize); type Error = Error; fn serialize_field(&mut self, _key: &'static str, _value: &T) -> Result<(), Self::Error> @@ -161,42 +251,43 @@ impl serde::ser::SerializeStructVariant for &mut Serializer<'_> { } } -impl serde::ser::SerializeSeq for &mut Serializer<'_> { - type Ok = (); +impl serde::ser::SerializeSeq for Serializer<'_, '_> { + type Ok = (ValueType, usize); 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) + value.serialize(self.get_next_ref())?; + Ok(()) } - // Close the sequence. - fn end(self) -> Result<(), Error> { - Ok(()) + fn end(self) -> Result { + // We think all seq we met is a prop. + Ok((ValueType::Prop, self.ser.dst.get_offset())) } } -impl serde::ser::SerializeTuple for &mut Serializer<'_> { - type Ok = (); +impl serde::ser::SerializeTuple for Serializer<'_, '_> { + type Ok = (ValueType, usize); type Error = Error; fn serialize_element(&mut self, value: &T) -> Result<(), Error> where T: ?Sized + serde::ser::Serialize, { - value.serialize(&mut **self) + value.serialize(self.get_next_ref())?; + Ok(()) } - // Close the sequence. - fn end(self) -> Result<(), Error> { - Ok(()) + fn end(self) -> Result { + Ok((ValueType::Prop, self.ser.dst.get_offset())) } } -impl serde::ser::SerializeTupleVariant for &mut Serializer<'_> { - type Ok = (); +impl serde::ser::SerializeTupleVariant for Serializer<'_, '_> { + type Ok = (ValueType, usize); type Error = Error; fn serialize_field(&mut self, _value: &T) -> Result<(), Self::Error> @@ -206,13 +297,13 @@ impl serde::ser::SerializeTupleVariant for &mut Serializer<'_> { todo!("tuple_variant_field"); } - fn end(self) -> Result<(), Error> { + fn end(self) -> Result { todo!("tuple_variant_end"); } } -impl serde::ser::SerializeTupleStruct for &mut Serializer<'_> { - type Ok = (); +impl serde::ser::SerializeTupleStruct for Serializer<'_, '_> { + type Ok = (ValueType, usize); type Error = Error; fn serialize_field(&mut self, _value: &T) -> Result<(), Self::Error> @@ -222,13 +313,13 @@ impl serde::ser::SerializeTupleStruct for &mut Serializer<'_> { todo!("tuple_struct_field"); } - fn end(self) -> Result<(), Error> { + fn end(self) -> Result { todo!("tuple_struct_end"); } } -impl<'se> serde::ser::Serializer for &mut Serializer<'se> { - type Ok = (); +impl<'se> serde::ser::Serializer for Serializer<'_, 'se> { + type Ok = (ValueType, usize); type Error = Error; type SerializeSeq = Self; type SerializeMap = Self; @@ -267,9 +358,8 @@ impl<'se> serde::ser::Serializer for &mut Serializer<'se> { } fn serialize_u32(self, v: u32) -> Result { - self.current_value_type = ValueType::Prop; - self.dst.step_by_u32(v); - Ok(()) + self.ser.dst.step_by_u32(v); + Ok((ValueType::Prop, self.ser.dst.get_offset())) } fn serialize_u64(self, _v: u64) -> Result { @@ -289,18 +379,16 @@ impl<'se> serde::ser::Serializer for &mut Serializer<'se> { } fn serialize_str(self, v: &str) -> Result { - self.current_value_type = ValueType::Prop; v.bytes().for_each(|x| { - self.dst.step_by_u8(x); + self.ser.dst.step_by_u8(x); }); - self.dst.step_by_u8(0); - Ok(()) + self.ser.dst.step_by_u8(0); + Ok((ValueType::Prop, self.ser.dst.get_offset())) } fn serialize_bytes(self, v: &[u8]) -> Result { - self.current_value_type = ValueType::Prop; - v.iter().for_each(|x| self.dst.step_by_u8(*x)); - Ok(()) + v.iter().for_each(|x| self.ser.dst.step_by_u8(*x)); + Ok((ValueType::Prop, self.ser.dst.get_offset())) } fn serialize_none(self) -> Result { @@ -331,11 +419,7 @@ impl<'se> serde::ser::Serializer for &mut Serializer<'se> { todo!("unit struct variant"); } - fn serialize_newtype_struct( - mut self, - name: &'static str, - v: &T, - ) -> Result + fn serialize_newtype_struct(self, name: &'static str, v: &T) -> Result where T: serde::ser::Serialize + ?Sized, { @@ -343,32 +427,7 @@ impl<'se> serde::ser::Serializer for &mut Serializer<'se> { 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::()) } @@ -390,7 +449,6 @@ impl<'se> serde::ser::Serializer for &mut Serializer<'se> { } fn serialize_seq(self, _len: Option) -> Result { - self.current_value_type = ValueType::Prop; Ok(self) } @@ -417,7 +475,9 @@ impl<'se> serde::ser::Serializer for &mut Serializer<'se> { } fn serialize_map(self, _len: Option) -> Result { - todo!("map"); + let mut ser = self.get_next(); + ser.start_node()?; + Ok(ser) } fn serialize_struct( @@ -425,16 +485,9 @@ impl<'se> serde::ser::Serializer for &mut Serializer<'se> { _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(self.current_name); - } - self.dst.step_align(); - self.current_value_type = ValueType::Node; - Ok(self) + let mut ser = self.get_next(); + ser.start_node()?; + Ok(ser) } fn serialize_struct_variant( @@ -591,7 +644,11 @@ mod tests { { let number = 0x55667788u32; - let patch = crate::ser::patch::Patch::new("/hello", &number as _); + let patch = crate::ser::patch::Patch::new( + "/hello", + &number as _, + crate::ser::serializer::ValueType::Prop, + ); let list = [patch]; let base = Base { hello: 0xdeedbeef, @@ -626,7 +683,11 @@ mod tests { let new_base = Base1 { hello: "replacement", }; - let patch = crate::ser::patch::Patch::new("/hello", &new_base as _); + let patch = crate::ser::patch::Patch::new( + "/hello", + &new_base as _, + crate::ser::serializer::ValueType::Node, + ); let list = [patch]; let base = Base { hello: 0xdeedbeef, @@ -659,7 +720,11 @@ mod tests { { let new_base = Base1 { hello: "added" }; - let patch = crate::ser::patch::Patch::new("/base3", &new_base as _); + let patch = crate::ser::patch::Patch::new( + "/base3", + &new_base as _, + crate::ser::serializer::ValueType::Node, + ); let list = [patch]; let base = Base { hello: 0xdeedbeef,