Skip to main content

nichlink/registry_core/declaration/
contract.rs

1//! Compile-time construction contracts for registration faces.
2//! 注册面的编译期构造合同。
3//!
4//! A preset declares the parts it expects, a parts type declares what it
5//! supplies, and [`assert_contract`] forces the two output types to match during
6//! macro expansion. [`ObjectContract`] is the runtime-readable record of that
7//! relationship.
8//! preset 声明它要求的 parts,parts 类型声明它提供的 parts,[`assert_contract`] 在宏
9//! 展开时强制两者的输出类型相同。[`ObjectContract`] 是这层关系的运行时可读记录。
10
11use super::*;
12
13/// A preset declares the construction shape it expects.
14/// preset 声明它要求的构造形状。
15pub trait PresetContract {
16    /// Concrete type this preset constructs.
17    /// 该 preset 构造出的具体类型。
18    type Output;
19    /// Part names that must all be supplied before the preset can construct.
20    /// 该 preset 完成构造前必须提供的全部 part 名称。
21    const REQUIRED_PARTS: &'static [&'static str];
22}
23
24/// Parts declare the construction shape an object supplies.
25/// parts 声明 object 实际提供的构造形状。
26pub trait PartsContract {
27    /// Concrete type these parts construct.
28    /// 这些 parts 构造出的具体类型。
29    type Output;
30    /// Part names this type actually supplies.
31    /// 该类型实际提供的 part 名称。
32    const PROVIDED_PARTS: &'static [&'static str];
33}
34
35/// Marker preset for a face that is constructed without a preset.
36/// 不需要 preset 即可构造的注册面所使用的标记类型。
37pub struct NoPreset;
38
39impl PresetContract for NoPreset {
40    type Output = ();
41    const REQUIRED_PARTS: &'static [&'static str] = &[];
42}
43
44/// Marker parts for a face that supplies no parts.
45/// 不提供任何 part 的注册面所使用的标记类型。
46pub struct NoParts;
47
48impl PartsContract for NoParts {
49    type Output = ();
50    const PROVIDED_PARTS: &'static [&'static str] = &[];
51}
52
53/// Force preset and parts output types to match during macro expansion.
54/// 在宏展开时强制 preset 与 parts 的输出类型相同。
55///
56/// ```compile_fail
57/// use nichlink::{assert_contract, PartsContract, PresetContract};
58///
59/// struct Expected;
60/// struct Supplied;
61/// impl PresetContract for Expected {
62///     type Output = Expected;
63///     const REQUIRED_PARTS: &'static [&'static str] = &[];
64/// }
65/// impl PartsContract for Supplied {
66///     type Output = Supplied;
67///     const PROVIDED_PARTS: &'static [&'static str] = &[];
68/// }
69///
70/// const _: () = assert_contract::<Expected, Supplied>();
71/// ```
72pub const fn assert_contract<P, T>()
73where
74    P: PresetContract,
75    T: PartsContract<Output = P::Output>,
76{
77}
78
79impl ObjectContract {
80    /// Copy this borrowed contract into the owned form a snapshot can retain.
81    /// 将该借用合同复制为快照可长期持有的拥有所有权形式。
82    pub fn into_owned(self) -> OwnedObjectContract {
83        OwnedObjectContract {
84            required_parts: self
85                .required_parts
86                .iter()
87                .map(|value| (*value).to_owned())
88                .collect(),
89            provided_parts: self
90                .provided_parts
91                .iter()
92                .map(|value| (*value).to_owned())
93                .collect(),
94        }
95    }
96
97    /// Return one message per unmet part requirement; an empty result means the
98    /// contract holds. `object` names the face being checked.
99    /// 每个未满足的 part 要求各返回一条消息;结果为空表示合同成立。
100    /// `object` 是被检查的注册面名称。
101    ///
102    /// The output half of this check is gone with the two names it compared: a
103    /// type-level `assert_contract` proves the same fact at compile time, per
104    /// face, and a graft cut proves it across two faces. This method now reports
105    /// only what the trait constants say, which is the part no compiler can see.
106    /// 本检查的输出那一半随它比较的那两个名字一起删除:同一件事由编译期
107    /// `assert_contract` 按面证明、由嫁接切口跨两个面证明。本方法现在只报告 trait 常量
108    /// 说了算的东西——那是编译器看不到的部分。
109    pub fn validate(&self, object: &str) -> Vec<String> {
110        validate_object_contract(self.required_parts, self.provided_parts, object)
111    }
112}
113
114/// Runtime-readable form of the construction contract.
115/// 构造合同的运行时可读形式。
116#[derive(Clone, Copy, Debug)]
117pub struct ObjectContract {
118    /// Part names the preset declared it needs.
119    /// preset 声明它需要的 part 名称。
120    pub required_parts: &'static [&'static str],
121    /// Part names the parts type supplied.
122    /// parts 类型实际提供的 part 名称。
123    pub provided_parts: &'static [&'static str],
124}