use std::{borrow::Cow, fmt};
use serde::{ser, ser::Serialize};
use serde_derive::{Deserialize, Serialize};
use unicode_ident::is_xid_continue;
use crate::{
error::{Error, Result},
extensions::Extensions,
options::Options,
parse::{is_ident_first_char, is_ident_raw_char, is_whitespace_char, LargeSInt, LargeUInt},
};
pub mod path_meta;
mod raw;
#[cfg(test)]
mod tests;
mod value;
pub fn to_writer<W, T>(writer: W, value: &T) -> Result<()>
where
W: fmt::Write,
T: ?Sized + Serialize,
{
Options::default().to_writer(writer, value)
}
pub fn to_writer_pretty<W, T>(writer: W, value: &T, config: PrettyConfig) -> Result<()>
where
W: fmt::Write,
T: ?Sized + Serialize,
{
Options::default().to_writer_pretty(writer, value, config)
}
pub fn to_string<T>(value: &T) -> Result<String>
where
T: ?Sized + Serialize,
{
Options::default().to_string(value)
}
pub fn to_string_pretty<T>(value: &T, config: PrettyConfig) -> Result<String>
where
T: ?Sized + Serialize,
{
Options::default().to_string_pretty(value, config)
}
struct Pretty {
indent: usize,
}
#[allow(clippy::struct_excessive_bools)]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(default)]
#[non_exhaustive]
pub struct PrettyConfig {
pub depth_limit: usize,
pub new_line: Cow<'static, str>,
pub indentor: Cow<'static, str>,
pub separator: Cow<'static, str>,
pub struct_names: bool,
pub separate_tuple_members: bool,
pub enumerate_arrays: bool,
pub extensions: Extensions,
pub compact_arrays: bool,
pub escape_strings: bool,
pub compact_structs: bool,
pub compact_maps: bool,
pub number_suffixes: bool,
pub path_meta: Option<path_meta::Field>,
}
impl PrettyConfig {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn depth_limit(mut self, depth_limit: usize) -> Self {
self.depth_limit = depth_limit;
self
}
#[must_use]
pub fn new_line(mut self, new_line: impl Into<Cow<'static, str>>) -> Self {
self.new_line = new_line.into();
self
}
#[must_use]
pub fn indentor(mut self, indentor: impl Into<Cow<'static, str>>) -> Self {
self.indentor = indentor.into();
self
}
#[must_use]
pub fn separator(mut self, separator: impl Into<Cow<'static, str>>) -> Self {
self.separator = separator.into();
self
}
#[must_use]
pub fn struct_names(mut self, struct_names: bool) -> Self {
self.struct_names = struct_names;
self
}
#[must_use]
pub fn separate_tuple_members(mut self, separate_tuple_members: bool) -> Self {
self.separate_tuple_members = separate_tuple_members;
self
}
#[must_use]
pub fn enumerate_arrays(mut self, enumerate_arrays: bool) -> Self {
self.enumerate_arrays = enumerate_arrays;
self
}
#[must_use]
pub fn compact_arrays(mut self, compact_arrays: bool) -> Self {
self.compact_arrays = compact_arrays;
self
}
#[must_use]
pub fn extensions(mut self, extensions: Extensions) -> Self {
self.extensions = extensions;
self
}
#[must_use]
pub fn escape_strings(mut self, escape_strings: bool) -> Self {
self.escape_strings = escape_strings;
self
}
#[must_use]
pub fn compact_structs(mut self, compact_structs: bool) -> Self {
self.compact_structs = compact_structs;
self
}
#[must_use]
pub fn compact_maps(mut self, compact_maps: bool) -> Self {
self.compact_maps = compact_maps;
self
}
#[must_use]
pub fn number_suffixes(mut self, number_suffixes: bool) -> Self {
self.number_suffixes = number_suffixes;
self
}
}
impl Default for PrettyConfig {
fn default() -> Self {
PrettyConfig {
depth_limit: usize::MAX,
new_line: if cfg!(not(target_os = "windows")) {
Cow::Borrowed("\n")
} else {
Cow::Borrowed("\r\n") },
indentor: Cow::Borrowed(" "),
separator: Cow::Borrowed(" "),
struct_names: false,
separate_tuple_members: false,
enumerate_arrays: false,
extensions: Extensions::empty(),
compact_arrays: false,
escape_strings: true,
compact_structs: false,
compact_maps: false,
number_suffixes: false,
path_meta: None,
}
}
}
pub struct Serializer<W: fmt::Write> {
output: W,
pretty: Option<(PrettyConfig, Pretty)>,
default_extensions: Extensions,
is_empty: Option<bool>,
newtype_variant: bool,
recursion_limit: Option<usize>,
implicit_some_depth: usize,
}
fn indent<W: fmt::Write>(output: &mut W, config: &PrettyConfig, pretty: &Pretty) -> fmt::Result {
if pretty.indent <= config.depth_limit {
for _ in 0..pretty.indent {
output.write_str(&config.indentor)?;
}
}
Ok(())
}
impl<W: fmt::Write> Serializer<W> {
pub fn new(writer: W, config: Option<PrettyConfig>) -> Result<Self> {
Self::with_options(writer, config, &Options::default())
}
pub fn with_options(
mut writer: W,
config: Option<PrettyConfig>,
options: &Options,
) -> Result<Self> {
if let Some(conf) = &config {
if !conf.new_line.chars().all(is_whitespace_char) {
return Err(Error::Message(String::from(
"Invalid non-whitespace `PrettyConfig::new_line`",
)));
}
if !conf.indentor.chars().all(is_whitespace_char) {
return Err(Error::Message(String::from(
"Invalid non-whitespace `PrettyConfig::indentor`",
)));
}
if !conf.separator.chars().all(is_whitespace_char) {
return Err(Error::Message(String::from(
"Invalid non-whitespace `PrettyConfig::separator`",
)));
}
let non_default_extensions = !options.default_extensions;
for (extension_name, _) in (non_default_extensions & conf.extensions).iter_names() {
write!(writer, "#![enable({})]", extension_name.to_lowercase())?;
writer.write_str(&conf.new_line)?;
}
};
Ok(Serializer {
output: writer,
pretty: config.map(|conf| (conf, Pretty { indent: 0 })),
default_extensions: options.default_extensions,
is_empty: None,
newtype_variant: false,
recursion_limit: options.recursion_limit,
implicit_some_depth: 0,
})
}
fn separate_tuple_members(&self) -> bool {
self.pretty
.as_ref()
.map_or(false, |(ref config, _)| config.separate_tuple_members)
}
fn compact_arrays(&self) -> bool {
self.pretty
.as_ref()
.map_or(false, |(ref config, _)| config.compact_arrays)
}
fn compact_structs(&self) -> bool {
self.pretty
.as_ref()
.map_or(false, |(ref config, _)| config.compact_structs)
}
fn compact_maps(&self) -> bool {
self.pretty
.as_ref()
.map_or(false, |(ref config, _)| config.compact_maps)
}
fn number_suffixes(&self) -> bool {
self.pretty
.as_ref()
.map_or(false, |(ref config, _)| config.number_suffixes)
}
fn extensions(&self) -> Extensions {
self.default_extensions
| self
.pretty
.as_ref()
.map_or(Extensions::empty(), |(ref config, _)| config.extensions)
}
fn escape_strings(&self) -> bool {
self.pretty
.as_ref()
.map_or(true, |(ref config, _)| config.escape_strings)
}
fn start_indent(&mut self) -> Result<()> {
if let Some((ref config, ref mut pretty)) = self.pretty {
pretty.indent += 1;
if pretty.indent <= config.depth_limit {
let is_empty = self.is_empty.unwrap_or(false);
if !is_empty {
self.output.write_str(&config.new_line)?;
}
}
}
Ok(())
}
fn indent(&mut self) -> fmt::Result {
if let Some((ref config, ref pretty)) = self.pretty {
indent(&mut self.output, config, pretty)?;
}
Ok(())
}
fn end_indent(&mut self) -> fmt::Result {
if let Some((ref config, ref mut pretty)) = self.pretty {
if pretty.indent <= config.depth_limit {
let is_empty = self.is_empty.unwrap_or(false);
if !is_empty {
for _ in 1..pretty.indent {
self.output.write_str(&config.indentor)?;
}
}
}
pretty.indent -= 1;
self.is_empty = None;
}
Ok(())
}
fn serialize_escaped_str(&mut self, value: &str) -> fmt::Result {
self.output.write_char('"')?;
let mut scalar = [0u8; 4];
for c in value.chars().flat_map(char::escape_debug) {
self.output.write_str(c.encode_utf8(&mut scalar))?;
}
self.output.write_char('"')?;
Ok(())
}
fn serialize_unescaped_or_raw_str(&mut self, value: &str) -> fmt::Result {
if value.contains('"') || value.contains('\\') {
let (_, num_consecutive_hashes) =
value.chars().fold((0, 0), |(count, max), c| match c {
'#' => (count + 1, max.max(count + 1)),
_ => (0_usize, max),
});
let hashes: String = "#".repeat(num_consecutive_hashes + 1);
self.output.write_char('r')?;
self.output.write_str(&hashes)?;
self.output.write_char('"')?;
self.output.write_str(value)?;
self.output.write_char('"')?;
self.output.write_str(&hashes)?;
} else {
self.output.write_char('"')?;
self.output.write_str(value)?;
self.output.write_char('"')?;
}
Ok(())
}
fn serialize_escaped_byte_str(&mut self, value: &[u8]) -> fmt::Result {
self.output.write_str("b\"")?;
for c in value.iter().flat_map(|c| std::ascii::escape_default(*c)) {
self.output.write_char(char::from(c))?;
}
self.output.write_char('"')?;
Ok(())
}
fn serialize_unescaped_or_raw_byte_str(&mut self, value: &str) -> fmt::Result {
if value.contains('"') || value.contains('\\') {
let (_, num_consecutive_hashes) =
value.chars().fold((0, 0), |(count, max), c| match c {
'#' => (count + 1, max.max(count + 1)),
_ => (0_usize, max),
});
let hashes: String = "#".repeat(num_consecutive_hashes + 1);
self.output.write_str("br")?;
self.output.write_str(&hashes)?;
self.output.write_char('"')?;
self.output.write_str(value)?;
self.output.write_char('"')?;
self.output.write_str(&hashes)?;
} else {
self.output.write_str("b\"")?;
self.output.write_str(value)?;
self.output.write_char('"')?;
}
Ok(())
}
fn serialize_sint(&mut self, value: impl Into<LargeSInt>, suffix: &str) -> Result<()> {
write!(self.output, "{}", value.into())?;
if self.number_suffixes() {
write!(self.output, "{}", suffix)?;
}
Ok(())
}
fn serialize_uint(&mut self, value: impl Into<LargeUInt>, suffix: &str) -> Result<()> {
write!(self.output, "{}", value.into())?;
if self.number_suffixes() {
write!(self.output, "{}", suffix)?;
}
Ok(())
}
fn write_identifier(&mut self, name: &str) -> Result<()> {
self.validate_identifier(name)?;
let mut chars = name.chars();
if !chars.next().map_or(false, is_ident_first_char)
|| !chars.all(is_xid_continue)
|| [
"true", "false", "Some", "None", "inf", "inff32", "inff64", "NaN", "NaNf32",
"NaNf64",
]
.contains(&name)
{
self.output.write_str("r#")?;
}
self.output.write_str(name)?;
Ok(())
}
#[allow(clippy::unused_self)]
fn validate_identifier(&self, name: &str) -> Result<()> {
if name.is_empty() || !name.chars().all(is_ident_raw_char) {
return Err(Error::InvalidIdentifier(name.into()));
}
Ok(())
}
fn struct_names(&self) -> bool {
self.extensions()
.contains(Extensions::EXPLICIT_STRUCT_NAMES)
|| self
.pretty
.as_ref()
.map_or(false, |(pc, _)| pc.struct_names)
}
}
macro_rules! guard_recursion {
($self:expr => $expr:expr) => {{
if let Some(limit) = &mut $self.recursion_limit {
if let Some(new_limit) = limit.checked_sub(1) {
*limit = new_limit;
} else {
return Err(Error::ExceededRecursionLimit);
}
}
let result = $expr;
if let Some(limit) = &mut $self.recursion_limit {
*limit = limit.saturating_add(1);
}
result
}};
}
impl<'a, W: fmt::Write> ser::Serializer for &'a mut Serializer<W> {
type Error = Error;
type Ok = ();
type SerializeMap = Compound<'a, W>;
type SerializeSeq = Compound<'a, W>;
type SerializeStruct = Compound<'a, W>;
type SerializeStructVariant = Compound<'a, W>;
type SerializeTuple = Compound<'a, W>;
type SerializeTupleStruct = Compound<'a, W>;
type SerializeTupleVariant = Compound<'a, W>;
fn serialize_bool(self, v: bool) -> Result<()> {
self.output.write_str(if v { "true" } else { "false" })?;
Ok(())
}
fn serialize_i8(self, v: i8) -> Result<()> {
self.serialize_sint(v, "i8")
}
fn serialize_i16(self, v: i16) -> Result<()> {
self.serialize_sint(v, "i16")
}
fn serialize_i32(self, v: i32) -> Result<()> {
self.serialize_sint(v, "i32")
}
fn serialize_i64(self, v: i64) -> Result<()> {
self.serialize_sint(v, "i64")
}
#[cfg(feature = "integer128")]
fn serialize_i128(self, v: i128) -> Result<()> {
self.serialize_sint(v, "i128")
}
fn serialize_u8(self, v: u8) -> Result<()> {
self.serialize_uint(v, "u8")
}
fn serialize_u16(self, v: u16) -> Result<()> {
self.serialize_uint(v, "u16")
}
fn serialize_u32(self, v: u32) -> Result<()> {
self.serialize_uint(v, "u32")
}
fn serialize_u64(self, v: u64) -> Result<()> {
self.serialize_uint(v, "u64")
}
#[cfg(feature = "integer128")]
fn serialize_u128(self, v: u128) -> Result<()> {
self.serialize_uint(v, "u128")
}
fn serialize_f32(self, v: f32) -> Result<()> {
if v.is_nan() && v.is_sign_negative() {
write!(self.output, "-")?;
}
write!(self.output, "{}", v)?;
if v.fract() == 0.0 {
write!(self.output, ".0")?;
}
if self.number_suffixes() {
write!(self.output, "f32")?;
}
Ok(())
}
fn serialize_f64(self, v: f64) -> Result<()> {
if v.is_nan() && v.is_sign_negative() {
write!(self.output, "-")?;
}
write!(self.output, "{}", v)?;
if v.fract() == 0.0 {
write!(self.output, ".0")?;
}
if self.number_suffixes() {
write!(self.output, "f64")?;
}
Ok(())
}
fn serialize_char(self, v: char) -> Result<()> {
self.output.write_char('\'')?;
if v == '\\' || v == '\'' {
self.output.write_char('\\')?;
}
write!(self.output, "{}", v)?;
self.output.write_char('\'')?;
Ok(())
}
fn serialize_str(self, v: &str) -> Result<()> {
if self.escape_strings() {
self.serialize_escaped_str(v)?;
} else {
self.serialize_unescaped_or_raw_str(v)?;
}
Ok(())
}
fn serialize_bytes(self, v: &[u8]) -> Result<()> {
if !self.escape_strings() {
if let Ok(v) = std::str::from_utf8(v) {
return self
.serialize_unescaped_or_raw_byte_str(v)
.map_err(Error::from);
}
}
self.serialize_escaped_byte_str(v)?;
Ok(())
}
fn serialize_none(self) -> Result<()> {
let implicit_some_depth = self.implicit_some_depth;
self.implicit_some_depth = 0;
for _ in 0..implicit_some_depth {
self.output.write_str("Some(")?;
}
self.output.write_str("None")?;
for _ in 0..implicit_some_depth {
self.output.write_char(')')?;
}
Ok(())
}
fn serialize_some<T>(self, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
let implicit_some = self.extensions().contains(Extensions::IMPLICIT_SOME);
if implicit_some {
self.implicit_some_depth += 1;
} else {
self.newtype_variant = self
.extensions()
.contains(Extensions::UNWRAP_VARIANT_NEWTYPES);
self.output.write_str("Some(")?;
}
guard_recursion! { self => value.serialize(&mut *self)? };
if implicit_some {
self.implicit_some_depth = 0;
} else {
self.output.write_char(')')?;
self.newtype_variant = false;
}
Ok(())
}
fn serialize_unit(self) -> Result<()> {
if !self.newtype_variant {
self.output.write_str("()")?;
}
Ok(())
}
fn serialize_unit_struct(self, name: &'static str) -> Result<()> {
if self.struct_names() && !self.newtype_variant {
self.write_identifier(name)?;
Ok(())
} else {
self.validate_identifier(name)?;
self.serialize_unit()
}
}
fn serialize_unit_variant(
self,
name: &'static str,
_variant_index: u32,
variant: &'static str,
) -> Result<()> {
self.validate_identifier(name)?;
self.write_identifier(variant)?;
Ok(())
}
fn serialize_newtype_struct<T>(self, name: &'static str, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
if name == crate::value::raw::RAW_VALUE_TOKEN {
let implicit_some_depth = self.implicit_some_depth;
self.implicit_some_depth = 0;
for _ in 0..implicit_some_depth {
self.output.write_str("Some(")?;
}
guard_recursion! { self => value.serialize(raw::Serializer::new(self)) }?;
for _ in 0..implicit_some_depth {
self.output.write_char(')')?;
}
return Ok(());
}
if self.extensions().contains(Extensions::UNWRAP_NEWTYPES) || self.newtype_variant {
self.newtype_variant = false;
self.validate_identifier(name)?;
return guard_recursion! { self => value.serialize(&mut *self) };
}
if self.struct_names() {
self.write_identifier(name)?;
} else {
self.validate_identifier(name)?;
}
self.implicit_some_depth = 0;
self.output.write_char('(')?;
guard_recursion! { self => value.serialize(&mut *self)? };
self.output.write_char(')')?;
Ok(())
}
fn serialize_newtype_variant<T>(
self,
name: &'static str,
_variant_index: u32,
variant: &'static str,
value: &T,
) -> Result<()>
where
T: ?Sized + Serialize,
{
self.validate_identifier(name)?;
self.write_identifier(variant)?;
self.output.write_char('(')?;
self.newtype_variant = self
.extensions()
.contains(Extensions::UNWRAP_VARIANT_NEWTYPES);
self.implicit_some_depth = 0;
guard_recursion! { self => value.serialize(&mut *self)? };
self.newtype_variant = false;
self.output.write_char(')')?;
Ok(())
}
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq> {
self.newtype_variant = false;
self.implicit_some_depth = 0;
self.output.write_char('[')?;
if !self.compact_arrays() {
if let Some(len) = len {
self.is_empty = Some(len == 0);
}
self.start_indent()?;
}
Ok(Compound::new(self, false))
}
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
let old_newtype_variant = self.newtype_variant;
self.newtype_variant = false;
self.implicit_some_depth = 0;
if !old_newtype_variant {
self.output.write_char('(')?;
}
if self.separate_tuple_members() {
self.is_empty = Some(len == 0);
self.start_indent()?;
}
Ok(Compound::new(self, old_newtype_variant))
}
fn serialize_tuple_struct(
self,
name: &'static str,
len: usize,
) -> Result<Self::SerializeTupleStruct> {
if self.struct_names() && !self.newtype_variant {
self.write_identifier(name)?;
} else {
self.validate_identifier(name)?;
}
self.serialize_tuple(len)
}
fn serialize_tuple_variant(
self,
name: &'static str,
_variant_index: u32,
variant: &'static str,
len: usize,
) -> Result<Self::SerializeTupleVariant> {
self.newtype_variant = false;
self.implicit_some_depth = 0;
self.validate_identifier(name)?;
self.write_identifier(variant)?;
self.output.write_char('(')?;
if self.separate_tuple_members() {
self.is_empty = Some(len == 0);
self.start_indent()?;
}
Ok(Compound::new(self, false))
}
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap> {
self.newtype_variant = false;
self.implicit_some_depth = 0;
self.output.write_char('{')?;
if !self.compact_maps() {
if let Some(len) = len {
self.is_empty = Some(len == 0);
}
self.start_indent()?;
}
Ok(Compound::new(self, false))
}
fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self::SerializeStruct> {
let old_newtype_variant = self.newtype_variant;
self.newtype_variant = false;
self.implicit_some_depth = 0;
if old_newtype_variant {
self.validate_identifier(name)?;
} else {
if self.struct_names() {
self.write_identifier(name)?;
} else {
self.validate_identifier(name)?;
}
self.output.write_char('(')?;
}
if !self.compact_structs() {
self.is_empty = Some(len == 0);
self.start_indent()?;
}
Ok(Compound::new(self, old_newtype_variant))
}
fn serialize_struct_variant(
self,
name: &'static str,
_variant_index: u32,
variant: &'static str,
len: usize,
) -> Result<Self::SerializeStructVariant> {
self.newtype_variant = false;
self.implicit_some_depth = 0;
self.validate_identifier(name)?;
self.write_identifier(variant)?;
self.output.write_char('(')?;
if !self.compact_structs() {
self.is_empty = Some(len == 0);
self.start_indent()?;
}
Ok(Compound::new(self, false))
}
}
enum State {
First,
Rest,
}
#[doc(hidden)]
pub struct Compound<'a, W: fmt::Write> {
ser: &'a mut Serializer<W>,
state: State,
newtype_variant: bool,
sequence_index: usize,
}
impl<'a, W: fmt::Write> Compound<'a, W> {
fn new(ser: &'a mut Serializer<W>, newtype_variant: bool) -> Self {
Compound {
ser,
state: State::First,
newtype_variant,
sequence_index: 0,
}
}
}
impl<'a, W: fmt::Write> Drop for Compound<'a, W> {
fn drop(&mut self) {
if let Some(limit) = &mut self.ser.recursion_limit {
*limit = limit.saturating_add(1);
}
}
}
impl<'a, W: fmt::Write> ser::SerializeSeq for Compound<'a, W> {
type Error = Error;
type Ok = ();
fn serialize_element<T>(&mut self, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
if let State::First = self.state {
self.state = State::Rest;
} else {
self.ser.output.write_char(',')?;
if let Some((ref config, ref mut pretty)) = self.ser.pretty {
if pretty.indent <= config.depth_limit && !config.compact_arrays {
self.ser.output.write_str(&config.new_line)?;
} else {
self.ser.output.write_str(&config.separator)?;
}
}
}
if !self.ser.compact_arrays() {
self.ser.indent()?;
}
if let Some((ref mut config, ref mut pretty)) = self.ser.pretty {
if pretty.indent <= config.depth_limit && config.enumerate_arrays {
write!(self.ser.output, "/*[{}]*/ ", self.sequence_index)?;
self.sequence_index += 1;
}
}
guard_recursion! { self.ser => value.serialize(&mut *self.ser)? };
Ok(())
}
fn end(self) -> Result<()> {
if let State::Rest = self.state {
if let Some((ref config, ref mut pretty)) = self.ser.pretty {
if pretty.indent <= config.depth_limit && !config.compact_arrays {
self.ser.output.write_char(',')?;
self.ser.output.write_str(&config.new_line)?;
}
}
}
if !self.ser.compact_arrays() {
self.ser.end_indent()?;
}
self.ser.output.write_char(']')?;
Ok(())
}
}
impl<'a, W: fmt::Write> ser::SerializeTuple for Compound<'a, W> {
type Error = Error;
type Ok = ();
fn serialize_element<T>(&mut self, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
if let State::First = self.state {
self.state = State::Rest;
} else {
self.ser.output.write_char(',')?;
if let Some((ref config, ref pretty)) = self.ser.pretty {
if pretty.indent <= config.depth_limit && self.ser.separate_tuple_members() {
self.ser.output.write_str(&config.new_line)?;
} else {
self.ser.output.write_str(&config.separator)?;
}
}
}
if self.ser.separate_tuple_members() {
self.ser.indent()?;
}
guard_recursion! { self.ser => value.serialize(&mut *self.ser)? };
Ok(())
}
fn end(self) -> Result<()> {
if let State::Rest = self.state {
if let Some((ref config, ref pretty)) = self.ser.pretty {
if self.ser.separate_tuple_members() && pretty.indent <= config.depth_limit {
self.ser.output.write_char(',')?;
self.ser.output.write_str(&config.new_line)?;
}
}
}
if self.ser.separate_tuple_members() {
self.ser.end_indent()?;
}
if !self.newtype_variant {
self.ser.output.write_char(')')?;
}
Ok(())
}
}
impl<'a, W: fmt::Write> ser::SerializeTupleStruct for Compound<'a, W> {
type Error = Error;
type Ok = ();
fn serialize_field<T>(&mut self, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
ser::SerializeTuple::serialize_element(self, value)
}
fn end(self) -> Result<()> {
ser::SerializeTuple::end(self)
}
}
impl<'a, W: fmt::Write> ser::SerializeTupleVariant for Compound<'a, W> {
type Error = Error;
type Ok = ();
fn serialize_field<T>(&mut self, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
ser::SerializeTuple::serialize_element(self, value)
}
fn end(self) -> Result<()> {
ser::SerializeTuple::end(self)
}
}
impl<'a, W: fmt::Write> ser::SerializeMap for Compound<'a, W> {
type Error = Error;
type Ok = ();
fn serialize_key<T>(&mut self, key: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
if let State::First = self.state {
self.state = State::Rest;
} else {
self.ser.output.write_char(',')?;
if let Some((ref config, ref pretty)) = self.ser.pretty {
if pretty.indent <= config.depth_limit && !config.compact_maps {
self.ser.output.write_str(&config.new_line)?;
} else {
self.ser.output.write_str(&config.separator)?;
}
}
}
if !self.ser.compact_maps() {
self.ser.indent()?;
}
guard_recursion! { self.ser => key.serialize(&mut *self.ser) }
}
fn serialize_value<T>(&mut self, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
self.ser.output.write_char(':')?;
if let Some((ref config, _)) = self.ser.pretty {
self.ser.output.write_str(&config.separator)?;
}
guard_recursion! { self.ser => value.serialize(&mut *self.ser)? };
Ok(())
}
fn end(self) -> Result<()> {
if let State::Rest = self.state {
if let Some((ref config, ref pretty)) = self.ser.pretty {
if pretty.indent <= config.depth_limit && !config.compact_maps {
self.ser.output.write_char(',')?;
self.ser.output.write_str(&config.new_line)?;
}
}
}
if !self.ser.compact_maps() {
self.ser.end_indent()?;
}
self.ser.output.write_char('}')?;
Ok(())
}
}
impl<'a, W: fmt::Write> ser::SerializeStruct for Compound<'a, W> {
type Error = Error;
type Ok = ();
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
let mut restore_field = self.ser.pretty.as_mut().and_then(|(config, _)| {
config.path_meta.take().map(|mut field| {
if let Some(fields) = field.fields_mut() {
config.path_meta = fields.remove(key);
}
field
})
});
if let State::First = self.state {
self.state = State::Rest;
} else {
self.ser.output.write_char(',')?;
if let Some((ref config, ref pretty)) = self.ser.pretty {
if pretty.indent <= config.depth_limit && !config.compact_structs {
self.ser.output.write_str(&config.new_line)?;
} else {
self.ser.output.write_str(&config.separator)?;
}
}
}
if !self.ser.compact_structs() {
if let Some((ref config, ref pretty)) = self.ser.pretty {
indent(&mut self.ser.output, config, pretty)?;
if let Some(ref field) = config.path_meta {
for doc_line in field.doc().lines() {
self.ser.output.write_str("/// ")?;
self.ser.output.write_str(doc_line)?;
self.ser.output.write_char('\n')?;
indent(&mut self.ser.output, config, pretty)?;
}
}
}
}
self.ser.write_identifier(key)?;
self.ser.output.write_char(':')?;
if let Some((ref config, _)) = self.ser.pretty {
self.ser.output.write_str(&config.separator)?;
}
guard_recursion! { self.ser => value.serialize(&mut *self.ser)? };
if let Some((ref mut config, _)) = self.ser.pretty {
std::mem::swap(&mut config.path_meta, &mut restore_field);
if let Some(ref mut field) = config.path_meta {
if let Some(fields) = field.fields_mut() {
if let Some(restore_field) = restore_field {
fields.insert(key, restore_field);
}
}
}
};
Ok(())
}
fn end(self) -> Result<()> {
if let State::Rest = self.state {
if let Some((ref config, ref pretty)) = self.ser.pretty {
if pretty.indent <= config.depth_limit && !config.compact_structs {
self.ser.output.write_char(',')?;
self.ser.output.write_str(&config.new_line)?;
}
}
}
if !self.ser.compact_structs() {
self.ser.end_indent()?;
}
if !self.newtype_variant {
self.ser.output.write_char(')')?;
}
Ok(())
}
}
impl<'a, W: fmt::Write> ser::SerializeStructVariant for Compound<'a, W> {
type Error = Error;
type Ok = ();
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
ser::SerializeStruct::serialize_field(self, key, value)
}
fn end(self) -> Result<()> {
ser::SerializeStruct::end(self)
}
}