lexicon_spec/
capability.rs1use std::collections::HashSet;
4
5use serde::{Deserialize, Serialize};
6
7use crate::mode::OperatingMode;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
11#[serde(rename_all = "snake_case")]
12pub enum Capability {
13 RepoContracts,
15 RepoConformance,
16 RepoScoring,
17 RepoGates,
18 RepoApi,
19
20 WorkspaceArchitecture,
22 WorkspaceDependencyLaw,
23 WorkspaceSharedContracts,
24
25 EcosystemGovernance,
27 EcosystemSharedContracts,
28 EcosystemImpact,
29}
30
31#[derive(Debug, Clone, PartialEq, Eq)]
33pub struct CapabilitySet {
34 inner: HashSet<Capability>,
35}
36
37impl CapabilitySet {
38 pub fn for_mode(mode: OperatingMode) -> Self {
40 let mut caps = HashSet::new();
41
42 caps.insert(Capability::RepoContracts);
44 caps.insert(Capability::RepoConformance);
45 caps.insert(Capability::RepoScoring);
46 caps.insert(Capability::RepoGates);
47 caps.insert(Capability::RepoApi);
48
49 if matches!(mode, OperatingMode::Workspace | OperatingMode::Ecosystem) {
50 caps.insert(Capability::WorkspaceArchitecture);
51 caps.insert(Capability::WorkspaceDependencyLaw);
52 caps.insert(Capability::WorkspaceSharedContracts);
53 }
54
55 if mode == OperatingMode::Ecosystem {
56 caps.insert(Capability::EcosystemGovernance);
57 caps.insert(Capability::EcosystemSharedContracts);
58 caps.insert(Capability::EcosystemImpact);
59 }
60
61 Self { inner: caps }
62 }
63
64 pub fn has(&self, cap: Capability) -> bool {
66 self.inner.contains(&cap)
67 }
68
69 pub fn is_empty(&self) -> bool {
71 self.inner.is_empty()
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78
79 #[test]
80 fn test_repo_capabilities() {
81 let set = CapabilitySet::for_mode(OperatingMode::Repo);
82 assert_eq!(set.inner.len(), 5);
83 assert!(set.has(Capability::RepoContracts));
84 assert!(set.has(Capability::RepoConformance));
85 assert!(set.has(Capability::RepoScoring));
86 assert!(set.has(Capability::RepoGates));
87 assert!(set.has(Capability::RepoApi));
88 assert!(!set.has(Capability::WorkspaceArchitecture));
89 assert!(!set.has(Capability::EcosystemGovernance));
90 }
91
92 #[test]
93 fn test_workspace_capabilities() {
94 let set = CapabilitySet::for_mode(OperatingMode::Workspace);
95 assert_eq!(set.inner.len(), 8);
96 assert!(set.has(Capability::RepoContracts));
98 assert!(set.has(Capability::RepoApi));
99 assert!(set.has(Capability::WorkspaceArchitecture));
101 assert!(set.has(Capability::WorkspaceDependencyLaw));
102 assert!(set.has(Capability::WorkspaceSharedContracts));
103 assert!(!set.has(Capability::EcosystemGovernance));
105 }
106
107 #[test]
108 fn test_ecosystem_capabilities() {
109 let set = CapabilitySet::for_mode(OperatingMode::Ecosystem);
110 assert_eq!(set.inner.len(), 11);
111 assert!(set.has(Capability::RepoContracts));
112 assert!(set.has(Capability::WorkspaceArchitecture));
113 assert!(set.has(Capability::EcosystemGovernance));
114 assert!(set.has(Capability::EcosystemSharedContracts));
115 assert!(set.has(Capability::EcosystemImpact));
116 }
117
118 #[test]
119 fn test_is_empty() {
120 let set = CapabilitySet::for_mode(OperatingMode::Repo);
121 assert!(!set.is_empty());
122 }
123
124 #[test]
125 fn test_capability_serde_roundtrip() {
126 let cap = Capability::WorkspaceArchitecture;
127 let json = serde_json::to_string(&cap).unwrap();
128 let back: Capability = serde_json::from_str(&json).unwrap();
129 assert_eq!(cap, back);
130 }
131}