1use crate::error::YsonError;
2use serde::{Serialize, ser};
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6pub enum YsonFormat {
7 Binary,
9 Text,
11}
12
13pub struct Serializer {
15 pub output: Vec<u8>,
17 pub(crate) is_binary: bool,
18 pub(crate) is_writing_attributes: bool,
19}
20
21impl Serializer {
22 #[must_use]
40 pub fn new(is_binary: bool) -> Self {
41 Self::with_buffer(Vec::with_capacity(8192), is_binary)
42 }
43
44 #[must_use]
51 pub fn with_buffer(buffer: Vec<u8>, is_binary: bool) -> Self {
52 Self {
53 output: buffer,
54 is_binary,
55 is_writing_attributes: false,
56 }
57 }
58
59 #[must_use]
61 pub fn into_output(self) -> Vec<u8> {
62 self.output
63 }
64
65 #[inline]
66 fn write_entity(&mut self) {
67 self.output.push(0x23);
68 }
69
70 fn write_bool(&mut self, v: bool) {
71 if self.is_binary {
72 self.output.push(if v { 0x05 } else { 0x04 });
73 } else {
74 self.output
75 .extend_from_slice(if v { b"%true" } else { b"%false" });
76 }
77 }
78
79 fn write_i64(&mut self, v: i64) {
80 if self.is_binary {
81 self.output.push(0x02);
82 crate::varint::write_varint(v, &mut self.output);
83 } else {
84 self.output
85 .extend_from_slice(itoa::Buffer::new().format(v).as_bytes());
86 }
87 }
88
89 fn write_u64(&mut self, v: u64) {
90 if self.is_binary {
91 self.output.push(0x06);
92 crate::varint::write_uvarint(v, &mut self.output);
93 } else {
94 self.output
95 .extend_from_slice(itoa::Buffer::new().format(v).as_bytes());
96 self.output.push(b'u');
97 }
98 }
99
100 fn write_f64(&mut self, v: f64) {
101 if self.is_binary {
102 self.output.push(0x03);
103 self.output.extend_from_slice(&v.to_le_bytes());
104 } else if v.is_nan() {
105 self.output.extend_from_slice(b"%nan");
106 } else if v.is_infinite() {
107 self.output.extend_from_slice(if v.is_sign_negative() {
108 b"%-inf"
109 } else {
110 b"%inf"
111 });
112 } else {
113 let s = ryu::Buffer::new().format(v).to_owned();
114 self.output.extend_from_slice(s.as_bytes());
115 if !s.contains(&['.', 'e', 'E'][..]) {
116 self.output.extend_from_slice(b".0");
117 }
118 }
119 }
120
121 fn write_string(&mut self, v: &str) {
122 if self.is_binary {
123 self.output.push(0x01);
124 crate::varint::write_varint(v.len() as i64, &mut self.output);
125 self.output.extend_from_slice(v.as_bytes());
126 } else if is_safe_unquoted(v.as_bytes()) {
127 self.output.extend_from_slice(v.as_bytes());
128 } else {
129 self.output.push(b'"');
130 for &b in v.as_bytes() {
131 match b {
132 b'"' => self.output.extend_from_slice(b"\\\""),
133 b'\\' => self.output.extend_from_slice(b"\\\\"),
134 b'\n' => self.output.extend_from_slice(b"\\n"),
135 b'\r' => self.output.extend_from_slice(b"\\r"),
136 b'\t' => self.output.extend_from_slice(b"\\t"),
137 0x00..=0x1F => {
138 const HEX: &[u8] = b"0123456789abcdef";
139 self.output.extend_from_slice(&[
140 b'\\',
141 b'x',
142 HEX[(b >> 4) as usize],
143 HEX[(b & 0x0F) as usize],
144 ]);
145 }
146 _ => self.output.push(b),
147 }
148 }
149 self.output.push(b'"');
150 }
151 }
152}
153
154macro_rules! impl_serialize {
155 ($($name:ident($ty:ty) => $method:ident as $cast:ty),*) => {
157 $(fn $name(self, v: $ty) -> Result<(), Self::Error> { self.$method(v as $cast); Ok(()) })*
158 };
159 (@empty $($name:ident $(($($arg:ident: $ty:ty),*))?),*) => {
161 $(fn $name(self $(, $($arg: $ty),*)?) -> Result<(), Self::Error> { self.write_entity(); Ok(()) })*
162 };
163}
164
165impl<'a> ser::Serializer for &'a mut Serializer {
166 type Ok = ();
167 type Error = YsonError;
168 type SerializeSeq = Compound<'a>;
169 type SerializeTuple = Compound<'a>;
170 type SerializeTupleStruct = Compound<'a>;
171 type SerializeTupleVariant = Compound<'a>;
172 type SerializeMap = Compound<'a>;
173 type SerializeStruct = Compound<'a>;
174 type SerializeStructVariant = Compound<'a>;
175
176 impl_serialize! {
177 serialize_i8(i8) => write_i64 as i64, serialize_i16(i16) => write_i64 as i64,
178 serialize_i32(i32) => write_i64 as i64, serialize_i64(i64) => write_i64 as i64,
179 serialize_u8(u8) => write_u64 as u64, serialize_u16(u16) => write_u64 as u64,
180 serialize_u32(u32) => write_u64 as u64, serialize_u64(u64) => write_u64 as u64,
181 serialize_f32(f32) => write_f64 as f64, serialize_f64(f64) => write_f64 as f64
182 }
183
184 impl_serialize!(@empty serialize_none, serialize_unit, serialize_unit_struct(_n: &'static str));
185
186 fn serialize_bool(self, v: bool) -> Result<(), Self::Error> {
187 self.write_bool(v);
188 Ok(())
189 }
190 fn serialize_char(self, v: char) -> Result<(), Self::Error> {
191 self.write_string(&v.to_string());
192 Ok(())
193 }
194 fn serialize_str(self, v: &str) -> Result<(), Self::Error> {
195 self.write_string(v);
196 Ok(())
197 }
198
199 fn serialize_bytes(self, v: &[u8]) -> Result<(), Self::Error> {
200 if self.is_binary {
201 self.output.push(0x01);
202 crate::varint::write_varint(v.len() as i64, &mut self.output);
203 self.output.extend_from_slice(v);
204 } else {
205 self.output.push(b'"');
206 for &b in v {
207 match b {
208 b'"' => self.output.extend_from_slice(b"\\\""),
209 b'\\' => self.output.extend_from_slice(b"\\\\"),
210 b'\n' => self.output.extend_from_slice(b"\\n"),
211 b'\r' => self.output.extend_from_slice(b"\\r"),
212 b'\t' => self.output.extend_from_slice(b"\\t"),
213 0x20..=0x7E => self.output.push(b),
214 _ => {
215 const HEX: &[u8] = b"0123456789abcdef";
216 self.output.extend_from_slice(&[
217 b'\\',
218 b'x',
219 HEX[(b >> 4) as usize],
220 HEX[(b & 0x0F) as usize],
221 ]);
222 }
223 }
224 }
225 self.output.push(b'"');
226 }
227 Ok(())
228 }
229
230 fn serialize_some<T: ?Sized + Serialize>(self, v: &T) -> Result<(), Self::Error> {
231 v.serialize(self)
232 }
233 fn serialize_newtype_struct<T: ?Sized + Serialize>(
234 self,
235 _: &'static str,
236 v: &T,
237 ) -> Result<(), Self::Error> {
238 v.serialize(self)
239 }
240
241 fn serialize_unit_variant(
242 self,
243 _: &'static str,
244 _: u32,
245 variant: &'static str,
246 ) -> Result<(), Self::Error> {
247 self.write_string(variant);
248 Ok(())
249 }
250
251 fn serialize_newtype_variant<T: ?Sized + Serialize>(
252 self,
253 _: &'static str,
254 _: u32,
255 var: &'static str,
256 val: &T,
257 ) -> Result<(), Self::Error> {
258 self.output.push(b'{');
259 self.write_string(var);
260 self.output.push(b'=');
261 val.serialize(&mut *self)?;
262 self.output.push(b'}');
263 Ok(())
264 }
265
266 fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
267 self.output.push(b'[');
268 Ok(Compound {
269 ser: self,
270 first: true,
271 mode: CompoundMode::Seq,
272 })
273 }
274
275 fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
276 self.serialize_seq(Some(len))
277 }
278 fn serialize_tuple_struct(
279 self,
280 _: &'static str,
281 len: usize,
282 ) -> Result<Self::SerializeTupleStruct, Self::Error> {
283 self.serialize_seq(Some(len))
284 }
285
286 fn serialize_tuple_variant(
287 self,
288 _: &'static str,
289 _: u32,
290 var: &'static str,
291 _: usize,
292 ) -> Result<Self::SerializeTupleVariant, Self::Error> {
293 self.output.push(b'{');
294 self.write_string(var);
295 self.output.extend_from_slice(b"=[");
296 Ok(Compound {
297 ser: self,
298 first: true,
299 mode: CompoundMode::VariantSeq,
300 })
301 }
302
303 fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
304 let (open, mode) = if self.is_writing_attributes {
305 (b'<', CompoundMode::Attr)
306 } else {
307 (b'{', CompoundMode::Map)
308 };
309 self.output.push(open);
310 self.is_writing_attributes = false;
311 Ok(Compound {
312 ser: self,
313 first: true,
314 mode,
315 })
316 }
317
318 fn serialize_struct(
319 self,
320 name: &'static str,
321 _: usize,
322 ) -> Result<Self::SerializeStruct, Self::Error> {
323 let mode = if name == "$__yson_attributes" {
324 CompoundMode::AttrWrapper
325 } else if self.is_writing_attributes {
326 self.output.push(b'<');
327 self.is_writing_attributes = false;
328 CompoundMode::Attr
329 } else {
330 CompoundMode::Struct {
331 attr_open: false,
332 body_open: false,
333 value_written: false,
334 }
335 };
336 Ok(Compound {
337 ser: self,
338 first: true,
339 mode,
340 })
341 }
342
343 fn serialize_struct_variant(
344 self,
345 _: &'static str,
346 _: u32,
347 var: &'static str,
348 _: usize,
349 ) -> Result<Self::SerializeStructVariant, Self::Error> {
350 self.output.push(b'{');
351 self.write_string(var);
352 self.output.extend_from_slice(b"={");
353 Ok(Compound {
354 ser: self,
355 first: true,
356 mode: CompoundMode::VariantMap,
357 })
358 }
359}
360
361#[derive(Clone, Copy)]
362enum CompoundMode {
363 Seq,
364 Map,
365 Attr,
366 AttrWrapper,
367 VariantSeq,
368 VariantMap,
369 Struct {
370 attr_open: bool,
371 body_open: bool,
372 value_written: bool,
375 },
376}
377
378pub struct Compound<'a> {
380 ser: &'a mut Serializer,
381 first: bool,
382 mode: CompoundMode,
383}
384
385impl Compound<'_> {
386 #[inline]
387 fn check_first(&mut self) {
388 if !self.first {
389 self.ser.output.push(b';');
390 }
391 self.first = false;
392 }
393}
394
395macro_rules! delegate_seq {
396 ($($trait:ident),*) => {
397 $(impl<'a> ser::$trait for Compound<'a> {
398 type Ok = (); type Error = YsonError;
399 fn serialize_element<T: ?Sized + Serialize>(&mut self, v: &T) -> Result<(), Self::Error> {
400 self.check_first(); v.serialize(&mut *self.ser)
401 }
402 fn end(self) -> Result<(), Self::Error> { self.ser.output.push(b']'); Ok(()) }
403 })*
404 };
405}
406delegate_seq!(SerializeSeq, SerializeTuple);
407
408impl ser::SerializeTupleStruct for Compound<'_> {
409 type Ok = ();
410 type Error = YsonError;
411 fn serialize_field<T: ?Sized + Serialize>(&mut self, v: &T) -> Result<(), Self::Error> {
412 self.check_first();
413 v.serialize(&mut *self.ser)
414 }
415 fn end(self) -> Result<(), Self::Error> {
416 self.ser.output.push(b']');
417 Ok(())
418 }
419}
420
421impl ser::SerializeTupleVariant for Compound<'_> {
422 type Ok = ();
423 type Error = YsonError;
424 fn serialize_field<T: ?Sized + Serialize>(&mut self, v: &T) -> Result<(), Self::Error> {
425 self.check_first();
426 v.serialize(&mut *self.ser)
427 }
428 fn end(self) -> Result<(), Self::Error> {
429 self.ser.output.extend_from_slice(b"]}");
430 Ok(())
431 }
432}
433
434impl ser::SerializeMap for Compound<'_> {
435 type Ok = ();
436 type Error = YsonError;
437 fn serialize_key<T: ?Sized + Serialize>(&mut self, key: &T) -> Result<(), Self::Error> {
438 self.check_first();
439 key.serialize(&mut *self.ser)
440 }
441 fn serialize_value<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error> {
442 self.ser.output.push(b'=');
443 value.serialize(&mut *self.ser)
444 }
445 fn end(self) -> Result<(), Self::Error> {
446 self.ser
447 .output
448 .push(if matches!(self.mode, CompoundMode::Attr) {
449 b'>'
450 } else {
451 b'}'
452 });
453 Ok(())
454 }
455}
456
457impl ser::SerializeStruct for Compound<'_> {
458 type Ok = ();
459 type Error = YsonError;
460
461 fn serialize_field<T: ?Sized + Serialize>(
462 &mut self,
463 key: &'static str,
464 value: &T,
465 ) -> Result<(), Self::Error> {
466 match self.mode {
467 CompoundMode::AttrWrapper => {
468 if key == "$attributes" {
469 self.ser.is_writing_attributes = true;
470 value.serialize(&mut *self.ser)?;
471 } else if key == "$value" {
472 value.serialize(&mut *self.ser)?;
473 }
474 }
475 CompoundMode::Struct {
476 mut attr_open,
477 mut body_open,
478 mut value_written,
479 } => {
480 if let Some(attr_name) = key.strip_prefix('@') {
481 if body_open || value_written {
485 return Err(YsonError::Custom(format!(
486 "attribute field \"@{attr_name}\" is declared after a value \
487 field; attribute fields must come first in the struct"
488 )));
489 }
490 if !attr_open {
491 self.ser.output.push(b'<');
492 attr_open = true;
493 self.first = true;
494 }
495 self.check_first();
496 self.ser.write_string(attr_name);
497 self.ser.output.push(b'=');
498 } else {
499 if attr_open {
500 self.ser.output.push(b'>');
501 attr_open = false;
502 }
503 if key == "$value" {
504 if body_open || value_written {
507 return Err(YsonError::Custom(
508 "\"$value\" cannot share a struct with plain fields: \
509 one value cannot have two bodies"
510 .into(),
511 ));
512 }
513 value_written = true;
514 } else {
515 if value_written {
516 return Err(YsonError::Custom(format!(
517 "field \"{key}\" is declared after \"$value\"; a struct \
518 with a \"$value\" field can carry only attributes beside it"
519 )));
520 }
521 if !body_open {
522 self.ser.output.push(b'{');
523 body_open = true;
524 self.first = true;
525 }
526 self.check_first();
527 self.ser.write_string(key);
528 self.ser.output.push(b'=');
529 }
530 }
531
532 self.mode = CompoundMode::Struct {
533 attr_open,
534 body_open,
535 value_written,
536 };
537 value.serialize(&mut *self.ser)?;
538 }
539 _ => {
540 self.check_first();
541 self.ser.write_string(key);
542 self.ser.output.push(b'=');
543 value.serialize(&mut *self.ser)?;
544 }
545 }
546 Ok(())
547 }
548
549 fn end(self) -> Result<(), Self::Error> {
550 match self.mode {
551 CompoundMode::Attr => self.ser.output.push(b'>'),
552 CompoundMode::Seq | CompoundMode::VariantSeq => self.ser.output.push(b']'),
553 CompoundMode::Struct {
554 attr_open,
555 body_open,
556 value_written,
557 } => {
558 if attr_open {
559 self.ser.output.extend_from_slice(b">#");
563 } else if body_open {
564 self.ser.output.push(b'}');
565 } else if !value_written {
566 self.ser.output.extend_from_slice(b"{}");
569 }
570 }
571 CompoundMode::AttrWrapper => {}
572 _ => self.ser.output.push(b'}'),
573 }
574 Ok(())
575 }
576}
577
578impl ser::SerializeStructVariant for Compound<'_> {
579 type Ok = ();
580 type Error = YsonError;
581 fn serialize_field<T: ?Sized + Serialize>(
582 &mut self,
583 k: &'static str,
584 v: &T,
585 ) -> Result<(), Self::Error> {
586 ser::SerializeStruct::serialize_field(self, k, v)
587 }
588 fn end(self) -> Result<(), Self::Error> {
589 self.ser.output.extend_from_slice(b"}}");
590 Ok(())
591 }
592}
593
594fn is_safe_unquoted(b: &[u8]) -> bool {
595 matches!(b.first(), Some(f) if f.is_ascii_alphabetic() || *f == b'_')
596 && b.iter()
597 .all(|&c| c.is_ascii_alphanumeric() || b"_-.".contains(&c))
598}