1extern crate alloc;
4
5use alloc::string::String;
6use core::fmt::Write as FmtWrite;
7use facet_core::{Def, ScalarType};
8use facet_reflect::Peek;
9
10use super::DomSerializer;
11
12pub trait WriteScalar: DomSerializer {
14 fn format_scalar(&self, value: Peek<'_, '_>) -> Option<String> {
18 let value = value.innermost_peek();
20
21 if let Def::Option(_) = &value.shape().def
23 && let Ok(opt) = value.into_option()
24 {
25 return match opt.value() {
26 Some(inner) => self.format_scalar(inner),
27 None => None,
28 };
29 }
30
31 if let Some(scalar_type) = value.scalar_type() {
32 let mut buf = ScalarBuffer::new();
33 let written = match scalar_type {
34 ScalarType::Unit => {
35 buf.push_str("null");
36 true
37 }
38 ScalarType::Bool => {
39 if let Ok(b) = value.get::<bool>() {
40 buf.push_str(if *b { "true" } else { "false" });
41 true
42 } else {
43 false
44 }
45 }
46 ScalarType::Char => {
47 if let Ok(c) = value.get::<char>() {
48 buf.push(*c);
49 true
50 } else {
51 false
52 }
53 }
54 ScalarType::Str | ScalarType::String | ScalarType::CowStr => {
55 if let Some(s) = value.as_str() {
56 return Some(s.to_string());
57 }
58 false
59 }
60 ScalarType::F32 => {
61 if let Ok(v) = value.get::<f32>() {
62 self.write_float(*v as f64, &mut buf);
63 true
64 } else {
65 false
66 }
67 }
68 ScalarType::F64 => {
69 if let Ok(v) = value.get::<f64>() {
70 self.write_float(*v, &mut buf);
71 true
72 } else {
73 false
74 }
75 }
76 ScalarType::U8 => write_int!(buf, value, u8),
77 ScalarType::U16 => write_int!(buf, value, u16),
78 ScalarType::U32 => write_int!(buf, value, u32),
79 ScalarType::U64 => write_int!(buf, value, u64),
80 ScalarType::U128 => write_int!(buf, value, u128),
81 ScalarType::USize => write_int!(buf, value, usize),
82 ScalarType::I8 => write_int!(buf, value, i8),
83 ScalarType::I16 => write_int!(buf, value, i16),
84 ScalarType::I32 => write_int!(buf, value, i32),
85 ScalarType::I64 => write_int!(buf, value, i64),
86 ScalarType::I128 => write_int!(buf, value, i128),
87 ScalarType::ISize => write_int!(buf, value, isize),
88 #[cfg(feature = "net")]
89 ScalarType::IpAddr => write_int!(buf, value, core::net::IpAddr),
90 #[cfg(feature = "net")]
91 ScalarType::Ipv4Addr => write_int!(buf, value, core::net::Ipv4Addr),
92 #[cfg(feature = "net")]
93 ScalarType::Ipv6Addr => write_int!(buf, value, core::net::Ipv6Addr),
94 #[cfg(feature = "net")]
95 ScalarType::SocketAddr => write_int!(buf, value, core::net::SocketAddr),
96 _ => false,
97 };
98
99 if written {
100 return Some(buf.as_str().to_string());
101 }
102 }
103
104 if matches!(value.shape().def, Def::Scalar) && value.shape().vtable.has_display() {
106 let mut buf = ScalarBuffer::new();
107 let _ = write!(buf, "{}", value);
108 return Some(buf.as_str().to_string());
109 }
110
111 None
112 }
113
114 fn write_scalar(&mut self, value: Peek<'_, '_>) -> Result<bool, Self::Error> {
119 if let Def::Option(_) = &value.shape().def
121 && let Ok(opt) = value.into_option()
122 {
123 return match opt.value() {
124 Some(inner) => self.write_scalar(inner),
125 None => Ok(false),
126 };
127 }
128
129 if let Some(scalar_type) = value.scalar_type() {
130 let mut buf = ScalarBuffer::new();
131 let written = match scalar_type {
132 ScalarType::Unit => {
133 buf.push_str("null");
134 true
135 }
136 ScalarType::Bool => {
137 if let Ok(b) = value.get::<bool>() {
138 buf.push_str(if *b { "true" } else { "false" });
139 true
140 } else {
141 false
142 }
143 }
144 ScalarType::Char => {
145 if let Ok(c) = value.get::<char>() {
146 buf.push(*c);
147 true
148 } else {
149 false
150 }
151 }
152 ScalarType::Str | ScalarType::String | ScalarType::CowStr => {
153 if let Some(s) = value.as_str() {
154 self.text(s)?;
155 return Ok(true);
156 }
157 false
158 }
159 ScalarType::F32 => {
160 if let Ok(v) = value.get::<f32>() {
161 self.write_float(*v as f64, &mut buf);
162 true
163 } else {
164 false
165 }
166 }
167 ScalarType::F64 => {
168 if let Ok(v) = value.get::<f64>() {
169 self.write_float(*v, &mut buf);
170 true
171 } else {
172 false
173 }
174 }
175 ScalarType::U8 => write_int!(buf, value, u8),
176 ScalarType::U16 => write_int!(buf, value, u16),
177 ScalarType::U32 => write_int!(buf, value, u32),
178 ScalarType::U64 => write_int!(buf, value, u64),
179 ScalarType::U128 => write_int!(buf, value, u128),
180 ScalarType::USize => write_int!(buf, value, usize),
181 ScalarType::I8 => write_int!(buf, value, i8),
182 ScalarType::I16 => write_int!(buf, value, i16),
183 ScalarType::I32 => write_int!(buf, value, i32),
184 ScalarType::I64 => write_int!(buf, value, i64),
185 ScalarType::I128 => write_int!(buf, value, i128),
186 ScalarType::ISize => write_int!(buf, value, isize),
187 #[cfg(feature = "net")]
188 ScalarType::IpAddr => write_display!(buf, value, core::net::IpAddr),
189 #[cfg(feature = "net")]
190 ScalarType::Ipv4Addr => write_display!(buf, value, core::net::Ipv4Addr),
191 #[cfg(feature = "net")]
192 ScalarType::Ipv6Addr => write_display!(buf, value, core::net::Ipv6Addr),
193 #[cfg(feature = "net")]
194 ScalarType::SocketAddr => write_display!(buf, value, core::net::SocketAddr),
195 _ => false,
196 };
197
198 if written {
199 self.text(buf.as_str())?;
200 return Ok(true);
201 }
202 }
203
204 if matches!(value.shape().def, Def::Scalar) && value.shape().vtable.has_display() {
206 let mut buf = ScalarBuffer::new();
207 let _ = write!(buf, "{}", value);
208 self.text(buf.as_str())?;
209 return Ok(true);
210 }
211
212 Ok(false)
213 }
214
215 fn write_float(&self, value: f64, buf: &mut ScalarBuffer) {
217 let _ = write!(buf, "{}", value);
218 }
219}
220
221impl<T: DomSerializer> WriteScalar for T {}
223
224macro_rules! write_int {
225 ($buf:expr, $value:expr, $ty:ty) => {{
226 if let Ok(v) = $value.get::<$ty>() {
227 let _ = write!($buf, "{}", v);
228 true
229 } else {
230 false
231 }
232 }};
233}
234use write_int;
235
236#[cfg(feature = "net")]
237macro_rules! write_display {
238 ($buf:expr, $value:expr, $ty:ty) => {{
239 if let Ok(v) = $value.get::<$ty>() {
240 let _ = write!($buf, "{}", v);
241 true
242 } else {
243 false
244 }
245 }};
246}
247#[cfg(feature = "net")]
248use write_display;
249
250pub struct ScalarBuffer {
253 inline: [u8; 32],
255 len: usize,
256 overflow: Option<String>,
258}
259
260impl ScalarBuffer {
261 pub fn new() -> Self {
263 Self {
264 inline: [0u8; 32],
265 len: 0,
266 overflow: None,
267 }
268 }
269
270 pub fn as_str(&self) -> &str {
272 if let Some(ref s) = self.overflow {
273 s.as_str()
274 } else {
275 unsafe { core::str::from_utf8_unchecked(&self.inline[..self.len]) }
277 }
278 }
279
280 fn push_str(&mut self, s: &str) {
281 if let Some(ref mut overflow) = self.overflow {
282 overflow.push_str(s);
283 } else if self.len + s.len() <= self.inline.len() {
284 self.inline[self.len..self.len + s.len()].copy_from_slice(s.as_bytes());
285 self.len += s.len();
286 } else {
287 let mut heap = String::with_capacity(self.len + s.len() + 32);
289 heap.push_str(unsafe { core::str::from_utf8_unchecked(&self.inline[..self.len]) });
290 heap.push_str(s);
291 self.overflow = Some(heap);
292 }
293 }
294
295 fn push(&mut self, c: char) {
296 let mut buf = [0u8; 4];
297 let s = c.encode_utf8(&mut buf);
298 self.push_str(s);
299 }
300}
301
302impl Default for ScalarBuffer {
303 fn default() -> Self {
304 Self::new()
305 }
306}
307
308impl FmtWrite for ScalarBuffer {
309 fn write_str(&mut self, s: &str) -> core::fmt::Result {
310 self.push_str(s);
311 Ok(())
312 }
313}