1use super::*;
2
3#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default, Merge)]
5#[cfg_attr(feature = "schemars", derive(JsonSchema))]
6#[serde(default, rename_all = "kebab-case")]
7#[serde(deny_unknown_fields)]
8pub struct Workspace {
9 pub members: BTreeSet<String>,
11
12 #[serde(skip_serializing_if = "BTreeSet::is_empty")]
16 pub default_members: BTreeSet<String>,
17
18 #[serde(skip_serializing_if = "Option::is_none")]
20 #[merge(with = merge_options)]
21 pub package: Option<PackageTemplate>,
22
23 #[serde(skip_serializing_if = "BTreeSet::is_empty")]
25 pub exclude: BTreeSet<String>,
26
27 #[serde(skip_serializing_if = "BTreeMap::is_empty")]
29 pub metadata: BTreeMap<String, Value>,
30
31 #[serde(skip_serializing_if = "Option::is_none")]
33 pub resolver: Option<Resolver>,
34
35 #[serde(skip_serializing_if = "BTreeMap::is_empty")]
37 #[merge(with = merge_btree_maps)]
38 pub dependencies: BTreeMap<String, Dependency>,
39
40 #[serde(skip_serializing_if = "Option::is_none")]
42 pub lints: Option<Lints>,
43}
44
45impl AsTomlValue for Workspace {
46 fn as_toml_value(&self) -> Item {
47 let mut table = Table::new();
48
49 add_value!(self, table => resolver);
50
51 add_string_list!(self, table => members, default_members, exclude);
52
53 add_value!(self, table => package, lints);
54
55 if !self.metadata.is_empty() {
56 let mut metadata = Table::from_iter(self.metadata.iter().filter_map(|(k, v)| {
57 json_to_standard_table(v).map(|v| (toml_edit::Key::from(k), v))
58 }));
59
60 metadata.set_implicit(true);
61
62 table["metadata"] = metadata.into();
63 }
64
65 if !self.dependencies.is_empty() {
66 table["dependencies"] = Table::from_iter(
67 self.dependencies
68 .iter()
69 .map(|(name, dep)| (toml_edit::Key::from(name), dep.as_toml_value())),
70 )
71 .into();
72 }
73
74 table.into()
75 }
76}
77
78#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, Merge)]
80#[cfg_attr(feature = "schemars", derive(JsonSchema))]
81#[serde(default, deny_unknown_fields)]
82pub struct Lints {
83 #[serde(skip_serializing_if = "BTreeMap::is_empty")]
85 pub rust: BTreeMap<String, LintKind>,
86
87 #[serde(skip_serializing_if = "BTreeMap::is_empty")]
89 pub clippy: BTreeMap<String, LintKind>,
90}
91
92impl AsTomlValue for Lints {
93 fn as_toml_value(&self) -> Item {
94 let mut table = Table::new();
95
96 table.set_implicit(true);
97
98 add_table!(self, table => rust, clippy);
99
100 table.into()
101 }
102}
103
104#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
106#[cfg_attr(feature = "schemars", derive(JsonSchema))]
107#[serde(untagged)]
108pub enum LintKind {
109 Simple(LintLevel),
111 Detailed(Lint),
113}
114
115impl AsTomlValue for LintKind {
116 fn as_toml_value(&self) -> Item {
117 match self {
118 Self::Simple(lev) => lev.as_toml_value(),
119 Self::Detailed(det) => det.as_toml_value(),
120 }
121 }
122}
123
124#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default, Merge)]
126#[cfg_attr(feature = "schemars", derive(JsonSchema))]
127#[serde(default, rename_all = "kebab-case")]
128#[serde(deny_unknown_fields)]
129pub struct PackageTemplate {
130 #[serde(skip_serializing_if = "Vec::is_empty")]
132 pub authors: Vec<String>,
133
134 #[serde(skip_serializing_if = "BTreeSet::is_empty")]
136 pub categories: BTreeSet<String>,
137
138 #[serde(skip_serializing_if = "Option::is_none")]
140 pub description: Option<String>,
141
142 #[serde(skip_serializing_if = "Option::is_none")]
144 pub documentation: Option<String>,
145
146 #[serde(skip_serializing_if = "Option::is_none")]
148 pub edition: Option<Edition>,
149
150 #[serde(skip_serializing_if = "BTreeSet::is_empty")]
152 pub exclude: BTreeSet<String>,
153
154 #[serde(skip_serializing_if = "Option::is_none")]
156 pub homepage: Option<String>,
157
158 #[serde(skip_serializing_if = "BTreeSet::is_empty")]
160 pub include: BTreeSet<String>,
161
162 #[serde(skip_serializing_if = "BTreeSet::is_empty")]
164 pub keywords: BTreeSet<String>,
165
166 #[serde(skip_serializing_if = "Option::is_none")]
168 pub license: Option<String>,
169
170 #[serde(skip_serializing_if = "Option::is_none")]
172 pub license_file: Option<PathBuf>,
173
174 #[serde(skip_serializing_if = "Option::is_none")]
176 pub publish: Option<Publish>,
177
178 #[serde(skip_serializing_if = "Option::is_none")]
180 pub readme: Option<OptionalFile>,
181
182 #[serde(skip_serializing_if = "Option::is_none")]
184 pub repository: Option<String>,
185
186 #[serde(skip_serializing_if = "Option::is_none")]
188 pub rust_version: Option<String>,
189
190 #[serde(skip_serializing_if = "Option::is_none")]
192 pub version: Option<String>,
193}
194
195impl AsTomlValue for PackageTemplate {
196 fn as_toml_value(&self) -> Item {
197 let mut table = Table::new();
198
199 add_value!(self, table => publish, edition, readme);
200
201 add_string_list!(self, table => categories, exclude, include, keywords);
202
203 add_string!(self, table =>
204 description,
205 documentation,
206 homepage,
207 license,
208 repository,
209 rust_version,
210 version
211 );
212
213 if let Some(license_file) = &self.license_file {
214 table["license-file"] = license_file.to_string_lossy().to_string().into();
215 }
216
217 table.into()
218 }
219}