Skip to main content

typeshare_engine/serde/
args.rs

1use std::{
2    collections::HashMap,
3    fmt::{self, Display, Write},
4};
5
6use serde::ser;
7
8#[derive(Debug, Clone, Copy)]
9pub enum ArgType {
10    Bool,
11    Value,
12}
13
14/// Support type for automatic CLI argument generation. A CliArgSet is a
15/// description of the fields for a given config type, but only the fields
16/// that can be effectively loaded from the command like (boolean flags and
17/// string or integer options)
18#[derive(Debug, Clone)]
19pub struct CliArgsSet {
20    // Mapping for the fields. The keys of this type are the field name itself,
21    // such as `prefix`, and the value includes both information about the
22    // field's type and the argument that will be used on the command line,
23    // such as `swift-prefix`. Pre-computing these strings makes it easier
24    // to reuse them for building a clap parser and for deserialize operations.
25    args: HashMap<&'static str, (String, ArgType)>,
26}
27
28impl CliArgsSet {
29    pub fn iter(&self) -> impl Iterator<Item = ArgSpec<'_>> + '_ {
30        self.args
31            .iter()
32            .map(|(&key, &(ref full_key, arg_type))| ArgSpec {
33                key,
34                full_key: full_key.as_str(),
35                arg_type,
36            })
37    }
38
39    pub fn contains_key(&self, key: &str) -> bool {
40        self.args.contains_key(key)
41    }
42}
43
44pub struct ArgSpec<'a> {
45    /// The ID for this argument; this is (what serde thinks is) the field name
46    /// in the config; eg, `package_name`
47    pub key: &'static str,
48
49    /// The full key as given to clap, including the language prefix and an
50    /// underscore to hyphen conversion; eg, `kotlin-package-name`
51    pub full_key: &'a str,
52
53    /// The type of argument we think this is, which affects how we configure
54    /// the clap parser and how we look up this argument from the parsed cli
55    /// arguments
56    pub arg_type: ArgType,
57}
58
59#[derive(thiserror::Error, Debug, Clone)]
60#[error("config container must be a struct type")]
61pub struct ArgsSetError;
62
63impl ser::Error for ArgsSetError {
64    fn custom<T>(_msg: T) -> Self
65    where
66        T: std::fmt::Display,
67    {
68        Self
69    }
70}
71
72/// Serializer that constructs a new `CliArgsSet`. It does this by serializing
73/// a config object to learn about its fields' names and their types.
74pub struct ArgsSetSerializer {
75    language: &'static str,
76    args: CliArgsSet,
77}
78
79impl ArgsSetSerializer {
80    pub fn new(language: &'static str) -> Self {
81        Self {
82            language,
83            args: CliArgsSet {
84                args: HashMap::new(),
85            },
86        }
87    }
88}
89
90impl ser::Serializer for ArgsSetSerializer {
91    type Ok = CliArgsSet;
92    type Error = ArgsSetError;
93
94    type SerializeSeq = ser::Impossible<Self::Ok, Self::Error>;
95    type SerializeTuple = ser::Impossible<Self::Ok, Self::Error>;
96    type SerializeTupleStruct = ser::Impossible<Self::Ok, Self::Error>;
97    type SerializeTupleVariant = ser::Impossible<Self::Ok, Self::Error>;
98    type SerializeStructVariant = ser::Impossible<Self::Ok, Self::Error>;
99    type SerializeMap = ser::Impossible<Self::Ok, Self::Error>;
100
101    type SerializeStruct = Self;
102
103    fn serialize_bool(self, _v: bool) -> Result<Self::Ok, Self::Error> {
104        Err(ArgsSetError)
105    }
106
107    fn serialize_i8(self, _v: i8) -> Result<Self::Ok, Self::Error> {
108        Err(ArgsSetError)
109    }
110
111    fn serialize_i16(self, _v: i16) -> Result<Self::Ok, Self::Error> {
112        Err(ArgsSetError)
113    }
114
115    fn serialize_i32(self, _v: i32) -> Result<Self::Ok, Self::Error> {
116        Err(ArgsSetError)
117    }
118
119    fn serialize_i64(self, _v: i64) -> Result<Self::Ok, Self::Error> {
120        Err(ArgsSetError)
121    }
122
123    fn serialize_u8(self, _v: u8) -> Result<Self::Ok, Self::Error> {
124        Err(ArgsSetError)
125    }
126
127    fn serialize_u16(self, _v: u16) -> Result<Self::Ok, Self::Error> {
128        Err(ArgsSetError)
129    }
130
131    fn serialize_u32(self, _v: u32) -> Result<Self::Ok, Self::Error> {
132        Err(ArgsSetError)
133    }
134
135    fn serialize_u64(self, _v: u64) -> Result<Self::Ok, Self::Error> {
136        Err(ArgsSetError)
137    }
138
139    fn serialize_f32(self, _v: f32) -> Result<Self::Ok, Self::Error> {
140        Err(ArgsSetError)
141    }
142
143    fn serialize_f64(self, _v: f64) -> Result<Self::Ok, Self::Error> {
144        Err(ArgsSetError)
145    }
146
147    fn serialize_char(self, _v: char) -> Result<Self::Ok, Self::Error> {
148        Err(ArgsSetError)
149    }
150
151    fn serialize_str(self, _v: &str) -> Result<Self::Ok, Self::Error> {
152        Err(ArgsSetError)
153    }
154
155    fn serialize_bytes(self, _v: &[u8]) -> Result<Self::Ok, Self::Error> {
156        Err(ArgsSetError)
157    }
158
159    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
160        Err(ArgsSetError)
161    }
162
163    fn serialize_some<T>(self, _value: &T) -> Result<Self::Ok, Self::Error>
164    where
165        T: ?Sized + ser::Serialize,
166    {
167        Err(ArgsSetError)
168    }
169
170    fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
171        Err(ArgsSetError)
172    }
173
174    fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
175        Err(ArgsSetError)
176    }
177
178    fn serialize_unit_variant(
179        self,
180        _name: &'static str,
181        _variant_index: u32,
182        _variant: &'static str,
183    ) -> Result<Self::Ok, Self::Error> {
184        Err(ArgsSetError)
185    }
186
187    fn serialize_newtype_struct<T>(
188        self,
189        _name: &'static str,
190        value: &T,
191    ) -> Result<Self::Ok, Self::Error>
192    where
193        T: ?Sized + ser::Serialize,
194    {
195        value.serialize(self)
196    }
197
198    fn serialize_newtype_variant<T>(
199        self,
200        _name: &'static str,
201        _variant_index: u32,
202        _variant: &'static str,
203        _value: &T,
204    ) -> Result<Self::Ok, Self::Error>
205    where
206        T: ?Sized + ser::Serialize,
207    {
208        Err(ArgsSetError)
209    }
210
211    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
212        Err(ArgsSetError)
213    }
214
215    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
216        Err(ArgsSetError)
217    }
218
219    fn serialize_tuple_struct(
220        self,
221        _name: &'static str,
222        _len: usize,
223    ) -> Result<Self::SerializeTupleStruct, Self::Error> {
224        Err(ArgsSetError)
225    }
226
227    fn serialize_tuple_variant(
228        self,
229        _name: &'static str,
230        _variant_index: u32,
231        _variant: &'static str,
232        _len: usize,
233    ) -> Result<Self::SerializeTupleVariant, Self::Error> {
234        Err(ArgsSetError)
235    }
236
237    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
238        Err(ArgsSetError)
239    }
240
241    fn serialize_struct(
242        self,
243        _name: &'static str,
244        _len: usize,
245    ) -> Result<Self::SerializeStruct, Self::Error> {
246        Ok(self)
247    }
248
249    fn serialize_struct_variant(
250        self,
251        _name: &'static str,
252        _variant_index: u32,
253        _variant: &'static str,
254        _len: usize,
255    ) -> Result<Self::SerializeStructVariant, Self::Error> {
256        Err(ArgsSetError)
257    }
258}
259
260impl ser::SerializeStruct for ArgsSetSerializer {
261    type Ok = CliArgsSet;
262    type Error = ArgsSetError;
263
264    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
265    where
266        T: ?Sized + ser::Serialize,
267    {
268        // TODO: duplicate key detection? seems awfully niche
269        if let Some(arg_type) = value.serialize(ArgsSetFieldSerializer)? {
270            let full_key = format!(
271                "{language}-{key}",
272                language = self.language,
273                key = UnderscoreToHyphen(key)
274            );
275
276            self.args.args.insert(key, (full_key, arg_type));
277        }
278
279        Ok(())
280    }
281
282    fn end(self) -> Result<Self::Ok, Self::Error> {
283        Ok(self.args)
284    }
285}
286
287struct UnderscoreToHyphen<'a>(&'a str);
288
289impl Display for UnderscoreToHyphen<'_> {
290    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
291        let mut chunks = self.0.split('_');
292
293        match chunks.next() {
294            None => Ok(()),
295            Some(first) => {
296                f.write_str(first)?;
297                chunks.try_for_each(|chunk| {
298                    f.write_char('-')?;
299                    f.write_str(chunk)
300                })
301            }
302        }
303    }
304}
305
306/// This type detects only what type the field has: bool (for a cli flag),
307/// primitive (for a cli argument), or anything else, in which case it has
308/// no CLI presence.
309struct ArgsSetFieldSerializer;
310
311impl ser::Serializer for ArgsSetFieldSerializer {
312    type Ok = Option<ArgType>;
313    type Error = ArgsSetError;
314
315    // Fill these with no-ops that don't return errors
316    type SerializeSeq = NoOpSubSerializer;
317    type SerializeTuple = NoOpSubSerializer;
318    type SerializeTupleStruct = NoOpSubSerializer;
319    type SerializeTupleVariant = NoOpSubSerializer;
320    type SerializeMap = NoOpSubSerializer;
321    type SerializeStruct = NoOpSubSerializer;
322    type SerializeStructVariant = NoOpSubSerializer;
323
324    fn serialize_bool(self, _v: bool) -> Result<Self::Ok, Self::Error> {
325        Ok(Some(ArgType::Bool))
326    }
327
328    fn serialize_i8(self, _v: i8) -> Result<Self::Ok, Self::Error> {
329        Ok(Some(ArgType::Value))
330    }
331
332    fn serialize_i16(self, _v: i16) -> Result<Self::Ok, Self::Error> {
333        Ok(Some(ArgType::Value))
334    }
335
336    fn serialize_i32(self, _v: i32) -> Result<Self::Ok, Self::Error> {
337        Ok(Some(ArgType::Value))
338    }
339
340    fn serialize_i64(self, _v: i64) -> Result<Self::Ok, Self::Error> {
341        Ok(Some(ArgType::Value))
342    }
343
344    fn serialize_u8(self, _v: u8) -> Result<Self::Ok, Self::Error> {
345        Ok(Some(ArgType::Value))
346    }
347
348    fn serialize_u16(self, _v: u16) -> Result<Self::Ok, Self::Error> {
349        Ok(Some(ArgType::Value))
350    }
351
352    fn serialize_u32(self, _v: u32) -> Result<Self::Ok, Self::Error> {
353        Ok(Some(ArgType::Value))
354    }
355
356    fn serialize_u64(self, _v: u64) -> Result<Self::Ok, Self::Error> {
357        Ok(Some(ArgType::Value))
358    }
359
360    fn serialize_f32(self, _v: f32) -> Result<Self::Ok, Self::Error> {
361        Ok(Some(ArgType::Value))
362    }
363
364    fn serialize_f64(self, _v: f64) -> Result<Self::Ok, Self::Error> {
365        Ok(Some(ArgType::Value))
366    }
367
368    fn serialize_char(self, _v: char) -> Result<Self::Ok, Self::Error> {
369        Ok(Some(ArgType::Value))
370    }
371
372    fn serialize_str(self, _v: &str) -> Result<Self::Ok, Self::Error> {
373        Ok(Some(ArgType::Value))
374    }
375
376    fn serialize_bytes(self, _v: &[u8]) -> Result<Self::Ok, Self::Error> {
377        Ok(Some(ArgType::Value))
378    }
379
380    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
381        Ok(Some(ArgType::Value))
382    }
383
384    fn serialize_some<T>(self, _value: &T) -> Result<Self::Ok, Self::Error>
385    where
386        T: ?Sized + ser::Serialize,
387    {
388        Ok(Some(ArgType::Value))
389    }
390
391    fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
392        Ok(None)
393    }
394
395    fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
396        Ok(None)
397    }
398
399    fn serialize_unit_variant(
400        self,
401        _name: &'static str,
402        _variant_index: u32,
403        _variant: &'static str,
404    ) -> Result<Self::Ok, Self::Error> {
405        Ok(Some(ArgType::Value))
406    }
407
408    fn serialize_newtype_struct<T>(
409        self,
410        _name: &'static str,
411        value: &T,
412    ) -> Result<Self::Ok, Self::Error>
413    where
414        T: ?Sized + ser::Serialize,
415    {
416        value.serialize(self)
417    }
418
419    fn serialize_newtype_variant<T>(
420        self,
421        _name: &'static str,
422        _variant_index: u32,
423        _variant: &'static str,
424        _value: &T,
425    ) -> Result<Self::Ok, Self::Error>
426    where
427        T: ?Sized + ser::Serialize,
428    {
429        Ok(None)
430    }
431
432    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
433        Ok(NoOpSubSerializer)
434    }
435
436    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
437        Ok(NoOpSubSerializer)
438    }
439
440    fn serialize_tuple_struct(
441        self,
442        _name: &'static str,
443        _len: usize,
444    ) -> Result<Self::SerializeTupleStruct, Self::Error> {
445        Ok(NoOpSubSerializer)
446    }
447
448    fn serialize_tuple_variant(
449        self,
450        _name: &'static str,
451        _variant_index: u32,
452        _variant: &'static str,
453        _len: usize,
454    ) -> Result<Self::SerializeTupleVariant, Self::Error> {
455        Ok(NoOpSubSerializer)
456    }
457
458    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
459        Ok(NoOpSubSerializer)
460    }
461
462    fn serialize_struct(
463        self,
464        _name: &'static str,
465        _len: usize,
466    ) -> Result<Self::SerializeStruct, Self::Error> {
467        Ok(NoOpSubSerializer)
468    }
469
470    fn serialize_struct_variant(
471        self,
472        _name: &'static str,
473        _variant_index: u32,
474        _variant: &'static str,
475        _len: usize,
476    ) -> Result<Self::SerializeStructVariant, Self::Error> {
477        Ok(NoOpSubSerializer)
478    }
479}
480
481struct NoOpSubSerializer;
482
483impl ser::SerializeSeq for NoOpSubSerializer {
484    type Ok = Option<ArgType>;
485    type Error = ArgsSetError;
486
487    fn serialize_element<T>(&mut self, _value: &T) -> Result<(), Self::Error>
488    where
489        T: ?Sized + ser::Serialize,
490    {
491        Ok(())
492    }
493
494    fn end(self) -> Result<Self::Ok, Self::Error> {
495        Ok(None)
496    }
497}
498
499impl ser::SerializeTuple for NoOpSubSerializer {
500    type Ok = Option<ArgType>;
501    type Error = ArgsSetError;
502
503    fn serialize_element<T>(&mut self, _value: &T) -> Result<(), Self::Error>
504    where
505        T: ?Sized + ser::Serialize,
506    {
507        Ok(())
508    }
509
510    fn end(self) -> Result<Self::Ok, Self::Error> {
511        Ok(None)
512    }
513}
514
515impl ser::SerializeTupleStruct for NoOpSubSerializer {
516    type Ok = Option<ArgType>;
517    type Error = ArgsSetError;
518
519    fn serialize_field<T>(&mut self, _value: &T) -> Result<(), Self::Error>
520    where
521        T: ?Sized + ser::Serialize,
522    {
523        Ok(())
524    }
525
526    fn end(self) -> Result<Self::Ok, Self::Error> {
527        Ok(None)
528    }
529}
530
531impl ser::SerializeTupleVariant for NoOpSubSerializer {
532    type Ok = Option<ArgType>;
533    type Error = ArgsSetError;
534
535    fn serialize_field<T>(&mut self, _value: &T) -> Result<(), Self::Error>
536    where
537        T: ?Sized + ser::Serialize,
538    {
539        Ok(())
540    }
541
542    fn end(self) -> Result<Self::Ok, Self::Error> {
543        Ok(None)
544    }
545}
546
547impl ser::SerializeMap for NoOpSubSerializer {
548    type Ok = Option<ArgType>;
549    type Error = ArgsSetError;
550
551    fn serialize_key<T>(&mut self, _key: &T) -> Result<(), Self::Error>
552    where
553        T: ?Sized + ser::Serialize,
554    {
555        Ok(())
556    }
557
558    fn serialize_value<T>(&mut self, _value: &T) -> Result<(), Self::Error>
559    where
560        T: ?Sized + ser::Serialize,
561    {
562        Ok(())
563    }
564
565    fn end(self) -> Result<Self::Ok, Self::Error> {
566        Ok(None)
567    }
568}
569
570impl ser::SerializeStruct for NoOpSubSerializer {
571    type Ok = Option<ArgType>;
572    type Error = ArgsSetError;
573
574    fn serialize_field<T>(&mut self, _key: &'static str, _value: &T) -> Result<(), Self::Error>
575    where
576        T: ?Sized + ser::Serialize,
577    {
578        Ok(())
579    }
580
581    fn end(self) -> Result<Self::Ok, Self::Error> {
582        Ok(None)
583    }
584}
585
586impl ser::SerializeStructVariant for NoOpSubSerializer {
587    type Ok = Option<ArgType>;
588    type Error = ArgsSetError;
589
590    fn serialize_field<T>(&mut self, _key: &'static str, _value: &T) -> Result<(), Self::Error>
591    where
592        T: ?Sized + ser::Serialize,
593    {
594        Ok(())
595    }
596
597    fn end(self) -> Result<Self::Ok, Self::Error> {
598        Ok(None)
599    }
600}