use std::fmt::Display; use std::fmt::Write as _; use serde::ser; use crate::error::{ConfigError, Result}; use crate::value::{Value, ValueKind}; use crate::Config; #[derive(Default, Debug)] pub struct ConfigSerializer { keys: Vec, pub output: Config, } #[derive(Debug)] enum SerKey { Named(String), Seq(usize), } /// Serializer for numbered sequences /// /// This wrapper is present when we are outputting a sequence (numbered indices). /// Making this a separate type centralises the handling of sequences /// and ensures we don't have any call sites for `ser::SerializeSeq::serialize_element` /// that don't do the necessary work of `SeqSerializer::new`. /// /// Existence of this wrapper implies that `.0.keys.last()` is /// `Some(SerKey::Seq(next_index))`. pub struct SeqSerializer<'a>(&'a mut ConfigSerializer); impl ConfigSerializer { fn serialize_primitive(&mut self, value: T) -> Result<()> where T: Into + Display, { // At some future point we could perhaps retain a cursor into the output `Config`, // rather than reifying the whole thing into a single string with `make_full_key` // and passing that whole path to the `set` method. // // That would be marginally more performant, but more fiddly. let key = self.make_full_key()?; #[allow(deprecated)] self.output.set(&key, value.into())?; Ok(()) } fn make_full_key(&self) -> Result { let mut keys = self.keys.iter(); let mut whole = match keys.next() { Some(SerKey::Named(s)) => s.clone(), _ => { return Err(ConfigError::Message( "top level is not a struct".to_string(), )) } }; for k in keys { match k { SerKey::Named(s) => write!(whole, ".{}", s), SerKey::Seq(i) => write!(whole, "[{}]", i), } .expect("write! to a string failed"); } Ok(whole) } fn push_key(&mut self, key: &str) { self.keys.push(SerKey::Named(key.to_string())); } fn pop_key(&mut self) { self.keys.pop(); } } impl<'a> ser::Serializer for &'a mut ConfigSerializer { type Ok = (); type Error = ConfigError; type SerializeSeq = SeqSerializer<'a>; type SerializeTuple = SeqSerializer<'a>; type SerializeTupleStruct = SeqSerializer<'a>; type SerializeTupleVariant = SeqSerializer<'a>; type SerializeMap = Self; type SerializeStruct = Self; type SerializeStructVariant = Self; fn serialize_bool(self, v: bool) -> Result { self.serialize_primitive(v) } fn serialize_i8(self, v: i8) -> Result { self.serialize_i64(v.into()) } fn serialize_i16(self, v: i16) -> Result { self.serialize_i64(v.into()) } fn serialize_i32(self, v: i32) -> Result { self.serialize_i64(v.into()) } fn serialize_i64(self, v: i64) -> Result { self.serialize_primitive(v) } fn serialize_u8(self, v: u8) -> Result { self.serialize_u64(v.into()) } fn serialize_u16(self, v: u16) -> Result { self.serialize_u64(v.into()) } fn serialize_u32(self, v: u32) -> Result { self.serialize_u64(v.into()) } fn serialize_u64(self, v: u64) -> Result { if v > (i64::max_value() as u64) { Err(ConfigError::Message(format!( "value {} is greater than the max {}", v, i64::max_value() ))) } else { self.serialize_i64(v as i64) } } fn serialize_f32(self, v: f32) -> Result { self.serialize_f64(v.into()) } fn serialize_f64(self, v: f64) -> Result { self.serialize_primitive(v) } fn serialize_char(self, v: char) -> Result { self.serialize_primitive(v.to_string()) } fn serialize_str(self, v: &str) -> Result { self.serialize_primitive(v.to_string()) } fn serialize_bytes(self, v: &[u8]) -> Result { use serde::ser::SerializeSeq; let mut seq = self.serialize_seq(Some(v.len()))?; for byte in v { seq.serialize_element(byte)?; } seq.end(); Ok(()) } fn serialize_none(self) -> Result { self.serialize_unit() } fn serialize_some(self, value: &T) -> Result where T: ?Sized + ser::Serialize, { value.serialize(self) } fn serialize_unit(self) -> Result { self.serialize_primitive(Value::from(ValueKind::Nil)) } fn serialize_unit_struct(self, _name: &'static str) -> Result { self.serialize_unit() } fn serialize_unit_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str, ) -> Result { self.serialize_str(variant) } fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result where T: ?Sized + ser::Serialize, { value.serialize(self) } fn serialize_newtype_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str, value: &T, ) -> Result where T: ?Sized + ser::Serialize, { self.push_key(variant); value.serialize(&mut *self)?; self.pop_key(); Ok(()) } fn serialize_seq(self, _len: Option) -> Result { SeqSerializer::new(self) } fn serialize_tuple(self, len: usize) -> Result { self.serialize_seq(Some(len)) } fn serialize_tuple_struct( self, _name: &'static str, len: usize, ) -> Result { self.serialize_seq(Some(len)) } fn serialize_tuple_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str, len: usize, ) -> Result { self.push_key(variant); self.serialize_seq(Some(len)) } fn serialize_map(self, _len: Option) -> Result { Ok(self) } fn serialize_struct(self, _name: &'static str, len: usize) -> Result { self.serialize_map(Some(len)) } fn serialize_struct_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str, _len: usize, ) -> Result { self.push_key(variant); Ok(self) } } impl<'a> SeqSerializer<'a> { fn new(inner: &'a mut ConfigSerializer) -> Result { inner.keys.push(SerKey::Seq(0)); Ok(SeqSerializer(inner)) } fn end(self) -> &'a mut ConfigSerializer { // This ought to be Some(SerKey::Seq(..)) but we don't want to panic if we are buggy let _: Option = self.0.keys.pop(); self.0 } } impl<'a> ser::SerializeSeq for SeqSerializer<'a> { type Ok = (); type Error = ConfigError; fn serialize_element(&mut self, value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { value.serialize(&mut *(self.0))?; match self.0.keys.last_mut() { Some(SerKey::Seq(i)) => *i += 1, _ => { return Err(ConfigError::Message( "config-rs internal error (ser._element but last not Seq!".to_string(), )) } }; Ok(()) } fn end(self) -> Result { self.end(); Ok(()) } } impl<'a> ser::SerializeTuple for SeqSerializer<'a> { type Ok = (); type Error = ConfigError; fn serialize_element(&mut self, value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { ser::SerializeSeq::serialize_element(self, value) } fn end(self) -> Result { ser::SerializeSeq::end(self) } } impl<'a> ser::SerializeTupleStruct for SeqSerializer<'a> { type Ok = (); type Error = ConfigError; fn serialize_field(&mut self, value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { ser::SerializeSeq::serialize_element(self, value) } fn end(self) -> Result { ser::SerializeSeq::end(self) } } impl<'a> ser::SerializeTupleVariant for SeqSerializer<'a> { type Ok = (); type Error = ConfigError; fn serialize_field(&mut self, value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { ser::SerializeSeq::serialize_element(self, value) } fn end(self) -> Result { let inner = self.end(); inner.pop_key(); Ok(()) } } impl<'a> ser::SerializeMap for &'a mut ConfigSerializer { type Ok = (); type Error = ConfigError; fn serialize_key(&mut self, key: &T) -> Result<()> where T: ?Sized + ser::Serialize, { let key_serializer = StringKeySerializer; let key = key.serialize(key_serializer)?; self.push_key(&key); Ok(()) } fn serialize_value(&mut self, value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { value.serialize(&mut **self)?; self.pop_key(); Ok(()) } fn end(self) -> Result { Ok(()) } } impl<'a> ser::SerializeStruct for &'a mut ConfigSerializer { type Ok = (); type Error = ConfigError; fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { self.push_key(key); value.serialize(&mut **self)?; self.pop_key(); Ok(()) } fn end(self) -> Result { Ok(()) } } impl<'a> ser::SerializeStructVariant for &'a mut ConfigSerializer { type Ok = (); type Error = ConfigError; fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { self.push_key(key); value.serialize(&mut **self)?; self.pop_key(); Ok(()) } fn end(self) -> Result { self.pop_key(); Ok(()) } } pub struct StringKeySerializer; impl ser::Serializer for StringKeySerializer { type Ok = String; type Error = ConfigError; type SerializeSeq = Self; type SerializeTuple = Self; type SerializeTupleStruct = Self; type SerializeTupleVariant = Self; type SerializeMap = Self; type SerializeStruct = Self; type SerializeStructVariant = Self; fn serialize_bool(self, v: bool) -> Result { Ok(v.to_string()) } fn serialize_i8(self, v: i8) -> Result { Ok(v.to_string()) } fn serialize_i16(self, v: i16) -> Result { Ok(v.to_string()) } fn serialize_i32(self, v: i32) -> Result { Ok(v.to_string()) } fn serialize_i64(self, v: i64) -> Result { Ok(v.to_string()) } fn serialize_u8(self, v: u8) -> Result { Ok(v.to_string()) } fn serialize_u16(self, v: u16) -> Result { Ok(v.to_string()) } fn serialize_u32(self, v: u32) -> Result { Ok(v.to_string()) } fn serialize_u64(self, v: u64) -> Result { Ok(v.to_string()) } fn serialize_f32(self, v: f32) -> Result { Ok(v.to_string()) } fn serialize_f64(self, v: f64) -> Result { Ok(v.to_string()) } fn serialize_char(self, v: char) -> Result { Ok(v.to_string()) } fn serialize_str(self, v: &str) -> Result { Ok(v.to_string()) } fn serialize_bytes(self, v: &[u8]) -> Result { Ok(String::from_utf8_lossy(v).to_string()) } fn serialize_none(self) -> Result { self.serialize_unit() } fn serialize_some(self, value: &T) -> Result where T: ?Sized + ser::Serialize, { value.serialize(self) } fn serialize_unit(self) -> Result { Ok(String::new()) } fn serialize_unit_struct(self, _name: &str) -> Result { self.serialize_unit() } fn serialize_unit_variant( self, _name: &str, _variant_index: u32, variant: &str, ) -> Result { Ok(variant.to_string()) } fn serialize_newtype_struct(self, _name: &str, value: &T) -> Result where T: ?Sized + ser::Serialize, { value.serialize(self) } fn serialize_newtype_variant( self, _name: &str, _variant_index: u32, _variant: &str, value: &T, ) -> Result where T: ?Sized + ser::Serialize, { value.serialize(self) } fn serialize_seq(self, _len: Option) -> Result { Err(ConfigError::Message( "seq can't serialize to string key".to_string(), )) } fn serialize_tuple(self, _len: usize) -> Result { Err(ConfigError::Message( "tuple can't serialize to string key".to_string(), )) } fn serialize_tuple_struct(self, name: &str, _len: usize) -> Result { Err(ConfigError::Message(format!( "tuple struct {} can't serialize to string key", name ))) } fn serialize_tuple_variant( self, name: &str, _variant_index: u32, variant: &str, _len: usize, ) -> Result { Err(ConfigError::Message(format!( "tuple variant {}::{} can't serialize to string key", name, variant ))) } fn serialize_map(self, _len: Option) -> Result { Err(ConfigError::Message( "map can't serialize to string key".to_string(), )) } fn serialize_struct(self, name: &str, _len: usize) -> Result { Err(ConfigError::Message(format!( "struct {} can't serialize to string key", name ))) } fn serialize_struct_variant( self, name: &str, _variant_index: u32, variant: &str, _len: usize, ) -> Result { Err(ConfigError::Message(format!( "struct variant {}::{} can't serialize to string key", name, variant ))) } } impl ser::SerializeSeq for StringKeySerializer { type Ok = String; type Error = ConfigError; fn serialize_element(&mut self, _value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { unreachable!() } fn end(self) -> Result { unreachable!() } } impl ser::SerializeTuple for StringKeySerializer { type Ok = String; type Error = ConfigError; fn serialize_element(&mut self, _value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { unreachable!() } fn end(self) -> Result { unreachable!() } } impl ser::SerializeTupleStruct for StringKeySerializer { type Ok = String; type Error = ConfigError; fn serialize_field(&mut self, _value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { unreachable!() } fn end(self) -> Result { unreachable!() } } impl ser::SerializeTupleVariant for StringKeySerializer { type Ok = String; type Error = ConfigError; fn serialize_field(&mut self, _value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { unreachable!() } fn end(self) -> Result { unreachable!() } } impl ser::SerializeMap for StringKeySerializer { type Ok = String; type Error = ConfigError; fn serialize_key(&mut self, _key: &T) -> Result<()> where T: ?Sized + ser::Serialize, { unreachable!() } fn serialize_value(&mut self, _value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { unreachable!() } fn end(self) -> Result { unreachable!() } } impl ser::SerializeStruct for StringKeySerializer { type Ok = String; type Error = ConfigError; fn serialize_field(&mut self, _key: &'static str, _value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { unreachable!() } fn end(self) -> Result { unreachable!() } } impl ser::SerializeStructVariant for StringKeySerializer { type Ok = String; type Error = ConfigError; fn serialize_field(&mut self, _key: &'static str, _value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { unreachable!() } fn end(self) -> Result { unreachable!() } } #[cfg(test)] mod test { use super::*; use serde::{Deserialize, Serialize}; #[test] fn test_struct() { #[derive(Debug, Serialize, Deserialize, PartialEq)] struct Test { int: u32, seq: Vec, } let test = Test { int: 1, seq: vec!["a".to_string(), "b".to_string()], }; let config = Config::try_from(&test).unwrap(); let actual: Test = config.try_deserialize().unwrap(); assert_eq!(test, actual); } #[test] fn test_nest() { let val = serde_json::json! { { "top": { "num": 1, "array": [2], "nested": [[3,4]], "deep": [{ "yes": true, }], "mixed": [ { "boolish": false, }, 42, ["hi"], { "inner": 66 }, 23, ], } } }; let config = Config::try_from(&val).unwrap(); let output: serde_json::Value = config.try_deserialize().unwrap(); assert_eq!(val, output); } }