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