From b30203fc29880a4cdb1f107343a06ad0d1b1881d Mon Sep 17 00:00:00 2001 From: dev Date: Fri, 2 Oct 2026 13:31:14 +0800 Subject: [PATCH] Write the comments in both languages, part four --- src/graph/mod.rs | 114 ++++++++++++++++++++++++++++++++++++++++ src/tools/mod.rs | 10 ---- tests/api.rs | 1 - tests/docs_api.rs | 1 - tests/docs_content.rs | 1 - tests/docs_document.rs | 1 - tests/docs_markdown.rs | 1 - tests/docs_mathml.rs | 1 - tests/embedded.rs | 1 - tests/graph.rs | 1 - tests/http_request.rs | 1 - tests/http_response.rs | 1 - tests/http_server.rs | 1 - tests/i18n.rs | 1 - tests/json_codec.rs | 1 - tests/state.rs | 1 - tests/tools_handlers.rs | 1 - tests/tools_labels.rs | 1 - tests/tools_out.rs | 1 - tests/tools_registry.rs | 1 - 20 files changed, 114 insertions(+), 28 deletions(-) diff --git a/src/graph/mod.rs b/src/graph/mod.rs index c7cdd86..e912112 100644 --- a/src/graph/mod.rs +++ b/src/graph/mod.rs @@ -15,6 +15,17 @@ //! handles either. The layout is computed on the frontend from the node //! kinds; the backend only supplies the structure, which keeps the authored //! data independent of any particular rendering. +//! +//! 服务提供两种图: +//! +//! - 概念图谱,撰写于 `content/graph/concepts.json`。其节点是概念,边是它们之间 +//! 的关系,例如 `uses`、`refines` 或 `contrasts`。节点携带解释它的文档的 +//! 标识,因此前端可以在节点被点击时打开那篇文档。 +//! - 流程图,每个文件一张,位于 `content/flows/`。一张流程图以带形状的节点与 +//! 带分支的带标签边,描述某个算法的步骤,例如 SGP4 的传播序列。 +//! +//! 两者都是同一形状的纯 JSON,因此前端一个渲染器即可处理任一者。布局在前端由 +//! 节点种类算出;后端只提供结构,这让撰写的数据与任何特定的渲染方式无关。 use crate::docs::ApiCatalog; 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 /// that a new graph can be authored without touching the renderer. +/// +/// 图节点的种类。 +/// +/// 种类决定节点如何绘制。该集合刻意保持很小,使新增一张图无需改动渲染器。 #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum NodeKind { /// A concept in the knowledge graph. + /// + /// 知识图谱中的一个概念。 Concept, /// A crate of the `apsis-rs` workspace. + /// + /// `apsis-rs` 工作区中的一个 crate。 Crate, /// A layer of the `apsis-rs` workspace. + /// + /// `apsis-rs` 工作区中的一个层。 Layer, /// A step of an algorithm. + /// + /// 算法的一个步骤。 Step, /// A decision in an algorithm, with more than one outgoing edge. + /// + /// 算法中的一个判定,有多于一条出边。 Decision, /// A terminal step, such as a returned value or an error. + /// + /// 一个终结步骤,例如返回的值或一个错误。 Terminal, /// A data item, such as an element set or an epoch. + /// + /// 一个数据项,例如元素集或历元。 Data, } impl NodeKind { /// Parses a kind name, defaulting to [`NodeKind::Concept`]. + /// + /// 解析一个种类名,默认为 [`NodeKind::Concept`]。 pub fn parse(name: &str) -> Self { match name { "crate" => Self::Crate, @@ -56,6 +87,8 @@ impl NodeKind { } /// Returns the kind name as it is written in the data. + /// + /// 以数据中书写的原样返回种类名。 pub const fn name(self) -> &'static str { match self { Self::Concept => "concept", @@ -70,60 +103,108 @@ impl NodeKind { } /// A node of a graph. +/// +/// 图的一个节点。 #[derive(Debug, Clone)] pub struct Node { /// Identifier, unique within the graph. + /// + /// 标识,在图内唯一。 pub id: String, /// Display label in English. + /// + /// 英文显示标签。 pub label: String, /// Display label in Chinese, or `None` when the label is a name that is /// written the same way in both languages. + /// + /// 中文显示标签;当标签是一个在两种语言中写法相同的名字时为 `None`。 pub label_zh: Option, /// Kind, selecting how the node is drawn. + /// + /// 种类,决定节点如何绘制。 pub kind: NodeKind, /// Chapter or group the node belongs to, used for colouring. + /// + /// 节点所属的章或分组,用于着色。 pub group: String, /// One sentence description in English. + /// + /// 一句话英文描述。 + /// + /// 一句话英文描述。 pub summary: String, /// One sentence description in Chinese, when one is authored. + /// + /// 一句话中文描述,若已撰写。 + /// + /// 一句话中文描述,若已撰写。 pub summary_zh: Option, /// Identifier of the document that explains the node, when one exists. + /// + /// 解释该节点的文档标识,若存在。 pub document: Option, /// Identifier of the interface item, when the node names one. + /// + /// 接口条目标识,若该节点指名了某个条目。 pub api: Option, } /// An edge of a graph. +/// +/// 图的一条边。 #[derive(Debug, Clone)] pub struct Edge { /// Source node identifier. + /// + /// 起点节点标识。 pub source: String, /// Target node identifier. + /// + /// 终点节点标识。 pub target: String, /// Relationship name, such as `uses`. + /// + /// 关系名,例如 `uses`。 pub kind: String, /// Optional label drawn on the edge, in English. + /// + /// 绘制在边上的可选标签,英文。 pub label: Option, /// The same label in Chinese, when one is authored. + /// + /// 同一标签的中文,若已撰写。 pub label_zh: Option, } /// A graph, either the concept graph or one flow graph. +/// +/// 一张图,或为概念图谱,或为一张流程图。 #[derive(Debug, Clone)] pub struct Graph { /// Identifier of the graph. + /// + /// 图的标识。 pub id: String, /// Display title in English. + /// + /// 英文显示标题。 pub title: String, /// Display title in Chinese, when one is authored. + /// + /// 中文显示标题,若已撰写。 pub title_zh: Option, /// One sentence description in English. pub summary: String, /// One sentence description in Chinese, when one is authored. pub summary_zh: Option, /// Nodes. + /// + /// 各节点。 pub nodes: Vec, /// Edges. + /// + /// 各边。 pub edges: Vec, } @@ -132,12 +213,18 @@ impl Graph { /// /// Used to resolve the endpoints of an edge, which is what the check /// for a dangling edge does. + /// + /// 按标识返回一个节点。 + /// + /// 用于解析一条边的两个端点,悬空边的检查正是这么做的。 #[allow(dead_code)] pub fn node(&self, id: &str) -> Option<&Node> { self.nodes.iter().find(|node| node.id == id) } /// Returns the edges that leave a node. + /// + /// 返回离开某个节点的各条边。 #[allow(dead_code)] pub fn outgoing(&self, id: &str) -> impl Iterator { 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. +/// +/// 从内嵌内容载入概念图谱与每一张流程图。 pub fn load_graph() -> GraphSet { let concepts = crate::docs::content::get("graph/concepts.json") .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 /// identifier cannot be addressed. +/// +/// 从 JSON 表示解析一张图。 +/// +/// 标识缺失时返回 `None`,因为没有标识的图无法被寻址。 pub fn parse_graph(text: &str) -> Option { let value = json::parse(text).ok()?; let id = value.get("id")?.as_str()?.to_string(); @@ -306,6 +399,8 @@ pub fn parse_graph(text: &str) -> Option { /// Returns a member of a JSON object as an owned string, when it is a /// non-empty string. +/// +/// 把 JSON 对象的某个成员返回为自有字符串,当它是非空字符串时。 fn text_field(value: &Value, key: &str) -> Option { value .get(key) @@ -321,6 +416,13 @@ fn text_field(value: &Value, key: &str) -> Option { /// `foundation -> physics -> orbit -> rf -> network -> ops -> sim`. A layer /// 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. +/// +/// 从接口目录构建 crate 结构图。 +/// +/// 节点是各 crate,按层分组;边沿 `apsis-rs` 强制的层序: +/// `foundation -> physics -> orbit -> rf -> network -> ops -> sim`。 +/// 层边从每一层画向所启用特性集合中包含的下一层,这正是依赖规则在实践中 +/// 的含义。 pub fn crate_structure(catalog: &ApiCatalog) -> Graph { let layers = [ "foundation", @@ -340,6 +442,10 @@ pub fn crate_structure(catalog: &ApiCatalog) -> Graph { // 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, // where it is a crate like any other. + + // 不属于任何层的 crate 在层结构图中没有位置:工作区门面转出所有层, + // 它会落在一个自己并不属于的层之下。它留在索引里,在那里它与别的 crate + // 无异。 if krate.layer.is_empty() { continue; } @@ -372,6 +478,8 @@ pub fn crate_structure(catalog: &ApiCatalog) -> Graph { // One node per layer that the catalog contains, so the graph describes // this build rather than the whole workspace. + + // 目录中包含的每一层一个节点,因此该图描述的是本次构建,而不是整个工作区。 for layer in layers { if !present.contains(&layer) { continue; @@ -394,6 +502,8 @@ pub fn crate_structure(catalog: &ApiCatalog) -> Graph { } // The dependency rule, drawn between the layers that are present. + + // 依赖规则,画在存在的各层之间。 for window in layers.windows(2) { let (lower, upper) = (window[0], window[1]); 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 /// than in a separate translation file. +/// +/// 返回某个 crate 的中文摘要,若已撰写。 +/// +/// 以 crate 名为键,因此该表与图放在一起,而不在单独的译文文件中。 fn crate_summary_zh(name: &str) -> Option { let text = match name { "apsis-core" => "共享基础类型:通用错误、常量与单位标记 trait。", diff --git a/src/tools/mod.rs b/src/tools/mod.rs index 2e5cd8c..cb6c759 100644 --- a/src/tools/mod.rs +++ b/src/tools/mod.rs @@ -12,7 +12,6 @@ //! handler never has to parse a value itself and never sees a value of the //! wrong type. //! -//! //! 服务的第三项任务是为 `apsis-rs` 各内核提供一个在线试验台。注册表是「服务能 //! 运行什么」的唯一描述:每个工具声明其参数、类型、单位与默认值,前端据此渲染 //! 表单。因此新增一个工具意味着在此加一个条目、并在 [`handlers`] 中加一个处理 @@ -150,7 +149,6 @@ pub struct ToolSpec { /// The `apsis-rs` items the tool calls, for cross linking to the /// interface documentation. /// - /// /// 该工具调用的 `apsis-rs` 条目,用于交叉链接到接口文档。 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` /// lifetime and the registry holds no owned data. /// -/// /// 所有工具的注册表。 /// /// 该表是常量,因此其参数切片具有 `'static` 生命周期,注册表不持有任何自有数据。 @@ -220,7 +217,6 @@ impl Default for Registry { /// 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. /// -/// /// 工具表。 /// /// 它是一个常量而不是函数,这样参数切片会被提升为 `'static`,注册表借用它而不是 @@ -1033,7 +1029,6 @@ impl<'a> Params<'a> { /// declared by the parameter, and only a parameter with neither a value /// nor a default is reported as required. /// - /// /// 返回一个必需的数值。 /// /// 取值可以作为 JSON 数字或字符串到达,因为表单控件发送的是文本。缺失的成员 @@ -1078,7 +1073,6 @@ impl<'a> Params<'a> { /// A value that is not a whole number is rejected rather than rounded, /// 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 /// parameter. /// - /// /// 返回一个必须是某个选择型参数选项的取值。 pub fn choice(&self, name: &str) -> Result<&'static str, ToolError> { 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 /// 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 { /// the concept documentation, so a formula written between dollar signs is /// set the same way in both places. /// -/// /// 把一个工具编码为 JSON。 /// /// 描述与参数帮助都以 Markdown 书写,因此各发送两次:源码形式,供阅读 JSON 的人 diff --git a/tests/api.rs b/tests/api.rs index 1282cd5..29f565e 100644 --- a/tests/api.rs +++ b/tests/api.rs @@ -6,7 +6,6 @@ //! reaches only what the library makes public, so the few internal items the //! tests need are opened through `apsis_book::testkit`. //! -//! //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 经 `apsis_book::testkit` 开放。 diff --git a/tests/docs_api.rs b/tests/docs_api.rs index a3fbdcc..3f4307b 100644 --- a/tests/docs_api.rs +++ b/tests/docs_api.rs @@ -6,7 +6,6 @@ //! reaches only what the library makes public, so the few internal items the //! tests need are opened through `apsis_book::testkit`. //! -//! //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 经 `apsis_book::testkit` 开放。 diff --git a/tests/docs_content.rs b/tests/docs_content.rs index 54ecbcf..647051b 100644 --- a/tests/docs_content.rs +++ b/tests/docs_content.rs @@ -6,7 +6,6 @@ //! reaches only what the library makes public, so the few internal items the //! tests need are opened through `apsis_book::testkit`. //! -//! //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 经 `apsis_book::testkit` 开放。 diff --git a/tests/docs_document.rs b/tests/docs_document.rs index a0bf92d..8a577c7 100644 --- a/tests/docs_document.rs +++ b/tests/docs_document.rs @@ -6,7 +6,6 @@ //! reaches only what the library makes public, so the few internal items the //! tests need are opened through `apsis_book::testkit`. //! -//! //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 经 `apsis_book::testkit` 开放。 diff --git a/tests/docs_markdown.rs b/tests/docs_markdown.rs index f17fe42..3628530 100644 --- a/tests/docs_markdown.rs +++ b/tests/docs_markdown.rs @@ -6,7 +6,6 @@ //! reaches only what the library makes public, so the few internal items the //! tests need are opened through `apsis_book::testkit`. //! -//! //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 经 `apsis_book::testkit` 开放。 diff --git a/tests/docs_mathml.rs b/tests/docs_mathml.rs index 37d050c..35bdabd 100644 --- a/tests/docs_mathml.rs +++ b/tests/docs_mathml.rs @@ -6,7 +6,6 @@ //! reaches only what the library makes public, so the few internal items the //! tests need are opened through `apsis_book::testkit`. //! -//! //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 经 `apsis_book::testkit` 开放。 diff --git a/tests/embedded.rs b/tests/embedded.rs index 04ad478..ecd1f1a 100644 --- a/tests/embedded.rs +++ b/tests/embedded.rs @@ -6,7 +6,6 @@ //! reaches only what the library makes public, so the few internal items the //! tests need are opened through `apsis_book::testkit`. //! -//! //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 经 `apsis_book::testkit` 开放。 diff --git a/tests/graph.rs b/tests/graph.rs index aff88aa..648681d 100644 --- a/tests/graph.rs +++ b/tests/graph.rs @@ -6,7 +6,6 @@ //! reaches only what the library makes public, so the few internal items the //! tests need are opened through `apsis_book::testkit`. //! -//! //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 经 `apsis_book::testkit` 开放。 diff --git a/tests/http_request.rs b/tests/http_request.rs index e2d7200..28d0436 100644 --- a/tests/http_request.rs +++ b/tests/http_request.rs @@ -6,7 +6,6 @@ //! reaches only what the library makes public, so the few internal items the //! tests need are opened through `apsis_book::testkit`. //! -//! //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 经 `apsis_book::testkit` 开放。 diff --git a/tests/http_response.rs b/tests/http_response.rs index 1c9e488..33ab24d 100644 --- a/tests/http_response.rs +++ b/tests/http_response.rs @@ -6,7 +6,6 @@ //! reaches only what the library makes public, so the few internal items the //! tests need are opened through `apsis_book::testkit`. //! -//! //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 经 `apsis_book::testkit` 开放。 diff --git a/tests/http_server.rs b/tests/http_server.rs index 463c85b..d45eb66 100644 --- a/tests/http_server.rs +++ b/tests/http_server.rs @@ -6,7 +6,6 @@ //! reaches only what the library makes public, so the few internal items the //! tests need are opened through `apsis_book::testkit`. //! -//! //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 经 `apsis_book::testkit` 开放。 diff --git a/tests/i18n.rs b/tests/i18n.rs index b6752d6..b2825bd 100644 --- a/tests/i18n.rs +++ b/tests/i18n.rs @@ -6,7 +6,6 @@ //! reaches only what the library makes public, so the few internal items the //! tests need are opened through `apsis_book::testkit`. //! -//! //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 经 `apsis_book::testkit` 开放。 diff --git a/tests/json_codec.rs b/tests/json_codec.rs index c45d795..a600754 100644 --- a/tests/json_codec.rs +++ b/tests/json_codec.rs @@ -6,7 +6,6 @@ //! reaches only what the library makes public, so the few internal items the //! tests need are opened through `apsis_book::testkit`. //! -//! //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 经 `apsis_book::testkit` 开放。 diff --git a/tests/state.rs b/tests/state.rs index a9f200d..6c4c3d8 100644 --- a/tests/state.rs +++ b/tests/state.rs @@ -6,7 +6,6 @@ //! reaches only what the library makes public, so the few internal items the //! tests need are opened through `apsis_book::testkit`. //! -//! //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 经 `apsis_book::testkit` 开放。 diff --git a/tests/tools_handlers.rs b/tests/tools_handlers.rs index 844f41d..4a44289 100644 --- a/tests/tools_handlers.rs +++ b/tests/tools_handlers.rs @@ -6,7 +6,6 @@ //! reaches only what the library makes public, so the few internal items the //! tests need are opened through `apsis_book::testkit`. //! -//! //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 经 `apsis_book::testkit` 开放。 diff --git a/tests/tools_labels.rs b/tests/tools_labels.rs index 1b7e4cc..a046c29 100644 --- a/tests/tools_labels.rs +++ b/tests/tools_labels.rs @@ -6,7 +6,6 @@ //! reaches only what the library makes public, so the few internal items the //! tests need are opened through `apsis_book::testkit`. //! -//! //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 经 `apsis_book::testkit` 开放。 diff --git a/tests/tools_out.rs b/tests/tools_out.rs index 0c96bff..341adcd 100644 --- a/tests/tools_out.rs +++ b/tests/tools_out.rs @@ -6,7 +6,6 @@ //! reaches only what the library makes public, so the few internal items the //! tests need are opened through `apsis_book::testkit`. //! -//! //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 经 `apsis_book::testkit` 开放。 diff --git a/tests/tools_registry.rs b/tests/tools_registry.rs index 6917792..0ed2d94 100644 --- a/tests/tools_registry.rs +++ b/tests/tools_registry.rs @@ -6,7 +6,6 @@ //! reaches only what the library makes public, so the few internal items the //! tests need are opened through `apsis_book::testkit`. //! -//! //! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。 //! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目 //! 经 `apsis_book::testkit` 开放。