keyvalues_serde/de/
mod.rs

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