aopt/ctx/
store.rs

1use std::ffi::OsStr;
2
3use crate::acore::opt::Action;
4use crate::map::ErasedTy;
5use crate::opt::Opt;
6use crate::set::SetExt;
7use crate::set::SetOpt;
8use crate::Error;
9use crate::Uid;
10
11/// The [`Store`] saving the value of given option.
12pub trait Store<S, Value> {
13    type Ret;
14    type Error: Into<Error>;
15
16    fn process(
17        &mut self,
18        uid: Uid,
19        set: &mut S,
20        raw: Option<&OsStr>,
21        val: Option<Value>,
22    ) -> Result<Self::Ret, Self::Error>;
23}
24
25#[cfg(not(feature = "sync"))]
26impl<Func, Set, Value, Ret, Err> Store<Set, Value> for Func
27where
28    Err: Into<Error>,
29    Func: FnMut(Uid, &mut Set, Option<&OsStr>, Option<Value>) -> Result<Ret, Err>,
30{
31    type Ret = Ret;
32    type Error = Err;
33
34    fn process(
35        &mut self,
36        uid: Uid,
37        set: &mut Set,
38        raw: Option<&OsStr>,
39        val: Option<Value>,
40    ) -> Result<Self::Ret, Self::Error> {
41        (self)(uid, set, raw, val)
42    }
43}
44#[cfg(feature = "sync")]
45impl<Func, S, Value, Ret, Err> Store<S, Value> for Func
46where
47    Err: Into<Error>,
48    Func: FnMut(Uid, &mut S, Option<&OsStr>, Option<Value>) -> Result<Ret, Err> + Send + Sync,
49{
50    type Ret = Ret;
51    type Error = Err;
52
53    fn process(
54        &mut self,
55        uid: Uid,
56        set: &mut S,
57        raw: Option<&OsStr>,
58        val: Option<Value>,
59    ) -> Result<Self::Ret, Self::Error> {
60        (self)(uid, set, raw, val)
61    }
62}
63
64/// Null store, do nothing. See [`Action`](crate::opt::Action) for default store.
65pub struct NullStore;
66
67impl<Set, Value> Store<Set, Value> for NullStore {
68    type Ret = bool;
69
70    type Error = Error;
71
72    fn process(
73        &mut self,
74        _: Uid,
75        _: &mut Set,
76        _: Option<&OsStr>,
77        _: Option<Value>,
78    ) -> Result<Self::Ret, Self::Error> {
79        Ok(true)
80    }
81}
82
83/// Vector store, append the value to the [`ValStorer`](crate::value::ValStorer)
84/// if option's action is Action::App.
85/// See [`Action`](crate::opt::Action) for default store.
86pub struct VecStore;
87
88impl<Set, Value: ErasedTy> Store<Set, Vec<Value>> for VecStore
89where
90    Set: crate::set::Set,
91    SetOpt<Set>: Opt,
92{
93    type Ret = bool;
94
95    type Error = Error;
96
97    fn process(
98        &mut self,
99        uid: Uid,
100        set: &mut Set,
101        raw: Option<&OsStr>,
102        val: Option<Vec<Value>>,
103    ) -> Result<Self::Ret, Self::Error> {
104        let has_value = val.is_some();
105
106        // Set the value if return Some(Value)
107        if let Some(val) = val {
108            if let Some(opt) = set.get_mut(uid) {
109                let act = *opt.action();
110                let (raw_handler, handler) = opt.accessor_mut().handlers();
111
112                if act.is_app() {
113                    if let Some(raw) = raw {
114                        raw_handler.push(raw.to_os_string());
115                    }
116                    for value in val {
117                        handler.push(value);
118                    }
119                } else {
120                    panic!("the action is not Action::App, but set a vector value")
121                }
122            }
123        }
124
125        Ok(has_value)
126    }
127}
128
129/// Default store using for store value to [`ValStorer`](crate::value::ValStorer).
130/// It will store `OsString` and `Val` if `val` is `Some(Val)`, otherwise do nothing.
131///
132/// Note: The [`ValStorer`](crate::value::ValStorer) internal using an [`vec`] saving the option value.
133///
134/// * [`Action::Set`] : Set the option value to `vec![ val ]`.
135///
136/// * [`Action::App`] : Append the value to value vector.
137///
138/// * [`Action::Pop`] : Pop last value from value vector.
139///
140/// * [`Action::Cnt`] : Count the value and save the count as `vec![cnt]`.
141///
142/// * [`Action::Clr`] : Clear all the value from value vector.
143///
144/// * [`Action::Null`] : Do nothing.
145impl<Set, Val> Store<Set, Val> for Action
146where
147    Val: ErasedTy,
148    SetOpt<Set>: Opt,
149    Set: crate::set::Set,
150{
151    type Ret = bool;
152
153    type Error = Error;
154
155    fn process(
156        &mut self,
157        uid: Uid,
158        set: &mut Set,
159        raw: Option<&OsStr>,
160        val: Option<Val>,
161    ) -> Result<Self::Ret, Self::Error> {
162        let opt = set.opt_mut(uid)?;
163
164        crate::trace!("storing value of {} = `{:?}`", opt.name(), raw);
165        let (raw_handler, handler) = opt.accessor_mut().handlers();
166        // Set the value if return Some(Value)
167        Ok(self.store2(raw, val, raw_handler, handler))
168    }
169}