a3s_code_core/capability/
source.rs1use serde::Serialize;
2
3use super::{
4 CapabilitySetError, CapabilitySourceId, Sha256Digest, UseCapabilityGeneration,
5 UsePackageGeneration,
6};
7
8#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize)]
11#[serde(rename_all = "kebab-case")]
12pub enum CapabilitySourceClass {
13 BuiltIn,
14 Host,
15 UsePackage,
16 Session,
17}
18
19#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
20#[serde(rename_all = "camelCase", tag = "kind")]
21enum CapabilitySourceEvidence {
22 #[allow(dead_code)]
25 BuiltIn {
26 revision: Sha256Digest,
27 },
28 Host {
29 revision: Sha256Digest,
30 },
31 UsePackage {
32 capability: UseCapabilityGeneration,
33 package: UsePackageGeneration,
34 },
35 Session {
36 revision: Sha256Digest,
37 },
38}
39
40#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
44#[serde(rename_all = "camelCase")]
45pub struct CapabilitySource {
46 id: CapabilitySourceId,
47 class: CapabilitySourceClass,
48 evidence: CapabilitySourceEvidence,
49}
50
51impl CapabilitySource {
52 #[allow(dead_code)]
53 pub(crate) fn builtin(
54 component: impl Into<String>,
55 revision: Sha256Digest,
56 ) -> Result<Self, CapabilitySetError> {
57 Ok(Self {
58 id: CapabilitySourceId::scoped("builtin", component)?,
59 class: CapabilitySourceClass::BuiltIn,
60 evidence: CapabilitySourceEvidence::BuiltIn { revision },
61 })
62 }
63
64 pub fn host(
65 component: impl Into<String>,
66 revision: Sha256Digest,
67 ) -> Result<Self, CapabilitySetError> {
68 Ok(Self {
69 id: CapabilitySourceId::scoped("host", component)?,
70 class: CapabilitySourceClass::Host,
71 evidence: CapabilitySourceEvidence::Host { revision },
72 })
73 }
74
75 pub fn session(
76 registration: impl Into<String>,
77 revision: Sha256Digest,
78 ) -> Result<Self, CapabilitySetError> {
79 Ok(Self {
80 id: CapabilitySourceId::scoped("session", registration)?,
81 class: CapabilitySourceClass::Session,
82 evidence: CapabilitySourceEvidence::Session { revision },
83 })
84 }
85
86 pub fn use_package(
87 capability: UseCapabilityGeneration,
88 package: UsePackageGeneration,
89 ) -> Result<Self, CapabilitySetError> {
90 if capability.generation() == 0 {
91 return Err(CapabilitySetError::InvalidGeneration {
92 field: "use_capability_generation",
93 });
94 }
95 let id = CapabilitySourceId::scoped("use", package.package_id())?;
96 Ok(Self {
97 id,
98 class: CapabilitySourceClass::UsePackage,
99 evidence: CapabilitySourceEvidence::UsePackage {
100 capability,
101 package,
102 },
103 })
104 }
105
106 pub fn id(&self) -> &CapabilitySourceId {
107 &self.id
108 }
109
110 pub const fn class(&self) -> CapabilitySourceClass {
111 self.class
112 }
113
114 pub fn revision(&self) -> Option<&Sha256Digest> {
115 match &self.evidence {
116 CapabilitySourceEvidence::BuiltIn { revision }
117 | CapabilitySourceEvidence::Host { revision }
118 | CapabilitySourceEvidence::Session { revision } => Some(revision),
119 CapabilitySourceEvidence::UsePackage { .. } => None,
120 }
121 }
122
123 pub fn use_capability_generation(&self) -> Option<&UseCapabilityGeneration> {
124 match &self.evidence {
125 CapabilitySourceEvidence::UsePackage { capability, .. } => Some(capability),
126 _ => None,
127 }
128 }
129
130 pub fn use_package_generation(&self) -> Option<&UsePackageGeneration> {
131 match &self.evidence {
132 CapabilitySourceEvidence::UsePackage { package, .. } => Some(package),
133 _ => None,
134 }
135 }
136}