1use crate::{Dynamic, Identifier, Position, RhaiError, RhaiResult, RhaiResultOf, ERR, INT};
4use serde::ser::{
5 Error, SerializeMap, SerializeSeq, SerializeStruct, SerializeTuple, SerializeTupleStruct,
6};
7use serde::{Serialize, Serializer};
8use std::fmt;
9#[cfg(feature = "no_std")]
10use std::prelude::v1::*;
11
12#[cfg(feature = "decimal")]
13use num_traits::FromPrimitive;
14
15pub struct DynamicSerializer {
17 _key: Identifier,
19 _value: Dynamic,
21}
22
23impl DynamicSerializer {
24 #[must_use]
26 pub const fn new(value: Dynamic) -> Self {
27 Self {
28 _key: Identifier::new_const(),
29 _value: value,
30 }
31 }
32}
33
34pub fn to_dynamic<T: Serialize>(value: T) -> RhaiResult {
84 let mut s = DynamicSerializer::new(Dynamic::UNIT);
85 value.serialize(&mut s)
86}
87
88impl Error for RhaiError {
89 fn custom<T: fmt::Display>(err: T) -> Self {
90 ERR::ErrorRuntime(err.to_string().into(), Position::NONE).into()
91 }
92}
93
94impl Serializer for &mut DynamicSerializer {
95 type Ok = Dynamic;
96 type Error = RhaiError;
97 type SerializeSeq = DynamicSerializer;
98 type SerializeTuple = DynamicSerializer;
99 type SerializeTupleStruct = DynamicSerializer;
100 #[cfg(not(feature = "no_object"))]
101 #[cfg(not(feature = "no_index"))]
102 type SerializeTupleVariant = TupleVariantSerializer;
103 #[cfg(any(feature = "no_object", feature = "no_index"))]
104 type SerializeTupleVariant = serde::ser::Impossible<Dynamic, RhaiError>;
105 type SerializeMap = DynamicSerializer;
106 type SerializeStruct = DynamicSerializer;
107 #[cfg(not(feature = "no_object"))]
108 type SerializeStructVariant = StructVariantSerializer;
109 #[cfg(feature = "no_object")]
110 type SerializeStructVariant = serde::ser::Impossible<Dynamic, RhaiError>;
111
112 #[inline(always)]
113 fn serialize_bool(self, v: bool) -> RhaiResultOf<Self::Ok> {
114 Ok(v.into())
115 }
116
117 #[inline(always)]
118 fn serialize_i8(self, v: i8) -> RhaiResultOf<Self::Ok> {
119 Ok(INT::from(v).into())
120 }
121
122 #[inline(always)]
123 fn serialize_i16(self, v: i16) -> RhaiResultOf<Self::Ok> {
124 Ok(INT::from(v).into())
125 }
126
127 #[inline(always)]
128 fn serialize_i32(self, v: i32) -> RhaiResultOf<Self::Ok> {
129 Ok(INT::from(v).into())
130 }
131
132 #[inline]
133 fn serialize_i64(self, v: i64) -> RhaiResultOf<Self::Ok> {
134 #[cfg(not(feature = "only_i32"))]
135 return Ok(v.into());
136
137 #[cfg(feature = "only_i32")]
138 if v <= INT::MAX as i64 {
139 return Ok(Dynamic::from(v as INT));
140 }
141
142 #[allow(unreachable_code)]
143 {
144 #[cfg(feature = "decimal")]
145 if let Some(n) = rust_decimal::Decimal::from_i64(v) {
146 return Ok(Dynamic::from_decimal(n));
147 }
148
149 #[cfg(not(feature = "no_float"))]
150 return Ok(Dynamic::from_float(v as crate::FLOAT));
151
152 Err(Error::custom(format!("integer number too large: {v}")))
153 }
154 }
155
156 #[inline]
157 fn serialize_i128(self, v: i128) -> RhaiResultOf<Self::Ok> {
158 if v <= i128::from(INT::MAX) {
159 return Ok(Dynamic::from(v as INT));
160 }
161
162 #[allow(unreachable_code)]
163 {
164 #[cfg(feature = "decimal")]
165 if let Some(n) = rust_decimal::Decimal::from_i128(v) {
166 return Ok(Dynamic::from_decimal(n));
167 }
168
169 #[cfg(not(feature = "no_float"))]
170 return Ok(Dynamic::from_float(v as crate::FLOAT));
171
172 Err(Error::custom(format!("integer number too large: {v}")))
173 }
174 }
175
176 #[inline(always)]
177 fn serialize_u8(self, v: u8) -> RhaiResultOf<Self::Ok> {
178 Ok(INT::from(v).into())
179 }
180
181 #[inline(always)]
182 fn serialize_u16(self, v: u16) -> RhaiResultOf<Self::Ok> {
183 Ok(INT::from(v).into())
184 }
185
186 #[inline]
187 fn serialize_u32(self, v: u32) -> RhaiResultOf<Self::Ok> {
188 #[cfg(not(feature = "only_i32"))]
189 return Ok(Dynamic::from(v as INT));
190
191 #[cfg(feature = "only_i32")]
192 if v <= INT::MAX as u32 {
193 return Ok(Dynamic::from(v as INT));
194 }
195
196 #[allow(unreachable_code)]
197 {
198 #[cfg(feature = "decimal")]
199 if let Some(n) = rust_decimal::Decimal::from_u32(v) {
200 return Ok(Dynamic::from_decimal(n));
201 }
202
203 #[cfg(not(feature = "no_float"))]
204 return Ok(Dynamic::from_float(v as crate::FLOAT));
205
206 Err(Error::custom(format!("integer number too large: {v}")))
207 }
208 }
209
210 #[inline]
211 fn serialize_u64(self, v: u64) -> RhaiResultOf<Self::Ok> {
212 if v <= INT::MAX as u64 {
213 return Ok(Dynamic::from(v as INT));
214 }
215
216 #[cfg(feature = "decimal")]
217 if let Some(n) = rust_decimal::Decimal::from_u64(v) {
218 return Ok(Dynamic::from_decimal(n));
219 }
220
221 #[cfg(not(feature = "no_float"))]
222 return Ok(Dynamic::from_float(v as crate::FLOAT));
223
224 #[allow(unreachable_code)]
225 Err(Error::custom(format!("integer number too large: {v}")))
226 }
227
228 #[inline]
229 fn serialize_u128(self, v: u128) -> RhaiResultOf<Self::Ok> {
230 if v <= INT::MAX as u128 {
231 return Ok(Dynamic::from(v as INT));
232 }
233
234 #[cfg(feature = "decimal")]
235 if let Some(n) = rust_decimal::Decimal::from_u128(v) {
236 return Ok(Dynamic::from_decimal(n));
237 }
238
239 #[cfg(not(feature = "no_float"))]
240 return Ok(Dynamic::from_float(v as crate::FLOAT));
241
242 #[allow(unreachable_code)]
243 Err(Error::custom(format!("integer number too large: {v}")))
244 }
245
246 #[inline(always)]
247 fn serialize_f32(self, v: f32) -> RhaiResultOf<Self::Ok> {
248 #[cfg(not(feature = "no_float"))]
249 return Ok((v as crate::FLOAT).into());
250
251 #[allow(unreachable_code)]
252 {
253 #[cfg(feature = "decimal")]
254 if let Some(n) = rust_decimal::Decimal::from_f32(v) {
255 return Ok(Dynamic::from_decimal(n));
256 }
257
258 Err(Error::custom(format!(
259 "floating-point number is not supported: {v}"
260 )))
261 }
262 }
263
264 #[inline(always)]
265 fn serialize_f64(self, v: f64) -> RhaiResultOf<Self::Ok> {
266 #[cfg(not(feature = "no_float"))]
267 return Ok((v as crate::FLOAT).into());
268
269 #[allow(unreachable_code)]
270 {
271 #[cfg(feature = "decimal")]
272 if let Some(n) = rust_decimal::Decimal::from_f64(v) {
273 return Ok(Dynamic::from_decimal(n));
274 }
275
276 Err(Error::custom(format!(
277 "floating-point number is not supported: {v}"
278 )))
279 }
280 }
281
282 #[inline(always)]
283 fn serialize_char(self, v: char) -> RhaiResultOf<Self::Ok> {
284 Ok(v.into())
285 }
286
287 #[inline(always)]
288 fn serialize_str(self, v: &str) -> RhaiResultOf<Self::Ok> {
289 Ok(v.into())
290 }
291
292 #[inline]
293 fn serialize_bytes(self, _v: &[u8]) -> RhaiResultOf<Self::Ok> {
294 #[cfg(not(feature = "no_index"))]
295 return Ok(Dynamic::from_blob(_v.to_vec()));
296
297 #[cfg(feature = "no_index")]
298 return Err(ERR::ErrorMismatchDataType(
299 "".into(),
300 "BLOB's are not supported under 'no_index'".into(),
301 Position::NONE,
302 )
303 .into());
304 }
305
306 #[inline(always)]
307 fn serialize_none(self) -> RhaiResultOf<Self::Ok> {
308 Ok(Dynamic::UNIT)
309 }
310
311 #[inline(always)]
312 fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> RhaiResultOf<Self::Ok> {
313 value.serialize(&mut *self)
314 }
315
316 #[inline(always)]
317 fn serialize_unit(self) -> RhaiResultOf<Self::Ok> {
318 Ok(Dynamic::UNIT)
319 }
320
321 #[inline(always)]
322 fn serialize_unit_struct(self, _name: &'static str) -> RhaiResultOf<Self::Ok> {
323 self.serialize_unit()
324 }
325
326 #[inline(always)]
327 fn serialize_unit_variant(
328 self,
329 _name: &'static str,
330 _variant_index: u32,
331 variant: &'static str,
332 ) -> RhaiResultOf<Self::Ok> {
333 self.serialize_str(variant)
334 }
335
336 #[inline(always)]
337 fn serialize_newtype_struct<T: ?Sized + Serialize>(
338 self,
339 _name: &'static str,
340 value: &T,
341 ) -> RhaiResultOf<Self::Ok> {
342 value.serialize(&mut *self)
343 }
344
345 #[inline]
346 fn serialize_newtype_variant<T: ?Sized + Serialize>(
347 self,
348 _name: &'static str,
349 _variant_index: u32,
350 _variant: &'static str,
351 _value: &T,
352 ) -> RhaiResultOf<Self::Ok> {
353 #[cfg(not(feature = "no_object"))]
354 return Ok(make_variant(_variant, to_dynamic(_value)?));
355 #[cfg(feature = "no_object")]
356 return Err(ERR::ErrorMismatchDataType(
357 "".into(),
358 "object maps are not supported under 'no_object'".into(),
359 Position::NONE,
360 )
361 .into());
362 }
363
364 #[inline]
365 fn serialize_seq(self, _len: Option<usize>) -> RhaiResultOf<Self::SerializeSeq> {
366 #[cfg(not(feature = "no_index"))]
367 return Ok(DynamicSerializer::new(crate::Array::new().into()));
368 #[cfg(feature = "no_index")]
369 return Err(ERR::ErrorMismatchDataType(
370 "".into(),
371 "arrays are not supported under 'no_index'".into(),
372 Position::NONE,
373 )
374 .into());
375 }
376
377 #[inline(always)]
378 fn serialize_tuple(self, len: usize) -> RhaiResultOf<Self::SerializeTuple> {
379 self.serialize_seq(Some(len))
380 }
381
382 #[inline(always)]
383 fn serialize_tuple_struct(
384 self,
385 _name: &'static str,
386 len: usize,
387 ) -> RhaiResultOf<Self::SerializeTupleStruct> {
388 self.serialize_seq(Some(len))
389 }
390
391 #[inline]
392 fn serialize_tuple_variant(
393 self,
394 _name: &'static str,
395 _variant_index: u32,
396 _variant: &'static str,
397 _len: usize,
398 ) -> RhaiResultOf<Self::SerializeTupleVariant> {
399 #[cfg(not(feature = "no_object"))]
400 #[cfg(not(feature = "no_index"))]
401 return Ok(TupleVariantSerializer {
402 variant: _variant,
403 array: crate::Array::with_capacity(_len),
404 });
405 #[cfg(any(feature = "no_object", feature = "no_index"))]
406 return Err(ERR::ErrorMismatchDataType(
407 "".into(),
408 "tuples are not supported under 'no_index' or 'no_object'".into(),
409 Position::NONE,
410 )
411 .into());
412 }
413
414 #[inline]
415 fn serialize_map(self, _len: Option<usize>) -> RhaiResultOf<Self::SerializeMap> {
416 #[cfg(not(feature = "no_object"))]
417 return Ok(DynamicSerializer::new(crate::Map::new().into()));
418 #[cfg(feature = "no_object")]
419 return Err(ERR::ErrorMismatchDataType(
420 "".into(),
421 "object maps are not supported under 'no_object'".into(),
422 Position::NONE,
423 )
424 .into());
425 }
426
427 #[inline(always)]
428 fn serialize_struct(
429 self,
430 _name: &'static str,
431 len: usize,
432 ) -> RhaiResultOf<Self::SerializeStruct> {
433 self.serialize_map(Some(len))
434 }
435
436 #[inline]
437 fn serialize_struct_variant(
438 self,
439 _name: &'static str,
440 _variant_index: u32,
441 _variant: &'static str,
442 _len: usize,
443 ) -> RhaiResultOf<Self::SerializeStructVariant> {
444 #[cfg(not(feature = "no_object"))]
445 return Ok(StructVariantSerializer {
446 variant: _variant,
447 map: crate::Map::new(),
448 });
449 #[cfg(feature = "no_object")]
450 return Err(ERR::ErrorMismatchDataType(
451 "".into(),
452 "object maps are not supported under 'no_object'".into(),
453 Position::NONE,
454 )
455 .into());
456 }
457}
458
459impl SerializeSeq for DynamicSerializer {
460 type Ok = Dynamic;
461 type Error = RhaiError;
462
463 fn serialize_element<T: ?Sized + Serialize>(&mut self, _value: &T) -> RhaiResultOf<()> {
464 #[cfg(not(feature = "no_index"))]
465 {
466 let value = _value.serialize(&mut *self)?;
467 let arr = self._value.downcast_mut::<crate::Array>().unwrap();
468 arr.push(value);
469 Ok(())
470 }
471 #[cfg(feature = "no_index")]
472 return Err(ERR::ErrorMismatchDataType(
473 "".into(),
474 "arrays are not supported under 'no_index'".into(),
475 Position::NONE,
476 )
477 .into());
478 }
479
480 #[inline]
482 fn end(self) -> RhaiResultOf<Self::Ok> {
483 #[cfg(not(feature = "no_index"))]
484 return Ok(self._value);
485 #[cfg(feature = "no_index")]
486 return Err(ERR::ErrorMismatchDataType(
487 "".into(),
488 "arrays are not supported under 'no_index'".into(),
489 Position::NONE,
490 )
491 .into());
492 }
493}
494
495impl SerializeTuple for DynamicSerializer {
496 type Ok = Dynamic;
497 type Error = RhaiError;
498
499 fn serialize_element<T: ?Sized + Serialize>(&mut self, _value: &T) -> RhaiResultOf<()> {
500 #[cfg(not(feature = "no_index"))]
501 {
502 let value = _value.serialize(&mut *self)?;
503 let arr = self._value.downcast_mut::<crate::Array>().unwrap();
504 arr.push(value);
505 Ok(())
506 }
507 #[cfg(feature = "no_index")]
508 return Err(ERR::ErrorMismatchDataType(
509 "".into(),
510 "tuples are not supported under 'no_index'".into(),
511 Position::NONE,
512 )
513 .into());
514 }
515
516 #[inline]
517 fn end(self) -> RhaiResultOf<Self::Ok> {
518 #[cfg(not(feature = "no_index"))]
519 return Ok(self._value);
520 #[cfg(feature = "no_index")]
521 return Err(ERR::ErrorMismatchDataType(
522 "".into(),
523 "tuples are not supported under 'no_index'".into(),
524 Position::NONE,
525 )
526 .into());
527 }
528}
529
530impl SerializeTupleStruct for DynamicSerializer {
531 type Ok = Dynamic;
532 type Error = RhaiError;
533
534 fn serialize_field<T: ?Sized + Serialize>(&mut self, _value: &T) -> RhaiResultOf<()> {
535 #[cfg(not(feature = "no_index"))]
536 {
537 let value = _value.serialize(&mut *self)?;
538 let arr = self._value.downcast_mut::<crate::Array>().unwrap();
539 arr.push(value);
540 Ok(())
541 }
542 #[cfg(feature = "no_index")]
543 return Err(ERR::ErrorMismatchDataType(
544 "".into(),
545 "tuples are not supported under 'no_index'".into(),
546 Position::NONE,
547 )
548 .into());
549 }
550
551 #[inline]
552 fn end(self) -> RhaiResultOf<Self::Ok> {
553 #[cfg(not(feature = "no_index"))]
554 return Ok(self._value);
555 #[cfg(feature = "no_index")]
556 return Err(ERR::ErrorMismatchDataType(
557 "".into(),
558 "tuples are not supported under 'no_index'".into(),
559 Position::NONE,
560 )
561 .into());
562 }
563}
564
565impl SerializeMap for DynamicSerializer {
566 type Ok = Dynamic;
567 type Error = RhaiError;
568
569 fn serialize_key<T: ?Sized + Serialize>(&mut self, _key: &T) -> RhaiResultOf<()> {
570 #[cfg(not(feature = "no_object"))]
571 {
572 let key = _key.serialize(&mut *self)?;
573 self._key = key
574 .into_immutable_string()
575 .map_err(|typ| {
576 ERR::ErrorMismatchDataType("string".into(), typ.into(), Position::NONE)
577 })?
578 .into();
579 Ok(())
580 }
581 #[cfg(feature = "no_object")]
582 return Err(ERR::ErrorMismatchDataType(
583 "".into(),
584 "object maps are not supported under 'no_object'".into(),
585 Position::NONE,
586 )
587 .into());
588 }
589
590 fn serialize_value<T: ?Sized + Serialize>(&mut self, _value: &T) -> RhaiResultOf<()> {
591 #[cfg(not(feature = "no_object"))]
592 {
593 let key = std::mem::take(&mut self._key);
594 let value = _value.serialize(&mut *self)?;
595 let map = self._value.downcast_mut::<crate::Map>().unwrap();
596 map.insert(key, value);
597 Ok(())
598 }
599 #[cfg(feature = "no_object")]
600 return Err(ERR::ErrorMismatchDataType(
601 "".into(),
602 "object maps are not supported under 'no_object'".into(),
603 Position::NONE,
604 )
605 .into());
606 }
607
608 fn serialize_entry<K: ?Sized + Serialize, T: ?Sized + Serialize>(
609 &mut self,
610 _key: &K,
611 _value: &T,
612 ) -> RhaiResultOf<()> {
613 #[cfg(not(feature = "no_object"))]
614 {
615 let key: Dynamic = _key.serialize(&mut *self)?;
616 let key = key.into_immutable_string().map_err(|typ| {
617 ERR::ErrorMismatchDataType("string".into(), typ.into(), Position::NONE)
618 })?;
619 let value = _value.serialize(&mut *self)?;
620 let map = self._value.downcast_mut::<crate::Map>().unwrap();
621 map.insert(key.into(), value);
622 Ok(())
623 }
624 #[cfg(feature = "no_object")]
625 return Err(ERR::ErrorMismatchDataType(
626 "".into(),
627 "object maps are not supported under 'no_object'".into(),
628 Position::NONE,
629 )
630 .into());
631 }
632
633 #[inline]
634 fn end(self) -> RhaiResultOf<Self::Ok> {
635 #[cfg(not(feature = "no_object"))]
636 return Ok(self._value);
637 #[cfg(feature = "no_object")]
638 return Err(ERR::ErrorMismatchDataType(
639 "".into(),
640 "object maps are not supported under 'no_object'".into(),
641 Position::NONE,
642 )
643 .into());
644 }
645}
646
647impl SerializeStruct for DynamicSerializer {
648 type Ok = Dynamic;
649 type Error = RhaiError;
650
651 fn serialize_field<T: ?Sized + Serialize>(
652 &mut self,
653 _key: &'static str,
654 _value: &T,
655 ) -> RhaiResultOf<()> {
656 #[cfg(not(feature = "no_object"))]
657 {
658 let value = _value.serialize(&mut *self)?;
659 let map = self._value.downcast_mut::<crate::Map>().unwrap();
660 map.insert(_key.into(), value);
661 Ok(())
662 }
663 #[cfg(feature = "no_object")]
664 return Err(ERR::ErrorMismatchDataType(
665 "".into(),
666 "object maps are not supported under 'no_object'".into(),
667 Position::NONE,
668 )
669 .into());
670 }
671
672 #[inline]
673 fn end(self) -> RhaiResultOf<Self::Ok> {
674 #[cfg(not(feature = "no_object"))]
675 return Ok(self._value);
676 #[cfg(feature = "no_object")]
677 return Err(ERR::ErrorMismatchDataType(
678 "".into(),
679 "object maps are not supported under 'no_object'".into(),
680 Position::NONE,
681 )
682 .into());
683 }
684}
685
686#[cfg(not(feature = "no_object"))]
687#[cfg(not(feature = "no_index"))]
688pub struct TupleVariantSerializer {
689 variant: &'static str,
690 array: crate::Array,
691}
692
693#[cfg(not(feature = "no_object"))]
694#[cfg(not(feature = "no_index"))]
695impl serde::ser::SerializeTupleVariant for TupleVariantSerializer {
696 type Ok = Dynamic;
697 type Error = RhaiError;
698
699 fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> RhaiResultOf<()> {
700 let value = to_dynamic(value)?;
701 self.array.push(value);
702 Ok(())
703 }
704
705 #[inline]
706 fn end(self) -> RhaiResultOf<Self::Ok> {
707 Ok(make_variant(self.variant, self.array.into()))
708 }
709}
710
711#[cfg(not(feature = "no_object"))]
712pub struct StructVariantSerializer {
713 variant: &'static str,
714 map: crate::Map,
715}
716
717#[cfg(not(feature = "no_object"))]
718impl serde::ser::SerializeStructVariant for StructVariantSerializer {
719 type Ok = Dynamic;
720 type Error = RhaiError;
721
722 #[inline]
723 fn serialize_field<T: ?Sized + Serialize>(
724 &mut self,
725 key: &'static str,
726 value: &T,
727 ) -> RhaiResultOf<()> {
728 let value = to_dynamic(value)?;
729 self.map.insert(key.into(), value);
730 Ok(())
731 }
732
733 #[inline]
734 fn end(self) -> RhaiResultOf<Self::Ok> {
735 Ok(make_variant(self.variant, self.map.into()))
736 }
737}
738
739#[cfg(not(feature = "no_object"))]
740#[inline]
741fn make_variant(variant: &'static str, value: Dynamic) -> Dynamic {
742 let mut map = crate::Map::new();
743 map.insert(variant.into(), value);
744 map.into()
745}