panproto_schema/protocol.rs
1//! Protocol definition.
2//!
3//! A [`Protocol`] identifies which schema theory and instance theory a
4//! particular data format uses, together with well-formedness rules
5//! for edges and the set of recognized vertex/constraint kinds.
6
7use serde::{Deserialize, Serialize};
8
9/// A well-formedness rule for edges of a given kind.
10///
11/// When `src_kinds` is non-empty, only vertices whose kind appears in the
12/// list may serve as the source of an edge of this kind. An empty list
13/// means any vertex kind is allowed. The same applies to `tgt_kinds`.
14#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
15pub struct EdgeRule {
16 /// The edge kind this rule governs (e.g., `"prop"`, `"record-schema"`).
17 pub edge_kind: String,
18 /// Permitted source vertex kinds (empty = any).
19 pub src_kinds: Vec<String>,
20 /// Permitted target vertex kinds (empty = any).
21 pub tgt_kinds: Vec<String>,
22}
23
24/// Identifies the schema and instance theories for a data-format protocol,
25/// together with structural well-formedness rules.
26///
27/// Protocols are the Level-1 configuration objects that drive schema
28/// construction and validation. Each protocol names a schema theory GAT
29/// and an instance theory GAT (both defined in `panproto-protocols`),
30/// and supplies edge rules, recognized vertex kinds, and constraint sorts.
31#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
32pub struct Protocol {
33 /// Human-readable protocol name (e.g., `"atproto"`, `"sql"`).
34 pub name: String,
35 /// Name of the schema theory GAT in the theory registry.
36 pub schema_theory: String,
37 /// Name of the instance theory GAT in the theory registry.
38 pub instance_theory: String,
39 /// Well-formedness rules for each edge kind.
40 pub edge_rules: Vec<EdgeRule>,
41 /// Vertex kinds that are considered "object-like" (containers).
42 pub obj_kinds: Vec<String>,
43 /// Recognized constraint sorts (e.g., `"maxLength"`, `"format"`).
44 pub constraint_sorts: Vec<String>,
45}
46
47impl Protocol {
48 /// Returns the [`EdgeRule`] for the given edge kind, if one exists.
49 #[must_use]
50 pub fn find_edge_rule(&self, edge_kind: &str) -> Option<&EdgeRule> {
51 self.edge_rules.iter().find(|r| r.edge_kind == edge_kind)
52 }
53
54 /// Returns `true` if `kind` is a recognized vertex kind in this protocol.
55 ///
56 /// The set of recognized kinds is the union of all kinds mentioned in
57 /// edge rules (both source and target) plus `obj_kinds`.
58 #[must_use]
59 pub fn is_known_vertex_kind(&self, kind: &str) -> bool {
60 if self.obj_kinds.iter().any(|k| k == kind) {
61 return true;
62 }
63 for rule in &self.edge_rules {
64 if rule.src_kinds.iter().any(|k| k == kind) {
65 return true;
66 }
67 if rule.tgt_kinds.iter().any(|k| k == kind) {
68 return true;
69 }
70 }
71 false
72 }
73}