@@ -19,6 +19,68 @@ pub mod text;
1919/// `pest` re-exported for your convenience :)
2020pub use pest;
2121
22+ /// Parse a KeyValues document to a loosely typed representation
23+ ///
24+ /// This is shorthand for parsing a document with default settings aka `Parser::new().parse(text)`
25+ pub fn parse < ' text > ( text : & ' text str ) -> error:: Result < PartialVdf < ' text > > {
26+ Parser :: new ( ) . parse ( text)
27+ }
28+
29+ /// A configurable KeyValues parser allowing for adjusting settings before parsing
30+ #[ derive( Clone , Debug , Default ) ]
31+ pub struct Parser {
32+ literal_special_chars : bool ,
33+ }
34+
35+ impl Parser {
36+ /// Constructs a default parser
37+ ///
38+ /// Currently this consists of:
39+ ///
40+ /// | Toggle | Description |
41+ /// | :---: | :--- |
42+ /// | [`Parser::literal_special_chars()`] | Whether to interpret `\` in strings as the start of an escaped special character, or a literal `\` |
43+ pub const fn new ( ) -> Self {
44+ // same as Default, but const 😏
45+ Self {
46+ literal_special_chars : false ,
47+ }
48+ }
49+
50+ /// Toggle how to interpret `\` in strings
51+ ///
52+ /// By default (`false`) the parser will interpret backslashes (`\`) in strings as the start of
53+ /// an escaped special character (e.g. `\\` -> `\`, `\"` -> `"`). When `true` the parser will
54+ /// instead interpret backslashes (`\`) as a literal backslash. Commonly seen with
55+ /// windows-paths, for instance
56+ pub const fn literal_special_chars ( mut self , yes : bool ) -> Self {
57+ self . literal_special_chars = yes;
58+ self
59+ }
60+
61+ /// Parse a KeyValues document to a loosely typed representation
62+ ///
63+ /// # Example
64+ ///
65+ /// ```
66+ /// use keyvalues_parser::Parser;
67+ /// let vdf = Parser::new()
68+ /// .literal_special_chars(true)
69+ /// .parse(r"InstallDir C:\You\Later")
70+ /// .unwrap();
71+ /// assert_eq!(vdf.value.unwrap_str(), r"C:\You\Later");
72+ /// ```
73+ pub fn parse < ' text > ( & self , vdf : & ' text str ) -> error:: Result < PartialVdf < ' text > > {
74+ if self . literal_special_chars {
75+ #[ expect( deprecated) ] // deprecated for thee, but not for me!
76+ text:: parse:: raw_parse ( vdf)
77+ } else {
78+ #[ expect( deprecated) ] // deprecated for thee, but not for me!
79+ text:: parse:: escaped_parse ( vdf)
80+ }
81+ }
82+ }
83+
2284/// A Key is simply an alias for `Cow<str>`
2385pub type Key < ' text > = Cow < ' text , str > ;
2486
@@ -28,8 +90,8 @@ pub type Key<'text> = Cow<'text, str>;
2890///
2991/// ## Parse
3092///
31- /// `Vdf`s will generally be created through the use of [`Vdf ::parse()`] which takes a string
32- /// representing VDF text and attempts to parse it to a `Vdf` representation.
93+ /// `Vdf`s will generally be created through the use of [`parse()`] or [`Parser ::parse()`] which
94+ /// takes a string representing VDF text and attempts to parse it to a `Vdf` representation.
3395///
3496/// ## Mutate
3597///
@@ -43,8 +105,6 @@ pub type Key<'text> = Cow<'text, str>;
43105/// ## Example
44106///
45107/// ```
46- /// use keyvalues_parser::Vdf;
47- ///
48108/// // Parse
49109/// let vdf_text = r#"
50110/// "Outer Key"
@@ -55,7 +115,7 @@ pub type Key<'text> = Cow<'text, str>;
55115/// }
56116/// }
57117/// "#;
58- /// let mut parsed = Vdf ::parse(vdf_text)?;
118+ /// let mut parsed = keyvalues_parser ::parse(vdf_text)?;
59119///
60120/// // Mutate: i.e. remove the last "Inner Key" pair
61121/// parsed
@@ -80,24 +140,6 @@ pub struct Vdf<'text> {
80140 pub value : Value < ' text > ,
81141}
82142
83- impl < ' text > From < PartialVdf < ' text > > for Vdf < ' text > {
84- fn from ( partial : PartialVdf < ' text > ) -> Self {
85- Self {
86- key : partial. key ,
87- value : partial. value ,
88- }
89- }
90- }
91-
92- // TODO: Just store a `Vdf` internally?
93- // TODO: don't expose these publicly?
94- #[ derive( Clone , Debug , PartialEq , Eq , Hash , PartialOrd , Ord ) ]
95- pub struct PartialVdf < ' text > {
96- pub key : Key < ' text > ,
97- pub value : Value < ' text > ,
98- pub bases : Vec < Cow < ' text , str > > ,
99- }
100-
101143impl < ' text > Vdf < ' text > {
102144 /// Creates a [`Vdf`] using a provided key and value
103145 ///
@@ -115,6 +157,23 @@ impl<'text> Vdf<'text> {
115157 }
116158}
117159
160+ impl < ' text > From < PartialVdf < ' text > > for Vdf < ' text > {
161+ fn from ( partial : PartialVdf < ' text > ) -> Self {
162+ Self {
163+ key : partial. key ,
164+ value : partial. value ,
165+ }
166+ }
167+ }
168+
169+ // TODO: Just store a `Vdf` internally?
170+ #[ derive( Clone , Debug , PartialEq , Eq , Hash , PartialOrd , Ord ) ]
171+ pub struct PartialVdf < ' text > {
172+ pub key : Key < ' text > ,
173+ pub value : Value < ' text > ,
174+ pub bases : Vec < Cow < ' text , str > > ,
175+ }
176+
118177// TODO: why is this type alias a thing if it's not private but the usage of it inside `Obj` is?
119178type ObjInner < ' text > = BTreeMap < Key < ' text > , Vec < Value < ' text > > > ;
120179type ObjInnerPair < ' text > = ( Key < ' text > , Vec < Value < ' text > > ) ;
0 commit comments