Skip to main content

cargo_utils/
manifest.rs

1use anyhow::Context;
2
3use crate::DepTable;
4use std::str;
5
6/// A Cargo manifest
7#[derive(Debug, Clone)]
8pub struct Manifest {
9    /// Manifest contents as TOML data
10    pub data: toml_edit::DocumentMut,
11}
12
13impl Manifest {
14    /// Get all sections in the manifest that exist and might contain dependencies.
15    /// The returned items are always `Table` or `InlineTable`.
16    pub(crate) fn get_sections(&self) -> Vec<(DepTable, toml_edit::Item)> {
17        let mut sections = Vec::new();
18
19        for table in DepTable::KINDS {
20            let dependency_type = table.kind_table();
21            // Dependencies can be in the three standard sections...
22            if self
23                .data
24                .get(dependency_type)
25                .map(|t| t.is_table_like())
26                .unwrap_or(false)
27            {
28                sections.push((table.clone(), self.data[dependency_type].clone()));
29            }
30
31            // ... and in `target.<target>.(build-/dev-)dependencies`.
32            let target_sections = self
33                .data
34                .as_table()
35                .get("target")
36                .and_then(toml_edit::Item::as_table_like)
37                .into_iter()
38                .flat_map(toml_edit::TableLike::iter)
39                .filter_map(|(target_name, target_table)| {
40                    let dependency_table = target_table.get(dependency_type)?;
41                    dependency_table.as_table_like().map(|_| {
42                        (
43                            table.clone().set_target(target_name),
44                            dependency_table.clone(),
45                        )
46                    })
47                });
48
49            sections.extend(target_sections);
50        }
51
52        sections
53    }
54}
55
56impl str::FromStr for Manifest {
57    type Err = anyhow::Error;
58
59    /// Read manifest data from string
60    fn from_str(input: &str) -> ::std::result::Result<Self, Self::Err> {
61        let d: toml_edit::DocumentMut = input.parse().context("Manifest not valid TOML")?;
62
63        Ok(Self { data: d })
64    }
65}
66
67impl std::fmt::Display for Manifest {
68    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69        let s = self.data.to_string();
70        s.fmt(f)
71    }
72}