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}