From 16f19e361ed90a46e1ac5a2ad0fb1e72eea0f636 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 1 Feb 2021 16:50:44 -0800 Subject: [PATCH 1/5] Rename Serializer -> SerializerToYaml --- src/ser.rs | 6 +++--- src/value/mod.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ser.rs b/src/ser.rs index 71815a64..cc5d546f 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -7,9 +7,9 @@ use serde::{ser, serde_if_integer128}; use std::{fmt, io, num, str}; use yaml_rust::{yaml, Yaml, YamlEmitter}; -pub struct Serializer; +pub struct SerializerToYaml; -impl ser::Serializer for Serializer { +impl ser::Serializer for SerializerToYaml { type Ok = Yaml; type Error = Error; @@ -446,7 +446,7 @@ fn to_yaml(elem: T) -> Result where T: ser::Serialize, { - elem.serialize(Serializer) + elem.serialize(SerializerToYaml) } fn singleton_hash(k: Yaml, v: Yaml) -> Yaml { diff --git a/src/value/mod.rs b/src/value/mod.rs index e9ce9c23..1365f957 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -1,4 +1,4 @@ -use crate::ser::Serializer; +use crate::ser::SerializerToYaml; use crate::{Error, Mapping}; use serde::de::{Deserialize, DeserializeOwned}; use serde::Serialize; @@ -83,7 +83,7 @@ pub fn to_value(value: T) -> Result where T: Serialize, { - value.serialize(Serializer).map(yaml_to_value) + value.serialize(SerializerToYaml).map(yaml_to_value) } /// Interpret a `serde_yaml::Value` as an instance of type `T`. From 0f5c53260cff441756421a2549a05f5a1855c0ef Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 1 Feb 2021 16:58:14 -0800 Subject: [PATCH 2/5] Add Serializer struct that outputs to io::Write --- src/ser.rs | 404 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 404 insertions(+) diff --git a/src/ser.rs b/src/ser.rs index cc5d546f..2f580a16 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -7,6 +7,410 @@ use serde::{ser, serde_if_integer128}; use std::{fmt, io, num, str}; use yaml_rust::{yaml, Yaml, YamlEmitter}; +pub struct Serializer { + writer: W, +} + +impl Serializer +where + W: io::Write, +{ + pub fn new(writer: W) -> Self { + Serializer { writer } + } + + pub fn into_inner(self) -> W { + self.writer + } + + fn write(&mut self, doc: Yaml) -> Result<()> { + let mut writer_adapter = FmtToIoWriter { + writer: &mut self.writer, + }; + YamlEmitter::new(&mut writer_adapter) + .dump(&doc) + .map_err(error::emitter)?; + writer_adapter.writer.write_all(b"\n").map_err(error::io)?; + Ok(()) + } +} + +impl<'a, W> ser::Serializer for &'a mut Serializer +where + W: io::Write, +{ + type Ok = (); + type Error = Error; + + type SerializeSeq = ThenWrite<'a, W, SerializeArray>; + type SerializeTuple = ThenWrite<'a, W, SerializeArray>; + type SerializeTupleStruct = ThenWrite<'a, W, SerializeArray>; + type SerializeTupleVariant = ThenWrite<'a, W, SerializeTupleVariant>; + type SerializeMap = ThenWrite<'a, W, SerializeMap>; + type SerializeStruct = ThenWrite<'a, W, SerializeStruct>; + type SerializeStructVariant = ThenWrite<'a, W, SerializeStructVariant>; + + fn serialize_bool(self, v: bool) -> Result<()> { + let doc = SerializerToYaml.serialize_bool(v)?; + self.write(doc) + } + + fn serialize_i8(self, v: i8) -> Result<()> { + let doc = SerializerToYaml.serialize_i8(v)?; + self.write(doc) + } + + fn serialize_i16(self, v: i16) -> Result<()> { + let doc = SerializerToYaml.serialize_i16(v)?; + self.write(doc) + } + + fn serialize_i32(self, v: i32) -> Result<()> { + let doc = SerializerToYaml.serialize_i32(v)?; + self.write(doc) + } + + fn serialize_i64(self, v: i64) -> Result<()> { + let doc = SerializerToYaml.serialize_i64(v)?; + self.write(doc) + } + + serde_if_integer128! { + fn serialize_i128(self, v: i128) -> Result<()> { + let doc = SerializerToYaml.serialize_i128(v)?; + self.write(doc) + } + } + + fn serialize_u8(self, v: u8) -> Result<()> { + let doc = SerializerToYaml.serialize_u8(v)?; + self.write(doc) + } + + fn serialize_u16(self, v: u16) -> Result<()> { + let doc = SerializerToYaml.serialize_u16(v)?; + self.write(doc) + } + + fn serialize_u32(self, v: u32) -> Result<()> { + let doc = SerializerToYaml.serialize_u32(v)?; + self.write(doc) + } + + fn serialize_u64(self, v: u64) -> Result<()> { + let doc = SerializerToYaml.serialize_u64(v)?; + self.write(doc) + } + + serde_if_integer128! { + fn serialize_u128(self, v: u128) -> Result<()> { + let doc = SerializerToYaml.serialize_u128(v)?; + self.write(doc) + } + } + + fn serialize_f32(self, v: f32) -> Result<()> { + let doc = SerializerToYaml.serialize_f32(v)?; + self.write(doc) + } + + fn serialize_f64(self, v: f64) -> Result<()> { + let doc = SerializerToYaml.serialize_f64(v)?; + self.write(doc) + } + + fn serialize_char(self, value: char) -> Result<()> { + let doc = SerializerToYaml.serialize_char(value)?; + self.write(doc) + } + + fn serialize_str(self, value: &str) -> Result<()> { + let doc = SerializerToYaml.serialize_str(value)?; + self.write(doc) + } + + fn serialize_bytes(self, value: &[u8]) -> Result<()> { + let doc = SerializerToYaml.serialize_bytes(value)?; + self.write(doc) + } + + fn serialize_unit(self) -> Result<()> { + let doc = SerializerToYaml.serialize_unit()?; + self.write(doc) + } + + fn serialize_unit_struct(self, name: &'static str) -> Result<()> { + let doc = SerializerToYaml.serialize_unit_struct(name)?; + self.write(doc) + } + + fn serialize_unit_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + ) -> Result<()> { + let doc = SerializerToYaml.serialize_unit_variant(name, variant_index, variant)?; + self.write(doc) + } + + fn serialize_newtype_struct(self, name: &'static str, value: &T) -> Result<()> + where + T: ser::Serialize, + { + let doc = SerializerToYaml.serialize_newtype_struct(name, value)?; + self.write(doc) + } + + fn serialize_newtype_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result<()> + where + T: ser::Serialize, + { + let doc = + SerializerToYaml.serialize_newtype_variant(name, variant_index, variant, value)?; + self.write(doc) + } + + fn serialize_none(self) -> Result<()> { + let doc = SerializerToYaml.serialize_none()?; + self.write(doc) + } + + fn serialize_some(self, value: &V) -> Result<()> + where + V: ser::Serialize, + { + let doc = SerializerToYaml.serialize_some(value)?; + self.write(doc) + } + + fn serialize_seq(self, len: Option) -> Result { + let delegate = SerializerToYaml.serialize_seq(len)?; + Ok(ThenWrite::new(self, delegate)) + } + + fn serialize_tuple(self, len: usize) -> Result { + let delegate = SerializerToYaml.serialize_tuple(len)?; + Ok(ThenWrite::new(self, delegate)) + } + + fn serialize_tuple_struct( + self, + name: &'static str, + len: usize, + ) -> Result { + let delegate = SerializerToYaml.serialize_tuple_struct(name, len)?; + Ok(ThenWrite::new(self, delegate)) + } + + fn serialize_tuple_variant( + self, + enm: &'static str, + idx: u32, + variant: &'static str, + len: usize, + ) -> Result { + let delegate = SerializerToYaml.serialize_tuple_variant(enm, idx, variant, len)?; + Ok(ThenWrite::new(self, delegate)) + } + + fn serialize_map(self, len: Option) -> Result { + let delegate = SerializerToYaml.serialize_map(len)?; + Ok(ThenWrite::new(self, delegate)) + } + + fn serialize_struct(self, name: &'static str, len: usize) -> Result { + let delegate = SerializerToYaml.serialize_struct(name, len)?; + Ok(ThenWrite::new(self, delegate)) + } + + fn serialize_struct_variant( + self, + enm: &'static str, + idx: u32, + variant: &'static str, + len: usize, + ) -> Result { + let delegate = SerializerToYaml.serialize_struct_variant(enm, idx, variant, len)?; + Ok(ThenWrite::new(self, delegate)) + } +} + +pub struct ThenWrite<'a, W, D> { + serializer: &'a mut Serializer, + delegate: D, +} + +impl<'a, W, D> ThenWrite<'a, W, D> { + fn new(serializer: &'a mut Serializer, delegate: D) -> Self { + ThenWrite { + serializer, + delegate, + } + } +} + +impl<'a, W> ser::SerializeSeq for ThenWrite<'a, W, SerializeArray> +where + W: io::Write, +{ + type Ok = (); + type Error = Error; + + fn serialize_element(&mut self, elem: &T) -> Result<()> + where + T: ser::Serialize, + { + self.delegate.serialize_element(elem) + } + + fn end(self) -> Result<()> { + let doc = self.delegate.end()?; + self.serializer.write(doc) + } +} + +impl<'a, W> ser::SerializeTuple for ThenWrite<'a, W, SerializeArray> +where + W: io::Write, +{ + type Ok = (); + type Error = Error; + + fn serialize_element(&mut self, elem: &T) -> Result<()> + where + T: ser::Serialize, + { + self.delegate.serialize_element(elem) + } + + fn end(self) -> Result<()> { + let doc = self.delegate.end()?; + self.serializer.write(doc) + } +} + +impl<'a, W> ser::SerializeTupleStruct for ThenWrite<'a, W, SerializeArray> +where + W: io::Write, +{ + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, value: &V) -> Result<()> + where + V: ser::Serialize, + { + self.delegate.serialize_field(value) + } + + fn end(self) -> Result<()> { + let doc = self.delegate.end()?; + self.serializer.write(doc) + } +} + +impl<'a, W> ser::SerializeTupleVariant for ThenWrite<'a, W, SerializeTupleVariant> +where + W: io::Write, +{ + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, v: &V) -> Result<()> + where + V: ser::Serialize, + { + self.delegate.serialize_field(v) + } + + fn end(self) -> Result<()> { + let doc = self.delegate.end()?; + self.serializer.write(doc) + } +} + +impl<'a, W> ser::SerializeMap for ThenWrite<'a, W, SerializeMap> +where + W: io::Write, +{ + type Ok = (); + type Error = Error; + + fn serialize_key(&mut self, key: &T) -> Result<()> + where + T: ser::Serialize, + { + self.delegate.serialize_key(key) + } + + fn serialize_value(&mut self, value: &T) -> Result<()> + where + T: ser::Serialize, + { + self.delegate.serialize_value(value) + } + + fn serialize_entry(&mut self, key: &K, value: &V) -> Result<()> + where + K: ser::Serialize, + V: ser::Serialize, + { + self.delegate.serialize_entry(key, value) + } + + fn end(self) -> Result<()> { + let doc = self.delegate.end()?; + self.serializer.write(doc) + } +} + +impl<'a, W> ser::SerializeStruct for ThenWrite<'a, W, SerializeStruct> +where + W: io::Write, +{ + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, key: &'static str, value: &V) -> Result<()> + where + V: ser::Serialize, + { + self.delegate.serialize_field(key, value) + } + + fn end(self) -> Result<()> { + let doc = self.delegate.end()?; + self.serializer.write(doc) + } +} + +impl<'a, W> ser::SerializeStructVariant for ThenWrite<'a, W, SerializeStructVariant> +where + W: io::Write, +{ + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, field: &'static str, v: &V) -> Result<()> + where + V: ser::Serialize, + { + self.delegate.serialize_field(field, v) + } + + fn end(self) -> Result<()> { + let doc = self.delegate.end()?; + self.serializer.write(doc) + } +} + pub struct SerializerToYaml; impl ser::Serializer for SerializerToYaml { From 59d5389a707de657d8e567d7308d1427bd0e25e5 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 1 Feb 2021 20:40:08 -0800 Subject: [PATCH 3/5] Ignore needless_pass_by_value clippy pedantic lint error: this argument is passed by value, but not consumed in the function body --> src/ser.rs:33:30 | 33 | fn write(&mut self, doc: Yaml) -> Result<()> { | ^^^^ help: consider taking a reference instead: `&Yaml` | = note: `-D clippy::needless-pass-by-value` implied by `-D clippy::pedantic` = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value --- src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib.rs b/src/lib.rs index 45f46b55..7750f931 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -74,6 +74,7 @@ // things are often more readable this way clippy::cast_lossless, clippy::module_name_repetitions, + clippy::needless_pass_by_value, clippy::option_if_let_else, clippy::single_match_else, clippy::use_self, From 4f9af330bcb1d92eef4131a2832924d52e814b8c Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 1 Feb 2021 18:24:27 -0800 Subject: [PATCH 4/5] Reimplement top level ser functions in terms of Serializer --- src/ser.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/ser.rs b/src/ser.rs index 2f580a16..ee891d75 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -795,13 +795,7 @@ where W: io::Write, T: ser::Serialize, { - let doc = to_yaml(value)?; - let mut writer_adapter = FmtToIoWriter { writer }; - YamlEmitter::new(&mut writer_adapter) - .dump(&doc) - .map_err(error::emitter)?; - writer_adapter.writer.write_all(b"\n").map_err(error::io)?; - Ok(()) + value.serialize(&mut Serializer::new(writer)) } /// Serialize the given data structure as a YAML byte vector. From fd828cb8b0c0ccefd3ab67b3c5f00ec888476d82 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 1 Feb 2021 18:25:55 -0800 Subject: [PATCH 5/5] Export Serializer from crate root --- src/lib.rs | 2 +- src/ser.rs | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 7750f931..86d0ba53 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -100,7 +100,7 @@ pub use crate::de::{from_reader, from_slice, from_str, Deserializer}; pub use crate::error::{Error, Location, Result}; -pub use crate::ser::{to_string, to_vec, to_writer}; +pub use crate::ser::{to_string, to_vec, to_writer, Serializer}; pub use crate::value::{from_value, to_value, Index, Number, Sequence, Value}; #[doc(inline)] diff --git a/src/ser.rs b/src/ser.rs index ee891d75..c183f0bc 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -7,6 +7,7 @@ use serde::{ser, serde_if_integer128}; use std::{fmt, io, num, str}; use yaml_rust::{yaml, Yaml, YamlEmitter}; +/// A structure for serializing Rust values into YAML. pub struct Serializer { writer: W, } @@ -15,10 +16,12 @@ impl Serializer where W: io::Write, { + /// Creates a new YAML serializer. pub fn new(writer: W) -> Self { Serializer { writer } } + /// Unwrap the underlying `io::Write` object from the `Serializer`. pub fn into_inner(self) -> W { self.writer }