oficina / docs Public

Clone
git clone https://amadan.net/oficina/docs

Plain git — no account needed to clone.

Download

Download this file

1use crate::any::Any;
2use serde::ser::{
3 SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple,
4 SerializeTupleStruct, SerializeTupleVariant,
5};
6use serde::{Serialize, Serializer};
7use std::collections::HashMap;
8use std::convert::TryInto;
9use std::fmt::Display;
10use thiserror::Error;
11
12pub fn to_any<T: Serialize>(value: &T) -> Result<Any, AnySerializeError> {
13 value.serialize(AnySerializer)
14}
15
16impl Serialize for Any {
17 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
18 where
19 S: Serializer,
20 {
21 match self {
22 Any::Null => serializer.serialize_none(),
23 Any::Undefined => serializer.serialize_none(),
24 Any::Bool(value) => serializer.serialize_bool(*value),
25 Any::Number(value) => {
26 let value = *value;
27 // since JS doesn't clearly recognise difference between integers and floats,
28 // we check if it's possible to perform lossless conversion to i64
29 if value as i64 as f64 == value {
30 serializer.serialize_i64(value as i64)
31 } else {
32 serializer.serialize_f64(value)
33 }
34 }
35 Any::BigInt(value) => serializer.serialize_i64(*value),
36 Any::String(value) => serializer.serialize_str(value.as_ref()),
37 Any::Array(values) => {
38 let mut seq = serializer.serialize_seq(Some(values.len()))?;
39 for value in values.iter() {
40 seq.serialize_element(value)?;
41 }
42 seq.end()
43 }
44 Any::Map(entries) => {
45 let mut map = serializer.serialize_map(Some(entries.len()))?;
46 for (key, value) in entries.iter() {
47 map.serialize_entry(key, value)?;
48 }
49 map.end()
50 }
51 Any::Buffer(buf) => serializer.serialize_bytes(buf),
52 }
53 }
54}
55
56struct AnySerializer;
57
58#[derive(Debug, Error)]
59#[non_exhaustive]
60pub enum AnySerializeError {
61 #[error("integers above i64::MAX cannot be represented as Any")]
62 UnrepresentableInt,
63 #[error("Any only supports Strings as map keys")]
64 MapKeyNotString,
65 #[error("{0}")]
66 Custom(String),
67}
68
69impl serde::ser::Error for AnySerializeError {
70 fn custom<T>(msg: T) -> Self
71 where
72 T: Display,
73 {
74 AnySerializeError::Custom(msg.to_string())
75 }
76}
77
78impl Serializer for AnySerializer {
79 type Ok = Any;
80 type Error = AnySerializeError;
81 type SerializeSeq = AnyArraySerializer;
82 type SerializeTuple = AnyArraySerializer;
83 type SerializeTupleStruct = AnyArraySerializer;
84 type SerializeTupleVariant = AnyTupleVariantSerializer;
85 type SerializeMap = AnyMapSerializer;
86 type SerializeStruct = AnyMapSerializer;
87 type SerializeStructVariant = AnyStructVariantSerializer;
88
89 #[inline]
90 fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
91 Ok(Any::Bool(v))
92 }
93
94 #[inline]
95 fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
96 self.serialize_i64(v.into())
97 }
98
99 #[inline]
100 fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
101 self.serialize_i64(v.into())
102 }
103
104 #[inline]
105 fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
106 self.serialize_i64(v.into())
107 }
108
109 #[inline]
110 fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
111 Ok(Any::from(v))
112 }
113
114 #[inline]
115 fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
116 self.serialize_i64(v.into())
117 }
118
119 #[inline]
120 fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
121 self.serialize_i64(v.into())
122 }
123
124 #[inline]
125 fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
126 self.serialize_i64(v.into())
127 }
128
129 #[inline]
130 fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
131 self.serialize_i64(
132 v.try_into()
133 .map_err(|_e| AnySerializeError::UnrepresentableInt)?,
134 )
135 }
136
137 #[inline]
138 fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
139 self.serialize_f64(v.into())
140 }
141
142 #[inline]
143 fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> {
144 Ok(Any::Number(v))
145 }
146
147 #[inline]
148 fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> {
149 self.serialize_str(&v.to_string())
150 }
151
152 #[inline]
153 fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
154 Ok(Any::String(v.into()))
155 }
156
157 #[inline]
158 fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> {
159 Ok(Any::Buffer(v.into()))
160 }
161
162 #[inline]
163 fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
164 self.serialize_unit()
165 }
166
167 #[inline]
168 fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
169 where
170 T: Serialize,
171 {
172 value.serialize(self)
173 }
174
175 #[inline]
176 fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
177 Ok(Any::Null)
178 }
179
180 #[inline]
181 fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
182 self.serialize_unit()
183 }
184
185 #[inline]
186 fn serialize_unit_variant(
187 self,
188 _name: &'static str,
189 _variant_index: u32,
190 variant: &'static str,
191 ) -> Result<Self::Ok, Self::Error> {
192 self.serialize_str(variant)
193 }
194
195 #[inline]
196 fn serialize_newtype_struct<T: ?Sized>(
197 self,
198 _name: &'static str,
199 value: &T,
200 ) -> Result<Self::Ok, Self::Error>
201 where
202 T: Serialize,
203 {
204 value.serialize(self)
205 }
206
207 #[inline]
208 fn serialize_newtype_variant<T: ?Sized>(
209 self,
210 _name: &'static str,
211 _variant_index: u32,
212 variant: &'static str,
213 value: &T,
214 ) -> Result<Self::Ok, Self::Error>
215 where
216 T: Serialize,
217 {
218 Ok(Any::from(HashMap::from([(
219 variant.to_string(),
220 value.serialize(AnySerializer)?,
221 )])))
222 }
223
224 #[inline]
225 fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
226 let array = if let Some(len) = len {
227 Vec::with_capacity(len)
228 } else {
229 Vec::new()
230 };
231 Ok(AnyArraySerializer { array })
232 }
233
234 #[inline]
235 fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
236 self.serialize_seq(Some(len))
237 }
238
239 #[inline]
240 fn serialize_tuple_struct(
241 self,
242 _name: &'static str,
243 len: usize,
244 ) -> Result<Self::SerializeTupleStruct, Self::Error> {
245 self.serialize_seq(Some(len))
246 }
247
248 #[inline]
249 fn serialize_tuple_variant(
250 self,
251 _name: &'static str,
252 _variant_index: u32,
253 variant: &'static str,
254 len: usize,
255 ) -> Result<Self::SerializeTupleVariant, Self::Error> {
256 Ok(AnyTupleVariantSerializer {
257 variant,
258 array_serializer: self.serialize_seq(Some(len))?,
259 })
260 }
261
262 #[inline]
263 fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
264 let map = if let Some(len) = len {
265 HashMap::with_capacity(len)
266 } else {
267 HashMap::new()
268 };
269
270 Ok(AnyMapSerializer {
271 map,
272 next_key: None,
273 })
274 }
275
276 #[inline]
277 fn serialize_struct(
278 self,
279 _name: &'static str,
280 len: usize,
281 ) -> Result<Self::SerializeStruct, Self::Error> {
282 self.serialize_map(Some(len))
283 }
284
285 #[inline]
286 fn serialize_struct_variant(
287 self,
288 _name: &'static str,
289 _variant_index: u32,
290 variant: &'static str,
291 len: usize,
292 ) -> Result<Self::SerializeStructVariant, Self::Error> {
293 Ok(AnyStructVariantSerializer {
294 variant,
295 map_serializer: self.serialize_map(Some(len))?,
296 })
297 }
298}
299
300struct AnyArraySerializer {
301 array: Vec<Any>,
302}
303
304impl SerializeSeq for AnyArraySerializer {
305 type Ok = Any;
306 type Error = AnySerializeError;
307
308 fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
309 where
310 T: Serialize,
311 {
312 self.array.push(value.serialize(AnySerializer)?);
313 Ok(())
314 }
315
316 fn end(self) -> Result<Self::Ok, Self::Error> {
317 Ok(Any::from(self.array))
318 }
319}
320
321impl SerializeTuple for AnyArraySerializer {
322 type Ok = Any;
323 type Error = AnySerializeError;
324
325 fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
326 where
327 T: Serialize,
328 {
329 serde::ser::SerializeSeq::serialize_element(self, value)
330 }
331
332 fn end(self) -> Result<Self::Ok, Self::Error> {
333 serde::ser::SerializeSeq::end(self)
334 }
335}
336
337impl SerializeTupleStruct for AnyArraySerializer {
338 type Ok = Any;
339 type Error = AnySerializeError;
340
341 fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
342 where
343 T: Serialize,
344 {
345 serde::ser::SerializeSeq::serialize_element(self, value)
346 }
347
348 fn end(self) -> Result<Self::Ok, Self::Error> {
349 serde::ser::SerializeSeq::end(self)
350 }
351}
352
353struct AnyMapSerializer {
354 map: HashMap<String, Any>,
355 next_key: Option<String>,
356}
357
358impl SerializeMap for AnyMapSerializer {
359 type Ok = Any;
360 type Error = AnySerializeError;
361
362 fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
363 where
364 T: Serialize,
365 {
366 self.next_key = Some(match key.serialize(AnySerializer)? {
367 Any::String(s) => s.to_string(),
368 _ => return Err(AnySerializeError::MapKeyNotString),
369 });
370 Ok(())
371 }
372
373 fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
374 where
375 T: Serialize,
376 {
377 let key = self.next_key.take();
378 let key = key.expect("serialize_value must not be called before serialize_key");
379 self.map.insert(key, value.serialize(AnySerializer)?);
380 Ok(())
381 }
382
383 fn end(self) -> Result<Self::Ok, Self::Error> {
384 Ok(self.map.into())
385 }
386}
387
388impl SerializeStruct for AnyMapSerializer {
389 type Ok = Any;
390 type Error = AnySerializeError;
391
392 fn serialize_field<T: ?Sized>(
393 &mut self,
394 key: &'static str,
395 value: &T,
396 ) -> Result<(), Self::Error>
397 where
398 T: Serialize,
399 {
400 self.map
401 .insert(key.to_string(), value.serialize(AnySerializer)?);
402 Ok(())
403 }
404
405 fn end(self) -> Result<Self::Ok, Self::Error> {
406 serde::ser::SerializeMap::end(self)
407 }
408}
409
410struct AnyTupleVariantSerializer {
411 variant: &'static str,
412 array_serializer: AnyArraySerializer,
413}
414
415impl SerializeTupleVariant for AnyTupleVariantSerializer {
416 type Ok = Any;
417 type Error = AnySerializeError;
418
419 fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
420 where
421 T: Serialize,
422 {
423 SerializeSeq::serialize_element(&mut self.array_serializer, value)
424 }
425
426 fn end(self) -> Result<Self::Ok, Self::Error> {
427 Ok(HashMap::from([(
428 self.variant.to_string(),
429 SerializeSeq::end(self.array_serializer)?,
430 )])
431 .into())
432 }
433}
434
435struct AnyStructVariantSerializer {
436 variant: &'static str,
437 map_serializer: AnyMapSerializer,
438}
439
440impl SerializeStructVariant for AnyStructVariantSerializer {
441 type Ok = Any;
442 type Error = AnySerializeError;
443
444 fn serialize_field<T: ?Sized>(
445 &mut self,
446 key: &'static str,
447 value: &T,
448 ) -> Result<(), Self::Error>
449 where
450 T: Serialize,
451 {
452 SerializeStruct::serialize_field(&mut self.map_serializer, key, value)
453 }
454
455 fn end(self) -> Result<Self::Ok, Self::Error> {
456 Ok(HashMap::from([(
457 self.variant.to_string(),
458 SerializeStruct::end(self.map_serializer)?,
459 )])
460 .into())
461 }
462}
463
464#[cfg(test)]
465mod test {
466 use super::*;
467 use crate::any::Any;
468 use serde::Serialize;
469 use serde_json::json;
470 use std::collections::HashMap;
471 use std::sync::Arc;
472
473 #[test]
474 fn test_serialize_any_to_bool() {
475 assert_eq!(serde_json::to_string(&Any::Bool(false)).unwrap(), "false");
476 }
477
478 #[test]
479 fn test_serialize_any_to_float() {
480 assert_eq!(
481 serde_json::to_string(&Any::Number(-1298.283f64)).unwrap(),
482 "-1298.283"
483 );
484 }
485
486 #[test]
487 fn test_serialize_any_to_int() {
488 assert_eq!(serde_json::to_string(&Any::BigInt(-1298)).unwrap(), "-1298");
489 }
490
491 #[test]
492 fn test_serialize_any_to_string() {
493 assert_eq!(
494 serde_json::to_string(&Any::String("string".into())).unwrap(),
495 "\"string\""
496 );
497 }
498
499 #[test]
500 fn test_serialize_any_to_null() {
501 assert_eq!(serde_json::to_string(&Any::Null).unwrap(), "null");
502 }
503
504 #[test]
505 fn test_serialize_any_to_undefined() {
506 assert_eq!(serde_json::to_string(&Any::Undefined).unwrap(), "null");
507 }
508
509 #[test]
510 fn test_serialize_any_to_buffer() {
511 assert_eq!(
512 serde_json::to_string(&Any::Buffer("buffer".as_bytes().into())).unwrap(),
513 "[98,117,102,102,101,114]"
514 );
515 }
516
517 #[test]
518 fn test_serialize_any_to_array() {
519 assert_eq!(
520 serde_json::to_string(&Any::from(vec![Any::from(true), Any::from(1)])).unwrap(),
521 "[true,1]"
522 );
523 }
524
525 #[test]
526 fn test_serialize_any_to_map() {
527 assert_eq!(
528 serde_json::to_value(&Any::from(HashMap::from([
529 ("key1".into(), Any::from(true)),
530 ("key2".into(), Any::from(1))
531 ])))
532 .unwrap(),
533 json!({"key1":true, "key2":1})
534 );
535 }
536
537 #[test]
538 fn test_serialize_any_to_complex_map() {
539 assert_eq!(
540 serde_json::to_value(&Any::from(HashMap::from([
541 ("key1".into(), Any::from(true)),
542 ("key2".into(), Any::from(1)),
543 (
544 "key3".into(),
545 Any::from(HashMap::from([
546 ("key4".into(), Any::from(true)),
547 ("key5".into(), Any::from(1))
548 ]))
549 ),
550 (
551 "key6".into(),
552 Any::from(vec![Any::from(true), Any::from(1)])
553 )
554 ])))
555 .unwrap(),
556 json!({"key1": true, "key2":1, "key3":{"key4":true, "key5":1}, "key6": [true,1]})
557 );
558 }
559
560 #[test]
561 fn test_any_serializer_many_fields() {
562 #[derive(Debug, Serialize, PartialEq)]
563 struct Test {
564 bool: bool,
565 int: i64,
566 negative_int: i64,
567 max_int: i64,
568 min_int: i64,
569 real_number: f64,
570 max_number: f64,
571 min_number: f64,
572 null: Option<bool>,
573 some: Option<bool>,
574 nested: Nested,
575 enum_a: StringEnum,
576 enum_b: StringEnum,
577 }
578
579 #[derive(Debug, Serialize, PartialEq)]
580 struct Nested {
581 int: i16,
582 other: f32,
583 }
584
585 #[derive(Debug, Serialize, PartialEq)]
586 enum StringEnum {
587 VariantA,
588 VariantB,
589 }
590
591 let any = Any::from(HashMap::from([
592 ("bool".to_string(), Any::from(true)),
593 ("int".to_string(), Any::from(1)),
594 ("negative_int".to_string(), Any::from(-1)),
595 ("max_int".to_string(), Any::from(i64::MAX)),
596 ("min_int".to_string(), Any::from(i64::MIN)),
597 ("real_number".to_string(), Any::from(-123.2387f64)),
598 ("max_number".to_string(), Any::from(f64::MIN)),
599 ("min_number".to_string(), Any::from(f64::MAX)),
600 ("null".to_string(), Any::Null),
601 ("some".to_string(), Any::from(false)),
602 (
603 "nested".to_string(),
604 Any::from(HashMap::from([
605 ("int".to_string(), Any::from(100)),
606 ("other".to_string(), Any::from(100.0)),
607 ])),
608 ),
609 ("enum_a".to_string(), "VariantA".into()),
610 ("enum_b".to_string(), "VariantB".into()),
611 ]));
612
613 assert_eq!(
614 any,
615 to_any(&Test {
616 bool: true,
617 int: 1,
618 negative_int: -1,
619 max_int: i64::MAX,
620 min_int: i64::MIN,
621 real_number: -123.2387f64,
622 max_number: f64::MIN,
623 min_number: f64::MAX,
624 null: None,
625 some: Some(false),
626 nested: Nested {
627 int: 100,
628 other: 100.0
629 },
630 enum_a: StringEnum::VariantA,
631 enum_b: StringEnum::VariantB
632 })
633 .unwrap(),
634 )
635 }
636
637 #[test]
638 fn test_any_serializer_nested_array() {
639 #[derive(Debug, Serialize, PartialEq)]
640 struct Test {
641 array: Vec<Test>,
642 }
643
644 let any: Any = HashMap::from([(
645 "array".to_string(),
646 Any::from(vec![
647 Any::from(HashMap::from([(
648 "array".to_string(),
649 Any::Array(Arc::<[Any; 0]>::default()),
650 )])),
651 Any::from(HashMap::from([(
652 "array".to_string(),
653 Any::Array(Arc::<[Any; 0]>::default()),
654 )])),
655 ]),
656 )])
657 .into();
658
659 assert_eq!(
660 any,
661 to_any(&Test {
662 array: vec![Test { array: vec![] }, Test { array: vec![] }]
663 },)
664 .unwrap(),
665 )
666 }
667
668 #[test]
669 fn test_any_serializer_newtype_u64_within_bounds() {
670 #[derive(Debug, Serialize, PartialEq)]
671 struct Test(u64);
672
673 assert_eq!(
674 to_any(&Test(i64::MAX as u64)).unwrap(),
675 Any::BigInt(i64::MAX)
676 )
677 }
678
679 #[test]
680 fn test_any_serializer_u64_error() {
681 #[derive(Debug, Serialize, PartialEq)]
682 struct Test(u64);
683
684 assert!(matches!(
685 to_any(&Test(u64::MAX)).unwrap_err(),
686 AnySerializeError::UnrepresentableInt
687 ))
688 }
689
690 #[test]
691 fn test_any_serializer_non_string_keys_error() {
692 #[derive(Debug, Serialize, PartialEq)]
693 struct Test(HashMap<u32, u32>);
694
695 assert!(matches!(
696 to_any(&Test(HashMap::from([(100, 1)]))).unwrap_err(),
697 AnySerializeError::MapKeyNotString
698 ))
699 }
700
701 #[test]
702 fn test_serialize_any_to_any() {
703 let any = Any::from(HashMap::from([
704 ("bool".to_string(), Any::from(true)),
705 ("int".to_string(), Any::from(1)),
706 ("negative_int".to_string(), Any::from(-1)),
707 ("max_int".to_string(), Any::from(i64::MAX)),
708 ("min_int".to_string(), Any::from(i64::MIN)),
709 ("real_number".to_string(), Any::from(-123.2387f64)),
710 ("max_number".to_string(), Any::from(f64::MIN)),
711 ("min_number".to_string(), Any::from(f64::MAX)),
712 ("null".to_string(), Any::Null),
713 ("some".to_string(), Any::from(false)),
714 (
715 "nested".to_string(),
716 Any::from(HashMap::from([
717 ("int".to_string(), Any::from(100)),
718 ("other".to_string(), Any::from(100.0)),
719 ])),
720 ),
721 ("enum_a".to_string(), "VariantA".into()),
722 ("enum_b".to_string(), "VariantB".into()),
723 ]));
724
725 assert_eq!(any, to_any(&any.clone()).unwrap())
726 }
727}
728