@@ -43,6 +43,12 @@ pub struct Options {
43
43
/// [`null`]: crate::LuaSerdeExt::null
44
44
/// [`Nil`]: crate::Value::Nil
45
45
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 ,
46
52
}
47
53
48
54
impl Default for Options {
@@ -58,6 +64,7 @@ impl Options {
58
64
set_array_metatable : true ,
59
65
serialize_none_to_null : true ,
60
66
serialize_unit_to_null : true ,
67
+ detect_serde_json_arbitrary_precision : false ,
61
68
}
62
69
}
63
70
@@ -87,6 +94,20 @@ impl Options {
87
94
self . serialize_unit_to_null = enabled;
88
95
self
89
96
}
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
+ }
90
111
}
91
112
92
113
impl < ' lua > Serializer < ' lua > {
@@ -121,7 +142,7 @@ impl<'lua> ser::Serializer for Serializer<'lua> {
121
142
type SerializeTupleStruct = SerializeSeq < ' lua > ;
122
143
type SerializeTupleVariant = SerializeTupleVariant < ' lua > ;
123
144
type SerializeMap = SerializeMap < ' lua > ;
124
- type SerializeStruct = SerializeMap < ' lua > ;
145
+ type SerializeStruct = SerializeStruct < ' lua > ;
125
146
type SerializeStructVariant = SerializeStructVariant < ' lua > ;
126
147
127
148
#[ inline]
@@ -282,8 +303,23 @@ impl<'lua> ser::Serializer for Serializer<'lua> {
282
303
}
283
304
284
305
#[ 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
+ } )
287
323
}
288
324
289
325
#[ inline]
@@ -465,20 +501,53 @@ impl<'lua> ser::SerializeMap for SerializeMap<'lua> {
465
501
}
466
502
}
467
503
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 > {
469
512
type Ok = Value < ' lua > ;
470
513
type Error = Error ;
471
514
472
515
fn serialize_field < T > ( & mut self , key : & ' static str , value : & T ) -> Result < ( ) >
473
516
where
474
517
T : Serialize + ?Sized ,
475
518
{
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 ( ( ) )
478
531
}
479
532
480
533
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
+ }
482
551
}
483
552
}
484
553
@@ -505,7 +574,7 @@ impl<'lua> ser::SerializeStructVariant for SerializeStructVariant<'lua> {
505
574
506
575
fn end ( self ) -> Result < Value < ' lua > > {
507
576
let lua = self . table . 0 . lua ;
508
- let table = lua. create_table ( ) ?;
577
+ let table = lua. create_table_with_capacity ( 0 , 1 ) ?;
509
578
table. raw_set ( self . name , self . table ) ?;
510
579
Ok ( Value :: Table ( table) )
511
580
}
0 commit comments