Skip to main content

spo_rhai/serde/
ser.rs

1//! Implement serialization support of [`Dynamic`][crate::Dynamic] for [`serde`].
2
3use 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
15/// Serializer for [`Dynamic`][crate::Dynamic].
16pub struct DynamicSerializer {
17    /// Buffer to hold a temporary key.
18    _key: Identifier,
19    /// Buffer to hold a temporary value.
20    _value: Dynamic,
21}
22
23impl DynamicSerializer {
24    /// Create a [`DynamicSerializer`] from a [`Dynamic`][crate::Dynamic] value.
25    #[must_use]
26    pub const fn new(value: Dynamic) -> Self {
27        Self {
28            _key: Identifier::new_const(),
29            _value: value,
30        }
31    }
32}
33
34/// Serialize a Rust type that implements [`serde::Serialize`] into a [`Dynamic`][crate::Dynamic].
35///
36/// # Example
37///
38/// ```
39/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
40/// # #[cfg(not(feature = "no_index"))]
41/// # #[cfg(not(feature = "no_object"))]
42/// # #[cfg(not(feature = "no_float"))]
43/// # #[cfg(not(feature = "f32_float"))]
44/// # {
45/// use rhai::{Dynamic, Array, Map};
46/// use rhai::serde::to_dynamic;
47/// use serde::Serialize;
48///
49/// #[derive(Debug, serde::Serialize, PartialEq)]
50/// struct Point {
51///     x: f64,
52///     y: f64
53/// }
54///
55/// #[derive(Debug, serde::Serialize, PartialEq)]
56/// struct MyStruct {
57///     a: i64,
58///     b: Vec<String>,
59///     c: bool,
60///     d: Point
61/// }
62///
63/// let x = MyStruct {
64///     a: 42,
65///     b: vec![ "hello".into(), "world".into() ],
66///     c: true,
67///     d: Point { x: 123.456, y: 999.0 }
68/// };
69///
70/// // Convert the 'MyStruct' into a 'Dynamic'
71/// let value = to_dynamic(x)?;
72///
73/// assert!(value.is::<Map>());
74///
75/// let map = value.cast::<Map>();
76/// let point = map["d"].read_lock::<Map>().unwrap();
77/// assert_eq!(*point["x"].read_lock::<f64>().unwrap(), 123.456);
78/// assert_eq!(*point["y"].read_lock::<f64>().unwrap(), 999.0);
79/// # }
80/// # Ok(())
81/// # }
82/// ```
83pub 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    // Close the sequence.
481    #[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}