Skip to main content

serde_nt/ser/
mod.rs

1//! 流式直写 NestedText 文本序列化器。
2//!
3//! `to_string` 单遍直接把 `Serialize` 值写入单个 `String` 缓冲区:
4//! - 零中间 `Value` 树、零标量 `String` 分配;
5//! - `itoa` / `zmij` 直写栈缓冲;
6//! - 依据容器 `len` 预留 `String` 容量,大幅压低 `realloc` 次数。
7
8mod val;
9
10use itoa::Buffer as ItoaBuffer;
11use nt_syntax::{STEP, push_indent};
12use serde::{
13  Serialize,
14  ser::{
15    self, Impossible, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
16    SerializeTuple, SerializeTupleStruct, SerializeTupleVariant,
17  },
18};
19pub use val::to_value;
20use zmij::Buffer as ZmijBuffer;
21
22use crate::{
23  dump::{is_inline_key, multiline, write_multiline_key, write_str_block},
24  error::{Error, Result},
25};
26
27/// 序列化为 NestedText 文本(流式单缓冲直写,零中间 `Value` 分配)
28pub fn to_string<T: Serialize + ?Sized>(value: &T) -> Result<String> {
29  let mut out = String::with_capacity(128);
30  value.serialize(StreamSer {
31    out: &mut out,
32    depth: 0,
33    ctx: Ctx::Root,
34  })?;
35  Ok(out)
36}
37
38/// 当前标量 / 容器所处的排版位置
39#[derive(Clone, Copy, PartialEq, Eq)]
40enum Ctx {
41  /// 文档根
42  Root,
43  /// 列表项 `-` 已经写出(未写空格和换行),等待行内单行标量或换行缩进子块
44  AfterDash,
45  /// 字典键 `key:` 已经写出(未写空格和换行),等待行内单行标量或换行缩进子块
46  AfterColon,
47  /// 多行键 `: k\n` 已经写出换行,子值必须以 `depth` 块形态写出
48  BlockChild,
49}
50
51struct StreamSer<'a> {
52  out: &'a mut String,
53  depth: usize,
54  ctx: Ctx,
55}
56
57impl<'a> StreamSer<'a> {
58  /// 输出一个已知不含换行、无首尾空白的纯 ASCII 标量(数字、bool)
59  #[inline]
60  fn emit_clean_scalar(self, s: &str) -> Result<()> {
61    match self.ctx {
62      Ctx::AfterColon | Ctx::AfterDash => {
63        if !s.is_empty() {
64          self.out.push(' ');
65          self.out.push_str(s);
66        }
67        self.out.push('\n');
68      }
69      Ctx::Root | Ctx::BlockChild => {
70        push_indent(self.out, self.depth);
71        if s.is_empty() {
72          self.out.push_str(">\n");
73        } else {
74          self.out.push_str("> ");
75          self.out.push_str(s);
76          self.out.push('\n');
77        }
78      }
79    }
80    Ok(())
81  }
82
83  /// 输出任意字符串值(自动处理空串、行内或 `>` 多行块)
84  fn emit_str(self, s: &str) -> Result<()> {
85    match self.ctx {
86      Ctx::AfterColon | Ctx::AfterDash => {
87        if s.is_empty() {
88          self.out.push('\n');
89        } else if !multiline(s) {
90          self.out.push(' ');
91          self.out.push_str(s);
92          self.out.push('\n');
93        } else {
94          self.out.push('\n');
95          write_str_block(self.out, self.depth + STEP, s);
96        }
97      }
98      Ctx::Root | Ctx::BlockChild => {
99        write_str_block(self.out, self.depth, s);
100      }
101    }
102    Ok(())
103  }
104
105  /// 进入子容器(列表 / 字典)前闭合父标签行并计算子缩进
106  #[inline]
107  fn enter_container(&mut self) -> usize {
108    match self.ctx {
109      Ctx::AfterColon | Ctx::AfterDash => {
110        self.out.push('\n');
111        self.depth + STEP
112      }
113      Ctx::Root | Ctx::BlockChild => self.depth,
114    }
115  }
116}
117
118/// 把任意字典键写到 `out`,返回紧随其后的值应使用的 `(depth, Ctx)`
119#[inline]
120fn write_dict_key(out: &mut String, depth: usize, raw_key: &str) -> (usize, Ctx) {
121  if is_inline_key(raw_key) {
122    push_indent(out, depth);
123    out.push_str(raw_key);
124    out.push(':');
125    (depth, Ctx::AfterColon)
126  } else {
127    write_multiline_key(out, depth, raw_key);
128    (depth + STEP, Ctx::BlockChild)
129  }
130}
131
132macro_rules! stream_int {
133  ($($method:ident => $t:ty),* $(,)?) => {
134    $(
135      #[inline]
136      fn $method(self, v: $t) -> Result<Self::Ok> {
137        let mut b = ItoaBuffer::new();
138        self.emit_clean_scalar(b.format(v))
139      }
140    )*
141  };
142}
143
144macro_rules! key_int {
145  ($($method:ident => $t:ty),* $(,)?) => {
146    $(
147      #[inline]
148      fn $method(self, v: $t) -> Result<Self::Ok> {
149        let mut b = ItoaBuffer::new();
150        self.emit(b.format(v))
151      }
152    )*
153  };
154}
155
156impl<'a> ser::Serializer for StreamSer<'a> {
157  type Ok = ();
158  type Error = Error;
159  type SerializeSeq = StreamSeq<'a>;
160  type SerializeTuple = StreamSeq<'a>;
161  type SerializeTupleStruct = StreamSeq<'a>;
162  type SerializeTupleVariant = StreamTupleVariant<'a>;
163  type SerializeMap = StreamMap<'a>;
164  type SerializeStruct = StreamMap<'a>;
165  type SerializeStructVariant = StreamStructVariant<'a>;
166
167  #[inline]
168  fn serialize_bool(self, v: bool) -> Result<()> {
169    self.emit_clean_scalar(if v { "true" } else { "false" })
170  }
171
172  stream_int! {
173    serialize_i8 => i8,
174    serialize_i16 => i16,
175    serialize_i32 => i32,
176    serialize_i64 => i64,
177    serialize_i128 => i128,
178    serialize_u8 => u8,
179    serialize_u16 => u16,
180    serialize_u32 => u32,
181    serialize_u64 => u64,
182    serialize_u128 => u128,
183  }
184
185  #[inline]
186  fn serialize_f32(self, v: f32) -> Result<()> {
187    let mut b = ZmijBuffer::new();
188    self.emit_clean_scalar(b.format(v))
189  }
190
191  #[inline]
192  fn serialize_f64(self, v: f64) -> Result<()> {
193    let mut b = ZmijBuffer::new();
194    self.emit_clean_scalar(b.format(v))
195  }
196
197  #[inline]
198  fn serialize_char(self, v: char) -> Result<()> {
199    let mut buf = [0u8; 4];
200    self.emit_str(v.encode_utf8(&mut buf))
201  }
202
203  #[inline]
204  fn serialize_str(self, v: &str) -> Result<()> {
205    self.emit_str(v)
206  }
207
208  fn serialize_bytes(self, _: &[u8]) -> Result<()> {
209    Err(Error::msg("NestedText does not support byte arrays"))
210  }
211
212  #[inline]
213  fn serialize_none(self) -> Result<()> {
214    self.emit_str("")
215  }
216
217  #[inline]
218  fn serialize_some<T: Serialize + ?Sized>(self, value: &T) -> Result<()> {
219    value.serialize(self)
220  }
221
222  #[inline]
223  fn serialize_unit(self) -> Result<()> {
224    self.emit_str("")
225  }
226
227  #[inline]
228  fn serialize_unit_struct(self, _: &'static str) -> Result<()> {
229    self.emit_str("")
230  }
231
232  #[inline]
233  fn serialize_unit_variant(self, _: &'static str, _: u32, variant: &'static str) -> Result<()> {
234    self.emit_str(variant)
235  }
236
237  #[inline]
238  fn serialize_newtype_struct<T: Serialize + ?Sized>(
239    self,
240    _: &'static str,
241    value: &T,
242  ) -> Result<()> {
243    value.serialize(self)
244  }
245
246  fn serialize_newtype_variant<T: Serialize + ?Sized>(
247    mut self,
248    _: &'static str,
249    _: u32,
250    variant: &'static str,
251    value: &T,
252  ) -> Result<()> {
253    let d = self.enter_container();
254    let (vd, vctx) = write_dict_key(self.out, d, variant);
255    value.serialize(StreamSer {
256      out: self.out,
257      depth: vd,
258      ctx: vctx,
259    })
260  }
261
262  fn serialize_seq(mut self, len: Option<usize>) -> Result<StreamSeq<'a>> {
263    let d = self.enter_container();
264    if d == 0
265      && let Some(n) = len.filter(|&n| n > 0)
266    {
267      self.out.reserve(n.saturating_mul(16));
268    }
269    Ok(StreamSeq {
270      out: self.out,
271      depth: d,
272      count: 0,
273    })
274  }
275
276  fn serialize_tuple(self, len: usize) -> Result<StreamSeq<'a>> {
277    self.serialize_seq(Some(len))
278  }
279
280  fn serialize_tuple_struct(self, _: &'static str, len: usize) -> Result<StreamSeq<'a>> {
281    self.serialize_seq(Some(len))
282  }
283
284  fn serialize_tuple_variant(
285    mut self,
286    _: &'static str,
287    _: u32,
288    variant: &'static str,
289    _: usize,
290  ) -> Result<StreamTupleVariant<'a>> {
291    let d = self.enter_container();
292    let (vd, vctx) = write_dict_key(self.out, d, variant);
293    let seq_depth = match vctx {
294      Ctx::AfterColon => {
295        self.out.push('\n');
296        vd + STEP
297      }
298      _ => vd,
299    };
300    Ok(StreamTupleVariant {
301      seq: StreamSeq {
302        out: self.out,
303        depth: seq_depth,
304        count: 0,
305      },
306    })
307  }
308
309  fn serialize_map(mut self, len: Option<usize>) -> Result<StreamMap<'a>> {
310    let d = self.enter_container();
311    if d == 0
312      && let Some(n) = len.filter(|&n| n > 0)
313    {
314      self.out.reserve(n.saturating_mul(64));
315    }
316    Ok(StreamMap {
317      out: self.out,
318      depth: d,
319      count: 0,
320      val_target: None,
321    })
322  }
323
324  fn serialize_struct(self, _: &'static str, len: usize) -> Result<StreamMap<'a>> {
325    self.serialize_map(Some(len))
326  }
327
328  fn serialize_struct_variant(
329    mut self,
330    _: &'static str,
331    _: u32,
332    variant: &'static str,
333    _: usize,
334  ) -> Result<StreamStructVariant<'a>> {
335    let d = self.enter_container();
336    let (vd, vctx) = write_dict_key(self.out, d, variant);
337    let map_depth = match vctx {
338      Ctx::AfterColon => {
339        self.out.push('\n');
340        vd + STEP
341      }
342      _ => vd,
343    };
344    Ok(StreamStructVariant {
345      map: StreamMap {
346        out: self.out,
347        depth: map_depth,
348        count: 0,
349        val_target: None,
350      },
351    })
352  }
353}
354
355pub struct StreamSeq<'a> {
356  out: &'a mut String,
357  depth: usize,
358  count: usize,
359}
360
361impl SerializeSeq for StreamSeq<'_> {
362  type Ok = ();
363  type Error = Error;
364
365  #[inline]
366  fn serialize_element<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<()> {
367    self.count += 1;
368    push_indent(self.out, self.depth);
369    self.out.push('-');
370    value.serialize(StreamSer {
371      out: self.out,
372      depth: self.depth,
373      ctx: Ctx::AfterDash,
374    })
375  }
376
377  #[inline]
378  fn end(self) -> Result<()> {
379    if self.count == 0 {
380      push_indent(self.out, self.depth);
381      self.out.push_str("[]\n");
382    }
383    Ok(())
384  }
385}
386
387impl SerializeTuple for StreamSeq<'_> {
388  type Ok = ();
389  type Error = Error;
390
391  fn serialize_element<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<()> {
392    SerializeSeq::serialize_element(self, value)
393  }
394
395  fn end(self) -> Result<()> {
396    SerializeSeq::end(self)
397  }
398}
399
400impl SerializeTupleStruct for StreamSeq<'_> {
401  type Ok = ();
402  type Error = Error;
403
404  fn serialize_field<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<()> {
405    SerializeSeq::serialize_element(self, value)
406  }
407
408  fn end(self) -> Result<()> {
409    SerializeSeq::end(self)
410  }
411}
412
413pub struct StreamTupleVariant<'a> {
414  seq: StreamSeq<'a>,
415}
416
417impl SerializeTupleVariant for StreamTupleVariant<'_> {
418  type Ok = ();
419  type Error = Error;
420
421  fn serialize_field<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<()> {
422    SerializeSeq::serialize_element(&mut self.seq, value)
423  }
424
425  fn end(self) -> Result<()> {
426    SerializeSeq::end(self.seq)
427  }
428}
429
430pub struct StreamMap<'a> {
431  out: &'a mut String,
432  depth: usize,
433  count: usize,
434  val_target: Option<(usize, Ctx)>,
435}
436
437impl SerializeMap for StreamMap<'_> {
438  type Ok = ();
439  type Error = Error;
440
441  #[inline]
442  fn serialize_key<T: Serialize + ?Sized>(&mut self, key: &T) -> Result<()> {
443    self.count += 1;
444    let target = key.serialize(KeyWriter {
445      out: self.out,
446      depth: self.depth,
447    })?;
448    self.val_target = Some(target);
449    Ok(())
450  }
451
452  #[inline]
453  fn serialize_value<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<()> {
454    let (vd, vctx) = self
455      .val_target
456      .take()
457      .ok_or_else(|| Error::msg("missing dictionary key"))?;
458    value.serialize(StreamSer {
459      out: self.out,
460      depth: vd,
461      ctx: vctx,
462    })
463  }
464
465  #[inline]
466  fn end(self) -> Result<()> {
467    if self.count == 0 {
468      push_indent(self.out, self.depth);
469      self.out.push_str("{}\n");
470    }
471    Ok(())
472  }
473}
474
475impl SerializeStruct for StreamMap<'_> {
476  type Ok = ();
477  type Error = Error;
478
479  #[inline]
480  fn serialize_field<T: Serialize + ?Sized>(&mut self, key: &'static str, value: &T) -> Result<()> {
481    self.count += 1;
482    let (vd, vctx) = write_dict_key(self.out, self.depth, key);
483    value.serialize(StreamSer {
484      out: self.out,
485      depth: vd,
486      ctx: vctx,
487    })
488  }
489
490  #[inline]
491  fn end(self) -> Result<()> {
492    SerializeMap::end(self)
493  }
494}
495
496pub struct StreamStructVariant<'a> {
497  map: StreamMap<'a>,
498}
499
500impl SerializeStructVariant for StreamStructVariant<'_> {
501  type Ok = ();
502  type Error = Error;
503
504  fn serialize_field<T: Serialize + ?Sized>(&mut self, key: &'static str, value: &T) -> Result<()> {
505    SerializeStruct::serialize_field(&mut self.map, key, value)
506  }
507
508  fn end(self) -> Result<()> {
509    SerializeStruct::end(self.map)
510  }
511}
512
513/// 零分配字典键写出器:把标量键直接写进 `out` 缓冲,不分配临时 `String`
514struct KeyWriter<'a> {
515  out: &'a mut String,
516  depth: usize,
517}
518
519impl KeyWriter<'_> {
520  #[inline]
521  fn emit(self, s: &str) -> Result<(usize, Ctx)> {
522    Ok(write_dict_key(self.out, self.depth, s))
523  }
524}
525
526impl ser::Serializer for KeyWriter<'_> {
527  type Ok = (usize, Ctx);
528  type Error = Error;
529  type SerializeSeq = Impossible<(usize, Ctx), Error>;
530  type SerializeTuple = Impossible<(usize, Ctx), Error>;
531  type SerializeTupleStruct = Impossible<(usize, Ctx), Error>;
532  type SerializeTupleVariant = Impossible<(usize, Ctx), Error>;
533  type SerializeMap = Impossible<(usize, Ctx), Error>;
534  type SerializeStruct = Impossible<(usize, Ctx), Error>;
535  type SerializeStructVariant = Impossible<(usize, Ctx), Error>;
536
537  fn serialize_bool(self, v: bool) -> Result<Self::Ok> {
538    self.emit(if v { "true" } else { "false" })
539  }
540
541  key_int! {
542    serialize_i8 => i8,
543    serialize_i16 => i16,
544    serialize_i32 => i32,
545    serialize_i64 => i64,
546    serialize_i128 => i128,
547    serialize_u8 => u8,
548    serialize_u16 => u16,
549    serialize_u32 => u32,
550    serialize_u64 => u64,
551    serialize_u128 => u128,
552  }
553
554  fn serialize_f32(self, v: f32) -> Result<Self::Ok> {
555    let mut b = ZmijBuffer::new();
556    self.emit(b.format(v))
557  }
558
559  fn serialize_f64(self, v: f64) -> Result<Self::Ok> {
560    let mut b = ZmijBuffer::new();
561    self.emit(b.format(v))
562  }
563
564  fn serialize_char(self, v: char) -> Result<Self::Ok> {
565    let mut buf = [0u8; 4];
566    self.emit(v.encode_utf8(&mut buf))
567  }
568
569  #[inline]
570  fn serialize_str(self, v: &str) -> Result<Self::Ok> {
571    self.emit(v)
572  }
573
574  fn serialize_bytes(self, _: &[u8]) -> Result<Self::Ok> {
575    Err(Error::msg("NestedText dictionary keys must be strings"))
576  }
577
578  fn serialize_none(self) -> Result<Self::Ok> {
579    self.emit("")
580  }
581
582  fn serialize_some<T: Serialize + ?Sized>(self, value: &T) -> Result<Self::Ok> {
583    value.serialize(self)
584  }
585
586  fn serialize_unit(self) -> Result<Self::Ok> {
587    self.emit("")
588  }
589
590  fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok> {
591    self.emit("")
592  }
593
594  fn serialize_unit_variant(self, _: &'static str, _: u32, v: &'static str) -> Result<Self::Ok> {
595    self.emit(v)
596  }
597
598  fn serialize_newtype_struct<T: Serialize + ?Sized>(
599    self,
600    _: &'static str,
601    value: &T,
602  ) -> Result<Self::Ok> {
603    value.serialize(self)
604  }
605
606  fn serialize_newtype_variant<T: Serialize + ?Sized>(
607    self,
608    _: &'static str,
609    _: u32,
610    _: &'static str,
611    _: &T,
612  ) -> Result<Self::Ok> {
613    Err(Error::msg("NestedText dictionary keys must be strings"))
614  }
615
616  fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq> {
617    Err(Error::msg("NestedText dictionary keys must be strings"))
618  }
619
620  fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple> {
621    Err(Error::msg("NestedText dictionary keys must be strings"))
622  }
623
624  fn serialize_tuple_struct(self, _: &'static str, _: usize) -> Result<Self::SerializeTupleStruct> {
625    Err(Error::msg("NestedText dictionary keys must be strings"))
626  }
627
628  fn serialize_tuple_variant(
629    self,
630    _: &'static str,
631    _: u32,
632    _: &'static str,
633    _: usize,
634  ) -> Result<Self::SerializeTupleVariant> {
635    Err(Error::msg("NestedText dictionary keys must be strings"))
636  }
637
638  fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap> {
639    Err(Error::msg("NestedText dictionary keys must be strings"))
640  }
641
642  fn serialize_struct(self, _: &'static str, _: usize) -> Result<Self::SerializeStruct> {
643    Err(Error::msg("NestedText dictionary keys must be strings"))
644  }
645
646  fn serialize_struct_variant(
647    self,
648    _: &'static str,
649    _: u32,
650    _: &'static str,
651    _: usize,
652  ) -> Result<Self::SerializeStructVariant> {
653    Err(Error::msg("NestedText dictionary keys must be strings"))
654  }
655}