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