use crate::types::{
ArtifactLocation, BaselineState, Kind, Level, Location, Message, MultiformatMessage,
ReportingDescriptorReference,
};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Result {
pub rule_id: Option<String>,
pub rule_index: Option<i32>,
pub rule: Option<ReportingDescriptorReference>,
pub kind: Option<Kind>,
pub level: Option<Level>,
pub message: Message,
pub analysis_target: Option<ArtifactLocation>,
pub locations: Option<Vec<Location>>,
pub guid: Option<String>,
pub correlation_guid: Option<String>,
pub occurrence_count: Option<i32>,
pub partial_fingerprints: Option<HashMap<String, String>>,
pub fingerprints: Option<HashMap<String, String>>,
pub stacks: Option<Vec<Stack>>,
pub code_flows: Option<Vec<CodeFlow>>,
pub graphs: Option<Vec<Graph>>,
pub graph_traversals: Option<Vec<GraphTraversal>>,
pub related_locations: Option<Vec<Location>>,
pub suppressions: Option<Vec<Suppression>>,
pub baseline_state: Option<BaselineState>,
pub rank: Option<f64>,
pub attachments: Option<Vec<Attachment>>,
pub hosted_viewer_uri: Option<String>,
pub work_item_uris: Option<Vec<String>>,
pub provenance: Option<ResultProvenance>,
pub fixes: Option<Vec<Fix>>,
pub taxa: Option<Vec<ReportingDescriptorReference>>,
pub web_request: Option<WebRequest>,
pub web_response: Option<WebResponse>,
#[serde(flatten)]
pub properties: Option<HashMap<String, serde_json::Value>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Stack {
pub message: Option<Message>,
pub frames: Vec<StackFrame>,
#[serde(flatten)]
pub properties: Option<HashMap<String, serde_json::Value>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct StackFrame {
pub location: Option<Location>,
pub module: Option<String>,
pub thread_id: Option<i32>,
pub parameters: Option<Vec<String>>,
#[serde(flatten)]
pub properties: Option<HashMap<String, serde_json::Value>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CodeFlow {
pub message: Option<Message>,
pub thread_flows: Vec<ThreadFlow>,
#[serde(flatten)]
pub properties: Option<HashMap<String, serde_json::Value>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ThreadFlow {
pub id: Option<String>,
pub message: Option<Message>,
pub initial_state: Option<HashMap<String, MultiformatMessage>>,
pub immutable_state: Option<HashMap<String, MultiformatMessage>>,
pub locations: Vec<ThreadFlowLocation>,
#[serde(flatten)]
pub properties: Option<HashMap<String, serde_json::Value>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ThreadFlowLocation {
pub index: Option<i32>,
pub location: Option<Location>,
pub stack: Option<Stack>,
pub kinds: Option<Vec<String>>,
pub taxa: Option<Vec<ReportingDescriptorReference>>,
pub module: Option<String>,
pub state: Option<HashMap<String, MultiformatMessage>>,
pub execution_order: Option<i32>,
pub execution_time_utc: Option<String>,
pub importance: Option<ThreadFlowLocationImportance>,
pub web_request: Option<WebRequest>,
pub web_response: Option<WebResponse>,
#[serde(flatten)]
pub properties: Option<HashMap<String, serde_json::Value>>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum ThreadFlowLocationImportance {
Important,
Essential,
Unimportant,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct WebRequest {
pub index: Option<i32>,
pub protocol: Option<String>,
pub version: Option<String>,
pub target: Option<String>,
pub method: Option<String>,
pub headers: Option<HashMap<String, String>>,
pub parameters: Option<HashMap<String, String>>,
pub body: Option<ResultArtifactContent>,
#[serde(flatten)]
pub properties: Option<HashMap<String, serde_json::Value>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct WebResponse {
pub index: Option<i32>,
pub protocol: Option<String>,
pub version: Option<String>,
pub status_code: Option<i32>,
pub reason_phrase: Option<String>,
pub headers: Option<HashMap<String, String>>,
pub body: Option<ResultArtifactContent>,
pub no_response_received: Option<bool>,
#[serde(flatten)]
pub properties: Option<HashMap<String, serde_json::Value>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ResultArtifactContent {
pub text: Option<String>,
pub binary: Option<String>,
#[serde(flatten)]
pub properties: Option<HashMap<String, serde_json::Value>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Graph {
pub description: Option<Message>,
pub nodes: Option<Vec<Node>>,
pub edges: Option<Vec<Edge>>,
#[serde(flatten)]
pub properties: Option<HashMap<String, serde_json::Value>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Node {
pub id: String,
pub label: Option<Message>,
pub location: Option<Location>,
pub children: Option<Vec<NodeReference>>,
#[serde(flatten)]
pub properties: Option<HashMap<String, serde_json::Value>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Edge {
pub id: String,
pub label: Option<Message>,
pub source_node_id: String,
pub target_node_id: String,
#[serde(flatten)]
pub properties: Option<HashMap<String, serde_json::Value>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GraphTraversal {
pub run_graph_index: Option<i32>,
pub result_graph_index: Option<i32>,
pub description: Option<Message>,
pub initial_state: Option<HashMap<String, MultiformatMessage>>,
pub immutable_state: Option<HashMap<String, MultiformatMessage>>,
pub edge_traversals: Option<Vec<EdgeTraversal>>,
#[serde(flatten)]
pub properties: Option<HashMap<String, serde_json::Value>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct EdgeTraversal {
pub edge_id: String,
pub message: Option<Message>,
pub final_state: Option<HashMap<String, MultiformatMessage>>,
pub step_over_edge_count: Option<i32>,
#[serde(flatten)]
pub properties: Option<HashMap<String, serde_json::Value>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct NodeReference {
pub id: String,
#[serde(flatten)]
pub properties: Option<HashMap<String, serde_json::Value>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Suppression {
pub kind: String,
pub status: Option<SuppressionStatus>,
pub justification: Option<String>,
pub location: Option<Location>,
pub guid: Option<String>,
#[serde(flatten)]
pub properties: Option<HashMap<String, serde_json::Value>>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum SuppressionStatus {
Accepted,
UnderReview,
Rejected,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Attachment {
pub description: Option<Message>,
pub artifact_location: ArtifactLocation,
pub regions: Option<Vec<crate::types::Region>>,
pub rectangles: Option<Vec<Rectangle>>,
#[serde(flatten)]
pub properties: Option<HashMap<String, serde_json::Value>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Rectangle {
pub top: Option<f64>,
pub left: Option<f64>,
pub bottom: Option<f64>,
pub right: Option<f64>,
pub message: Option<Message>,
#[serde(flatten)]
pub properties: Option<HashMap<String, serde_json::Value>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ResultProvenance {
pub first_detection_time_utc: Option<String>,
pub last_detection_time_utc: Option<String>,
pub first_detection_run_guid: Option<String>,
pub last_detection_run_guid: Option<String>,
pub invocation_index: Option<i32>,
pub conversion_sources: Option<Vec<PhysicalLocation>>,
#[serde(flatten)]
pub properties: Option<HashMap<String, serde_json::Value>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Fix {
pub description: Option<Message>,
pub artifact_changes: Vec<ArtifactChange>,
#[serde(flatten)]
pub properties: Option<HashMap<String, serde_json::Value>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ArtifactChange {
pub artifact_location: ArtifactLocation,
pub replacements: Vec<Replacement>,
#[serde(flatten)]
pub properties: Option<HashMap<String, serde_json::Value>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Replacement {
pub deleted_region: crate::types::Region,
pub inserted_content: Option<ResultArtifactContent>,
#[serde(flatten)]
pub properties: Option<HashMap<String, serde_json::Value>>,
}
pub use crate::types::PhysicalLocation;
impl Result {
pub fn new(message: impl Into<Message>) -> Self {
Self {
rule_id: None,
rule_index: None,
rule: None,
kind: None,
level: None,
message: message.into(),
analysis_target: None,
locations: None,
guid: None,
correlation_guid: None,
occurrence_count: None,
partial_fingerprints: None,
fingerprints: None,
stacks: None,
code_flows: None,
graphs: None,
graph_traversals: None,
related_locations: None,
suppressions: None,
baseline_state: None,
rank: None,
attachments: None,
hosted_viewer_uri: None,
work_item_uris: None,
provenance: None,
fixes: None,
taxa: None,
web_request: None,
web_response: None,
properties: None,
}
}
pub fn with_rule_id(mut self, rule_id: impl Into<String>) -> Self {
self.rule_id = Some(rule_id.into());
self
}
pub fn with_level(mut self, level: Level) -> Self {
self.level = Some(level);
self
}
pub fn with_kind(mut self, kind: Kind) -> Self {
self.kind = Some(kind);
self
}
pub fn add_location(mut self, location: Location) -> Self {
self.locations.get_or_insert_with(Vec::new).push(location);
self
}
pub fn with_analysis_target(mut self, target: ArtifactLocation) -> Self {
self.analysis_target = Some(target);
self
}
pub fn add_code_flow(mut self, code_flow: CodeFlow) -> Self {
self.code_flows.get_or_insert_with(Vec::new).push(code_flow);
self
}
}