smos_application/types/
search_hit.rs1use serde::{Deserialize, Serialize};
10use smos_domain::{FactId, MemoryKey};
11
12#[derive(Debug, Clone, PartialEq)]
14pub struct SearchHit {
15 pub id: FactId,
16 pub document: String,
17 pub memory_key: MemoryKey,
18 pub metadata: SearchHitMetadata,
19}
20
21#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
23pub struct SearchHitMetadata {
24 pub status: String,
26 pub confidence: f32,
28 pub valid_until: Option<String>,
32 pub heat_base: f32,
34 pub last_access_at: f32,
41 pub distance: Option<f32>,
44}
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49
50 fn sample_metadata() -> SearchHitMetadata {
51 SearchHitMetadata {
52 status: "accepted".into(),
53 confidence: 0.85,
54 valid_until: None,
55 heat_base: 1.0,
56 last_access_at: 1_700_000_000.0,
57 distance: Some(0.12),
58 }
59 }
60
61 #[test]
62 fn metadata_roundtrips_through_serde() {
63 let meta = sample_metadata();
64 let json = serde_json::to_string(&meta).unwrap();
65 let back: SearchHitMetadata = serde_json::from_str(&json).unwrap();
66 assert_eq!(meta, back);
67 }
68
69 #[test]
70 fn metadata_serialises_optional_valid_until_as_null_when_absent() {
71 let meta = sample_metadata();
72 let v: serde_json::Value = serde_json::to_value(&meta).unwrap();
73 assert_eq!(v["valid_until"], serde_json::Value::Null);
74 }
75
76 #[test]
77 fn metadata_serialises_optional_distance_as_number_when_present() {
78 let meta = sample_metadata();
79 let v: serde_json::Value = serde_json::to_value(&meta).unwrap();
80 let got = v["distance"].as_f64().unwrap_or(f64::NAN);
83 assert!((got - 0.12).abs() < 1e-5, "got {got}");
84 }
85
86 #[test]
87 fn metadata_supports_tombstoned_fact() {
88 let meta = SearchHitMetadata {
89 status: "accepted".into(),
90 confidence: 0.9,
91 valid_until: Some("2027-01-01T00:00:00Z".into()),
92 heat_base: 0.4,
93 last_access_at: 1_700_000_050.0,
94 distance: None,
95 };
96 let v: serde_json::Value = serde_json::to_value(&meta).unwrap();
97 assert_eq!(v["valid_until"], "2027-01-01T00:00:00Z");
98 assert_eq!(v["distance"], serde_json::Value::Null);
99 }
100}