[][src]Crate vdf_serde

Support for the Valve Data Format for Serde.

Based on the steamy-vdf VDF parser library.

Simple Example

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct Example {
    thing: String,
    other_thing: bool,
    more_stuff: Inner,
}

#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct Inner {
    bonus_content: u8,
    coolness: f64,
}

let vdf_data = "\"Example\"
{
\t\"thing\"\t\"hello\"
\t\"other_thing\"\t\"1\"
\t\"more_stuff\"
\t{
\t\t\"bonus_content\"\t\"69\"
\t\t\"coolness\"\t\"420.1337\"
\t}
}";
let data = Example {
    thing: "hello".to_string(),
    other_thing: true,
    more_stuff: Inner {
        bonus_content: 69,
        coolness: 420.1337,
    },
};

assert_eq!(vdf_serde::to_string(&data)?, vdf_data);
assert_eq!(vdf_serde::from_str::<Example>(vdf_data)?, data);

Example I Needed When I Wrote This Library

If you've got a pile of arbitrary key-value data you can't predict the structure of in advance, you can use a HashMap<K, V>. But if there's a top-level name attached, you'll need a newtype, like this:

use std::collections::HashMap;
use serde::Deserialize;
#[derive(Deserialize)]
struct LibraryFolders(HashMap<String, String>);

let vdf_data = r#""LibraryFolders"
{
    "TimeNextStatsReport"   "69420691337"
    "ContentStatsID"        "31337131269420"
    "1"                     "D:\\SteamLibrary"
}"#;
let LibraryFolders(data) = vdf_serde::from_str(vdf_data)?;
let expected = [("TimeNextStatsReport", "69420691337"), ("ContentStatsID", "31337131269420"), ("1", r"D:\SteamLibrary")]
    .iter()
    .map(|(a, b)| (a.to_string(), b.to_string()))
    .collect::<HashMap<_, _>>();
assert_eq!(data, expected);

Notes

The VDF format is rather drastically underspecified, so until I figure out a way to implement them in a way that's compatible with existing VDF files, the following types from the Serde data model are unsupported:

  • byte array
  • option
  • unit ()
  • unit_struct struct WillNotWork;
  • newtype_variant enum Broken { Example(u8) }
  • seq Vec<T>
  • tuple
  • tuple_struct struct Unsupported(u8, bool, char);
  • tuple_variant enum Bad { NotWorking(u8, bool, char) }
  • struct_variant enum Nope { NotHappening { datum: u8 } }

You might wind up needing to implement Serialize yourself and implement Deserialize yourself if you use anything like this. The rest of the Serde data model works, though, although maps with non-atomic keys might be a bit of a mess.

use std::collections::HashMap as Map;
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, Debug, PartialEq)]
enum UnitVariants { A, B }
#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct NewtypeStruct(u8);
#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct KitchenSink {
    a: bool,
    b: i8,
    c: i16,
    d: i32,
    e: i64,
    f: u8,
    g: u16,
    h: u32,
    i: u64,
    j: f32,
    k: f64,
    l: char,
    m: String,
    n: UnitVariants,
    o: NewtypeStruct,
    p: Map<String, String>,
}

let data = KitchenSink { // yada yada yada
};
assert_eq!(data, vdf_serde::from_str(&vdf_serde::to_string(&data)?)?);

Structs

Deserializer

A structure that deserializes VDF into Rust values

Serializer

A structure for serializing Rust values into VDF

Enums

Error

This type represents all possible errors that can occur when serializing or deserializing VDF data

Functions

from_str

Deserialize an instance of type T from a string of VDF text

to_string

Serialize the given data structure as a String of VDF

Type Definitions

Result

Alias for a Result with the error type vdf_serde::Error