Skip to content

Commit

Permalink
Support string prefix parsing
Browse files Browse the repository at this point in the history
This adds support for parsing json from the prefix of a string. It
does so via two small api additions:

- Deserializer now has the `into_reader` associated function, which
  consume the deserializer and returns reader it has been using.

- StrRead and SliceRead now have the `index` associated function,
  which reports the byte index of the data which will be read next.

These can be used to parse a single value (or multiple values) from
an input string or buffer, and then recover the next byte position
from the reader. It allows the json parser to be easily integrated
into an outer parser, where the JSON data is sitting inside some
larger non-JSON context.
  • Loading branch information
mullr committed Mar 7, 2023
1 parent a15bd09 commit 08b9823
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/de.rs
Expand Up @@ -60,6 +60,11 @@ where
disable_recursion_limit: false,
}
}

/// Consume the deserializer and return its inner reader.
pub fn into_reader(self) -> R {
self.read
}
}

#[cfg(feature = "std")]
Expand Down
10 changes: 10 additions & 0 deletions src/read.rs
Expand Up @@ -412,6 +412,11 @@ impl<'a> SliceRead<'a> {
}
}

/// Get the byte index of the data that will be read next
pub fn index(&self) -> usize {
self.index
}

fn position_of_index(&self, i: usize) -> Position {
let mut position = Position { line: 1, column: 0 };
for ch in &self.slice[..i] {
Expand Down Expand Up @@ -623,6 +628,11 @@ impl<'a> StrRead<'a> {
data: s,
}
}

/// Get the byte index of the data that will be read next
pub fn index(&self) -> usize {
self.delegate.index()
}
}

impl<'a> private::Sealed for StrRead<'a> {}
Expand Down
19 changes: 19 additions & 0 deletions tests/test.rs
Expand Up @@ -2407,3 +2407,22 @@ fn hash_positive_and_negative_zero() {
assert_eq!(hash(k1), hash(k2));
}
}

#[test]
fn parse_string_prefix() {
#[derive(PartialEq, Deserialize, Debug)]
struct S {
a: u32
}

let data = "{\"a\": 42} tail";

let mut de = serde_json::Deserializer::from_str(data);
let val = S::deserialize(&mut de).unwrap();

assert_eq!(val, S { a: 42 });

let str_read = de.into_reader();
let tail = &data[str_read.index()..];
assert_eq!(tail, " tail");
}

0 comments on commit 08b9823

Please sign in to comment.