Skip to main content

cargo_toml_parser/
lib.rs

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            }
72        }
73    }
74    Ok(dependencies)
75}
76
77#[cfg(test)]
78mod test {
79    use super::*;
80    #[test]
81    fn test_parse_cargo_toml() {
82        let toml = r#"
83            [package]
84            name = "hello"
85            version = "0.1.0"
86            [dependencies]
87            serde = "1.0"
88            toml = { version = "0.5" }
89            hyle = { git = "https://github.com/Hyle-org/hyle", tag = "0.12" }
90            "#;
91        let cargo_toml = parse_cargo_toml(toml).unwrap();
92        assert_eq!(cargo_toml.dependencies.as_ref().unwrap().len(), 3);
93
94        assert_eq!(cargo_toml.get_dependency("serde").unwrap().version, "1.0");
95        assert_eq!(cargo_toml.get_dependency("toml").unwrap().version, "0.5");
96        assert_eq!(cargo_toml.get_dependency("hyle").unwrap().version, "0.12");
97    }
98}
99