aopt/value/
infer.rs

1use std::any::TypeId;
2use std::ffi::OsStr;
3use std::ffi::OsString;
4use std::io::Stdin;
5use std::path::PathBuf;
6
7use crate::ctx::Ctx;
8use crate::map::ErasedTy;
9use crate::opt::Action;
10use crate::opt::AnyOpt;
11use crate::opt::Cid;
12use crate::opt::Cmd;
13use crate::opt::ConfigValue;
14use crate::opt::Index;
15use crate::opt::Main;
16use crate::opt::MutOpt;
17use crate::opt::Pos;
18use crate::opt::Style;
19use crate::trace;
20use crate::typeid;
21use crate::value::ValInitializer;
22use crate::value::ValValidator;
23use crate::Error;
24
25use super::AnyValue;
26use super::RawValParser;
27use super::Stop;
28use super::ValStorer;
29
30/// Implement this if you want the type can used for create option.
31pub trait Infer {
32    type Val: ErasedTy;
33
34    fn infer_act() -> Action {
35        Action::App
36    }
37
38    fn infer_force() -> bool {
39        false
40    }
41
42    fn infer_ctor() -> String {
43        crate::set::ctor_default_name()
44    }
45
46    fn infer_index() -> Option<Index> {
47        None
48    }
49
50    fn infer_style() -> Vec<Style> {
51        vec![Style::Argument]
52    }
53
54    fn infer_ignore_name() -> bool {
55        false
56    }
57
58    fn infer_ignore_alias() -> bool {
59        false
60    }
61
62    fn infer_ignore_index() -> bool {
63        true
64    }
65
66    fn infer_validator() -> Option<ValValidator<Self::Val>> {
67        None
68    }
69
70    fn infer_initializer() -> Option<ValInitializer> {
71        Some(ValInitializer::fallback())
72    }
73
74    fn infer_type_id() -> TypeId {
75        typeid::<Self::Val>()
76    }
77
78    fn infer_map(val: Self::Val) -> Self;
79
80    fn infer_mutable(&mut self, val: Self::Val)
81    where
82        Self: Sized,
83    {
84        *self = Self::infer_map(val);
85    }
86
87    fn infer_tweak_info<C>(_cfg: &mut C) -> Result<(), Error>
88    where
89        Self: Sized + 'static,
90        Self::Val: RawValParser,
91        C: ConfigValue + Default,
92    {
93        Ok(())
94    }
95
96    fn infer_fill_info<C>(cfg: &mut C) -> Result<(), Error>
97    where
98        Self: Sized + 'static,
99        Self::Val: RawValParser,
100        C: ConfigValue + Default,
101    {
102        let act = Self::infer_act();
103        let style = Self::infer_style();
104        let index = Self::infer_index();
105        let ignore_name = Self::infer_ignore_name();
106        let ignore_alias = Self::infer_ignore_alias();
107        let ignore_index = Self::infer_ignore_index();
108        let force = Self::infer_force();
109        let ctor = Self::infer_ctor();
110        let type_id = Self::infer_type_id();
111        let initializer = Self::infer_initializer();
112        let storer = if let Some(validator) = Self::infer_validator() {
113            Some(ValStorer::from(validator))
114        } else {
115            Some(ValStorer::fallback::<Self::Val>())
116        };
117
118        Self::infer_tweak_info(cfg)?;
119        (!cfg.has_ctor()).then(|| cfg.set_ctor(ctor));
120        (!cfg.has_index()).then(|| index.map(|idx| cfg.set_index(idx)));
121        (!cfg.has_type()).then(|| cfg.set_type_id(type_id));
122        (!cfg.has_action()).then(|| cfg.set_action(act));
123        (!cfg.has_style()).then(|| cfg.set_style(style));
124        (!cfg.has_force()).then(|| cfg.set_force(force));
125        (!cfg.has_action()).then(|| cfg.set_action(act));
126        if let Some(storer) = storer {
127            (!cfg.has_storer()).then(|| cfg.set_storer(storer));
128        }
129        if let Some(initializer) = initializer {
130            (!cfg.has_initializer()).then(|| cfg.set_initializer(initializer));
131        }
132        cfg.set_ignore_name(ignore_name);
133        cfg.set_ignore_alias(ignore_alias);
134        cfg.set_ignore_index(ignore_index);
135        Ok(())
136    }
137}
138
139impl Infer for bool {
140    type Val = bool;
141
142    fn infer_act() -> Action {
143        Action::Set
144    }
145
146    fn infer_style() -> Vec<Style> {
147        vec![Style::Combined, Style::Boolean]
148    }
149
150    /// bool has a default value [`false`]
151    fn infer_initializer() -> Option<ValInitializer> {
152        Some(ValInitializer::new_value(false))
153    }
154
155    fn infer_map(val: Self::Val) -> Self {
156        val
157    }
158}
159
160impl Infer for Cmd {
161    type Val = bool;
162
163    fn infer_act() -> Action {
164        Action::Set
165    }
166
167    fn infer_force() -> bool {
168        true
169    }
170
171    fn infer_index() -> Option<Index> {
172        Some(Index::forward(1))
173    }
174
175    fn infer_style() -> Vec<Style> {
176        vec![Style::Cmd]
177    }
178
179    fn infer_ignore_index() -> bool {
180        false
181    }
182
183    fn infer_initializer() -> Option<ValInitializer> {
184        Some(ValInitializer::new_value(false))
185    }
186
187    fn infer_type_id() -> TypeId {
188        typeid::<Self>()
189    }
190
191    fn infer_map(val: Self::Val) -> Self {
192        Cmd::new(val)
193    }
194
195    fn infer_mutable(&mut self, val: Self::Val) {
196        self.0 = val;
197    }
198}
199
200impl<T> Infer for Pos<T>
201where
202    T: Infer + ErasedTy,
203{
204    type Val = T::Val;
205
206    fn infer_type_id() -> TypeId {
207        typeid::<Self>()
208    }
209
210    fn infer_style() -> Vec<Style> {
211        vec![Style::Pos]
212    }
213
214    fn infer_ignore_name() -> bool {
215        true
216    }
217
218    fn infer_ignore_alias() -> bool {
219        true
220    }
221
222    fn infer_ignore_index() -> bool {
223        false
224    }
225
226    fn infer_map(val: Self::Val) -> Self {
227        Pos::new(<T as Infer>::infer_map(val))
228    }
229
230    fn infer_mutable(&mut self, val: Self::Val) {
231        self.0.infer_mutable(val);
232    }
233
234    /// Will add default type storer when value type is bool.
235    ///
236    /// # Storer
237    /// ```ignore
238    /// Box::new(
239    ///     |raw: Option<&OsStr>, _: &Ctx, act: &Action, handler: &mut AnyValue| {
240    ///         let val = raw.is_some();
241    ///
242    ///         trace!("Pos value storer, parsing {:?} -> {:?}", raw, val);
243    ///         act.store1(Some(val), handler);
244    ///         Ok(())
245    ///     },
246    /// );
247    /// ```
248    fn infer_tweak_info<C>(cfg: &mut C) -> Result<(), Error>
249    where
250        Self: Sized + 'static,
251        Self::Val: RawValParser,
252        C: ConfigValue + Default,
253    {
254        if !cfg.has_storer() {
255            let type_id = std::any::TypeId::of::<T>();
256            let bool_type = std::any::TypeId::of::<bool>();
257
258            trace!(
259                "tweak the storer for Pos<bool> for {:?}?: type = {:?}",
260                cfg.name(),
261                std::any::type_name::<T>()
262            );
263            // add default storer when value type is bool.
264            if type_id == bool_type {
265                cfg.set_storer(ValStorer::new(Box::new(
266                    |raw: Option<&OsStr>, _: &Ctx, act: &Action, handler: &mut AnyValue| {
267                        let val = raw.is_some();
268
269                        trace!("in pos<bool> value storer, parsing {:?} -> {:?}", raw, val);
270                        act.store1(Some(val), handler);
271                        Ok(())
272                    },
273                )));
274            }
275        }
276        Ok(())
277    }
278}
279
280impl<T> Infer for Main<T>
281where
282    T: Infer + ErasedTy,
283{
284    type Val = T::Val;
285
286    fn infer_act() -> Action {
287        Action::Null
288    }
289
290    fn infer_index() -> Option<Index> {
291        Some(Index::anywhere())
292    }
293
294    fn infer_style() -> Vec<Style> {
295        vec![Style::Main]
296    }
297
298    fn infer_ignore_name() -> bool {
299        true
300    }
301
302    fn infer_ignore_alias() -> bool {
303        true
304    }
305
306    fn infer_ignore_index() -> bool {
307        false
308    }
309
310    fn infer_type_id() -> TypeId {
311        typeid::<Self>()
312    }
313
314    fn infer_map(val: Self::Val) -> Self {
315        Main::new(<T as Infer>::infer_map(val))
316    }
317
318    fn infer_mutable(&mut self, val: Self::Val) {
319        self.0.infer_mutable(val);
320    }
321}
322
323impl<T: ErasedTy + RawValParser> Infer for MutOpt<T> {
324    type Val = T;
325
326    fn infer_map(val: Self::Val) -> Self {
327        MutOpt::new(val)
328    }
329
330    fn infer_mutable(&mut self, val: Self::Val) {
331        self.0 = val;
332    }
333}
334
335impl<T> Infer for AnyOpt<T>
336where
337    T: Infer + ErasedTy,
338{
339    type Val = T::Val;
340
341    fn infer_act() -> Action {
342        Action::Null
343    }
344
345    fn infer_style() -> Vec<Style> {
346        vec![
347            Style::Argument,
348            Style::Boolean,
349            Style::Combined,
350            Style::Pos,
351            Style::Cmd,
352            Style::Main,
353        ]
354    }
355
356    fn infer_ignore_index() -> bool {
357        false
358    }
359
360    fn infer_type_id() -> TypeId {
361        typeid::<Self>()
362    }
363
364    fn infer_map(val: Self::Val) -> Self {
365        AnyOpt::new(<T as Infer>::infer_map(val))
366    }
367
368    fn infer_mutable(&mut self, val: Self::Val) {
369        self.0.infer_mutable(val);
370    }
371}
372
373impl Infer for Stdin {
374    type Val = Stdin;
375
376    fn infer_act() -> Action {
377        Action::Set
378    }
379
380    fn infer_style() -> Vec<Style> {
381        vec![Style::Boolean]
382    }
383
384    fn infer_ignore_alias() -> bool {
385        true
386    }
387
388    fn infer_map(val: Self::Val) -> Self {
389        val
390    }
391
392    /// For type Stdin, swap the name and default alias(`-`) when build configuration.
393    fn infer_tweak_info<C>(cfg: &mut C) -> Result<(), Error>
394    where
395        Self: Sized + 'static,
396        Self::Val: RawValParser,
397        C: ConfigValue + Default,
398    {
399        if let Some(name) = cfg.name() {
400            cfg.add_alias(name.to_string());
401        }
402        cfg.set_name("-");
403        Ok(())
404    }
405}
406
407impl Infer for Stop {
408    type Val = Stop;
409
410    fn infer_act() -> Action {
411        Action::Set
412    }
413
414    fn infer_style() -> Vec<Style> {
415        vec![Style::Boolean]
416    }
417
418    fn infer_ignore_alias() -> bool {
419        true
420    }
421
422    fn infer_map(val: Self::Val) -> Self {
423        val
424    }
425
426    /// For type Stop, swap the name and default alias(`--`) when build configuration.
427    fn infer_tweak_info<C>(cfg: &mut C) -> Result<(), Error>
428    where
429        Self: Sized + 'static,
430        Self::Val: RawValParser,
431        C: ConfigValue + Default,
432    {
433        if let Some(name) = cfg.name() {
434            cfg.add_alias(name.to_string());
435        }
436        cfg.set_name("--");
437        Ok(())
438    }
439}
440
441macro_rules! impl_infer_for {
442    ($name:path) => {
443        impl Infer for $name {
444            type Val = $name;
445
446            fn infer_map(val: Self::Val) -> Self {
447                val
448            }
449        }
450    };
451    (&$a:lifetime $name:path) => {
452        impl<$a> Infer for &$a $name {
453            type Val = $name;
454        }
455    };
456    (&$a:lifetime $name:path, $inner_type:path) => {
457        impl<$a> Infer for &$a $name {
458            type Val = $inner_type;
459        }
460    };
461    ($name:path, $force:literal { type Val = $val_type:ty; $( fn $fn_name:ident() -> $ret_type:ty $fn_block:block )+ }) => {
462        impl Infer for $name {
463            type Val = $val_type;
464
465            $(
466                fn $fn_name() -> $ret_type $fn_block
467            )+
468        }
469    };
470}
471
472impl_infer_for!(f64);
473impl_infer_for!(f32);
474
475impl_infer_for!(i8);
476impl_infer_for!(i16);
477impl_infer_for!(i32);
478impl_infer_for!(i64);
479
480impl_infer_for!(u8);
481impl_infer_for!(u16);
482impl_infer_for!(u32);
483impl_infer_for!(u64);
484
485impl_infer_for!(i128);
486impl_infer_for!(u128);
487
488impl_infer_for!(isize);
489impl_infer_for!(usize);
490impl_infer_for!(String);
491impl_infer_for!(PathBuf);
492impl_infer_for!(OsString);
493
494#[derive(Debug, Clone, Copy)]
495pub struct Placeholder;
496
497impl Infer for Placeholder {
498    type Val = ();
499
500    fn infer_type_id() -> TypeId {
501        typeid::<Self>()
502    }
503
504    fn infer_map(_: Self::Val) -> Self {
505        Placeholder
506    }
507
508    fn infer_mutable(&mut self, _: Self::Val) {}
509
510    fn infer_fill_info<C>(cfg: &mut C) -> Result<(), Error>
511    where
512        Self: Sized + 'static,
513        Self::Val: RawValParser,
514        C: ConfigValue + Default,
515    {
516        // it must have ctor here
517        let ctor = cfg
518            .ctor()
519            .ok_or_else(|| crate::error!("incomplete configuration: missing `ctor`"))?;
520        let cid = Cid::from(ctor);
521
522        trace!("in default, fill info in Placeholder");
523        match cid {
524            Cid::Int => <i64>::infer_fill_info(cfg),
525            Cid::Str => <String>::infer_fill_info(cfg),
526            Cid::Flt => <f64>::infer_fill_info(cfg),
527            Cid::Uint => <u64>::infer_fill_info(cfg),
528            Cid::Bool => bool::infer_fill_info(cfg),
529            Cid::Cmd => Cmd::infer_fill_info(cfg),
530            Cid::Pos => <Pos<bool>>::infer_fill_info(cfg),
531            Cid::Main => Main::<()>::infer_fill_info(cfg),
532            Cid::Any => AnyOpt::<()>::infer_fill_info(cfg),
533            Cid::Raw => <OsString>::infer_fill_info(cfg),
534            _ => Ok(()),
535        }
536    }
537}
538
539impl Infer for () {
540    type Val = ();
541
542    fn infer_map(val: Self::Val) -> Self {
543        val
544    }
545}
546
547impl<T: Infer> Infer for Option<T> {
548    type Val = <T as Infer>::Val;
549
550    fn infer_act() -> Action {
551        <T as Infer>::infer_act()
552    }
553
554    fn infer_force() -> bool {
555        false
556    }
557
558    fn infer_ctor() -> String {
559        <T as Infer>::infer_ctor()
560    }
561
562    fn infer_index() -> Option<Index> {
563        <T as Infer>::infer_index()
564    }
565
566    fn infer_style() -> Vec<Style> {
567        <T as Infer>::infer_style()
568    }
569
570    fn infer_ignore_name() -> bool {
571        <T as Infer>::infer_ignore_name()
572    }
573
574    fn infer_ignore_alias() -> bool {
575        <T as Infer>::infer_ignore_alias()
576    }
577
578    fn infer_ignore_index() -> bool {
579        <T as Infer>::infer_ignore_index()
580    }
581
582    fn infer_validator() -> Option<ValValidator<Self::Val>> {
583        <T as Infer>::infer_validator()
584    }
585
586    fn infer_initializer() -> Option<ValInitializer> {
587        <T as Infer>::infer_initializer()
588    }
589
590    fn infer_type_id() -> TypeId {
591        <T as Infer>::infer_type_id()
592    }
593
594    fn infer_map(val: Self::Val) -> Self {
595        Some(<T as Infer>::infer_map(val))
596    }
597
598    fn infer_mutable(&mut self, val: Self::Val) {
599        if let Some(value) = self {
600            value.infer_mutable(val);
601        } else {
602            *self = Self::infer_map(val);
603        }
604    }
605
606    fn infer_tweak_info<C>(cfg: &mut C) -> Result<(), Error>
607    where
608        Self: Sized + 'static,
609        Self::Val: RawValParser,
610        C: ConfigValue + Default,
611    {
612        <T as Infer>::infer_tweak_info(cfg)
613    }
614
615    fn infer_fill_info<C>(cfg: &mut C) -> Result<(), Error>
616    where
617        Self: Sized + 'static,
618        Self::Val: RawValParser,
619        C: ConfigValue + Default,
620    {
621        <T as Infer>::infer_fill_info(cfg)
622    }
623}
624
625impl<Err, T: Infer> Infer for Result<T, Err> {
626    type Val = <T as Infer>::Val;
627
628    fn infer_act() -> Action {
629        <T as Infer>::infer_act()
630    }
631
632    fn infer_force() -> bool {
633        false
634    }
635
636    fn infer_ctor() -> String {
637        <T as Infer>::infer_ctor()
638    }
639
640    fn infer_index() -> Option<Index> {
641        <T as Infer>::infer_index()
642    }
643
644    fn infer_style() -> Vec<Style> {
645        <T as Infer>::infer_style()
646    }
647
648    fn infer_ignore_name() -> bool {
649        <T as Infer>::infer_ignore_name()
650    }
651
652    fn infer_ignore_alias() -> bool {
653        <T as Infer>::infer_ignore_alias()
654    }
655
656    fn infer_ignore_index() -> bool {
657        <T as Infer>::infer_ignore_index()
658    }
659
660    fn infer_validator() -> Option<ValValidator<Self::Val>> {
661        <T as Infer>::infer_validator()
662    }
663
664    fn infer_initializer() -> Option<ValInitializer> {
665        <T as Infer>::infer_initializer()
666    }
667
668    fn infer_type_id() -> TypeId {
669        <T as Infer>::infer_type_id()
670    }
671
672    fn infer_map(val: Self::Val) -> Self {
673        Ok(<T as Infer>::infer_map(val))
674    }
675
676    fn infer_mutable(&mut self, val: Self::Val) {
677        if let Ok(value) = self {
678            value.infer_mutable(val);
679        } else {
680            *self = Self::infer_map(val);
681        }
682    }
683
684    fn infer_tweak_info<C>(cfg: &mut C) -> Result<(), Error>
685    where
686        Self: Sized + 'static,
687        Self::Val: RawValParser,
688        C: ConfigValue + Default,
689    {
690        <T as Infer>::infer_tweak_info(cfg)
691    }
692
693    fn infer_fill_info<C>(cfg: &mut C) -> Result<(), Error>
694    where
695        Self: Sized + 'static,
696        Self::Val: RawValParser,
697        C: ConfigValue + Default,
698    {
699        <T as Infer>::infer_fill_info(cfg)
700    }
701}
702
703impl<T: Infer> Infer for Vec<T> {
704    type Val = <T as Infer>::Val;
705
706    fn infer_act() -> Action {
707        Action::App
708    }
709
710    fn infer_force() -> bool {
711        true
712    }
713
714    fn infer_ctor() -> String {
715        <T as Infer>::infer_ctor()
716    }
717
718    fn infer_index() -> Option<Index> {
719        <T as Infer>::infer_index()
720    }
721
722    fn infer_style() -> Vec<Style> {
723        <T as Infer>::infer_style()
724    }
725
726    fn infer_ignore_name() -> bool {
727        <T as Infer>::infer_ignore_name()
728    }
729
730    fn infer_ignore_alias() -> bool {
731        <T as Infer>::infer_ignore_alias()
732    }
733
734    fn infer_ignore_index() -> bool {
735        <T as Infer>::infer_ignore_index()
736    }
737
738    fn infer_validator() -> Option<ValValidator<Self::Val>> {
739        <T as Infer>::infer_validator()
740    }
741
742    fn infer_initializer() -> Option<ValInitializer> {
743        <T as Infer>::infer_initializer()
744    }
745
746    fn infer_type_id() -> TypeId {
747        <T as Infer>::infer_type_id()
748    }
749
750    fn infer_map(val: Self::Val) -> Self {
751        vec![<T as Infer>::infer_map(val)]
752    }
753
754    fn infer_mutable(&mut self, val: Self::Val) {
755        self.push(<T as Infer>::infer_map(val));
756    }
757
758    fn infer_tweak_info<C>(cfg: &mut C) -> Result<(), Error>
759    where
760        Self: Sized + 'static,
761        Self::Val: RawValParser,
762        C: ConfigValue + Default,
763    {
764        <T as Infer>::infer_tweak_info(cfg)
765    }
766
767    fn infer_fill_info<C>(cfg: &mut C) -> Result<(), Error>
768    where
769        Self: Sized + 'static,
770        Self::Val: RawValParser,
771        C: ConfigValue + Default,
772    {
773        <T as Infer>::infer_fill_info(cfg)
774    }
775}