spdx_rs/models/
annotation.rs

1// SPDX-FileCopyrightText: 2020-2021 HH Partners
2//
3// SPDX-License-Identifier: MIT
4
5use chrono::{DateTime, Utc};
6use serde::{Deserialize, Serialize};
7
8/// <https://spdx.github.io/spdx-spec/8-annotations/>
9#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
10#[serde(rename_all = "camelCase")]
11pub struct Annotation {
12    /// <https://spdx.github.io/spdx-spec/8-annotations/#81-annotator>
13    pub annotator: String,
14
15    /// <https://spdx.github.io/spdx-spec/8-annotations/#82-annotation-date>
16    pub annotation_date: DateTime<Utc>,
17
18    /// <https://spdx.github.io/spdx-spec/8-annotations/#83-annotation-type>
19    pub annotation_type: AnnotationType,
20
21    /// <https://spdx.github.io/spdx-spec/8-annotations/#84-spdx-identifier-reference>
22    // TODO: According to the spec this is mandatory, but the example file doesn't
23    // have it.
24    pub spdx_identifier_reference: Option<String>,
25
26    /// <https://spdx.github.io/spdx-spec/8-annotations/#85-annotation-comment>
27    #[serde(rename = "comment")]
28    pub annotation_comment: String,
29}
30
31impl Annotation {
32    pub fn new(
33        annotator: String,
34        annotation_date: DateTime<Utc>,
35        annotation_type: AnnotationType,
36        spdx_identifier_reference: Option<String>,
37        annotation_comment: String,
38    ) -> Self {
39        Self {
40            annotator,
41            annotation_date,
42            annotation_type,
43            spdx_identifier_reference,
44            annotation_comment,
45        }
46    }
47}
48
49/// <https://spdx.github.io/spdx-spec/8-annotations/#83-annotation-type>
50#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy)]
51#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
52pub enum AnnotationType {
53    Review,
54    Other,
55}
56
57#[cfg(test)]
58mod test {
59    use std::fs::read_to_string;
60
61    use chrono::TimeZone;
62
63    use crate::models::SPDX;
64
65    use super::*;
66
67    #[test]
68    fn annotator() {
69        let spdx_file: SPDX = serde_json::from_str(
70            &read_to_string("tests/data/SPDXJSONExample-v2.2.spdx.json").unwrap(),
71        )
72        .unwrap();
73        assert_eq!(
74            spdx_file.annotations[0].annotator,
75            "Person: Jane Doe ()".to_string()
76        );
77    }
78
79    #[test]
80    fn annotation_date() {
81        let spdx_file: SPDX = serde_json::from_str(
82            &read_to_string("tests/data/SPDXJSONExample-v2.2.spdx.json").unwrap(),
83        )
84        .unwrap();
85        assert_eq!(
86            spdx_file.annotations[0].annotation_date,
87            Utc.with_ymd_and_hms(2010, 1, 29, 18, 30, 22).unwrap()
88        );
89    }
90
91    #[test]
92    fn annotation_type() {
93        let spdx_file: SPDX = serde_json::from_str(
94            &read_to_string("tests/data/SPDXJSONExample-v2.2.spdx.json").unwrap(),
95        )
96        .unwrap();
97        assert_eq!(
98            spdx_file.annotations[0].annotation_type,
99            AnnotationType::Other
100        );
101    }
102
103    #[test]
104    fn annotation_comment() {
105        let spdx_file: SPDX = serde_json::from_str(
106            &read_to_string("tests/data/SPDXJSONExample-v2.2.spdx.json").unwrap(),
107        )
108        .unwrap();
109        assert_eq!(
110            spdx_file.annotations[0].annotation_comment,
111            "Document level annotation"
112        );
113    }
114}