Write the comments in both languages, part four

This commit is contained in:
dev 2026-10-02 13:31:14 +08:00
parent 6bc8b1e355
commit b30203fc29
20 changed files with 114 additions and 28 deletions

View File

@ -15,6 +15,17 @@
//! handles either. The layout is computed on the frontend from the node //! handles either. The layout is computed on the frontend from the node
//! kinds; the backend only supplies the structure, which keeps the authored //! kinds; the backend only supplies the structure, which keeps the authored
//! data independent of any particular rendering. //! data independent of any particular rendering.
//!
//! 服务提供两种图:
//!
//! - 概念图谱,撰写于 `content/graph/concepts.json`。其节点是概念,边是它们之间
//! 的关系,例如 `uses`、`refines` 或 `contrasts`。节点携带解释它的文档的
//! 标识,因此前端可以在节点被点击时打开那篇文档。
//! - 流程图,每个文件一张,位于 `content/flows/`。一张流程图以带形状的节点与
//! 带分支的带标签边,描述某个算法的步骤,例如 SGP4 的传播序列。
//!
//! 两者都是同一形状的纯 JSON,因此前端一个渲染器即可处理任一者。布局在前端由
//! 节点种类算出;后端只提供结构,这让撰写的数据与任何特定的渲染方式无关。
use crate::docs::ApiCatalog; use crate::docs::ApiCatalog;
use crate::json::{self, Value}; use crate::json::{self, Value};
@ -23,26 +34,46 @@ use crate::json::{self, Value};
/// ///
/// The kind selects how a node is drawn. The set is intentionally small so /// The kind selects how a node is drawn. The set is intentionally small so
/// that a new graph can be authored without touching the renderer. /// that a new graph can be authored without touching the renderer.
///
/// 图节点的种类。
///
/// 种类决定节点如何绘制。该集合刻意保持很小,使新增一张图无需改动渲染器。
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NodeKind { pub enum NodeKind {
/// A concept in the knowledge graph. /// A concept in the knowledge graph.
///
/// 知识图谱中的一个概念。
Concept, Concept,
/// A crate of the `apsis-rs` workspace. /// A crate of the `apsis-rs` workspace.
///
/// `apsis-rs` 工作区中的一个 crate。
Crate, Crate,
/// A layer of the `apsis-rs` workspace. /// A layer of the `apsis-rs` workspace.
///
/// `apsis-rs` 工作区中的一个层。
Layer, Layer,
/// A step of an algorithm. /// A step of an algorithm.
///
/// 算法的一个步骤。
Step, Step,
/// A decision in an algorithm, with more than one outgoing edge. /// A decision in an algorithm, with more than one outgoing edge.
///
/// 算法中的一个判定,有多于一条出边。
Decision, Decision,
/// A terminal step, such as a returned value or an error. /// A terminal step, such as a returned value or an error.
///
/// 一个终结步骤,例如返回的值或一个错误。
Terminal, Terminal,
/// A data item, such as an element set or an epoch. /// A data item, such as an element set or an epoch.
///
/// 一个数据项,例如元素集或历元。
Data, Data,
} }
impl NodeKind { impl NodeKind {
/// Parses a kind name, defaulting to [`NodeKind::Concept`]. /// Parses a kind name, defaulting to [`NodeKind::Concept`].
///
/// 解析一个种类名,默认为 [`NodeKind::Concept`]。
pub fn parse(name: &str) -> Self { pub fn parse(name: &str) -> Self {
match name { match name {
"crate" => Self::Crate, "crate" => Self::Crate,
@ -56,6 +87,8 @@ impl NodeKind {
} }
/// Returns the kind name as it is written in the data. /// Returns the kind name as it is written in the data.
///
/// 以数据中书写的原样返回种类名。
pub const fn name(self) -> &'static str { pub const fn name(self) -> &'static str {
match self { match self {
Self::Concept => "concept", Self::Concept => "concept",
@ -70,60 +103,108 @@ impl NodeKind {
} }
/// A node of a graph. /// A node of a graph.
///
/// 图的一个节点。
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Node { pub struct Node {
/// Identifier, unique within the graph. /// Identifier, unique within the graph.
///
/// 标识,在图内唯一。
pub id: String, pub id: String,
/// Display label in English. /// Display label in English.
///
/// 英文显示标签。
pub label: String, pub label: String,
/// Display label in Chinese, or `None` when the label is a name that is /// Display label in Chinese, or `None` when the label is a name that is
/// written the same way in both languages. /// written the same way in both languages.
///
/// 中文显示标签;当标签是一个在两种语言中写法相同的名字时为 `None`。
pub label_zh: Option<String>, pub label_zh: Option<String>,
/// Kind, selecting how the node is drawn. /// Kind, selecting how the node is drawn.
///
/// 种类,决定节点如何绘制。
pub kind: NodeKind, pub kind: NodeKind,
/// Chapter or group the node belongs to, used for colouring. /// Chapter or group the node belongs to, used for colouring.
///
/// 节点所属的章或分组,用于着色。
pub group: String, pub group: String,
/// One sentence description in English. /// One sentence description in English.
///
/// 一句话英文描述。
///
/// 一句话英文描述。
pub summary: String, pub summary: String,
/// One sentence description in Chinese, when one is authored. /// One sentence description in Chinese, when one is authored.
///
/// 一句话中文描述,若已撰写。
///
/// 一句话中文描述,若已撰写。
pub summary_zh: Option<String>, pub summary_zh: Option<String>,
/// Identifier of the document that explains the node, when one exists. /// Identifier of the document that explains the node, when one exists.
///
/// 解释该节点的文档标识,若存在。
pub document: Option<String>, pub document: Option<String>,
/// Identifier of the interface item, when the node names one. /// Identifier of the interface item, when the node names one.
///
/// 接口条目标识,若该节点指名了某个条目。
pub api: Option<String>, pub api: Option<String>,
} }
/// An edge of a graph. /// An edge of a graph.
///
/// 图的一条边。
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Edge { pub struct Edge {
/// Source node identifier. /// Source node identifier.
///
/// 起点节点标识。
pub source: String, pub source: String,
/// Target node identifier. /// Target node identifier.
///
/// 终点节点标识。
pub target: String, pub target: String,
/// Relationship name, such as `uses`. /// Relationship name, such as `uses`.
///
/// 关系名,例如 `uses`。
pub kind: String, pub kind: String,
/// Optional label drawn on the edge, in English. /// Optional label drawn on the edge, in English.
///
/// 绘制在边上的可选标签,英文。
pub label: Option<String>, pub label: Option<String>,
/// The same label in Chinese, when one is authored. /// The same label in Chinese, when one is authored.
///
/// 同一标签的中文,若已撰写。
pub label_zh: Option<String>, pub label_zh: Option<String>,
} }
/// A graph, either the concept graph or one flow graph. /// A graph, either the concept graph or one flow graph.
///
/// 一张图,或为概念图谱,或为一张流程图。
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Graph { pub struct Graph {
/// Identifier of the graph. /// Identifier of the graph.
///
/// 图的标识。
pub id: String, pub id: String,
/// Display title in English. /// Display title in English.
///
/// 英文显示标题。
pub title: String, pub title: String,
/// Display title in Chinese, when one is authored. /// Display title in Chinese, when one is authored.
///
/// 中文显示标题,若已撰写。
pub title_zh: Option<String>, pub title_zh: Option<String>,
/// One sentence description in English. /// One sentence description in English.
pub summary: String, pub summary: String,
/// One sentence description in Chinese, when one is authored. /// One sentence description in Chinese, when one is authored.
pub summary_zh: Option<String>, pub summary_zh: Option<String>,
/// Nodes. /// Nodes.
///
/// 各节点。
pub nodes: Vec<Node>, pub nodes: Vec<Node>,
/// Edges. /// Edges.
///
/// 各边。
pub edges: Vec<Edge>, pub edges: Vec<Edge>,
} }
@ -132,12 +213,18 @@ impl Graph {
/// ///
/// Used to resolve the endpoints of an edge, which is what the check /// Used to resolve the endpoints of an edge, which is what the check
/// for a dangling edge does. /// for a dangling edge does.
///
/// 按标识返回一个节点。
///
/// 用于解析一条边的两个端点,悬空边的检查正是这么做的。
#[allow(dead_code)] #[allow(dead_code)]
pub fn node(&self, id: &str) -> Option<&Node> { pub fn node(&self, id: &str) -> Option<&Node> {
self.nodes.iter().find(|node| node.id == id) self.nodes.iter().find(|node| node.id == id)
} }
/// Returns the edges that leave a node. /// Returns the edges that leave a node.
///
/// 返回离开某个节点的各条边。
#[allow(dead_code)] #[allow(dead_code)]
pub fn outgoing(&self, id: &str) -> impl Iterator<Item = &Edge> { pub fn outgoing(&self, id: &str) -> impl Iterator<Item = &Edge> {
self.edges.iter().filter(move |edge| edge.source == id) self.edges.iter().filter(move |edge| edge.source == id)
@ -185,6 +272,8 @@ impl GraphSet {
} }
/// Loads the concept graph and every flow graph from the embedded content. /// Loads the concept graph and every flow graph from the embedded content.
///
/// 从内嵌内容载入概念图谱与每一张流程图。
pub fn load_graph() -> GraphSet { pub fn load_graph() -> GraphSet {
let concepts = crate::docs::content::get("graph/concepts.json") let concepts = crate::docs::content::get("graph/concepts.json")
.and_then(parse_graph) .and_then(parse_graph)
@ -211,6 +300,10 @@ pub fn load_graph() -> GraphSet {
/// ///
/// Returns `None` when the identifier is missing, because a graph without an /// Returns `None` when the identifier is missing, because a graph without an
/// identifier cannot be addressed. /// identifier cannot be addressed.
///
/// 从 JSON 表示解析一张图。
///
/// 标识缺失时返回 `None`,因为没有标识的图无法被寻址。
pub fn parse_graph(text: &str) -> Option<Graph> { pub fn parse_graph(text: &str) -> Option<Graph> {
let value = json::parse(text).ok()?; let value = json::parse(text).ok()?;
let id = value.get("id")?.as_str()?.to_string(); let id = value.get("id")?.as_str()?.to_string();
@ -306,6 +399,8 @@ pub fn parse_graph(text: &str) -> Option<Graph> {
/// Returns a member of a JSON object as an owned string, when it is a /// Returns a member of a JSON object as an owned string, when it is a
/// non-empty string. /// non-empty string.
///
/// 把 JSON 对象的某个成员返回为自有字符串,当它是非空字符串时。
fn text_field(value: &Value, key: &str) -> Option<String> { fn text_field(value: &Value, key: &str) -> Option<String> {
value value
.get(key) .get(key)
@ -321,6 +416,13 @@ fn text_field(value: &Value, key: &str) -> Option<String> {
/// `foundation -> physics -> orbit -> rf -> network -> ops -> sim`. A layer /// `foundation -> physics -> orbit -> rf -> network -> ops -> sim`. A layer
/// edge is drawn from each layer to the next one that the enabled feature /// edge is drawn from each layer to the next one that the enabled feature
/// set contains, which is what the dependency rule means in practice. /// set contains, which is what the dependency rule means in practice.
///
/// 从接口目录构建 crate 结构图。
///
/// 节点是各 crate,按层分组;边沿 `apsis-rs` 强制的层序:
/// `foundation -> physics -> orbit -> rf -> network -> ops -> sim`。
/// 层边从每一层画向所启用特性集合中包含的下一层,这正是依赖规则在实践中
/// 的含义。
pub fn crate_structure(catalog: &ApiCatalog) -> Graph { pub fn crate_structure(catalog: &ApiCatalog) -> Graph {
let layers = [ let layers = [
"foundation", "foundation",
@ -340,6 +442,10 @@ pub fn crate_structure(catalog: &ApiCatalog) -> Graph {
// layer structure: the workspace facade re-exports every layer and // layer structure: the workspace facade re-exports every layer and
// would sit under a layer it is not part of. It stays on the index, // would sit under a layer it is not part of. It stays on the index,
// where it is a crate like any other. // where it is a crate like any other.
// 不属于任何层的 crate 在层结构图中没有位置:工作区门面转出所有层,
// 它会落在一个自己并不属于的层之下。它留在索引里,在那里它与别的 crate
// 无异。
if krate.layer.is_empty() { if krate.layer.is_empty() {
continue; continue;
} }
@ -372,6 +478,8 @@ pub fn crate_structure(catalog: &ApiCatalog) -> Graph {
// One node per layer that the catalog contains, so the graph describes // One node per layer that the catalog contains, so the graph describes
// this build rather than the whole workspace. // this build rather than the whole workspace.
// 目录中包含的每一层一个节点,因此该图描述的是本次构建,而不是整个工作区。
for layer in layers { for layer in layers {
if !present.contains(&layer) { if !present.contains(&layer) {
continue; continue;
@ -394,6 +502,8 @@ pub fn crate_structure(catalog: &ApiCatalog) -> Graph {
} }
// The dependency rule, drawn between the layers that are present. // The dependency rule, drawn between the layers that are present.
// 依赖规则,画在存在的各层之间。
for window in layers.windows(2) { for window in layers.windows(2) {
let (lower, upper) = (window[0], window[1]); let (lower, upper) = (window[0], window[1]);
if present.contains(&lower) && present.contains(&upper) { if present.contains(&lower) && present.contains(&upper) {
@ -423,6 +533,10 @@ pub fn crate_structure(catalog: &ApiCatalog) -> Graph {
/// ///
/// The crate name is the key, so the table stays beside the graph rather /// The crate name is the key, so the table stays beside the graph rather
/// than in a separate translation file. /// than in a separate translation file.
///
/// 返回某个 crate 的中文摘要,若已撰写。
///
/// 以 crate 名为键,因此该表与图放在一起,而不在单独的译文文件中。
fn crate_summary_zh(name: &str) -> Option<String> { fn crate_summary_zh(name: &str) -> Option<String> {
let text = match name { let text = match name {
"apsis-core" => "共享基础类型:通用错误、常量与单位标记 trait。", "apsis-core" => "共享基础类型:通用错误、常量与单位标记 trait。",

View File

@ -12,7 +12,6 @@
//! handler never has to parse a value itself and never sees a value of the //! handler never has to parse a value itself and never sees a value of the
//! wrong type. //! wrong type.
//! //!
//!
//! 服务的第三项任务是为 `apsis-rs` 各内核提供一个在线试验台。注册表是「服务能 //! 服务的第三项任务是为 `apsis-rs` 各内核提供一个在线试验台。注册表是「服务能
//! 运行什么」的唯一描述:每个工具声明其参数、类型、单位与默认值,前端据此渲染 //! 运行什么」的唯一描述:每个工具声明其参数、类型、单位与默认值,前端据此渲染
//! 表单。因此新增一个工具意味着在此加一个条目、并在 [`handlers`] 中加一个处理 //! 表单。因此新增一个工具意味着在此加一个条目、并在 [`handlers`] 中加一个处理
@ -150,7 +149,6 @@ pub struct ToolSpec {
/// The `apsis-rs` items the tool calls, for cross linking to the /// The `apsis-rs` items the tool calls, for cross linking to the
/// interface documentation. /// interface documentation.
/// ///
///
/// 该工具调用的 `apsis-rs` 条目,用于交叉链接到接口文档。 /// 该工具调用的 `apsis-rs` 条目,用于交叉链接到接口文档。
pub api_items: &'static [&'static str], pub api_items: &'static [&'static str],
} }
@ -160,7 +158,6 @@ pub struct ToolSpec {
/// The table is a constant, so its parameter slices have a `'static` /// The table is a constant, so its parameter slices have a `'static`
/// lifetime and the registry holds no owned data. /// lifetime and the registry holds no owned data.
/// ///
///
/// 所有工具的注册表。 /// 所有工具的注册表。
/// ///
/// 该表是常量,因此其参数切片具有 `'static` 生命周期,注册表不持有任何自有数据。 /// 该表是常量,因此其参数切片具有 `'static` 生命周期,注册表不持有任何自有数据。
@ -220,7 +217,6 @@ impl Default for Registry {
/// It is a constant rather than a function so that the parameter slices are /// It is a constant rather than a function so that the parameter slices are
/// promoted to `'static` and the registry borrows it instead of owning it. /// promoted to `'static` and the registry borrows it instead of owning it.
/// ///
///
/// 工具表。 /// 工具表。
/// ///
/// 它是一个常量而不是函数,这样参数切片会被提升为 `'static`,注册表借用它而不是 /// 它是一个常量而不是函数,这样参数切片会被提升为 `'static`,注册表借用它而不是
@ -1033,7 +1029,6 @@ impl<'a> Params<'a> {
/// declared by the parameter, and only a parameter with neither a value /// declared by the parameter, and only a parameter with neither a value
/// nor a default is reported as required. /// nor a default is reported as required.
/// ///
///
/// 返回一个必需的数值。 /// 返回一个必需的数值。
/// ///
/// 取值可以作为 JSON 数字或字符串到达,因为表单控件发送的是文本。缺失的成员 /// 取值可以作为 JSON 数字或字符串到达,因为表单控件发送的是文本。缺失的成员
@ -1078,7 +1073,6 @@ impl<'a> Params<'a> {
/// A value that is not a whole number is rejected rather than rounded, /// A value that is not a whole number is rejected rather than rounded,
/// because rounding would silently change a field such as a year. /// because rounding would silently change a field such as a year.
/// ///
///
/// 返回一个必需的整数。 /// 返回一个必需的整数。
/// ///
/// 不是整数的取值会被拒绝而不是四舍五入,因为取整会悄悄改变诸如年份这样的 /// 不是整数的取值会被拒绝而不是四舍五入,因为取整会悄悄改变诸如年份这样的
@ -1111,7 +1105,6 @@ impl<'a> Params<'a> {
/// Returns a value that must be one of the options of a select /// Returns a value that must be one of the options of a select
/// parameter. /// parameter.
/// ///
///
/// 返回一个必须是某个选择型参数选项的取值。 /// 返回一个必须是某个选择型参数选项的取值。
pub fn choice(&self, name: &str) -> Result<&'static str, ToolError> { pub fn choice(&self, name: &str) -> Result<&'static str, ToolError> {
let spec = self.spec(name)?; let spec = self.spec(name)?;
@ -1189,7 +1182,6 @@ impl<'a> Params<'a> {
/// the handler runs. An unknown identifier is reported as a general failure /// the handler runs. An unknown identifier is reported as a general failure
/// so that the HTTP layer can answer with a not found status. /// so that the HTTP layer can answer with a not found status.
/// ///
///
/// 按标识执行一个工具。 /// 按标识执行一个工具。
/// ///
/// 注册表解析该标识,参数被校验,随后处理函数运行。未知标识被报告为一般性失败, /// 注册表解析该标识,参数被校验,随后处理函数运行。未知标识被报告为一般性失败,
@ -1207,7 +1199,6 @@ pub fn execute(registry: &Registry, id: &str, values: &Value) -> Result<Value, T
/// Every label is encoded in both languages, so the frontend can switch the /// Every label is encoded in both languages, so the frontend can switch the
/// language of the interface without another request. /// language of the interface without another request.
/// ///
///
/// 把注册表编码为供前端使用的 JSON。 /// 把注册表编码为供前端使用的 JSON。
/// ///
/// 每个标签都以两种语言编码,因此前端无须再次请求即可切换界面语言。 /// 每个标签都以两种语言编码,因此前端无须再次请求即可切换界面语言。
@ -1228,7 +1219,6 @@ pub fn registry_json(registry: &Registry) -> Value {
/// the concept documentation, so a formula written between dollar signs is /// the concept documentation, so a formula written between dollar signs is
/// set the same way in both places. /// set the same way in both places.
/// ///
///
/// 把一个工具编码为 JSON。 /// 把一个工具编码为 JSON。
/// ///
/// 描述与参数帮助都以 Markdown 书写,因此各发送两次:源码形式,供阅读 JSON 的人 /// 描述与参数帮助都以 Markdown 书写,因此各发送两次:源码形式,供阅读 JSON 的人

View File

@ -6,7 +6,6 @@
//! reaches only what the library makes public, so the few internal items the //! reaches only what the library makes public, so the few internal items the
//! tests need are opened through `apsis_book::testkit`. //! tests need are opened through `apsis_book::testkit`.
//! //!
//!
//! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。
//! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目
//! 经 `apsis_book::testkit` 开放。 //! 经 `apsis_book::testkit` 开放。

View File

@ -6,7 +6,6 @@
//! reaches only what the library makes public, so the few internal items the //! reaches only what the library makes public, so the few internal items the
//! tests need are opened through `apsis_book::testkit`. //! tests need are opened through `apsis_book::testkit`.
//! //!
//!
//! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。
//! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目
//! 经 `apsis_book::testkit` 开放。 //! 经 `apsis_book::testkit` 开放。

View File

@ -6,7 +6,6 @@
//! reaches only what the library makes public, so the few internal items the //! reaches only what the library makes public, so the few internal items the
//! tests need are opened through `apsis_book::testkit`. //! tests need are opened through `apsis_book::testkit`.
//! //!
//!
//! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。
//! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目
//! 经 `apsis_book::testkit` 开放。 //! 经 `apsis_book::testkit` 开放。

View File

@ -6,7 +6,6 @@
//! reaches only what the library makes public, so the few internal items the //! reaches only what the library makes public, so the few internal items the
//! tests need are opened through `apsis_book::testkit`. //! tests need are opened through `apsis_book::testkit`.
//! //!
//!
//! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。
//! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目
//! 经 `apsis_book::testkit` 开放。 //! 经 `apsis_book::testkit` 开放。

View File

@ -6,7 +6,6 @@
//! reaches only what the library makes public, so the few internal items the //! reaches only what the library makes public, so the few internal items the
//! tests need are opened through `apsis_book::testkit`. //! tests need are opened through `apsis_book::testkit`.
//! //!
//!
//! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。
//! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目
//! 经 `apsis_book::testkit` 开放。 //! 经 `apsis_book::testkit` 开放。

View File

@ -6,7 +6,6 @@
//! reaches only what the library makes public, so the few internal items the //! reaches only what the library makes public, so the few internal items the
//! tests need are opened through `apsis_book::testkit`. //! tests need are opened through `apsis_book::testkit`.
//! //!
//!
//! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。
//! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目
//! 经 `apsis_book::testkit` 开放。 //! 经 `apsis_book::testkit` 开放。

View File

@ -6,7 +6,6 @@
//! reaches only what the library makes public, so the few internal items the //! reaches only what the library makes public, so the few internal items the
//! tests need are opened through `apsis_book::testkit`. //! tests need are opened through `apsis_book::testkit`.
//! //!
//!
//! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。
//! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目
//! 经 `apsis_book::testkit` 开放。 //! 经 `apsis_book::testkit` 开放。

View File

@ -6,7 +6,6 @@
//! reaches only what the library makes public, so the few internal items the //! reaches only what the library makes public, so the few internal items the
//! tests need are opened through `apsis_book::testkit`. //! tests need are opened through `apsis_book::testkit`.
//! //!
//!
//! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。
//! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目
//! 经 `apsis_book::testkit` 开放。 //! 经 `apsis_book::testkit` 开放。

View File

@ -6,7 +6,6 @@
//! reaches only what the library makes public, so the few internal items the //! reaches only what the library makes public, so the few internal items the
//! tests need are opened through `apsis_book::testkit`. //! tests need are opened through `apsis_book::testkit`.
//! //!
//!
//! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。
//! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目
//! 经 `apsis_book::testkit` 开放。 //! 经 `apsis_book::testkit` 开放。

View File

@ -6,7 +6,6 @@
//! reaches only what the library makes public, so the few internal items the //! reaches only what the library makes public, so the few internal items the
//! tests need are opened through `apsis_book::testkit`. //! tests need are opened through `apsis_book::testkit`.
//! //!
//!
//! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。
//! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目
//! 经 `apsis_book::testkit` 开放。 //! 经 `apsis_book::testkit` 开放。

View File

@ -6,7 +6,6 @@
//! reaches only what the library makes public, so the few internal items the //! reaches only what the library makes public, so the few internal items the
//! tests need are opened through `apsis_book::testkit`. //! tests need are opened through `apsis_book::testkit`.
//! //!
//!
//! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。
//! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目
//! 经 `apsis_book::testkit` 开放。 //! 经 `apsis_book::testkit` 开放。

View File

@ -6,7 +6,6 @@
//! reaches only what the library makes public, so the few internal items the //! reaches only what the library makes public, so the few internal items the
//! tests need are opened through `apsis_book::testkit`. //! tests need are opened through `apsis_book::testkit`.
//! //!
//!
//! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。
//! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目
//! 经 `apsis_book::testkit` 开放。 //! 经 `apsis_book::testkit` 开放。

View File

@ -6,7 +6,6 @@
//! reaches only what the library makes public, so the few internal items the //! reaches only what the library makes public, so the few internal items the
//! tests need are opened through `apsis_book::testkit`. //! tests need are opened through `apsis_book::testkit`.
//! //!
//!
//! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。
//! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目
//! 经 `apsis_book::testkit` 开放。 //! 经 `apsis_book::testkit` 开放。

View File

@ -6,7 +6,6 @@
//! reaches only what the library makes public, so the few internal items the //! reaches only what the library makes public, so the few internal items the
//! tests need are opened through `apsis_book::testkit`. //! tests need are opened through `apsis_book::testkit`.
//! //!
//!
//! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。
//! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目
//! 经 `apsis_book::testkit` 开放。 //! 经 `apsis_book::testkit` 开放。

View File

@ -6,7 +6,6 @@
//! reaches only what the library makes public, so the few internal items the //! reaches only what the library makes public, so the few internal items the
//! tests need are opened through `apsis_book::testkit`. //! tests need are opened through `apsis_book::testkit`.
//! //!
//!
//! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。
//! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目
//! 经 `apsis_book::testkit` 开放。 //! 经 `apsis_book::testkit` 开放。

View File

@ -6,7 +6,6 @@
//! reaches only what the library makes public, so the few internal items the //! reaches only what the library makes public, so the few internal items the
//! tests need are opened through `apsis_book::testkit`. //! tests need are opened through `apsis_book::testkit`.
//! //!
//!
//! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。
//! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目
//! 经 `apsis_book::testkit` 开放。 //! 经 `apsis_book::testkit` 开放。

View File

@ -6,7 +6,6 @@
//! reaches only what the library makes public, so the few internal items the //! reaches only what the library makes public, so the few internal items the
//! tests need are opened through `apsis_book::testkit`. //! tests need are opened through `apsis_book::testkit`.
//! //!
//!
//! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。
//! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目
//! 经 `apsis_book::testkit` 开放。 //! 经 `apsis_book::testkit` 开放。

View File

@ -6,7 +6,6 @@
//! reaches only what the library makes public, so the few internal items the //! reaches only what the library makes public, so the few internal items the
//! tests need are opened through `apsis_book::testkit`. //! tests need are opened through `apsis_book::testkit`.
//! //!
//!
//! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。
//! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目
//! 经 `apsis_book::testkit` 开放。 //! 经 `apsis_book::testkit` 开放。