Skip to main content

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}