cargo_deny/
root_cfg.rs

1use crate::{
2    Spanned, advisories::cfg::Config as AdvisoriesConfig, bans::cfg::Config as BansConfig,
3    licenses::cfg::Config as LicensesConfig, sources::cfg::Config as SourcesConfig,
4};
5use toml_span::{
6    DeserError, Deserialize,
7    de_helpers::TableHelper,
8    value::{Value, ValueInner},
9};
10
11pub struct Target {
12    pub filter: Spanned<krates::Target>,
13    pub features: Vec<String>,
14}
15
16impl<'de> Deserialize<'de> for Target {
17    fn deserialize(value: &mut Value<'de>) -> Result<Self, DeserError> {
18        let (triple, features) = match value.take() {
19            ValueInner::String(s) => (Spanned::with_span(s, value.span), Vec::new()),
20            ValueInner::Table(tab) => {
21                let mut th = TableHelper::from((tab, value.span));
22                let triple = th.required("triple")?;
23                let features = th.optional("features").unwrap_or_default();
24                th.finalize(None)?;
25
26                (triple, features)
27            }
28            other => {
29                return Err(toml_span::de_helpers::expected(
30                    "a string or table",
31                    other,
32                    value.span,
33                )
34                .into());
35            }
36        };
37
38        Ok(Self {
39            filter: triple.map(),
40            features,
41        })
42    }
43}
44
45#[derive(Default)]
46pub struct GraphConfig {
47    pub targets: Vec<Target>,
48    pub exclude: Vec<String>,
49    pub features: Vec<String>,
50    pub all_features: bool,
51    pub no_default_features: bool,
52    /// By default, dev dependencies for workspace crates are not ignored
53    pub exclude_dev: bool,
54    pub exclude_unpublished: bool,
55}
56
57impl<'de> Deserialize<'de> for GraphConfig {
58    fn deserialize(value: &mut Value<'de>) -> Result<Self, DeserError> {
59        let mut th = TableHelper::new(value)?;
60        let targets = th.optional("targets").unwrap_or_default();
61        let exclude = th.optional("exclude").unwrap_or_default();
62        let features = th.optional("features").unwrap_or_default();
63        let all_features = th.optional("all-features").unwrap_or_default();
64        let no_default_features = th.optional("no-default-features").unwrap_or_default();
65        let exclude_dev = th.optional("exclude-dev").unwrap_or_default();
66        let exclude_unpublished = th.optional("exclude-unpublished").unwrap_or_default();
67        th.finalize(None)?;
68
69        Ok(Self {
70            targets,
71            exclude,
72            features,
73            all_features,
74            no_default_features,
75            exclude_dev,
76            exclude_unpublished,
77        })
78    }
79}
80
81#[derive(Default)]
82pub struct OutputConfig {
83    pub feature_depth: Option<u32>,
84}
85
86impl<'de> Deserialize<'de> for OutputConfig {
87    fn deserialize(value: &mut Value<'de>) -> Result<Self, DeserError> {
88        let mut th = TableHelper::new(value)?;
89        let feature_depth = th.optional("feature-depth");
90        th.finalize(None)?;
91        Ok(Self { feature_depth })
92    }
93}
94
95pub struct RootConfig {
96    pub advisories: Option<AdvisoriesConfig>,
97    pub bans: Option<BansConfig>,
98    pub licenses: Option<LicensesConfig>,
99    pub sources: Option<SourcesConfig>,
100    pub graph: GraphConfig,
101    pub output: OutputConfig,
102    // Bit ugly but we keep track of usage of deprecated options until they
103    // are removed
104    pub graph_deprecated: Vec<crate::Span>,
105    pub output_deprecated: Option<crate::Span>,
106}
107
108impl<'de> Deserialize<'de> for RootConfig {
109    fn deserialize(value: &mut Value<'de>) -> Result<Self, DeserError> {
110        let mut th = TableHelper::new(value)?;
111
112        let advisories = th.optional("advisories");
113        let bans = th.optional("bans");
114        let licenses = th.optional("licenses");
115        let sources = th.optional("sources");
116
117        let mut graph: GraphConfig = th.optional("graph").unwrap_or_default();
118
119        fn deser<'de, T>(v: &mut Value<'de>, errors: &mut Vec<toml_span::Error>) -> T
120        where
121            T: Deserialize<'de> + Default,
122        {
123            match T::deserialize(v) {
124                Ok(v) => v,
125                Err(mut err) => {
126                    errors.append(&mut err.errors);
127                    T::default()
128                }
129            }
130        }
131
132        let graph_deprecated = {
133            let mut gd = Vec::new();
134
135            macro_rules! dep {
136                ($name:literal, $field:ident) => {
137                    if let Some((k, mut v)) = th.take($name) {
138                        gd.push(k.span);
139                        graph.$field = deser(&mut v, &mut th.errors);
140                    }
141                };
142            }
143
144            dep!("targets", targets);
145            dep!("exclude", exclude);
146            dep!("features", features);
147            dep!("all-features", all_features);
148            dep!("no-default-features", no_default_features);
149            dep!("exclude-dev", exclude_dev);
150
151            gd
152        };
153
154        let mut output: OutputConfig = th.optional("output").unwrap_or_default();
155        let output_deprecated = if let Some((key, mut v)) = th.take("feature-depth") {
156            output.feature_depth = Some(deser(&mut v, &mut th.errors));
157            Some(key.span)
158        } else {
159            None
160        };
161
162        th.finalize(None)?;
163
164        Ok(Self {
165            advisories,
166            bans,
167            licenses,
168            sources,
169            graph,
170            graph_deprecated,
171            output,
172            output_deprecated,
173        })
174    }
175}