mirror of
https://codeberg.org/icewind/vdf-reader.git
synced 2026-06-03 10:04:08 +02:00
parse string error
This commit is contained in:
parent
1f0a53d241
commit
f75a64204c
4 changed files with 55 additions and 34 deletions
35
src/error.rs
35
src/error.rs
|
|
@ -34,6 +34,10 @@ pub enum VdfError {
|
|||
#[diagnostic(transparent)]
|
||||
/// Failed to parse string into type
|
||||
ParseString(#[from] ParseStringError),
|
||||
#[error(transparent)]
|
||||
#[diagnostic(transparent)]
|
||||
/// Failed to parse serde string
|
||||
SerdeParse(#[from] SerdeParseError),
|
||||
#[error("{0}")]
|
||||
Other(String),
|
||||
}
|
||||
|
|
@ -173,7 +177,7 @@ impl WrongEventTypeError {
|
|||
|
||||
#[derive(Debug, Clone, Error, Diagnostic)]
|
||||
#[error("Can't parse entry {value:?} as {ty}")]
|
||||
#[diagnostic(code(vmt_parser::eof))]
|
||||
#[diagnostic(code(vmt_parser::parse_value))]
|
||||
pub struct ParseEntryError {
|
||||
pub ty: &'static str,
|
||||
pub value: Entry,
|
||||
|
|
@ -187,7 +191,7 @@ impl ParseEntryError {
|
|||
|
||||
#[derive(Debug, Clone, Error, Diagnostic)]
|
||||
#[error("Can't parse entry {value:?} as {ty}")]
|
||||
#[diagnostic(code(vmt_parser::eof))]
|
||||
#[diagnostic(code(vmt_parser::parse_item))]
|
||||
pub struct ParseItemError {
|
||||
pub ty: &'static str,
|
||||
pub value: Item<'static>,
|
||||
|
|
@ -203,8 +207,8 @@ impl ParseItemError {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, Error, Diagnostic)]
|
||||
#[error("Can't parse entry {value:?} as {ty}")]
|
||||
#[diagnostic(code(vmt_parser::eof))]
|
||||
#[error("Can't parse string {value:?} as {ty}")]
|
||||
#[diagnostic(code(vmt_parser::parse_string))]
|
||||
pub struct ParseStringError {
|
||||
pub ty: &'static str,
|
||||
pub value: String,
|
||||
|
|
@ -219,6 +223,29 @@ impl ParseStringError {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Error, Diagnostic)]
|
||||
#[error("Can't parse {value:?} as {ty}")]
|
||||
#[diagnostic(code(vmt_parser::parse_serde))]
|
||||
pub struct SerdeParseError {
|
||||
pub ty: &'static str,
|
||||
pub value: String,
|
||||
#[label("Expected a {ty}")]
|
||||
err_span: SourceSpan,
|
||||
#[source_code]
|
||||
src: String,
|
||||
}
|
||||
|
||||
impl SerdeParseError {
|
||||
pub fn new(ty: &'static str, value: &str, span: Span, src: &str) -> Self {
|
||||
SerdeParseError {
|
||||
ty,
|
||||
value: value.into(),
|
||||
err_span: span.into(),
|
||||
src: src.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ExpectToken<'source> {
|
||||
fn expect_token(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ use std::borrow::Cow;
|
|||
pub struct Reader<'a> {
|
||||
pub source: &'a str,
|
||||
lexer: SpannedIter<'a, Token>,
|
||||
peeked: Option<(Result<Token, <Token as Logos<'a>>::Error>, Span)>,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for Reader<'a> {
|
||||
|
|
@ -16,25 +15,13 @@ impl<'a> From<&'a str> for Reader<'a> {
|
|||
Reader {
|
||||
source: content,
|
||||
lexer: Lexer::new(content).spanned(),
|
||||
peeked: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Reader<'a> {
|
||||
fn token(&mut self) -> Option<(Result<Token, <Token as Logos>::Error>, Span)> {
|
||||
if let Some((token, span)) = self.peeked.take() {
|
||||
Some((token, span))
|
||||
} else {
|
||||
self.lexer.next()
|
||||
}
|
||||
}
|
||||
|
||||
fn peek(&mut self) -> Option<(Result<Token, <Token as Logos>::Error>, Span)> {
|
||||
if self.peeked.is_none() {
|
||||
self.peeked = self.lexer.next();
|
||||
}
|
||||
self.peeked.clone()
|
||||
self.lexer.next()
|
||||
}
|
||||
|
||||
pub fn span(&self) -> Span {
|
||||
|
|
|
|||
37
src/serde.rs
37
src/serde.rs
|
|
@ -1,5 +1,5 @@
|
|||
use crate::entry::ParseItem;
|
||||
use crate::error::{ExpectToken, NoValidTokenError, ParseStringError};
|
||||
use crate::error::{ExpectToken, NoValidTokenError, SerdeParseError};
|
||||
use crate::tokenizer::{SpannedToken, Tokenizer};
|
||||
use crate::{Token, VdfError};
|
||||
use logos::Span;
|
||||
|
|
@ -50,13 +50,15 @@ impl<'de> Deserializer<'de> {
|
|||
self.peeked = Some(Ok(token))
|
||||
}
|
||||
|
||||
fn read_str(&mut self) -> Result<Cow<'de, str>> {
|
||||
fn read_str(&mut self) -> Result<(Cow<'de, str>, Span)> {
|
||||
let token = self.next().expect_token(STRING_ITEMS, self.source())?;
|
||||
Ok(token.string(self.source()))
|
||||
Ok((token.string(self.source()), token.span))
|
||||
}
|
||||
|
||||
fn parse<T: ParseItem>(&mut self) -> Result<T> {
|
||||
T::from_str(self.read_str()?.as_ref()).map_err(VdfError::from)
|
||||
let (str, span) = self.read_str()?;
|
||||
T::from_str(str.as_ref())
|
||||
.map_err(|e| SerdeParseError::new(e.ty, &e.value, span, self.source()).into())
|
||||
}
|
||||
|
||||
fn set_last_key(&mut self, key: Cow<'de, str>) {
|
||||
|
|
@ -183,11 +185,16 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
|||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
let str = self.read_str()?;
|
||||
let (str, span) = self.read_str()?;
|
||||
let mut chars = str.chars();
|
||||
match (chars.next(), chars.next()) {
|
||||
(Some(_), None) => Ok(()),
|
||||
_ => Err(ParseStringError::new("char", str.as_ref())),
|
||||
_ => Err(SerdeParseError::new(
|
||||
"char",
|
||||
str.as_ref(),
|
||||
span,
|
||||
self.source(),
|
||||
)),
|
||||
}?;
|
||||
|
||||
visitor.visit_str(str.as_ref())
|
||||
|
|
@ -199,14 +206,14 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
|||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_str(self.read_str()?.as_ref())
|
||||
visitor.visit_str(self.read_str()?.0.as_ref())
|
||||
}
|
||||
|
||||
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_string(self.read_str()?.into())
|
||||
visitor.visit_string(self.read_str()?.0.into())
|
||||
}
|
||||
|
||||
// The `Serializer` implementation on the previous page serialized byte
|
||||
|
|
@ -222,7 +229,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
|||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_byte_buf(self.read_str()?.as_bytes().into())
|
||||
visitor.visit_byte_buf(self.read_str()?.0.as_bytes().into())
|
||||
}
|
||||
|
||||
// An absent optional is represented as the JSON `null` and a present
|
||||
|
|
@ -257,9 +264,9 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
|||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
let str = self.read_str()?;
|
||||
let (str, span) = self.read_str()?;
|
||||
if !str.is_empty() {
|
||||
return Err(ParseStringError::new("unit", str.as_ref()).into());
|
||||
return Err(SerdeParseError::new("unit", str.as_ref(), span, self.source()).into());
|
||||
}
|
||||
visitor.visit_unit()
|
||||
}
|
||||
|
|
@ -268,9 +275,9 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
|||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
let str = self.read_str()?;
|
||||
let (str, span) = self.read_str()?;
|
||||
if !str.is_empty() {
|
||||
return Err(ParseStringError::new("unit", str.as_ref()).into());
|
||||
return Err(SerdeParseError::new("unit", str.as_ref(), span, self.source()).into());
|
||||
}
|
||||
visitor.visit_unit()
|
||||
}
|
||||
|
|
@ -517,10 +524,10 @@ impl<'de, 'a> VariantAccess<'de> for Enum<'a, 'de> {
|
|||
type Error = VdfError;
|
||||
|
||||
fn unit_variant(self) -> Result<()> {
|
||||
let str = self.de.read_str()?;
|
||||
let (str, span) = self.de.read_str()?;
|
||||
|
||||
if !str.is_empty() {
|
||||
return Err(ParseStringError::new("unit", str.as_ref()).into());
|
||||
return Err(SerdeParseError::new("unit", str.as_ref(), span, self.source()).into());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::collections::BTreeMap;
|
||||
use std::fs::read_to_string;
|
||||
use test_case::test_case;
|
||||
use vdf_reader::from_str;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue