move to serde_core

This commit is contained in:
Robin Appelman 2025-10-22 21:46:10 +02:00
commit cf230951a9
10 changed files with 282 additions and 40 deletions

19
Cargo.lock generated
View file

@ -404,18 +404,28 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.218" version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [
"serde_core",
"serde_derive",
]
[[package]]
name = "serde_core"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.218" version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -604,6 +614,7 @@ dependencies = [
"miette", "miette",
"parse-display", "parse-display",
"serde", "serde",
"serde_core",
"test-case", "test-case",
"thiserror 2.0.11", "thiserror 2.0.11",
"walkdir", "walkdir",

View file

@ -12,7 +12,7 @@ logos = "0.14.0"
thiserror = "2.0.11" thiserror = "2.0.11"
miette = "7.5.0" miette = "7.5.0"
parse-display = "0.9.0" parse-display = "0.9.0"
serde = { version = "1.0.200", features = ["derive"] } serde_core = "1.0.228"
[dev-dependencies] [dev-dependencies]
test-case = "3.3.1" test-case = "3.3.1"
@ -20,3 +20,4 @@ insta = { version = "1.38.0", features = ["ron"] }
miette = { version = "7.2.0", features = ["fancy"] } miette = { version = "7.2.0", features = ["fancy"] }
walkdir = "2.5.0" walkdir = "2.5.0"
maplit = "1.0.2" maplit = "1.0.2"
serde = { version = "1.0.228", features = ["derive"] }

164
app.vdf Normal file
View file

@ -0,0 +1,164 @@
"appinfo"
{
"appid" "232250"
"common"
{
"name" "Team Fortress 2 Dedicated Server"
"type" "Tool"
"releasestate" "released"
"oslist" "windows,linux"
"parent" "440"
"freetodownload" "1"
"gameid" "232250"
"exfgls" "9"
}
"extended"
{
"checkpkgstate" "1"
"developer" ""
"gamedir" "ValveTestApp232250"
"homepage" ""
"icon" ""
"noservers" "0"
"sourcegame" "1"
"state" "eStateComingSoonNoPreload"
"visibleonlywhensubscribed" "1"
}
"config"
{
"verifyupdates" "1"
"contenttype" "3"
"installdir" "Team Fortress 2 Dedicated Server"
}
"depots"
{
"232250"
{
"manifests"
{
"public"
{
"gid" "3423298312000784891"
"size" "13557339255"
"download" "8923361280"
}
"prerelease"
{
"gid" "3423298312000784891"
"size" "13557339255"
"download" "8923361280"
}
"valve_ds"
{
"gid" "3423298312000784891"
"size" "13557339255"
"download" "8923361280"
}
}
}
"232255"
{
"config"
{
"oslist" "windows"
}
"manifests"
{
"public"
{
"gid" "6628420416233102704"
"size" "267733389"
"download" "88870304"
}
"prerelease"
{
"gid" "6628420416233102704"
"size" "267733389"
"download" "88870304"
}
"valve_ds"
{
"gid" "6628420416233102704"
"size" "267733389"
"download" "88870304"
}
}
}
"232256"
{
"config"
{
"oslist" "linux"
}
"manifests"
{
"public"
{
"gid" "4606186468524235451"
"size" "155992583"
"download" "39774800"
}
"prerelease"
{
"gid" "4606186468524235451"
"size" "155992583"
"download" "39774800"
}
"valve_ds"
{
"gid" "4606186468524235451"
"size" "155992583"
"download" "39774800"
}
}
}
"232257"
{
"config"
{
"oslist" "linux"
}
"manifests"
{
"public"
{
"gid" "4797708003880603728"
"size" "9989"
"download" "2608"
}
"prerelease"
{
"gid" "4797708003880603728"
"size" "9989"
"download" "2608"
}
"valve_ds"
{
"gid" "4797708003880603728"
"size" "9989"
"download" "2608"
}
}
}
"overridescddb" "1"
"branches"
{
"public"
{
"buildid" "18450794"
"timeupdated" "1747175459"
}
"prerelease"
{
"buildid" "18450794"
"timeupdated" "1747175467"
}
"valve_ds"
{
"buildid" "18450794"
"description" "The version Valve dedicated servers will sync to"
"timeupdated" "1747175424"
}
}
}
}

View file

@ -2,13 +2,12 @@ use super::{Entry, Table};
use crate::entry::Value; use crate::entry::Value;
use crate::error::{ParseStringError, UnknownError}; use crate::error::{ParseStringError, UnknownError};
use crate::VdfError; use crate::VdfError;
use serde::de::{DeserializeSeed, SeqAccess}; use serde_core::de::{DeserializeSeed, SeqAccess};
use serde::{Deserialize, Serialize}; use serde_core::{Deserialize, Deserializer, Serialize, Serializer};
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
/// An array of entries (items that have the same key). /// An array of entries (items that have the same key).
#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize, Default)] #[derive(Clone, PartialEq, Eq, Debug, Default)]
#[serde(transparent)]
pub struct Array(Vec<Entry>); pub struct Array(Vec<Entry>);
impl Array { impl Array {
@ -23,6 +22,24 @@ impl Array {
} }
} }
impl<'de> Deserialize<'de> for Array {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
<Vec<Entry>>::deserialize(deserializer).map(Array)
}
}
impl Serialize for Array {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.serialize(serializer)
}
}
impl From<Vec<Entry>> for Array { impl From<Vec<Entry>> for Array {
fn from(value: Vec<Entry>) -> Self { fn from(value: Vec<Entry>) -> Self {
Array(value) Array(value)

View file

@ -16,8 +16,7 @@ pub use table::Table;
pub use value::Value; pub use value::Value;
/// The kinds of entry. /// The kinds of entry.
#[derive(Clone, PartialEq, Eq, Debug, Serialize)] #[derive(Clone, PartialEq, Eq, Debug)]
#[serde(untagged)]
pub enum Entry { pub enum Entry {
/// A table. /// A table.
Table(Table), Table(Table),
@ -32,6 +31,20 @@ pub enum Entry {
Statement(Statement), Statement(Statement),
} }
impl Serialize for Entry {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self {
Entry::Table(entry) => entry.serialize(serializer),
Entry::Array(entry) => entry.serialize(serializer),
Entry::Value(entry) => entry.serialize(serializer),
Entry::Statement(entry) => entry.serialize(serializer),
}
}
}
impl From<Item<'_>> for Entry { impl From<Item<'_>> for Entry {
fn from(item: Item) -> Self { fn from(item: Item) -> Self {
match item { match item {
@ -218,8 +231,10 @@ macro_rules! from_str {
use crate::entry::array::{ArraySeq, TableArraySeq}; use crate::entry::array::{ArraySeq, TableArraySeq};
use crate::entry::table::TableSeq; use crate::entry::table::TableSeq;
use serde::de::{DeserializeSeed, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor}; use serde_core::de::{
use serde::{Deserialize, Deserializer, Serialize}; DeserializeSeed, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor,
};
use serde_core::{Deserialize, Deserializer, Serialize, Serializer};
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
from_str!(for IpAddr Ipv4Addr Ipv6Addr SocketAddr SocketAddrV4 SocketAddrV6); from_str!(for IpAddr Ipv4Addr Ipv6Addr SocketAddr SocketAddrV4 SocketAddrV6);
from_str!(for i8 i16 i32 i64 isize u8 u16 u32 u64 usize f32 f64); from_str!(for i8 i16 i32 i64 isize u8 u16 u32 u64 usize f32 f64);

View file

@ -1,13 +1,30 @@
use super::Entry; use super::Entry;
use serde::{Deserialize, Serialize}; use serde_core::{Deserialize, Deserializer, Serialize, Serializer};
use std::borrow::Cow; use std::borrow::Cow;
use std::ops::Deref; use std::ops::Deref;
/// A statement. /// A statement.
#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize, Default)] #[derive(Clone, PartialEq, Eq, Debug, Default)]
#[serde(transparent)]
pub struct Statement(String); pub struct Statement(String);
impl<'de> Deserialize<'de> for Statement {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
String::deserialize(deserializer).map(Statement)
}
}
impl Serialize for Statement {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.serialize(serializer)
}
}
impl From<Cow<'_, str>> for Statement { impl From<Cow<'_, str>> for Statement {
fn from(value: Cow<'_, str>) -> Self { fn from(value: Cow<'_, str>) -> Self {
Statement(value.into()) Statement(value.into())

View file

@ -3,16 +3,35 @@ use crate::entry::{string_is_array, Statement, Value};
use crate::error::UnknownError; use crate::error::UnknownError;
use crate::event::{EntryEvent, GroupStartEvent, ValueContinuationEvent}; use crate::event::{EntryEvent, GroupStartEvent, ValueContinuationEvent};
use crate::{Event, Item, Reader, Result, VdfError}; use crate::{Event, Item, Reader, Result, VdfError};
use serde::de::{DeserializeSeed, MapAccess}; use serde_core::de::{DeserializeSeed, MapAccess};
use serde::{Deserialize, Serialize, Serializer}; use serde_core::{Deserialize, Deserializer, Serialize, Serializer};
use std::collections::hash_map; use std::collections::hash_map;
use std::collections::HashMap; use std::collections::HashMap;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
/// A table of entries. /// A table of entries.
#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize, Default)] #[derive(Clone, PartialEq, Eq, Debug, Default)]
#[serde(transparent)] pub struct Table(HashMap<String, Entry>); // todo: switch to a map that maintains item order
pub struct Table(#[serde(serialize_with = "ordered_map")] HashMap<String, Entry>); // todo: switch to a map that maintains item order
impl<'de> Deserialize<'de> for Table {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: Deserializer<'de>,
{
HashMap::deserialize(deserializer).map(Table)
}
}
impl Serialize for Table {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: Serializer,
{
use std::collections::BTreeMap;
let ordered: BTreeMap<_, _> = self.0.iter().collect();
ordered.serialize(serializer)
}
}
impl From<HashMap<String, Entry>> for Table { impl From<HashMap<String, Entry>> for Table {
fn from(value: HashMap<String, Entry>) -> Self { fn from(value: HashMap<String, Entry>) -> Self {
@ -20,18 +39,6 @@ impl From<HashMap<String, Entry>> for Table {
} }
} }
fn ordered_map<S, K: Ord + Serialize, V: Serialize>(
value: &HashMap<K, V>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use std::collections::BTreeMap;
let ordered: BTreeMap<_, _> = value.iter().collect();
ordered.serialize(serializer)
}
fn insert<K: Into<String>, V: Into<Entry>>(map: &mut HashMap<String, Entry>, key: K, value: V) { fn insert<K: Into<String>, V: Into<Entry>>(map: &mut HashMap<String, Entry>, key: K, value: V) {
let key = key.into(); let key = key.into();
let value = value.into(); let value = value.into();

View file

@ -2,16 +2,24 @@ use super::Entry;
use crate::entry::{string_is_array, ParseItem, Statement}; use crate::entry::{string_is_array, ParseItem, Statement};
use crate::error::{ParseStringError, SerdeParseError}; use crate::error::{ParseStringError, SerdeParseError};
use crate::VdfError; use crate::VdfError;
use serde::de::{Error, Visitor}; use serde_core::de::{Error, Visitor};
use serde::{Deserialize, Deserializer, Serialize}; use serde_core::{Deserialize, Deserializer, Serialize, Serializer};
use std::borrow::Cow; use std::borrow::Cow;
use std::fmt::Formatter; use std::fmt::Formatter;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Default)] #[derive(Clone, PartialEq, Eq, Debug, Default)]
#[serde(transparent)]
pub struct Value(String); pub struct Value(String);
impl Serialize for Value {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.serialize(serializer)
}
}
impl From<Cow<'_, str>> for Value { impl From<Cow<'_, str>> for Value {
fn from(value: Cow<'_, str>) -> Value { fn from(value: Cow<'_, str>) -> Value {
Value(value.into()) Value(value.into())

View file

@ -464,7 +464,7 @@ impl<'source> ExpectToken<'source> for SpannedToken {
} }
} }
impl serde::de::Error for VdfError { impl serde_core::de::Error for VdfError {
fn custom<T>(msg: T) -> Self fn custom<T>(msg: T) -> Self
where where
T: Display, T: Display,

View file

@ -3,8 +3,10 @@ use crate::error::{ExpectToken, NoValidTokenError, ResultExt, SerdeParseError, U
use crate::tokenizer::{SpannedToken, Tokenizer}; use crate::tokenizer::{SpannedToken, Tokenizer};
use crate::{Token, VdfError}; use crate::{Token, VdfError};
use logos::Span; use logos::Span;
use serde::de::{self, DeserializeSeed, EnumAccess, MapAccess, SeqAccess, VariantAccess, Visitor}; use serde_core::de::{
use serde::Deserialize; self, DeserializeSeed, EnumAccess, MapAccess, SeqAccess, VariantAccess, Visitor,
};
use serde_core::Deserialize;
use std::borrow::Cow; use std::borrow::Cow;
type Result<T, E = VdfError> = std::result::Result<T, E>; type Result<T, E = VdfError> = std::result::Result<T, E>;