Skip to main content

telltale_machine/
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/// 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
55/// Basic in-memory guard layer.
56#[derive(Debug, Clone, Default, Serialize, Deserialize)]
57pub struct InMemoryGuardLayer {
58    /// Available resources by layer id.
59    pub resources: BTreeMap<LayerId, Value>,
60}
61
62impl GuardLayer for InMemoryGuardLayer {
63    type Resource = Value;
64    type Evidence = Value;
65
66    fn open_(&mut self, layer: &LayerId) -> Result<(Self::Resource, Self::Evidence), String> {
67        let resource = self
68            .resources
69            .get(layer)
70            .cloned()
71            .ok_or_else(|| format!("unknown guard layer {}", layer.0))?;
72        Ok((resource.clone(), resource))
73    }
74
75    fn close(&mut self, layer: &LayerId, evidence: Self::Evidence) -> Result<(), String> {
76        if !self.resources.contains_key(layer) {
77            return Err(format!("unknown guard layer {}", layer.0));
78        }
79        // SimpleGuardLayer does not validate; custom implementations can override
80        // to verify evidence matches open(). Evidence intentionally discarded:
81        let _ = evidence;
82        Ok(())
83    }
84
85    fn encode_evidence(evidence: &Self::Evidence) -> Result<Value, String> {
86        Ok(evidence.clone())
87    }
88
89    fn decode_evidence(value: &Value) -> Result<Self::Evidence, String> {
90        Ok(value.clone())
91    }
92}