1#![allow(unused)]
2
3use core::convert::TryFrom;
4use melodium_common::descriptor::{
5 Identifier, LoadingError, LoadingResult, PackageRequirement, Version, VersionReq,
6};
7use std::collections::HashMap;
8use toml::{Table, Value};
9
10#[derive(Debug)]
11pub struct Compo {
12 pub name: String,
13 pub version: Version,
14 pub requirements: Vec<PackageRequirement>,
15 pub entrypoints: HashMap<String, Identifier>,
16}
17
18impl Compo {
19 pub fn parse(composition: &str) -> LoadingResult<Self> {
20 let composition = match composition.parse::<Table>() {
21 Ok(table) => table,
22 Err(_) => {
23 return LoadingResult::new_failure(LoadingError::wrong_configuration(
24 178,
25 "[unreachable name]".to_string(),
26 ))
27 }
28 };
29
30 if let Some(Value::String(name)) = composition.get("name") {
31 let name = name.clone();
32 match Version::parse(
33 match match composition.get("version") {
34 Some(val) => val,
35 None => {
36 return LoadingResult::new_failure(LoadingError::wrong_configuration(
37 180, name,
38 ))
39 }
40 }
41 .as_str()
42 {
43 Some(val) => val,
44 None => {
45 return LoadingResult::new_failure(LoadingError::wrong_configuration(
46 181, name,
47 ))
48 }
49 },
50 ) {
51 Ok(version) => {
52 let requirements = if let Some(Value::Table(dependencies)) =
53 composition.get("dependencies")
54 {
55 let mut deps = Vec::new();
56 for (package_name, version_req) in dependencies {
57 if let Some(version_req) = version_req.as_str() {
58 if let Ok(version_req) = VersionReq::parse(version_req) {
59 deps.push(PackageRequirement {
60 package: package_name.clone(),
61 version_requirement: version_req,
62 })
63 } else {
64 return LoadingResult::new_failure(
65 LoadingError::wrong_configuration(
66 207,
67 package_name.clone(),
68 ),
69 );
70 }
71 } else {
72 return LoadingResult::new_failure(
73 LoadingError::wrong_configuration(206, package_name.clone()),
74 );
75 }
76 }
77 deps
78 } else {
79 Vec::new()
80 };
81
82 let mut entrypoints = HashMap::new();
83 if let Some(Value::Table(toml_entrypoints)) = composition.get("entrypoints") {
84 for (name, pos_id) in toml_entrypoints {
85 if let Value::String(pos_id) = pos_id {
86 if let Ok(pos_id) = Identifier::try_from(pos_id) {
87 entrypoints.insert(name.clone(), pos_id.with_version(&version));
88 } else {
89 return LoadingResult::new_failure(
90 LoadingError::wrong_configuration(242, name.clone()),
91 );
92 }
93 }
94 }
95 }
96
97 LoadingResult::new_success(Self {
98 name,
99 version,
100 requirements,
101 entrypoints,
102 })
103 }
104 Err(_) => {
105 return LoadingResult::new_failure(LoadingError::wrong_configuration(227, name))
106 }
107 }
108 } else {
109 return LoadingResult::new_failure(LoadingError::wrong_configuration(
110 179,
111 "[unreachable name]".to_string(),
112 ));
113 }
114 }
115
116 pub fn restitute(&self) -> String {
117 let mut toml = Table::new();
118
119 toml.insert("name".to_string(), Value::String(self.name.clone()));
120 toml.insert(
121 "version".to_string(),
122 Value::String(self.version.to_string()),
123 );
124 if !self.requirements.is_empty() {
125 let mut deps = Table::new();
126 for requirement in &self.requirements {
127 deps.insert(
128 requirement.package.clone(),
129 Value::String(requirement.version_requirement.to_string()),
130 );
131 }
132 toml.insert("dependencies".to_string(), Value::Table(deps));
133 }
134
135 if !self.entrypoints.is_empty() {
136 let mut entrypoints = Table::new();
137 for (name, id) in &self.entrypoints {
138 entrypoints.insert(name.clone(), Value::String(id.to_string()));
139 }
140 toml.insert("entrypoints".to_string(), Value::Table(entrypoints));
141 }
142
143 toml::to_string_pretty(&toml).unwrap()
144 }
145}