-
Notifications
You must be signed in to change notification settings - Fork 84
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: nuke old version * feat: init deserializer * feat: error * feat: parse number * feat: deserialize more tokens * feat: deserialize more * fix: ref * chore: yoink from #2437 * feat: adapt `skip_tokens` for `justjson` * chore: imports * feat: create `ObjectAccess` * fix: compile * feat: recursion limit * feat: recursion limit grace * feat: deserialize colon * feat: deserialize array * feat: deserialize struct * feat: deserialize enum * fix: clippy * chore: remove comments * chore: temporary fix * fix: clippy * feat: implement `deserialize_identifier` * feat: pub `StackLimit`
- Loading branch information
Showing
15 changed files
with
1,211 additions
and
715 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
use deer::{ | ||
error::{ArrayAccessError, ArrayLengthError, DeserializerError, Error, Variant}, | ||
Context, Deserialize, Deserializer as _, | ||
}; | ||
use error_stack::{Report, Result, ResultExt}; | ||
use justjson::parser::{PeekableTokenKind, Token}; | ||
|
||
use crate::{ | ||
deserializer::Deserializer, | ||
error::{ErrorAccumulator, Position, SyntaxError}, | ||
skip::skip_tokens, | ||
}; | ||
|
||
pub(crate) struct ArrayAccess<'a, 'b, 'de: 'a> { | ||
deserializer: &'a mut Deserializer<'b, 'de>, | ||
|
||
dirty: bool, | ||
expected: usize, | ||
} | ||
|
||
impl<'a, 'b, 'de: 'a> ArrayAccess<'a, 'b, 'de> { | ||
pub(crate) fn new( | ||
deserializer: &'a mut Deserializer<'b, 'de>, | ||
) -> Result<Self, DeserializerError> { | ||
deserializer.try_stack_push(&Token::Array)?; | ||
|
||
Ok(Self { | ||
deserializer, | ||
dirty: false, | ||
expected: 0, | ||
}) | ||
} | ||
|
||
fn try_skip_comma(&mut self) -> Result<(), Error> { | ||
self.deserializer | ||
.try_skip(PeekableTokenKind::Comma, SyntaxError::ExpectedComma) | ||
} | ||
} | ||
|
||
impl<'de> deer::ArrayAccess<'de> for ArrayAccess<'_, '_, 'de> { | ||
fn is_dirty(&self) -> bool { | ||
self.dirty | ||
} | ||
|
||
fn context(&self) -> &Context { | ||
self.deserializer.context() | ||
} | ||
|
||
fn next<T>(&mut self) -> Option<Result<T, ArrayAccessError>> | ||
where | ||
T: Deserialize<'de>, | ||
{ | ||
let mut errors = ErrorAccumulator::new(); | ||
|
||
if self.dirty { | ||
// we parse in a way where every subsequent invocation (except the first one) | ||
// needs to parse the `,` that is the token, if that token is not present we will error | ||
// out, but(!) will still attempt deserialization, as we can tolerate that error. | ||
|
||
// the statement after this _will_ fail and return the visitor, therefore we don't | ||
// need to check for EOF | ||
if let Err(error) = self.try_skip_comma() { | ||
errors.extend_one(error); | ||
} | ||
} | ||
|
||
self.dirty = true; | ||
|
||
let peek_key = self.deserializer.peek(); | ||
|
||
// we check for `is_none` here because we could be EOF, in that case we're "done", we will | ||
// error out at `.end()` | ||
if peek_key.is_none() || peek_key == Some(PeekableTokenKind::ArrayEnd) { | ||
return None; | ||
} | ||
|
||
self.expected += 1; | ||
|
||
let value = T::deserialize(&mut *self.deserializer); | ||
|
||
Some(value.change_context(ArrayAccessError)) | ||
} | ||
|
||
fn size_hint(&self) -> Option<usize> { | ||
None | ||
} | ||
|
||
fn end(self) -> Result<(), ArrayAccessError> { | ||
self.deserializer.stack.pop(); | ||
|
||
let result = match self.deserializer.peek() { | ||
None => Err(Report::new(SyntaxError::UnexpectedEof.into_error()) | ||
.attach(Position::new(self.deserializer.offset()))), | ||
Some(PeekableTokenKind::ArrayEnd) => Ok(()), | ||
Some(_) => Err(ArrayLengthError::new(&self, self.expected)), | ||
}; | ||
|
||
skip_tokens(&mut self.deserializer.tokenizer, &Token::Array); | ||
|
||
result.change_context(ArrayAccessError) | ||
} | ||
} |
Oops, something went wrong.