vdf_serde/lib.rs
1//! Support for the [Valve Data Format](https://developer.valvesoftware.com/wiki/KeyValues) for [Serde](https://serde.rs/).
2//!
3//! Based on the [steamy-vdf](https://crates.io/crates/steamy-vdf) VDF parser library.
4//!
5//! # Simple Example
6//!
7//! ```
8//! use serde::{Serialize, Deserialize};
9//!
10//! #[derive(Serialize, Deserialize, Debug, PartialEq)]
11//! struct Example {
12//! thing: String,
13//! other_thing: bool,
14//! more_stuff: Inner,
15//! }
16//!
17//! #[derive(Serialize, Deserialize, Debug, PartialEq)]
18//! struct Inner {
19//! bonus_content: u8,
20//! coolness: f64,
21//! }
22//!
23//! let vdf_data = "\"Example\"
24//! {
25//! \t\"thing\"\t\"hello\"
26//! \t\"other_thing\"\t\"1\"
27//! \t\"more_stuff\"
28//! \t{
29//! \t\t\"bonus_content\"\t\"69\"
30//! \t\t\"coolness\"\t\"420.1337\"
31//! \t}
32//! }";
33//! let data = Example {
34//! thing: "hello".to_string(),
35//! other_thing: true,
36//! more_stuff: Inner {
37//! bonus_content: 69,
38//! coolness: 420.1337,
39//! },
40//! };
41//!
42//! assert_eq!(vdf_serde::to_string(&data)?, vdf_data);
43//! assert_eq!(vdf_serde::from_str::<Example>(vdf_data)?, data);
44//! # Ok::<(), vdf_serde::Error>(())
45//! ```
46//!
47//! # Example I Needed When I Wrote This Library
48//!
49//! If you've got a pile of arbitrary key-value data you can't predict the structure of
50//! in advance, you can use a `HashMap<K, V>`. But if there's a top-level name attached,
51//! you'll need a newtype, like this:
52//!
53//! ```
54//! use std::collections::HashMap;
55//! use serde::Deserialize;
56//! #[derive(Deserialize)]
57//! struct LibraryFolders(HashMap<String, String>);
58//!
59//! let vdf_data = r#""LibraryFolders"
60//! {
61//! "TimeNextStatsReport" "69420691337"
62//! "ContentStatsID" "31337131269420"
63//! "1" "D:\\SteamLibrary"
64//! }"#;
65//! let LibraryFolders(data) = vdf_serde::from_str(vdf_data)?;
66//! let expected = [("TimeNextStatsReport", "69420691337"), ("ContentStatsID", "31337131269420"), ("1", r"D:\SteamLibrary")]
67//! .iter()
68//! .map(|(a, b)| (a.to_string(), b.to_string()))
69//! .collect::<HashMap<_, _>>();
70//! assert_eq!(data, expected);
71//! # Ok::<(), vdf_serde::Error>(())
72//! ```
73//!
74//! # Notes
75//!
76//! The VDF format is rather drastically underspecified, so until I figure out a way to implement them in a way that's compatible with
77//! existing VDF files, the following types from [the Serde data model](https://serde.rs/data-model.html) are unsupported:
78//!
79//! - byte array
80//! - option
81//! - unit `()`
82//! - unit_struct `struct WillNotWork;`
83//! - newtype_variant `enum Broken { Example(u8) }`
84//! - seq `Vec<T>`
85//! - tuple
86//! - tuple_struct `struct Unsupported(u8, bool, char);`
87//! - tuple_variant `enum Bad { NotWorking(u8, bool, char) }`
88//! - struct_variant `enum Nope { NotHappening { datum: u8 } }`
89//!
90//! You might wind up needing to [implement Serialize yourself](https://serde.rs/impl-serialize.html) and
91//! [implement Deserialize yourself](https://serde.rs/impl-deserialize.html) if you use anything like this.
92//! The rest of the Serde data model works, though, although maps with non-atomic keys might be a bit of a mess.
93//!
94//! ```
95//! use std::collections::HashMap as Map;
96//! use serde::{Serialize, Deserialize};
97//! #[derive(Serialize, Deserialize, Debug, PartialEq)]
98//! enum UnitVariants { A, B }
99//! #[derive(Serialize, Deserialize, Debug, PartialEq)]
100//! struct NewtypeStruct(u8);
101//! #[derive(Serialize, Deserialize, Debug, PartialEq)]
102//! struct KitchenSink {
103//! a: bool,
104//! b: i8,
105//! c: i16,
106//! d: i32,
107//! e: i64,
108//! f: u8,
109//! g: u16,
110//! h: u32,
111//! i: u64,
112//! j: f32,
113//! k: f64,
114//! l: char,
115//! m: String,
116//! n: UnitVariants,
117//! o: NewtypeStruct,
118//! p: Map<String, String>,
119//! }
120//!
121//! # let mut p = Map::new();
122//! # p.insert("hello".to_string(), "there".to_string());
123//! let data = KitchenSink { // yada yada yada
124//! # a: false, b: -123, c: -45, d: -67, e: -890, f: 12, g: 345, h: 678, i: 901, j: 0.3,
125//! # k: 9.25, l: '≈', m: "sample text".to_string(), n: UnitVariants::A,
126//! # o: NewtypeStruct(3), p,
127//! };
128//! assert_eq!(data, vdf_serde::from_str(&vdf_serde::to_string(&data)?)?);
129//! # Ok::<(), vdf_serde::Error>(())
130//! ```
131#![deny(missing_docs)]
132#![doc(html_root_url = "https://docs.rs/vdf-serde/0.3.0")]
133
134mod de;
135mod error;
136mod ser;
137
138pub use de::{from_str, Deserializer};
139pub use error::{Error, Result};
140pub use ser::{to_string, Serializer};