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