switch to miette for error reporting

This commit is contained in:
Robin Appelman 2021-08-29 20:30:35 +02:00
commit 097ed69b9e
9 changed files with 387 additions and 316 deletions

View file

@ -2,36 +2,30 @@ use crate::lexer::{SpannedToken, Token};
use crate::num::ParseIntError;
use crate::string::UnescapeError;
use logos::Span;
use source_span::{
fmt::{Formatter, Style},
DefaultMetrics, Position, SourceBuffer, Span as SourceSpan,
};
use miette::{Diagnostic, SourceOffset, SourceSpan};
use std::error::Error;
use std::fmt::{self, Debug, Display};
use std::fmt::{self, Debug, Display, Formatter};
use std::num::ParseFloatError;
use std::str::ParseBoolError;
use thiserror::Error;
/// An error and related source span
///
/// You can pretty-print the error with the offending source by using `with_source`
///
/// ## Example
///
/// ```text
/// . |
/// 2 | [
/// 3 | "broken"
/// 4 | "array"
/// | ^^^^^^^^ Unexpected token, found LiteralString expected one of [SquareClose, Comma, Arrow]
/// 5 | ]
/// 6 |
/// ```
///
#[derive(Debug, Clone)]
pub struct ParseError {
span: Option<Span>,
error: RawParseError,
#[derive(Error, Debug, Clone, Diagnostic)]
pub enum ParseError {
#[error(transparent)]
#[diagnostic(transparent)]
UnexpectedToken(#[from] UnexpectedTokenError),
#[error(transparent)]
#[diagnostic(transparent)]
InvalidPrimitive(#[from] PrimitiveError),
#[error("Array key not valid for this position")]
#[diagnostic(code(php_object_parser::invalid_array_key))]
UnexpectedArrayKey(ArrayKeyError),
#[error("Trailing characters after parsing")]
#[diagnostic(code(php_object_parser::trailing))]
TrailingCharacters,
#[error("{0}")]
#[diagnostic(code(php_object_parser::other))]
Custom(String),
}
impl serde::de::Error for ParseError {
@ -39,181 +33,85 @@ impl serde::de::Error for ParseError {
where
T: Display,
{
ParseError {
span: None,
error: RawParseError::custom(msg),
}
ParseError::Custom(msg.to_string())
}
}
impl ParseError {
pub fn new(error: RawParseError, span: Span) -> Self {
ParseError {
span: Some(span),
error,
}
}
pub fn error(&self) -> &RawParseError {
&self.error
}
pub fn with_source(self, source: &str) -> SourceSpannedError {
SourceSpannedError {
span: self.span,
error: self.error,
source,
}
}
}
impl Error for ParseError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
Some(&self.error)
}
}
impl Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<RawParseError as Display>::fmt(&self.error, f)
}
}
impl From<RawParseError> for ParseError {
fn from(err: RawParseError) -> Self {
ParseError {
span: None,
error: err,
}
}
}
pub struct SourceSpannedError<'source> {
span: Option<Span>,
error: RawParseError,
source: &'source str,
}
impl<'source> SourceSpannedError<'source> {
pub fn into_inner(self) -> ParseError {
ParseError {
span: self.span,
error: self.error,
}
}
}
const METRICS: DefaultMetrics = DefaultMetrics::with_tab_stop(4);
impl<'source> Display for SourceSpannedError<'source> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.span.as_ref() {
Some(span) => {
let start = get_position(self.source, span.start);
let end = get_position(self.source, span.end);
let span = SourceSpan::new(start, end, end.next_line());
let mut fmt = Formatter::new();
let buffer = SourceBuffer::new(
self.source.chars().map(|char| Result::<char, ()>::Ok(char)),
Position::default(),
METRICS,
);
fmt.add(span, Some(format!("{}", self.error)), Style::Error);
let formatted = fmt
.render(
buffer.iter(),
SourceSpan::new(
Position::default(),
Position::new(usize::max_value() - 1, usize::max_value()),
Position::end(),
),
&METRICS,
)
.unwrap();
write!(f, "{}", formatted)?;
}
None => write!(f, "{}", self.error)?,
}
Ok(())
}
}
fn get_position(text: &str, index: usize) -> Position {
let mut pos = Position::default();
for char in text.chars().take(index) {
pos = pos.next(char, &METRICS);
}
pos
}
#[derive(Error, Debug, Clone)]
pub enum RawParseError {
#[error("{0}")]
UnexpectedToken(#[from] UnexpectedTokenError),
#[error("Invalid boolean literal: {0}")]
InvalidBoolLiteral(#[from] ParseBoolError),
#[error("Invalid integer literal: {0}")]
InvalidIntLiteral(#[from] ParseIntError),
#[error("Invalid float literal: {0}")]
InvalidFloatLiteral(#[from] ParseFloatError),
#[error("Invalid string literal")]
InvalidStringLiteral,
#[error("Array key not valid for this position")]
UnexpectedArrayKey,
#[error("Trailing characters after parsing")]
TrailingCharacters,
#[error("{0}")]
Custom(String),
}
impl serde::de::Error for RawParseError {
fn custom<T>(msg: T) -> Self
where
T: Display,
{
RawParseError::Custom(msg.to_string())
}
}
impl From<UnescapeError> for RawParseError {
fn from(_: UnescapeError) -> Self {
RawParseError::InvalidStringLiteral
}
}
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Diagnostic)]
#[diagnostic(code(php_object_parser::unexpected_token))]
pub struct UnexpectedTokenError {
pub expected: Vec<Token>,
src: String,
#[snippet(src)]
snip: SourceSpan,
#[highlight(snip, label("Expected {}", self.expected))]
err_span: SourceSpan,
pub expected: TokenList,
pub found: Option<Token>,
}
impl UnexpectedTokenError {
pub fn new(expected: &[Token], found: Option<Token>) -> Self {
pub fn new(
expected: &[Token],
found: Option<Token>,
src: String,
snip: SourceSpan,
err_span: SourceSpan,
) -> Self {
UnexpectedTokenError {
expected: expected.to_vec(),
src,
snip,
err_span,
expected: expected.into(),
found,
}
}
}
#[derive(Clone)]
pub struct TokenList(Vec<Token>);
impl Debug for TokenList {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl From<&[Token]> for TokenList {
fn from(list: &[Token]) -> Self {
TokenList(list.into())
}
}
impl Display for TokenList {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
if !self.0.is_empty() {
let mut tokens = self.0[0..self.0.len() - 1].iter();
write!(f, "{}", tokens.next().unwrap())?;
for token in tokens {
write!(f, ", {}", token)?;
}
if self.0.len() > 1 {
write!(f, " or {}", self.0.last().unwrap())?;
}
}
Ok(())
}
}
impl Display for UnexpectedTokenError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.found {
Some(Token::Error) => write!(
f,
"No valid token found, expected one of {:?}",
self.expected
),
Some(Token::Error) => {
write!(f, "No valid token found, expected one of {}", self.expected)
}
Some(token) => write!(
f,
"Unexpected token, found {:?} expected one of {:?}",
"Unexpected token, found {} expected one of {}",
token, self.expected
),
None => write!(
f,
"Unexpected token, found None expected one of {:?}",
"Unexpected token, found None expected one of {}",
self.expected
),
}
@ -222,55 +120,158 @@ impl Display for UnexpectedTokenError {
impl Error for UnexpectedTokenError {}
pub trait ExpectToken<'source> {
fn expect_token(self, expected: &[Token]) -> Result<SpannedToken<'source>, ParseError>;
#[derive(Debug, Clone, Error, Diagnostic)]
#[diagnostic(code(php_object_parser::invalid_primitive))]
#[error("{kind}")]
pub struct PrimitiveError {
src: String,
#[snippet(src)]
snip: SourceSpan,
#[highlight(snip, label("{}", self.kind.desc()))]
err_span: SourceSpan,
pub kind: PrimitiveErrorKind,
}
impl<'source> ExpectToken<'source> for Option<SpannedToken<'source>> {
fn expect_token(self, expected: &[Token]) -> Result<SpannedToken<'source>, ParseError> {
self.ok_or_else(|| UnexpectedTokenError {
expected: expected.to_vec(),
found: None,
})
.with_span(usize::max_value()..usize::max_value())
.and_then(|token| token.expect_token(expected))
}
#[derive(Error, Debug, Clone)]
pub enum PrimitiveErrorKind {
#[error("Invalid boolean literal: {0}")]
InvalidBoolLiteral(#[from] ParseBoolError),
#[error("Invalid integer literal: {0}")]
InvalidIntLiteral(#[from] ParseIntError),
#[error("Invalid float literal: {0}")]
InvalidFloatLiteral(#[from] ParseFloatError),
#[error("Invalid string literal")]
InvalidStringLiteral,
}
impl<'a, 'source> ExpectToken<'source> for Option<&'a SpannedToken<'source>> {
fn expect_token(self, expected: &[Token]) -> Result<SpannedToken<'source>, ParseError> {
self.ok_or_else(|| UnexpectedTokenError {
expected: expected.to_vec(),
found: None,
})
.with_span(usize::max_value()..usize::max_value())
.and_then(|token| token.clone().expect_token(expected))
}
}
impl<'source> ExpectToken<'source> for SpannedToken<'source> {
fn expect_token(self, expected: &[Token]) -> Result<SpannedToken<'source>, ParseError> {
if expected.iter().any(|expect| self.token.eq(expect)) {
Ok(self)
} else {
Err(UnexpectedTokenError {
expected: expected.to_vec(),
found: Some(self.token),
})
.with_span(self.span)
impl PrimitiveErrorKind {
pub fn desc(&self) -> &str {
match self {
PrimitiveErrorKind::InvalidBoolLiteral(_) => "Not a boolean",
PrimitiveErrorKind::InvalidIntLiteral(err) => err.desc(),
PrimitiveErrorKind::InvalidFloatLiteral(_) => "Not a valid float",
PrimitiveErrorKind::InvalidStringLiteral => "Not a string literal",
}
}
}
pub trait ResultExt<T> {
fn with_span(self, span: Span) -> Result<T, ParseError>;
impl From<UnescapeError> for PrimitiveErrorKind {
fn from(_: UnescapeError) -> Self {
PrimitiveErrorKind::InvalidStringLiteral
}
}
impl<T, E: Into<RawParseError>> ResultExt<T> for Result<T, E> {
fn with_span(self, span: Span) -> Result<T, ParseError> {
self.map_err(|error| ParseError {
span: Some(span),
error: error.into(),
#[derive(Debug, Clone, Error, Diagnostic)]
#[diagnostic(code(php_object_parser::invalid_array_key))]
#[error("Invalid array key")]
pub struct ArrayKeyError {
src: String,
#[snippet(src)]
snip: SourceSpan,
#[highlight(snip, label("This is the highlight"))]
err_span: SourceSpan,
}
impl ArrayKeyError {
pub fn new(source: &str, snip: Span, err_span: Span) -> Self {
ArrayKeyError {
src: source.into(),
snip: map_span(&snip),
err_span: map_span(&err_span),
}
}
}
pub trait ExpectToken<'source> {
fn expect_token(
self,
expected: &[Token],
source: &str,
) -> Result<SpannedToken<'source>, ParseError>;
}
impl<'source> ExpectToken<'source> for Option<SpannedToken<'source>> {
fn expect_token(
self,
expected: &[Token],
source: &str,
) -> Result<SpannedToken<'source>, ParseError> {
self.ok_or_else(|| {
UnexpectedTokenError::new(
expected,
None,
source.into(),
map_span(&(0..source.len())),
map_span(&(source.len()..source.len())),
)
.into()
})
.and_then(|token| token.expect_token(expected, source))
}
}
impl<'a, 'source> ExpectToken<'source> for Option<&'a SpannedToken<'source>> {
fn expect_token(
self,
expected: &[Token],
source: &str,
) -> Result<SpannedToken<'source>, ParseError> {
self.ok_or_else(|| {
UnexpectedTokenError::new(
expected,
None,
source.into(),
map_span(&(0..source.len())),
map_span(&(source.len()..source.len())),
)
.into()
})
.and_then(|token| token.clone().expect_token(expected, source))
}
}
impl<'source> ExpectToken<'source> for SpannedToken<'source> {
fn expect_token(
self,
expected: &[Token],
source: &str,
) -> Result<SpannedToken<'source>, ParseError> {
if expected.iter().any(|expect| self.token.eq(expect)) {
Ok(self)
} else {
Err(UnexpectedTokenError::new(
expected,
Some(self.token),
source.into(),
map_span(&(0..source.len())),
map_span(&self.span),
)
.into())
}
}
}
fn map_span(span: &Span) -> SourceSpan {
SourceSpan::new(
SourceOffset::from(span.start),
SourceOffset::from(span.end - span.start),
)
}
pub trait ResultExt<T> {
fn with_span(self, span: Span, source: &str) -> Result<T, ParseError>;
}
impl<T, E: Into<PrimitiveErrorKind>> ResultExt<T> for Result<T, E> {
fn with_span(self, span: Span, source: &str) -> Result<T, ParseError> {
self.map_err(|error| {
PrimitiveError {
src: source.into(),
snip: map_span(&(0..source.len())),
err_span: map_span(&span),
kind: error.into(),
}
.into()
})
}
}

View file

@ -1,38 +1,53 @@
use logos::{Lexer, Logos, Span};
use parse_display::Display;
use std::fmt::{Debug, Formatter};
#[derive(Logos, Debug, PartialEq, Clone, Copy)]
#[derive(Logos, Debug, PartialEq, Clone, Copy, Display)]
pub enum Token {
#[token("array")]
#[display("'array'")]
Array,
#[regex("(?i:true|false)")]
#[display("boolean literal")]
Bool,
#[regex("null")]
#[token("null")]
#[display("'null'")]
Null,
#[token("=>")]
#[display("'=>'")]
Arrow,
#[token("(")]
#[display("'('")]
BracketOpen,
#[token(")")]
#[display("')'")]
BracketClose,
#[token("[")]
#[display("'['")]
SquareOpen,
#[token("]")]
#[display("']'")]
SquareClose,
#[token(",")]
#[display("','")]
Comma,
#[display("string literal")]
#[regex("(\"([^\"\\\\]|\\\\.)*\")|(\'([^\'\\\\]|\\\\.)*\')")]
LiteralString,
#[display("float literal")]
#[regex("-?((([0-9]+(_[0-9]+)*|([0-9]*(_[0-9]+)*[\\.][0-9]+(_[0-9]+)*)|([0-9]+(_[0-9]+)*[\\.][0-9]*(_[0-9]+)*)))[eE][+-]?[0-9]+(_[0-9]+)*|([0-9]*(_[0-9]+)*[\\.][0-9]+(_[0-9]+)*)|([0-9]+(_[0-9]+)*[\\.][0-9]*(_[0-9]+)*))")]
Float,
#[display("integer literal")]
#[regex("-?(0|[1-9][0-9]*(_[0-9]+)*|0[xX][0-9a-fA-F]+(_[0-9a-fA-F]+)*|0[0-7]+(_[0-7]+)*|0[bB][01]+(_[01]+)*)")]
Integer,
#[token(";")]
#[display("';'")]
SemiColon,
#[error]
#[regex(r"(#|//)[^\n]*", logos::skip)]
#[regex(r"/\*([^*]|\*[^/])+\*/", logos::skip)]
#[regex(r"[ \t\n\f]+", logos::skip)]
#[display("error")]
Error,
}

View file

@ -55,7 +55,7 @@ mod serde_impl;
mod string;
use crate::string::is_array_key_numeric;
pub use error::{ParseError, RawParseError};
pub use error::ParseError;
use serde::de::{self, MapAccess, SeqAccess, Visitor};
use serde::{Deserialize, Deserializer};
pub use serde_impl::from_str;

View file

@ -11,8 +11,18 @@ pub enum ParseIntError {
#[error("unexpected negative number")]
UnexpectedNegative,
}
impl ParseIntError {
pub fn desc(&self) -> &str {
match self {
ParseIntError::Empty => "Number expected",
ParseIntError::InvalidDigit => "Not a valid digit",
ParseIntError::Overflow => "Number to large",
ParseIntError::UnexpectedNegative => "Expected a positive number",
}
}
}
/// Mostly copied from std
/// Mostly copied from std, adjusted for php specifics
pub fn parse_int(src: &str) -> Result<i64, ParseIntError> {
if src.is_empty() {
return Err(ParseIntError::Empty);

View file

@ -8,12 +8,14 @@ use std::iter::Peekable;
use std::num::ParseFloatError;
pub struct Parser<'source> {
source: &'source str,
tokens: Peekable<TokenStream<'source>>,
}
impl<'source> Parser<'source> {
pub fn new(source: &'source str) -> Self {
Parser {
source,
tokens: TokenStream::new(Token::lexer(source)).peekable(),
}
}
@ -40,29 +42,32 @@ impl<'source> Parser<'source> {
.slice()
.to_ascii_lowercase()
.parse()
.with_span(token.span)
.with_span(token.span, token.source)
}
pub fn parse_int_token(&self, token: SpannedToken) -> Result<i64, ParseError> {
parse_int(token.slice()).with_span(token.span)
parse_int(token.slice()).with_span(token.span, token.source)
}
pub fn parse_float_token(&self, token: SpannedToken) -> Result<f64, ParseError> {
parse_float(token.slice()).with_span(token.span)
parse_float(token.slice()).with_span(token.span, token.source)
}
pub fn parse_string_token(&self, token: SpannedToken) -> Result<String, ParseError> {
parse_string(token.slice()).with_span(token.span)
parse_string(token.slice()).with_span(token.span, token.source)
}
pub fn parse_array_key(&self, token: SpannedToken) -> Result<Key, ParseError> {
let token = token.expect_token(&[
Token::Bool,
Token::Integer,
Token::Float,
Token::LiteralString,
Token::Null,
])?;
let token = token.expect_token(
&[
Token::Bool,
Token::Integer,
Token::Float,
Token::LiteralString,
Token::Null,
],
self.source,
)?;
Ok(match self.parse_literal(token)? {
Value::Int(int) => Key::Int(int),
Value::Float(float) => Key::Int(float as i64),
@ -73,6 +78,10 @@ impl<'source> Parser<'source> {
_ => unreachable!(),
})
}
pub fn source(&self) -> &'source str {
self.source
}
}
fn parse_float(literal: &str) -> Result<f64, ParseFloatError> {

View file

@ -4,11 +4,11 @@ use serde::de::{
};
use serde::Deserialize;
use crate::error::{ExpectToken, ResultExt};
use crate::error::{ArrayKeyError, ExpectToken, ResultExt};
use crate::lexer::{SpannedToken, Token};
use crate::num::ParseIntError;
use crate::parser::{ArraySyntax, Parser};
use crate::{Key, ParseError, RawParseError};
use crate::{Key, ParseError};
use std::collections::VecDeque;
use std::convert::TryFrom;
@ -26,6 +26,10 @@ impl<'de> Deserializer<'de> {
peeked: Default::default(),
}
}
pub fn source(&self) -> &'de str {
self.parser.source()
}
}
/// Parse a php literal
@ -58,7 +62,7 @@ where
token: Token::SemiColon,
..
}) => Ok(t),
Some(_) => Err(RawParseError::TrailingCharacters.into()),
Some(_) => Err(ParseError::TrailingCharacters.into()),
}
}
@ -80,7 +84,9 @@ impl<'de> Deserializer<'de> {
}
fn parse_bool(&mut self) -> Result<bool> {
let token = self.next_token().expect_token(&[Token::Bool])?;
let token = self
.next_token()
.expect_token(&[Token::Bool], self.source())?;
Ok(self.parser.parse_bool_token(token)?)
}
@ -92,22 +98,16 @@ impl<'de> Deserializer<'de> {
where
T: TryFrom<i64>,
{
let token = self.next_token().expect_token(&[Token::Integer])?;
let token = self
.next_token()
.expect_token(&[Token::Integer], self.source())?;
let span = token.span.clone();
let int = self.parser.parse_int_token(token)?;
if int < 0 {
Err(ParseError::new(
RawParseError::InvalidIntLiteral(ParseIntError::UnexpectedNegative),
span,
)
.into())
Err(ParseIntError::UnexpectedNegative).with_span(span, self.source())
} else {
Ok(T::try_from(int).map_err(|_| {
ParseError::new(
RawParseError::InvalidIntLiteral(ParseIntError::Overflow),
span,
)
})?)
Ok(T::try_from(int)
.or_else(|_| Err(ParseIntError::Overflow).with_span(span, self.source()))?)
}
}
@ -115,25 +115,25 @@ impl<'de> Deserializer<'de> {
where
T: TryFrom<i64>,
{
let token = self.next_token().expect_token(&[Token::Integer])?;
let token = self
.next_token()
.expect_token(&[Token::Integer], self.source())?;
let span = token.span.clone();
Ok(
T::try_from(self.parser.parse_int_token(token)?).map_err(|_| {
ParseError::new(
RawParseError::InvalidIntLiteral(ParseIntError::Overflow),
span,
)
})?,
)
Ok(T::try_from(self.parser.parse_int_token(token)?)
.or_else(|_| Err(ParseIntError::Overflow).with_span(span, self.source()))?)
}
fn parse_float(&mut self) -> Result<f64> {
let token = self.next_token().expect_token(&[Token::Float])?;
let token = self
.next_token()
.expect_token(&[Token::Float], self.source())?;
Ok(self.parser.parse_float_token(token)?)
}
fn parse_string(&mut self) -> Result<String> {
let token = self.next_token().expect_token(&[Token::LiteralString])?;
let token = self
.next_token()
.expect_token(&[Token::LiteralString], self.source())?;
Ok(self.parser.parse_string_token(token)?)
}
}
@ -145,15 +145,19 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
where
V: Visitor<'de>,
{
let peek = self.peek_token().expect_token(&[
Token::Null,
Token::Bool,
Token::LiteralString,
Token::Integer,
Token::Float,
Token::Array,
Token::SquareOpen,
])?;
let source = self.source();
let peek = self.peek_token().expect_token(
&[
Token::Null,
Token::Bool,
Token::LiteralString,
Token::Integer,
Token::Float,
Token::Array,
Token::SquareOpen,
],
source,
)?;
match peek.token {
Token::Null => self.deserialize_unit(visitor),
Token::Bool => self.deserialize_bool(visitor),
@ -300,15 +304,19 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
where
V: Visitor<'de>,
{
let token = self.peek_token().expect_token(&[
Token::Null,
Token::Bool,
Token::LiteralString,
Token::Integer,
Token::Float,
Token::Array,
Token::SquareOpen,
])?;
let source = self.source();
let token = self.peek_token().expect_token(
&[
Token::Null,
Token::Bool,
Token::LiteralString,
Token::Integer,
Token::Float,
Token::Array,
Token::SquareOpen,
],
source,
)?;
if token.token == Token::Null {
let _ = self.next_token();
visitor.visit_none()
@ -321,7 +329,8 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
where
V: Visitor<'de>,
{
self.next_token().expect_token(&[Token::Null])?;
self.next_token()
.expect_token(&[Token::Null], self.source())?;
visitor.visit_unit()
}
@ -345,10 +354,11 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
{
let token = self
.next_token()
.expect_token(&[Token::Array, Token::SquareOpen])?;
.expect_token(&[Token::Array, Token::SquareOpen], self.source())?;
let syntax = match token.token {
Token::Array => {
self.next_token().expect_token(&[Token::BracketOpen])?;
self.next_token()
.expect_token(&[Token::BracketOpen], self.source())?;
ArraySyntax::Long
}
Token::SquareOpen => ArraySyntax::Short,
@ -384,10 +394,11 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
{
let token = self
.next_token()
.expect_token(&[Token::Array, Token::SquareOpen])?;
.expect_token(&[Token::Array, Token::SquareOpen], self.source())?;
let syntax = match token.token {
Token::Array => {
self.next_token().expect_token(&[Token::BracketOpen])?;
self.next_token()
.expect_token(&[Token::BracketOpen], self.source())?;
ArraySyntax::Long
}
Token::SquareOpen => ArraySyntax::Short,
@ -419,25 +430,26 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
where
V: Visitor<'de>,
{
// panic!("a");
let token = self.peek_token().expect_token(&[
Token::LiteralString,
Token::Array,
Token::SquareOpen,
])?;
let source = self.source();
let token = self.peek_token().expect_token(
&[Token::LiteralString, Token::Array, Token::SquareOpen],
source,
)?;
match token.token {
Token::LiteralString => visitor.visit_enum(self.parse_string()?.into_deserializer()),
Token::Array | Token::SquareOpen => {
self.eat_token();
let syntax = if token.token == Token::Array {
self.next_token().expect_token(&[Token::BracketOpen])?;
self.next_token()
.expect_token(&[Token::BracketOpen], self.source())?;
ArraySyntax::Long
} else {
ArraySyntax::Short
};
let value = visitor.visit_enum(Enum::new(self))?;
self.next_token().expect_token(&[syntax.close_bracket()])?;
self.next_token()
.expect_token(&[syntax.close_bracket()], self.source())?;
Ok(value)
}
_ => unreachable!(),
@ -475,6 +487,10 @@ impl<'source, 'a> ArrayWalker<'source, 'a> {
done: false,
}
}
fn source(&self) -> &'source str {
self.de.source()
}
}
impl<'de, 'a> SeqAccess<'de> for ArrayWalker<'de, 'a> {
@ -488,27 +504,29 @@ impl<'de, 'a> SeqAccess<'de> for ArrayWalker<'de, 'a> {
return Ok(None);
}
let token = self.de.next_token().expect_token(&[
Token::Bool,
Token::Integer,
Token::Float,
Token::LiteralString,
Token::Null,
Token::Array,
Token::SquareOpen,
self.syntax.close_bracket(),
])?;
let token = self.de.next_token().expect_token(
&[
Token::Bool,
Token::Integer,
Token::Float,
Token::LiteralString,
Token::Null,
Token::Array,
Token::SquareOpen,
self.syntax.close_bracket(),
],
self.source(),
)?;
if token.token == self.syntax.close_bracket() {
self.done = true;
return Ok(None);
}
let next = self.de.next_token().expect_token(&[
self.syntax.close_bracket(),
Token::Comma,
Token::Arrow,
])?;
let next = self.de.next_token().expect_token(
&[self.syntax.close_bracket(), Token::Comma, Token::Arrow],
self.source(),
)?;
let value_token = match next.token.clone() {
Token::Comma => token,
@ -517,22 +535,29 @@ impl<'de, 'a> SeqAccess<'de> for ArrayWalker<'de, 'a> {
let key = self.de.parser.parse_array_key(token)?;
match key {
Key::Int(key) if key == self.next_int_key => Ok(()),
_ => Err(RawParseError::UnexpectedArrayKey).with_span(span),
_ => Err(ParseError::UnexpectedArrayKey(ArrayKeyError::new(
self.source(),
span.clone(),
span,
))),
}?;
self.next_int_key += 1;
let value = self.de.next_token().expect_token(&[
Token::Bool,
Token::Integer,
Token::Float,
Token::LiteralString,
Token::Null,
Token::Array,
Token::SquareOpen,
])?;
let value = self.de.next_token().expect_token(
&[
Token::Bool,
Token::Integer,
Token::Float,
Token::LiteralString,
Token::Null,
Token::Array,
Token::SquareOpen,
],
self.source(),
)?;
let next = self
.de
.next_token()
.expect_token(&[Token::Comma, self.syntax.close_bracket()])?;
.expect_token(&[Token::Comma, self.syntax.close_bracket()], self.source())?;
if next.token == self.syntax.close_bracket() {
self.done = true;
}
@ -562,25 +587,27 @@ impl<'de, 'a> MapAccess<'de> for ArrayWalker<'de, 'a> {
return Ok(None);
}
let token = self.de.next_token().expect_token(&[
Token::Bool,
Token::Integer,
Token::Float,
Token::LiteralString,
Token::Null,
self.syntax.close_bracket(),
])?;
let token = self.de.next_token().expect_token(
&[
Token::Bool,
Token::Integer,
Token::Float,
Token::LiteralString,
Token::Null,
self.syntax.close_bracket(),
],
self.source(),
)?;
if token.token == self.syntax.close_bracket() {
self.done = true;
return Ok(None);
}
let next = self.de.next_token().expect_token(&[
Token::Arrow,
Token::Comma,
self.syntax.close_bracket(),
])?;
let next = self.de.next_token().expect_token(
&[Token::Arrow, Token::Comma, self.syntax.close_bracket()],
self.source(),
)?;
match next.token {
Token::Arrow => {
@ -607,15 +634,19 @@ impl<'de, 'a> MapAccess<'de> for ArrayWalker<'de, 'a> {
where
V: DeserializeSeed<'de>,
{
self.de.peek_token().expect_token(&[
Token::Bool,
Token::Integer,
Token::Float,
Token::LiteralString,
Token::Null,
Token::Array,
Token::SquareOpen,
])?;
let source = self.source();
self.de.peek_token().expect_token(
&[
Token::Bool,
Token::Integer,
Token::Float,
Token::LiteralString,
Token::Null,
Token::Array,
Token::SquareOpen,
],
source,
)?;
// Deserialize a map key.
let value = seed.deserialize(&mut *self.de)?;
@ -623,7 +654,7 @@ impl<'de, 'a> MapAccess<'de> for ArrayWalker<'de, 'a> {
let next = self
.de
.next_token()
.expect_token(&[Token::Comma, self.syntax.close_bracket()])?;
.expect_token(&[Token::Comma, self.syntax.close_bracket()], self.source())?;
if next.token == self.syntax.close_bracket() {
self.done = true;
@ -640,6 +671,10 @@ impl<'a, 'de> Enum<'a, 'de> {
fn new(de: &'a mut Deserializer<'de>) -> Self {
Enum { de }
}
fn source(&self) -> &'de str {
self.de.source()
}
}
// `EnumAccess` is provided to the `Visitor` to give it the ability to determine
@ -656,7 +691,9 @@ impl<'de, 'a> EnumAccess<'de> for Enum<'a, 'de> {
V: DeserializeSeed<'de>,
{
let val = seed.deserialize(&mut *self.de)?;
self.de.next_token().expect_token(&[Token::Arrow])?;
self.de
.next_token()
.expect_token(&[Token::Arrow], self.source())?;
Ok((val, self))
}
}
@ -667,7 +704,9 @@ impl<'de, 'a> VariantAccess<'de> for Enum<'a, 'de> {
type Error = ParseError;
fn unit_variant(self) -> Result<()> {
self.de.next_token().expect_token(&[Token::LiteralString])?;
self.de
.next_token()
.expect_token(&[Token::LiteralString], self.source())?;
Ok(())
}