use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum WitnessClass {
StaticAnalysis,
PropertyTest,
FormalVerification,
ManualReview,
RuntimeFuzz,
SubstrateWitness,
}
impl WitnessClass {
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Self::StaticAnalysis => "static-analysis",
Self::PropertyTest => "property-test",
Self::FormalVerification => "formal-verification",
Self::ManualReview => "manual-review",
Self::RuntimeFuzz => "runtime-fuzz",
Self::SubstrateWitness => "substrate-witness",
}
}
#[must_use]
pub fn parse_class(s: &str) -> Option<Self> {
match s {
"static-analysis" | "static_analysis" | "StaticAnalysis" => Some(Self::StaticAnalysis),
"property-test" | "property_test" | "PropertyTest" => Some(Self::PropertyTest),
"formal-verification" | "formal_verification" | "FormalVerification" => {
Some(Self::FormalVerification)
}
"manual-review" | "manual_review" | "ManualReview" => Some(Self::ManualReview),
"runtime-fuzz" | "runtime_fuzz" | "RuntimeFuzz" => Some(Self::RuntimeFuzz),
"substrate-witness" | "substrate_witness" | "SubstrateWitness" => {
Some(Self::SubstrateWitness)
}
_ => None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "kind", rename_all = "kebab-case")]
pub enum SeedKind {
Random,
EntropyFromCi,
TimestampSeeded,
Fixed(u64),
}
impl SeedKind {
#[must_use]
pub const fn is_non_deterministic(self) -> bool {
matches!(
self,
Self::Random | Self::EntropyFromCi | Self::TimestampSeeded
)
}
#[must_use]
pub const fn is_fixed(self) -> bool {
matches!(self, Self::Fixed(_))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn witness_class_str_roundtrip() {
for variant in [
WitnessClass::StaticAnalysis,
WitnessClass::PropertyTest,
WitnessClass::FormalVerification,
WitnessClass::ManualReview,
WitnessClass::RuntimeFuzz,
WitnessClass::SubstrateWitness,
] {
let s = variant.as_str();
let back = WitnessClass::parse_class(s).expect("kebab roundtrip");
assert_eq!(back, variant);
}
}
#[test]
fn witness_class_parses_snake_and_camel_too() {
assert_eq!(
WitnessClass::parse_class("property_test"),
Some(WitnessClass::PropertyTest)
);
assert_eq!(
WitnessClass::parse_class("PropertyTest"),
Some(WitnessClass::PropertyTest)
);
assert_eq!(WitnessClass::parse_class("unknown"), None);
}
#[test]
fn seed_kind_non_determinism() {
assert!(SeedKind::Random.is_non_deterministic());
assert!(SeedKind::EntropyFromCi.is_non_deterministic());
assert!(SeedKind::TimestampSeeded.is_non_deterministic());
assert!(!SeedKind::Fixed(42).is_non_deterministic());
assert!(!SeedKind::Random.is_fixed());
assert!(SeedKind::Fixed(42).is_fixed());
}
}