@@ -19,6 +19,75 @@ 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+
84+ #[ derive( Clone , Debug , PartialEq , Eq , Hash , PartialOrd , Ord ) ]
85+ pub struct TopLevelVdf < ' text > {
86+ pub key : Key < ' text > ,
87+ pub value : Value < ' text > ,
88+ pub bases : Vec < Cow < ' text , str > > ,
89+ }
90+
2291/// A Key is simply an alias for `Cow<str>`
2392pub type Key < ' text > = Cow < ' text , str > ;
2493
@@ -28,8 +97,8 @@ pub type Key<'text> = Cow<'text, str>;
2897///
2998/// ## Parse
3099///
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.
100+ /// `Vdf`s will generally be created through the use of [`parse()`] or [`Parser ::parse()`] which
101+ /// takes a string representing VDF text and attempts to parse it to a `Vdf` representation.
33102///
34103/// ## Mutate
35104///
@@ -43,8 +112,6 @@ pub type Key<'text> = Cow<'text, str>;
43112/// ## Example
44113///
45114/// ```
46- /// use keyvalues_parser::Vdf;
47- ///
48115/// // Parse
49116/// let vdf_text = r#"
50117/// "Outer Key"
@@ -55,7 +122,7 @@ pub type Key<'text> = Cow<'text, str>;
55122/// }
56123/// }
57124/// "#;
58- /// let mut parsed = Vdf ::parse(vdf_text)?;
125+ /// let mut parsed = keyvalues_parser ::parse(vdf_text)?;
59126///
60127/// // Mutate: i.e. remove the last "Inner Key" pair
61128/// parsed
@@ -80,24 +147,6 @@ pub struct Vdf<'text> {
80147 pub value : Value < ' text > ,
81148}
82149
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-
101150impl < ' text > Vdf < ' text > {
102151 /// Creates a [`Vdf`] using a provided key and value
103152 ///
@@ -115,6 +164,23 @@ impl<'text> Vdf<'text> {
115164 }
116165}
117166
167+ impl < ' text > From < PartialVdf < ' text > > for Vdf < ' text > {
168+ fn from ( partial : PartialVdf < ' text > ) -> Self {
169+ Self {
170+ key : partial. key ,
171+ value : partial. value ,
172+ }
173+ }
174+ }
175+
176+ // TODO: Just store a `Vdf` internally?
177+ #[ derive( Clone , Debug , PartialEq , Eq , Hash , PartialOrd , Ord ) ]
178+ pub struct PartialVdf < ' text > {
179+ pub key : Key < ' text > ,
180+ pub value : Value < ' text > ,
181+ pub bases : Vec < Cow < ' text , str > > ,
182+ }
183+
118184// TODO: why is this type alias a thing if it's not private but the usage of it inside `Obj` is?
119185type ObjInner < ' text > = BTreeMap < Key < ' text > , Vec < Value < ' text > > > ;
120186type ObjInnerPair < ' text > = ( Key < ' text > , Vec < Value < ' text > > ) ;
0 commit comments