1use std::collections::BTreeMap;
2
3use sim_kernel::{Error, Expr, Result, Symbol};
4
5#[derive(Clone, Debug, PartialEq, Eq)]
7pub enum RenderClass {
8 Structural,
10 Frame,
12 Data,
14 Evidence,
16 Review,
18 Vote,
20 Patch,
22 Fetch,
24 Return,
26 Receipt,
28 Extension,
30}
31
32#[derive(Clone, Debug, PartialEq, Eq)]
34pub enum AuthorityClass {
35 Data,
37 Normative,
39 Callable,
41 Evidence,
43}
44
45#[derive(Clone, Debug, PartialEq, Eq)]
47pub enum UnknownPolicy {
48 Reject,
50 PreserveDataOnly,
52}
53
54#[derive(Clone, Debug, PartialEq, Eq)]
56pub struct BridgePartSpec {
57 pub kind: Symbol,
59 pub shape_expr: Expr,
61 pub render_class: RenderClass,
63 pub authority_class: AuthorityClass,
65 pub unknown_policy: UnknownPolicy,
67}
68
69impl BridgePartSpec {
70 pub fn new(
72 kind: Symbol,
73 shape_expr: Expr,
74 render_class: RenderClass,
75 authority_class: AuthorityClass,
76 unknown_policy: UnknownPolicy,
77 ) -> Self {
78 Self {
79 kind,
80 shape_expr,
81 render_class,
82 authority_class,
83 unknown_policy,
84 }
85 }
86
87 pub fn preserve_data_only(kind: Symbol, shape_expr: Expr) -> Self {
89 Self::new(
90 kind,
91 shape_expr,
92 RenderClass::Extension,
93 AuthorityClass::Data,
94 UnknownPolicy::PreserveDataOnly,
95 )
96 }
97}
98
99#[derive(Clone, Debug, Default, PartialEq, Eq)]
101pub struct BridgePartBook {
102 specs: BTreeMap<Symbol, BridgePartSpec>,
103}
104
105impl BridgePartBook {
106 pub fn new() -> Self {
108 Self::default()
109 }
110
111 pub fn register(&mut self, spec: BridgePartSpec) {
113 self.specs.insert(spec.kind.clone(), spec);
114 }
115
116 pub fn spec(&self, kind: &Symbol) -> Option<&BridgePartSpec> {
118 self.specs.get(kind)
119 }
120
121 pub fn specs(&self) -> impl Iterator<Item = &BridgePartSpec> {
123 self.specs.values()
124 }
125
126 pub fn require_registered(&self, kind: &Symbol) -> Result<&BridgePartSpec> {
128 self.spec(kind)
129 .ok_or_else(|| Error::Eval(format!("unknown BRIDGE part kind {kind}")))
130 }
131}
132
133#[derive(Clone, Debug, PartialEq, Eq)]
135pub struct BridgeBook {
136 pub parts: BridgePartBook,
138 pub moves: crate::BridgeMoveBook,
140 pub frames: crate::BridgeFrameBook,
142 pub profiles: crate::BridgeProfileBook,
144 pub warrant_policy: crate::BridgeWarrantPolicy,
146}
147
148impl BridgeBook {
149 pub fn new(
151 parts: BridgePartBook,
152 moves: crate::BridgeMoveBook,
153 frames: crate::BridgeFrameBook,
154 profiles: crate::BridgeProfileBook,
155 ) -> Self {
156 Self {
157 parts,
158 moves,
159 frames,
160 profiles,
161 warrant_policy: crate::BridgeWarrantPolicy::SharedTrust,
162 }
163 }
164
165 pub fn standard() -> Self {
167 Self::new(
168 crate::standard_part_book(),
169 crate::standard_move_book(),
170 crate::standard_frame_book(),
171 crate::standard_profile_book(),
172 )
173 }
174
175 pub fn with_part(mut self, spec: BridgePartSpec) -> Self {
177 self.parts.register(spec);
178 self
179 }
180
181 pub fn with_frame(mut self, spec: crate::FrameSpec) -> Self {
183 self.frames.register(spec);
184 self
185 }
186
187 pub fn with_profile(mut self, spec: crate::BridgeProfileSpec) -> Self {
189 self.profiles.register(spec);
190 self
191 }
192
193 pub fn with_warrant_policy(mut self, policy: crate::BridgeWarrantPolicy) -> Self {
195 self.warrant_policy = policy;
196 self
197 }
198}
199
200pub fn standard_part_book() -> BridgePartBook {
202 let mut book = BridgePartBook::new();
203 for spec in [
204 spec("Given", RenderClass::Data, AuthorityClass::Data),
205 spec("Frame", RenderClass::Frame, AuthorityClass::Normative),
206 spec("Call", RenderClass::Structural, AuthorityClass::Callable),
207 spec("Weave", RenderClass::Structural, AuthorityClass::Normative),
208 spec("Check", RenderClass::Structural, AuthorityClass::Normative),
209 spec("Evidence", RenderClass::Evidence, AuthorityClass::Evidence),
210 spec("Review", RenderClass::Review, AuthorityClass::Evidence),
211 spec("Vote", RenderClass::Vote, AuthorityClass::Evidence),
212 spec("Patch", RenderClass::Patch, AuthorityClass::Normative),
213 spec("Fetch", RenderClass::Fetch, AuthorityClass::Callable),
214 spec("Return", RenderClass::Return, AuthorityClass::Normative),
215 spec("Receipt", RenderClass::Receipt, AuthorityClass::Evidence),
216 spec("Attest", RenderClass::Evidence, AuthorityClass::Evidence),
217 spec("Extension", RenderClass::Extension, AuthorityClass::Data),
218 ] {
219 book.register(spec);
220 }
221 book
222}
223
224fn spec(name: &str, render_class: RenderClass, authority_class: AuthorityClass) -> BridgePartSpec {
225 let kind = Symbol::qualified("bridge", name);
226 BridgePartSpec::new(
227 kind.clone(),
228 Expr::Symbol(kind),
229 render_class,
230 authority_class,
231 UnknownPolicy::Reject,
232 )
233}