1use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7use url::Url;
8
9#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
11#[serde(rename_all = "camelCase")]
12pub struct ArtifactLocation {
13 pub uri: Option<String>,
15
16 pub uri_base_id: Option<String>,
18
19 pub index: Option<i32>,
21
22 pub description: Option<crate::types::Message>,
24
25 #[serde(flatten)]
27 pub properties: Option<HashMap<String, serde_json::Value>>,
28}
29
30#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
32#[serde(rename_all = "camelCase")]
33pub struct Artifact {
34 pub location: Option<ArtifactLocation>,
36
37 pub parent_index: Option<i32>,
39
40 pub offset: Option<i32>,
42
43 pub length: Option<i32>,
45
46 pub roles: Option<Vec<ArtifactRole>>,
48
49 pub mime_type: Option<String>,
51
52 pub contents: Option<ArtifactContent>,
54
55 pub encoding: Option<String>,
57
58 pub source_language: Option<String>,
60
61 pub hashes: Option<Vec<Hash>>,
63
64 pub last_modified_time_utc: Option<String>,
66
67 pub description: Option<crate::types::Message>,
69
70 #[serde(flatten)]
72 pub properties: Option<HashMap<String, serde_json::Value>>,
73}
74
75#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
77#[serde(rename_all = "camelCase")]
78pub struct ArtifactContent {
79 pub text: Option<String>,
81
82 pub binary: Option<String>,
84
85 pub rendered: Option<MultiformatMessageString>,
87
88 #[serde(flatten)]
90 pub properties: Option<HashMap<String, serde_json::Value>>,
91}
92
93#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
95#[serde(rename_all = "camelCase")]
96pub struct MultiformatMessageString {
97 pub text: Option<String>,
99
100 pub markdown: Option<String>,
102
103 #[serde(flatten)]
105 pub properties: Option<HashMap<String, serde_json::Value>>,
106}
107
108#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
110#[serde(rename_all = "camelCase")]
111pub enum ArtifactRole {
112 AnalysisTarget,
114 Attachment,
116 ResponseFile,
118 ResultFile,
120 StandardStream,
122 TracedFile,
124 Unmodified,
126 Modified,
128 Added,
130 Deleted,
132 Renamed,
134 Translated,
136 ConfigurationFile,
138 PolicyFile,
140 DebugOutputFile,
142}
143
144#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
146#[serde(rename_all = "camelCase")]
147pub struct Hash {
148 pub value: String,
150
151 pub algorithm: String,
153
154 #[serde(flatten)]
156 pub properties: Option<HashMap<String, serde_json::Value>>,
157}
158
159impl ArtifactLocation {
160 pub fn new(uri: impl Into<String>) -> Self {
162 Self {
163 uri: Some(uri.into()),
164 uri_base_id: None,
165 index: None,
166 description: None,
167 properties: None,
168 }
169 }
170
171 pub fn from_index(index: i32) -> Self {
173 Self {
174 uri: None,
175 uri_base_id: None,
176 index: Some(index),
177 description: None,
178 properties: None,
179 }
180 }
181
182 pub fn with_uri_base_id(mut self, uri_base_id: impl Into<String>) -> Self {
184 self.uri_base_id = Some(uri_base_id.into());
185 self
186 }
187
188 pub fn with_description(mut self, description: impl Into<crate::types::Message>) -> Self {
190 self.description = Some(description.into());
191 self
192 }
193
194 pub fn parse_uri(&self) -> Result<Option<Url>, url::ParseError> {
196 match &self.uri {
197 Some(uri) => Ok(Some(Url::parse(uri)?)),
198 None => Ok(None),
199 }
200 }
201}
202
203impl Artifact {
204 pub fn new(location: ArtifactLocation) -> Self {
206 Self {
207 location: Some(location),
208 parent_index: None,
209 offset: None,
210 length: None,
211 roles: None,
212 mime_type: None,
213 contents: None,
214 encoding: None,
215 source_language: None,
216 hashes: None,
217 last_modified_time_utc: None,
218 description: None,
219 properties: None,
220 }
221 }
222
223 pub fn add_role(mut self, role: ArtifactRole) -> Self {
225 self.roles.get_or_insert_with(Vec::new).push(role);
226 self
227 }
228
229 pub fn with_mime_type(mut self, mime_type: impl Into<String>) -> Self {
231 self.mime_type = Some(mime_type.into());
232 self
233 }
234
235 pub fn with_text_content(mut self, text: impl Into<String>) -> Self {
237 let content = ArtifactContent {
238 text: Some(text.into()),
239 binary: None,
240 rendered: None,
241 properties: None,
242 };
243 self.contents = Some(content);
244 self
245 }
246}
247
248impl Hash {
249 pub fn new(algorithm: impl Into<String>, value: impl Into<String>) -> Self {
251 Self {
252 algorithm: algorithm.into(),
253 value: value.into(),
254 properties: None,
255 }
256 }
257
258 pub fn md5(value: impl Into<String>) -> Self {
260 Self::new("md5", value)
261 }
262
263 pub fn sha1(value: impl Into<String>) -> Self {
265 Self::new("sha1", value)
266 }
267
268 pub fn sha256(value: impl Into<String>) -> Self {
270 Self::new("sha256", value)
271 }
272}