mirror of
https://codeberg.org/icewind/vdf-reader.git
synced 2026-06-03 10:04:08 +02:00
boxed arrays
This commit is contained in:
parent
778696590a
commit
d54e44b51d
7 changed files with 143 additions and 6 deletions
36
src/error.rs
36
src/error.rs
|
|
@ -42,6 +42,42 @@ pub enum VdfError {
|
||||||
Other(String),
|
Other(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl VdfError {
|
||||||
|
pub(crate) fn with_source_span<Sp: Into<SourceSpan>, Sr: Into<String>>(
|
||||||
|
self,
|
||||||
|
span: Sp,
|
||||||
|
source: Sr,
|
||||||
|
) -> VdfError {
|
||||||
|
match self {
|
||||||
|
VdfError::UnexpectedToken(e) => UnexpectedTokenError {
|
||||||
|
src: source.into(),
|
||||||
|
err_span: span.into(),
|
||||||
|
..e
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
VdfError::NoValidToken(e) => NoValidTokenError {
|
||||||
|
src: source.into(),
|
||||||
|
err_span: span.into(),
|
||||||
|
..e
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
VdfError::WrongEntryType(e) => WrongEventTypeError {
|
||||||
|
src: source.into(),
|
||||||
|
err_span: span.into(),
|
||||||
|
..e
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
VdfError::SerdeParse(e) => SerdeParseError {
|
||||||
|
src: source.into(),
|
||||||
|
err_span: span.into(),
|
||||||
|
..e
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
_ => self,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct ExpectedTokens<'a>(&'a [Token]);
|
struct ExpectedTokens<'a>(&'a [Token]);
|
||||||
|
|
||||||
impl Display for ExpectedTokens<'_> {
|
impl Display for ExpectedTokens<'_> {
|
||||||
|
|
|
||||||
69
src/serde.rs
69
src/serde.rs
|
|
@ -293,9 +293,17 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||||
where
|
where
|
||||||
V: Visitor<'de>,
|
V: Visitor<'de>,
|
||||||
{
|
{
|
||||||
let key = self.last_key.clone();
|
let token = self.peek().expect_token(STRING_ITEMS, self.source())?;
|
||||||
let value = visitor.visit_seq(SeqWalker::new(&mut self, key))?;
|
let value_str = &self.source()[token.span.clone()];
|
||||||
Ok(value)
|
if value_str.starts_with("\"[") && value_str.ends_with("]\"") {
|
||||||
|
let _ = self.next();
|
||||||
|
let seq = &value_str[2..value_str.len() - 2];
|
||||||
|
let span = token.span.start + 2..token.span.end - 2;
|
||||||
|
visitor.visit_seq(StringArrayWalker::new(self.source(), seq, span))
|
||||||
|
} else {
|
||||||
|
let key = self.last_key.clone();
|
||||||
|
visitor.visit_seq(SeqWalker::new(&mut self, key))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value>
|
fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value>
|
||||||
|
|
@ -322,16 +330,16 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||||
V: Visitor<'de>,
|
V: Visitor<'de>,
|
||||||
{
|
{
|
||||||
// as a special case we allow a map without a `{` at the start of the file to create a top level struct
|
// as a special case we allow a map without a `{` at the start of the file to create a top level struct
|
||||||
let toplevel = match dbg!(self
|
let toplevel = match self
|
||||||
.peek()
|
.peek()
|
||||||
.expect_token(&[Token::GroupStart], self.source()))
|
.expect_token(&[Token::GroupStart], self.source())
|
||||||
{
|
{
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let _ = self.next();
|
let _ = self.next();
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
Err(VdfError::UnexpectedToken(e)) => {
|
Err(VdfError::UnexpectedToken(e)) => {
|
||||||
if dbg!(self.tokenizer.count) > 1 {
|
if self.tokenizer.count > 1 {
|
||||||
return Err(e.into());
|
return Err(e.into());
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
|
|
@ -526,6 +534,55 @@ impl<'de, 'a> SeqAccess<'de> for SeqWalker<'de, 'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct StringArrayWalker<'source> {
|
||||||
|
source: &'source str,
|
||||||
|
remaining: &'source str,
|
||||||
|
span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'source> StringArrayWalker<'source> {
|
||||||
|
fn new(source: &'source str, array: &'source str, span: Span) -> Self {
|
||||||
|
StringArrayWalker {
|
||||||
|
source,
|
||||||
|
remaining: array,
|
||||||
|
span,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de, 'source> SeqAccess<'de> for StringArrayWalker<'source>
|
||||||
|
where
|
||||||
|
'source: 'de,
|
||||||
|
{
|
||||||
|
type Error = VdfError;
|
||||||
|
|
||||||
|
fn next_element_seed<T>(
|
||||||
|
&mut self,
|
||||||
|
seed: T,
|
||||||
|
) -> std::result::Result<Option<T::Value>, Self::Error>
|
||||||
|
where
|
||||||
|
T: DeserializeSeed<'de>,
|
||||||
|
{
|
||||||
|
if self.remaining.is_empty() {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
let (item, rest) = self
|
||||||
|
.remaining
|
||||||
|
.split_once(" ")
|
||||||
|
.unwrap_or((self.remaining, ""));
|
||||||
|
let item_span = self.span.start..(self.span.start + item.len());
|
||||||
|
self.remaining = rest.trim();
|
||||||
|
self.span = (self.span.end - self.remaining.len())..self.span.end;
|
||||||
|
|
||||||
|
let mut de = Deserializer::from_str(item);
|
||||||
|
let val = seed
|
||||||
|
.deserialize(&mut de)
|
||||||
|
.map_err(|e| e.with_source_span(item_span, self.source))?;
|
||||||
|
Ok(Some(val))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct Enum<'a, 'de: 'a> {
|
struct Enum<'a, 'de: 'a> {
|
||||||
de: &'a mut Deserializer<'de>,
|
de: &'a mut Deserializer<'de>,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
5
tests/data/serde_array_type.vdf
Normal file
5
tests/data/serde_array_type.vdf
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
"Types" {
|
||||||
|
fixed_array "[1 2 3]"
|
||||||
|
flex_array "[1.0 2.2]"
|
||||||
|
tuple "[1 57]"
|
||||||
|
}
|
||||||
5
tests/errors/serde_array_type.vdf
Normal file
5
tests/errors/serde_array_type.vdf
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
"Types" {
|
||||||
|
fixed_array "[1 2 3.1]"
|
||||||
|
flex_array "[1.0 2.2]"
|
||||||
|
tuple "[1 57]"
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,11 @@ use vdf_reader::from_str;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
enum Expected {
|
enum Expected {
|
||||||
|
Types {
|
||||||
|
fixed_array: [u8; 3],
|
||||||
|
flex_array: Vec<f32>,
|
||||||
|
tuple: (bool, u8),
|
||||||
|
},
|
||||||
LightmappedGeneric {
|
LightmappedGeneric {
|
||||||
#[serde(rename = "$baseTexture")]
|
#[serde(rename = "$baseTexture")]
|
||||||
base_texture: String,
|
base_texture: String,
|
||||||
|
|
@ -152,8 +157,10 @@ struct GameList {
|
||||||
#[test_case("tests/data/concrete.vmt")]
|
#[test_case("tests/data/concrete.vmt")]
|
||||||
#[test_case("tests/data/messy.vdf")]
|
#[test_case("tests/data/messy.vdf")]
|
||||||
#[test_case("tests/data/DialogConfigOverlay_1280x720.vdf")]
|
#[test_case("tests/data/DialogConfigOverlay_1280x720.vdf")]
|
||||||
|
#[test_case("tests/data/serde_array_type.vdf")]
|
||||||
#[test_case("tests/errors/concrete.vmt")]
|
#[test_case("tests/errors/concrete.vmt")]
|
||||||
#[test_case("tests/errors/novalue.vdf")]
|
#[test_case("tests/errors/novalue.vdf")]
|
||||||
|
#[test_case("tests/errors/serde_array_type.vdf")]
|
||||||
fn test_serde(path: &str) {
|
fn test_serde(path: &str) {
|
||||||
let raw = read_to_string(path).unwrap();
|
let raw = read_to_string(path).unwrap();
|
||||||
match from_str::<Expected>(&raw) {
|
match from_str::<Expected>(&raw) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
source: tests/serde.rs
|
||||||
|
expression: result
|
||||||
|
---
|
||||||
|
Types(
|
||||||
|
fixed_array: (1, 2, 3),
|
||||||
|
flex_array: [
|
||||||
|
1.0,
|
||||||
|
2.2,
|
||||||
|
],
|
||||||
|
tuple: (true, 57),
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
---
|
||||||
|
source: tests/serde.rs
|
||||||
|
expression: out
|
||||||
|
---
|
||||||
|
vmt_parser::parse_serde
|
||||||
|
|
||||||
|
× Can't parse "3.1" as u8
|
||||||
|
╭─[1:1]
|
||||||
|
1 │ "Types" {
|
||||||
|
2 │ fixed_array "[1 2 3.1]"
|
||||||
|
· ─┬─
|
||||||
|
· ╰── Expected a u8
|
||||||
|
3 │ flex_array "[1.0 2.2]"
|
||||||
|
╰────
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue