1use crate::{
8 capability::CapabilityName,
9 datum::Datum,
10 datum_store::DatumStore,
11 error::Result,
12 id::Symbol,
13 ref_id::{ContentId, Coordinate, HandleId, Ref},
14};
15
16#[derive(Clone, Debug, PartialEq, Eq)]
37pub struct Claim {
38 pub id: Option<ContentId>,
40 pub subject: Ref,
42 pub predicate: Symbol,
44 pub object: Ref,
46 pub kind: ClaimKind,
48 pub evidence: Vec<Ref>,
50 pub requires: Vec<CapabilityName>,
52 pub visibility: Visibility,
54}
55
56#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
58pub enum ClaimKind {
59 Asserted,
61 Derived,
63 Observed,
65 Revoked,
67}
68
69#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
71pub enum Visibility {
72 Public,
74 CapabilityGated,
76 Private,
78}
79
80#[derive(Clone, Debug, Default, PartialEq, Eq)]
82pub struct ClaimPattern {
83 pub subject: Option<Ref>,
85 pub predicate: Option<Symbol>,
87 pub object: Option<Ref>,
89 pub include_revoked: bool,
91}
92
93impl Claim {
94 pub fn new(subject: Ref, predicate: Symbol, object: Ref) -> Self {
96 Self {
97 id: None,
98 subject,
99 predicate,
100 object,
101 kind: ClaimKind::Asserted,
102 evidence: Vec::new(),
103 requires: Vec::new(),
104 visibility: Visibility::Public,
105 }
106 }
107
108 pub fn public(subject: Ref, predicate: Symbol, object: Ref) -> Self {
110 Self::new(subject, predicate, object)
111 }
112
113 pub fn content_object(
116 store: &mut dyn DatumStore,
117 subject: Ref,
118 predicate: Symbol,
119 object: Datum,
120 ) -> Result<Self> {
121 Ok(Self::new(
122 subject,
123 predicate,
124 Self::intern_object(store, object)?,
125 ))
126 }
127
128 pub fn intern_object(store: &mut dyn DatumStore, object: Datum) -> Result<Ref> {
130 store.intern(object).map(Ref::Content)
131 }
132
133 pub fn with_kind(mut self, kind: ClaimKind) -> Self {
135 self.kind = kind;
136 self
137 }
138
139 pub fn with_visibility(mut self, visibility: Visibility) -> Self {
141 self.visibility = visibility;
142 self
143 }
144
145 pub fn with_evidence(mut self, evidence: Vec<Ref>) -> Self {
147 self.evidence = evidence;
148 self
149 }
150
151 pub fn requiring(mut self, capability: CapabilityName) -> Self {
153 self.requires.push(capability);
154 self
155 }
156
157 pub fn with_requirements(mut self, requires: Vec<CapabilityName>) -> Self {
159 self.requires = requires;
160 self
161 }
162
163 pub fn canonical_datum(&self) -> Datum {
165 Datum::Node {
166 tag: core_symbol("claim"),
167 fields: vec![
168 (Symbol::new("subject"), ref_datum(&self.subject)),
169 (
170 Symbol::new("predicate"),
171 Datum::Symbol(self.predicate.clone()),
172 ),
173 (Symbol::new("object"), ref_datum(&self.object)),
174 (Symbol::new("kind"), Datum::Symbol(self.kind.as_symbol())),
175 (
176 Symbol::new("evidence"),
177 Datum::Vector(self.evidence.iter().map(ref_datum).collect()),
178 ),
179 (
180 Symbol::new("requires"),
181 Datum::Set(requirement_data(&self.requires)),
182 ),
183 (
184 Symbol::new("visibility"),
185 Datum::Symbol(self.visibility.as_symbol()),
186 ),
187 ],
188 }
189 }
190
191 pub fn content_id(&self, store: &mut dyn DatumStore) -> Result<ContentId> {
193 store.intern(self.canonical_datum())
194 }
195}
196
197impl ClaimKind {
198 pub fn as_symbol(self) -> Symbol {
200 match self {
201 Self::Asserted => core_symbol("asserted"),
202 Self::Derived => core_symbol("derived"),
203 Self::Observed => core_symbol("observed"),
204 Self::Revoked => core_symbol("revoked"),
205 }
206 }
207}
208
209impl Visibility {
210 pub fn as_symbol(self) -> Symbol {
212 match self {
213 Self::Public => core_symbol("public"),
214 Self::CapabilityGated => core_symbol("capability-gated"),
215 Self::Private => core_symbol("private"),
216 }
217 }
218}
219
220impl ClaimPattern {
221 pub fn any() -> Self {
223 Self::default()
224 }
225
226 pub fn exact(subject: Ref, predicate: Symbol, object: Ref) -> Self {
228 Self {
229 subject: Some(subject),
230 predicate: Some(predicate),
231 object: Some(object),
232 include_revoked: false,
233 }
234 }
235
236 pub fn include_revoked(mut self) -> Self {
238 self.include_revoked = true;
239 self
240 }
241}
242
243fn requirement_data(requires: &[CapabilityName]) -> Vec<Datum> {
244 let mut requirements = requires
245 .iter()
246 .map(|capability| Datum::String(capability.as_str().to_owned()))
247 .collect::<Vec<_>>();
248 requirements.sort_by_key(|datum| datum.canonical_bytes().unwrap_or_default());
249 requirements.dedup();
250 requirements
251}
252
253fn ref_datum(reference: &Ref) -> Datum {
254 match reference {
255 Ref::Symbol(symbol) => Datum::Node {
256 tag: core_symbol("ref"),
257 fields: vec![
258 (Symbol::new("kind"), Datum::Symbol(core_symbol("symbol"))),
259 (Symbol::new("symbol"), Datum::Symbol(symbol.clone())),
260 ],
261 },
262 Ref::Content(content) => Datum::Node {
263 tag: core_symbol("ref"),
264 fields: vec![
265 (Symbol::new("kind"), Datum::Symbol(core_symbol("content"))),
266 (Symbol::new("content"), content_id_datum(content)),
267 ],
268 },
269 Ref::Handle(handle) => Datum::Node {
270 tag: core_symbol("ref"),
271 fields: vec![
272 (Symbol::new("kind"), Datum::Symbol(core_symbol("handle"))),
273 (Symbol::new("id"), handle_id_datum(*handle)),
274 ],
275 },
276 Ref::Coord(coordinate) => coordinate_datum(coordinate),
277 }
278}
279
280fn coordinate_datum(coordinate: &Coordinate) -> Datum {
281 Datum::Node {
282 tag: core_symbol("ref"),
283 fields: vec![
284 (Symbol::new("kind"), Datum::Symbol(core_symbol("coord"))),
285 (
286 Symbol::new("space"),
287 Datum::Symbol(coordinate.space.clone()),
288 ),
289 (
290 Symbol::new("ordinal"),
291 content_id_datum(&coordinate.ordinal),
292 ),
293 ],
294 }
295}
296
297fn content_id_datum(content: &ContentId) -> Datum {
298 Datum::Node {
299 tag: core_symbol("content-id"),
300 fields: vec![
301 (
302 Symbol::new("algorithm"),
303 Datum::Symbol(content.algorithm.clone()),
304 ),
305 (Symbol::new("bytes"), Datum::Bytes(content.bytes.to_vec())),
306 ],
307 }
308}
309
310fn handle_id_datum(handle: HandleId) -> Datum {
311 Datum::Bytes(handle.0.to_be_bytes().to_vec())
312}
313
314fn core_symbol(name: &str) -> Symbol {
315 Symbol::qualified("core", name)
316}