sdf_parser_core/config/
import.rs1use std::fmt;
2
3use schemars::JsonSchema;
4use serde::{
5 de::{Unexpected, Visitor},
6 Deserialize, Deserializer, Serialize,
7};
8use anyhow::Result;
9
10use super::Metadata;
11
12pub type PackageMetadata = Metadata;
13
14#[derive(Serialize, Deserialize, Debug, Clone, Default, JsonSchema)]
15pub struct PackageImport {
16 #[serde(rename = "pkg")]
17 pub package: ImportMetadata,
18 pub path: Option<String>,
19 #[serde(skip_serializing_if = "Vec::is_empty", default)]
20 pub types: Vec<TypeImport>,
21 #[serde(skip_serializing_if = "Vec::is_empty", default)]
22 pub states: Vec<StateImport>,
23 #[serde(skip_serializing_if = "Vec::is_empty", default)]
24 pub functions: Vec<FunctionImport>,
25}
26
27#[derive(Serialize, Debug, Clone, Default, PartialEq, Eq, JsonSchema)]
28pub struct ImportMetadata {
29 pub namespace: String,
30 pub name: String,
31 pub version: String,
32}
33
34impl<'de> Deserialize<'de> for ImportMetadata {
35 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
36 where
37 D: Deserializer<'de>,
38 {
39 deserializer.deserialize_str(PackageImportMetadataVisitor)
40 }
41}
42
43struct PackageImportMetadataVisitor;
44
45impl Visitor<'_> for PackageImportMetadataVisitor {
46 type Value = ImportMetadata;
47
48 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
49 write!(
50 formatter,
51 "a string of the form `<namespace>/<name>@<version>`"
52 )
53 }
54
55 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
56 where
57 E: serde::de::Error,
58 {
59 if s.is_empty() {
60 return Err(serde::de::Error::invalid_value(Unexpected::Str(s), &self));
61 }
62
63 let split = s.split('/').collect::<Vec<&str>>();
65 let namespace = split
66 .first()
67 .ok_or(serde::de::Error::invalid_value(Unexpected::Str(s), &self))?;
68 let rest = split
69 .get(1)
70 .ok_or(serde::de::Error::invalid_value(Unexpected::Str(s), &self))?;
71
72 if namespace.is_empty() || rest.is_empty() {
73 return Err(serde::de::Error::invalid_value(Unexpected::Str(s), &self));
74 }
75
76 let split = rest.split('@').collect::<Vec<&str>>();
77 let name = split
78 .first()
79 .ok_or(serde::de::Error::invalid_value(Unexpected::Str(s), &self))?;
80 let version = split
81 .get(1)
82 .ok_or(serde::de::Error::invalid_value(Unexpected::Str(s), &self))?;
83
84 if name.is_empty() || version.is_empty() {
85 return Err(serde::de::Error::invalid_value(Unexpected::Str(s), &self));
86 }
87
88 Ok(ImportMetadata {
89 namespace: namespace.to_string(),
90 name: name.to_string(),
91 version: version.to_string(),
92 })
93 }
94}
95
96#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)]
97pub struct FunctionImport {
98 pub name: String,
99 pub alias: Option<String>,
100}
101
102#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)]
103pub struct TypeImport {
104 pub name: String,
105}
106
107#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)]
108pub struct StateImport {
109 pub name: String,
110}
111
112#[cfg(test)]
113mod test {
114 use super::*;
115
116 #[test]
117 fn test_empty_name_does_not_parse() {
118 let yaml = "";
119
120 let result: Result<ImportMetadata, _> = serde_yaml::from_str(yaml);
121 assert!(result.is_err());
122 }
123
124 #[test]
125 fn test_name_without_forward_slash_does_not_parse() {
126 let yaml = "example-ns\\my-fn@0.0.0";
127
128 let result: Result<ImportMetadata, _> = serde_yaml::from_str(yaml);
129 let error = result.unwrap_err();
130
131 assert_eq!(
132 error.to_string(),
133 "invalid value: string \"example-ns\\\\my-fn@0.0.0\", expected a string of the form `<namespace>/<name>@<version>`"
134 )
135 }
136
137 #[test]
138 fn test_name_without_at_sign_does_not_parse() {
139 let yaml = "example-ns/my-fna0.0.0";
140
141 let result: Result<ImportMetadata, _> = serde_yaml::from_str(yaml);
142 let error = result.unwrap_err();
143
144 assert_eq!(
145 error.to_string(),
146 "invalid value: string \"example-ns/my-fna0.0.0\", expected a string of the form `<namespace>/<name>@<version>`"
147 )
148 }
149
150 #[test]
151 fn test_valid_name_parses() {
152 let yaml = "example-ns/my-fn@0.0.0";
153
154 let result: Result<ImportMetadata, _> = serde_yaml::from_str(yaml);
155 assert!(result.is_ok());
156 }
157}