cyclonedx_rust/component/
pedigree_type.rs1use crate::common::attached_text::AttachedTextType;
2use crate::component::Component;
3use derive_builder::Builder;
4use serde::{Deserialize, Serialize};
5use yaserde_derive::{YaDeserialize, YaSerialize};
6
7#[derive(
8 Clone, Default, Builder, PartialEq, Debug, Serialize, Deserialize, YaSerialize, YaDeserialize,
9)]
10#[yaserde(
11 prefix = "ns",
12 default_namespace = "ns",
13 namespace = "ns: http://cyclonedx.org/schema/bom/1.2"
14)]
15pub struct PedigreeType {
16 ancestors: Vec<Component>,
17 descendants: Vec<Component>,
18 variants: Vec<Component>,
19 commits: Vec<CommitType>,
20 patches: Vec<PatchType>,
21 #[yaserde(prefix = "ns")]
22 notes: Option<String>,
23}
24
25#[derive(
26 Clone, Default, Builder, PartialEq, Debug, Serialize, Deserialize, YaSerialize, YaDeserialize,
27)]
28pub struct PatchType {
29 #[serde(rename = "type")]
30 #[yaserde(rename = "type", attribute)]
31 patchtype_type: BomPatchClassification,
32
33 diff: Option<DiffType>,
34 resolves: Vec<IssueType>,
35}
36
37#[derive(
38 Clone, Default, Builder, PartialEq, Debug, Serialize, Deserialize, YaSerialize, YaDeserialize,
39)]
40pub struct DiffType {
41 text: Option<AttachedTextType>,
42 url: Option<String>,
43}
44
45impl DiffType {
46 pub fn new(text: Option<AttachedTextType>, url: Option<String>) {
47 DiffType { text, url };
48 }
49}
50
51#[derive(
52 Clone, Default, Builder, Debug, PartialEq, Serialize, Deserialize, YaSerialize, YaDeserialize,
53)]
54pub struct IssueType {
55 #[serde(rename = "type")]
56 #[yaserde(rename = "type", attribute)]
57 issue_type: BomIssueClassification,
58
59 id: Option<String>,
60 name: Option<String>,
61 description: Option<String>,
62 source: Option<Source>,
63 references: Vec<String>,
64}
65
66#[derive(Clone, PartialEq, Debug, Serialize, Deserialize, YaSerialize, YaDeserialize)]
67pub struct Source {
68 name: Option<String>,
69 url: Option<String>,
70}
71
72#[derive(Clone, PartialEq, Debug, Serialize, Deserialize, YaSerialize, YaDeserialize)]
73pub enum BomIssueClassification {
74 Detect,
75 Enhancement,
76 Security,
77}
78
79impl Default for BomIssueClassification {
80 fn default() -> Self {
81 BomIssueClassification::Detect
82 }
83}
84
85#[derive(Clone, PartialEq, Debug, Serialize, Deserialize, YaSerialize, YaDeserialize)]
86pub enum BomPatchClassification {
87 Unofficial,
88 Monkey,
89 Backport,
90 CherryPick,
91}
92
93impl Default for BomPatchClassification {
94 fn default() -> Self {
95 BomPatchClassification::Backport
96 }
97}
98
99#[derive(
100 Default, Clone, Builder, PartialEq, Debug, Serialize, Deserialize, YaSerialize, YaDeserialize,
101)]
102#[yaserde(
103 prefix = "ns",
104 default_namespace = "ns",
105 namespace = "ns: http://cyclonedx.org/schema/bom/1.2"
106)]
107pub struct CommitType {
108 #[yaserde(prefix = "ns")]
109 uid: Option<String>,
110 #[yaserde(prefix = "ns")]
111 url: Option<String>,
112 #[yaserde(prefix = "ns")]
113 author: Option<IdentifiableActionType>,
114 #[yaserde(prefix = "ns")]
115 committer: Option<IdentifiableActionType>,
116 #[yaserde(prefix = "ns")]
117 message: Option<String>,
118}
119
120#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, YaSerialize, YaDeserialize)]
121#[yaserde(
122 prefix = "ns",
123 default_namespace = "ns",
124 namespace = "ns: http://cyclonedx.org/schema/bom/1.2"
125)]
126pub struct IdentifiableActionType {
127 #[yaserde(prefix = "ns")]
128 timestamp: Option<String>,
129 #[yaserde(prefix = "ns")]
130 name: Option<String>,
131 #[yaserde(prefix = "ns")]
132 email: Option<String>,
133}
134
135impl IdentifiableActionType {
136 pub fn new(
137 timestamp: Option<String>,
138 name: Option<String>,
139 email: Option<String>,
140 ) -> IdentifiableActionType {
141 IdentifiableActionType {
142 timestamp,
143 name,
144 email,
145 }
146 }
147}
148
149#[cfg(test)]
150pub mod tests {
151 use super::*;
152 use crate::common::license::*;
153 use crate::component::classification::Classification;
154 use crate::component::pedigree_type::PedigreeType;
155 use crate::component::*;
156 use yaserde::ser::Config;
157
158 #[test]
159 pub fn print_xml() {
160 let expected: PedigreeType = PedigreeTypeBuilder::default()
161 .ancestors(vec![ComponentBuilder::default()
162 .component_type(Classification::Application)
163 .mime_type(None)
164 .bom_ref(None)
165 .supplier(None)
166 .author(None)
167 .publisher(Option::from("Apache".to_string()))
168 .group(Option::from("org.apache.tomcat".to_string()))
169 .name(Option::from("tomcat-catalina".to_string()))
170 .version(Option::from("9.0.14".to_string()))
171 .description(Option::from("Apache Catalina".to_string()))
172 .scope(None)
173 .hashes(Vec::new())
174 .licenses(vec![LicensesBuilder::default()
175 .license(vec![LicenseTypeBuilder::default()
176 .id(Option::from("Apache-2.0".to_string()))
177 .name(None)
178 .text(None)
179 .url(None)
180 .build()
181 .unwrap()])
182 .expression(None)
183 .build()
184 .unwrap()])
185 .copyright(None)
186 .purl(Option::from(
187 "pkg:maven/org.apache.tomcat/tomcat-catalina@9.0.14?packaging=jar".to_string(),
188 ))
189 .swid(None)
190 .modified(None)
191 .pedigree(None)
192 .external_references(Vec::new())
193 .components(Vec::new())
194 .build()
195 .unwrap()])
196 .descendants(Vec::new())
197 .variants(Vec::new())
198 .commits(vec![CommitTypeBuilder::default()
199 .uid(Option::from(
200 "7638417db6d59f3c431d3e1f261cc637155684cd".to_string(),
201 ))
202 .url(Option::from(
203 "https://location/to/7638417db6d59f3c431d3e1f261cc637155684cd".to_string(),
204 ))
205 .author(Option::from(IdentifiableActionType::new(
206 Option::from("2018-11-07T22:01:45Z".to_string()),
207 Option::from("John Doe".to_string()),
208 Option::from("john.doe@example.com".to_string()),
209 )))
210 .committer(None)
211 .message(None)
212 .build()
213 .unwrap()])
214 .patches(Vec::new())
215 .notes(Option::from("Commentary here".to_string()))
216 .build()
217 .unwrap();
218
219 let parsed = yaserde::ser::to_string_with_config(
220 &expected,
221 &Config {
222 perform_indent: false,
223 write_document_declaration: false,
224 indent_string: None,
225 },
226 )
227 .unwrap();
228
229 let actual: PedigreeType = yaserde::de::from_str(parsed.as_str()).unwrap();
230
231 assert_eq!(expected, actual);
232 }
233}