url_cleaner_engine/types/
map.rs1use std::collections::{HashMap, HashSet};
6
7use serde::{Serialize, Deserialize};
8use serde_with::{serde_as, MapPreventDuplicates, SetPreventDuplicates};
9
10use crate::util::*;
11
12#[serde_as]
16#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Suitability)]
17#[serde(deny_unknown_fields)]
18pub struct Map<T> {
19 #[serde_as(as = "MapPreventDuplicates<_, _>")]
21 pub map: HashMap<String, T>,
22 #[serde(default = "Option::default", skip_serializing_if = "Option::is_none")]
24 pub if_none: Option<Box<T>>,
25 #[serde(default = "Option::default", skip_serializing_if = "Option::is_none")]
27 pub r#else: Option<Box<T>>
28}
29
30impl<T> Map<T> {
31 pub fn with_capacity(capacity: usize) -> Self {
33 Map {
34 map : HashMap::with_capacity(capacity),
35 if_none: None,
36 r#else : None
37 }
38 }
39
40 pub fn get<U: AsRef<str>>(&self, key: Option<U>) -> Option<&T> {
46 match key {
47 Some(key) => self.map.get(key.as_ref()),
48 None => self.if_none.as_deref()
49 }.or(self.r#else.as_deref())
50 }
51}
52
53impl<T> Default for Map<T> {
54 fn default() -> Self {
55 Self {
56 map : Default::default(),
57 if_none: Default::default(),
58 r#else : Default::default()
59 }
60 }
61}
62
63#[serde_as]
65#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, Suitability)]
66pub struct MapDiff<T> {
67 #[serde_as(as = "MapPreventDuplicates<_, _>")]
69 #[serde(default, bound(serialize = "T: Serialize", deserialize = "T: Deserialize<'de>"))]
70 pub insert: HashMap<String, T>,
71 #[serde_as(as = "SetPreventDuplicates<_>")]
73 #[serde(default)]
74 pub remove: HashSet<String>
75}
76
77impl<T> MapDiff<T> {
78 pub fn apply_once(self, to: &mut Map<T>) {
82 to.map.extend(self.insert);
83 to.map.retain(|k, _| !self.remove.contains(k));
84 }
85}
86
87impl<T: Clone> MapDiff<T> {
88 pub fn apply_multiple(&self, to: &mut Map<T>) {
92 to.map.extend(self.insert.iter().map(|(k, v)| (k.clone(), v.clone())));
93 to.map.retain(|k, _| !self.remove.contains(k));
94 }
95}
96
97impl<T, const N: usize> From<[(String, T); N]> for Map<T> {
98 fn from(value: [(String, T); N]) -> Self {
99 Self {
100 map: value.into(),
101 if_none: None,
102 r#else: None
103 }
104 }
105}
106
107impl<T, const N: usize> From<[(Option<String>, T); N]> for Map<T> {
108 fn from(value: [(Option<String>, T); N]) -> Self {
109 let mut ret = Self {
110 map: HashMap::with_capacity(N),
111 if_none: None,
112 r#else: None
113 };
114
115 for (k, v) in value {
116 match k {
117 Some(k) => {ret.map.insert(k, v);},
118 None => ret.if_none = Some(Box::new(v))
119 }
120 }
121
122 ret
123 }
124}
125
126impl<T> From<HashMap<String, T>> for Map<T> {
127 fn from(value: HashMap<String, T>) -> Self {
128 Self {
129 map: value,
130 if_none: None,
131 r#else: None
132 }
133 }
134}
135
136impl<T> From<HashMap<Option<String>, T>> for Map<T> {
137 fn from(value: HashMap<Option<String>, T>) -> Self {
138 let mut ret = Self {
139 map: HashMap::with_capacity(value.len()),
140 if_none: None,
141 r#else: None
142 };
143
144 for (k, v) in value {
145 match k {
146 Some(k) => {ret.map.insert(k, v);},
147 None => ret.if_none = Some(Box::new(v))
148 }
149 }
150
151 ret
152 }
153}
154
155impl<T> FromIterator<(String, T)> for Map<T> {
156 fn from_iter<I: IntoIterator<Item = (String, T)>>(iter: I) -> Self {
157 Self {
158 map: iter.into_iter().collect(),
159 if_none: None,
160 r#else: None
161 }
162 }
163}
164
165impl<T> FromIterator<(Option<String>, T)> for Map<T> {
166 fn from_iter<I: IntoIterator<Item = (Option<String>, T)>>(iter: I) -> Self {
167 let iter = iter.into_iter();
168 let size_hint = iter.size_hint();
169 let mut ret = Self {
170 map: HashMap::with_capacity(size_hint.1.unwrap_or(size_hint.0)),
171 if_none: None,
172 r#else: None
173 };
174 for (k, v) in iter {
175 match k {
176 Some(k) => {ret.map.insert(k, v);},
177 None => ret.if_none = Some(Box::new(v))
178 }
179 }
180 ret
181 }
182}