support tagged enums inside tables

This commit is contained in:
Robin Appelman 2023-12-21 20:36:09 +01:00
commit 21c048625e
5 changed files with 65 additions and 7 deletions

View file

@ -656,11 +656,15 @@ where
struct Enum<'a, 'de: 'a> {
de: &'a mut Deserializer<'de>,
enclosed: bool,
}
impl<'a, 'de> Enum<'a, 'de> {
fn new(de: &'a mut Deserializer<'de>) -> Self {
Enum { de }
Enum {
de,
enclosed: false,
}
}
}
@ -673,10 +677,19 @@ impl<'de, 'a> EnumAccess<'de> for Enum<'a, 'de> {
type Error = VdfError;
type Variant = Self;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant)>
fn variant_seed<V>(mut self, seed: V) -> Result<(V::Value, Self::Variant)>
where
V: DeserializeSeed<'de>,
{
if self
.de
.peek()
.expect_token(&[Token::GroupStart], self.de.source())
.is_ok()
{
self.enclosed = true;
let _ = self.de.next();
}
let val = seed.deserialize(&mut *self.de)?;
Ok((val, self))
}
@ -695,21 +708,39 @@ impl<'de, 'a> VariantAccess<'de> for Enum<'a, 'de> {
where
T: DeserializeSeed<'de>,
{
seed.deserialize(self.de)
let val = seed.deserialize(&mut *self.de)?;
if self.enclosed {
self.de
.next()
.expect_token(&[Token::GroupEnd], self.de.source())?;
}
Ok(val)
}
fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
de::Deserializer::deserialize_seq(self.de, visitor)
let val = de::Deserializer::deserialize_seq(&mut *self.de, visitor)?;
if self.enclosed {
self.de
.next()
.expect_token(&[Token::GroupEnd], self.de.source())?;
}
Ok(val)
}
fn struct_variant<V>(self, _fields: &'static [&'static str], visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
de::Deserializer::deserialize_map(self.de, visitor)
let val = de::Deserializer::deserialize_map(&mut *self.de, visitor)?;
if self.enclosed {
self.de
.next()
.expect_token(&[Token::GroupEnd], self.de.source())?;
}
Ok(val)
}
}

7
tests/data/enuminmap.vdf Normal file
View file

@ -0,0 +1,7 @@
EnumInMap {
foo {
bar {
a 1
}
}
}

View file

@ -64,6 +64,16 @@ enum Expected {
#[serde(rename = "$no_fullbright")]
no_full_bright: bool,
},
EnumInMap {
foo: EnumInMap,
},
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum EnumInMap {
Bar { a: bool },
Foo { a: bool },
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
@ -194,6 +204,7 @@ struct GameList {
#[test_case("tests/data/DialogConfigOverlay_1280x720.vdf")]
#[test_case("tests/data/serde_array_type.vdf")]
#[test_case("tests/data/game_text.vmt")]
#[test_case("tests/data/enuminmap.vdf")]
#[test_case("tests/errors/unmatched.vdf")]
#[test_case("tests/errors/concrete.vmt")]
#[test_case("tests/errors/novalue.vdf")]

View file

@ -0,0 +1,9 @@
---
source: tests/serde.rs
expression: result
---
EnumInMap(
foo: bar(
a: true,
),
)

View file

@ -4,11 +4,11 @@ expression: out
---
vmt_parser::unknown_variant
× Unknown variant "Resource" expected on of expected on of Types, LightmappedGeneric, Resource/specificPanel.res, UserConfigData, Sprite
× Unknown variant "Resource" expected on of expected on of Types, LightmappedGeneric, Resource/specificPanel.res, UserConfigData, Sprite, EnumInMap
╭─[1:1]
1 │ "Resource"
· ─────┬────
· ╰── expected on of Types, LightmappedGeneric, Resource/specificPanel.res, UserConfigData, Sprite
· ╰── expected on of Types, LightmappedGeneric, Resource/specificPanel.res, UserConfigData, Sprite, EnumInMap
2 │ {
╰────