pub mod error;
pub mod options;
pub(crate) mod quoting;
mod wrapping;
mod zmij_format;
use serde::ser::Error as _;
use serde::ser::{
self, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
SerializeTuple, SerializeTupleStruct, SerializeTupleVariant, Serializer,
};
use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt::{self, Write};
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use crate::long_strings::{NAME_FOLD_STR, NAME_LIT_STR};
use crate::{
ArcAnchor, ArcRecursion, ArcRecursive, ArcWeakAnchor, Commented, FlowMap, FlowSeq,
RcAnchor, RcRecursion, RcRecursive, RcWeakAnchor, SpaceAfter,
};
use self::options::{FOLDED_WRAP_CHARS, MIN_FOLD_CHARS, SerializerOptions};
use base64::{Engine as _, engine::general_purpose::STANDARD as B64};
use nohash_hasher::BuildNoHashHasher;
pub use self::error::Error;
use self::quoting::{is_plain_safe, is_plain_value_safe};
pub type Result<T> = std::result::Result<T, Error>;
pub use crate::long_strings::{FoldStr, FoldString, LitStr, LitString};
struct RcRecursivePayload<'a, T>(&'a Rc<RefCell<Option<T>>>);
struct ArcRecursivePayload<'a, T>(&'a Arc<Mutex<Option<T>>>);
impl<T: Serialize> Serialize for RcRecursivePayload<'_, T> {
fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
let borrowed = self.0.borrow();
if let Some(value) = borrowed.as_ref() {
value.serialize(s)
} else {
s.serialize_unit()
}
}
}
impl<T: Serialize> Serialize for ArcRecursivePayload<'_, T> {
fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
let guard = self
.0
.lock()
.map_err(|_| ser::Error::custom("recursive Arc anchor mutex poisoned"))?;
if let Some(value) = guard.as_ref() {
value.serialize(s)
} else {
s.serialize_unit()
}
}
}
const NAME_TUPLE_ANCHOR: &str = "__yaml_anchor";
const NAME_TUPLE_WEAK: &str = "__yaml_weak_anchor";
const NAME_FLOW_SEQ: &str = "__yaml_flow_seq";
const NAME_FLOW_MAP: &str = "__yaml_flow_map";
const NAME_TUPLE_COMMENTED: &str = "__yaml_commented";
const NAME_SPACE_AFTER: &str = "__yaml_space_after";
impl<T: Serialize> Serialize for RcAnchor<T> {
fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
let mut ts = s.serialize_tuple_struct(NAME_TUPLE_ANCHOR, 2)?;
let ptr = Rc::as_ptr(&self.0) as usize;
ts.serialize_field(&ptr)?;
ts.serialize_field(&*self.0)?;
ts.end()
}
}
impl<T: Serialize> Serialize for ArcAnchor<T> {
fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
let mut ts = s.serialize_tuple_struct(NAME_TUPLE_ANCHOR, 2)?;
let ptr = Arc::as_ptr(&self.0) as usize;
ts.serialize_field(&ptr)?;
ts.serialize_field(&*self.0)?;
ts.end()
}
}
impl<T: Serialize> Serialize for RcRecursive<T> {
fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
let mut ts = s.serialize_tuple_struct(NAME_TUPLE_ANCHOR, 2)?;
let ptr = Rc::as_ptr(&self.0) as usize;
ts.serialize_field(&ptr)?;
let borrowed = self.0.borrow();
let value = borrowed
.as_ref()
.ok_or_else(|| ser::Error::custom("recursive Rc anchor not initialized"))?;
ts.serialize_field(value)?;
ts.end()
}
}
impl<T: Serialize> Serialize for ArcRecursive<T> {
fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
let mut ts = s.serialize_tuple_struct(NAME_TUPLE_ANCHOR, 2)?;
let ptr = Arc::as_ptr(&self.0) as usize;
ts.serialize_field(&ptr)?;
let guard = self
.0
.lock()
.map_err(|_| ser::Error::custom("recursive Arc anchor mutex poisoned"))?;
let value = guard
.as_ref()
.ok_or_else(|| ser::Error::custom("recursive Arc anchor not initialized"))?;
ts.serialize_field(value)?;
ts.end()
}
}
impl<T: Serialize> Serialize for RcWeakAnchor<T> {
fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
let up = self.0.upgrade();
let mut ts = s.serialize_tuple_struct(NAME_TUPLE_WEAK, 3)?;
let ptr = self.0.as_ptr() as usize;
ts.serialize_field(&ptr)?;
ts.serialize_field(&up.is_some())?;
if let Some(rc) = up {
ts.serialize_field(&*rc)?;
} else {
ts.serialize_field(&())?; }
ts.end()
}
}
impl<T: Serialize> Serialize for ArcWeakAnchor<T> {
fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
let up = self.0.upgrade();
let mut ts = s.serialize_tuple_struct(NAME_TUPLE_WEAK, 3)?;
let ptr = self.0.as_ptr() as usize;
ts.serialize_field(&ptr)?;
ts.serialize_field(&up.is_some())?;
if let Some(arc) = up {
ts.serialize_field(&*arc)?;
} else {
ts.serialize_field(&())?;
}
ts.end()
}
}
impl<T: Serialize> Serialize for RcRecursion<T> {
fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
let up = self.0.upgrade();
let mut ts = s.serialize_tuple_struct(NAME_TUPLE_WEAK, 3)?;
let ptr = self.0.as_ptr() as usize;
ts.serialize_field(&ptr)?;
ts.serialize_field(&up.is_some())?;
if let Some(rc) = up {
ts.serialize_field(&RcRecursivePayload(&rc))?;
} else {
ts.serialize_field(&())?;
}
ts.end()
}
}
impl<T: Serialize> Serialize for ArcRecursion<T> {
fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
let up = self.0.upgrade();
let mut ts = s.serialize_tuple_struct(NAME_TUPLE_WEAK, 3)?;
let ptr = self.0.as_ptr() as usize;
ts.serialize_field(&ptr)?;
ts.serialize_field(&up.is_some())?;
if let Some(arc) = up {
ts.serialize_field(&ArcRecursivePayload(&arc))?;
} else {
ts.serialize_field(&())?;
}
ts.end()
}
}
impl<T: Serialize> Serialize for FlowSeq<T> {
fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
s.serialize_newtype_struct(NAME_FLOW_SEQ, &self.0)
}
}
impl<T: Serialize> Serialize for FlowMap<T> {
fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
s.serialize_newtype_struct(NAME_FLOW_MAP, &self.0)
}
}
impl<T: Serialize> Serialize for SpaceAfter<T> {
fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
s.serialize_newtype_struct(NAME_SPACE_AFTER, &self.0)
}
}
impl<T: Serialize> Serialize for Commented<T> {
fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
let mut ts = s.serialize_tuple_struct(NAME_TUPLE_COMMENTED, 2)?;
ts.serialize_field(&self.1)?; ts.serialize_field(&self.0)?; ts.end()
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
enum PendingFlow {
AnySeq,
AnyMap,
}
#[derive(Clone, Copy, PartialEq, Eq)]
enum StrStyle {
Literal, Folded, }
type AnchorId = u32;
pub struct YamlSerializer<'a, W: Write> {
out: &'a mut W,
indent_step: usize,
min_fold_chars: usize,
folded_wrap_col: usize,
depth: usize,
at_line_start: bool,
anchors: HashMap<usize, AnchorId, BuildNoHashHasher<usize>>,
next_anchor_id: AnchorId,
pending_anchor_id: Option<AnchorId>,
anchor_gen: Option<fn(usize) -> String>,
custom_anchor_names: Option<Vec<String>>,
pending_flow: Option<PendingFlow>,
in_flow: usize,
pending_str_style: Option<StrStyle>,
pending_str_from_auto: bool,
pending_inline_comment: Option<String>,
tagged_enums: bool,
empty_as_braces: bool,
compact_list_indent: bool,
prefer_block_scalars: bool,
pending_inline_map: bool,
pending_space_after_colon: bool,
inline_map_after_dash: bool,
last_value_was_block: bool,
after_dash_depth: Option<usize>,
current_map_depth: Option<usize>,
quote_all: bool,
yaml_12: bool,
doc_started: bool,
}
impl<'a, W: Write> YamlSerializer<'a, W> {
pub fn new(out: &'a mut W) -> Self {
Self {
out,
indent_step: 2,
min_fold_chars: MIN_FOLD_CHARS,
folded_wrap_col: FOLDED_WRAP_CHARS,
depth: 0,
at_line_start: true,
anchors: HashMap::with_hasher(BuildNoHashHasher::default()),
next_anchor_id: 1,
pending_anchor_id: None,
anchor_gen: None,
custom_anchor_names: None,
pending_flow: None,
in_flow: 0,
pending_str_style: None,
pending_str_from_auto: false,
pending_inline_comment: None,
tagged_enums: false,
empty_as_braces: true,
compact_list_indent: false,
prefer_block_scalars: true,
pending_inline_map: false,
pending_space_after_colon: false,
inline_map_after_dash: false,
last_value_was_block: false,
after_dash_depth: None,
current_map_depth: None,
quote_all: false,
yaml_12: false,
doc_started: false,
}
}
pub fn with_indent(out: &'a mut W, indent_step: usize) -> Self {
let mut s = Self::new(out);
s.indent_step = indent_step;
s
}
#[allow(deprecated)]
pub fn with_options(out: &'a mut W, options: &mut SerializerOptions) -> Self {
let mut s = Self::new(out);
s.indent_step = options.indent_step;
s.min_fold_chars = options.min_fold_chars;
s.folded_wrap_col = options.folded_wrap_chars;
s.anchor_gen = options.anchor_generator.take();
s.tagged_enums = options.tagged_enums;
s.empty_as_braces = options.empty_as_braces;
s.compact_list_indent = options.compact_list_indent;
s.prefer_block_scalars = options.prefer_block_scalars;
s.quote_all = options.quote_all;
s.yaml_12 = options.yaml_12;
s
}
#[inline]
fn needs_double_quotes(s: &str) -> bool {
s.chars().any(|c| {
c == '\'' || c == '\\' || c.is_control() })
}
fn write_single_quoted(&mut self, s: &str) -> Result<()> {
self.out.write_char('\'')?;
for ch in s.chars() {
if ch == '\'' {
self.out.write_str("''")?; } else {
self.out.write_char(ch)?;
}
}
self.out.write_char('\'')?;
Ok(())
}
#[inline]
fn write_end_of_scalar(&mut self) -> Result<()> {
if self.in_flow == 0 {
if let Some(c) = self.pending_inline_comment.take() {
self.out.write_str(" # ")?;
self.out.write_str(&c)?;
}
self.newline()?;
}
Ok(())
}
#[inline]
fn alloc_anchor_for(&mut self, ptr: usize) -> (AnchorId, bool) {
match self.anchors.entry(ptr) {
std::collections::hash_map::Entry::Occupied(e) => (*e.get(), false),
std::collections::hash_map::Entry::Vacant(v) => {
let id = self.next_anchor_id;
self.next_anchor_id = self.next_anchor_id.saturating_add(1);
if let Some(generator) = self.anchor_gen {
let name = generator(id as usize);
self.custom_anchor_names
.get_or_insert_with(Vec::new)
.push(name);
}
v.insert(id);
(id, true)
}
}
}
#[inline]
fn write_anchor_name(&mut self, id: AnchorId) -> Result<()> {
if let Some(names) = &self.custom_anchor_names {
let idx = id as usize - 1;
if let Some(name) = names.get(idx) {
self.out.write_str(name)?;
} else {
write!(self.out, "a{}", id)?;
}
} else {
write!(self.out, "a{}", id)?;
}
Ok(())
}
#[inline]
fn write_space_if_pending(&mut self) -> Result<()> {
if self.pending_space_after_colon {
self.out.write_char(' ')?;
self.pending_space_after_colon = false;
}
self.last_value_was_block = false;
Ok(())
}
#[inline]
fn write_indent(&mut self, depth: usize) -> Result<()> {
if self.at_line_start {
if !self.doc_started {
self.doc_started = true;
if self.yaml_12 {
self.out.write_str("%YAML 1.2\n")?;
self.at_line_start = true;
}
}
for _k in 0..self.indent_step * depth {
self.out.write_char(' ')?;
}
self.at_line_start = false;
}
Ok(())
}
#[inline]
fn newline(&mut self) -> Result<()> {
self.out.write_char('\n')?;
self.at_line_start = true;
Ok(())
}
fn write_folded_block(&mut self, s: &str, indent: usize) -> Result<()> {
self::wrapping::write_folded_block(
self.out,
s,
indent,
self.indent_step,
self.folded_wrap_col,
)?;
self.at_line_start = true;
Ok(())
}
fn write_plain_or_quoted(&mut self, s: &str) -> Result<()> {
if self.quote_all {
if Self::needs_double_quotes(s) {
self.write_quoted(s)
} else {
self.write_single_quoted(s)
}
} else if is_plain_safe(s) {
self.out.write_str(s)?;
Ok(())
} else {
self.write_quoted(s)
}
}
fn write_quoted(&mut self, s: &str) -> Result<()> {
self.out.write_char('"')?;
for ch in s.chars() {
match ch {
'\\' => self.out.write_str("\\\\")?,
'"' => self.out.write_str("\\\"")?,
'\0' => self.out.write_str("\\0")?,
'\u{7}' => self.out.write_str("\\a")?,
'\u{8}' => self.out.write_str("\\b")?,
'\t' => self.out.write_str("\\t")?,
'\n' => self.out.write_str("\\n")?,
'\u{b}' => self.out.write_str("\\v")?,
'\u{c}' => self.out.write_str("\\f")?,
'\r' => self.out.write_str("\\r")?,
'\u{1b}' => self.out.write_str("\\e")?,
'\u{FEFF}' => self.out.write_str("\\uFEFF")?,
'\u{0085}' => self.out.write_str("\\N")?,
'\u{2028}' => self.out.write_str("\\L")?,
'\u{2029}' => self.out.write_str("\\P")?,
c if (c as u32) <= 0xFF
&& (c.is_control() || (0x7F..=0x9F).contains(&(c as u32))) =>
{
write!(self.out, "\\x{:02X}", c as u32)?
}
c if (c as u32) <= 0xFFFF
&& (c.is_control() || (0x7F..=0x9F).contains(&(c as u32))) =>
{
write!(self.out, "\\u{:04X}", c as u32)?
}
c => self.out.write_char(c)?,
}
}
self.out.write_char('"')?;
Ok(())
}
#[inline]
fn write_plain_or_quoted_value(&mut self, s: &str) -> Result<()> {
if self.quote_all {
if Self::needs_double_quotes(s) {
self.write_quoted(s)
} else {
self.write_single_quoted(s)
}
} else if is_plain_value_safe(s, self.yaml_12, self.in_flow > 0) {
self.out.write_str(s)?;
Ok(())
} else {
self.write_quoted(s)
}
}
fn serialize_tagged_scalar(&mut self, enum_name: &str, variant: &str) -> Result<()> {
self.write_scalar_prefix_if_anchor()?;
if self.at_line_start {
self.write_indent(self.depth)?;
}
self.out.write_str("!!")?;
self.out.write_str(enum_name)?;
self.out.write_char(' ')?;
self.write_plain_or_quoted_value(variant)?;
self.write_end_of_scalar()
}
#[inline]
fn write_scalar_prefix_if_anchor(&mut self) -> Result<()> {
if let Some(id) = self.pending_anchor_id.take() {
if self.at_line_start {
self.write_indent(self.depth)?;
}
self.out.write_char('&')?;
self.write_anchor_name(id)?;
self.out.write_char(' ')?;
}
Ok(())
}
#[inline]
fn write_anchor_for_complex_node(&mut self) -> Result<()> {
if let Some(id) = self.pending_anchor_id.take() {
if self.at_line_start {
self.write_indent(self.depth)?;
}
self.write_space_if_pending()?;
self.out.write_char('&')?;
self.write_anchor_name(id)?;
self.newline()?;
}
Ok(())
}
#[inline]
fn write_alias_id(&mut self, id: AnchorId) -> Result<()> {
if self.at_line_start {
self.write_indent(self.depth)?;
}
self.write_space_if_pending()?;
self.out.write_char('*')?;
self.write_anchor_name(id)?;
self.write_end_of_scalar()?;
Ok(())
}
#[inline]
fn take_flow_for_seq(&mut self) -> bool {
if self.in_flow > 0 {
true
} else {
matches!(self.pending_flow.take(), Some(PendingFlow::AnySeq))
}
}
#[inline]
fn take_flow_for_map(&mut self) -> bool {
if self.in_flow > 0 {
true
} else {
matches!(self.pending_flow.take(), Some(PendingFlow::AnyMap))
}
}
#[inline]
fn with_in_flow<T>(&mut self, f: impl FnOnce(&mut Self) -> Result<T>) -> Result<T> {
self.in_flow += 1;
let r = f(self);
self.in_flow -= 1;
r
}
}
impl<'a, 'b, W: Write> Serializer for &'a mut YamlSerializer<'b, W> {
type Ok = ();
type Error = Error;
type SerializeSeq = SeqSer<'a, 'b, W>;
type SerializeTuple = SeqSer<'a, 'b, W>;
type SerializeTupleStruct = TupleSer<'a, 'b, W>;
type SerializeTupleVariant = TupleVariantSer<'a, 'b, W>;
type SerializeMap = MapSer<'a, 'b, W>;
type SerializeStruct = MapSer<'a, 'b, W>;
type SerializeStructVariant = StructVariantSer<'a, 'b, W>;
fn serialize_bool(self, v: bool) -> Result<()> {
self.write_space_if_pending()?;
self.write_scalar_prefix_if_anchor()?;
if self.at_line_start {
self.write_indent(self.depth)?;
}
self.out.write_str(if v { "true" } else { "false" })?;
self.write_end_of_scalar()?;
Ok(())
}
fn serialize_i8(self, v: i8) -> Result<()> {
self.serialize_i64(v as i64)
}
fn serialize_i16(self, v: i16) -> Result<()> {
self.serialize_i64(v as i64)
}
fn serialize_i32(self, v: i32) -> Result<()> {
self.serialize_i64(v as i64)
}
fn serialize_i64(self, v: i64) -> Result<()> {
self.write_space_if_pending()?;
self.write_scalar_prefix_if_anchor()?;
if self.at_line_start {
self.write_indent(self.depth)?;
}
write!(self.out, "{}", v)?;
self.write_end_of_scalar()?;
Ok(())
}
fn serialize_i128(self, v: i128) -> Result<()> {
self.write_space_if_pending()?;
self.write_scalar_prefix_if_anchor()?;
if self.at_line_start {
self.write_indent(self.depth)?;
}
write!(self.out, "{}", v)?;
self.write_end_of_scalar()?;
Ok(())
}
fn serialize_u8(self, v: u8) -> Result<()> {
self.serialize_u64(v as u64)
}
fn serialize_u16(self, v: u16) -> Result<()> {
self.serialize_u64(v as u64)
}
fn serialize_u32(self, v: u32) -> Result<()> {
self.serialize_u64(v as u64)
}
fn serialize_u64(self, v: u64) -> Result<()> {
self.write_space_if_pending()?;
self.write_scalar_prefix_if_anchor()?;
if self.at_line_start {
self.write_indent(self.depth)?;
}
write!(self.out, "{}", v)?;
self.write_end_of_scalar()?;
Ok(())
}
fn serialize_u128(self, v: u128) -> Result<()> {
self.write_space_if_pending()?;
self.write_scalar_prefix_if_anchor()?;
if self.at_line_start {
self.write_indent(self.depth)?;
}
write!(self.out, "{}", v)?;
self.write_end_of_scalar()?;
Ok(())
}
fn serialize_f32(self, v: f32) -> Result<()> {
self.write_space_if_pending()?;
self.write_scalar_prefix_if_anchor()?;
if self.at_line_start {
self.write_indent(self.depth)?;
}
zmij_format::write_float_string(self.out, v)?;
self.write_end_of_scalar()
}
fn serialize_f64(self, v: f64) -> Result<()> {
self.write_space_if_pending()?;
self.write_scalar_prefix_if_anchor()?;
if self.at_line_start {
self.write_indent(self.depth)?;
}
zmij_format::write_float_string(self.out, v)?;
self.write_end_of_scalar()
}
fn serialize_char(self, v: char) -> Result<()> {
self.write_space_if_pending()?;
let mut buf = [0u8; 4];
self.serialize_str(v.encode_utf8(&mut buf))
}
fn serialize_str(self, v: &str) -> Result<()> {
#[inline]
fn block_indent_indicator_digit(indent_n: usize) -> Result<char> {
char::from_digit(indent_n as u32, 10).ok_or_else(|| {
Error::custom("indentation indicator must be a single digit (1..=9)")
})
}
if self.pending_str_style.is_none() && self.in_flow == 0 && !self.quote_all {
use self::quoting::is_plain_value_safe;
if v.contains('\n') {
if self.prefer_block_scalars {
let char_len = v.chars().count();
if char_len > self.folded_wrap_col {
self.pending_str_style = Some(StrStyle::Literal);
self.pending_str_from_auto = true;
} else {
let trimmed = v.trim_end_matches('\n');
let normalized = trimmed.replace('\n', " ");
if is_plain_value_safe(&normalized, self.yaml_12, false) {
self.pending_str_style = Some(StrStyle::Literal);
self.pending_str_from_auto = true;
}
}
}
} else if self.prefer_block_scalars {
let needs_quoting = !is_plain_value_safe(v, self.yaml_12, false);
if !needs_quoting {
if v.chars().count() > self.folded_wrap_col {
self.pending_str_style = Some(StrStyle::Folded);
self.pending_str_from_auto = true;
}
}
}
}
if let Some(style) = self.pending_str_style.take() {
let was_map_value = self.pending_space_after_colon;
self.write_space_if_pending()?;
let base = if was_map_value {
self.current_map_depth.unwrap_or(self.depth)
} else {
self.after_dash_depth.unwrap_or(self.depth)
};
if self.at_line_start {
self.write_indent(base)?;
}
let body_base = base + 1;
let indent_n = self.indent_step * body_base;
let content_trimmed = v.trim_end_matches('\n');
let first_line_spaces = self::wrapping::first_line_leading_spaces(content_trimmed);
let needs_indicator = first_line_spaces > 0;
if needs_indicator && indent_n > 9 {
self.pending_str_style = None;
self.pending_str_from_auto = false;
self.write_scalar_prefix_if_anchor()?;
self.write_plain_or_quoted_value(v)?;
self.write_end_of_scalar()?;
return Ok(());
}
match style {
StrStyle::Literal => {
let content = v.trim_end_matches('\n');
let trailing_nl = v.len() - content.len();
self.out.write_char('|')?;
if needs_indicator {
let digit = block_indent_indicator_digit(indent_n)?;
self.out.write_char(digit)?;
}
match trailing_nl {
0 => self.out.write_char('-')?,
1 => {} _ => self.out.write_char('+')?,
}
self.newline()?;
let mut indent_buf: String = String::new();
let spaces = self.indent_step * body_base;
if spaces > 0 {
indent_buf.reserve(spaces);
for _ in 0..spaces {
indent_buf.push(' ');
}
}
let indent_str = indent_buf.as_str();
if content.is_empty() {
if trailing_nl >= 1 {
self.out.write_str(indent_str)?;
self.at_line_start = false;
self.newline()?;
}
} else {
for line in content.split('\n') {
self.out.write_str(indent_str)?;
self.at_line_start = false;
self.out.write_str(line)?;
self.newline()?;
}
if trailing_nl >= 2 {
for _ in 0..(trailing_nl - 1) {
self.out.write_str(indent_str)?;
self.at_line_start = false;
self.newline()?;
}
}
}
}
StrStyle::Folded => {
self.out.write_char('>')?;
if needs_indicator {
let digit = block_indent_indicator_digit(indent_n)?;
self.out.write_char(digit)?;
}
if self.pending_str_from_auto {
let content = v.trim_end_matches('\n');
let trailing_nl = v.len() - content.len();
match trailing_nl {
0 => self.out.write_char('-')?,
1 => {} _ => self.out.write_char('+')?,
}
}
self.newline()?;
self.write_folded_block(v, body_base)?;
}
}
self.pending_str_from_auto = false;
return Ok(());
}
self.write_space_if_pending()?;
self.write_scalar_prefix_if_anchor()?;
if self.at_line_start {
self.write_indent(self.depth)?;
}
if v.len() == 1
&& let Some(ch) = v.chars().next()
&& (ch == '.' || ch == '#' || ch == '-')
{
self.out.write_char('\'')?;
self.out.write_char(ch)?;
self.out.write_char('\'')?;
self.write_end_of_scalar()?;
return Ok(());
}
self.write_plain_or_quoted_value(v)?;
self.write_end_of_scalar()?;
Ok(())
}
fn serialize_bytes(self, v: &[u8]) -> Result<()> {
if self.at_line_start {
let mut seq = self.serialize_seq(Some(v.len()))?;
for b in v {
serde::ser::SerializeSeq::serialize_element(&mut seq, b)?;
}
return serde::ser::SerializeSeq::end(seq);
}
self.write_space_if_pending()?;
self.write_scalar_prefix_if_anchor()?;
self.out.write_str("!!binary ")?;
let mut s = String::new();
B64.encode_string(v, &mut s);
self.out.write_str(&s)?;
self.write_end_of_scalar()?;
Ok(())
}
fn serialize_none(self) -> Result<()> {
self.write_space_if_pending()?;
self.last_value_was_block = false;
if self.at_line_start {
self.write_indent(self.depth)?;
}
self.out.write_str("null")?;
self.write_end_of_scalar()?;
Ok(())
}
fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<()> {
value.serialize(self)
}
fn serialize_unit(self) -> Result<()> {
self.write_space_if_pending()?;
self.last_value_was_block = false;
if self.at_line_start {
self.write_indent(self.depth)?;
}
self.out.write_str("null")?;
self.write_end_of_scalar()?;
Ok(())
}
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.write_space_if_pending()?;
if self.tagged_enums {
self.serialize_tagged_scalar(name, variant)
} else {
self.serialize_str(variant)
}
}
fn serialize_newtype_struct<T: ?Sized + Serialize>(
self,
name: &'static str,
value: &T,
) -> Result<()> {
match name {
NAME_FLOW_SEQ => {
self.pending_flow = Some(PendingFlow::AnySeq);
return value.serialize(self);
}
NAME_FLOW_MAP => {
self.pending_flow = Some(PendingFlow::AnyMap);
return value.serialize(self);
}
NAME_LIT_STR => {
let mut cap = StrCapture::default();
value.serialize(&mut cap)?;
let s = cap.finish()?;
self.pending_str_style = Some(StrStyle::Literal);
return self.serialize_str(&s);
}
NAME_FOLD_STR => {
let mut cap = StrCapture::default();
value.serialize(&mut cap)?;
let s = cap.finish()?;
let is_multiline = s.contains('\n');
if !is_multiline && s.len() < self.min_fold_chars {
return self.serialize_str(&s);
}
self.pending_str_style = Some(StrStyle::Folded);
return self.serialize_str(&s);
}
NAME_SPACE_AFTER => {
let result = value.serialize(&mut *self);
if self.in_flow == 0 {
self.newline()?;
}
return result;
}
_ => {}
}
value.serialize(self)
}
fn serialize_newtype_variant<T: ?Sized + Serialize>(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
value: &T,
) -> Result<()> {
if self.pending_space_after_colon {
self.pending_space_after_colon = false;
self.newline()?;
let base = self.current_map_depth.unwrap_or(self.depth);
self.write_indent(base + 1)?;
self.write_plain_or_quoted(variant)?;
self.out.write_str(":")?;
self.pending_space_after_colon = true;
self.at_line_start = false;
self.pending_inline_map = false;
let prev_map_depth = self.current_map_depth.replace(base + 1);
let res = value.serialize(&mut *self);
self.current_map_depth = prev_map_depth;
return res;
}
if self.at_line_start {
self.write_indent(self.depth)?;
}
self.write_plain_or_quoted(variant)?;
self.out.write_str(":")?;
self.pending_space_after_colon = true;
self.at_line_start = false;
self.pending_inline_map = false;
if let Some(d) = self.after_dash_depth.take() {
let prev_map_depth = self.current_map_depth.replace(d + 1);
let res = value.serialize(&mut *self);
self.current_map_depth = prev_map_depth;
res
} else {
value.serialize(&mut *self)
}
}
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
let flow = self.take_flow_for_seq();
if flow {
self.write_scalar_prefix_if_anchor()?;
self.write_space_if_pending()?;
if self.at_line_start {
self.write_indent(self.depth)?;
}
self.out.write_str("[")?;
self.at_line_start = false;
let depth_next = self.depth; Ok(SeqSer {
ser: self,
depth: depth_next,
flow: true,
first: true,
})
} else {
let was_inline_value = !self.at_line_start;
if self.pending_space_after_colon
&& self.last_value_was_block
&& self.pending_anchor_id.is_none()
{
self.pending_space_after_colon = false;
if !self.at_line_start {
self.newline()?;
}
self.last_value_was_block = false;
}
let inline_first = (!self.at_line_start)
&& self.after_dash_depth.is_some()
&& !self.pending_space_after_colon;
self.write_anchor_for_complex_node()?;
if inline_first {
self.at_line_start = false;
} else if was_inline_value {
}
let base = if inline_first {
self.after_dash_depth.unwrap_or(self.depth)
} else if was_inline_value && self.current_map_depth.is_some() {
self.current_map_depth.unwrap_or(self.depth)
} else {
self.depth
};
let depth_next = if inline_first {
base + 1
} else if was_inline_value {
if self.compact_list_indent && self.current_map_depth.is_some() {
base
} else {
base + 1
}
} else {
base
};
self.pending_inline_comment = None;
Ok(SeqSer {
ser: self,
depth: depth_next,
flow: false,
first: true,
})
}
}
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
self.serialize_seq(Some(len))
}
fn serialize_tuple_struct(
self,
name: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleStruct> {
if name == NAME_TUPLE_ANCHOR {
Ok(TupleSer::anchor_strong(self))
} else if name == NAME_TUPLE_WEAK {
Ok(TupleSer::anchor_weak(self))
} else if name == NAME_TUPLE_COMMENTED {
Ok(TupleSer::commented(self))
} else {
Ok(TupleSer::normal(self))
}
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleVariant> {
if self.pending_space_after_colon {
self.pending_space_after_colon = false;
self.newline()?;
let base = self.current_map_depth.unwrap_or(self.depth) + 1;
self.write_indent(base)?;
self.write_plain_or_quoted(variant)?;
self.out.write_str(":\n")?;
self.at_line_start = true;
let depth_next = base + 1;
return Ok(TupleVariantSer {
ser: self,
depth: depth_next,
});
}
if self.at_line_start {
self.write_indent(self.depth)?;
}
self.write_plain_or_quoted(variant)?;
self.out.write_str(":\n")?;
self.at_line_start = true;
let mut depth_next = self.depth + 1;
if let Some(d) = self.after_dash_depth.take() {
depth_next = d + 2;
self.pending_inline_map = false;
}
Ok(TupleVariantSer {
ser: self,
depth: depth_next,
})
}
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
let flow = self.take_flow_for_map();
if flow {
self.write_scalar_prefix_if_anchor()?;
self.write_space_if_pending()?;
if self.at_line_start {
self.write_indent(self.depth)?;
}
self.out.write_str("{")?;
self.at_line_start = false;
let depth_next = self.depth;
Ok(MapSer {
ser: self,
depth: depth_next,
flow: true,
first: true,
last_key_complex: false,
align_after_dash: false,
inline_value_start: false,
})
} else {
let inline_first = self.pending_inline_map;
let was_inline_value = self.pending_space_after_colon;
let mut forced_newline = false;
if was_inline_value && self.last_value_was_block && self.pending_anchor_id.is_none() {
self.pending_space_after_colon = false;
if !self.at_line_start {
self.newline()?;
}
forced_newline = true;
self.last_value_was_block = false;
}
self.write_anchor_for_complex_node()?;
if inline_first {
self.pending_inline_map = false;
self.inline_map_after_dash = true;
} else if was_inline_value {
let known_empty = matches!(_len, Some(0));
let known_non_empty = matches!(_len, Some(n) if n > 0);
if !self.empty_as_braces || known_non_empty {
self.pending_space_after_colon = false;
if !self.at_line_start {
self.newline()?;
}
} else if !known_empty {
}
}
let base = if inline_first {
self.after_dash_depth.unwrap_or(self.depth)
} else if was_inline_value && self.current_map_depth.is_some() {
self.current_map_depth.unwrap_or(self.depth)
} else {
self.depth
};
let depth_next = if inline_first || was_inline_value {
base + 1
} else {
base
};
let inline_value_start_flag = was_inline_value
&& self.empty_as_braces
&& _len.is_none()
&& !inline_first
&& !forced_newline;
Ok(MapSer {
ser: self,
depth: depth_next,
flow: false,
first: true,
last_key_complex: false,
align_after_dash: inline_first,
inline_value_start: inline_value_start_flag,
})
}
}
fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
self.serialize_map(Some(_len))
}
fn serialize_struct_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
_len: usize,
) -> Result<Self::SerializeStructVariant> {
let _was_inline_value = !self.at_line_start;
if self.pending_space_after_colon {
self.pending_space_after_colon = false;
self.newline()?;
let base = self.current_map_depth.unwrap_or(self.depth) + 1;
self.write_indent(base)?;
self.write_plain_or_quoted(variant)?;
self.out.write_str(":\n")?;
self.at_line_start = true;
let depth_next = base + 1;
return Ok(StructVariantSer {
ser: self,
depth: depth_next,
});
}
if self.at_line_start {
self.write_indent(self.depth)?;
}
self.write_plain_or_quoted(variant)?;
self.out.write_str(":\n")?;
self.at_line_start = true;
let mut depth_next = self.depth + 1;
if let Some(d) = self.after_dash_depth.take() {
depth_next = d + 2;
self.pending_inline_map = false;
}
Ok(StructVariantSer {
ser: self,
depth: depth_next,
})
}
}
pub struct SeqSer<'a, 'b, W: Write> {
ser: &'a mut YamlSerializer<'b, W>,
depth: usize,
flow: bool,
first: bool,
}
impl<'a, 'b, W: Write> SerializeTuple for SeqSer<'a, 'b, W> {
type Ok = ();
type Error = Error;
fn serialize_element<T: ?Sized + Serialize>(&mut self, v: &T) -> Result<()> {
SerializeSeq::serialize_element(self, v)
}
fn end(self) -> Result<()> {
SerializeSeq::end(self)
}
}
impl<'a, 'b, W: Write> SerializeSeq for SeqSer<'a, 'b, W> {
type Ok = ();
type Error = Error;
fn serialize_element<T: ?Sized + Serialize>(&mut self, v: &T) -> Result<()> {
if self.flow {
if !self.first {
self.ser.out.write_str(", ")?;
}
self.ser.with_in_flow(|s| v.serialize(s))?;
} else {
if self.first && self.ser.pending_space_after_colon {
self.ser.pending_space_after_colon = false;
if !self.ser.at_line_start {
self.ser.newline()?;
}
}
if !self.first && self.ser.inline_map_after_dash {
self.ser.inline_map_after_dash = false;
}
if self.first && (!self.ser.at_line_start || self.ser.pending_inline_map) {
} else {
self.ser.write_indent(self.depth)?;
}
self.ser.out.write_str("- ")?;
self.ser.at_line_start = false;
if self.first && self.ser.inline_map_after_dash {
self.ser.inline_map_after_dash = false;
}
self.ser.after_dash_depth = Some(self.depth);
self.ser.pending_inline_map = true;
v.serialize(&mut *self.ser)?;
}
self.first = false;
Ok(())
}
fn end(self) -> Result<()> {
if self.flow {
let me = self;
me.ser.out.write_str("]")?;
if me.ser.in_flow == 0 {
me.ser.newline()?;
}
} else if self.first {
if self.ser.empty_as_braces {
if self.ser.pending_space_after_colon {
self.ser.out.write_str(" ")?;
self.ser.pending_space_after_colon = false;
} else if self.ser.at_line_start {
self.ser.write_indent(self.depth)?;
}
self.ser.out.write_str("[]")?;
self.ser.newline()?;
} else {
self.ser.pending_space_after_colon = false;
self.ser.newline()?;
}
} else {
self.ser.last_value_was_block = true;
self.ser.pending_inline_map = false;
self.ser.after_dash_depth = None;
self.ser.inline_map_after_dash = false;
}
Ok(())
}
}
pub struct TupleSer<'a, 'b, W: Write> {
ser: &'a mut YamlSerializer<'b, W>,
kind: TupleKind,
idx: usize,
depth_for_normal: usize,
strong_alias_id: Option<AnchorId>,
weak_present: bool,
skip_third: bool,
weak_alias_id: Option<AnchorId>,
comment_text: Option<String>,
}
enum TupleKind {
Normal, AnchorStrong, AnchorWeak, Commented, }
impl<'a, 'b, W: Write> TupleSer<'a, 'b, W> {
fn normal(ser: &'a mut YamlSerializer<'b, W>) -> Self {
let depth_next = ser.depth + 1;
Self {
ser,
kind: TupleKind::Normal,
idx: 0,
depth_for_normal: depth_next,
strong_alias_id: None,
weak_present: false,
skip_third: false,
weak_alias_id: None,
comment_text: None,
}
}
fn anchor_strong(ser: &'a mut YamlSerializer<'b, W>) -> Self {
Self {
ser,
kind: TupleKind::AnchorStrong,
idx: 0,
depth_for_normal: 0,
strong_alias_id: None,
weak_present: false,
skip_third: false,
weak_alias_id: None,
comment_text: None,
}
}
fn anchor_weak(ser: &'a mut YamlSerializer<'b, W>) -> Self {
Self {
ser,
kind: TupleKind::AnchorWeak,
idx: 0,
depth_for_normal: 0,
strong_alias_id: None,
weak_present: false,
skip_third: false,
weak_alias_id: None,
comment_text: None,
}
}
fn commented(ser: &'a mut YamlSerializer<'b, W>) -> Self {
Self {
ser,
kind: TupleKind::Commented,
idx: 0,
depth_for_normal: 0,
strong_alias_id: None,
weak_present: false,
skip_third: false,
weak_alias_id: None,
comment_text: None,
}
}
}
impl<'a, 'b, W: Write> SerializeTupleStruct for TupleSer<'a, 'b, W> {
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<()> {
match self.kind {
TupleKind::Normal => {
if self.idx == 0 {
self.ser.write_anchor_for_complex_node()?;
if !self.ser.at_line_start {
self.ser.newline()?;
}
}
self.ser.write_indent(self.ser.depth + 1)?;
self.ser.out.write_str("- ")?;
self.ser.at_line_start = false;
value.serialize(&mut *self.ser)?;
}
TupleKind::AnchorStrong => {
match self.idx {
0 => {
let mut cap = UsizeCapture::default();
value.serialize(&mut cap)?;
let ptr = cap.finish()?;
let (id, fresh) = self.ser.alloc_anchor_for(ptr);
if fresh {
self.ser.pending_anchor_id = Some(id); self.strong_alias_id = None;
} else {
self.strong_alias_id = Some(id); }
}
1 => {
if let Some(id) = self.strong_alias_id.take() {
self.ser.write_alias_id(id)?;
} else {
value.serialize(&mut *self.ser)?;
}
}
_ => return Err(Error::unexpected("unexpected field in __yaml_anchor")),
}
}
TupleKind::AnchorWeak => {
match self.idx {
0 => {
let mut cap = UsizeCapture::default();
value.serialize(&mut cap)?;
let ptr = cap.finish()?;
self.depth_for_normal = ptr; }
1 => {
let mut bc = BoolCapture::default();
value.serialize(&mut bc)?;
self.weak_present = bc.finish()?;
if !self.weak_present {
if self.ser.at_line_start {
self.ser.write_indent(self.ser.depth)?;
}
self.ser.out.write_str("null")?;
self.ser.write_end_of_scalar()?;
self.skip_third = true;
} else {
let ptr = self.depth_for_normal;
let (id, fresh) = self.ser.alloc_anchor_for(ptr);
if fresh {
self.ser.pending_anchor_id = Some(id); self.weak_alias_id = None;
} else {
self.weak_alias_id = Some(id); }
}
}
2 => {
if self.skip_third {
} else if let Some(id) = self.weak_alias_id.take() {
self.ser.write_alias_id(id)?;
} else {
value.serialize(&mut *self.ser)?;
}
}
_ => return Err(Error::unexpected("unexpected field in __yaml_weak_anchor")),
}
}
TupleKind::Commented => {
match self.idx {
0 => {
let mut sc = StrCapture::default();
value.serialize(&mut sc)?;
self.comment_text = Some(sc.finish()?);
}
1 => {
let comment = self.comment_text.take().unwrap_or_default();
if self.ser.in_flow == 0 {
if !comment.is_empty() {
let sanitized: String = comment
.chars()
.map(|ch| match ch {
'\n' | '\r' | '\u{85}' | '\u{2028}' | '\u{2029}' => ' ',
_ => ch,
})
.collect();
self.ser.pending_inline_comment = Some(sanitized);
}
value.serialize(&mut *self.ser)?;
self.ser.pending_inline_comment = None;
} else {
value.serialize(&mut *self.ser)?;
}
}
_ => return Err(Error::unexpected("unexpected field in __yaml_commented")),
}
}
}
self.idx += 1;
Ok(())
}
fn end(self) -> Result<()> {
Ok(())
}
}
pub struct TupleVariantSer<'a, 'b, W: Write> {
ser: &'a mut YamlSerializer<'b, W>,
depth: usize,
}
impl<'a, 'b, W: Write> SerializeTupleVariant for TupleVariantSer<'a, 'b, W> {
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<()> {
self.ser.write_indent(self.depth)?;
self.ser.out.write_str("- ")?;
self.ser.at_line_start = false;
value.serialize(&mut *self.ser)
}
fn end(self) -> Result<()> {
Ok(())
}
}
pub struct MapSer<'a, 'b, W: Write> {
ser: &'a mut YamlSerializer<'b, W>,
depth: usize,
flow: bool,
first: bool,
last_key_complex: bool,
align_after_dash: bool,
inline_value_start: bool,
}
impl<'a, 'b, W: Write> SerializeMap for MapSer<'a, 'b, W> {
type Ok = ();
type Error = Error;
fn serialize_key<T: ?Sized + Serialize>(&mut self, key: &T) -> Result<()> {
if self.flow {
if !self.first {
self.ser.out.write_str(", ")?;
}
let text = scalar_key_to_string(key, self.ser.yaml_12)?;
self.ser.out.write_str(&text)?;
self.ser.out.write_str(": ")?;
self.ser.at_line_start = false;
self.last_key_complex = false;
} else {
if self.inline_value_start {
if self.ser.pending_space_after_colon {
self.ser.pending_space_after_colon = false;
}
if !self.ser.at_line_start {
self.ser.newline()?;
}
self.inline_value_start = false;
} else if !self.ser.at_line_start {
self.ser.write_space_if_pending()?;
}
self.ser.after_dash_depth = None;
self.ser.pending_inline_map = false;
self.ser.last_value_was_block = false;
match scalar_key_to_string(key, self.ser.yaml_12) {
Ok(text) => {
if self.align_after_dash && self.ser.at_line_start {
let base = self.depth.saturating_sub(1);
for _ in 0..self.ser.indent_step * base {
self.ser.out.write_char(' ')?;
}
self.ser.out.write_str(" ")?; self.ser.at_line_start = false;
} else {
self.ser.write_indent(self.depth)?;
}
self.ser.out.write_str(&text)?;
self.ser.out.write_str(":")?;
self.ser.pending_space_after_colon = true;
self.ser.at_line_start = false;
self.last_key_complex = false;
}
Err(Error::Unexpected { msg }) if msg == "non-scalar key" => {
self.ser.write_anchor_for_complex_node()?;
self.ser.write_indent(self.depth)?;
self.ser.out.write_str("? ")?;
self.ser.at_line_start = false;
let saved_depth = self.ser.depth;
let saved_current_map_depth = self.ser.current_map_depth;
let saved_pending_inline_map = self.ser.pending_inline_map;
let saved_inline_map_after_dash = self.ser.inline_map_after_dash;
let saved_after_dash_depth = self.ser.after_dash_depth;
self.ser.pending_inline_map = true;
self.ser.depth = self.depth;
self.ser.current_map_depth = Some(self.depth);
self.ser.after_dash_depth = None;
key.serialize(&mut *self.ser)?;
self.ser.depth = saved_depth;
self.ser.current_map_depth = saved_current_map_depth;
self.ser.pending_inline_map = saved_pending_inline_map;
self.ser.inline_map_after_dash = saved_inline_map_after_dash;
self.ser.after_dash_depth = saved_after_dash_depth;
self.ser.last_value_was_block = false;
self.last_key_complex = true;
}
Err(e) => return Err(e),
}
}
Ok(())
}
fn serialize_value<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<()> {
if self.flow {
self.ser.with_in_flow(|s| value.serialize(s))?;
} else {
let saved_pending_inline_map = self.ser.pending_inline_map;
let saved_depth = self.ser.depth;
if self.last_key_complex {
if self.align_after_dash && self.ser.at_line_start {
let base = self.depth.saturating_sub(1);
for _ in 0..self.ser.indent_step * base {
self.ser.out.write_char(' ')?;
}
self.ser.out.write_str(" ")?;
self.ser.at_line_start = false;
} else {
self.ser.write_indent(self.depth)?;
}
self.ser.out.write_str(":")?;
self.ser.pending_space_after_colon = true;
self.ser.pending_inline_map = true;
self.ser.at_line_start = false;
self.ser.depth = self.depth;
}
let prev_map_depth = self.ser.current_map_depth.replace(self.depth);
let result = value.serialize(&mut *self.ser);
self.ser.current_map_depth = prev_map_depth;
self.ser.pending_inline_map = saved_pending_inline_map;
if self.last_key_complex {
self.ser.depth = saved_depth;
self.last_key_complex = false;
}
result?;
}
self.first = false;
Ok(())
}
fn end(self) -> Result<()> {
if self.flow {
self.ser.out.write_str("}")?;
if self.ser.in_flow == 0 {
self.ser.newline()?;
}
} else if self.first {
if self.ser.empty_as_braces {
if self.ser.pending_space_after_colon {
self.ser.out.write_str(" ")?;
self.ser.pending_space_after_colon = false;
}
if self.ser.at_line_start {
if self.align_after_dash {
let base = self.depth.saturating_sub(1);
for _ in 0..self.ser.indent_step * base {
self.ser.out.write_char(' ')?;
}
self.ser.out.write_str(" ")?; self.ser.at_line_start = false;
} else {
self.ser.write_indent(self.depth)?;
}
}
self.ser.out.write_str("{}")?;
self.ser.newline()?;
} else {
self.ser.newline()?;
}
} else {
self.ser.last_value_was_block = true;
}
Ok(())
}
}
impl<'a, 'b, W: Write> SerializeStruct for MapSer<'a, 'b, W> {
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized + Serialize>(
&mut self,
key: &'static str,
value: &T,
) -> Result<()> {
SerializeMap::serialize_key(self, &key)?;
SerializeMap::serialize_value(self, value)
}
fn end(self) -> Result<()> {
SerializeMap::end(self)
}
}
pub struct StructVariantSer<'a, 'b, W: Write> {
ser: &'a mut YamlSerializer<'b, W>,
depth: usize,
}
impl<'a, 'b, W: Write> SerializeStructVariant for StructVariantSer<'a, 'b, W> {
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized + Serialize>(
&mut self,
key: &'static str,
value: &T,
) -> Result<()> {
let text = scalar_key_to_string(&key, self.ser.yaml_12)?;
self.ser.write_indent(self.depth)?;
self.ser.out.write_str(&text)?;
self.ser.out.write_str(":")?;
self.ser.pending_space_after_colon = true;
self.ser.at_line_start = false;
let prev_map_depth = self.ser.current_map_depth.replace(self.depth);
let result = value.serialize(&mut *self.ser);
self.ser.current_map_depth = prev_map_depth;
result
}
fn end(self) -> Result<()> {
Ok(())
}
}
#[derive(Default)]
struct UsizeCapture {
v: Option<usize>,
}
impl Serializer for &mut UsizeCapture {
type Ok = ();
type Error = Error;
type SerializeSeq = ser::Impossible<(), Error>;
type SerializeTuple = ser::Impossible<(), Error>;
type SerializeTupleStruct = ser::Impossible<(), Error>;
type SerializeTupleVariant = ser::Impossible<(), Error>;
type SerializeMap = ser::Impossible<(), Error>;
type SerializeStruct = ser::Impossible<(), Error>;
type SerializeStructVariant = ser::Impossible<(), Error>;
fn serialize_i8(self, _v: i8) -> Result<()> {
ptr_unsigned_err()
}
fn serialize_i16(self, _v: i16) -> Result<()> {
ptr_unsigned_err()
}
fn serialize_i32(self, _v: i32) -> Result<()> {
ptr_unsigned_err()
}
fn serialize_i64(self, _v: i64) -> Result<()> {
ptr_unsigned_err()
}
fn serialize_u8(self, v: u8) -> Result<()> {
self.v = Some(v as usize);
Ok(())
}
fn serialize_u16(self, v: u16) -> Result<()> {
self.v = Some(v as usize);
Ok(())
}
fn serialize_u32(self, v: u32) -> Result<()> {
self.v = Some(v as usize);
Ok(())
}
fn serialize_u64(self, v: u64) -> Result<()> {
self.v = Some(v as usize);
Ok(())
}
fn serialize_u128(self, v: u128) -> Result<()> {
self.v = Some(v as usize);
Ok(())
}
fn serialize_f32(self, _v: f32) -> Result<()> {
ptr_unsigned_err()
}
fn serialize_f64(self, _v: f64) -> Result<()> {
ptr_unsigned_err()
}
fn serialize_bool(self, _v: bool) -> Result<()> {
ptr_unsigned_err()
}
fn serialize_char(self, _v: char) -> Result<()> {
Err(Error::unexpected("ptr expects number"))
}
fn serialize_str(self, _v: &str) -> Result<()> {
Err(Error::unexpected("ptr expects number"))
}
fn serialize_bytes(self, _v: &[u8]) -> Result<()> {
Err(Error::unexpected("ptr expects number"))
}
fn serialize_none(self) -> Result<()> {
Err(Error::unexpected("ptr cannot be none"))
}
fn serialize_some<T: ?Sized + Serialize>(self, _value: &T) -> Result<()> {
Err(Error::unexpected("ptr not option"))
}
fn serialize_unit(self) -> Result<()> {
Err(Error::unexpected("ptr cannot be unit"))
}
fn serialize_unit_struct(self, _name: &'static str) -> Result<()> {
unexpected_e()
}
fn serialize_unit_variant(self, _name: &'static str, _i: u32, _v: &'static str) -> Result<()> {
unexpected_e()
}
fn serialize_newtype_struct<T: ?Sized + Serialize>(
self,
_name: &'static str,
_value: &T,
) -> Result<()> {
unexpected_e()
}
fn serialize_newtype_variant<T: ?Sized + Serialize>(
self,
_name: &'static str,
_i: u32,
_v: &'static str,
_value: &T,
) -> Result<()> {
unexpected_e()
}
fn serialize_seq(self, _len: Option<usize>) -> Result<ser::Impossible<(), Error>> {
unexpected()
}
fn serialize_tuple(self, _len: usize) -> Result<ser::Impossible<(), Error>> {
unexpected()
}
fn serialize_tuple_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<ser::Impossible<(), Error>> {
unexpected()
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_i: u32,
_v: &'static str,
_len: usize,
) -> Result<ser::Impossible<(), Error>> {
unexpected()
}
fn serialize_map(self, _len: Option<usize>) -> Result<ser::Impossible<(), Error>> {
unexpected()
}
fn serialize_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<ser::Impossible<(), Error>> {
unexpected()
}
fn serialize_struct_variant(
self,
_name: &'static str,
_i: u32,
_v: &'static str,
_len: usize,
) -> Result<ser::Impossible<(), Error>> {
unexpected()
}
fn collect_str<T: ?Sized + fmt::Display>(self, _value: &T) -> Result<()> {
unexpected_e()
}
fn is_human_readable(&self) -> bool {
true
}
}
impl UsizeCapture {
fn finish(self) -> Result<usize> {
self.v
.ok_or_else(|| Error::unexpected("missing numeric ptr"))
}
}
#[derive(Default)]
struct BoolCapture {
v: Option<bool>,
}
impl Serializer for &mut BoolCapture {
type Ok = ();
type Error = Error;
type SerializeSeq = ser::Impossible<(), Error>;
type SerializeTuple = ser::Impossible<(), Error>;
type SerializeTupleStruct = ser::Impossible<(), Error>;
type SerializeTupleVariant = ser::Impossible<(), Error>;
type SerializeMap = ser::Impossible<(), Error>;
type SerializeStruct = ser::Impossible<(), Error>;
type SerializeStructVariant = ser::Impossible<(), Error>;
fn serialize_bool(self, v: bool) -> Result<()> {
self.v = Some(v);
Ok(())
}
fn serialize_i8(self, _v: i8) -> Result<()> {
bool_expected_err()
}
fn serialize_i16(self, _v: i16) -> Result<()> {
bool_expected_err()
}
fn serialize_i32(self, _v: i32) -> Result<()> {
bool_expected_err()
}
fn serialize_i64(self, _v: i64) -> Result<()> {
bool_expected_err()
}
fn serialize_u8(self, _v: u8) -> Result<()> {
bool_expected_err()
}
fn serialize_u16(self, _v: u16) -> Result<()> {
bool_expected_err()
}
fn serialize_u32(self, _v: u32) -> Result<()> {
bool_expected_err()
}
fn serialize_u64(self, _v: u64) -> Result<()> {
bool_expected_err()
}
fn serialize_f32(self, _v: f32) -> Result<()> {
bool_expected_err()
}
fn serialize_f64(self, _v: f64) -> Result<()> {
bool_expected_err()
}
fn serialize_char(self, _c: char) -> Result<()> {
bool_expected_err()
}
fn serialize_str(self, _v: &str) -> Result<()> {
bool_expected_err()
}
fn serialize_bytes(self, _v: &[u8]) -> Result<()> {
bool_expected_err()
}
fn serialize_none(self) -> Result<()> {
bool_expected_err()
}
fn serialize_some<T: ?Sized + Serialize>(self, _v: &T) -> Result<()> {
bool_expected_err()
}
fn serialize_unit(self) -> Result<()> {
bool_expected_err()
}
fn serialize_unit_struct(self, _name: &'static str) -> Result<()> {
unexpected_e()
}
fn serialize_unit_variant(self, _name: &'static str, _i: u32, _v: &'static str) -> Result<()> {
unexpected_e()
}
fn serialize_newtype_struct<T: ?Sized + Serialize>(
self,
_name: &'static str,
_value: &T,
) -> Result<()> {
unexpected_e()
}
fn serialize_newtype_variant<T: ?Sized + Serialize>(
self,
_name: &'static str,
_i: u32,
_v: &'static str,
_value: &T,
) -> Result<()> {
unexpected_e()
}
fn serialize_seq(self, _len: Option<usize>) -> Result<ser::Impossible<(), Error>> {
unexpected()
}
fn serialize_tuple(self, _len: usize) -> Result<ser::Impossible<(), Error>> {
unexpected()
}
fn serialize_tuple_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<ser::Impossible<(), Error>> {
unexpected()
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_i: u32,
_v: &'static str,
_len: usize,
) -> Result<ser::Impossible<(), Error>> {
unexpected()
}
fn serialize_map(self, _len: Option<usize>) -> Result<ser::Impossible<(), Error>> {
unexpected()
}
fn serialize_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<ser::Impossible<(), Error>> {
unexpected()
}
fn serialize_struct_variant(
self,
_name: &'static str,
_i: u32,
_v: &'static str,
_len: usize,
) -> Result<ser::Impossible<(), Error>> {
unexpected()
}
fn collect_str<T: ?Sized + fmt::Display>(self, _value: &T) -> Result<()> {
unexpected_e()
}
fn is_human_readable(&self) -> bool {
true
}
}
impl BoolCapture {
fn finish(self) -> Result<bool> {
self.v.ok_or_else(|| Error::unexpected("missing bool"))
}
}
#[derive(Default)]
struct StrCapture {
s: Option<String>,
}
impl Serializer for &mut StrCapture {
type Ok = ();
type Error = Error;
type SerializeSeq = ser::Impossible<(), Error>;
type SerializeTuple = ser::Impossible<(), Error>;
type SerializeTupleStruct = ser::Impossible<(), Error>;
type SerializeTupleVariant = ser::Impossible<(), Error>;
type SerializeMap = ser::Impossible<(), Error>;
type SerializeStruct = ser::Impossible<(), Error>;
type SerializeStructVariant = ser::Impossible<(), Error>;
fn serialize_str(self, v: &str) -> Result<()> {
self.s = Some(v.to_string());
Ok(())
}
fn serialize_bool(self, _v: bool) -> Result<()> {
str_expected_err()
}
fn serialize_i8(self, _v: i8) -> Result<()> {
str_expected_err()
}
fn serialize_i16(self, _v: i16) -> Result<()> {
str_expected_err()
}
fn serialize_i32(self, _v: i32) -> Result<()> {
str_expected_err()
}
fn serialize_i64(self, _v: i64) -> Result<()> {
str_expected_err()
}
fn serialize_i128(self, _v: i128) -> Result<()> {
str_expected_err()
}
fn serialize_u8(self, _v: u8) -> Result<()> {
str_expected_err()
}
fn serialize_u16(self, _v: u16) -> Result<()> {
str_expected_err()
}
fn serialize_u32(self, _v: u32) -> Result<()> {
str_expected_err()
}
fn serialize_u64(self, _v: u64) -> Result<()> {
str_expected_err()
}
fn serialize_u128(self, _v: u128) -> Result<()> {
str_expected_err()
}
fn serialize_f32(self, _v: f32) -> Result<()> {
str_expected_err()
}
fn serialize_f64(self, _v: f64) -> Result<()> {
str_expected_err()
}
fn serialize_char(self, _c: char) -> Result<()> {
str_expected_err()
}
fn serialize_bytes(self, _v: &[u8]) -> Result<()> {
str_expected_err()
}
fn serialize_none(self) -> Result<()> {
str_expected_err()
}
fn serialize_some<T: ?Sized + Serialize>(self, _value: &T) -> Result<()> {
str_expected_err()
}
fn serialize_unit(self) -> Result<()> {
str_expected_err()
}
fn serialize_unit_struct(self, _name: &'static str) -> Result<()> {
str_expected_err()
}
fn serialize_unit_variant(self, _name: &'static str, _i: u32, _v: &'static str) -> Result<()> {
str_expected_err()
}
fn serialize_newtype_struct<T: ?Sized + Serialize>(
self,
_name: &'static str,
_value: &T,
) -> Result<()> {
str_expected_err()
}
fn serialize_newtype_variant<T: ?Sized + Serialize>(
self,
_name: &'static str,
_i: u32,
_v: &'static str,
_value: &T,
) -> Result<()> {
str_expected_err()
}
fn serialize_seq(self, _len: Option<usize>) -> Result<ser::Impossible<(), Error>> {
str_expected_err_impossible()
}
fn serialize_tuple(self, _len: usize) -> Result<ser::Impossible<(), Error>> {
str_expected_err_impossible()
}
fn serialize_tuple_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<ser::Impossible<(), Error>> {
str_expected_err_impossible()
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_i: u32,
_v: &'static str,
_len: usize,
) -> Result<ser::Impossible<(), Error>> {
str_expected_err_impossible()
}
fn serialize_map(self, _len: Option<usize>) -> Result<ser::Impossible<(), Error>> {
str_expected_err_impossible()
}
fn serialize_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<ser::Impossible<(), Error>> {
str_expected_err_impossible()
}
fn serialize_struct_variant(
self,
_name: &'static str,
_i: u32,
_v: &'static str,
_len: usize,
) -> Result<ser::Impossible<(), Error>> {
str_expected_err_impossible()
}
fn collect_str<T: ?Sized + fmt::Display>(self, _value: &T) -> Result<()> {
str_expected_err()
}
fn is_human_readable(&self) -> bool {
true
}
}
impl StrCapture {
fn finish(self) -> Result<String> {
self.s.ok_or_else(|| Error::unexpected("missing string"))
}
}
fn scalar_key_to_string<K: Serialize + ?Sized>(key: &K, yaml_12: bool) -> Result<String> {
let mut s = String::new();
{
let mut ks = KeyScalarSink { s: &mut s, yaml_12 };
key.serialize(&mut ks)?;
}
Ok(s)
}
struct KeyScalarSink<'a> {
s: &'a mut String,
yaml_12: bool,
}
impl<'a> Serializer for &'a mut KeyScalarSink<'a> {
type Ok = ();
type Error = Error;
type SerializeSeq = ser::Impossible<(), Error>;
type SerializeTuple = ser::Impossible<(), Error>;
type SerializeTupleStruct = ser::Impossible<(), Error>;
type SerializeTupleVariant = ser::Impossible<(), Error>;
type SerializeMap = ser::Impossible<(), Error>;
type SerializeStruct = ser::Impossible<(), Error>;
type SerializeStructVariant = ser::Impossible<(), Error>;
fn serialize_bool(self, v: bool) -> Result<()> {
self.s.push_str(if v { "true" } else { "false" });
Ok(())
}
fn serialize_i64(self, v: i64) -> Result<()> {
let _ = write!(self.s, "{}", v);
Ok(())
}
fn serialize_i32(self, v: i32) -> Result<()> {
self.serialize_i64(v as i64)
}
fn serialize_i16(self, v: i16) -> Result<()> {
self.serialize_i64(v as i64)
}
fn serialize_i8(self, v: i8) -> Result<()> {
self.serialize_i64(v as i64)
}
fn serialize_i128(self, v: i128) -> Result<()> {
let _ = write!(self.s, "{}", v);
Ok(())
}
fn serialize_u64(self, v: u64) -> Result<()> {
let _ = write!(self.s, "{}", v);
Ok(())
}
fn serialize_u32(self, v: u32) -> Result<()> {
self.serialize_u64(v as u64)
}
fn serialize_u16(self, v: u16) -> Result<()> {
self.serialize_u64(v as u64)
}
fn serialize_u8(self, v: u8) -> Result<()> {
self.serialize_u64(v as u64)
}
fn serialize_u128(self, v: u128) -> Result<()> {
let _ = write!(self.s, "{}", v);
Ok(())
}
fn serialize_f32(self, v: f32) -> Result<()> {
zmij_format::push_float_string(self.s, v)
}
fn serialize_f64(self, v: f64) -> Result<()> {
zmij_format::push_float_string(self.s, v)
}
fn serialize_char(self, v: char) -> Result<()> {
let mut buf = [0u8; 4];
self.serialize_str(v.encode_utf8(&mut buf))
}
fn serialize_str(self, v: &str) -> Result<()> {
if is_plain_safe(v) && is_plain_value_safe(v, self.yaml_12, true) {
self.s.push_str(v);
} else {
self.s.push('"');
for ch in v.chars() {
match ch {
'\\' => self.s.push_str("\\\\"),
'"' => self.s.push_str("\\\""),
'\n' => self.s.push_str("\\n"),
'\r' => self.s.push_str("\\r"),
'\t' => self.s.push_str("\\t"),
c if c.is_control() => {
use std::fmt::Write as _;
let _ = write!(self.s, "\\u{:04X}", c as u32);
}
c => self.s.push(c),
}
}
self.s.push('"');
}
Ok(())
}
fn serialize_bytes(self, _v: &[u8]) -> Result<()> {
non_scalar_key_e()
}
fn serialize_none(self) -> Result<()> {
self.s.push_str("null");
Ok(())
}
fn serialize_some<T: ?Sized + Serialize>(self, v: &T) -> Result<()> {
v.serialize(self)
}
fn serialize_unit(self) -> Result<()> {
self.s.push_str("null");
Ok(())
}
fn serialize_unit_struct(self, _name: &'static str) -> Result<()> {
self.serialize_unit()
}
fn serialize_unit_variant(
self,
_name: &'static str,
_idx: u32,
variant: &'static str,
) -> Result<()> {
self.serialize_str(variant)
}
fn serialize_newtype_struct<T: ?Sized + Serialize>(
self,
_name: &'static str,
value: &T,
) -> Result<()> {
value.serialize(self)
}
fn serialize_newtype_variant<T: ?Sized + Serialize>(
self,
_: &'static str,
_: u32,
_: &'static str,
_: &T,
) -> Result<()> {
non_scalar_key_e()
}
fn serialize_seq(self, _len: Option<usize>) -> Result<ser::Impossible<(), Error>> {
non_scalar_key()
}
fn serialize_tuple(self, _len: usize) -> Result<ser::Impossible<(), Error>> {
non_scalar_key()
}
fn serialize_tuple_struct(
self,
_: &'static str,
_: usize,
) -> Result<ser::Impossible<(), Error>> {
non_scalar_key()
}
fn serialize_tuple_variant(
self,
_: &'static str,
_: u32,
_: &'static str,
_: usize,
) -> Result<ser::Impossible<(), Error>> {
non_scalar_key()
}
fn serialize_map(self, _len: Option<usize>) -> Result<ser::Impossible<(), Error>> {
non_scalar_key()
}
fn serialize_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<ser::Impossible<(), Error>> {
non_scalar_key()
}
fn serialize_struct_variant(
self,
_: &'static str,
_: u32,
_: &'static str,
_: usize,
) -> Result<ser::Impossible<(), Error>> {
non_scalar_key()
}
fn collect_str<T: ?Sized + fmt::Display>(self, v: &T) -> Result<()> {
self.serialize_str(&v.to_string())
}
fn is_human_readable(&self) -> bool {
true
}
}
#[cold]
fn ptr_unsigned_err() -> Result<()> {
Err(Error::unexpected("ptr expects unsigned integer"))
}
#[cold]
fn bool_expected_err() -> Result<()> {
Err(Error::unexpected("bool expected"))
}
#[cold]
fn str_expected_err() -> Result<()> {
Err(Error::unexpected("str expected"))
}
#[cold]
fn str_expected_err_impossible() -> Result<ser::Impossible<(), Error>> {
Err(Error::unexpected("str expected"))
}
#[cold]
fn unexpected() -> Result<ser::Impossible<(), Error>> {
Err(Error::unexpected("unexpected"))
}
#[cold]
fn unexpected_e() -> Result<()> {
Err(Error::unexpected("unexpected"))
}
#[cold]
fn non_scalar_key() -> Result<ser::Impossible<(), Error>> {
Err(Error::unexpected("non-scalar key"))
}
#[cold]
fn non_scalar_key_e() -> Result<()> {
Err(Error::unexpected("non-scalar key"))
}