stackless_core/def/
parse.rs1use serde::Deserialize;
4
5use super::error::DefError;
6use super::model::StackDef;
7
8impl StackDef {
9 pub fn parse(text: &str) -> Result<Self, DefError> {
12 match toml::from_str::<Self>(text) {
13 Ok(def) => Ok(def),
14 Err(err) => Err(map_toml_error(err.to_string())),
15 }
16 }
17
18 pub fn parse_snapshot(text: &str) -> Result<Self, DefError> {
25 let mut value: toml::Value = match toml::from_str(text) {
26 Ok(value) => value,
27 Err(err) => return Err(map_toml_error(err.to_string())),
28 };
29 let legacy_datastores = value
30 .as_table()
31 .and_then(|table| table.get("datastores"))
32 .and_then(|section| section.as_table())
33 .map(|section| section.keys().cloned().collect())
34 .unwrap_or_default();
35 if let Some(table) = value.as_table_mut() {
36 table.remove("datastores");
37 }
38 match StackDef::deserialize(value) {
39 Ok(mut def) => {
40 def.legacy_datastores = legacy_datastores;
41 Ok(def)
42 }
43 Err(err) => Err(map_toml_error(err.to_string())),
44 }
45 }
46}
47
48fn map_toml_error(message: String) -> DefError {
49 if let Some(name) = dns_name_parse_failure(&message) {
53 return DefError::NameInvalid {
54 kind: "stack",
55 name,
56 };
57 }
58 if message.contains("unknown field")
63 || message.contains("missing field")
64 || message.contains("invalid type")
65 || message.contains("unknown variant")
66 || message.contains("duplicate field")
67 {
68 DefError::Schema { message }
69 } else {
70 DefError::Syntax { message }
71 }
72}
73
74fn dns_name_parse_failure(message: &str) -> Option<String> {
75 let rest = message.split("invalid DNS name ").nth(1)?;
77 let name = rest.strip_prefix('"')?.split('"').next()?;
78 Some(name.to_owned())
79}