aopt_core/value/
storer.rs1use std::ffi::OsStr;
2use std::fmt::Debug;
3
4use crate::ctx::Ctx;
5use crate::map::ErasedTy;
6use crate::opt::Action;
7use crate::trace;
8use crate::Error;
9
10use super::AnyValue;
11use super::RawValParser;
12use super::ValValidator;
13
14#[cfg(feature = "sync")]
15pub type StoreHandler<T> =
16 Box<dyn FnMut(Option<&OsStr>, &Ctx, &Action, &mut T) -> Result<(), Error> + Send + Sync>;
17
18#[cfg(not(feature = "sync"))]
19pub type StoreHandler<T> =
20 Box<dyn FnMut(Option<&OsStr>, &Ctx, &Action, &mut T) -> Result<(), Error>>;
21
22pub struct ValStorer(StoreHandler<AnyValue>);
24
25impl Debug for ValStorer {
26 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27 f.debug_tuple("WriterHandler").field(&"{...}").finish()
28 }
29}
30
31impl ValStorer {
32 pub fn new(handler: StoreHandler<AnyValue>) -> Self {
33 Self(handler)
34 }
35
36 pub fn fallback<U: ErasedTy + RawValParser>() -> Self {
37 Self(Self::fallback_handler::<U>())
38 }
39
40 pub fn new_validator<U: ErasedTy + RawValParser>(validator: ValValidator<U>) -> Self {
44 Self(Self::validator(validator))
45 }
46
47 pub fn invoke(
49 &mut self,
50 raw: Option<&OsStr>,
51 ctx: &Ctx,
52 act: &Action,
53 arg: &mut AnyValue,
54 ) -> Result<(), Error> {
55 crate::trace!("saving raw value({:?}) for {}", raw, ctx.uid()?);
56 (self.0)(raw, ctx, act, arg)
57 }
58
59 pub fn validator<U: ErasedTy + RawValParser>(
60 validator: ValValidator<U>,
61 ) -> StoreHandler<AnyValue> {
62 Box::new(
63 move |raw: Option<&OsStr>, ctx: &Ctx, act: &Action, handler: &mut AnyValue| {
64 let val = U::parse(raw, ctx).map_err(Into::into)?;
65
66 if !validator.invoke(&val) {
67 let uid = ctx.uid()?;
68
69 trace!(
70 "validator value storer failed, parsing {:?} -> {:?}",
71 raw,
72 val
73 );
74 Err(
75 crate::failure!("value check failed: `{:?}`", ctx.inner_ctx().ok(),)
76 .with_uid(uid),
77 )
78 } else {
79 trace!(
80 "validator value storer okay, parsing {:?} -> {:?}",
81 raw,
82 val
83 );
84 act.store1(Some(val), handler);
85 Ok(())
86 }
87 },
88 )
89 }
90
91 pub fn fallback_handler<U: ErasedTy + RawValParser>() -> StoreHandler<AnyValue> {
92 Box::new(
93 |raw: Option<&OsStr>, ctx: &Ctx, act: &Action, handler: &mut AnyValue| {
94 let val = U::parse(raw, ctx).map_err(Into::into);
95
96 trace!("in fallback value storer, parsing {:?} -> {:?}", raw, val);
97 act.store1(Some(val?), handler);
98 Ok(())
99 },
100 )
101 }
102}
103
104impl<U: ErasedTy + RawValParser> From<ValValidator<U>> for ValStorer {
105 fn from(validator: ValValidator<U>) -> Self {
106 Self::new_validator(validator)
107 }
108}
109
110impl<U: ErasedTy + RawValParser> From<Option<ValValidator<U>>> for ValStorer {
111 fn from(validator: Option<ValValidator<U>>) -> Self {
112 if let Some(validator) = validator {
113 Self::new_validator(validator)
114 } else {
115 Self::fallback::<U>()
116 }
117 }
118}