1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize)]
5#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
6pub struct Signal {
7 pub kind: SignalKind,
9 pub evidence: String,
11 #[serde(skip_serializing_if = "Option::is_none", default)]
13 pub rfc_basis: Option<String>,
14}
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
20#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
21pub enum SignalKind {
22 StatusCodeDiff,
24 HeaderPresence,
26 HeaderValue,
28 BodyDiff,
30 TimingDiff,
32 MetadataLeak,
34 InputReflection,
38}
39
40#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
46#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
47pub enum ImpactClass {
48 Low,
50 Medium,
52 High,
54}
55
56impl std::fmt::Display for SignalKind {
57 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58 match self {
59 Self::StatusCodeDiff => write!(f, "StatusCodeDiff"),
60 Self::HeaderPresence => write!(f, "HeaderPresence"),
61 Self::HeaderValue => write!(f, "HeaderValue"),
62 Self::BodyDiff => write!(f, "BodyDiff"),
63 Self::TimingDiff => write!(f, "TimingDiff"),
64 Self::MetadataLeak => write!(f, "MetadataLeak"),
65 Self::InputReflection => write!(f, "InputReflection"),
66 }
67 }
68}
69
70impl std::fmt::Display for ImpactClass {
71 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72 match self {
73 Self::Low => write!(f, "Low"),
74 Self::Medium => write!(f, "Medium"),
75 Self::High => write!(f, "High"),
76 }
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use super::{ImpactClass, SignalKind};
83
84 #[test]
85 fn signal_kind_display() {
86 assert_eq!(format!("{}", SignalKind::StatusCodeDiff), "StatusCodeDiff");
87 assert_eq!(format!("{}", SignalKind::HeaderPresence), "HeaderPresence");
88 assert_eq!(format!("{}", SignalKind::HeaderValue), "HeaderValue");
89 assert_eq!(format!("{}", SignalKind::BodyDiff), "BodyDiff");
90 assert_eq!(format!("{}", SignalKind::TimingDiff), "TimingDiff");
91 assert_eq!(format!("{}", SignalKind::MetadataLeak), "MetadataLeak");
92 assert_eq!(
93 format!("{}", SignalKind::InputReflection),
94 "InputReflection"
95 );
96 }
97
98 #[test]
99 fn impact_class_display() {
100 assert_eq!(format!("{}", ImpactClass::Low), "Low");
101 assert_eq!(format!("{}", ImpactClass::Medium), "Medium");
102 assert_eq!(format!("{}", ImpactClass::High), "High");
103 }
104}