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