citeworks_cff/
cff.rs

1use semver::Version;
2use serde::{Deserialize, Serialize};
3use url::Url;
4
5use crate::{
6	date::Date, identifiers::Identifier, license::License, names::Name, references::Reference,
7};
8
9/// The top-level CFF document.
10///
11/// This contains the citation metadata for a project, and may also contain
12/// reference information (the project's bibligraphy).
13#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
14#[serde(rename_all = "kebab-case")]
15pub struct Cff {
16	/// Version of the CFF specification this document conforms to.
17	///
18	/// This is required and must be non-empty.
19	pub cff_version: Version,
20
21	/// What to do with the citation metadata, in a human-readable message.
22	///
23	/// This is required and must be non-empty.
24	///
25	/// # Examples
26	///
27	/// - "If you use this software, please cite it using the metadata from this file."
28	/// - "Please cite this software using these metadata."
29	/// - "Please cite this software using the metadata from 'preferred-citation'."
30	/// - "If you use this dataset, please cite it using the metadata from this file."
31	/// - "Please cite this dataset using these metadata."
32	/// - "Please cite this dataset using the metadata from 'preferred-citation'."
33	pub message: String,
34
35	/// The name of the work.
36	///
37	/// This is required and must be non-empty.
38	pub title: String,
39
40	/// The type of the work.
41	#[serde(default, skip_serializing_if = "Option::is_none", rename = "type")]
42	pub work_type: Option<WorkType>,
43
44	/// Version of the work.
45	///
46	/// There is no requirement that this be semver.
47	#[serde(default, skip_serializing_if = "Option::is_none")]
48	pub version: Option<String>,
49
50	/// The commit hash or revision number of the software version.
51	///
52	/// By convention:
53	/// - if this is a Git hash, it should be bare lowercase hex, e.g.
54	///   `1ff847d81f29c45a3a1a5ce73d38e45c2f319bba`;
55	/// - if this is a decimal revision or build number, it should be preceded
56	///   by a label, e.g. `Revision: 8612`.
57	#[serde(default, skip_serializing_if = "Option::is_none")]
58	pub commit: Option<String>,
59
60	/// The date the work has been released.
61	#[serde(default, skip_serializing_if = "Option::is_none")]
62	pub date_released: Option<Date>,
63
64	/// A description of the work.
65	#[serde(default, skip_serializing_if = "Option::is_none", rename = "abstract")]
66	pub abstract_text: Option<String>,
67
68	/// Keywords that describe the work.
69	#[serde(default, skip_serializing_if = "Vec::is_empty")]
70	pub keywords: Vec<String>,
71
72	/// The URL of a landing page/website for the software or dataset.
73	#[serde(default, skip_serializing_if = "Option::is_none")]
74	pub url: Option<Url>,
75
76	/// The URL of the work in a repository/archive.
77	///
78	/// This is to be used when the repository is neither a source code
79	/// repository nor a build artifact repository. For source code, use the
80	/// `repository_code` field; for binary releases or other built forms, use
81	/// the `repository_artifact` field.
82	#[serde(default, skip_serializing_if = "Option::is_none")]
83	pub repository: Option<Url>,
84
85	/// The URL of the work in a build artifact/binary repository.
86	#[serde(default, skip_serializing_if = "Option::is_none")]
87	pub repository_artifact: Option<Url>,
88
89	/// The URL of the work in a source code repository.
90	#[serde(default, skip_serializing_if = "Option::is_none")]
91	pub repository_code: Option<Url>,
92
93	/// [SPDX][spdx] license expression(s).
94	#[serde(default, skip_serializing_if = "Option::is_none")]
95	pub license: Option<License>,
96
97	/// The URL of the license text under which the work is licensed.
98	///
99	/// This should only be used for non-standard licenses not included in the
100	/// SPDX License List.
101	#[serde(default, skip_serializing_if = "Option::is_none")]
102	pub license_url: Option<Url>,
103
104	/// The authors of the work.
105	///
106	/// This is required and must contain at least one author.
107	pub authors: Vec<Name>,
108
109	/// The contact person, group, company, etc. for the work.
110	#[serde(default, skip_serializing_if = "Vec::is_empty")]
111	pub contact: Vec<Name>,
112
113	/// The DOI for the work.
114	///
115	/// Use this if the work has a single DOI. Otherwise, use the `identifiers`
116	/// field.
117	///
118	/// Note that the DOI is not parsed or validated in any way.
119	#[serde(default, skip_serializing_if = "Option::is_none")]
120	pub doi: Option<String>,
121
122	/// The identifiers for the work.
123	#[serde(default, skip_serializing_if = "Vec::is_empty")]
124	pub identifiers: Vec<Identifier>,
125
126	/// A reference to another work that should be cited instead of the work.
127	///
128	/// Note that the principles of [software citation] and [data citation]
129	/// require that software should be cited on the same basis as any other
130	/// research product such as a paper or a book. Adding a different preferred
131	/// citation may result in a violation of the respective primary principle,
132	/// "Importance", when others cite this work.
133	///
134	/// [software citation]: https://doi.org/10.7717/peerj-cs.86
135	/// [data citation]: https://doi.org/10.25490/a97f-egyk
136	#[serde(default, skip_serializing_if = "Option::is_none")]
137	pub preferred_citation: Option<Reference>,
138
139	/// Reference(s) to other creative works.
140	///
141	/// Similar to a list of references in a paper, references of the software
142	/// or dataset may include other software (dependencies), or other research
143	/// products that the software or dataset builds on, but not work describing
144	/// the software or dataset.
145	#[serde(default, skip_serializing_if = "Vec::is_empty")]
146	pub references: Vec<Reference>,
147}
148
149impl Default for Cff {
150	fn default() -> Self {
151		Self {
152			cff_version: Version::new(1, 2, 0),
153			message: String::from("Please cite this software using these metadata."),
154			title: Default::default(),
155			work_type: Default::default(),
156			version: Default::default(),
157			commit: Default::default(),
158			date_released: Default::default(),
159			abstract_text: Default::default(),
160			keywords: Default::default(),
161			url: Default::default(),
162			repository: Default::default(),
163			repository_artifact: Default::default(),
164			repository_code: Default::default(),
165			license: Default::default(),
166			license_url: Default::default(),
167			authors: Default::default(),
168			contact: Default::default(),
169			doi: Default::default(),
170			identifiers: Default::default(),
171			preferred_citation: Default::default(),
172			references: Default::default(),
173		}
174	}
175}
176
177/// Types of works recognised by CFF.
178#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Serialize, Deserialize)]
179#[serde(rename_all = "kebab-case")]
180pub enum WorkType {
181	/// A software project.
182	Software,
183
184	/// A dataset.
185	Dataset,
186}