Skip to main content

rust_manifest/
package.rs

1use super::*;
2
3/// The `[package]` section of the [`Manifest`]. This is where crate properties are.
4#[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	/// The name of the crate.
10	#[serde(skip_serializing_if = "Option::is_none")]
11	pub name: Option<String>,
12
13	/// Deprecated
14	#[serde(skip_serializing_if = "Vec::is_empty")]
15	pub authors: Vec<String>,
16
17	/// Must parse as semver, e.g. "1.9.0"
18	#[serde(skip_serializing_if = "Option::is_none")]
19	pub version: Option<Inheritable<String>>,
20
21	/// Package's edition opt-in.
22	#[serde(skip_serializing_if = "Option::is_none")]
23	pub edition: Option<Inheritable<Edition>>,
24
25	/// MSRV 1.x (beware: does not require semver formatting)
26	#[serde(skip_serializing_if = "Option::is_none")]
27	pub rust_version: Option<Inheritable<String>>,
28
29	/// Build script definition.
30	#[serde(skip_serializing_if = "Option::is_none")]
31	pub build: Option<OptionalFile>,
32
33	/// Workspace this package is a member of (`None` if it's implicit).
34	#[serde(skip_serializing_if = "Option::is_none")]
35	pub workspace: Option<PathBuf>,
36
37	/// Name of the native library the package links with.
38	#[serde(skip_serializing_if = "Option::is_none")]
39	pub links: Option<String>,
40
41	/// A short blurb about the package. This is not rendered in any format when
42	/// uploaded to crates.io (aka this is not markdown).
43	#[serde(skip_serializing_if = "Option::is_none")]
44	pub description: Option<Inheritable<String>>,
45
46	/// Project's homepage.
47	#[serde(skip_serializing_if = "Option::is_none")]
48	pub homepage: Option<Inheritable<String>>,
49
50	/// Path to your custom docs. Unnecessary if you rely on docs.rs.
51	#[serde(skip_serializing_if = "Option::is_none")]
52	pub documentation: Option<Inheritable<String>>,
53
54	/// This points to a file under the package root (relative to this `Cargo.toml`).
55	/// implied if README.md, README.txt or README exists.
56	#[serde(skip_serializing_if = "Option::is_none")]
57	pub readme: Option<Inheritable<OptionalFile>>,
58
59	/// Up to 5, for search.
60	#[serde(skip_serializing_if = "Inheritable::is_default")]
61	pub keywords: Inheritable<BTreeSet<String>>,
62
63	/// This is a list of up to five categories where this crate would fit.
64	#[serde(skip_serializing_if = "Inheritable::is_default")]
65	pub categories: Inheritable<BTreeSet<String>>,
66
67	/// Don't publish these files
68	#[serde(skip_serializing_if = "Inheritable::is_default")]
69	pub exclude: Inheritable<BTreeSet<String>>,
70
71	/// Publish these files
72	#[serde(skip_serializing_if = "Inheritable::is_default")]
73	pub include: Inheritable<BTreeSet<String>>,
74
75	/// e.g. "MIT"
76	#[serde(skip_serializing_if = "Option::is_none")]
77	pub license: Option<Inheritable<String>>,
78
79	/// If `license` is not standard
80	#[serde(skip_serializing_if = "Option::is_none")]
81	pub license_file: Option<Inheritable<PathBuf>>,
82
83	/// (HTTPS) URL to crate's repository
84	#[serde(skip_serializing_if = "Option::is_none")]
85	pub repository: Option<Inheritable<String>>,
86
87	/// The default binary to run by cargo run.
88	#[serde(skip_serializing_if = "Option::is_none")]
89	pub default_run: Option<String>,
90
91	/// Discover binaries from the file system
92	#[serde(skip_serializing_if = "Option::is_none")]
93	pub autobins: Option<bool>,
94
95	/// Discover libraries from the file system
96	#[serde(skip_serializing_if = "Option::is_none")]
97	pub autolib: Option<bool>,
98
99	/// Discover examples from the file system
100	#[serde(skip_serializing_if = "Option::is_none")]
101	pub autoexamples: Option<bool>,
102
103	/// Discover tests from the file system
104	#[serde(skip_serializing_if = "Option::is_none")]
105	pub autotests: Option<bool>,
106
107	/// Discover benchmarks from the file system
108	#[serde(skip_serializing_if = "Option::is_none")]
109	pub autobenches: Option<bool>,
110
111	/// Disable publishing or select custom registries.
112	#[serde(skip_serializing_if = "Option::is_none")]
113	pub publish: Option<Inheritable<Publish>>,
114
115	/// The feature resolver version.
116	#[serde(skip_serializing_if = "Option::is_none")]
117	pub resolver: Option<Resolver>,
118
119	/// Arbitrary metadata of any type, an extension point for 3rd party tools.
120	#[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}