Skip to content

Commit 7298322

Browse files
committed
Add methods for reading borrowed strings
This initial implementation is possibly not very clean and causes quite some code duplication in `reader.rs`; ideally this should be improved in the future, if possible. Resolves #1
1 parent aaec4f4 commit 7298322

File tree

12 files changed

+1356
-456
lines changed

12 files changed

+1356
-456
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ let json = r#"{"a": [1, true]}"#;
4646
let mut json_reader = JsonStreamReader::new(json.as_bytes());
4747

4848
json_reader.begin_object()?;
49-
assert_eq!(json_reader.next_name()?, "a");
49+
assert_eq!("a", json_reader.next_name()?);
5050

5151
json_reader.begin_array()?;
5252
assert_eq!(1_u32, json_reader.next_number()??);

benches/reader_benchmark.rs

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,10 @@ fn bench_compare(c: &mut Criterion, name: &str, json: &str) {
9090
stack.push(StackValue::Object)
9191
}
9292
ValueType::String => {
93-
json_reader.next_string()?;
93+
json_reader.next_str()?;
9494
}
9595
ValueType::Number => {
96-
json_reader.next_number_as_string()?;
96+
json_reader.next_number_as_str()?;
9797
}
9898
ValueType::Boolean => {
9999
json_reader.next_bool()?;
@@ -178,13 +178,13 @@ fn benchmark_large_array(c: &mut Criterion) {
178178
.repeat(1000)
179179
.as_str()
180180
+ "true]";
181-
bench_compare(c, "read-large-array", json.as_str());
181+
bench_compare(c, "read-large-array", &json);
182182
}
183183

184184
fn benchmark_nested_object(c: &mut Criterion) {
185185
let count = 1000;
186186
let json = r#"{"member name":"#.repeat(count) + "true" + "}".repeat(count).as_str();
187-
bench_compare(c, "read-nested-object", json.as_str());
187+
bench_compare(c, "read-nested-object", &json);
188188
}
189189

190190
fn benchmark_nested_object_pretty(c: &mut Criterion) {
@@ -202,7 +202,7 @@ fn benchmark_nested_object_pretty(c: &mut Criterion) {
202202
json.push('}');
203203
}
204204

205-
bench_compare(c, "read-nested-object-pretty", json.as_str());
205+
bench_compare(c, "read-nested-object-pretty", &json);
206206
}
207207

208208
fn bench_compare_string_reading(c: &mut Criterion, name: &str, json: &str) {
@@ -212,7 +212,7 @@ fn bench_compare_string_reading(c: &mut Criterion, name: &str, json: &str) {
212212
b.iter(|| {
213213
call_unwrap(|| {
214214
let mut json_reader = JsonStreamReader::new(json.as_bytes());
215-
json_reader.next_string()?;
215+
json_reader.next_str()?;
216216
json_reader.consume_trailing_whitespace()?;
217217

218218
Ok(())
@@ -289,8 +289,8 @@ fn bench_compare_string_reading(c: &mut Criterion, name: &str, json: &str) {
289289

290290
fn benchmark_large_ascii_string(c: &mut Criterion) {
291291
let json = "\"".to_owned() + "this is a test string".repeat(10_000).as_str() + "\"";
292-
bench_compare(c, "read-large-ascii-string", json.as_str());
293-
bench_compare_string_reading(c, "read-large-ascii-string (string reading)", json.as_str());
292+
bench_compare(c, "read-large-ascii-string", &json);
293+
bench_compare_string_reading(c, "read-large-ascii-string (string reading)", &json);
294294
}
295295

296296
fn benchmark_large_unicode_string(c: &mut Criterion) {
@@ -299,12 +299,8 @@ fn benchmark_large_unicode_string(c: &mut Criterion) {
299299
.repeat(10_000)
300300
.as_str()
301301
+ "\"";
302-
bench_compare(c, "read-large-unicode-string", json.as_str());
303-
bench_compare_string_reading(
304-
c,
305-
"read-large-unicode-string (string reading)",
306-
json.as_str(),
307-
);
302+
bench_compare(c, "read-large-unicode-string", &json);
303+
bench_compare_string_reading(c, "read-large-unicode-string (string reading)", &json);
308304
}
309305

310306
fn benchmark_escapes_string(c: &mut Criterion) {
@@ -313,12 +309,8 @@ fn benchmark_escapes_string(c: &mut Criterion) {
313309
.repeat(10_000)
314310
.as_str()
315311
+ "\"";
316-
bench_compare(c, "read-large-escapes-string", json.as_str());
317-
bench_compare_string_reading(
318-
c,
319-
"read-large-escapes-string (string reading)",
320-
json.as_str(),
321-
);
312+
bench_compare(c, "read-large-escapes-string", &json);
313+
bench_compare_string_reading(c, "read-large-escapes-string (string reading)", &json);
322314
}
323315

324316
criterion_group!(

benches/reader_struct_benchmark.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,8 @@ fn benchmark_struct(c: &mut Criterion) {
2222

2323
static COUNT: usize = 5000;
2424
let json = r#"{"bool_value": true, "integer": 123456, "float": 1234.56, "string": "this is a string value"}"#.repeat(COUNT);
25-
let json = json.as_str();
2625

27-
group.bench_with_input("struson", json, |b, json| {
26+
group.bench_with_input("struson", &json, |b, json| {
2827
b.iter(|| {
2928
let mut json_reader = JsonStreamReader::new_custom(
3029
json.as_bytes(),
@@ -46,7 +45,7 @@ fn benchmark_struct(c: &mut Criterion) {
4645

4746
json_reader.begin_object()?;
4847
while json_reader.has_next()? {
49-
match json_reader.next_name()?.as_str() {
48+
match json_reader.next_name()? {
5049
"bool_value" => {
5150
bool_value = Some(json_reader.next_bool()?);
5251
}

benches/writer_benchmark.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -101,42 +101,43 @@ fn bench_compare_string_writing(c: &mut Criterion, name: &str, string_value: &st
101101

102102
fn benchmark_large_ascii_string(c: &mut Criterion) {
103103
let string_value = "this is a test string".repeat(10_000);
104-
let string_value = string_value.as_str();
105104
bench_compare(c, "write-large-ascii-string", |json_writer| {
106-
json_writer.string_value(string_value)?;
105+
json_writer.string_value(&string_value)?;
107106

108107
Ok(())
109108
});
110-
bench_compare_string_writing(c, "write-large-ascii-string (string writing)", string_value);
109+
bench_compare_string_writing(
110+
c,
111+
"write-large-ascii-string (string writing)",
112+
&string_value,
113+
);
111114
}
112115

113116
fn benchmark_large_unicode_string(c: &mut Criterion) {
114117
let string_value = "ab\u{0080}cd\u{0800}ef\u{1234}gh\u{10FFFF}".repeat(10_000);
115-
let string_value = string_value.as_str();
116118
bench_compare(c, "write-large-unicode-string", |json_writer| {
117-
json_writer.string_value(string_value)?;
119+
json_writer.string_value(&string_value)?;
118120

119121
Ok(())
120122
});
121123
bench_compare_string_writing(
122124
c,
123125
"write-large-unicode-string (string writing)",
124-
string_value,
126+
&string_value,
125127
);
126128
}
127129

128130
fn benchmark_escapes_string(c: &mut Criterion) {
129131
let string_value = r#"a\nb\tc\\d\"e\u0000f\u0080g\u0800h\u1234i\uD800\uDC00"#.repeat(10_000);
130-
let string_value = string_value.as_str();
131132
bench_compare(c, "write-large-escapes-string", |json_writer| {
132-
json_writer.string_value(string_value)?;
133+
json_writer.string_value(&string_value)?;
133134

134135
Ok(())
135136
});
136137
bench_compare_string_writing(
137138
c,
138139
"write-large-escapes-string (string writing)",
139-
string_value,
140+
&string_value,
140141
);
141142
}
142143

src/json_number.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
//! Internal module for parsing / validating JSON numbers
22
3+
pub(crate) trait NumberBytesProvider<E> {
4+
/// Consumes the byte which is currently processed, and peeks at the next.
5+
///
6+
/// Returns `None` if the end of the input has been reached.
7+
fn consume_current_peek_next(&mut self) -> Result<Option<u8>, E>;
8+
}
9+
310
/// Returns `None` if the number is invalid and `Some(exponent_digits_count)` if
411
/// the number is valid. The `exponent_digits_count` is the number of exponent
512
/// digits, without sign and without leading 0s.
6-
pub fn consume_json_number<E, F: FnMut() -> Result<Option<u8>, E>, C: FnMut(u8)>(
7-
consume_current_peek_next: &mut F,
8-
consumer: &mut C,
13+
pub(crate) fn consume_json_number<E, R: NumberBytesProvider<E>>(
14+
reader: &mut R,
915
first_byte: u8,
1016
) -> Result<Option<u32>, E> {
1117
#[derive(PartialEq)]
@@ -91,10 +97,8 @@ pub fn consume_json_number<E, F: FnMut() -> Result<Option<u8>, E>, C: FnMut(u8)>
9197
break;
9298
}
9399

94-
consumer(byte);
95-
96100
// In the first iteration this consumes the `first_byte` argument
97-
if let Some(peeked_byte) = consume_current_peek_next()? {
101+
if let Some(peeked_byte) = reader.consume_current_peek_next()? {
98102
byte = peeked_byte;
99103
} else {
100104
has_trailing_number_chars = false;

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
//! let mut json_reader = JsonStreamReader::new(json.as_bytes());
5252
//!
5353
//! json_reader.begin_object()?;
54-
//! assert_eq!(json_reader.next_name()?, "a");
54+
//! assert_eq!("a", json_reader.next_name()?);
5555
//!
5656
//! json_reader.begin_array()?;
5757
//! assert_eq!(1_u32, json_reader.next_number()??);

0 commit comments

Comments
 (0)