1
1
use std:: fmt:: Display ;
2
+ use std:: fmt:: Write as _;
2
3
3
4
use serde:: ser;
4
5
@@ -8,79 +9,73 @@ use crate::Config;
8
9
9
10
#[ derive( Default , Debug ) ]
10
11
pub struct ConfigSerializer {
11
- keys : Vec < ( String , Option < usize > ) > ,
12
+ keys : Vec < SerKey > ,
12
13
pub output : Config ,
13
14
}
14
15
16
+ #[ derive( Debug ) ]
17
+ enum SerKey {
18
+ Named ( String ) ,
19
+ Seq ( usize ) ,
20
+ }
21
+
22
+ /// Serializer for numbered sequences
23
+ ///
24
+ /// This wrapper is present when we are outputting a sequence (numbered indices).
25
+ /// Making this a separate type centralises the handling of sequences
26
+ /// and ensures we don't have any call sites for `ser::SerializeSeq::serialize_element`
27
+ /// that don't do the necessary work of `SeqSerializer::new`.
28
+ ///
29
+ /// Existence of this wrapper implies that `.0.keys.last()` is
30
+ /// `Some(SerKey::Seq(next_index))`.
15
31
pub struct SeqSerializer < ' a > ( & ' a mut ConfigSerializer ) ;
16
32
17
33
impl ConfigSerializer {
18
34
fn serialize_primitive < T > ( & mut self , value : T ) -> Result < ( ) >
19
35
where
20
36
T : Into < Value > + Display ,
21
37
{
22
- let key = match self . last_key_index_pair ( ) {
23
- Some ( ( key, Some ( index) ) ) => format ! ( "{}[{}]" , key, index) ,
24
- Some ( ( key, None ) ) => key. to_string ( ) ,
25
- None => {
26
- return Err ( ConfigError :: Message ( format ! (
27
- "key is not found for value {}" ,
28
- value
29
- ) ) )
30
- }
31
- } ;
38
+ // At some future point we could perhaps retain a cursor into the output `Config`,
39
+ // rather than reifying the whole thing into a single string with `make_full_key`
40
+ // and passing that whole path to the `set` method.
41
+ //
42
+ // That would be marginally more performant, but more fiddly.
43
+ let key = self . make_full_key ( ) ?;
32
44
33
45
#[ allow( deprecated) ]
34
46
self . output . set ( & key, value. into ( ) ) ?;
35
47
Ok ( ( ) )
36
48
}
37
49
38
- fn last_key_index_pair ( & self ) -> Option < ( & str , Option < usize > ) > {
39
- let len = self . keys . len ( ) ;
40
- if len > 0 {
41
- self . keys
42
- . get ( len - 1 )
43
- . map ( |& ( ref key, opt) | ( key. as_str ( ) , opt) )
44
- } else {
45
- None
46
- }
47
- }
50
+ fn make_full_key ( & self ) -> Result < String > {
51
+ let mut keys = self . keys . iter ( ) ;
48
52
49
- fn inc_last_key_index ( & mut self ) -> Result < ( ) > {
50
- let len = self . keys . len ( ) ;
51
- if len > 0 {
52
- self . keys
53
- . get_mut ( len - 1 )
54
- . map ( |pair| pair. 1 = pair. 1 . map ( |i| i + 1 ) . or ( Some ( 0 ) ) )
55
- . ok_or_else ( || {
56
- ConfigError :: Message ( format ! ( "last key is not found in {} keys" , len) )
57
- } )
58
- } else {
59
- Err ( ConfigError :: Message ( "keys is empty" . to_string ( ) ) )
60
- }
61
- }
53
+ let mut whole = match keys. next ( ) {
54
+ Some ( SerKey :: Named ( s) ) => s. clone ( ) ,
55
+ _ => {
56
+ return Err ( ConfigError :: Message (
57
+ "top level is not a struct" . to_string ( ) ,
58
+ ) )
59
+ }
60
+ } ;
62
61
63
- fn make_full_key ( & self , key : & str ) -> String {
64
- let len = self . keys . len ( ) ;
65
- if len > 0 {
66
- if let Some ( & ( ref prev_key, index) ) = self . keys . get ( len - 1 ) {
67
- return if let Some ( index) = index {
68
- format ! ( "{}[{}].{}" , prev_key, index, key)
69
- } else {
70
- format ! ( "{}.{}" , prev_key, key)
71
- } ;
62
+ for k in keys {
63
+ match k {
64
+ SerKey :: Named ( s) => write ! ( whole, ".{}" , s) ,
65
+ SerKey :: Seq ( i) => write ! ( whole, "[{}]" , i) ,
72
66
}
67
+ . expect ( "write! to a string failed" ) ;
73
68
}
74
- key. to_string ( )
69
+
70
+ Ok ( whole)
75
71
}
76
72
77
73
fn push_key ( & mut self , key : & str ) {
78
- let full_key = self . make_full_key ( key) ;
79
- self . keys . push ( ( full_key, None ) ) ;
74
+ self . keys . push ( SerKey :: Named ( key. to_string ( ) ) ) ;
80
75
}
81
76
82
- fn pop_key ( & mut self ) -> Option < ( String , Option < usize > ) > {
83
- self . keys . pop ( )
77
+ fn pop_key ( & mut self ) {
78
+ self . keys . pop ( ) ;
84
79
}
85
80
}
86
81
@@ -265,10 +260,14 @@ impl<'a> ser::Serializer for &'a mut ConfigSerializer {
265
260
266
261
impl < ' a > SeqSerializer < ' a > {
267
262
fn new ( inner : & ' a mut ConfigSerializer ) -> Result < Self > {
263
+ inner. keys . push ( SerKey :: Seq ( 0 ) ) ;
264
+
268
265
Ok ( SeqSerializer ( inner) )
269
266
}
270
267
271
268
fn end ( self ) -> & ' a mut ConfigSerializer {
269
+ // This ought to be Some(SerKey::Seq(..)) but we don't want to panic if we are buggy
270
+ let _: Option < SerKey > = self . 0 . keys . pop ( ) ;
272
271
self . 0
273
272
}
274
273
}
@@ -281,8 +280,15 @@ impl<'a> ser::SerializeSeq for SeqSerializer<'a> {
281
280
where
282
281
T : ?Sized + ser:: Serialize ,
283
282
{
284
- self . 0 . inc_last_key_index ( ) ?;
285
283
value. serialize ( & mut * ( self . 0 ) ) ?;
284
+ match self . 0 . keys . last_mut ( ) {
285
+ Some ( SerKey :: Seq ( i) ) => * i += 1 ,
286
+ _ => {
287
+ return Err ( ConfigError :: Message (
288
+ "config-rs internal error (ser._element but last not Seq!" . to_string ( ) ,
289
+ ) )
290
+ }
291
+ } ;
286
292
Ok ( ( ) )
287
293
}
288
294
0 commit comments