serde_saphyr/ser/api.rs
1use super::options::SerializerOptions;
2
3// ---------------- Serialization (public API) ----------------
4
5/// Serialize a value to a YAML `String`.
6///
7/// This is the easiest entry point when you just want a YAML string.
8///
9/// Example
10///
11/// ```rust
12/// use serde::Serialize;
13///
14/// #[derive(Serialize)]
15/// struct Foo { a: i32, b: bool }
16///
17/// let s = serde_saphyr::to_string(&Foo { a: 1, b: true }).unwrap();
18/// assert!(s.contains("a: 1"));
19/// ```
20#[cfg(feature = "serialize")]
21pub fn to_string<T: serde_core::Serialize>(
22 value: &T,
23) -> std::result::Result<String, crate::ser::Error> {
24 let mut out = String::new();
25 to_fmt_writer(&mut out, value)?;
26 Ok(out)
27}
28
29/// Serialize a value to a YAML `String`, with [`SerializerOptions`].
30///
31/// This is like [`to_string`], but lets you control formatting and serialization
32/// behavior through the provided `options`.
33///
34/// Example
35///
36/// ```rust
37/// use serde::Serialize;
38/// use serde_saphyr::SerializerOptions;
39///
40/// #[derive(Serialize)]
41/// struct Foo { a: i32, b: bool }
42///
43/// let options = SerializerOptions::default();
44/// let s = serde_saphyr::to_string_with_options(&Foo { a: 1, b: true }, options).unwrap();
45/// assert!(s.contains("a: 1"));
46/// ```
47#[cfg(feature = "serialize")]
48pub fn to_string_with_options<T: serde_core::Serialize>(
49 value: &T,
50 options: SerializerOptions,
51) -> std::result::Result<String, crate::ser::Error> {
52 let mut out = String::new();
53 to_fmt_writer_with_options(&mut out, value, options)?;
54 Ok(out)
55}
56
57/// Serialize a value as YAML into any [`std::fmt::Write`] target.
58#[cfg(feature = "serialize")]
59pub fn to_fmt_writer<W: std::fmt::Write, T: serde_core::Serialize>(
60 output: &mut W,
61 value: &T,
62) -> std::result::Result<(), crate::ser::Error> {
63 to_fmt_writer_with_options(output, value, SerializerOptions::default())
64}
65
66/// Serialize a value as YAML into any [`std::io::Write`] target.
67#[cfg(feature = "serialize")]
68pub fn to_io_writer<W: std::io::Write, T: serde_core::Serialize>(
69 output: &mut W,
70 value: &T,
71) -> std::result::Result<(), crate::ser::Error> {
72 to_io_writer_with_options(output, value, SerializerOptions::default())
73}
74
75/// Serialize a value as YAML into any [`std::fmt::Write`] target, with options.
76/// Options are consumed to leave room for non-`Copy` settings.
77#[cfg(feature = "serialize")]
78pub fn to_fmt_writer_with_options<W: std::fmt::Write, T: serde_core::Serialize>(
79 output: &mut W,
80 value: &T,
81 options: SerializerOptions,
82) -> std::result::Result<(), crate::ser::Error> {
83 let mut ser = crate::ser::YamlSerializer::with_options(output, options)?;
84 value.serialize(&mut ser)
85}
86
87/// Serialize a value as YAML into any [`std::io::Write`] target, with options.
88/// Options are consumed to leave room for non-`Copy` settings.
89#[cfg(feature = "serialize")]
90pub fn to_io_writer_with_options<W: std::io::Write, T: serde_core::Serialize>(
91 output: &mut W,
92 value: &T,
93 options: SerializerOptions,
94) -> std::result::Result<(), crate::ser::Error> {
95 struct Adapter<'a, W: std::io::Write> {
96 output: &'a mut W,
97 last_err: Option<std::io::Error>,
98 }
99 impl<W: std::io::Write> std::fmt::Write for Adapter<'_, W> {
100 fn write_str(&mut self, s: &str) -> std::fmt::Result {
101 if let Err(e) = self.output.write_all(s.as_bytes()) {
102 self.last_err = Some(e);
103 return Err(std::fmt::Error);
104 }
105 Ok(())
106 }
107 fn write_char(&mut self, c: char) -> std::fmt::Result {
108 let mut buf = [0u8; 4];
109 let s = c.encode_utf8(&mut buf);
110 self.write_str(s)
111 }
112 }
113 let mut adapter = Adapter {
114 output,
115 last_err: None,
116 };
117 let mut ser = crate::ser::YamlSerializer::with_options(&mut adapter, options)?;
118 match value.serialize(&mut ser) {
119 Ok(()) => Ok(()),
120 Err(e) => {
121 if let Some(io_error) = adapter.last_err.take() {
122 return Err(crate::ser::Error::from(io_error));
123 }
124 Err(e)
125 }
126 }
127}
128
129/// Serialize multiple documents into a YAML string.
130///
131/// Serializes each value in the provided slice as an individual YAML document.
132/// Documents are separated by a standard YAML document start marker ("---\n").
133/// No marker is emitted before the first document.
134///
135/// Example
136///
137/// ```rust
138/// use serde::Serialize;
139///
140/// #[derive(Serialize)]
141/// struct Point { x: i32 }
142///
143/// let docs = vec![Point { x: 1 }, Point { x: 2 }];
144/// let out = serde_saphyr::to_string_multiple(&docs).unwrap();
145/// assert_eq!(out, "x: 1\n---\nx: 2\n");
146/// ```
147#[cfg(feature = "serialize")]
148pub fn to_string_multiple<T: serde_core::Serialize>(
149 values: &[T],
150) -> std::result::Result<String, crate::ser::Error> {
151 to_string_multiple_with_options(values, SerializerOptions::default())
152}
153
154/// Serialize multiple documents into a YAML string with configurable `Options`.
155///
156/// Serializes each value in the provided slice as an individual YAML document.
157/// Documents are separated by a standard YAML document start marker ("---\n").
158/// By default, no marker is emitted before the first document.
159/// When `options.yaml_12` is enabled and `options.no_lang_directive` is false,
160/// each document emits its own `%YAML 1.2` directive and document start marker,
161/// and later documents are preceded by an explicit document end marker ("...\n")
162/// so the following directive is valid. With `options.no_lang_directive` enabled,
163/// only the separators between documents are emitted.
164///
165/// Example
166///
167/// ```rust
168/// use serde::Serialize;
169///
170/// #[derive(Serialize)]
171/// struct Point { coords: Vec<i32> }
172///
173/// let docs = vec![Point { coords: vec![0,1] }, Point { coords: vec![3,2] }];
174/// let options = serde_saphyr::ser_options! {
175/// indent_step: 2,
176/// compact_list_indent: true
177/// };
178/// let out = serde_saphyr::to_string_multiple_with_options(&docs, options).unwrap();
179/// assert_eq!(out, "coords:\n- 0\n- 1\n---\ncoords:\n- 3\n- 2\n");
180/// ```
181#[cfg(feature = "serialize")]
182pub fn to_string_multiple_with_options<T: serde_core::Serialize>(
183 values: &[T],
184 options: SerializerOptions,
185) -> std::result::Result<String, crate::ser::Error> {
186 options.consistent()?;
187 let mut out = String::new();
188 let mut first = true;
189 let emit_directive = options.yaml_12 && !options.no_lang_directive;
190 for v in values {
191 if !first {
192 if emit_directive {
193 out.push_str("...\n");
194 } else {
195 out.push_str("---\n");
196 }
197 }
198 first = false;
199 to_fmt_writer_with_options(&mut out, v, options.clone())?;
200 }
201 Ok(out)
202}