use crate::base::hash::Hash256;
use crate::base::schema::*;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub enum Evidence {
Deterministic,
Verified,
Reported,
Inferred,
Assumed,
}
pub fn base_evidence(schema: &Hash256) -> Evidence {
match schema_name_for_id(schema) {
Some(SCHEMA_VERDICT) => Evidence::Deterministic,
Some(SCHEMA_RESULT_EXTERNAL) => Evidence::Verified,
Some(SCHEMA_REQUEST) => Evidence::Reported,
Some(SCHEMA_ACTION) => Evidence::Reported,
Some(SCHEMA_RESPONSE) => Evidence::Reported,
Some(SCHEMA_RESULT) => Evidence::Reported,
Some(SCHEMA_RESULT_EFFECT_CONFIRMATION) => Evidence::Reported,
Some(SCHEMA_CAPABILITY) => Evidence::Reported,
Some(SCHEMA_APPROVAL) => Evidence::Reported,
Some(SCHEMA_REFUSAL) => Evidence::Reported,
Some(SCHEMA_USAGE) => Evidence::Reported,
Some(SCHEMA_RETRACTION) => Evidence::Reported,
Some(SCHEMA_SUMMARY) => Evidence::Inferred,
Some(SCHEMA_PLAN) => Evidence::Inferred,
Some(_) | None => Evidence::Assumed,
}
}
pub fn weakest(evidences: &[Evidence]) -> Evidence {
evidences
.iter()
.copied()
.max()
.unwrap_or(Evidence::Deterministic)
}
pub fn derive_evidence(schema: &Hash256, ref_evidences: &[Evidence]) -> Evidence {
let base = base_evidence(schema);
if ref_evidences.is_empty() {
base
} else {
let mut all = vec![base];
all.extend_from_slice(ref_evidences);
weakest(&all)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_base_evidence() {
assert_eq!(
base_evidence(&schema_id(SCHEMA_VERDICT)),
Evidence::Deterministic
);
assert_eq!(
base_evidence(&schema_id(SCHEMA_RESULT_EXTERNAL)),
Evidence::Verified
);
assert_eq!(
base_evidence(&schema_id(SCHEMA_REQUEST)),
Evidence::Reported
);
assert_eq!(base_evidence(&schema_id(SCHEMA_ACTION)), Evidence::Reported);
assert_eq!(
base_evidence(&schema_id(SCHEMA_SUMMARY)),
Evidence::Inferred
);
assert_eq!(base_evidence(&schema_id(SCHEMA_PLAN)), Evidence::Inferred);
assert_eq!(base_evidence(&[0xEEu8; 32]), Evidence::Assumed);
}
#[test]
fn every_frozen_schema_is_classified() {
assert_eq!(ALL_SCHEMAS.len(), 14);
for name in ALL_SCHEMAS {
assert_ne!(
base_evidence(&schema_id(name)),
Evidence::Assumed,
"frozen schema {name} fell through to the unknown-schema arm"
);
}
}
#[test]
fn test_lattice_order_strongest_to_weakest() {
assert!(Evidence::Deterministic < Evidence::Verified);
assert!(Evidence::Verified < Evidence::Reported);
assert!(Evidence::Reported < Evidence::Inferred);
assert!(Evidence::Inferred < Evidence::Assumed);
}
#[test]
fn test_weakest() {
assert_eq!(
weakest(&[Evidence::Deterministic, Evidence::Reported]),
Evidence::Reported
);
assert_eq!(
weakest(&[Evidence::Verified, Evidence::Deterministic]),
Evidence::Verified
);
assert_eq!(
weakest(&[Evidence::Reported, Evidence::Inferred, Evidence::Assumed]),
Evidence::Assumed
);
assert_eq!(weakest(&[Evidence::Reported]), Evidence::Reported);
}
#[test]
fn test_derive_evidence_no_refs() {
assert_eq!(
derive_evidence(&schema_id(SCHEMA_VERDICT), &[]),
Evidence::Deterministic
);
assert_eq!(
derive_evidence(&schema_id(SCHEMA_REQUEST), &[]),
Evidence::Reported
);
}
#[test]
fn test_derive_evidence_with_refs() {
assert_eq!(
derive_evidence(&schema_id(SCHEMA_RESULT_EXTERNAL), &[Evidence::Reported]),
Evidence::Reported
);
assert_eq!(
derive_evidence(&schema_id(SCHEMA_SUMMARY), &[Evidence::Assumed]),
Evidence::Assumed
);
assert_eq!(
derive_evidence(&schema_id(SCHEMA_SUMMARY), &[Evidence::Deterministic]),
Evidence::Inferred
);
}
}