1#![deny(
2 warnings,
3 missing_debug_implementations,
4 trivial_casts,
5 trivial_numeric_casts,
6 unsafe_code,
7 unstable_features,
8 unused_import_braces,
9 unused_qualifications,
10 unreachable_pub,
11 type_alias_bounds,
12 trivial_bounds,
13 mutable_transmutes,
14 invalid_value,
15 explicit_outlives_requirements,
16 deprecated,
17 clashing_extern_declarations,
18 clippy::expect_used,
19 clippy::explicit_deref_methods
20)]
21#![warn(clippy::cognitive_complexity)]
22#![allow(missing_docs, clippy::exhaustive_enums, clippy::exhaustive_structs)]
23
24#[cfg(feature = "config")]
25pub(crate) mod conversions;
26pub(crate) mod parse;
27
28use std::collections::HashMap;
29use std::str::FromStr;
30
31use num_traits::FromPrimitive;
32use serde::{Deserialize, Serialize};
33use serde_json::Value;
34use serde_with_expand_env::with_expand_envs;
35
36#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)]
37#[serde(deny_unknown_fields)]
38pub struct HostManifest {
40 #[serde(deserialize_with = "with_expand_envs")]
43 pub format: u32,
44 #[serde(default)]
46 #[serde(deserialize_with = "with_expand_envs")]
47 pub version: String,
48 #[serde(default)]
50 pub host: Option<HostConfig>,
51 #[serde(default)]
53 pub network: NetworkManifest,
54 #[serde(default)]
56 pub default_schematic: Option<String>,
57}
58
59#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)]
60#[serde(deny_unknown_fields)]
61pub struct HostConfig {
63 #[serde(default)]
65 #[serde(deserialize_with = "with_expand_envs")]
66 pub allow_latest: bool,
67 #[serde(default)]
69 #[serde(skip_serializing_if = "Vec::is_empty")]
70 pub insecure_registries: Vec<String>,
71 #[serde(default)]
73 pub id: Option<String>,
74 #[serde(default)]
76 #[serde(skip_serializing_if = "Vec::is_empty")]
77 pub expose: Vec<String>,
78 #[serde(default)]
80 pub mesh: Option<MeshConfig>,
81 #[serde(default)]
83 pub rpc: Option<HttpConfig>,
84 #[serde(default)]
86 pub http: Option<HttpConfig>,
87}
88
89#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)]
90#[serde(deny_unknown_fields)]
91pub struct HttpConfig {
93 #[serde(default)]
95 #[serde(deserialize_with = "with_expand_envs")]
96 pub enabled: bool,
97 #[serde(default)]
99 pub port: Option<u16>,
100 #[serde(default)]
102 pub address: Option<String>,
103 #[serde(default)]
105 pub pem: Option<String>,
106 #[serde(default)]
108 pub key: Option<String>,
109 #[serde(default)]
111 pub ca: Option<String>,
112}
113
114#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)]
115#[serde(deny_unknown_fields)]
116pub struct MeshConfig {
118 #[serde(default)]
120 #[serde(deserialize_with = "with_expand_envs")]
121 pub enabled: bool,
122 #[serde(default)]
124 #[serde(deserialize_with = "with_expand_envs")]
125 pub address: String,
126 #[serde(default)]
128 pub creds_path: Option<String>,
129 #[serde(default)]
131 pub token: Option<String>,
132}
133
134#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)]
135#[serde(deny_unknown_fields)]
136pub struct NetworkManifest {
138 #[serde(default)]
140 pub name: Option<String>,
141 #[serde(default)]
143 #[serde(skip_serializing_if = "Vec::is_empty")]
144 pub schematics: Vec<SchematicManifest>,
145 #[serde(default)]
147 #[serde(skip_serializing_if = "Vec::is_empty")]
148 pub collections: Vec<CollectionDefinition>,
149}
150
151#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)]
152#[serde(deny_unknown_fields)]
153pub struct CollectionDefinition {
155 #[serde(default)]
157 #[serde(deserialize_with = "with_expand_envs")]
158 pub namespace: String,
159 #[serde(default)]
161 pub kind: CollectionKind,
162 #[serde(default)]
164 #[serde(deserialize_with = "with_expand_envs")]
165 pub reference: String,
166 #[serde(default)]
168 pub data: Option<HashMap<String, Value>>,
169}
170
171#[derive(Debug, Clone, Serialize, Deserialize, Copy, PartialEq)]
172#[serde(deny_unknown_fields)]
173pub enum CollectionKind {
175 Native = 0,
177 GrpcUrl = 1,
179 WaPC = 2,
181 Network = 4,
183}
184
185impl Default for CollectionKind {
186 fn default() -> Self {
187 Self::from_u16(0).unwrap()
188 }
189}
190
191impl FromPrimitive for CollectionKind {
192 fn from_i64(n: i64) -> Option<Self> {
193 Some(match n {
194 0 => Self::Native,
195 1 => Self::GrpcUrl,
196 2 => Self::WaPC,
197 4 => Self::Network,
198 _ => {
199 return None;
200 }
201 })
202 }
203
204 fn from_u64(n: u64) -> Option<Self> {
205 Some(match n {
206 0 => Self::Native,
207 1 => Self::GrpcUrl,
208 2 => Self::WaPC,
209 4 => Self::Network,
210 _ => {
211 return None;
212 }
213 })
214 }
215}
216
217#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)]
218#[serde(deny_unknown_fields)]
219pub struct SchematicManifest {
221 #[serde(deserialize_with = "with_expand_envs")]
223 pub name: String,
224 #[serde(default)]
226 #[serde(skip_serializing_if = "HashMap::is_empty")]
227 #[serde(deserialize_with = "map_component_def")]
228 pub instances: HashMap<String, ComponentDefinition>,
229 #[serde(default)]
231 #[serde(skip_serializing_if = "Vec::is_empty")]
232 #[serde(deserialize_with = "vec_connection")]
233 pub connections: Vec<ConnectionDefinition>,
234 #[serde(default)]
236 #[serde(skip_serializing_if = "HashMap::is_empty")]
237 pub constraints: HashMap<String, String>,
238}
239
240#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)]
241#[serde(deny_unknown_fields)]
242pub struct ComponentDefinition {
244 #[serde(deserialize_with = "with_expand_envs")]
246 pub id: String,
247 #[serde(default)]
249 pub data: Option<HashMap<String, Value>>,
250}
251
252#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)]
253#[serde(deny_unknown_fields)]
254pub struct ConnectionDefinition {
256 #[serde(default)]
258 #[serde(deserialize_with = "connection_target_shortform")]
259 pub from: ConnectionTargetDefinition,
260 #[serde(default)]
262 #[serde(deserialize_with = "connection_target_shortform")]
263 pub to: ConnectionTargetDefinition,
264}
265
266#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)]
267#[serde(deny_unknown_fields)]
268pub struct ConnectionTargetDefinition {
270 #[serde(deserialize_with = "with_expand_envs")]
272 pub instance: String,
273 #[serde(deserialize_with = "with_expand_envs")]
275 pub port: String,
276 #[serde(default)]
278 pub data: Option<HashMap<String, Value>>,
279}
280
281impl FromStr for ComponentDefinition {
282 type Err = crate::Error;
283
284 fn from_str(s: &str) -> Result<Self, Self::Err> {
285 Ok(Self {
286 id: s.to_owned(),
287 data: Default::default(),
288 })
289 }
290}
291
292impl FromStr for ConnectionDefinition {
293 type Err = crate::Error;
294
295 fn from_str(s: &str) -> Result<Self, Self::Err> {
296 crate::v0::parse::parse_connection(s)
297 }
298}
299
300impl FromStr for ConnectionTargetDefinition {
301 type Err = crate::Error;
302
303 fn from_str(s: &str) -> Result<Self, Self::Err> {
304 crate::v0::parse::parse_connection_target(s)
305 }
306}
307
308fn map_component_def<'de, D>(deserializer: D) -> Result<HashMap<String, ComponentDefinition>, D::Error>
309where
310 D: serde::Deserializer<'de>,
311{
312 struct ComponentDefinitionVisitor;
313 impl<'de> serde::de::Visitor<'de> for ComponentDefinitionVisitor {
314 type Value = HashMap<String, ComponentDefinition>;
315 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
316 write!(f, "a map of instances to their components")
317 }
318
319 fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
320 where
321 M: serde::de::MapAccess<'de>,
322 {
323 let mut map = HashMap::with_capacity(access.size_hint().unwrap_or(0));
324
325 while let Some((key, value)) = access.next_entry::<String, serde_value::Value>()? {
326 let result = match value {
327 serde_value::Value::String(s) => {
328 ComponentDefinition::from_str(&s).map_err(|e| serde::de::Error::custom(e.to_string()))?
329 }
330 serde_value::Value::Map(map) => {
331 ComponentDefinition::deserialize(serde_value::ValueDeserializer::new(serde_value::Value::Map(map)))?
332 }
333 _ => {
334 return Err(serde::de::Error::invalid_type(
335 serde::de::Unexpected::Other("other"),
336 &self,
337 ))
338 }
339 };
340
341 map.insert(key, result);
342 }
343
344 Ok(map)
345 }
346 }
347
348 deserializer.deserialize_map(ComponentDefinitionVisitor)
349}
350
351fn vec_connection<'de, D>(deserializer: D) -> Result<Vec<ConnectionDefinition>, D::Error>
352where
353 D: serde::Deserializer<'de>,
354{
355 struct ConnectionDefVisitor;
356 impl<'de> serde::de::Visitor<'de> for ConnectionDefVisitor {
357 type Value = Vec<ConnectionDefinition>;
358 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
359 write!(f, "a list of connections")
360 }
361
362 fn visit_seq<A: serde::de::SeqAccess<'de>>(self, mut seq: A) -> Result<Vec<ConnectionDefinition>, A::Error> {
363 let mut v = vec![];
364 while let Some(thing) = seq.next_element::<serde_value::Value>()? {
365 let result = match thing {
366 serde_value::Value::String(s) => {
367 ConnectionDefinition::from_str(&s).map_err(|e| serde::de::Error::custom(e.to_string()))?
368 }
369 serde_value::Value::Map(map) => {
370 ConnectionDefinition::deserialize(serde_value::ValueDeserializer::new(serde_value::Value::Map(map)))?
371 }
372 _ => {
373 return Err(serde::de::Error::invalid_type(
374 serde::de::Unexpected::Other("other"),
375 &self,
376 ))
377 }
378 };
379 v.push(result);
380 }
381 Ok(v)
382 }
383 }
384
385 deserializer.deserialize_seq(ConnectionDefVisitor)
386}
387
388fn connection_target_shortform<'de, D>(deserializer: D) -> Result<ConnectionTargetDefinition, D::Error>
389where
390 D: serde::Deserializer<'de>,
391{
392 struct ConnectionTargetVisitor;
393
394 impl<'de> serde::de::Visitor<'de> for ConnectionTargetVisitor {
395 type Value = ConnectionTargetDefinition;
396
397 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
398 formatter.write_str("a connection target definition")
399 }
400
401 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
402 where
403 E: serde::de::Error,
404 {
405 ConnectionTargetDefinition::from_str(s).map_err(|e| serde::de::Error::custom(e.to_string()))
406 }
407
408 fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
409 where
410 A: serde::de::MapAccess<'de>,
411 {
412 ConnectionTargetDefinition::deserialize(serde::de::value::MapAccessDeserializer::new(map))
413 }
414 }
415
416 deserializer.deserialize_any(ConnectionTargetVisitor)
417}