Skip to main content

telltale_vm/
guard.rs

1//! Guard-layer typed interface.
2
3use std::collections::BTreeMap;
4
5use serde::{Deserialize, Serialize};
6
7use crate::coroutine::Value;
8
9/// Guard-layer identifier.
10#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
11pub struct LayerId(pub String);
12
13impl From<&str> for LayerId {
14    fn from(value: &str) -> Self {
15        Self(value.to_string())
16    }
17}
18
19/// Lean-style guard layer API.
20pub trait GuardLayer {
21    /// Guard resource type.
22    type Resource: Clone;
23    /// Evidence type produced/consumed by acquire/release.
24    type Evidence: Clone;
25
26    /// Acquire a layer resource and produce evidence.
27    ///
28    /// # Errors
29    ///
30    /// Returns an error if the layer cannot be acquired.
31    fn open_(&mut self, layer: &LayerId) -> Result<(Self::Resource, Self::Evidence), String>;
32
33    /// Release a layer resource and consume evidence.
34    ///
35    /// # Errors
36    ///
37    /// Returns an error if the layer cannot be released.
38    fn close(&mut self, layer: &LayerId, evidence: Self::Evidence) -> Result<(), String>;
39
40    /// Encode evidence for register transport.
41    ///
42    /// # Errors
43    ///
44    /// Returns an error if encoding fails.
45    fn encode_evidence(evidence: &Self::Evidence) -> Result<Value, String>;
46
47    /// Decode evidence from register value.
48    ///
49    /// # Errors
50    ///
51    /// Returns an error if decoding fails.
52    fn decode_evidence(value: &Value) -> Result<Self::Evidence, String>;
53
54    /// Lean-name compatibility wrapper.
55    ///
56    /// # Errors
57    ///
58    /// Returns an error if encoding fails.
59    #[allow(non_snake_case)]
60    fn encodeEvidence(evidence: &Self::Evidence) -> Result<Value, String> {
61        Self::encode_evidence(evidence)
62    }
63
64    /// Lean-name compatibility wrapper.
65    ///
66    /// # Errors
67    ///
68    /// Returns an error if decoding fails.
69    #[allow(non_snake_case)]
70    fn decodeEvidence(value: &Value) -> Result<Self::Evidence, String> {
71        Self::decode_evidence(value)
72    }
73}
74
75/// Basic in-memory guard layer.
76#[derive(Debug, Clone, Default, Serialize, Deserialize)]
77pub struct InMemoryGuardLayer {
78    /// Available resources by layer id.
79    pub resources: BTreeMap<LayerId, Value>,
80}
81
82impl GuardLayer for InMemoryGuardLayer {
83    type Resource = Value;
84    type Evidence = Value;
85
86    fn open_(&mut self, layer: &LayerId) -> Result<(Self::Resource, Self::Evidence), String> {
87        let resource = self
88            .resources
89            .get(layer)
90            .cloned()
91            .ok_or_else(|| format!("unknown guard layer {}", layer.0))?;
92        Ok((resource.clone(), resource))
93    }
94
95    fn close(&mut self, layer: &LayerId, evidence: Self::Evidence) -> Result<(), String> {
96        if !self.resources.contains_key(layer) {
97            return Err(format!("unknown guard layer {}", layer.0));
98        }
99        // SimpleGuardLayer does not validate; custom implementations can override
100        // to verify evidence matches open(). Evidence intentionally discarded:
101        let _ = evidence;
102        Ok(())
103    }
104
105    fn encode_evidence(evidence: &Self::Evidence) -> Result<Value, String> {
106        Ok(evidence.clone())
107    }
108
109    fn decode_evidence(value: &Value) -> Result<Self::Evidence, String> {
110        Ok(value.clone())
111    }
112}