Skip to content

Commit

Permalink
fix: should checking the ending when deserialize seq
Browse files Browse the repository at this point in the history
  • Loading branch information
liuq19 committed Apr 22, 2024
1 parent 0df9e30 commit 584f7ae
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 26 deletions.
5 changes: 2 additions & 3 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ use std::{
str::from_utf8_unchecked,
};

use ::serde::de::{Expected, Unexpected};
use arrayref::array_ref;
use faststr::FastStr;
use serde::de::{Expected, Unexpected};
use smallvec::SmallVec;

use super::reader::{Reader, Reference};
Expand Down Expand Up @@ -187,7 +187,6 @@ where
reason = EofWhileParsing;
index = len;
}

Error::syntax(reason, self.read.as_u8_slice(), index)
}

Expand Down Expand Up @@ -2091,7 +2090,7 @@ where

#[cold]
pub(crate) fn peek_invalid_type(&mut self, peek: u8, exp: &dyn Expected) -> Error {
use ::serde::de;
use serde::de;
let err = match peek {
b'n' => {
if let Err(err) = self.parse_literal("ull") {
Expand Down
45 changes: 22 additions & 23 deletions src/serde/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,12 @@ impl<'de, 'a, R: Reader<'de>> de::Deserializer<'de> for &'a mut Deserializer<R>
}
}
b'[' => {
let _ = DepthGuard::guard(self);
visitor.visit_seq(SeqAccess::new(self))
let ret = {
let _ = DepthGuard::guard(self);
visitor.visit_seq(SeqAccess::new(self))
}?;
self.parser.parse_array_end()?;
Ok(ret)
}
b'{' => {
let _ = DepthGuard::guard(self);
Expand Down Expand Up @@ -571,8 +575,9 @@ impl<'de, 'a, R: Reader<'de>> de::Deserializer<'de> for &'a mut Deserializer<R>
let ret = {
let _ = DepthGuard::guard(self);
visitor.visit_seq(SeqAccess::new(self))
};
ret
}?;
self.parser.parse_array_end()?;
Ok(ret)
}
_ => return Err(self.peek_invalid_type(peek, &visitor)),
};
Expand All @@ -586,9 +591,7 @@ impl<'de, 'a, R: Reader<'de>> de::Deserializer<'de> for &'a mut Deserializer<R>
where
V: de::Visitor<'de>,
{
let ret = self.deserialize_seq(visitor)?;
self.parser.parse_array_end()?;
Ok(ret)
self.deserialize_seq(visitor)
}

fn deserialize_tuple_struct<V>(
Expand All @@ -600,9 +603,7 @@ impl<'de, 'a, R: Reader<'de>> de::Deserializer<'de> for &'a mut Deserializer<R>
where
V: de::Visitor<'de>,
{
let ret = self.deserialize_seq(visitor)?;
self.parser.parse_array_end()?;
Ok(ret)
self.deserialize_seq(visitor)
}

fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
Expand Down Expand Up @@ -644,11 +645,9 @@ impl<'de, 'a, R: Reader<'de>> de::Deserializer<'de> for &'a mut Deserializer<R>
let ret = {
let _ = DepthGuard::guard(self);
visitor.visit_seq(SeqAccess::new(self))
};
match (ret, self.end_seq()) {
(Ok(ret), Ok(())) => Ok(ret),
(Err(err), _) | (_, Err(err)) => Err(err),
}
}?;
self.parser.parse_array_end()?;
Ok(ret)
}
b'{' => {
let ret = {
Expand Down Expand Up @@ -733,15 +732,18 @@ impl<'de, 'a, R: Reader<'de> + 'a> de::SeqAccess<'de> for SeqAccess<'a, R> {
where
T: de::DeserializeSeed<'de>,
{
match self.de.parser.skip_space() {
Some(b']') => Ok(None),
Some(b',') if !self.first => Ok(Some(tri!(seed.deserialize(&mut *self.de)))),
match self.de.parser.skip_space_peek() {
Some(b']') => Ok(None), // we will check the ending brace after `visit_seq`
Some(b',') if !self.first => {
self.de.parser.read.eat(1);
Ok(Some(tri!(seed.deserialize(&mut *self.de))))
}
Some(_) => {
if self.first {
self.de.parser.read.backward(1);
self.first = false;
Ok(Some(tri!(seed.deserialize(&mut *self.de))))
} else {
self.de.parser.read.eat(1); // makes the error position is correct
Err(self.de.parser.error(ErrorCode::ExpectedArrayCommaOrEnd))
}
}
Expand Down Expand Up @@ -866,10 +868,7 @@ impl<'de, 'a, R: Reader<'de> + 'a> de::VariantAccess<'de> for VariantAccess<'a,
where
V: de::Visitor<'de>,
{
let parser = &mut self.de.parser as *mut Parser<R>;
let ret = de::Deserializer::deserialize_seq(self.de, visitor)?;
unsafe { (*parser).parse_array_end()? };
Ok(ret)
de::Deserializer::deserialize_seq(self.de, visitor)
}

fn struct_variant<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value>
Expand Down
49 changes: 49 additions & 0 deletions src/serde/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,4 +353,53 @@ mod test {
test_struct!(Bytes, &b"[]"[..]);
test_struct!(Data, &br#"{"content":[1,2,3,4,5]}"#[..]);
}

use std::{
fmt::{Formatter, Result as FmtResult},
result::Result as StdResult,
};

fn my_deseirlize_seq<'de, D>(deserializer: D) -> StdResult<(i64, i64), D::Error>
where
D: serde::de::Deserializer<'de>,
{
struct TupleVisitor;

impl<'de> serde::de::Visitor<'de> for TupleVisitor {
type Value = (i64, i64);

fn expecting(&self, formatter: &mut Formatter) -> FmtResult {
formatter.write_str("expect an array")
}

fn visit_seq<S>(self, mut seq: S) -> StdResult<Self::Value, S::Error>
where
S: serde::de::SeqAccess<'de>,
{
let x = seq
.next_element::<i64>()?
.ok_or_else(|| serde::de::Error::invalid_length(0, &self))?;
let y = seq
.next_element::<i64>()?
.ok_or_else(|| serde::de::Error::invalid_length(1, &self))?;
Ok((x, y))
}
}

deserializer.deserialize_seq(TupleVisitor)
}

#[derive(serde::Deserialize, Eq, PartialEq)]
struct MyTuple {
#[serde(deserialize_with = "my_deseirlize_seq")]
data: (i64, i64),
}

#[test]
fn test_serde_with_seq() {
let json = r#"{"data":[1, 2]}"#;
let expect: MyTuple = serde_json::from_str(json).unwrap();
let got: MyTuple = from_str(json).unwrap();
assert_eq!(expect.data, got.data);
}
}

0 comments on commit 584f7ae

Please sign in to comment.