Skip to main content

keyvalues_serde/de/
mod.rs

1//! Deserialize VDF text to Rust types
2
3mod map;
4mod seq;
5
6use keyvalues_parser::{parse, Key, Parser, Vdf};
7use serde_core::{
8    de::{self, DeserializeOwned, IntoDeserializer, Visitor},
9    Deserialize,
10};
11
12use std::{
13    borrow::Cow,
14    io::Read,
15    iter::Peekable,
16    ops::{Deref, DerefMut},
17    vec::IntoIter,
18};
19
20use crate::{
21    de::{map::ObjEater, seq::SeqBuilder},
22    error::{Error, Result},
23    tokens::{tokens_from_vdf, Token},
24};
25
26pub fn from_reader<R: Read, T: DeserializeOwned>(rdr: R) -> Result<T> {
27    from_reader_with_key(rdr).map(|(t, _)| t)
28}
29
30pub fn from_reader_with_key<R: Read, T: DeserializeOwned>(mut rdr: R) -> Result<(T, String)> {
31    let mut buffer = String::new();
32    rdr.read_to_string(&mut buffer)?;
33
34    from_str_with_key(&buffer).map(|(t, key)| (t, key.into_owned()))
35}
36
37/// Attempts to deserialize a string of VDF text to some type T
38pub fn from_str<'a, T: Deserialize<'a>>(s: &'a str) -> Result<T> {
39    from_str_with_key(s).map(|(t, _)| t)
40}
41
42/// The same as [`from_str()`], but also returns the top level VDF key
43pub fn from_str_with_key<'a, T: Deserialize<'a>>(s: &'a str) -> Result<(T, Key<'a>)> {
44    let vdf = parse(s)?.into();
45    from_vdf_with_key(vdf)
46}
47
48/// Attempts to deserialize a string of VDF text to some type T, without parsing escape sequences
49pub fn from_str_raw<'a, T: Deserialize<'a>>(s: &'a str) -> Result<T> {
50    from_str_raw_with_key(s).map(|(t, _)| t)
51}
52
53/// The same as [`from_str_raw()`], but also returns the top level VDF key
54pub fn from_str_raw_with_key<'a, T: Deserialize<'a>>(s: &'a str) -> Result<(T, Key<'a>)> {
55    let vdf = Parser::new().literal_special_chars(true).parse(s)?.into();
56    from_vdf_with_key(vdf)
57}
58
59pub fn from_vdf<'a, T: Deserialize<'a>>(vdf: Vdf<'a>) -> Result<T> {
60    from_vdf_with_key(vdf).map(|(t, _)| t)
61}
62
63pub fn from_vdf_with_key<'a, T: Deserialize<'a>>(vdf: Vdf<'a>) -> Result<(T, Key<'a>)> {
64    let (mut deserializer, key) = Deserializer::new_with_key(vdf)?;
65    let t = T::deserialize(&mut deserializer)?;
66
67    #[expect(deprecated)]
68    if deserializer.is_empty() {
69        Ok((t, key))
70    } else {
71        Err(Error::TrailingTokens)
72    }
73}
74
75/// The struct that handles deserializing VDF into Rust structs
76///
77/// This typically doesn't need to be invoked directly when [`from_str()`] and
78/// [`from_str_with_key()`] can be used instead
79#[derive(Debug)]
80pub struct Deserializer<'de> {
81    tokens: Peekable<IntoIter<Token<'de>>>,
82}
83
84// TODO: almost none of these should be `pub`
85impl<'de> Deserializer<'de> {
86    /// Attempts to create a new VDF deserializer along with returning the top level VDF key
87    pub fn new_with_key(vdf: Vdf<'de>) -> Result<(Self, Key<'de>)> {
88        let token_stream = tokens_from_vdf(vdf);
89
90        let key = if let Some(Token::Key(key)) = token_stream.first() {
91            key.clone()
92        } else {
93            unreachable!("Tokenstream must start with key");
94        };
95
96        let tokens = token_stream.into_iter().peekable();
97        Ok((Self { tokens }, key.clone()))
98    }
99
100    /// Returns if the internal tokenstream is empty
101    #[deprecated(
102        since = "0.2.4",
103        note = "This is an internal implementation detail, not intended for use"
104    )]
105    pub fn is_empty(&mut self) -> bool {
106        self.peek().is_none()
107    }
108
109    /// Returns if the next token is a value type (str, object, or sequence)
110    #[deprecated(
111        since = "0.2.4",
112        note = "This is an internal implementation detail, not intended for use"
113    )]
114    pub fn peek_is_value(&mut self) -> bool {
115        matches!(
116            self.peek(),
117            Some(Token::ObjBegin | Token::SeqBegin | Token::Str(_))
118        )
119    }
120
121    /// Returns the next key or str if available
122    #[deprecated(
123        since = "0.2.4",
124        note = "This is an internal implementation detail, not intended for use"
125    )]
126    pub fn next_key_or_str(&mut self) -> Option<Cow<'de, str>> {
127        match self.peek() {
128            Some(Token::Key(_) | Token::Str(_)) => match self.next() {
129                Some(Token::Key(s) | Token::Str(s)) => Some(s),
130                _ => unreachable!("Token was peeked"),
131            },
132            _ => None,
133        }
134    }
135
136    /// Returns the next key or str or returns an appropriate error
137    #[deprecated(
138        since = "0.2.4",
139        note = "This is an internal implementation detail, not intended for use"
140    )]
141    pub fn next_key_or_str_else_eof(&mut self) -> Result<Cow<'de, str>> {
142        #[expect(deprecated)]
143        self.next_key_or_str()
144            .ok_or(Error::EofWhileParsingKeyOrValue)
145    }
146
147    /// Returns the next finite float or returns an appropriate error
148    #[deprecated(
149        since = "0.2.4",
150        note = "This is an internal implementation detail, not intended for use"
151    )]
152    pub fn next_finite_float_else_eof(&mut self) -> Result<f32> {
153        #[expect(deprecated)]
154        let float: f32 = self.next_key_or_str_else_eof()?.parse()?;
155        if float.is_finite() {
156            Ok(float)
157        } else {
158            Err(Error::NonFiniteFloat(float))
159        }
160    }
161}
162
163// TODO: almost none of these should be `pub`
164impl<'de> Deref for Deserializer<'de> {
165    type Target = Peekable<IntoIter<Token<'de>>>;
166
167    fn deref(&self) -> &Self::Target {
168        &self.tokens
169    }
170}
171
172// TODO: almost none of these should be `pub`
173impl DerefMut for Deserializer<'_> {
174    fn deref_mut(&mut self) -> &mut Self::Target {
175        &mut self.tokens
176    }
177}
178
179macro_rules! forward_string_to_parse {
180    ( $( ( $deserializer_name:ident, $visitor_name:ident ) ),* $(,)? ) => {
181        $(
182            fn $deserializer_name<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
183                #[expect(deprecated)]
184                visitor.$visitor_name(self.next_key_or_str_else_eof()?.parse()?)
185            }
186        )*
187    }
188}
189
190impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> {
191    type Error = Error;
192
193    fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
194        match self
195            .peek()
196            .expect("Tokenstream structure prevents premature end")
197        {
198            Token::ObjBegin => self.deserialize_map(visitor),
199            Token::SeqBegin => self.deserialize_seq(visitor),
200            // `Any` always falls back to a `str` when possible, because the VDF format doesn't
201            // give any reasonable type information
202            Token::Key(_) | Token::Str(_) => self.deserialize_str(visitor),
203            Token::ObjEnd | Token::SeqEnd => unreachable!("End is always consumed with a Begin"),
204        }
205    }
206
207    fn deserialize_bool<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
208        #[expect(deprecated)]
209        let val = self.next_key_or_str_else_eof()?;
210        match val.as_ref() {
211            "0" => visitor.visit_bool(false),
212            "1" => visitor.visit_bool(true),
213            _ => Err(Error::InvalidBoolean),
214        }
215    }
216
217    forward_string_to_parse!(
218        (deserialize_i8, visit_i8),
219        (deserialize_i16, visit_i16),
220        (deserialize_i32, visit_i32),
221        (deserialize_i64, visit_i64),
222        (deserialize_i128, visit_i128),
223        (deserialize_u8, visit_u8),
224        (deserialize_u16, visit_u16),
225        (deserialize_u32, visit_u32),
226        (deserialize_u64, visit_u64),
227        (deserialize_u128, visit_u128),
228    );
229
230    fn deserialize_f32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
231        #[expect(deprecated)]
232        let float = self.next_finite_float_else_eof()?;
233        visitor.visit_f32(float)
234    }
235
236    fn deserialize_f64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
237        #[expect(deprecated)]
238        let float = self.next_finite_float_else_eof()?;
239        // Note: All floats are represented as through f32 since I believe that's what steam uses
240        visitor.visit_f64(f64::from(float))
241    }
242
243    fn deserialize_char<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
244        #[expect(deprecated)]
245        let s = self.next_key_or_str_else_eof()?;
246        let mut chars_iter = s.chars();
247        match (chars_iter.next(), chars_iter.next()) {
248            (Some(c), None) => visitor.visit_char(c),
249            // Either there are no or multiple chars
250            _ => Err(Error::InvalidChar),
251        }
252    }
253
254    fn deserialize_str<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
255        #[expect(deprecated)]
256        let val = self.next_key_or_str_else_eof()?;
257        match val {
258            // The borrowed content can be tied to the original text's lifetime
259            Cow::Borrowed(borrowed) => visitor.visit_borrowed_str(borrowed),
260            // TODO: Owned strings don't actually make it to here. Find out where the owned data
261            // becomes borrowed
262            Cow::Owned(s) => visitor.visit_string(s),
263        }
264    }
265
266    fn deserialize_string<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
267        #[expect(deprecated)]
268        visitor.visit_string(self.next_key_or_str_else_eof()?.into_owned())
269    }
270
271    fn deserialize_bytes<V: Visitor<'de>>(self, _visitor: V) -> Result<V::Value> {
272        // It's unclear how `bytes` would be represented in vdf
273        Err(Error::Unsupported("Bytes"))
274    }
275
276    fn deserialize_byte_buf<V: Visitor<'de>>(self, _visitor: V) -> Result<V::Value> {
277        // It's unclear how `byte buf` would be represented in vdf
278        Err(Error::Unsupported("Byte Buf"))
279    }
280
281    fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
282        // It looks like vdf will just entirely omit values that aren't used, so if the field
283        // appeared then it should be `Some`
284        visitor.visit_some(self)
285    }
286
287    fn deserialize_unit<V: Visitor<'de>>(self, _visitor: V) -> Result<V::Value> {
288        // It's unclear how a unit type would be represented in vdf (Empty string or obj?)
289        Err(Error::Unsupported("Unit"))
290    }
291
292    fn deserialize_unit_struct<V: Visitor<'de>>(
293        self,
294        _name: &'static str,
295        _visitor: V,
296    ) -> Result<V::Value> {
297        // It's unclear how a unit type would be represented in vdf (Empty string or obj?)
298        Err(Error::Unsupported("Unit Struct"))
299    }
300
301    fn deserialize_newtype_struct<V: Visitor<'de>>(
302        self,
303        _name: &'static str,
304        visitor: V,
305    ) -> Result<V::Value> {
306        // Considered just a wrapper over the contained value
307        visitor.visit_newtype_struct(self)
308    }
309
310    fn deserialize_seq<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
311        visitor.visit_seq(SeqBuilder::new(self).try_build()?)
312    }
313
314    fn deserialize_tuple<V: Visitor<'de>>(self, len: usize, visitor: V) -> Result<V::Value> {
315        visitor.visit_seq(SeqBuilder::new(self).length(len).try_build()?)
316    }
317
318    fn deserialize_tuple_struct<V: Visitor<'de>>(
319        self,
320        _name: &'static str,
321        len: usize,
322        visitor: V,
323    ) -> Result<V::Value> {
324        visitor.visit_seq(SeqBuilder::new(self).length(len).try_build()?)
325    }
326
327    fn deserialize_map<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
328        // A map is just an object containing a list of keyvalues
329        visitor.visit_map(ObjEater::try_new(self)?)
330    }
331
332    fn deserialize_struct<V: Visitor<'de>>(
333        self,
334        _name: &'static str,
335        _fields: &'static [&'static str],
336        visitor: V,
337    ) -> Result<V::Value> {
338        self.deserialize_map(visitor)
339    }
340
341    fn deserialize_enum<V: Visitor<'de>>(
342        self,
343        _name: &'static str,
344        _variants: &'static [&'static str],
345        visitor: V,
346    ) -> Result<V::Value> {
347        // Enums are only supported to the extent of the `Str` value matching the variant. No
348        // newtype, tuple, or struct variants supported due to ambiguity in vdf types
349        // This is because there is no pretence (that I know of) for how enums are notated in the
350        // externally, internally, and adjacently tagged enums, and the content of the data is far
351        // too vague for untagged to make sense. Consider how deserializing
352        // "Key"
353        // {
354        //      "inner"    "1"
355        // }
356        // with
357        // ```
358        // struct Outer { inner: SampleEnum, }
359        // enum SampleEnum {
360        //     Bool(bool),
361        //     Int(i32),
362        //     Optional(Option<u32>)
363        //     Seq(Vec<u64>),
364        //  }
365        //  ```
366        //  where each of these variants are equally valid for trying to determine "1".
367        match self.next() {
368            Some(Token::Key(s) | Token::Str(s)) => visitor.visit_enum(s.into_deserializer()),
369            Some(_) => Err(Error::ExpectedSomeValue),
370            None => Err(Error::EofWhileParsingValue),
371        }
372    }
373
374    fn deserialize_identifier<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
375        // An identifier is just a str
376        self.deserialize_str(visitor)
377    }
378
379    // AFAIK this is just used for making sure that the deserializer travels through the right
380    // amount of data so it's safe to ignore more finer grain types
381    fn deserialize_ignored_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
382        match self
383            .peek()
384            .expect("Tokenstream structure prevents premature end")
385        {
386            Token::Key(_) | Token::Str(_) => {
387                self.next().expect("Token was peeked");
388                visitor.visit_none()
389            }
390            Token::ObjBegin => self.deserialize_map(visitor),
391            Token::SeqBegin => self.deserialize_seq(visitor),
392            Token::ObjEnd | Token::SeqEnd => unreachable!("End is always consumed with a Begin"),
393        }
394    }
395}