planspec_core/
resource.rs1use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6use crate::types::binding::Binding;
7use crate::types::capability::Capability;
8use crate::types::execution::Execution;
9use crate::types::gate::Gate;
10use crate::types::goal::Goal;
11use crate::types::meta::ObjectMeta;
12use crate::types::plan::Plan;
13
14#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
18#[serde(untagged)]
19pub enum Resource {
20 Goal(Goal),
22 Plan(Plan),
24 Capability(Capability),
26 Binding(Binding),
28 Execution(Execution),
30 Gate(Gate),
32}
33
34impl Resource {
35 pub fn kind(&self) -> &str {
37 match self {
38 Resource::Goal(_) => "Goal",
39 Resource::Plan(_) => "Plan",
40 Resource::Capability(_) => "Capability",
41 Resource::Binding(_) => "Binding",
42 Resource::Execution(_) => "Execution",
43 Resource::Gate(_) => "Gate",
44 }
45 }
46
47 pub fn metadata(&self) -> &ObjectMeta {
49 match self {
50 Resource::Goal(r) => &r.metadata,
51 Resource::Plan(r) => &r.metadata,
52 Resource::Capability(r) => &r.metadata,
53 Resource::Binding(r) => &r.metadata,
54 Resource::Execution(r) => &r.metadata,
55 Resource::Gate(r) => &r.metadata,
56 }
57 }
58
59 pub fn metadata_mut(&mut self) -> &mut ObjectMeta {
61 match self {
62 Resource::Goal(r) => &mut r.metadata,
63 Resource::Plan(r) => &mut r.metadata,
64 Resource::Capability(r) => &mut r.metadata,
65 Resource::Binding(r) => &mut r.metadata,
66 Resource::Execution(r) => &mut r.metadata,
67 Resource::Gate(r) => &mut r.metadata,
68 }
69 }
70
71 pub fn name(&self) -> &str {
73 &self.metadata().name
74 }
75
76 pub fn namespace(&self) -> &str {
78 &self.metadata().namespace
79 }
80
81 pub fn api_version(&self) -> &str {
83 match self {
84 Resource::Goal(r) => &r.api_version,
85 Resource::Plan(r) => &r.api_version,
86 Resource::Capability(r) => &r.api_version,
87 Resource::Binding(r) => &r.api_version,
88 Resource::Execution(r) => &r.api_version,
89 Resource::Gate(r) => &r.api_version,
90 }
91 }
92}
93
94impl From<Goal> for Resource {
95 fn from(goal: Goal) -> Self {
96 Resource::Goal(goal)
97 }
98}
99
100impl From<Plan> for Resource {
101 fn from(plan: Plan) -> Self {
102 Resource::Plan(plan)
103 }
104}
105
106impl From<Capability> for Resource {
107 fn from(capability: Capability) -> Self {
108 Resource::Capability(capability)
109 }
110}
111
112impl From<Binding> for Resource {
113 fn from(binding: Binding) -> Self {
114 Resource::Binding(binding)
115 }
116}
117
118impl From<Execution> for Resource {
119 fn from(execution: Execution) -> Self {
120 Resource::Execution(execution)
121 }
122}
123
124impl From<Gate> for Resource {
125 fn from(gate: Gate) -> Self {
126 Resource::Gate(gate)
127 }
128}
129
130impl TryFrom<Value> for Resource {
131 type Error = ResourceParseError;
132
133 fn try_from(value: Value) -> Result<Self, Self::Error> {
134 let kind = value
135 .get("kind")
136 .and_then(|k| k.as_str())
137 .ok_or(ResourceParseError::MissingKind)?;
138
139 match kind {
140 "Goal" => {
141 let goal: Goal = serde_json::from_value(value)
142 .map_err(|e| ResourceParseError::DeserializationError(e.to_string()))?;
143 Ok(Resource::Goal(goal))
144 }
145 "Plan" => {
146 let plan: Plan = serde_json::from_value(value)
147 .map_err(|e| ResourceParseError::DeserializationError(e.to_string()))?;
148 Ok(Resource::Plan(plan))
149 }
150 "Capability" => {
151 let capability: Capability = serde_json::from_value(value)
152 .map_err(|e| ResourceParseError::DeserializationError(e.to_string()))?;
153 Ok(Resource::Capability(capability))
154 }
155 "Binding" => {
156 let binding: Binding = serde_json::from_value(value)
157 .map_err(|e| ResourceParseError::DeserializationError(e.to_string()))?;
158 Ok(Resource::Binding(binding))
159 }
160 "Execution" => {
161 let execution: Execution = serde_json::from_value(value)
162 .map_err(|e| ResourceParseError::DeserializationError(e.to_string()))?;
163 Ok(Resource::Execution(execution))
164 }
165 "Gate" => {
166 let gate: Gate = serde_json::from_value(value)
167 .map_err(|e| ResourceParseError::DeserializationError(e.to_string()))?;
168 Ok(Resource::Gate(gate))
169 }
170 _ => Err(ResourceParseError::UnknownKind(kind.to_string())),
171 }
172 }
173}
174
175#[derive(Debug, Clone, thiserror::Error)]
177pub enum ResourceParseError {
178 #[error("missing 'kind' field")]
180 MissingKind,
181
182 #[error("unknown resource kind: {0}")]
184 UnknownKind(String),
185
186 #[error("deserialization error: {0}")]
188 DeserializationError(String),
189}