Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  mod.rs

  Sprache: Rust
 

use alloc::{borrow::Cow, string::String};
use core::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;

/// Serializes `value` into `writer`.
///
/// This function does not generate any newlines or nice formatting;
/// if you want that, you can use [`to_writer_pretty`] instead.
pub fn to_writer<W, T>(writer: W, value: &T) -> Result<()>
where
    W: fmt::Write,
    T: ?Sized + Serialize,
{
    Options::default().to_writer(writer, value)
}

/// Serializes `value` into `writer` in a pretty way.
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)
}

/// Serializes `value` and returns it as string.
///
/// This function does not generate any newlines or nice formatting;
/// if you want that, you can use [`to_string_pretty`] instead.
pub fn to_string<T>(value: &T) -> Result<String>
where
    T: ?Sized + Serialize,
{
    Options::default().to_string(value)
}

/// Serializes `value` in the recommended RON layout in a pretty way.
pub fn to_string_pretty<T>(value: &T, config: PrettyConfig) -> Result<String>
where
    T: ?Sized + Serialize,
{
    Options::default().to_string_pretty(value, config)
}

/// Pretty serializer state
struct Pretty {
    indent: usize,
}

/// Pretty serializer configuration.
///
/// # Examples
///
/// ```
/// use ron::ser::PrettyConfig;
///
/// let my_config = PrettyConfig::new()
///     .depth_limit(4)
///     // definitely superior (okay, just joking)
///     .indentor("\t");
/// ```
#[allow(clippy::struct_excessive_bools)]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(default)]
#[non_exhaustive]
pub struct PrettyConfig {
    /// Limit the pretty-ness up to the given depth.
    pub depth_limit: usize,
    /// New line string
    pub new_line: Cow<'static, str>,
    /// Indentation string
    pub indentor: Cow<'static, str>,
    /// Separator string
    pub separator: Cow<'static, str>,
    // Whether to emit struct names
    pub struct_names: bool,
    /// Separate tuple members with indentation
    pub separate_tuple_members: bool,
    /// Enumerate array items in comments
    pub enumerate_arrays: bool,
    /// Enable extensions. Only configures `implicit_some`,
    ///  `unwrap_newtypes`, and `unwrap_variant_newtypes` for now.
    pub extensions: Extensions,
    /// Enable compact arrays, which do not insert new lines and indentation
    ///  between the elements of an array
    pub compact_arrays: bool,
    /// Whether to serialize strings as escaped strings,
    ///  or fall back onto raw strings if necessary.
    pub escape_strings: bool,
    /// Enable compact structs, which do not insert new lines and indentation
    ///  between the fields of a struct
    pub compact_structs: bool,
    /// Enable compact maps, which do not insert new lines and indentation
    ///  between the entries of a struct
    pub compact_maps: bool,
    /// Enable explicit number type suffixes like `1u16`
    pub number_suffixes: bool,
    /// Additional path-based field metadata to serialize
    pub path_meta: Option<path_meta::Field>,
}

impl PrettyConfig {
    /// Creates a default [`PrettyConfig`].
    #[must_use]
    pub fn new() -> Self {
        Self::default()
    }

    /// Limits the pretty-formatting based on the number of indentations.
    /// I.e., with a depth limit of 5, starting with an element of depth
    /// (indentation level) 6, everything will be put into the same line,
    /// without pretty formatting.
    ///
    /// Default: [`usize::MAX`]
    #[must_use]
    pub fn depth_limit(mut self, depth_limit: usize) -> Self {
        self.depth_limit = depth_limit;

        self
    }

    /// Configures the newlines used for serialization.
    ///
    /// Default: `\r\n` on Windows, `\n` otherwise
    #[must_use]
    pub fn new_line(mut self, new_line: impl Into<Cow<'static, str>>) -> Self {
        self.new_line = new_line.into();

        self
    }

    /// Configures the string sequence used for indentation.
    ///
    /// Default: 4 spaces
    #[must_use]
    pub fn indentor(mut self, indentor: impl Into<Cow<'static, str>>) -> Self {
        self.indentor = indentor.into();

        self
    }

    /// Configures the string sequence used to separate items inline.
    ///
    /// Default: 1 space
    #[must_use]
    pub fn separator(mut self, separator: impl Into<Cow<'static, str>>) -> Self {
        self.separator = separator.into();

        self
    }

    /// Configures whether to emit struct names.
    ///
    /// See also [`Extensions::EXPLICIT_STRUCT_NAMES`] for the extension equivalent.
    ///
    /// Default: `false`
    #[must_use]
    pub fn struct_names(mut self, struct_names: bool) -> Self {
        self.struct_names = struct_names;

        self
    }

    /// Configures whether tuples are single- or multi-line.
    /// If set to `true`, tuples will have their fields indented and in new
    /// lines. If set to `false`, tuples will be serialized without any
    /// newlines or indentations.
    ///
    /// Default: `false`
    #[must_use]
    pub fn separate_tuple_members(mut self, separate_tuple_members: bool) -> Self {
        self.separate_tuple_members = separate_tuple_members;

        self
    }

    /// Configures whether a comment shall be added to every array element,
    /// indicating the index.
    ///
    /// Default: `false`
    #[must_use]
    pub fn enumerate_arrays(mut self, enumerate_arrays: bool) -> Self {
        self.enumerate_arrays = enumerate_arrays;

        self
    }

    /// Configures whether every array should be a single line (`true`)
    /// or a multi line one (`false`).
    ///
    /// When `false`, `["a","b"]` will serialize to
    /// ```
    /// [
    ///   "a",
    ///   "b",
    /// ]
    /// # ;
    /// ```
    /// When `true`, `["a","b"]` will instead serialize to
    /// ```
    /// ["a","b"]
    /// # ;
    /// ```
    ///
    /// Default: `false`
    #[must_use]
    pub fn compact_arrays(mut self, compact_arrays: bool) -> Self {
        self.compact_arrays = compact_arrays;

        self
    }

    /// Configures extensions
    ///
    /// Default: [`Extensions::empty()`]
    #[must_use]
    pub fn extensions(mut self, extensions: Extensions) -> Self {
        self.extensions = extensions;

        self
    }

    /// Configures whether strings should be serialized using escapes (true)
    /// or fall back to raw strings if the string contains a `"` (false).
    ///
    /// When `true`, `"a\nb"` will serialize to
    /// ```
    /// "a\nb"
    /// # ;
    /// ```
    /// When `false`, `"a\nb"` will instead serialize to
    /// ```
    /// "a
    /// b"
    /// # ;
    /// ```
    ///
    /// Default: `true`
    #[must_use]
    pub fn escape_strings(mut self, escape_strings: bool) -> Self {
        self.escape_strings = escape_strings;

        self
    }

    /// Configures whether every struct should be a single line (`true`)
    /// or a multi line one (`false`).
    ///
    /// When `false`, `Struct { a: 4, b: 2 }` will serialize to
    /// ```ignore
    /// Struct(
    ///     a: 4,
    ///     b: 2,
    /// )
    /// # ;
    /// ```
    /// When `true`, `Struct { a: 4, b: 2 }` will instead serialize to
    /// ```ignore
    /// Struct(a: 4, b: 2)
    /// # ;
    /// ```
    ///
    /// Default: `false`
    #[must_use]
    pub fn compact_structs(mut self, compact_structs: bool) -> Self {
        self.compact_structs = compact_structs;

        self
    }

    /// Configures whether every map should be a single line (`true`)
    /// or a multi line one (`false`).
    ///
    /// When `false`, a map with entries `{ "a": 4, "b": 2 }` will serialize to
    /// ```ignore
    /// {
    ///     "a": 4,
    ///     "b": 2,
    /// }
    /// # ;
    /// ```
    /// When `true`, a map with entries `{ "a": 4, "b": 2 }` will instead
    /// serialize to
    /// ```ignore
    /// {"a": 4, "b": 2}
    /// # ;
    /// ```
    ///
    /// Default: `false`
    #[must_use]
    pub fn compact_maps(mut self, compact_maps: bool) -> Self {
        self.compact_maps = compact_maps;

        self
    }

    /// Configures whether numbers should be printed without (`false`) or
    /// with (`true`) their explicit type suffixes.
    ///
    /// When `false`, the integer `12345u16` will serialize to
    /// ```ignore
    /// 12345
    /// # ;
    /// ```
    /// and the float `12345.6789f64` will serialize to
    /// ```ignore
    /// 12345.6789
    /// # ;
    /// ```
    /// When `true`, the integer `12345u16` will serialize to
    /// ```ignore
    /// 12345u16
    /// # ;
    /// ```
    /// and the float `12345.6789f64` will serialize to
    /// ```ignore
    /// 12345.6789f64
    /// # ;
    /// ```
    ///
    /// Default: `false`
    #[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"// GRCOV_EXCL_LINE
            },
            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,
        }
    }
}

/// The RON serializer.
///
/// You can just use [`to_string`] for deserializing a value.
/// If you want it pretty-printed, take a look at [`to_string_pretty`].
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>,
    // Tracks the number of opened implicit `Some`s, set to 0 on backtracking
    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> {
    /// Creates a new [`Serializer`].
    ///
    /// Most of the time you can just use [`to_string`] or
    /// [`to_string_pretty`].
    pub fn new(writer: W, config: Option<PrettyConfig>) -> Result<Self> {
        Self::with_options(writer, config, &Options::default())
    }

    /// Creates a new [`Serializer`].
    ///
    /// Most of the time you can just use [`to_string`] or
    /// [`to_string_pretty`].
    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,
        })
    }

    /// Unwrap the `Writer` from the `Serializer`.
    #[inline]
    pub fn into_inner(self) -> W {
        self.output
    }

    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((00), |(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| core::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((00), |(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)&nbsp;-> Result<()> {
        // TODO optimize
        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)&nbsp;-> Result<()> {
        // TODO optimize
        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(())
    }

    /// Checks if struct names should be emitted
    ///
    /// Note that when using the `explicit_struct_names` extension, this method will use an OR operation on the extension and the [`PrettyConfig::struct_names`] option. See also [`Extensions::EXPLICIT_STRUCT_NAMES`] for the extension equivalent.
    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 &'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)?;

        // Equivalent to v.fract() == 0.0
        // See: https://docs.rs/num-traits/0.2.19/src/num_traits/float.rs.html#459-465
        if v % 1. == 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)?;

        // Equivalent to v.fract() == 0.0
        // See: https://docs.rs/num-traits/0.2.19/src/num_traits/float.rs.html#459-465
        if v % 1. == 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<()> {
        // We need to fall back to escaping if the byte string would be invalid UTF-8
        if !self.escape_strings() {
            if let Ok(v) = core::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<()> {
        // We no longer need to keep track of the depth
        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)&nbsp;-> 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(selffalse))
    }

    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(selffalse))
    }

    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(selffalse))
    }

    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(selffalse))
    }
}

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()?;
        }

        // seq always disables `self.newtype_variant`
        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(())
    }
}

// Same thing but for tuple structs.
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()?;
        }

        // map always disables `self.newtype_variant`
        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 {
            core::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)
    }
}

Messung V0.5 in Prozent
C=95 H=90 G=92

¤ Dauer der Verarbeitung: 0.15 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002