melodium_loader/
compo.rs

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}