keyvalues_parser/
lib.rs

1#![doc = include_str!("../README.md")]
2#![allow(unknown_lints)]
3#![allow(clippy::result_large_err)]
4// TODO: resolve this ^^
5
6use std::{
7    borrow::Cow,
8    collections::{btree_map::IntoIter, BTreeMap},
9    ops::{Deref, DerefMut},
10};
11
12pub mod error;
13pub mod text;
14
15/// A Key is simply an alias for `Cow<str>`
16pub type Key<'a> = Cow<'a, str>;
17
18/// A loosely typed representation of VDF text
19///
20/// `Vdf` is represented as a single [`Key`] mapped to a single [`Value`]
21///
22/// ## Parse
23///
24/// `Vdf`s will generally be created through the use of [`Vdf::parse()`] which takes a string
25/// representing VDF text and attempts to parse it to a `Vdf` representation.
26///
27/// ## Mutate
28///
29/// From there you can manipulate/extract from the representation as desired by using the standard
30/// conventions on the internal types (plain old `BTreeMap`s, `Vec`s, and `Cow`s all the way down)
31///
32/// ## Render
33///
34/// The `Vdf` can also be rendered back to its text form through its `Display` implementation
35///
36/// ## Example
37///
38/// ```
39/// use keyvalues_parser::Vdf;
40///
41/// // Parse
42/// let vdf_text = r#"
43/// "Outer Key"
44/// {
45///     "Inner Key" "Inner Value"
46///     "Inner Key"
47///     {
48///     }
49/// }
50/// "#;
51/// let mut parsed = Vdf::parse(vdf_text)?;
52///
53/// // Mutate: i.e. remove the last "Inner Key" pair
54/// parsed
55///     .value
56///     .get_mut_obj()
57///     .unwrap()
58///     .get_mut("Inner Key")
59///     .unwrap()
60///     .pop();
61///
62/// // Render: prints
63/// // "Outer Key"
64/// // {
65/// //     "Inner Key" "Inner Value"
66/// // }
67/// println!("{}", parsed);
68/// # Ok::<(), keyvalues_parser::error::Error>(())
69/// ```
70#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
71pub struct Vdf<'a> {
72    pub key: Key<'a>,
73    pub value: Value<'a>,
74}
75
76impl<'a> From<PartialVdf<'a>> for Vdf<'a> {
77    fn from(partial: PartialVdf<'a>) -> Self {
78        Self {
79            key: partial.key,
80            value: partial.value,
81        }
82    }
83}
84
85// TODO: Just store a `Vdf` internally?
86// TODO: don't expose these publicly?
87#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
88pub struct PartialVdf<'a> {
89    pub key: Key<'a>,
90    pub value: Value<'a>,
91    pub bases: Vec<Cow<'a, str>>,
92}
93
94impl<'a> Vdf<'a> {
95    /// Creates a [`Vdf`] using a provided key and value
96    ///
97    /// ```
98    /// use keyvalues_parser::{Vdf, Value};
99    /// use std::borrow::Cow;
100    ///
101    /// let vdf = Vdf::new(Cow::from("Much Key"), Value::Str(Cow::from("Such Wow")));
102    /// // prints
103    /// // "Much Key"  "Such Wow"
104    /// println!("{}", vdf);
105    /// ```
106    pub fn new(key: Key<'a>, value: Value<'a>) -> Self {
107        Self { key, value }
108    }
109}
110
111type ObjInner<'a> = BTreeMap<Key<'a>, Vec<Value<'a>>>;
112type ObjInnerPair<'a> = (Key<'a>, Vec<Value<'a>>);
113
114#[derive(Debug, Clone, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
115pub struct Obj<'a>(pub ObjInner<'a>);
116
117impl<'a> Obj<'a> {
118    /// Creates an empty object value
119    ///
120    /// Internally This is just a [`BTreeMap`] that maps [`Key`]s to a [`Vec`] of [`Value`]s
121    ///
122    /// ```
123    /// # use keyvalues_parser::{Obj, Value};
124    /// # use std::borrow::Cow;
125    /// let mut obj = Obj::new();
126    /// obj.insert(
127    ///     Cow::from("key"),
128    ///     vec![]
129    /// );
130    /// obj.insert(
131    ///     Cow::from("earlier key"),
132    ///     vec![Value::Obj(Obj::default())]
133    /// );
134    ///
135    /// // It's a b-tree map so the entries are sorted by keys
136    /// assert_eq!(
137    ///     obj.keys().collect::<Vec<_>>(),
138    ///     ["earlier key", "key"]
139    /// );
140    /// ```
141    pub fn new() -> Self {
142        Self::default()
143    }
144
145    /// Returns the inner [`BTreeMap`]
146    ///
147    /// ```
148    /// # use keyvalues_parser::{Obj, Value};
149    /// # use std::{borrow::Cow, collections::BTreeMap};
150    /// let mut obj = Obj::new();
151    /// obj.insert(Cow::from("much key"), vec![]);
152    ///
153    /// let inner: BTreeMap<_, _> = obj.into_inner();
154    /// // Prints:
155    /// // {
156    /// //     "much key": [],
157    /// // }
158    /// println!("{:#?}", inner);
159    /// ```
160    pub fn into_inner(self) -> ObjInner<'a> {
161        self.0
162    }
163
164    /// Creates an iterator that returns the [`Vdf`]s that compose the object
165    ///
166    /// This is notably different compared to just iterating over the `BTreeMap`s items because it
167    /// will emit a [`Vdf`] for each key-value pair while the actual items are key-values pairs.
168    /// This means that empty values will not emit a [`Vdf`] at all, and a pair that has multiple
169    /// entries in values will emit a [`Vdf`] for each pairing
170    ///
171    /// ```
172    /// # use keyvalues_parser::{Obj, Value, Vdf};
173    /// # use std::borrow::Cow;
174    /// let mut obj = Obj::new();
175    /// obj.insert(
176    ///     Cow::from("no values"),
177    ///     vec![]
178    /// );
179    /// obj.insert(
180    ///     Cow::from("multiple values"),
181    ///     vec![Value::Str(Cow::from("first")), Value::Str(Cow::from("second"))]
182    /// );
183    ///
184    /// let vdfs: Vec<_> = obj.into_vdfs().collect();
185    /// assert_eq!(
186    ///     vdfs,
187    ///     [
188    ///         Vdf {
189    ///             key: Cow::from("multiple values"),
190    ///             value: Value::Str(Cow::from("first"))
191    ///         },
192    ///         Vdf {
193    ///             key: Cow::from("multiple values"),
194    ///             value: Value::Str(Cow::from("second"))
195    ///         },
196    ///     ]
197    /// );
198    /// ```
199    pub fn into_vdfs(self) -> IntoVdfs<'a> {
200        IntoVdfs::new(self)
201    }
202}
203
204impl<'a> FromIterator<ObjInnerPair<'a>> for Obj<'a> {
205    fn from_iter<T: IntoIterator<Item = ObjInnerPair<'a>>>(iter: T) -> Self {
206        let mut inner = BTreeMap::new();
207        for (key, values) in iter {
208            inner.insert(key, values);
209        }
210
211        Self(inner)
212    }
213}
214
215impl<'a> Deref for Obj<'a> {
216    type Target = ObjInner<'a>;
217
218    fn deref(&self) -> &Self::Target {
219        &self.0
220    }
221}
222
223impl<'a> DerefMut for Obj<'a> {
224    fn deref_mut(&mut self) -> &mut Self::Target {
225        &mut self.0
226    }
227}
228
229/// An iterator over an [`Obj`]'s [`Vdf`] pairs
230///
231/// Typically created by calling [`Obj::into_vdfs`] on an existing object
232pub struct IntoVdfs<'a> {
233    // TODO: can this just store an iterator for the values instead of `.collect()`ing
234    current_entry: Option<ObjInnerPair<'a>>,
235    it: IntoIter<Key<'a>, Vec<Value<'a>>>,
236}
237
238impl<'a> IntoVdfs<'a> {
239    fn new(obj: Obj<'a>) -> Self {
240        Self {
241            current_entry: None,
242            it: obj.into_inner().into_iter(),
243        }
244    }
245}
246
247impl<'a> Iterator for IntoVdfs<'a> {
248    type Item = Vdf<'a>;
249
250    fn next(&mut self) -> Option<Self::Item> {
251        // Iteration will pop the first pair off `current_entry` if it's set and then falls back to
252        // reading in a new `current_entry` from `it`. If `it` is exhausted then we're done
253        loop {
254            match self.current_entry.take() {
255                // There is a pair to return
256                Some((key, mut values)) if !values.is_empty() => {
257                    let value = values.pop().expect("values isn't empty");
258                    self.current_entry = Some((key.clone(), values));
259                    return Some(Vdf::new(key, value));
260                }
261                _ => {
262                    let (key, values) = self.it.next()?;
263                    // Store the next entry. Flip the values so that `pop`ing returns correct order
264                    self.current_entry = Some((key, values.into_iter().rev().collect()));
265                }
266            }
267        }
268    }
269}
270
271/// Enum representing all valid VDF values
272///
273/// VDF is composed of [`Key`]s and their respective [`Value`]s where this represents the latter. A
274/// value is either going to be a `Str(Cow<str>)`, or an `Obj(Obj)` that contains a list of keys
275/// and values.
276///
277/// ```
278/// # use keyvalues_parser::{Obj, Value};
279/// # use std::borrow::Cow;
280/// let value_str = Value::Str(Cow::from("some text"));
281/// let value_obj = Value::Obj(Obj::new());
282/// ```
283#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
284pub enum Value<'a> {
285    Str(Cow<'a, str>),
286    Obj(Obj<'a>),
287}
288
289impl<'a> Value<'a> {
290    /// Returns if the current value is the `Str` variant
291    ///
292    /// ```
293    /// use std::borrow::Cow;
294    /// use keyvalues_parser::{Obj, Value};
295    ///
296    /// let value_str = Value::Str(Cow::default());
297    /// assert!(value_str.is_str());
298    /// ```
299    pub fn is_str(&self) -> bool {
300        self.get_str().is_some()
301    }
302
303    /// Returns if the current value is the `Obj` variant
304    ///
305    /// ```
306    /// use keyvalues_parser::{Obj, Value};
307    ///
308    /// let value_obj = Value::Obj(Obj::default());
309    /// assert!(value_obj.is_obj());
310    /// ```
311    pub fn is_obj(&self) -> bool {
312        self.get_obj().is_some()
313    }
314
315    /// Gets the inner `&str` if this is a `Value::Str`
316    ///
317    /// ```
318    /// # use keyvalues_parser::Value;
319    /// # use std::borrow::Cow;
320    /// let value = Value::Str(Cow::from("some text"));
321    ///
322    /// if let Some(s) = value.get_str() {
323    ///     println!("value str: {}", s);
324    /// }
325    /// ```
326    pub fn get_str(&self) -> Option<&str> {
327        if let Self::Str(s) = self {
328            Some(s)
329        } else {
330            None
331        }
332    }
333
334    /// Gets the inner `&Obj` if this value is a `Value::Obj`
335    ///
336    /// ```
337    /// # use keyvalues_parser::{Obj, Value};
338    /// let value = Value::Obj(Obj::new());
339    ///
340    /// if let Some(obj) = value.get_obj() {
341    ///     println!("value obj: {:?}", obj);
342    /// }
343    /// ```
344    pub fn get_obj(&self) -> Option<&Obj> {
345        if let Self::Obj(obj) = self {
346            Some(obj)
347        } else {
348            None
349        }
350    }
351
352    /// Gets the inner `&mut str` if this is a `Value::Str`
353    ///
354    /// ```
355    /// # use keyvalues_parser::Value;
356    /// # use std::borrow::Cow;
357    /// let mut value = Value::Str(Cow::from("some text"));
358    /// let mut inner_str = value.get_mut_str().unwrap();
359    /// inner_str.to_mut().make_ascii_uppercase();
360    ///
361    /// assert_eq!(
362    ///     value,
363    ///     Value::Str(Cow::from("SOME TEXT"))
364    /// );
365    /// ```
366    pub fn get_mut_str(&mut self) -> Option<&mut Cow<'a, str>> {
367        if let Self::Str(s) = self {
368            Some(s)
369        } else {
370            None
371        }
372    }
373
374    /// Gets the inner `&mut Obj` if this is a `Value::Obj`
375    ///
376    /// ```
377    /// # use keyvalues_parser::{Obj, Value};
378    /// # use std::borrow::Cow;
379    /// let mut value = Value::Obj(Obj::new());
380    /// let mut inner_obj = value.get_mut_obj().unwrap();
381    /// inner_obj.insert(Cow::from("new key"), vec![]);
382    ///
383    /// // Prints:
384    /// // Value::Obj({
385    /// //    "new key": [],
386    /// // })
387    /// println!("{:?}", value);
388    /// ```
389    pub fn get_mut_obj(&mut self) -> Option<&mut Obj<'a>> {
390        if let Self::Obj(obj) = self {
391            Some(obj)
392        } else {
393            None
394        }
395    }
396
397    /// Unwraps the `Cow<str>` from the `Value::Str`
398    ///
399    /// # Panics
400    ///
401    /// If the variant was `Value::Obj`
402    ///
403    /// # Examples
404    ///
405    /// ```
406    /// use keyvalues_parser::Value;
407    /// use std::borrow::Cow;
408    ///
409    /// let value = Value::Str(Cow::from("Sample text"));
410    /// assert_eq!(value.unwrap_str(), "Sample text");
411    /// ```
412    ///
413    /// ```should_panic
414    /// use keyvalues_parser::{Value, Obj};
415    ///
416    /// let value = Value::Obj(Obj::new());
417    /// value.unwrap_str(); // <-- panics
418    /// ```
419    pub fn unwrap_str(self) -> Cow<'a, str> {
420        self.expect_str("Called `unwrap_str` on a `Value::Obj` variant")
421    }
422
423    /// Unwraps the [`Obj`] from the `Value::Obj`
424    ///
425    /// # Panics
426    ///
427    /// If the variant was `Value::Str`
428    ///
429    /// # Examples
430    ///
431    /// ```
432    /// use keyvalues_parser::{Obj, Value};
433    ///
434    /// let value = Value::Obj(Obj::new());
435    /// assert_eq!(value.unwrap_obj(), Obj::new());
436    /// ```
437    ///
438    /// ```should_panic
439    /// use keyvalues_parser::Value;
440    /// use std::borrow::Cow;
441    ///
442    /// let value = Value::Str(Cow::from("D'Oh"));
443    /// value.unwrap_obj(); // <-- panics
444    /// ```
445    pub fn unwrap_obj(self) -> Obj<'a> {
446        self.expect_obj("Called `unwrap_obj` on a `Value::Str` variant")
447    }
448
449    /// Refer to [Value::unwrap_str]. Same situation, but with a custom message
450    pub fn expect_str(self, msg: &str) -> Cow<'a, str> {
451        if let Self::Str(s) = self {
452            s
453        } else {
454            panic!("{}", msg)
455        }
456    }
457
458    /// Refer to [Value::unwrap_obj]. Same situation, but with a custom message
459    pub fn expect_obj(self, msg: &str) -> Obj<'a> {
460        if let Self::Obj(obj) = self {
461            obj
462        } else {
463            panic!("{}", msg)
464        }
465    }
466}