animsmith_core/
finding.rs1use serde::Serialize;
6use std::fmt;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize)]
10#[serde(rename_all = "lowercase")]
11pub enum Severity {
12 Note,
14 Warning,
17 Error,
20}
21
22impl fmt::Display for Severity {
23 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24 f.write_str(match self {
25 Severity::Note => "note",
26 Severity::Warning => "warning",
27 Severity::Error => "error",
28 })
29 }
30}
31
32#[derive(Debug, Clone, Serialize)]
34#[serde(untagged)]
35#[non_exhaustive]
36pub enum Value {
37 Number(f64),
39 Text(String),
41}
42
43impl fmt::Display for Value {
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 match self {
46 Value::Number(n) => write!(f, "{n:.4}"),
47 Value::Text(s) => f.write_str(s),
48 }
49 }
50}
51
52#[derive(Debug, Clone, Serialize)]
59#[non_exhaustive]
60pub struct Finding {
61 pub check_id: &'static str,
63 pub severity: Severity,
65 #[serde(skip_serializing_if = "Option::is_none")]
67 pub clip: Option<String>,
68 #[serde(skip_serializing_if = "Option::is_none")]
70 pub bone: Option<String>,
71 #[serde(skip_serializing_if = "Option::is_none")]
73 pub time_s: Option<f32>,
74 #[serde(skip_serializing_if = "Option::is_none")]
76 pub measured: Option<Value>,
77 #[serde(skip_serializing_if = "Option::is_none")]
79 pub expected: Option<Value>,
80 pub message: String,
82 #[serde(skip)]
88 pub diagnostic: bool,
89}
90
91impl Finding {
92 pub fn new(check_id: &'static str, severity: Severity, message: impl Into<String>) -> Self {
94 Self {
95 check_id,
96 severity,
97 clip: None,
98 bone: None,
99 time_s: None,
100 measured: None,
101 expected: None,
102 message: message.into(),
103 diagnostic: false,
104 }
105 }
106
107 pub fn as_diagnostic(mut self) -> Self {
110 self.diagnostic = true;
111 self
112 }
113
114 pub fn clip(mut self, clip: impl Into<String>) -> Self {
116 self.clip = Some(clip.into());
117 self
118 }
119
120 pub fn bone(mut self, bone: impl Into<String>) -> Self {
122 self.bone = Some(bone.into());
123 self
124 }
125
126 pub fn time(mut self, t: f32) -> Self {
128 self.time_s = Some(t);
129 self
130 }
131
132 pub fn measured(mut self, v: impl Into<Value>) -> Self {
134 self.measured = Some(v.into());
135 self
136 }
137
138 pub fn expected(mut self, v: impl Into<Value>) -> Self {
140 self.expected = Some(v.into());
141 self
142 }
143}
144
145impl From<f64> for Value {
146 fn from(n: f64) -> Self {
147 Value::Number(n)
148 }
149}
150
151impl From<f32> for Value {
152 fn from(n: f32) -> Self {
153 Value::Number(n as f64)
154 }
155}
156
157impl From<&str> for Value {
158 fn from(s: &str) -> Self {
159 Value::Text(s.to_owned())
160 }
161}
162
163impl From<String> for Value {
164 fn from(s: String) -> Self {
165 Value::Text(s)
166 }
167}