serde_saphyr/serializer_options.rs
1//! Serializer options for YAML emission.
2//!
3//! Controls indentation and optional anchor name generation for the serializer.
4//!
5//! Example: use 4-space indentation and a custom anchor naming scheme.
6//!
7//! ```rust
8//! use serde::Serialize;
9//!
10//! #[derive(Serialize)]
11//! struct Item { a: i32, b: bool }
12//!
13//! let mut buf = String::new();
14//! let opts = serde_saphyr::SerializerOptions {
15//! indent_step: 4,
16//! anchor_generator: Some(|id| format!("id{}/", id)),
17//! ..Default::default()
18//! };
19//! serde_saphyr::to_fmt_writer_with_options(&mut buf, &Item { a: 1, b: true }, opts).unwrap();
20//! assert!(buf.contains("a: 1"));
21//! ```
22
23use crate::ser_error::Error;
24
25#[derive(Clone, Copy)]
26pub struct SerializerOptions {
27 /// If true, empty maps are emitted as braces {} and empty lists as [] (this is the default).
28 /// Such form is equally valid YAML, allows to tell empty from null and may be easier for a
29 /// human to grasp.
30 pub empty_as_braces: bool,
31 /// Number of spaces to indent per nesting level when emitting block-style collections.
32 /// 0 value is invalid and will result and error when trying to deserialize, because
33 /// no indentation would produce invalid YAML otherwise.
34 pub indent_step: usize,
35 /// Optional custom anchor-name generator.
36 ///
37 /// Receives a monotonically increasing `usize` id (starting at 1) and returns the
38 /// anchor name to emit. If `None`, the built-in generator yields names like `a1`, `a2`, ...
39 pub anchor_generator: Option<fn(usize) -> String>,
40 /// Threshold for block-string wrappers ([crate::LitStr]/[crate::FoldStr] and owned variants
41 /// [crate::LitString]/[crate::FoldString]).
42 ///
43 /// If the string contains a newline, block style is always used. Otherwise, when the
44 /// string is single-line and its length is strictly less than this threshold, the
45 /// serializer emits a normal YAML scalar (no block style). Longer strings use block
46 /// styles `|` or `>` depending on the wrapper. See the type docs for
47 /// [crate::LitStr], [crate::FoldStr], [crate::LitString] and [crate::FoldString] for
48 /// examples.
49 pub min_fold_chars: usize,
50 /// Maximum width (in characters) for lines in folded block scalars (`>`).
51 ///
52 /// Lines are wrapped at whitespace so that each emitted line is at most this many
53 /// characters long (excluding indentation). If no whitespace is present within the
54 /// limit, a hard break is performed.
55 pub folded_wrap_chars: usize,
56 /// When enabled, serialize simple enums that become a single scalar (unit variants)
57 /// using YAML tags, e.g. `!!Enum Variant` instead of a plain scalar `Variant`.
58 /// Deserializer does not need this setting as both cases will be understood.
59 pub tagged_enums: bool,
60
61 /// When enabled, strings containing more than folded_wrap_chars (80 by default) are written
62 /// in wrapped multistring folded form (>), and strings containing new lines are written in
63 /// literal form (|), selecting format depending on the number of empty lines at the end.
64 pub prefer_block_scalars: bool,
65}
66
67// Below this length, block-string wrappers serialize as regular scalars
68// instead of YAML block styles. This keeps short values compact.
69pub(crate) const MIN_FOLD_CHARS: usize = 32;
70/// Maximum width (in characters) for lines inside folded block scalars.
71/// Lines will be wrapped at whitespace so that each emitted line is at most
72/// this many characters long (excluding indentation). If no whitespace is
73/// available within the limit, a hard break is performed.
74pub(crate) const FOLDED_WRAP_CHARS: usize = 80;
75
76impl SerializerOptions {
77 pub(crate) fn consistent(&self) -> Result<(), Error> {
78 if self.indent_step == 0 {
79 return Err(Error::InvalidOptions("Invalid indent step must be positive".to_string()));
80 }
81 Ok(())
82 }
83}
84
85impl Default for SerializerOptions {
86 fn default() -> Self {
87 // Defaults mirror internal constants used by the serializer.
88 Self {
89 indent_step: 2,
90 anchor_generator: None,
91 min_fold_chars: MIN_FOLD_CHARS,
92 folded_wrap_chars: FOLDED_WRAP_CHARS,
93 tagged_enums: false,
94 empty_as_braces: true,
95 prefer_block_scalars: true
96 }
97 }
98}