1 // SPDX-FileCopyrightText: 2020-2021 HH Partners
3 // SPDX-License-Identifier: MIT
5 use serde
::{Deserialize, Serialize}
;
6 use spdx_expression
::{SimpleExpression, SpdxExpression}
;
8 use super::{Algorithm, Checksum}
;
10 /// ## File Information
12 /// SPDX's [File Information](https://spdx.github.io/spdx-spec/4-file-information/)
13 #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
14 #[serde(rename_all = "camelCase")]
15 pub struct FileInformation
{
16 /// <https://spdx.github.io/spdx-spec/4-file-information/#41-file-name>
17 pub file_name
: String
,
19 /// <https://spdx.github.io/spdx-spec/4-file-information/#42-file-spdx-identifier>
20 #[serde(rename = "SPDXID")]
21 pub file_spdx_identifier
: String
,
23 /// <https://spdx.github.io/spdx-spec/4-file-information/#43-file-type>
24 #[serde(rename = "fileTypes", skip_serializing_if = "Vec::is_empty", default)]
25 pub file_type
: Vec
<FileType
>,
27 /// <https://spdx.github.io/spdx-spec/4-file-information/#44-file-checksum>
28 #[serde(rename = "checksums")]
29 pub file_checksum
: Vec
<Checksum
>,
31 /// <https://spdx.github.io/spdx-spec/4-file-information/#45-concluded-license>
32 #[serde(rename = "licenseConcluded")]
33 pub concluded_license
: SpdxExpression
,
35 /// <https://spdx.github.io/spdx-spec/4-file-information/#46-license-information-in-file>
36 #[serde(rename = "licenseInfoInFiles")]
37 pub license_information_in_file
: Vec
<SimpleExpression
>,
39 /// <https://spdx.github.io/spdx-spec/4-file-information/#47-comments-on-license>
41 rename
= "licenseComments",
42 skip_serializing_if
= "Option::is_none",
45 pub comments_on_license
: Option
<String
>,
47 /// <https://spdx.github.io/spdx-spec/4-file-information/#48-copyright-text>
48 pub copyright_text
: String
,
50 /// <https://spdx.github.io/spdx-spec/4-file-information/#412-file-comment>
51 #[serde(rename = "comment", skip_serializing_if = "Option::is_none", default)]
52 pub file_comment
: Option
<String
>,
54 /// <https://spdx.github.io/spdx-spec/4-file-information/#413-file-notice>
56 rename
= "noticeText",
57 skip_serializing_if
= "Option::is_none",
60 pub file_notice
: Option
<String
>,
62 /// <https://spdx.github.io/spdx-spec/4-file-information/#414-file-contributor>
64 rename
= "fileContributors",
65 skip_serializing_if
= "Vec::is_empty",
68 pub file_contributor
: Vec
<String
>,
70 /// <https://spdx.github.io/spdx-spec/4-file-information/#415-file-attribution-text>
71 #[serde(skip_serializing_if = "Option::is_none", default)]
72 pub file_attribution_text
: Option
<Vec
<String
>>,
73 // TODO: Snippet Information.
76 impl Default
for FileInformation
{
77 fn default() -> Self {
79 file_name
: "NOASSERTION".to_string(),
80 file_spdx_identifier
: "NOASSERTION".to_string(),
81 file_type
: Vec
::new(),
82 file_checksum
: Vec
::new(),
83 concluded_license
: SpdxExpression
::parse("NOASSERTION").expect("will always succeed"),
84 license_information_in_file
: Vec
::new(),
85 comments_on_license
: None
,
86 copyright_text
: "NOASSERTION".to_string(),
89 file_contributor
: Vec
::new(),
90 file_attribution_text
: None
,
95 impl FileInformation
{
97 pub fn new(name
: &str, id
: &mut i32) -> Self {
100 file_name
: name
.to_string(),
101 file_spdx_identifier
: format
!("SPDXRef-{}", id
),
106 /// Check if hash equals.
107 pub fn equal_by_hash(&self, algorithm
: Algorithm
, value
: &str) -> bool
{
111 .find(|&checksum
| checksum
.algorithm
== algorithm
);
113 checksum
.map_or(false, |checksum
| {
114 checksum
.value
.to_ascii_lowercase() == value
.to_ascii_lowercase()
119 pub fn checksum(&self, algorithm
: Algorithm
) -> Option
<&str> {
123 .find(|&checksum
| checksum
.algorithm
== algorithm
);
125 checksum
.map(|checksum
| checksum
.value
.as_str())
129 /// <https://spdx.github.io/spdx-spec/4-file-information/#43-file-type>
130 #[derive(Debug, Serialize, Deserialize, PartialEq, PartialOrd, Clone, Copy)]
131 #[serde(rename_all = "UPPERCASE")]
148 use std
::fs
::read_to_string
;
151 use crate::models
::{Checksum, FileType, SPDX}
;
154 fn checksum_equality() {
156 let mut file_sha256
= FileInformation
::new("sha256", &mut id
);
159 .push(Checksum
::new(Algorithm
::SHA256
, "test"));
161 assert
!(file_sha256
.equal_by_hash(Algorithm
::SHA256
, "test"));
162 assert
!(!file_sha256
.equal_by_hash(Algorithm
::SHA256
, "no_test"));
164 let mut file_md5
= FileInformation
::new("md5", &mut id
);
167 .push(Checksum
::new(Algorithm
::MD5
, "test"));
168 assert
!(file_md5
.equal_by_hash(Algorithm
::MD5
, "test"));
169 assert
!(!file_md5
.equal_by_hash(Algorithm
::MD5
, "no_test"));
170 assert
!(!file_md5
.equal_by_hash(Algorithm
::SHA1
, "test"));
176 let mut file_sha256
= FileInformation
::new("sha256", &mut id
);
179 .push(Checksum
::new(Algorithm
::SHA256
, "test"));
181 assert_eq
!(file_sha256
.checksum(Algorithm
::SHA256
), Some("test"));
182 assert_eq
!(file_sha256
.checksum(Algorithm
::MD2
), None
);
184 let mut file_md5
= FileInformation
::new("md5", &mut id
);
187 .push(Checksum
::new(Algorithm
::MD5
, "test"));
189 assert_eq
!(file_md5
.checksum(Algorithm
::MD5
), Some("test"));
194 let spdx
: SPDX
= serde_json
::from_str(
195 &read_to_string("tests/data/SPDXJSONExample-v2.2.spdx.json").unwrap(),
199 spdx
.file_information
[0].file_name
,
200 "./src/org/spdx/parser/DOAPProject.java"
204 fn file_spdx_identifier() {
205 let spdx
: SPDX
= serde_json
::from_str(
206 &read_to_string("tests/data/SPDXJSONExample-v2.2.spdx.json").unwrap(),
210 spdx
.file_information
[0].file_spdx_identifier
,
216 let spdx
: SPDX
= serde_json
::from_str(
217 &read_to_string("tests/data/SPDXJSONExample-v2.2.spdx.json").unwrap(),
220 assert_eq
!(spdx
.file_information
[0].file_type
, vec
![FileType
::Source
]);
224 let spdx
: SPDX
= serde_json
::from_str(
225 &read_to_string("tests/data/SPDXJSONExample-v2.2.spdx.json").unwrap(),
229 spdx
.file_information
[0].file_checksum
,
231 algorithm
: Algorithm
::SHA1
,
232 value
: "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12".to_string()
237 fn concluded_license() {
238 let spdx
: SPDX
= serde_json
::from_str(
239 &read_to_string("tests/data/SPDXJSONExample-v2.2.spdx.json").unwrap(),
243 spdx
.file_information
[0].concluded_license
,
244 SpdxExpression
::parse("Apache-2.0").unwrap()
248 fn license_information_in_file() {
249 let spdx
: SPDX
= serde_json
::from_str(
250 &read_to_string("tests/data/SPDXJSONExample-v2.2.spdx.json").unwrap(),
254 spdx
.file_information
[0].license_information_in_file
,
255 vec
![SimpleExpression
::parse("Apache-2.0").unwrap()]
259 fn comments_on_license() {
260 let spdx
: SPDX
= serde_json
::from_str(
261 &read_to_string("tests/data/SPDXJSONExample-v2.2.spdx.json").unwrap(),
265 spdx
.file_information
[2].comments_on_license
,
266 Some("This license is used by Jena".to_string())
270 fn copyright_text() {
271 let spdx
: SPDX
= serde_json
::from_str(
272 &read_to_string("tests/data/SPDXJSONExample-v2.2.spdx.json").unwrap(),
276 spdx
.file_information
[0].copyright_text
,
277 "Copyright 2010, 2011 Source Auditor Inc.".to_string()
282 let spdx
: SPDX
= serde_json
::from_str(
283 &read_to_string("tests/data/SPDXJSONExample-v2.2.spdx.json").unwrap(),
287 spdx
.file_information
[1].file_comment
,
288 Some("This file is used by Jena".to_string())
293 let spdx
: SPDX
= serde_json
::from_str(
294 &read_to_string("tests/data/SPDXJSONExample-v2.2.spdx.json").unwrap(),
298 spdx
.file_information
[1].file_notice
,
299 Some("Apache Commons Lang\nCopyright 2001-2011 The Apache Software Foundation\n\nThis product includes software developed by\nThe Apache Software Foundation (http://www.apache.org/).\n\nThis product includes software from the Spring Framework,\nunder the Apache License 2.0 (see: StringUtils.containsWhitespace())".to_string())
303 fn file_contributor() {
304 let spdx
: SPDX
= serde_json
::from_str(
305 &read_to_string("tests/data/SPDXJSONExample-v2.2.spdx.json").unwrap(),
309 spdx
.file_information
[1].file_contributor
,
310 vec
!["Apache Software Foundation".to_string()]