1mod iter;
2
3pub use iter::*;
4
5use crate::rawvalue::RawValue;
6use crate::{PropertyKey, PropertyValue};
7
8#[derive(Clone, Default)]
16pub struct Properties {
17 pairs: Vec<(String, RawValue)>,
22 idxes: Vec<usize>,
25 }
29
30impl Properties {
33 pub const fn new() -> Properties {
35 Properties {
36 pairs: Vec::new(),
37 idxes: Vec::new(),
38 }
39 }
40
41 pub fn len(&self) -> usize {
43 self.pairs.len()
44 }
45
46 pub fn is_empty(&self) -> bool {
48 self.pairs.is_empty()
49 }
50
51 fn find_idx(&self, key: &str) -> Result<usize, usize> {
54 self.idxes
55 .as_slice()
56 .binary_search_by_key(&key, |ki| self.pairs[*ki].0.as_str())
57 .map(|idx| self.idxes[idx])
58 }
59
60 pub fn get_raw_for_key(&self, key: impl AsRef<str>) -> &RawValue {
64 self.find_idx(key.as_ref())
65 .ok()
66 .map_or(&crate::rawvalue::UNSET, |idx| &self.pairs[idx].1)
67 }
68
69 pub fn get_raw<T: PropertyKey>(&self) -> &RawValue {
73 self.get_raw_for_key(T::key())
74 }
75
76 pub fn get<T: PropertyKey + PropertyValue>(&self) -> Result<T, &RawValue> {
80 let retval = self.get_raw::<T>();
81 retval.parse::<T>().or(Err(retval))
82 }
83
84 pub fn iter(&self) -> Iter<'_> {
92 Iter(self.pairs.iter())
93 }
94
95 pub fn iter_mut(&mut self) -> IterMut<'_> {
103 IterMut(self.pairs.iter_mut())
104 }
105
106 fn get_at_mut(&mut self, idx: usize) -> &mut RawValue {
107 &mut self.pairs.get_mut(idx).unwrap().1
108 }
109
110 fn insert_at(&mut self, idx: usize, key: String, val: RawValue) {
111 self.idxes.insert(idx, self.pairs.len());
112 self.pairs.push((key, val));
113 }
114
115 pub fn insert_raw_for_key(&mut self, key: impl AsRef<str>, val: impl Into<RawValue>) {
117 let key_str = key.as_ref();
118 match self.find_idx(key_str) {
119 Ok(idx) => {
120 *self.get_at_mut(idx) = val.into();
121 }
122 Err(idx) => {
123 self.insert_at(idx, key_str.to_owned(), val.into());
124 }
125 }
126 }
127
128 pub fn insert_raw<K: PropertyKey, V: Into<RawValue>>(&mut self, val: V) {
130 self.insert_raw_for_key(K::key(), val)
131 }
132
133 pub fn insert<T: PropertyKey + Into<RawValue>>(&mut self, prop: T) {
135 self.insert_raw_for_key(T::key(), prop.into())
136 }
137
138 pub fn try_insert_raw_for_key(
143 &mut self,
144 key: impl AsRef<str>,
145 value: impl Into<RawValue>,
146 ) -> Result<(), &mut RawValue> {
147 let key_str = key.as_ref();
148 #[allow(clippy::unit_arg)]
149 match self.find_idx(key_str) {
150 Ok(idx) => {
151 let valref = self.get_at_mut(idx);
152 if valref.is_unset() {
153 *valref = value.into();
154 Ok(())
155 } else {
156 Err(valref)
157 }
158 }
159 Err(idx) => Ok(self.insert_at(idx, key_str.to_owned(), value.into())),
160 }
161 }
162
163 pub fn try_insert_raw<K: PropertyKey, V: Into<RawValue>>(
168 &mut self,
169 val: V,
170 ) -> Result<(), &mut RawValue> {
171 self.try_insert_raw_for_key(K::key(), val)
172 }
173
174 pub fn try_insert<T: PropertyKey + Into<RawValue>>(
179 &mut self,
180 prop: T,
181 ) -> Result<(), &mut RawValue> {
182 self.try_insert_raw_for_key(T::key(), prop.into())
183 }
184
185 pub fn use_fallbacks(&mut self) {
190 crate::fallback::add_fallbacks(self, false)
191 }
192
193 pub fn use_fallbacks_legacy(&mut self) {
199 crate::fallback::add_fallbacks(self, true)
200 }
201}
202
203impl PartialEq for Properties {
204 fn eq(&self, other: &Self) -> bool {
205 if self.len() != other.len() {
206 return false;
207 }
208 self.idxes
209 .iter()
210 .zip(other.idxes.iter())
211 .all(|(idx_s, idx_o)| self.pairs[*idx_s] == other.pairs[*idx_o])
212 }
213}
214
215impl Eq for Properties {}
216
217impl std::fmt::Debug for Properties {
218 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
219 f.debug_tuple("Properties")
220 .field(&self.pairs.as_slice())
221 .finish()
222 }
223}
224
225impl<'a> IntoIterator for &'a Properties {
226 type Item = <Iter<'a> as Iterator>::Item;
227
228 type IntoIter = Iter<'a>;
229
230 fn into_iter(self) -> Self::IntoIter {
231 self.iter()
232 }
233}
234
235impl<'a> IntoIterator for &'a mut Properties {
236 type Item = <IterMut<'a> as Iterator>::Item;
237
238 type IntoIter = IterMut<'a>;
239
240 fn into_iter(self) -> Self::IntoIter {
241 self.iter_mut()
242 }
243}
244
245impl<K: AsRef<str>, V: Into<RawValue>> FromIterator<(K, V)> for Properties {
246 fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
247 let mut result = Properties::new();
248 result.extend(iter);
249 result
250 }
251}
252
253impl<K: AsRef<str>, V: Into<RawValue>> Extend<(K, V)> for Properties {
254 fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
255 let iter = iter.into_iter();
256 let min_len = iter.size_hint().0;
257 self.pairs.reserve(min_len);
258 self.idxes.reserve(min_len);
259 for (k, v) in iter {
260 let k = k.as_ref();
261 let v = v.into();
262 self.insert_raw_for_key(k, v);
263 }
264 }
265}
266
267pub trait PropertiesSource {
269 fn apply_to(
272 self,
273 props: &mut Properties,
274 path: impl AsRef<std::path::Path>,
275 ) -> Result<(), crate::Error>;
276}
277
278impl<'a> PropertiesSource for &'a Properties {
279 fn apply_to(
280 self,
281 props: &mut Properties,
282 _: impl AsRef<std::path::Path>,
283 ) -> Result<(), crate::Error> {
284 props.extend(self.pairs.iter().cloned());
285 Ok(())
286 }
287}