1use std::collections::BTreeMap;
2
3use serde::Deserialize;
4
5#[derive(Debug, Deserialize)]
6pub struct CargoToml {
7 pub dependencies: Option<BTreeMap<String, Dependency>>,
8}
9
10#[derive(Debug, Deserialize)]
11pub struct Dependency {
12 pub version: String,
13}
14
15impl CargoToml {
16 pub fn get_dependency(&self, name: &str) -> Option<&Dependency> {
17 self.dependencies.as_ref().and_then(|deps| deps.get(name))
18 }
19}
20
21pub fn parse_cargo_toml(toml: &str) -> Result<CargoToml, String> {
22 #[derive(Deserialize)]
23 struct CargoTomlVisitor {
24 dependencies: Option<BTreeMap<String, toml::Value>>,
25 }
26
27 let parsed = toml::from_str::<CargoTomlVisitor>(toml).map_err(|e| e.to_string())?;
28
29 let dependencies = parsed
30 .dependencies
31 .map(parse_dependencies)
32 .map_or(Ok(None), |v| v.map(Some))?;
33
34 Ok(CargoToml { dependencies })
35}
36
37fn parse_dependencies(
38 deps: BTreeMap<String, toml::Value>,
39) -> Result<BTreeMap<String, Dependency>, String> {
40 let mut dependencies = BTreeMap::new();
41 for (name, value) in deps {
42 if value.is_str() {
43 let version = value.as_str().unwrap();
44 dependencies.insert(
45 name,
46 Dependency {
47 version: version.to_string(),
48 },
49 );
50 } else if value.is_table() {
51 if let Some(version) = value.get("version") {
52 dependencies.insert(
53 name,
54 Dependency {
55 version: version
56 .as_str()
57 .ok_or("can't parse version as str".to_string())?
58 .to_string(),
59 },
60 );
61 } else if let Some(tag) = value.get("tag") {
62 dependencies.insert(
63 name,
64 Dependency {
65 version: tag
66 .as_str()
67 .ok_or("can't parse tag as str".to_string())?
68 .to_string(),
69 },
70 );
71 } else {
72 return Err("can't find version or path".to_string());
73 }
74 }
75 }
76 Ok(dependencies)
77}
78
79#[cfg(test)]
80mod test {
81 use super::*;
82 #[test]
83 fn test_parse_cargo_toml() {
84 let toml = r#"
85 [package]
86 name = "hello"
87 version = "0.1.0"
88 [dependencies]
89 serde = "1.0"
90 toml = { version = "0.5" }
91 hyle = { git = "https://github.com/Hyle-org/hyle", tag = "0.12" }
92 "#;
93 let cargo_toml = parse_cargo_toml(toml).unwrap();
94 assert_eq!(cargo_toml.dependencies.as_ref().unwrap().len(), 3);
95
96 assert_eq!(cargo_toml.get_dependency("serde").unwrap().version, "1.0");
97 assert_eq!(cargo_toml.get_dependency("toml").unwrap().version, "0.5");
98 assert_eq!(cargo_toml.get_dependency("hyle").unwrap().version, "0.12");
99 }
100}
101