changelog shortlog graph tags branches changeset files revisions annotate raw help

Mercurial > core / rust/lib/sxp/src/fmt.rs

changeset 698: 96958d3eb5b0
parent: 0ccbbd142694
author: Richard Westhaver <ellis@rwest.io>
date: Fri, 04 Oct 2024 22:04:59 -0400
permissions: -rw-r--r--
description: fixes
1 //! fmt.rs --- SXP Formatters
2 use crate::{
3  io::{self, Write},
4  read::Read,
5  tok::CharEscape,
6  Result,
7 };
8 
9 pub fn indent<W: ?Sized + io::Write>(
10  wr: &mut W,
11  n: usize,
12  s: &[u8],
13 ) -> io::Result<()> {
14  for _ in 0..n {
15  e!(wr.write_all(s));
16  }
17  Ok(())
18 }
19 
20 pub trait WriteFormatter {
21  /// Write a 'nil' value to the specified writer.
22  #[inline]
23  fn write_nil<W: ?Sized + Write>(&mut self, writer: &mut W) -> io::Result<()> {
24  writer.write_all(b"nil")
25  }
26  /// Write a bool value to the specified writer.
27  #[inline]
28  fn write_bool<W: ?Sized + Write>(
29  &mut self,
30  writer: &mut W,
31  value: bool,
32  ) -> io::Result<()> {
33  if value {
34  writer.write_all(b"t")
35  } else {
36  writer.write_all(b"nil")
37  }
38  }
39  /// Write an i8 value like '-123' to the specified writer.
40  #[inline]
41  fn write_i8<W: ?Sized + Write>(
42  &mut self,
43  writer: &mut W,
44  value: i8,
45  ) -> io::Result<()> {
46  let mut buffer = itoa::Buffer::new();
47  let s = buffer.format(value);
48  writer.write_all(s.as_bytes())
49  }
50  /// Write an i16 value like '-123' to the specified writer.
51  #[inline]
52  fn write_i16<W: ?Sized + Write>(
53  &mut self,
54  writer: &mut W,
55  value: i16,
56  ) -> io::Result<()> {
57  let mut buffer = itoa::Buffer::new();
58  let s = buffer.format(value);
59  writer.write_all(s.as_bytes())
60  }
61  /// Write an i32 value like `-123` to the specified writer.
62  #[inline]
63  fn write_i32<W: ?Sized + Write>(
64  &mut self,
65  writer: &mut W,
66  value: i32,
67  ) -> io::Result<()> {
68  let mut buffer = itoa::Buffer::new();
69  let s = buffer.format(value);
70  writer.write_all(s.as_bytes())
71  }
72  /// Write an i64 value like `-123` to the specified writer.
73  #[inline]
74  fn write_i64<W: ?Sized + Write>(
75  &mut self,
76  writer: &mut W,
77  value: i64,
78  ) -> io::Result<()> {
79  let mut buffer = itoa::Buffer::new();
80  let s = buffer.format(value);
81  writer.write_all(s.as_bytes())
82  }
83  /// Write an i128 value like `-123` to the specified writer.
84  #[inline]
85  fn write_i128<W: ?Sized + Write>(
86  &mut self,
87  writer: &mut W,
88  value: i128,
89  ) -> io::Result<()> {
90  let mut buffer = itoa::Buffer::new();
91  let s = buffer.format(value);
92  writer.write_all(s.as_bytes())
93  }
94  /// Write a u8 value like `123` to the specified writer.
95  #[inline]
96  fn write_u8<W: ?Sized + Write>(
97  &mut self,
98  writer: &mut W,
99  value: u8,
100  ) -> io::Result<()> {
101  let mut buffer = itoa::Buffer::new();
102  let s = buffer.format(value);
103  writer.write_all(s.as_bytes())
104  }
105  /// Write a u16 value like `123` to the specified writer.
106  #[inline]
107  fn write_u16<W: ?Sized + Write>(
108  &mut self,
109  writer: &mut W,
110  value: u16,
111  ) -> io::Result<()> {
112  let mut buffer = itoa::Buffer::new();
113  let s = buffer.format(value);
114  writer.write_all(s.as_bytes())
115  }
116  /// Write a u32 value like `123` to the specified writer.
117  #[inline]
118  fn write_u32<W: ?Sized + Write>(
119  &mut self,
120  writer: &mut W,
121  value: u32,
122  ) -> io::Result<()> {
123  let mut buffer = itoa::Buffer::new();
124  let s = buffer.format(value);
125  writer.write_all(s.as_bytes())
126  }
127  /// Write a u64 value like `123` to the specified writer.
128  #[inline]
129  fn write_u64<W: ?Sized + Write>(
130  &mut self,
131  writer: &mut W,
132  value: u64,
133  ) -> io::Result<()> {
134  let mut buffer = itoa::Buffer::new();
135  let s = buffer.format(value);
136  writer.write_all(s.as_bytes())
137  }
138  /// Write a u128 value like `123` to the specified writer.
139  #[inline]
140  fn write_u128<W: ?Sized + Write>(
141  &mut self,
142  writer: &mut W,
143  value: u128,
144  ) -> io::Result<()> {
145  let mut buffer = itoa::Buffer::new();
146  let s = buffer.format(value);
147  writer.write_all(s.as_bytes())
148  }
149  /// Write a f32 value like `-31.26e+12` to the specified writer.
150  #[inline]
151  fn write_f32<W: ?Sized + Write>(
152  &mut self,
153  writer: &mut W,
154  value: f32,
155  ) -> io::Result<()> {
156  let mut buffer = ryu::Buffer::new();
157  let s = buffer.format_finite(value);
158  writer.write_all(s.as_bytes())
159  }
160  /// Write a f64 value like `-31.26e+12` to the specified writer.
161  #[inline]
162  fn write_f64<W: ?Sized + Write>(
163  &mut self,
164  writer: &mut W,
165  value: f64,
166  ) -> io::Result<()> {
167  let mut buffer = ryu::Buffer::new();
168  let s = buffer.format_finite(value);
169  writer.write_all(s.as_bytes())
170  }
171  /// Write a number that has already been rendered to a string.
172  #[inline]
173  fn write_number_str<W: ?Sized + Write>(
174  &mut self,
175  writer: &mut W,
176  value: &str,
177  ) -> io::Result<()> {
178  writer.write_all(value.as_bytes())
179  }
180  /// Called before each series of `write_string_fragment` and
181  /// `write_char_escape`. Writes a `"` to the specified writer.
182  #[inline]
183  fn begin_string<W: ?Sized + Write>(
184  &mut self,
185  writer: &mut W,
186  ) -> io::Result<()> {
187  writer.write_all(b"\"")
188  }
189  /// Called after each series of `write_string_fragment` and
190  /// `write_char_escape`. Writes a `"` to the specified writer.
191  #[inline]
192  fn end_string<W: ?Sized + Write>(
193  &mut self,
194  writer: &mut W,
195  ) -> io::Result<()> {
196  writer.write_all(b"\"")
197  }
198  /// Writes a string fragment that doesn't need any escaping to the
199  /// specified writer.
200  #[inline]
201  fn write_string_fragment<W: ?Sized + Write>(
202  &mut self,
203  writer: &mut W,
204  fragment: &str,
205  ) -> io::Result<()> {
206  writer.write_all(fragment.as_bytes())
207  }
208  /// Writes a character escape code to the specified writer.
209  #[inline]
210  fn write_char_escape<W: ?Sized + Write>(
211  &mut self,
212  writer: &mut W,
213  char_escape: CharEscape,
214  ) -> io::Result<()> {
215  use self::CharEscape::*;
216  let s = match char_escape {
217  Quote => b"\\\"",
218  ReverseSolidus => b"\\\\",
219  Solidus => b"\\/",
220  Backspace => b"\\b",
221  FormFeed => b"\\f",
222  LineFeed => b"\\n",
223  CarriageReturn => b"\\r",
224  Tab => b"\\t",
225  AsciiControl(byte) => {
226  static HEX_DIGITS: [u8; 16] = *b"0123456789abcdef";
227  let bytes = &[
228  b'\\',
229  b'u',
230  b'0',
231  b'0',
232  HEX_DIGITS[(byte >> 4) as usize],
233  HEX_DIGITS[(byte & 0xF) as usize],
234  ];
235  return writer.write_all(bytes);
236  }
237  };
238  writer.write_all(s)
239  }
240  #[inline]
241  fn write_symbol<W: ?Sized + Write>(
242  &mut self,
243  writer: &mut W,
244  sym: &str,
245  ) -> io::Result<()> {
246  writer.write_all(sym.as_bytes())
247  }
248  /// Called before every list. Writes a `(` to the specified
249  /// writer.
250  #[inline]
251  fn begin_list<W: ?Sized + Write>(
252  &mut self,
253  writer: &mut W,
254  ) -> io::Result<()> {
255  writer.write_all(b"(")
256  }
257  /// Called after every list. Writes a `)` to the specified
258  /// writer.
259  #[inline]
260  fn end_list<W: ?Sized + Write>(&mut self, writer: &mut W) -> io::Result<()> {
261  writer.write_all(b")")
262  }
263  /// Called before every list element. Writes a ` ` if needed to the
264  /// specified writer.
265  #[inline]
266  fn begin_list_element<W: ?Sized + Write>(
267  &mut self,
268  writer: &mut W,
269  car: bool,
270  ) -> io::Result<()> {
271  if car {
272  Ok(())
273  } else {
274  writer.write_all(b" ")
275  }
276  }
277  /// Called after every list element.
278  #[inline]
279  fn end_list_element<W: ?Sized + Write>(
280  &mut self,
281  _writer: &mut W,
282  ) -> io::Result<()> {
283  Ok(())
284  }
285  /// Called before every slot identifier. Writes a `:` to the
286  /// specified writer.
287  #[inline]
288  fn begin_key<W: ?Sized + Write>(&mut self, writer: &mut W) -> io::Result<()> {
289  writer.write_all(b":")
290  }
291 
292  /// Writes a raw JSON fragment that doesn't need any escaping to the
293  /// specified writer.
294  #[inline]
295  fn write_raw_fragment<W: ?Sized + Write>(
296  &mut self,
297  writer: &mut W,
298  fragment: &str,
299  ) -> io::Result<()> {
300  writer.write_all(fragment.as_bytes())
301  }
302 }
303 
304 /// The ReadFormatter is the sister interface to WriteFormatter.
305 pub trait ReadFormatter<'r>: Read<'r> {
306  #[inline]
307  fn peek<R: ?Sized + Read<'r>>(
308  &mut self,
309  reader: &'r mut R,
310  ) -> Result<Option<u8>> {
311  reader.peek()
312  }
313 
314  // /// Read a 'nil' value from the specified reader.
315  // #[inline]
316  // fn read_nil<R:?Sized+Read<'r>>(&mut self, reader: &'r R) -> io::Result<()>
317  // { reader
318  // }
319 }
320 
321 pub trait Formatter<'r>: ReadFormatter<'r> + WriteFormatter {}
322 impl<'r, T: ReadFormatter<'r> + WriteFormatter> Formatter<'r> for T {}
323 
324 pub struct DefaultFormatter;
325 // impl<'r> ReadFormatter<'r> for DefaultFormatter {}
326 impl WriteFormatter for DefaultFormatter {}
327 
328 pub struct BinaryFormatter;
329 // impl<'r> ReadFormatter<'r> for BinaryFormatter {}
330 impl WriteFormatter for BinaryFormatter {}
331 
332 pub struct PrettyFormatter;
333 // impl<'r> ReadFormatter<'r> for PrettyFormatter {}
334 impl WriteFormatter for PrettyFormatter {}