You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
All configurations preserve the exact raw string while providing different parsed representations:
66
+
All configurations preserve the exact raw string of a number, while providing different parsed representations through the `JsonNumber` enum. The `parsed()` method on `JsonNumber` returns a `NumberResult` which can be matched to handle all possible outcomes.
Copy file name to clipboardExpand all lines: DESIGN.md
+49-35Lines changed: 49 additions & 35 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,7 +7,7 @@
7
7
8
8
This document outlines the design for the `picojson` crate, a high-level, allocation-free JSON pull-parser.
9
9
10
-
The primary philosophy is to build upon the lean, compact, and low-level `ujson` tokenizer to provide an ergonomic and highly efficient API for consumers.
10
+
The primary philosophy is to build upon the lean, compact, and low-level `ujson` tokenizer to provide an ergonomic API for consumers.
11
11
12
12
The core design goals are:
13
13
-**Zero Heap Allocations**: The parser must not perform any heap allocations during its operation. All memory will be provided by the caller.
@@ -21,26 +21,31 @@ Standard `Iterator` trait cannot be implemented because of borrowed return value
21
21
22
22
## 3. Memory Management: External Scratch Buffer
23
23
24
-
To achieve the zero-allocation goal while still handling complex cases like string un-escaping, the parser will not manage its own memory. Instead, the caller must provide a temporary "scratch" buffer during instantiation.
24
+
To achieve the zero-allocation goal while still handling complex cases like string un-escaping, the parser will not manage its own memory. Instead, the caller can provide a temporary "scratch" buffer during instantiation for operations that require it.
25
25
26
26
This design was chosen over an internal, fixed-size buffer to avoid complex lifetime issues with the borrow checker and to give the user full control over the memory's size and location (stack, static arena, etc.).
27
27
28
-
The parser's constructor will have the following signature:
28
+
The parser offers constructors that support both zero-copy parsing (when no escapes are present) and parsing with a scratch buffer for handling escaped strings:
29
29
30
30
```rust
31
+
// Conceptual representation of constructors
31
32
impl<'a, 'b> SliceParser<'a, 'b> {
32
-
/// Creates a new parser for the given JSON input.
33
-
///
34
-
/// - `input`: A string slice containing the JSON data to be parsed.
35
-
/// - `scratch_buffer`: A mutable byte slice for temporary operations,
/// An error bubbled up from the underlying tokenizer.
113
-
Tokenizer(ujson::Error),
114
-
/// The provided scratch buffer was not large enough for an operation.
126
+
/// An error from the underlying tokenizer (e.g., invalid syntax).
127
+
TokenizerError,
128
+
/// The provided scratch buffer was not large enough.
115
129
ScratchBufferFull,
116
130
/// A string slice was not valid UTF-8.
117
-
InvalidUtf8(core::str::Utf8Error),
118
-
/// A number string could not be parsed.
119
-
InvalidNumber(core::num::ParseFloatError),
120
-
/// The parser entered an unexpected internal state.
121
-
UnexpectedState(&'staticstr),
131
+
InvalidUtf8,
132
+
/// A number string could not be parsed as the configured type.
133
+
InvalidNumber,
134
+
// ... other specific error conditions
122
135
}
123
136
```
124
137
125
138
## 6. Dealing with non-slice input
126
139
127
-
IMPORTANT!!!
140
+
To support parsing from sources other than in-memory slices (like files, network sockets, or serial ports), the library provides a `StreamParser`. This parser is built upon a custom `Reader` trait, which is analogous to `std::io::Read` but is available in `no_std` environments.
128
141
129
-
More: In addition of taking just slice [u8] as input, we should accept an `impl Reader` of some sort.
130
-
So that the input can come no-copy from any source with low buffering
Note std::io has Read trait, but unfortunately that's not available in core::, so probably have to
133
-
make our own, and auto-implement it for arrays and slices or for anything that looks like AsRef<[u8]>
149
+
The `StreamParser` takes an implementation of this `Reader` and an internal buffer, processing the input as data becomes available. This allows for efficient parsing of large JSON documents with a small, fixed-size memory footprint.
134
150
135
-
## 7. TODO: Working with returned values
151
+
For convenience, the crate provides `picojson::ChunkReader`, a panic-free `Reader` implementation for parsing from byte slices, which is mostly useful for testing and examples.
136
152
137
-
String values in picojson now have Deref, AsRef and Format support, so using them in default examples
138
-
with things like println! is convenient and easy.
153
+
## 7. Ergonomics and Returned Values
139
154
140
-
Same should be done with Number, but it's a little more tricky to design, given the configuration
141
-
variability
155
+
String and number values returned by the parser are designed for ease of use.
142
156
143
-
## 8. TODO: Add direct defmt support for user API
157
+
-`picojson::String` implements `Deref<Target=str>`, so it can be used just like a regular `&str`.
158
+
-`picojson::JsonNumber` provides `as_int()` and `as_f64()` methods for easy conversion, along with `Deref<Target=str>` to access the raw number string. This design supports both zero-copy access to the raw number and convenient conversion to standard numeric types.
144
159
145
-
For any user of the pull parser with defmt:: enabled, all the formatting should do sensible
146
-
default things. Most tricky is number formatting. The objective is to have clean, ergonomic, readable
0 commit comments