Correctness fixes from a round of external review (#24 to #31): reading, validating, transcoding and framing now agree on the nesting limit and on what a BEVE value is, a failed read leaves nothing behind for a reader that retries, and json::Raw checks string escapes. One breaking change: a BEVE delimiter where a value belongs is now InvalidHeader everywhere.
[dependencies]
structio = "0.7"
# The derive is off by default:
structio = { version = "0.7", features = ["derive"] }Changed
- A BEVE delimiter is never a value.
validate_beveaccepted a document that was only a delimiter, which no reader could read and no stream framed. Everywhere a value belongs, every walk now refuses one asInvalidHeader; between streamed documents it is still a separator. Breaking for code expectingUnsupportedFeaturefor a delimiter from aValueread orbeve_to_json, or relying on a delimiter as an unknown member's value being stepped over.
Fixed
-
A failed read no longer costs a reader that winds back and retries. Every reader that entered a nesting level kept it on an error path, so a speculating reader lost a level per failed attempt and, after 256, had ordinary input refused as
ExceededMaxDepth. A failed internally tagged read with a late tag could also leave its held members behind for the next object at the same depth, which then read them as its own. -
json::Rawchecks string escapes.Raw::new,Raw::from_stringand aRawfield accepted"\q"or a lone"\ud800"and wrote it back out. They now refuse any escape the string reader refuses, with the same error. The number grammar is still not checked. -
A typed array read in one copy, borrowed, or read as a
&[u8]is charged a nesting level, as every other walk charges it. A document one level from the limit read withfrom_bevebut failedvalidate_beve,beve_to_jsonand framing, and a framing failure ends aDocumentsorFeedstream. -
-0read into aValuelost its sign. It became the integer0; it is now the float-0.0, as-0.0and-0e0already were and as anf64reads it. -
A BEVE float read as an integer, or a 128-bit float read at all, no longer reports an offset past the value. Both are refused on the header before the payload is taken, so the cursor and
Error::indexstop just past the header, as every other type mismatch does.