Write the comments in both languages, part five

This commit is contained in:
dev 2026-10-02 13:32:41 +08:00
parent b30203fc29
commit 5592e127e9
1 changed files with 142 additions and 0 deletions

View File

@ -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();