spdx_rs/models/
relationship.rs

1// SPDX-FileCopyrightText: 2020-2021 HH Partners
2//
3// SPDX-License-Identifier: MIT
4
5use serde::{Deserialize, Serialize};
6use strum_macros::AsRefStr;
7
8/// <https://spdx.github.io/spdx-spec/7-relationships-between-SPDX-elements/#71-relationship>
9#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Eq, Hash)]
10#[serde(rename_all = "camelCase")]
11pub struct Relationship {
12    /// SPDX ID of the element.
13    pub spdx_element_id: String,
14
15    /// SPDX ID of the related element.
16    pub related_spdx_element: String,
17
18    /// Type of the relationship.
19    pub relationship_type: RelationshipType,
20
21    /// <https://spdx.github.io/spdx-spec/7-relationships-between-SPDX-elements/#72-relationship-comment>
22    #[serde(skip_serializing_if = "Option::is_none")]
23    #[serde(default)]
24    pub comment: Option<String>,
25}
26
27impl Relationship {
28    /// Create a new relationship.
29    pub fn new(
30        spdx_element_id: &str,
31        related_spdx_element: &str,
32        relationship_type: RelationshipType,
33        comment: Option<String>,
34    ) -> Self {
35        Self {
36            spdx_element_id: spdx_element_id.to_string(),
37            related_spdx_element: related_spdx_element.to_string(),
38            relationship_type,
39            comment,
40        }
41    }
42}
43
44/// <https://spdx.github.io/spdx-spec/7-relationships-between-SPDX-elements/#71-relationship>
45#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, AsRefStr, Eq, Hash)]
46#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
47pub enum RelationshipType {
48    Describes,
49    DescribedBy,
50    Contains,
51    ContainedBy,
52    DependsOn,
53    DependencyOf,
54    DependencyManifestOf,
55    BuildDependencyOf,
56    DevDependencyOf,
57    OptionalDependencyOf,
58    ProvidedDependencyOf,
59    TestDependencyOf,
60    RuntimeDependencyOf,
61    ExampleOf,
62    Generates,
63    GeneratedFrom,
64    AncestorOf,
65    DescendantOf,
66    VariantOf,
67    DistributionArtifact,
68    PatchFor,
69    PatchApplied,
70    CopyOf,
71    FileAdded,
72    FileDeleted,
73    FileModified,
74    ExpandedFromArchive,
75    DynamicLink,
76    StaticLink,
77    DataFileOf,
78    TestCaseOf,
79    BuildToolOf,
80    DevToolOf,
81    TestOf,
82    TestToolOf,
83    DocumentationOf,
84    OptionalComponentOf,
85    MetafileOf,
86    PackageOf,
87    Amends,
88    PrerequisiteFor,
89    HasPrerequisite,
90    RequirementDescriptionFor,
91    SpecificationFor,
92    Other,
93}
94
95#[cfg(test)]
96mod test {
97    use std::fs::read_to_string;
98
99    use crate::models::SPDX;
100
101    use super::*;
102
103    #[test]
104    fn spdx_element_id() {
105        let spdx: 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.relationships[0].spdx_element_id,
111            "SPDXRef-DOCUMENT".to_string()
112        );
113    }
114    #[test]
115    fn related_spdx_element() {
116        let spdx: SPDX = serde_json::from_str(
117            &read_to_string("tests/data/SPDXJSONExample-v2.2.spdx.json").unwrap(),
118        )
119        .unwrap();
120        assert_eq!(
121            spdx.relationships[0].related_spdx_element,
122            "SPDXRef-Package".to_string()
123        );
124    }
125    #[test]
126    fn relationship_type() {
127        let spdx: SPDX = serde_json::from_str(
128            &read_to_string("tests/data/SPDXJSONExample-v2.2.spdx.json").unwrap(),
129        )
130        .unwrap();
131        assert_eq!(
132            spdx.relationships[0].relationship_type,
133            RelationshipType::Contains
134        );
135        assert_eq!(
136            spdx.relationships[2].relationship_type,
137            RelationshipType::CopyOf
138        );
139    }
140}