mirror of
https://codeberg.org/icewind/php-literal-parser.git
synced 2026-06-03 18:44:07 +02:00
fix nested arrays with serde
This commit is contained in:
parent
9d3295daff
commit
0127eecad2
5 changed files with 230 additions and 47 deletions
|
|
@ -49,6 +49,15 @@ pub enum Token {
|
|||
Error,
|
||||
}
|
||||
|
||||
impl Token {
|
||||
pub(crate) fn is_valid_array_key(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Token::Integer | Token::LiteralString | Token::Bool | Token::Float | Token::Null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lex() {
|
||||
let source = r###"
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ impl<'de> Deserializer<'de> {
|
|||
}
|
||||
|
||||
fn push_peeked(&mut self, peeked: SpannedToken<'de>) {
|
||||
self.peeked.push_back(peeked)
|
||||
self.peeked.push_front(peeked)
|
||||
}
|
||||
|
||||
fn parse_unsigned<T>(&mut self) -> Result<T>
|
||||
|
|
@ -500,6 +500,7 @@ impl<'de> SeqAccess<'de> for ArrayWalker<'de, '_> {
|
|||
where
|
||||
T: DeserializeSeed<'de>,
|
||||
{
|
||||
let source = self.source();
|
||||
if self.done {
|
||||
return Ok(None);
|
||||
}
|
||||
|
|
@ -515,7 +516,7 @@ impl<'de> SeqAccess<'de> for ArrayWalker<'de, '_> {
|
|||
Token::SquareOpen,
|
||||
self.syntax.close_bracket(),
|
||||
],
|
||||
self.source(),
|
||||
source,
|
||||
)?;
|
||||
|
||||
if token.token == self.syntax.close_bracket() {
|
||||
|
|
@ -523,31 +524,28 @@ impl<'de> SeqAccess<'de> for ArrayWalker<'de, '_> {
|
|||
return Ok(None);
|
||||
}
|
||||
|
||||
let next = self.de.next_token().expect_token(
|
||||
&[self.syntax.close_bracket(), Token::Comma, Token::Arrow],
|
||||
self.source(),
|
||||
)?;
|
||||
let value_token = if token.token.is_valid_array_key() {
|
||||
let next = self.de.peek_token();
|
||||
|
||||
let value_token = match next.token {
|
||||
Token::Comma => token,
|
||||
Token::Arrow => {
|
||||
let span = token.span.clone();
|
||||
if next.map(|t| t.token) == Some(Token::Arrow) {
|
||||
self.de.eat_token();
|
||||
let key_span = token.span.clone();
|
||||
let key = self.de.parser.parse_array_key(token)?;
|
||||
match key {
|
||||
Key::Int(key) if key == self.next_int_key => Ok(()),
|
||||
Key::Int(_) => Err(ParseError::UnexpectedArrayKey(ArrayKeyError::new(
|
||||
ArrayKeyErrorKind::NonConsecutive,
|
||||
self.source(),
|
||||
span,
|
||||
key_span,
|
||||
))),
|
||||
_ => Err(ParseError::UnexpectedArrayKey(ArrayKeyError::new(
|
||||
ArrayKeyErrorKind::IntegerExpected,
|
||||
self.source(),
|
||||
span,
|
||||
key_span,
|
||||
))),
|
||||
}?;
|
||||
self.next_int_key += 1;
|
||||
let value = self.de.next_token().expect_token(
|
||||
self.de.next_token().expect_token(
|
||||
&[
|
||||
Token::Bool,
|
||||
Token::Integer,
|
||||
|
|
@ -558,26 +556,27 @@ impl<'de> SeqAccess<'de> for ArrayWalker<'de, '_> {
|
|||
Token::SquareOpen,
|
||||
],
|
||||
self.source(),
|
||||
)?;
|
||||
let next = self
|
||||
.de
|
||||
.next_token()
|
||||
.expect_token(&[Token::Comma, self.syntax.close_bracket()], self.source())?;
|
||||
if next.token == self.syntax.close_bracket() {
|
||||
self.done = true;
|
||||
}
|
||||
value
|
||||
}
|
||||
peeked_token if peeked_token == self.syntax.close_bracket() => {
|
||||
self.done = true;
|
||||
)?
|
||||
} else {
|
||||
token
|
||||
}
|
||||
_ => unreachable!(),
|
||||
} else {
|
||||
token
|
||||
};
|
||||
|
||||
// Deserialize an array element.
|
||||
self.de.push_peeked(value_token);
|
||||
seed.deserialize(&mut *self.de).map(Some)
|
||||
let result = seed.deserialize(&mut *self.de).map(Some)?;
|
||||
|
||||
let comma_or_end = self
|
||||
.de
|
||||
.next_token()
|
||||
.expect_token(&[Token::Comma, self.syntax.close_bracket()], source)?;
|
||||
if comma_or_end.token == self.syntax.close_bracket() {
|
||||
self.done = true;
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -646,8 +645,8 @@ impl<'de> MapAccess<'de> for ArrayWalker<'de, '_> {
|
|||
// implicit key
|
||||
let key = self.next_int_key;
|
||||
self.next_int_key += 1;
|
||||
self.de.push_peeked(token);
|
||||
self.de.push_peeked(next);
|
||||
self.de.push_peeked(token);
|
||||
seed.deserialize(format!("{}", key).into_deserializer())
|
||||
.map(Some)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue