toml_write/
value.rs

1#[cfg(feature = "alloc")]
2use alloc::borrow::Cow;
3#[cfg(feature = "alloc")]
4use alloc::string::String;
5#[cfg(feature = "alloc")]
6use alloc::vec::Vec;
7
8use crate::TomlWrite;
9use crate::WriteTomlKey;
10
11#[cfg(feature = "alloc")]
12pub trait ToTomlValue {
13    fn to_toml_value(&self) -> String;
14}
15
16#[cfg(feature = "alloc")]
17impl<T> ToTomlValue for T
18where
19    T: WriteTomlValue + ?Sized,
20{
21    fn to_toml_value(&self) -> String {
22        let mut result = String::new();
23        let _ = self.write_toml_value(&mut result);
24        result
25    }
26}
27
28pub trait WriteTomlValue {
29    fn write_toml_value<W: TomlWrite + ?Sized>(&self, writer: &mut W) -> core::fmt::Result;
30}
31
32impl WriteTomlValue for bool {
33    fn write_toml_value<W: TomlWrite + ?Sized>(&self, writer: &mut W) -> core::fmt::Result {
34        write!(writer, "{self}")
35    }
36}
37
38impl WriteTomlValue for u8 {
39    fn write_toml_value<W: TomlWrite + ?Sized>(&self, writer: &mut W) -> core::fmt::Result {
40        write!(writer, "{self}")
41    }
42}
43
44impl WriteTomlValue for i8 {
45    fn write_toml_value<W: TomlWrite + ?Sized>(&self, writer: &mut W) -> core::fmt::Result {
46        write!(writer, "{self}")
47    }
48}
49
50impl WriteTomlValue for u16 {
51    fn write_toml_value<W: TomlWrite + ?Sized>(&self, writer: &mut W) -> core::fmt::Result {
52        write!(writer, "{self}")
53    }
54}
55
56impl WriteTomlValue for i16 {
57    fn write_toml_value<W: TomlWrite + ?Sized>(&self, writer: &mut W) -> core::fmt::Result {
58        write!(writer, "{self}")
59    }
60}
61
62impl WriteTomlValue for u32 {
63    fn write_toml_value<W: TomlWrite + ?Sized>(&self, writer: &mut W) -> core::fmt::Result {
64        write!(writer, "{self}")
65    }
66}
67
68impl WriteTomlValue for i32 {
69    fn write_toml_value<W: TomlWrite + ?Sized>(&self, writer: &mut W) -> core::fmt::Result {
70        write!(writer, "{self}")
71    }
72}
73
74impl WriteTomlValue for u64 {
75    fn write_toml_value<W: TomlWrite + ?Sized>(&self, writer: &mut W) -> core::fmt::Result {
76        write!(writer, "{self}")
77    }
78}
79
80impl WriteTomlValue for i64 {
81    fn write_toml_value<W: TomlWrite + ?Sized>(&self, writer: &mut W) -> core::fmt::Result {
82        write!(writer, "{self}")
83    }
84}
85
86impl WriteTomlValue for u128 {
87    fn write_toml_value<W: TomlWrite + ?Sized>(&self, writer: &mut W) -> core::fmt::Result {
88        write!(writer, "{self}")
89    }
90}
91
92impl WriteTomlValue for i128 {
93    fn write_toml_value<W: TomlWrite + ?Sized>(&self, writer: &mut W) -> core::fmt::Result {
94        write!(writer, "{self}")
95    }
96}
97
98impl WriteTomlValue for f32 {
99    fn write_toml_value<W: TomlWrite + ?Sized>(&self, writer: &mut W) -> core::fmt::Result {
100        match (self.is_sign_negative(), self.is_nan(), *self == 0.0) {
101            (true, true, _) => write!(writer, "-nan"),
102            (false, true, _) => write!(writer, "nan"),
103            (true, false, true) => write!(writer, "-0.0"),
104            (false, false, true) => write!(writer, "0.0"),
105            (_, false, false) => {
106                if self % 1.0 == 0.0 {
107                    write!(writer, "{self}.0")
108                } else {
109                    write!(writer, "{self}")
110                }
111            }
112        }
113    }
114}
115
116impl WriteTomlValue for f64 {
117    fn write_toml_value<W: TomlWrite + ?Sized>(&self, writer: &mut W) -> core::fmt::Result {
118        match (self.is_sign_negative(), self.is_nan(), *self == 0.0) {
119            (true, true, _) => write!(writer, "-nan"),
120            (false, true, _) => write!(writer, "nan"),
121            (true, false, true) => write!(writer, "-0.0"),
122            (false, false, true) => write!(writer, "0.0"),
123            (_, false, false) => {
124                if self % 1.0 == 0.0 {
125                    write!(writer, "{self}.0")
126                } else {
127                    write!(writer, "{self}")
128                }
129            }
130        }
131    }
132}
133
134impl WriteTomlValue for char {
135    fn write_toml_value<W: TomlWrite + ?Sized>(&self, writer: &mut W) -> core::fmt::Result {
136        let mut buf = [0; 4];
137        let v = self.encode_utf8(&mut buf);
138        v.write_toml_value(writer)
139    }
140}
141
142impl WriteTomlValue for str {
143    fn write_toml_value<W: TomlWrite + ?Sized>(&self, writer: &mut W) -> core::fmt::Result {
144        crate::TomlStringBuilder::new(self)
145            .as_default()
146            .write_toml_value(writer)
147    }
148}
149
150#[cfg(feature = "alloc")]
151impl WriteTomlValue for String {
152    fn write_toml_value<W: TomlWrite + ?Sized>(&self, writer: &mut W) -> core::fmt::Result {
153        self.as_str().write_toml_value(writer)
154    }
155}
156
157#[cfg(feature = "alloc")]
158impl WriteTomlValue for Cow<'_, str> {
159    fn write_toml_value<W: TomlWrite + ?Sized>(&self, writer: &mut W) -> core::fmt::Result {
160        self.as_ref().write_toml_value(writer)
161    }
162}
163
164impl<V: WriteTomlValue> WriteTomlValue for [V] {
165    fn write_toml_value<W: TomlWrite + ?Sized>(&self, writer: &mut W) -> core::fmt::Result {
166        writer.open_array()?;
167        let mut iter = self.iter();
168        if let Some(v) = iter.next() {
169            writer.value(v)?;
170        }
171        for v in iter {
172            writer.val_sep()?;
173            writer.space()?;
174            writer.value(v)?;
175        }
176        writer.close_array()?;
177        Ok(())
178    }
179}
180
181impl<V: WriteTomlValue, const N: usize> WriteTomlValue for [V; N] {
182    fn write_toml_value<W: TomlWrite + ?Sized>(&self, writer: &mut W) -> core::fmt::Result {
183        self.as_slice().write_toml_value(writer)
184    }
185}
186
187#[cfg(feature = "alloc")]
188impl<V: WriteTomlValue> WriteTomlValue for Vec<V> {
189    fn write_toml_value<W: TomlWrite + ?Sized>(&self, writer: &mut W) -> core::fmt::Result {
190        self.as_slice().write_toml_value(writer)
191    }
192}
193
194#[cfg(feature = "alloc")]
195impl<K: WriteTomlKey, V: WriteTomlValue> WriteTomlValue for alloc::collections::BTreeMap<K, V> {
196    fn write_toml_value<W: TomlWrite + ?Sized>(&self, writer: &mut W) -> core::fmt::Result {
197        write_toml_inline_table(self.iter(), writer)
198    }
199}
200
201#[cfg(feature = "std")]
202impl<K: WriteTomlKey, V: WriteTomlValue> WriteTomlValue for std::collections::HashMap<K, V> {
203    fn write_toml_value<W: TomlWrite + ?Sized>(&self, writer: &mut W) -> core::fmt::Result {
204        write_toml_inline_table(self.iter(), writer)
205    }
206}
207
208fn write_toml_inline_table<
209    'i,
210    I: Iterator<Item = (&'i K, &'i V)>,
211    K: WriteTomlKey + 'i,
212    V: WriteTomlValue + 'i,
213    W: TomlWrite + ?Sized,
214>(
215    mut iter: I,
216    writer: &mut W,
217) -> core::fmt::Result {
218    writer.open_inline_table()?;
219    let mut trailing_space = false;
220    if let Some((key, value)) = iter.next() {
221        writer.space()?;
222        writer.key(key)?;
223        writer.space()?;
224        writer.keyval_sep()?;
225        writer.space()?;
226        writer.value(value)?;
227        trailing_space = true;
228    }
229    for (key, value) in iter {
230        writer.val_sep()?;
231        writer.space()?;
232        writer.key(key)?;
233        writer.space()?;
234        writer.keyval_sep()?;
235        writer.space()?;
236        writer.value(value)?;
237    }
238    if trailing_space {
239        writer.space()?;
240    }
241    writer.close_inline_table()?;
242    Ok(())
243}
244
245impl<V: WriteTomlValue + ?Sized> WriteTomlValue for &V {
246    fn write_toml_value<W: TomlWrite + ?Sized>(&self, writer: &mut W) -> core::fmt::Result {
247        (*self).write_toml_value(writer)
248    }
249}