Make Decodable and Decoder infallible.

`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
  currently panics on failure (e.g. if the input is too short, or on a
  bad `Result` discriminant), and in some places it returns an error
  (e.g. on a bad `Option` discriminant). The number of places where
  either happens is surprisingly small, just because the binary
  representation has very little redundancy and a lot of input reading
  can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
  `.rlink` file production, and there's a `FIXME` comment suggesting it
  should change to a binary format, and (b) in a few tests in
  non-fundamental ways. Indeed #85993 is open to remove it entirely.

And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.

Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
  optimization for small counts that the impl for `Result<T, E>` has,
  because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
  `collect`, which is nice; the one for `Vec` uses unsafe code, because
  that gave better perf on some benchmarks.
This commit is contained in:
Nicholas Nethercote
2022-01-18 13:22:50 +11:00
parent 88600a6d7f
commit 416399dc10
39 changed files with 726 additions and 781 deletions

View File

@@ -89,7 +89,7 @@
//! let encoded = json::encode(&object).unwrap();
//!
//! // Deserialize using `json::decode`
//! let decoded: TestStruct = json::decode(&encoded[..]).unwrap();
//! let decoded: TestStruct = json::decode(&encoded[..]);
//! ```
//!
//! ## Using the `ToJson` trait
@@ -173,7 +173,7 @@
//! let json_str: String = json_obj.to_string();
//!
//! // Deserialize like before
//! let decoded: TestStruct = json::decode(&json_str).unwrap();
//! let decoded: TestStruct = json::decode(&json_str);
//! ```
use self::DecoderError::*;
@@ -265,6 +265,12 @@ pub enum DecoderError {
ApplicationError(string::String),
}
macro_rules! bad {
($e:expr) => {{
panic!("json decode error: {:?}", $e);
}};
}
#[derive(Copy, Clone, Debug)]
pub enum EncoderError {
FmtError(fmt::Error),
@@ -295,10 +301,10 @@ pub fn error_str(error: ErrorCode) -> &'static str {
}
/// Shortcut function to decode a JSON `&str` into an object
pub fn decode<T: crate::Decodable<Decoder>>(s: &str) -> DecodeResult<T> {
pub fn decode<T: crate::Decodable<Decoder>>(s: &str) -> T {
let json = match from_str(s) {
Ok(x) => x,
Err(e) => return Err(ParseError(e)),
Err(e) => bad!(ParseError(e)),
};
let mut decoder = Decoder::new(json);
@@ -334,15 +340,6 @@ impl fmt::Display for ParserError {
}
}
impl fmt::Display for DecoderError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// FIXME this should be a nicer error
fmt::Debug::fmt(self, f)
}
}
impl std::error::Error for DecoderError {}
impl fmt::Display for EncoderError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// FIXME this should be a nicer error
@@ -2206,41 +2203,39 @@ impl Decoder {
macro_rules! expect {
($e:expr, Null) => {{
match $e {
Json::Null => Ok(()),
other => Err(ExpectedError("Null".to_owned(), other.to_string())),
Json::Null => (),
other => bad!(ExpectedError("Null".to_owned(), other.to_string())),
}
}};
($e:expr, $t:ident) => {{
match $e {
Json::$t(v) => Ok(v),
other => Err(ExpectedError(stringify!($t).to_owned(), other.to_string())),
Json::$t(v) => v,
other => bad!(ExpectedError(stringify!($t).to_owned(), other.to_string())),
}
}};
}
macro_rules! read_primitive {
($name:ident, $ty:ty) => {
fn $name(&mut self) -> DecodeResult<$ty> {
fn $name(&mut self) -> $ty {
match self.pop() {
Json::I64(f) => Ok(f as $ty),
Json::U64(f) => Ok(f as $ty),
Json::F64(f) => Err(ExpectedError("Integer".to_owned(), f.to_string())),
Json::I64(f) => f as $ty,
Json::U64(f) => f as $ty,
Json::F64(f) => bad!(ExpectedError("Integer".to_owned(), f.to_string())),
// re: #12967.. a type w/ numeric keys (ie HashMap<usize, V> etc)
// is going to have a string here, as per JSON spec.
Json::String(s) => match s.parse().ok() {
Some(f) => Ok(f),
None => Err(ExpectedError("Number".to_owned(), s)),
Some(f) => f,
None => bad!(ExpectedError("Number".to_owned(), s)),
},
value => Err(ExpectedError("Number".to_owned(), value.to_string())),
value => bad!(ExpectedError("Number".to_owned(), value.to_string())),
}
}
};
}
impl crate::Decoder for Decoder {
type Error = DecoderError;
fn read_unit(&mut self) -> DecodeResult<()> {
fn read_unit(&mut self) -> () {
expect!(self.pop(), Null)
}
@@ -2257,156 +2252,151 @@ impl crate::Decoder for Decoder {
read_primitive! { read_i64, i64 }
read_primitive! { read_i128, i128 }
fn read_f32(&mut self) -> DecodeResult<f32> {
self.read_f64().map(|x| x as f32)
fn read_f32(&mut self) -> f32 {
self.read_f64() as f32
}
fn read_f64(&mut self) -> DecodeResult<f64> {
fn read_f64(&mut self) -> f64 {
match self.pop() {
Json::I64(f) => Ok(f as f64),
Json::U64(f) => Ok(f as f64),
Json::F64(f) => Ok(f),
Json::I64(f) => f as f64,
Json::U64(f) => f as f64,
Json::F64(f) => f,
Json::String(s) => {
// re: #12967.. a type w/ numeric keys (ie HashMap<usize, V> etc)
// is going to have a string here, as per JSON spec.
match s.parse().ok() {
Some(f) => Ok(f),
None => Err(ExpectedError("Number".to_owned(), s)),
Some(f) => f,
None => bad!(ExpectedError("Number".to_owned(), s)),
}
}
Json::Null => Ok(f64::NAN),
value => Err(ExpectedError("Number".to_owned(), value.to_string())),
Json::Null => f64::NAN,
value => bad!(ExpectedError("Number".to_owned(), value.to_string())),
}
}
fn read_bool(&mut self) -> DecodeResult<bool> {
fn read_bool(&mut self) -> bool {
expect!(self.pop(), Boolean)
}
fn read_char(&mut self) -> DecodeResult<char> {
let s = self.read_str()?;
{
let mut it = s.chars();
if let (Some(c), None) = (it.next(), it.next()) {
// exactly one character
return Ok(c);
}
fn read_char(&mut self) -> char {
let s = self.read_str();
let mut it = s.chars();
if let (Some(c), None) = (it.next(), it.next()) {
// exactly one character
return c;
}
Err(ExpectedError("single character string".to_owned(), s.to_string()))
bad!(ExpectedError("single character string".to_owned(), s.to_string()));
}
fn read_str(&mut self) -> DecodeResult<Cow<'_, str>> {
expect!(self.pop(), String).map(Cow::Owned)
fn read_str(&mut self) -> Cow<'_, str> {
Cow::Owned(expect!(self.pop(), String))
}
fn read_raw_bytes_into(&mut self, s: &mut [u8]) -> Result<(), Self::Error> {
fn read_raw_bytes_into(&mut self, s: &mut [u8]) {
for c in s.iter_mut() {
*c = self.read_u8()?;
*c = self.read_u8();
}
Ok(())
()
}
fn read_enum<T, F>(&mut self, f: F) -> DecodeResult<T>
fn read_enum<T, F>(&mut self, f: F) -> T
where
F: FnOnce(&mut Decoder) -> DecodeResult<T>,
F: FnOnce(&mut Decoder) -> T,
{
f(self)
}
fn read_enum_variant<T, F>(&mut self, names: &[&str], mut f: F) -> DecodeResult<T>
fn read_enum_variant<T, F>(&mut self, names: &[&str], mut f: F) -> T
where
F: FnMut(&mut Decoder, usize) -> DecodeResult<T>,
F: FnMut(&mut Decoder, usize) -> T,
{
let name = match self.pop() {
Json::String(s) => s,
Json::Object(mut o) => {
let n = match o.remove("variant") {
Some(Json::String(s)) => s,
Some(val) => return Err(ExpectedError("String".to_owned(), val.to_string())),
None => return Err(MissingFieldError("variant".to_owned())),
Some(val) => bad!(ExpectedError("String".to_owned(), val.to_string())),
None => bad!(MissingFieldError("variant".to_owned())),
};
match o.remove("fields") {
Some(Json::Array(l)) => {
self.stack.extend(l.into_iter().rev());
}
Some(val) => return Err(ExpectedError("Array".to_owned(), val.to_string())),
None => return Err(MissingFieldError("fields".to_owned())),
Some(val) => bad!(ExpectedError("Array".to_owned(), val.to_string())),
None => bad!(MissingFieldError("fields".to_owned())),
}
n
}
json => return Err(ExpectedError("String or Object".to_owned(), json.to_string())),
json => bad!(ExpectedError("String or Object".to_owned(), json.to_string())),
};
let idx = match names.iter().position(|n| *n == &name[..]) {
Some(idx) => idx,
None => return Err(UnknownVariantError(name)),
None => bad!(UnknownVariantError(name)),
};
f(self, idx)
}
fn read_enum_variant_arg<T, F>(&mut self, f: F) -> DecodeResult<T>
fn read_enum_variant_arg<T, F>(&mut self, f: F) -> T
where
F: FnOnce(&mut Decoder) -> DecodeResult<T>,
F: FnOnce(&mut Decoder) -> T,
{
f(self)
}
fn read_struct<T, F>(&mut self, f: F) -> DecodeResult<T>
fn read_struct<T, F>(&mut self, f: F) -> T
where
F: FnOnce(&mut Decoder) -> DecodeResult<T>,
F: FnOnce(&mut Decoder) -> T,
{
let value = f(self)?;
let value = f(self);
self.pop();
Ok(value)
value
}
fn read_struct_field<T, F>(&mut self, name: &str, f: F) -> DecodeResult<T>
fn read_struct_field<T, F>(&mut self, name: &str, f: F) -> T
where
F: FnOnce(&mut Decoder) -> DecodeResult<T>,
F: FnOnce(&mut Decoder) -> T,
{
let mut obj = expect!(self.pop(), Object)?;
let mut obj = expect!(self.pop(), Object);
let value = match obj.remove(name) {
None => {
// Add a Null and try to parse it as an Option<_>
// to get None as a default value.
self.stack.push(Json::Null);
match f(self) {
Ok(x) => x,
Err(_) => return Err(MissingFieldError(name.to_string())),
}
f(self)
}
Some(json) => {
self.stack.push(json);
f(self)?
f(self)
}
};
self.stack.push(Json::Object(obj));
Ok(value)
value
}
fn read_tuple<T, F>(&mut self, tuple_len: usize, f: F) -> DecodeResult<T>
fn read_tuple<T, F>(&mut self, tuple_len: usize, f: F) -> T
where
F: FnOnce(&mut Decoder) -> DecodeResult<T>,
F: FnOnce(&mut Decoder) -> T,
{
self.read_seq(move |d, len| {
if len == tuple_len {
f(d)
} else {
Err(ExpectedError(format!("Tuple{}", tuple_len), format!("Tuple{}", len)))
bad!(ExpectedError(format!("Tuple{}", tuple_len), format!("Tuple{}", len)));
}
})
}
fn read_tuple_arg<T, F>(&mut self, f: F) -> DecodeResult<T>
fn read_tuple_arg<T, F>(&mut self, f: F) -> T
where
F: FnOnce(&mut Decoder) -> DecodeResult<T>,
F: FnOnce(&mut Decoder) -> T,
{
self.read_seq_elt(f)
}
fn read_option<T, F>(&mut self, mut f: F) -> DecodeResult<T>
fn read_option<T, F>(&mut self, mut f: F) -> T
where
F: FnMut(&mut Decoder, bool) -> DecodeResult<T>,
F: FnMut(&mut Decoder, bool) -> T,
{
match self.pop() {
Json::Null => f(self, false),
@@ -2417,28 +2407,28 @@ impl crate::Decoder for Decoder {
}
}
fn read_seq<T, F>(&mut self, f: F) -> DecodeResult<T>
fn read_seq<T, F>(&mut self, f: F) -> T
where
F: FnOnce(&mut Decoder, usize) -> DecodeResult<T>,
F: FnOnce(&mut Decoder, usize) -> T,
{
let array = expect!(self.pop(), Array)?;
let array = expect!(self.pop(), Array);
let len = array.len();
self.stack.extend(array.into_iter().rev());
f(self, len)
}
fn read_seq_elt<T, F>(&mut self, f: F) -> DecodeResult<T>
fn read_seq_elt<T, F>(&mut self, f: F) -> T
where
F: FnOnce(&mut Decoder) -> DecodeResult<T>,
F: FnOnce(&mut Decoder) -> T,
{
f(self)
}
fn read_map<T, F>(&mut self, f: F) -> DecodeResult<T>
fn read_map<T, F>(&mut self, f: F) -> T
where
F: FnOnce(&mut Decoder, usize) -> DecodeResult<T>,
F: FnOnce(&mut Decoder, usize) -> T,
{
let obj = expect!(self.pop(), Object)?;
let obj = expect!(self.pop(), Object);
let len = obj.len();
for (key, value) in obj {
self.stack.push(value);
@@ -2447,23 +2437,19 @@ impl crate::Decoder for Decoder {
f(self, len)
}
fn read_map_elt_key<T, F>(&mut self, f: F) -> DecodeResult<T>
fn read_map_elt_key<T, F>(&mut self, f: F) -> T
where
F: FnOnce(&mut Decoder) -> DecodeResult<T>,
F: FnOnce(&mut Decoder) -> T,
{
f(self)
}
fn read_map_elt_val<T, F>(&mut self, f: F) -> DecodeResult<T>
fn read_map_elt_val<T, F>(&mut self, f: F) -> T
where
F: FnOnce(&mut Decoder) -> DecodeResult<T>,
F: FnOnce(&mut Decoder) -> T,
{
f(self)
}
fn error(&mut self, err: &str) -> DecoderError {
ApplicationError(err.to_string())
}
}
/// A trait for converting values to JSON