Write the comments in both languages, part five
This commit is contained in:
parent
b30203fc29
commit
5592e127e9
142
src/json.rs
142
src/json.rs
|
|
@ -20,23 +20,54 @@
|
||||||
//! Encoding follows RFC 8259: strings are always quoted, control characters
|
//! Encoding follows RFC 8259: strings are always quoted, control characters
|
||||||
//! and the quote and reverse solidus are escaped, and non-finite floats are
|
//! and the quote and reverse solidus are escaped, and non-finite floats are
|
||||||
//! encoded as `null` because JSON has no representation for them.
|
//! encoded as `null` because JSON has no representation for them.
|
||||||
|
//!
|
||||||
|
//! 手写的 JSON 编解码器。
|
||||||
|
//!
|
||||||
|
//! 服务除 `apsis-rs` 外不得依赖任何 crate,因此 JSON 的编码与解码在此实现。
|
||||||
|
//! 该编解码器覆盖服务所需的 RFC 8259 子集:
|
||||||
|
//!
|
||||||
|
//! - [`Value`] 为任何 JSON 值建模,含嵌套的数组与对象。
|
||||||
|
//! - [`parse`] 解码一份文档,并以 [`JsonError`] 报告第一个问题的字节偏移。
|
||||||
|
//! - [`to_string`] 以紧凑形式编码一个值,[`to_string_pretty`] 以缩进编码以便
|
||||||
|
//! 阅读。
|
||||||
|
//! - [`object`] 宏构造对象字面量,无需重复 `Value` 的构造函数。
|
||||||
|
//!
|
||||||
|
//! 数字以 `f64` 持有。需要完整 `i64` 范围的整数,只要能无损地表示为 `f64`,
|
||||||
|
//! 就会被精确解码,这在上限 `2^53` 之内成立;服务只交换该范围内的量与标识。
|
||||||
|
//!
|
||||||
|
//! 编码遵循 RFC 8259:字符串始终加引号,控制字符、引号与反斜杠被转义,非有限
|
||||||
|
//! 浮点数编码为 `null`,因为 JSON 没有它们的表示。
|
||||||
|
|
||||||
use std::fmt::{self, Write as _};
|
use std::fmt::{self, Write as _};
|
||||||
|
|
||||||
/// A JSON value.
|
/// A JSON value.
|
||||||
|
///
|
||||||
|
/// 一个 JSON 值。
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
/// The `null` literal.
|
/// The `null` literal.
|
||||||
|
///
|
||||||
|
/// `null` 字面量。
|
||||||
Null,
|
Null,
|
||||||
/// A boolean, `true` or `false`.
|
/// A boolean, `true` or `false`.
|
||||||
|
///
|
||||||
|
/// 一个布尔值,`true` 或 `false`。
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
/// A number. JSON does not distinguish integers from floats.
|
/// A number. JSON does not distinguish integers from floats.
|
||||||
|
///
|
||||||
|
/// 一个数值。JSON 不区分整数与浮点数。
|
||||||
Number(f64),
|
Number(f64),
|
||||||
/// A string.
|
/// A string.
|
||||||
|
///
|
||||||
|
/// 一个字符串。
|
||||||
String(String),
|
String(String),
|
||||||
/// An array of values.
|
/// An array of values.
|
||||||
|
///
|
||||||
|
/// 一个值的数组。
|
||||||
Array(Vec<Value>),
|
Array(Vec<Value>),
|
||||||
/// An object, preserving the order in which members were inserted.
|
/// An object, preserving the order in which members were inserted.
|
||||||
|
///
|
||||||
|
/// 一个对象,保持成员被插入时的顺序。
|
||||||
Object(Vec<(String, Value)>),
|
Object(Vec<(String, Value)>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -45,12 +76,19 @@ impl Value {
|
||||||
///
|
///
|
||||||
/// The constructor and [`Value::number`] complete the pair of scalar
|
/// The constructor and [`Value::number`] complete the pair of scalar
|
||||||
/// constructors for callers that build a value without a literal.
|
/// constructors for callers that build a value without a literal.
|
||||||
|
///
|
||||||
|
/// 由任何可转换为 `String` 的东西创建一个字符串值。
|
||||||
|
///
|
||||||
|
/// 该构造函数与 [`Value::number`] 构成一对标量构造函数,供不通过字面量构造取值
|
||||||
|
/// 的调用方使用。
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn string(text: impl Into<String>) -> Self {
|
pub fn string(text: impl Into<String>) -> Self {
|
||||||
Self::String(text.into())
|
Self::String(text.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a number value.
|
/// Creates a number value.
|
||||||
|
///
|
||||||
|
/// 创建一个数值。
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn number(value: impl Into<f64>) -> Self {
|
pub fn number(value: impl Into<f64>) -> Self {
|
||||||
Self::Number(value.into())
|
Self::Number(value.into())
|
||||||
|
|
@ -58,6 +96,8 @@ impl Value {
|
||||||
|
|
||||||
/// Returns the value as an object member list, or an empty slice when it
|
/// Returns the value as an object member list, or an empty slice when it
|
||||||
/// is not an object.
|
/// is not an object.
|
||||||
|
///
|
||||||
|
/// 把该值返回为对象的成员列表,若它不是对象则为空切片。
|
||||||
pub fn members(&self) -> &[(String, Value)] {
|
pub fn members(&self) -> &[(String, Value)] {
|
||||||
match self {
|
match self {
|
||||||
Self::Object(members) => members,
|
Self::Object(members) => members,
|
||||||
|
|
@ -67,6 +107,8 @@ impl Value {
|
||||||
|
|
||||||
/// Returns the member with `key`, or `None` when it is absent or when
|
/// Returns the member with `key`, or `None` when it is absent or when
|
||||||
/// the value is not an object.
|
/// the value is not an object.
|
||||||
|
///
|
||||||
|
/// 返回键为 `key` 的成员;它不存在或该值不是对象时返回 `None`。
|
||||||
pub fn get(&self, key: &str) -> Option<&Value> {
|
pub fn get(&self, key: &str) -> Option<&Value> {
|
||||||
self.members()
|
self.members()
|
||||||
.iter()
|
.iter()
|
||||||
|
|
@ -76,6 +118,8 @@ impl Value {
|
||||||
|
|
||||||
/// Returns the value as a string slice, or `None` when it is not a
|
/// Returns the value as a string slice, or `None` when it is not a
|
||||||
/// string.
|
/// string.
|
||||||
|
///
|
||||||
|
/// 把该值返回为字符串切片,若它不是字符串则为 `None`。
|
||||||
pub fn as_str(&self) -> Option<&str> {
|
pub fn as_str(&self) -> Option<&str> {
|
||||||
match self {
|
match self {
|
||||||
Self::String(text) => Some(text),
|
Self::String(text) => Some(text),
|
||||||
|
|
@ -89,6 +133,11 @@ impl Value {
|
||||||
/// that arrive from a request are read through the tool parameter
|
/// that arrive from a request are read through the tool parameter
|
||||||
/// wrappers, which validate a number against its declared bounds, so
|
/// wrappers, which validate a number against its declared bounds, so
|
||||||
/// this is used where a value is known to be a number.
|
/// this is used where a value is known to be a number.
|
||||||
|
///
|
||||||
|
/// 把该值返回为数值,若它不是数值则为 `None`。
|
||||||
|
///
|
||||||
|
/// 该访问器补齐了 [`Value`] 上带类型的读取。来自请求的取值经由工具参数包装器
|
||||||
|
/// 读取,那些包装器会依据声明的上下界校验数值;因此这里用在已知是数值的地方。
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn as_f64(&self) -> Option<f64> {
|
pub fn as_f64(&self) -> Option<f64> {
|
||||||
match self {
|
match self {
|
||||||
|
|
@ -98,6 +147,8 @@ impl Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the value as a `bool`, or `None` when it is not a boolean.
|
/// Returns the value as a `bool`, or `None` when it is not a boolean.
|
||||||
|
///
|
||||||
|
/// 把该值返回为 `bool`,若它不是布尔值则为 `None`。
|
||||||
pub fn as_bool(&self) -> Option<bool> {
|
pub fn as_bool(&self) -> Option<bool> {
|
||||||
match self {
|
match self {
|
||||||
Self::Bool(value) => Some(*value),
|
Self::Bool(value) => Some(*value),
|
||||||
|
|
@ -107,6 +158,8 @@ impl Value {
|
||||||
|
|
||||||
/// Returns the value as an array, or an empty slice when it is not an
|
/// Returns the value as an array, or an empty slice when it is not an
|
||||||
/// array.
|
/// array.
|
||||||
|
///
|
||||||
|
/// 把该值返回为数组,若它不是数组则为空切片。
|
||||||
pub fn as_array(&self) -> &[Value] {
|
pub fn as_array(&self) -> &[Value] {
|
||||||
match self {
|
match self {
|
||||||
Self::Array(items) => items,
|
Self::Array(items) => items,
|
||||||
|
|
@ -120,6 +173,11 @@ impl Value {
|
||||||
/// Each key is converted to a `String` and each value is converted to a
|
/// Each key is converted to a `String` and each value is converted to a
|
||||||
/// [`Value`], so literals such as `object!{"n" => 1.0}` work without
|
/// [`Value`], so literals such as `object!{"n" => 1.0}` work without
|
||||||
/// repeating the constructors.
|
/// repeating the constructors.
|
||||||
|
///
|
||||||
|
/// 由 `key => value` 对构造一个对象 [`Value`]。
|
||||||
|
///
|
||||||
|
/// 每个键被转换为 `String`,每个值被转换为 [`Value`],因此诸如
|
||||||
|
/// `object!{"n" => 1.0}` 的字面量无需重复构造函数即可使用。
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! json_object {
|
macro_rules! json_object {
|
||||||
() => { $crate::json::Value::Object(Vec::new()) };
|
() => { $crate::json::Value::Object(Vec::new()) };
|
||||||
|
|
@ -195,11 +253,20 @@ impl<T: Into<Value>> From<Vec<T>> for Value {
|
||||||
/// detected, counted from zero. The message names the condition without
|
/// detected, counted from zero. The message names the condition without
|
||||||
/// quoting the input, so that a malformed request cannot echo attacker
|
/// quoting the input, so that a malformed request cannot echo attacker
|
||||||
/// controlled text back through the error channel.
|
/// controlled text back through the error channel.
|
||||||
|
///
|
||||||
|
/// 一次 JSON 解码失败。
|
||||||
|
///
|
||||||
|
/// 偏移是从零数起的、输入中检测到问题的字节位置。消息指名具体条件而不复述输入,
|
||||||
|
/// 使畸形的请求无法经由错误通道回显攻击者控制的文本。
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct JsonError {
|
pub struct JsonError {
|
||||||
/// Byte offset of the first problem.
|
/// Byte offset of the first problem.
|
||||||
|
///
|
||||||
|
/// 第一个问题的字节偏移。
|
||||||
pub offset: usize,
|
pub offset: usize,
|
||||||
/// Description of the problem.
|
/// Description of the problem.
|
||||||
|
///
|
||||||
|
/// 问题的描述。
|
||||||
pub message: String,
|
pub message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -224,10 +291,18 @@ impl std::error::Error for JsonError {}
|
||||||
///
|
///
|
||||||
/// Whitespace is allowed around every token. Trailing content after the
|
/// Whitespace is allowed around every token. Trailing content after the
|
||||||
/// first complete value is rejected.
|
/// first complete value is rejected.
|
||||||
|
///
|
||||||
|
/// 解码一份 JSON 文档。
|
||||||
|
///
|
||||||
|
/// 每个记号周围都允许空白。第一个完整值之后的剩余内容会被拒绝。
|
||||||
/// Returns the length in bytes of the UTF-8 sequence starting with `byte`.
|
/// Returns the length in bytes of the UTF-8 sequence starting with `byte`.
|
||||||
///
|
///
|
||||||
/// The leading byte states the length; the continuation bytes are checked
|
/// The leading byte states the length; the continuation bytes are checked
|
||||||
/// when the sequence itself is validated.
|
/// when the sequence itself is validated.
|
||||||
|
///
|
||||||
|
/// 返回以 `byte` 开头的 UTF-8 序列的字节长度。
|
||||||
|
///
|
||||||
|
/// 首字节给出长度;后续字节在该序列本身被校验时检查。
|
||||||
fn utf8_length(byte: u8) -> usize {
|
fn utf8_length(byte: u8) -> usize {
|
||||||
match byte {
|
match byte {
|
||||||
0x00..=0x7f => 1,
|
0x00..=0x7f => 1,
|
||||||
|
|
@ -236,6 +311,9 @@ fn utf8_length(byte: u8) -> usize {
|
||||||
0xf0..=0xf7 => 4,
|
0xf0..=0xf7 => 4,
|
||||||
// A continuation or an invalid leading byte; one byte is taken so
|
// A continuation or an invalid leading byte; one byte is taken so
|
||||||
// that the validation reports it as invalid rather than looping.
|
// that the validation reports it as invalid rather than looping.
|
||||||
|
|
||||||
|
// 一个后续字节或非法的首字节;只取一个字节,使校验把它报告为非法,
|
||||||
|
// 而不是陷入循环。
|
||||||
_ => 1,
|
_ => 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -258,9 +336,13 @@ pub fn parse(input: &str) -> Result<Value, JsonError> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encodes a value in compact form.
|
/// Encodes a value in compact form.
|
||||||
|
///
|
||||||
|
/// 以紧凑形式编码一个值。
|
||||||
pub fn to_string(value: &Value) -> String {
|
pub fn to_string(value: &Value) -> String {
|
||||||
let mut output = String::new();
|
let mut output = String::new();
|
||||||
// Writing into a String cannot fail, so the result is discarded.
|
// Writing into a String cannot fail, so the result is discarded.
|
||||||
|
|
||||||
|
// 向 String 写入不会失败,因此结果被丢弃。
|
||||||
let _ = write_value(&mut output, value);
|
let _ = write_value(&mut output, value);
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
|
@ -269,6 +351,10 @@ pub fn to_string(value: &Value) -> String {
|
||||||
///
|
///
|
||||||
/// A pretty document is larger than the compact form, so the service sends
|
/// A pretty document is larger than the compact form, so the service sends
|
||||||
/// the compact form; this is used when a payload is written for a reader.
|
/// the compact form; this is used when a payload is written for a reader.
|
||||||
|
///
|
||||||
|
/// 以每层嵌套两个空格的缩进编码一个值。
|
||||||
|
///
|
||||||
|
/// 带缩进的文档比紧凑形式更大,因此服务发送紧凑形式;这个用于为读者书写载荷时。
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn to_string_pretty(value: &Value) -> String {
|
pub fn to_string_pretty(value: &Value) -> String {
|
||||||
let mut output = String::new();
|
let mut output = String::new();
|
||||||
|
|
@ -277,6 +363,8 @@ pub fn to_string_pretty(value: &Value) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes a value to `output` in compact form.
|
/// Writes a value to `output` in compact form.
|
||||||
|
///
|
||||||
|
/// 以紧凑形式把一个值写入 `output`。
|
||||||
fn write_value(output: &mut String, value: &Value) -> fmt::Result {
|
fn write_value(output: &mut String, value: &Value) -> fmt::Result {
|
||||||
match value {
|
match value {
|
||||||
Value::Null => output.push_str("null"),
|
Value::Null => output.push_str("null"),
|
||||||
|
|
@ -315,6 +403,8 @@ fn write_value(output: &mut String, value: &Value) -> fmt::Result {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes a value to `output` with `depth` levels of indentation.
|
/// Writes a value to `output` with `depth` levels of indentation.
|
||||||
|
///
|
||||||
|
/// 以 `depth` 层缩进把一个值写入 `output`。
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn write_pretty(output: &mut String, value: &Value, depth: usize) -> fmt::Result {
|
fn write_pretty(output: &mut String, value: &Value, depth: usize) -> fmt::Result {
|
||||||
let indent = " ".repeat(depth);
|
let indent = " ".repeat(depth);
|
||||||
|
|
@ -361,6 +451,11 @@ fn write_pretty(output: &mut String, value: &Value, depth: usize) -> fmt::Result
|
||||||
/// Non-finite values have no JSON representation and are written as `null`,
|
/// Non-finite values have no JSON representation and are written as `null`,
|
||||||
/// so that a computation that produced a not-a-number value cannot produce
|
/// so that a computation that produced a not-a-number value cannot produce
|
||||||
/// an unparsable document.
|
/// an unparsable document.
|
||||||
|
///
|
||||||
|
/// 以 JSON 接受的形式写出一个数值。
|
||||||
|
///
|
||||||
|
/// 有限值以 `f64` 的最短往返格式写出。非有限值没有 JSON 表示,写为 `null`,
|
||||||
|
/// 使产生了非数值的计算不可能产生一份无法解析的文档。
|
||||||
fn write_number(output: &mut String, number: f64) -> fmt::Result {
|
fn write_number(output: &mut String, number: f64) -> fmt::Result {
|
||||||
if !number.is_finite() {
|
if !number.is_finite() {
|
||||||
output.push_str("null");
|
output.push_str("null");
|
||||||
|
|
@ -375,6 +470,11 @@ fn write_number(output: &mut String, number: f64) -> fmt::Result {
|
||||||
/// Characters below `0x20` are escaped; the quote and reverse solidus are
|
/// Characters below `0x20` are escaped; the quote and reverse solidus are
|
||||||
/// escaped; every other character is emitted as is, which keeps UTF-8 input
|
/// escaped; every other character is emitted as is, which keeps UTF-8 input
|
||||||
/// valid because the input was already valid UTF-8.
|
/// valid because the input was already valid UTF-8.
|
||||||
|
///
|
||||||
|
/// 写出一个带 RFC 8259 所要求转义的加引号字符串。
|
||||||
|
///
|
||||||
|
/// `0x20` 以下的字符被转义;引号与反斜杠被转义;其余字符按原样输出,这保持了
|
||||||
|
/// UTF-8 输入的有效性,因为输入本就是合法 UTF-8。
|
||||||
fn write_string(output: &mut String, text: &str) -> fmt::Result {
|
fn write_string(output: &mut String, text: &str) -> fmt::Result {
|
||||||
output.push('"');
|
output.push('"');
|
||||||
for character in text.chars() {
|
for character in text.chars() {
|
||||||
|
|
@ -400,21 +500,31 @@ fn write_string(output: &mut String, text: &str) -> fmt::Result {
|
||||||
///
|
///
|
||||||
/// Recursion depth follows the nesting of the document; [`MAX_DEPTH`]
|
/// Recursion depth follows the nesting of the document; [`MAX_DEPTH`]
|
||||||
/// bounds it so that a hostile document cannot exhaust the stack.
|
/// bounds it so that a hostile document cannot exhaust the stack.
|
||||||
|
///
|
||||||
|
/// 一个面向字节的递归下降解析器。
|
||||||
|
///
|
||||||
|
/// 递归深度跟随文档的嵌套;[`MAX_DEPTH`] 给它设界,使恶意文档无法耗尽栈。
|
||||||
struct Parser<'a> {
|
struct Parser<'a> {
|
||||||
bytes: &'a [u8],
|
bytes: &'a [u8],
|
||||||
position: usize,
|
position: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Maximum nesting depth accepted by [`parse`].
|
/// Maximum nesting depth accepted by [`parse`].
|
||||||
|
///
|
||||||
|
/// [`parse`] 接受的最大嵌套深度。
|
||||||
pub const MAX_DEPTH: usize = 64;
|
pub const MAX_DEPTH: usize = 64;
|
||||||
|
|
||||||
impl Parser<'_> {
|
impl Parser<'_> {
|
||||||
/// Parses a value at the current position.
|
/// Parses a value at the current position.
|
||||||
|
///
|
||||||
|
/// 在当前位置解析一个值。
|
||||||
fn value(&mut self) -> Result<Value, JsonError> {
|
fn value(&mut self) -> Result<Value, JsonError> {
|
||||||
self.value_at_depth(0)
|
self.value_at_depth(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a value, rejecting nesting beyond [`MAX_DEPTH`].
|
/// Parses a value, rejecting nesting beyond [`MAX_DEPTH`].
|
||||||
|
///
|
||||||
|
/// 解析一个值,拒绝超过 [`MAX_DEPTH`] 的嵌套。
|
||||||
fn value_at_depth(&mut self, depth: usize) -> Result<Value, JsonError> {
|
fn value_at_depth(&mut self, depth: usize) -> Result<Value, JsonError> {
|
||||||
if depth > MAX_DEPTH {
|
if depth > MAX_DEPTH {
|
||||||
return Err(JsonError::new(self.position, "nesting is too deep"));
|
return Err(JsonError::new(self.position, "nesting is too deep"));
|
||||||
|
|
@ -433,11 +543,15 @@ impl Parser<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the byte at the current position without consuming it.
|
/// Returns the byte at the current position without consuming it.
|
||||||
|
///
|
||||||
|
/// 返回当前位置的字节而不消费它。
|
||||||
fn peek(&self) -> Option<u8> {
|
fn peek(&self) -> Option<u8> {
|
||||||
self.bytes.get(self.position).copied()
|
self.bytes.get(self.position).copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Advances past any JSON whitespace.
|
/// Advances past any JSON whitespace.
|
||||||
|
///
|
||||||
|
/// 越过任何 JSON 空白。
|
||||||
fn skip_whitespace(&mut self) {
|
fn skip_whitespace(&mut self) {
|
||||||
while let Some(byte) = self.peek() {
|
while let Some(byte) = self.peek() {
|
||||||
match byte {
|
match byte {
|
||||||
|
|
@ -448,6 +562,8 @@ impl Parser<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consumes a fixed literal and returns `value`.
|
/// Consumes a fixed literal and returns `value`.
|
||||||
|
///
|
||||||
|
/// 消费一个固定字面量并返回 `value`。
|
||||||
fn literal(&mut self, text: &str, value: Value) -> Result<Value, JsonError> {
|
fn literal(&mut self, text: &str, value: Value) -> Result<Value, JsonError> {
|
||||||
if self.bytes[self.position..].starts_with(text.as_bytes()) {
|
if self.bytes[self.position..].starts_with(text.as_bytes()) {
|
||||||
self.position += text.len();
|
self.position += text.len();
|
||||||
|
|
@ -458,6 +574,8 @@ impl Parser<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a quoted string, decoding the escape sequences.
|
/// Parses a quoted string, decoding the escape sequences.
|
||||||
|
///
|
||||||
|
/// 解析一个加引号的字符串,并解码各转义序列。
|
||||||
fn string(&mut self) -> Result<String, JsonError> {
|
fn string(&mut self) -> Result<String, JsonError> {
|
||||||
let start = self.position;
|
let start = self.position;
|
||||||
self.position += 1; // opening quote
|
self.position += 1; // opening quote
|
||||||
|
|
@ -489,6 +607,12 @@ impl Parser<'_> {
|
||||||
// quadratic, because it repeats for every character in
|
// quadratic, because it repeats for every character in
|
||||||
// the document: a catalogue of seven hundred kilobytes
|
// the document: a catalogue of seven hundred kilobytes
|
||||||
// spent half a minute in this one line.
|
// spent half a minute in this one line.
|
||||||
|
|
||||||
|
// 从此处的字节解码一个 UTF-8 标量。
|
||||||
|
//
|
||||||
|
// 只校验该序列本身。改为校验整个剩余缓冲虽然正确却是二次
|
||||||
|
// 复杂度,因为它会为文档中的每个字符重复一遍:一份七百
|
||||||
|
// 千字节的目录曾在这一行上花掉半分钟。
|
||||||
let length = utf8_length(byte);
|
let length = utf8_length(byte);
|
||||||
let end = self.position + length;
|
let end = self.position + length;
|
||||||
if end > self.bytes.len() {
|
if end > self.bytes.len() {
|
||||||
|
|
@ -504,6 +628,8 @@ impl Parser<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decodes one escape sequence after the reverse solidus.
|
/// Decodes one escape sequence after the reverse solidus.
|
||||||
|
///
|
||||||
|
/// 解码反斜杠之后的一个转义序列。
|
||||||
fn escape(&mut self, output: &mut String) -> Result<(), JsonError> {
|
fn escape(&mut self, output: &mut String) -> Result<(), JsonError> {
|
||||||
let Some(byte) = self.peek() else {
|
let Some(byte) = self.peek() else {
|
||||||
return Err(JsonError::new(self.position, "unterminated escape"));
|
return Err(JsonError::new(self.position, "unterminated escape"));
|
||||||
|
|
@ -526,10 +652,14 @@ impl Parser<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decodes a `\uXXXX` escape, pairing surrogates into one scalar value.
|
/// Decodes a `\uXXXX` escape, pairing surrogates into one scalar value.
|
||||||
|
///
|
||||||
|
/// 解码一个 `\uXXXX` 转义,把代理对合并为一个标量值。
|
||||||
fn unicode_escape(&mut self, output: &mut String) -> Result<(), JsonError> {
|
fn unicode_escape(&mut self, output: &mut String) -> Result<(), JsonError> {
|
||||||
let first = self.hex4()?;
|
let first = self.hex4()?;
|
||||||
let scalar = match first {
|
let scalar = match first {
|
||||||
// A high surrogate must be followed by a low surrogate.
|
// A high surrogate must be followed by a low surrogate.
|
||||||
|
|
||||||
|
// 高代理之后必须跟一个低代理。
|
||||||
0xd800..=0xdbff => {
|
0xd800..=0xdbff => {
|
||||||
if self.peek() != Some(b'\\') {
|
if self.peek() != Some(b'\\') {
|
||||||
return Err(JsonError::new(self.position, "unpaired high surrogate"));
|
return Err(JsonError::new(self.position, "unpaired high surrogate"));
|
||||||
|
|
@ -557,6 +687,8 @@ impl Parser<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads exactly four hexadecimal digits.
|
/// Reads exactly four hexadecimal digits.
|
||||||
|
///
|
||||||
|
/// 恰好读取四个十六进制数字。
|
||||||
fn hex4(&mut self) -> Result<u32, JsonError> {
|
fn hex4(&mut self) -> Result<u32, JsonError> {
|
||||||
if self.position + 4 > self.bytes.len() {
|
if self.position + 4 > self.bytes.len() {
|
||||||
return Err(JsonError::new(self.position, "truncated unicode escape"));
|
return Err(JsonError::new(self.position, "truncated unicode escape"));
|
||||||
|
|
@ -583,6 +715,12 @@ impl Parser<'_> {
|
||||||
/// optional exponent. The token is collected in full and handed to the
|
/// optional exponent. The token is collected in full and handed to the
|
||||||
/// standard `f64` parser, which rounds once and applies the correct
|
/// standard `f64` parser, which rounds once and applies the correct
|
||||||
/// sign to every part of the value.
|
/// sign to every part of the value.
|
||||||
|
///
|
||||||
|
/// 解析一个数值。
|
||||||
|
///
|
||||||
|
/// 文法即 RFC 8259 的那一个:可选的负号、无前导零的整数部分、可选的小数部分、
|
||||||
|
/// 可选的指数。该记号被完整收集后交给标准库的 `f64` 解析器,它只做一次舍入,
|
||||||
|
/// 并对该值的每一部分施加正确的符号。
|
||||||
fn number(&mut self) -> Result<Value, JsonError> {
|
fn number(&mut self) -> Result<Value, JsonError> {
|
||||||
let start = self.position;
|
let start = self.position;
|
||||||
if self.peek() == Some(b'-') {
|
if self.peek() == Some(b'-') {
|
||||||
|
|
@ -633,6 +771,8 @@ impl Parser<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses an array.
|
/// Parses an array.
|
||||||
|
///
|
||||||
|
/// 解析一个数组。
|
||||||
fn array(&mut self, depth: usize) -> Result<Value, JsonError> {
|
fn array(&mut self, depth: usize) -> Result<Value, JsonError> {
|
||||||
self.position += 1; // opening bracket
|
self.position += 1; // opening bracket
|
||||||
let mut items = Vec::new();
|
let mut items = Vec::new();
|
||||||
|
|
@ -657,6 +797,8 @@ impl Parser<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses an object.
|
/// Parses an object.
|
||||||
|
///
|
||||||
|
/// 解析一个对象。
|
||||||
fn object(&mut self, depth: usize) -> Result<Value, JsonError> {
|
fn object(&mut self, depth: usize) -> Result<Value, JsonError> {
|
||||||
self.position += 1; // opening brace
|
self.position += 1; // opening brace
|
||||||
let mut members = Vec::new();
|
let mut members = Vec::new();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue