diff --git a/src/ser/custom.rs b/src/ser/custom.rs new file mode 100644 index 0000000..6cdf546 --- /dev/null +++ b/src/ser/custom.rs @@ -0,0 +1,55 @@ +use serde::ser::{Serialize, SerializeTupleStruct}; + +use error::KbinErrorKind; +use node_types::StandardType; +use ser::{Error, Result, Serializer, TypeHint, WriteMode}; + +pub struct Custom<'a> { + ser: &'a mut Serializer, + node_type: StandardType, +} + +impl<'a> Custom<'a> { + pub fn new(ser: &'a mut Serializer, name: &'static str, len: usize) -> Result { + let node_type = StandardType::from_name(name); + + // Custom node type handler + // + // Sets the serializer to output a specific format for wrapper types + match node_type { + StandardType::Ip4 => ser.write_mode = WriteMode::Array, + _ => {}, + }; + + // TODO: Fix check for types that have a count above 1 + let node_size = node_type.size as usize; + if node_size != len { + return Err(KbinErrorKind::SizeMismatch(*node_type, node_size, len).into()); + } + + Ok(Self { ser, node_type }) + } +} + +impl<'a> SerializeTupleStruct for Custom<'a> { + type Ok = Option; + type Error = Error; + + fn serialize_field(&mut self, value: &T) -> Result<()> + where T: ?Sized + Serialize + { + trace!("Custom::serialize_field()"); + + value.serialize(&mut *self.ser)?; + + Ok(()) + } + + fn end(self) -> Result { + trace!("Custom::end()"); + + self.ser.write_mode = WriteMode::Single; + + Ok(Some(TypeHint::from_type(self.node_type))) + } +} diff --git a/src/ser/mod.rs b/src/ser/mod.rs index daa4430..9528918 100644 --- a/src/ser/mod.rs +++ b/src/ser/mod.rs @@ -11,9 +11,11 @@ use node_types::StandardType; use error::{Error, KbinError, KbinErrorKind}; use super::{ARRAY_MASK, SIGNATURE, SIG_COMPRESSED}; +mod custom; mod structure; mod tuple; +use self::custom::Custom; use self::structure::Struct; use self::tuple::Tuple; @@ -146,7 +148,7 @@ impl<'a> ser::Serializer for &'a mut Serializer { type SerializeSeq = Tuple<'a>; type SerializeTuple = Tuple<'a>; - type SerializeTupleStruct = Impossible; + type SerializeTupleStruct = Custom<'a>; type SerializeTupleVariant = Impossible; type SerializeMap = Self; type SerializeStruct = Struct<'a>; @@ -258,7 +260,7 @@ impl<'a> ser::Serializer for &'a mut Serializer { fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result { debug!("serialize_tuple_struct => name: {}, len: {}", name, len); - Err(Error::Message("tuple struct not supported".to_string())) + Custom::new(self, name, len) } fn serialize_tuple_variant(self, name: &'static str, variant_index: u32, variant: &'static str, len: usize) -> Result {