weavatrix_memory/domain/
evidence.rs1use crate::error::{MemoryError, Result};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
5#[serde(transparent)]
6pub struct Confidence(u16);
7
8impl Confidence {
9 pub const CERTAIN: Self = Self(10_000);
10
11 pub fn from_basis_points(value: u16) -> Result<Self> {
17 if value > 10_000 {
18 return Err(MemoryError::InvalidValue {
19 field: "confidence",
20 reason: "must be between 0 and 10,000 basis points",
21 });
22 }
23 Ok(Self(value))
24 }
25
26 #[must_use]
27 pub const fn basis_points(self) -> u16 {
28 self.0
29 }
30}
31
32#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
33pub struct Evidence {
34 pub kind: String,
35 pub source: String,
36 #[serde(skip_serializing_if = "Option::is_none")]
37 pub locator: Option<String>,
38 #[serde(skip_serializing_if = "Option::is_none")]
39 pub digest: Option<String>,
40}
41
42impl Evidence {
43 pub fn new(kind: impl Into<String>, source: impl Into<String>) -> Result<Self> {
49 let evidence = Self {
50 kind: kind.into(),
51 source: source.into(),
52 locator: None,
53 digest: None,
54 };
55 evidence.validate()?;
56 Ok(evidence)
57 }
58
59 #[must_use]
60 pub fn with_locator(mut self, locator: impl Into<String>) -> Self {
61 self.locator = Some(locator.into());
62 self
63 }
64
65 #[must_use]
66 pub fn with_digest(mut self, digest: impl Into<String>) -> Self {
67 self.digest = Some(digest.into());
68 self
69 }
70
71 pub(crate) fn validate(&self) -> Result<()> {
72 super::validate_text("evidence.kind", &self.kind)?;
73 super::validate_text("evidence.source", &self.source)?;
74 super::validate_optional_text("evidence.locator", self.locator.as_deref())?;
75 super::validate_optional_text("evidence.digest", self.digest.as_deref())
76 }
77}