1
Fork 0

Remove support for JSON deserialization to Rust

This is no longer used by the compiler itself, and removing this support opens
the door to massively simplifying the Decodable/Decoder API by dropping the
self-describing deserialization support (necessary for JSON).
This commit is contained in:
Mark Rousskov 2022-02-09 17:05:44 -05:00
parent 45e2c2881d
commit 60b71f56e7
9 changed files with 46 additions and 718 deletions

View file

@ -45,12 +45,9 @@
//!
//! # Rust Type-based Encoding and Decoding
//!
//! Rust provides a mechanism for low boilerplate encoding & decoding of values to and from JSON via
//! the serialization API.
//! To be able to encode a piece of data, it must implement the `serialize::Encodable` trait.
//! To be able to decode a piece of data, it must implement the `serialize::Decodable` trait.
//! The Rust compiler provides an annotation to automatically generate the code for these traits:
//! `#[derive(Decodable, Encodable)]`
//! To be able to encode a piece of data, it must implement the
//! `serialize::Encodable` trait. The `rustc_macros` crate provides an
//! annotation to automatically generate the code for this trait: `#[derive(Encodable)]`.
//!
//! The JSON API provides an enum `json::Json` and a trait `ToJson` to encode objects.
//! The `ToJson` trait provides a `to_json` method to convert an object into a `json::Json` value.
@ -68,11 +65,11 @@
//!
//! ```rust
//! # #![feature(rustc_private)]
//! use rustc_macros::{Decodable, Encodable};
//! use rustc_macros::{Encodable};
//! use rustc_serialize::json;
//!
//! // Automatically generate `Decodable` and `Encodable` trait implementations
//! #[derive(Decodable, Encodable)]
//! // Automatically generate `Encodable` trait implementations
//! #[derive(Encodable)]
//! pub struct TestStruct {
//! data_int: u8,
//! data_str: String,
@ -87,9 +84,6 @@
//!
//! // Serialize using `json::encode`
//! let encoded = json::encode(&object).unwrap();
//!
//! // Deserialize using `json::decode`
//! let decoded: TestStruct = json::decode(&encoded[..]);
//! ```
//!
//! ## Using the `ToJson` trait
@ -139,12 +133,9 @@
//!
//! ```rust
//! # #![feature(rustc_private)]
//! use rustc_macros::Decodable;
//! use std::collections::BTreeMap;
//! use rustc_serialize::json::{self, Json, ToJson};
//! use rustc_serialize::json::{Json, ToJson};
//!
//! // Only generate `Decodable` trait implementation
//! #[derive(Decodable)]
//! pub struct TestStruct {
//! data_int: u8,
//! data_str: String,
@ -171,19 +162,14 @@
//! };
//! let json_obj: Json = input_data.to_json();
//! let json_str: String = json_obj.to_string();
//!
//! // Deserialize like before
//! let decoded: TestStruct = json::decode(&json_str);
//! ```
use self::DecoderError::*;
use self::ErrorCode::*;
use self::InternalStackElement::*;
use self::JsonEvent::*;
use self::ParserError::*;
use self::ParserState::*;
use std::borrow::Cow;
use std::collections::{BTreeMap, HashMap};
use std::mem::swap;
use std::num::FpCategory as Fp;
@ -253,21 +239,6 @@ pub enum ParserError {
// Builder and Parser have the same errors.
pub type BuilderError = ParserError;
#[derive(Clone, PartialEq, Debug)]
pub enum DecoderError {
ParseError(ParserError),
ExpectedError(string::String, string::String),
MissingFieldError(string::String),
UnknownVariantError(string::String),
ApplicationError(string::String),
}
macro_rules! bad {
($e:expr) => {{
panic!("json decode error: {:?}", $e);
}};
}
#[derive(Copy, Clone, Debug)]
pub enum EncoderError {
FmtError(fmt::Error),
@ -297,17 +268,6 @@ 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) -> T {
let json = match from_str(s) {
Ok(x) => x,
Err(e) => bad!(ParseError(e)),
};
let mut decoder = Decoder::new(json);
crate::Decodable::decode(&mut decoder)
}
/// Shortcut function to encode a `T` into a JSON `String`
pub fn encode<T: for<'r> crate::Encodable<Encoder<'r>>>(
object: &T,
@ -352,7 +312,6 @@ impl From<fmt::Error> for EncoderError {
}
pub type EncodeResult = Result<(), EncoderError>;
pub type DecodeResult<T> = Result<T, DecoderError>;
fn escape_str(wr: &mut dyn fmt::Write, v: &str) -> EncodeResult {
wr.write_str("\"")?;
@ -2162,272 +2121,6 @@ pub fn from_str(s: &str) -> Result<Json, BuilderError> {
builder.build()
}
/// A structure to decode JSON to values in rust.
pub struct Decoder {
stack: Vec<Json>,
}
impl Decoder {
/// Creates a new decoder instance for decoding the specified JSON value.
pub fn new(json: Json) -> Decoder {
Decoder { stack: vec![json] }
}
fn pop(&mut self) -> Json {
self.stack.pop().unwrap()
}
}
macro_rules! expect {
($e:expr, Null) => {{
match $e {
Json::Null => (),
other => bad!(ExpectedError("Null".to_owned(), other.to_string())),
}
}};
($e:expr, $t:ident) => {{
match $e {
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) -> $ty {
match self.pop() {
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) => f,
None => bad!(ExpectedError("Number".to_owned(), s)),
},
value => bad!(ExpectedError("Number".to_owned(), value.to_string())),
}
}
};
}
impl crate::Decoder for Decoder {
fn read_unit(&mut self) -> () {
expect!(self.pop(), Null)
}
read_primitive! { read_usize, usize }
read_primitive! { read_u8, u8 }
read_primitive! { read_u16, u16 }
read_primitive! { read_u32, u32 }
read_primitive! { read_u64, u64 }
read_primitive! { read_u128, u128 }
read_primitive! { read_isize, isize }
read_primitive! { read_i8, i8 }
read_primitive! { read_i16, i16 }
read_primitive! { read_i32, i32 }
read_primitive! { read_i64, i64 }
read_primitive! { read_i128, i128 }
fn read_f32(&mut self) -> f32 {
self.read_f64() as f32
}
fn read_f64(&mut self) -> f64 {
match self.pop() {
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) => f,
None => bad!(ExpectedError("Number".to_owned(), s)),
}
}
Json::Null => f64::NAN,
value => bad!(ExpectedError("Number".to_owned(), value.to_string())),
}
}
fn read_bool(&mut self) -> bool {
expect!(self.pop(), Boolean)
}
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;
}
bad!(ExpectedError("single character string".to_owned(), s.to_string()));
}
fn read_str(&mut self) -> Cow<'_, str> {
Cow::Owned(expect!(self.pop(), String))
}
fn read_raw_bytes_into(&mut self, s: &mut [u8]) {
for c in s.iter_mut() {
*c = self.read_u8();
}
}
fn read_enum<T, F>(&mut self, f: F) -> T
where
F: FnOnce(&mut Decoder) -> T,
{
f(self)
}
fn read_enum_variant<T, F>(&mut self, names: &[&str], mut f: F) -> T
where
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) => 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) => bad!(ExpectedError("Array".to_owned(), val.to_string())),
None => bad!(MissingFieldError("fields".to_owned())),
}
n
}
json => bad!(ExpectedError("String or Object".to_owned(), json.to_string())),
};
let Some(idx) = names.iter().position(|n| *n == &name[..]) else {
bad!(UnknownVariantError(name));
};
f(self, idx)
}
fn read_enum_variant_arg<T, F>(&mut self, f: F) -> T
where
F: FnOnce(&mut Decoder) -> T,
{
f(self)
}
fn read_struct<T, F>(&mut self, f: F) -> T
where
F: FnOnce(&mut Decoder) -> T,
{
let value = f(self);
self.pop();
value
}
fn read_struct_field<T, F>(&mut self, name: &str, f: F) -> T
where
F: FnOnce(&mut Decoder) -> T,
{
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);
f(self)
}
Some(json) => {
self.stack.push(json);
f(self)
}
};
self.stack.push(Json::Object(obj));
value
}
fn read_tuple<T, F>(&mut self, tuple_len: usize, f: F) -> T
where
F: FnOnce(&mut Decoder) -> T,
{
self.read_seq(move |d, len| {
if len == tuple_len {
f(d)
} else {
bad!(ExpectedError(format!("Tuple{}", tuple_len), format!("Tuple{}", len)));
}
})
}
fn read_tuple_arg<T, F>(&mut self, f: F) -> T
where
F: FnOnce(&mut Decoder) -> T,
{
self.read_seq_elt(f)
}
fn read_option<T, F>(&mut self, mut f: F) -> T
where
F: FnMut(&mut Decoder, bool) -> T,
{
match self.pop() {
Json::Null => f(self, false),
value => {
self.stack.push(value);
f(self, true)
}
}
}
fn read_seq<T, F>(&mut self, f: F) -> T
where
F: FnOnce(&mut Decoder, usize) -> T,
{
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) -> T
where
F: FnOnce(&mut Decoder) -> T,
{
f(self)
}
fn read_map<T, F>(&mut self, f: F) -> T
where
F: FnOnce(&mut Decoder, usize) -> T,
{
let obj = expect!(self.pop(), Object);
let len = obj.len();
for (key, value) in obj {
self.stack.push(value);
self.stack.push(Json::String(key));
}
f(self, len)
}
fn read_map_elt_key<T, F>(&mut self, f: F) -> T
where
F: FnOnce(&mut Decoder) -> T,
{
f(self)
}
fn read_map_elt_val<T, F>(&mut self, f: F) -> T
where
F: FnOnce(&mut Decoder) -> T,
{
f(self)
}
}
/// A trait for converting values to JSON
pub trait ToJson {
/// Converts the value of `self` to an instance of JSON