@@ -43,6 +43,12 @@ pub struct Options {
4343 /// [`null`]: crate::LuaSerdeExt::null
4444 /// [`Nil`]: crate::Value::Nil
4545 pub serialize_unit_to_null : bool ,
46+
47+ /// If true, serialize `serde_json::Number` with arbitrary_precision to a Lua number.
48+ /// Otherwise it will be serialized as an object (what serde does).
49+ ///
50+ /// Default: **false**
51+ pub detect_serde_json_arbitrary_precision : bool ,
4652}
4753
4854impl Default for Options {
@@ -58,6 +64,7 @@ impl Options {
5864 set_array_metatable : true ,
5965 serialize_none_to_null : true ,
6066 serialize_unit_to_null : true ,
67+ detect_serde_json_arbitrary_precision : false ,
6168 }
6269 }
6370
@@ -87,6 +94,20 @@ impl Options {
8794 self . serialize_unit_to_null = enabled;
8895 self
8996 }
97+
98+ /// Sets [`detect_serde_json_arbitrary_precision`] option.
99+ ///
100+ /// This option is used to serialize `serde_json::Number` with arbitrary precision to a Lua number.
101+ /// Otherwise it will be serialized as an object (what serde does).
102+ ///
103+ /// This option is disabled by default.
104+ ///
105+ /// [`detect_serde_json_arbitrary_precision`]: #structfield.detect_serde_json_arbitrary_precision
106+ #[ must_use]
107+ pub const fn detect_serde_json_arbitrary_precision ( mut self , enabled : bool ) -> Self {
108+ self . detect_serde_json_arbitrary_precision = enabled;
109+ self
110+ }
90111}
91112
92113impl < ' lua > Serializer < ' lua > {
@@ -121,7 +142,7 @@ impl<'lua> ser::Serializer for Serializer<'lua> {
121142 type SerializeTupleStruct = SerializeSeq < ' lua > ;
122143 type SerializeTupleVariant = SerializeTupleVariant < ' lua > ;
123144 type SerializeMap = SerializeMap < ' lua > ;
124- type SerializeStruct = SerializeMap < ' lua > ;
145+ type SerializeStruct = SerializeStruct < ' lua > ;
125146 type SerializeStructVariant = SerializeStructVariant < ' lua > ;
126147
127148 #[ inline]
@@ -282,8 +303,23 @@ impl<'lua> ser::Serializer for Serializer<'lua> {
282303 }
283304
284305 #[ inline]
285- fn serialize_struct ( self , _name : & ' static str , len : usize ) -> Result < Self :: SerializeStruct > {
286- self . serialize_map ( Some ( len) )
306+ fn serialize_struct ( self , name : & ' static str , len : usize ) -> Result < Self :: SerializeStruct > {
307+ if self . options . detect_serde_json_arbitrary_precision
308+ && name == "$serde_json::private::Number"
309+ && len == 1
310+ {
311+ return Ok ( SerializeStruct {
312+ lua : self . lua ,
313+ inner : None ,
314+ options : self . options ,
315+ } ) ;
316+ }
317+
318+ Ok ( SerializeStruct {
319+ lua : self . lua ,
320+ inner : Some ( Value :: Table ( self . lua . create_table_with_capacity ( 0 , len) ?) ) ,
321+ options : self . options ,
322+ } )
287323 }
288324
289325 #[ inline]
@@ -465,20 +501,53 @@ impl<'lua> ser::SerializeMap for SerializeMap<'lua> {
465501 }
466502}
467503
468- impl < ' lua > ser:: SerializeStruct for SerializeMap < ' lua > {
504+ #[ doc( hidden) ]
505+ pub struct SerializeStruct < ' lua > {
506+ lua : & ' lua Lua ,
507+ inner : Option < Value < ' lua > > ,
508+ options : Options ,
509+ }
510+
511+ impl < ' lua > ser:: SerializeStruct for SerializeStruct < ' lua > {
469512 type Ok = Value < ' lua > ;
470513 type Error = Error ;
471514
472515 fn serialize_field < T > ( & mut self , key : & ' static str , value : & T ) -> Result < ( ) >
473516 where
474517 T : Serialize + ?Sized ,
475518 {
476- ser:: SerializeMap :: serialize_key ( self , key) ?;
477- ser:: SerializeMap :: serialize_value ( self , value)
519+ match self . inner {
520+ Some ( Value :: Table ( ref table) ) => {
521+ table. raw_set ( key, self . lua . to_value_with ( value, self . options ) ?) ?;
522+ }
523+ None if self . options . detect_serde_json_arbitrary_precision => {
524+ // A special case for `serde_json::Number` with arbitrary precision.
525+ assert_eq ! ( key, "$serde_json::private::Number" ) ;
526+ self . inner = Some ( self . lua . to_value_with ( value, self . options ) ?) ;
527+ }
528+ _ => unreachable ! ( ) ,
529+ }
530+ Ok ( ( ) )
478531 }
479532
480533 fn end ( self ) -> Result < Value < ' lua > > {
481- ser:: SerializeMap :: end ( self )
534+ match self . inner {
535+ Some ( table @ Value :: Table ( _) ) => Ok ( table) ,
536+ Some ( value) if self . options . detect_serde_json_arbitrary_precision => {
537+ let number_s = value. as_str ( ) . expect ( "not an arbitrary precision number" ) ;
538+ if number_s. contains ( & [ '.' , 'e' , 'E' ] ) {
539+ if let Ok ( number) = number_s. parse ( ) . map ( Value :: Number ) {
540+ return Ok ( number) ;
541+ }
542+ }
543+ Ok ( number_s
544+ . parse ( )
545+ . map ( Value :: Integer )
546+ . or_else ( |_| number_s. parse ( ) . map ( Value :: Number ) )
547+ . unwrap_or_else ( |_| value) )
548+ }
549+ _ => unreachable ! ( ) ,
550+ }
482551 }
483552}
484553
@@ -505,7 +574,7 @@ impl<'lua> ser::SerializeStructVariant for SerializeStructVariant<'lua> {
505574
506575 fn end ( self ) -> Result < Value < ' lua > > {
507576 let lua = self . table . 0 . lua ;
508- let table = lua. create_table ( ) ?;
577+ let table = lua. create_table_with_capacity ( 0 , 1 ) ?;
509578 table. raw_set ( self . name , self . table ) ?;
510579 Ok ( Value :: Table ( table) )
511580 }
0 commit comments