Skip to main content

type_bridge_contract/
semantic_profile.rs

1//! Versioned defaults that affect schema semantics without changing declarations.
2
3use crate::diagnostic::{Diagnostic, DiagnosticCategory};
4use crate::fingerprint::SemanticProfileId;
5use crate::value::Cardinality;
6
7/// Interface family whose omitted cardinality is profile-defined.
8#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
9pub enum InterfaceKind {
10    /// Attribute ownership.
11    Owns,
12    /// Relation role declaration.
13    Relates,
14    /// Role playing declaration.
15    Plays,
16}
17
18/// Closed server-semantic defaults selected by a versioned profile identifier.
19#[derive(Clone, Debug, Eq, PartialEq)]
20pub struct SemanticProfile {
21    id: SemanticProfileId,
22    owns_cardinality: Cardinality,
23    relates_cardinality: Cardinality,
24    plays_cardinality: Cardinality,
25    key_owns_cardinality: Cardinality,
26}
27
28impl SemanticProfile {
29    /// Resolve a supported semantic profile, rejecting unknown default tables.
30    pub fn resolve(id: &SemanticProfileId) -> Result<Self, Diagnostic> {
31        match id.as_str() {
32            "typedb-3.11.5/v1" | "typedb-3.12.1/v1" => {
33                let bounded_to_one = Cardinality::new(0, Some(1))
34                    .expect("the frozen zero-to-one cardinality is valid");
35                let unconstrained = Cardinality::new(0, None)
36                    .expect("the frozen unconstrained cardinality is valid");
37                let exactly_one = Cardinality::new(1, Some(1))
38                    .expect("the frozen exactly-one cardinality is valid");
39                Ok(Self {
40                    id: id.clone(),
41                    owns_cardinality: bounded_to_one,
42                    relates_cardinality: bounded_to_one,
43                    plays_cardinality: unconstrained,
44                    key_owns_cardinality: exactly_one,
45                })
46            }
47            _ => Err(Diagnostic::stable(
48                DiagnosticCategory::UnsupportedCapability,
49                "unsupported_semantic_profile",
50                "semantic profile has no frozen schema-default table",
51            )),
52        }
53    }
54
55    /// Return the versioned profile identifier.
56    #[must_use]
57    pub const fn id(&self) -> &SemanticProfileId {
58        &self.id
59    }
60
61    /// Return the materialized cardinality for an omitted interface annotation.
62    #[must_use]
63    pub const fn default_cardinality(&self, kind: InterfaceKind) -> Cardinality {
64        match kind {
65            InterfaceKind::Owns => self.owns_cardinality,
66            InterfaceKind::Relates => self.relates_cardinality,
67            InterfaceKind::Plays => self.plays_cardinality,
68        }
69    }
70
71    /// Materialize effective interface cardinality, including `@key`'s exact-one contract.
72    #[must_use]
73    pub const fn effective_cardinality(
74        &self,
75        kind: InterfaceKind,
76        explicit: Option<Cardinality>,
77        key: bool,
78    ) -> Cardinality {
79        match (kind, key, explicit) {
80            (InterfaceKind::Owns, true, _) => self.key_owns_cardinality,
81            (_, _, Some(cardinality)) => cardinality,
82            _ => self.default_cardinality(kind),
83        }
84    }
85}