swc_config/types/
bool_or_data.rs

1use serde::{Deserialize, Serialize};
2
3use crate::merge::Merge;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
6pub struct BoolOrDataConfig<T>(#[serde(default)] Option<BoolOr<T>>);
7
8impl<T> BoolOrDataConfig<T> {
9    pub fn from_bool(v: bool) -> Self {
10        Self(Some(BoolOr::Bool(v)))
11    }
12
13    pub fn from_obj(v: T) -> Self {
14        v.into()
15    }
16
17    pub fn as_ref(&self) -> BoolOrDataConfig<&T> {
18        match &self.0 {
19            Some(BoolOr::Data(v)) => BoolOrDataConfig::from_obj(v),
20            Some(BoolOr::Bool(b)) => BoolOrDataConfig::from_bool(*b),
21            None => BoolOrDataConfig::default(),
22        }
23    }
24
25    pub fn or<F>(self, default: F) -> Self
26    where
27        F: FnOnce() -> Self,
28    {
29        match self.0 {
30            Some(..) => self,
31            None => default(),
32        }
33    }
34
35    pub fn unwrap_as_option<F>(self, default: F) -> Option<T>
36    where
37        F: FnOnce(Option<bool>) -> Option<T>,
38    {
39        match self.0 {
40            Some(BoolOr::Data(v)) => Some(v),
41            Some(BoolOr::Bool(b)) => default(Some(b)),
42            None => default(None),
43        }
44    }
45
46    pub fn map<F, N>(self, op: F) -> BoolOrDataConfig<N>
47    where
48        F: FnOnce(T) -> N,
49    {
50        match self.0 {
51            Some(BoolOr::Data(v)) => BoolOrDataConfig::from_obj(op(v)),
52            Some(BoolOr::Bool(b)) => BoolOrDataConfig::from_bool(b),
53            None => BoolOrDataConfig::default(),
54        }
55    }
56
57    pub fn is_true(&self) -> bool {
58        matches!(self.0, Some(BoolOr::Bool(true)))
59    }
60
61    pub fn is_false(&self) -> bool {
62        matches!(self.0, Some(BoolOr::Bool(false)))
63    }
64
65    pub fn is_obj(&self) -> bool {
66        matches!(self.0, Some(BoolOr::Data(_)))
67    }
68
69    pub fn into_inner(self) -> Option<BoolOr<T>> {
70        self.0
71    }
72
73    pub fn inner(&self) -> Option<BoolOr<&T>> {
74        match &self.0 {
75            Some(BoolOr::Data(v)) => Some(BoolOr::Data(v)),
76            Some(BoolOr::Bool(b)) => Some(BoolOr::Bool(*b)),
77            None => None,
78        }
79    }
80}
81
82impl<T> From<T> for BoolOrDataConfig<T> {
83    fn from(v: T) -> Self {
84        Self(Some(BoolOr::Data(v)))
85    }
86}
87
88impl<T> Default for BoolOrDataConfig<T> {
89    fn default() -> Self {
90        Self(Default::default())
91    }
92}
93
94impl<T> Merge for BoolOrDataConfig<T> {
95    #[inline]
96    fn merge(&mut self, other: Self) {
97        self.0.merge(other.0)
98    }
99}
100
101#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
102#[serde(untagged)]
103pub enum BoolOr<T> {
104    Bool(bool),
105    Data(T),
106}
107
108impl<'de, T> Deserialize<'de> for BoolOr<T>
109where
110    T: Deserialize<'de>,
111{
112    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
113    where
114        D: serde::Deserializer<'de>,
115    {
116        #[derive(Deserialize)]
117        #[serde(untagged)]
118        enum Deser<T> {
119            Bool(bool),
120            Obj(T),
121            EmptyObject(EmptyStruct),
122        }
123
124        #[derive(Deserialize)]
125        #[serde(deny_unknown_fields)]
126        struct EmptyStruct {}
127
128        use serde::__private::de;
129
130        let content = de::Content::deserialize(deserializer)?;
131
132        let deserializer = de::ContentRefDeserializer::<D::Error>::new(&content);
133
134        let res = Deser::deserialize(deserializer);
135
136        match res {
137            Ok(v) => Ok(match v {
138                Deser::Bool(v) => BoolOr::Bool(v),
139                Deser::Obj(v) => BoolOr::Data(v),
140                Deser::EmptyObject(_) => BoolOr::Bool(true),
141            }),
142            Err(..) => {
143                let d = de::ContentDeserializer::<D::Error>::new(content);
144                Ok(BoolOr::Data(T::deserialize(d)?))
145            }
146        }
147    }
148}