1use super::*;
2
3#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Merge, Default)]
5#[cfg_attr(feature = "schemars", derive(JsonSchema))]
6#[serde(default, rename_all = "kebab-case")]
7#[serde(deny_unknown_fields)]
8pub struct Package {
9 #[serde(skip_serializing_if = "Option::is_none")]
11 pub name: Option<String>,
12
13 #[serde(skip_serializing_if = "Vec::is_empty")]
15 pub authors: Vec<String>,
16
17 #[serde(skip_serializing_if = "Option::is_none")]
19 pub version: Option<Inheritable<String>>,
20
21 #[serde(skip_serializing_if = "Option::is_none")]
23 pub edition: Option<Inheritable<Edition>>,
24
25 #[serde(skip_serializing_if = "Option::is_none")]
27 pub rust_version: Option<Inheritable<String>>,
28
29 #[serde(skip_serializing_if = "Option::is_none")]
31 pub build: Option<OptionalFile>,
32
33 #[serde(skip_serializing_if = "Option::is_none")]
35 pub workspace: Option<PathBuf>,
36
37 #[serde(skip_serializing_if = "Option::is_none")]
39 pub links: Option<String>,
40
41 #[serde(skip_serializing_if = "Option::is_none")]
44 pub description: Option<Inheritable<String>>,
45
46 #[serde(skip_serializing_if = "Option::is_none")]
48 pub homepage: Option<Inheritable<String>>,
49
50 #[serde(skip_serializing_if = "Option::is_none")]
52 pub documentation: Option<Inheritable<String>>,
53
54 #[serde(skip_serializing_if = "Option::is_none")]
57 pub readme: Option<Inheritable<OptionalFile>>,
58
59 #[serde(skip_serializing_if = "Inheritable::is_default")]
61 pub keywords: Inheritable<BTreeSet<String>>,
62
63 #[serde(skip_serializing_if = "Inheritable::is_default")]
65 pub categories: Inheritable<BTreeSet<String>>,
66
67 #[serde(skip_serializing_if = "Inheritable::is_default")]
69 pub exclude: Inheritable<BTreeSet<String>>,
70
71 #[serde(skip_serializing_if = "Inheritable::is_default")]
73 pub include: Inheritable<BTreeSet<String>>,
74
75 #[serde(skip_serializing_if = "Option::is_none")]
77 pub license: Option<Inheritable<String>>,
78
79 #[serde(skip_serializing_if = "Option::is_none")]
81 pub license_file: Option<Inheritable<PathBuf>>,
82
83 #[serde(skip_serializing_if = "Option::is_none")]
85 pub repository: Option<Inheritable<String>>,
86
87 #[serde(skip_serializing_if = "Option::is_none")]
89 pub default_run: Option<String>,
90
91 #[serde(skip_serializing_if = "Option::is_none")]
93 pub autobins: Option<bool>,
94
95 #[serde(skip_serializing_if = "Option::is_none")]
97 pub autolib: Option<bool>,
98
99 #[serde(skip_serializing_if = "Option::is_none")]
101 pub autoexamples: Option<bool>,
102
103 #[serde(skip_serializing_if = "Option::is_none")]
105 pub autotests: Option<bool>,
106
107 #[serde(skip_serializing_if = "Option::is_none")]
109 pub autobenches: Option<bool>,
110
111 #[serde(skip_serializing_if = "Option::is_none")]
113 pub publish: Option<Inheritable<Publish>>,
114
115 #[serde(skip_serializing_if = "Option::is_none")]
117 pub resolver: Option<Resolver>,
118
119 #[serde(skip_serializing_if = "BTreeMap::is_empty")]
121 pub metadata: BTreeMap<String, Value>,
122}
123
124impl AsTomlValue for Package {
125 fn as_toml_value(&self) -> Item {
126 let mut table = Table::new();
127
128 add_string!(self, table => name, links);
129
130 add_value!(self, table => version, edition, rust_version, build, description, homepage, documentation, readme, license, repository, default_run, publish, resolver);
131
132 if let Some(license_file) = &self.license_file {
133 table["license-file"] = match license_file {
134 Inheritable::Workspace { workspace } => {
135 InlineTable::from_iter([("workspace", *workspace)]).into()
136 }
137 Inheritable::Value(path) => path.to_string_lossy().as_ref().into(),
138 };
139 }
140
141 macro_rules! add_set {
142 ($($names:ident),*) => {
143 $(
144 if !self.$names.is_default() {
145 table[stringify!($names)] = match &self.$names {
146 Inheritable::Workspace { workspace } => {
147 InlineTable::from_iter([("workspace", *workspace)]).into()
148 }
149 Inheritable::Value(set) => {
150 let mut array = Array::from_iter(set);
151 format_array(&mut array);
152
153 array.into()
154 }
155 }
156 }
157 )*
158 };
159 }
160
161 add_set!(categories, keywords, exclude, include);
162
163 if let Some(path) = &self.workspace {
164 table["workspace"] = path.to_string_lossy().as_ref().into();
165 }
166
167 add_if_false!(self, table => autobins, autolib, autoexamples, autotests, autobenches);
168
169 if !self.metadata.is_empty() {
170 let mut metadata = Table::from_iter(self.metadata.iter().filter_map(|(k, v)| {
171 json_to_standard_table(v).map(|v| (toml_edit::Key::from(k), v))
172 }));
173
174 metadata.set_implicit(true);
175
176 table["metadata"] = metadata.into();
177 }
178
179 table.into()
180 }
181}