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 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 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}