cairo_lang_filesystem/
cfg.rs1use std::collections::BTreeSet;
2use std::fmt;
3
4use serde::{Deserialize, Deserializer, Serialize, Serializer};
5
6#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
8pub struct Cfg {
9 pub key: String,
10 pub value: Option<String>,
11}
12
13impl Cfg {
14 pub fn name(name: impl Into<String>) -> Self {
16 Self { key: name.into(), value: None }
17 }
18
19 pub fn kv(key: impl Into<String>, value: impl Into<String>) -> Self {
21 Self { key: key.into(), value: Some(value.into()) }
22 }
23}
24
25impl fmt::Display for Cfg {
26 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27 write!(f, "{}", self.key)?;
28
29 if let Some(value) = &self.value {
30 write!(f, ": {value:?}")?;
31 }
32
33 Ok(())
34 }
35}
36
37impl fmt::Debug for Cfg {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 f.debug_tuple("Cfg").field(&DebugAsDisplay(&self)).finish()
40 }
41}
42
43mod serde_ext {
44 use serde::{Deserialize, Serialize};
45
46 #[derive(Serialize, Deserialize)]
47 #[serde(untagged)]
48 pub enum Cfg {
49 KV(String, String),
50 Name(String),
51 }
52}
53
54impl Serialize for Cfg {
55 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
56 let sd = if let Some(value) = &self.value {
57 serde_ext::Cfg::KV(self.key.clone(), value.clone())
58 } else {
59 serde_ext::Cfg::Name(self.key.clone())
60 };
61 sd.serialize(serializer)
62 }
63}
64
65impl<'de> Deserialize<'de> for Cfg {
66 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
67 let sd = serde_ext::Cfg::deserialize(deserializer)?;
68 match sd {
69 serde_ext::Cfg::KV(k, v) => Ok(Cfg::kv(k, v)),
70 serde_ext::Cfg::Name(name) => Ok(Cfg::name(name)),
71 }
72 }
73}
74
75#[derive(Clone, Default, Eq, Hash, PartialEq, Serialize, Deserialize)]
80pub struct CfgSet(BTreeSet<Cfg>);
81
82impl CfgSet {
83 pub fn new() -> Self {
87 Self(BTreeSet::new())
88 }
89
90 pub fn len(&self) -> usize {
92 self.0.len()
93 }
94
95 pub fn is_empty(&self) -> bool {
97 self.0.is_empty()
98 }
99
100 pub fn insert(&mut self, cfg: Cfg) {
102 self.0.insert(cfg);
103 }
104
105 pub fn union(&self, other: &Self) -> Self {
107 Self(self.0.union(&other.0).cloned().collect())
108 }
109
110 pub fn iter(&self) -> impl Iterator<Item = &Cfg> {
114 self.0.iter()
115 }
116
117 pub fn contains(&self, cfg: &Cfg) -> bool {
119 self.0.contains(cfg)
120 }
121
122 pub fn is_subset(&self, other: &Self) -> bool {
125 self.0.is_subset(&other.0)
126 }
127
128 pub fn is_superset(&self, other: &Self) -> bool {
131 other.is_subset(self)
132 }
133}
134
135impl IntoIterator for CfgSet {
136 type Item = Cfg;
137 type IntoIter = <BTreeSet<Cfg> as IntoIterator>::IntoIter;
138
139 fn into_iter(self) -> Self::IntoIter {
140 self.0.into_iter()
141 }
142}
143
144impl<'a> IntoIterator for &'a CfgSet {
145 type Item = &'a Cfg;
146 type IntoIter = <&'a BTreeSet<Cfg> as IntoIterator>::IntoIter;
147
148 fn into_iter(self) -> Self::IntoIter {
149 self.0.iter()
150 }
151}
152
153impl FromIterator<Cfg> for CfgSet {
154 fn from_iter<T: IntoIterator<Item = Cfg>>(iter: T) -> Self {
155 Self(FromIterator::from_iter(iter))
156 }
157}
158
159impl fmt::Debug for CfgSet {
160 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
161 let mut tuple = f.debug_tuple("CfgSet");
162 for cfg in &self.0 {
163 tuple.field(&DebugAsDisplay(cfg));
164 }
165 tuple.finish()
166 }
167}
168
169struct DebugAsDisplay<T>(T);
170
171impl<T: fmt::Display> fmt::Debug for DebugAsDisplay<T> {
172 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
173 fmt::Display::fmt(&self.0, f)
174 }
175}
176
177#[cfg(test)]
178mod tests {
179 use serde_json::json;
180
181 use crate::cfg::{Cfg, CfgSet};
182
183 #[test]
184 fn contains() {
185 let a = CfgSet::from_iter([Cfg::name("name"), Cfg::kv("k", "a"), Cfg::kv("k", "b")]);
186 assert!(a.contains(&Cfg::name("name")));
187 assert!(a.contains(&Cfg::kv("k", "a")));
188 assert!(a.contains(&Cfg::kv("k", "b")));
189 assert!(!a.contains(&Cfg::kv("k", "c")));
190 }
191
192 #[test]
193 fn is_superset() {
194 let a = CfgSet::from_iter([Cfg::name("name"), Cfg::kv("k", "a"), Cfg::kv("k", "b")]);
195 let b = CfgSet::from_iter([Cfg::name("name"), Cfg::kv("k", "a")]);
196 assert!(a.is_superset(&b));
197 }
198
199 #[test]
200 fn serde() {
201 let cfg = CfgSet::from_iter([
202 Cfg::name("name"),
203 Cfg::kv("k", "a"),
204 Cfg::name("name2"),
205 Cfg::kv("k", "b"),
206 ]);
207
208 let json = serde_json::to_value(&cfg).unwrap();
209
210 assert_eq!(json, json!([["k", "a"], ["k", "b"], "name", "name2"]));
211
212 let serde_cfg = serde_json::from_value::<CfgSet>(json).unwrap();
213
214 assert_eq!(serde_cfg, cfg);
215 }
216}