Skip to main content

this_me/
runtime.rs

1use std::fmt;
2
3use serde_json::{Map, Value as JsonValue};
4
5use crate::kernel::{
6    execute_value_to_json, kernel_event_to_json, memory_to_json, ExecuteError, ExecuteValue,
7    IntoPath, Kernel, KernelError, KernelEvent, Memory, Value,
8};
9use crate::storage::{MemoryStore, StorageError};
10
11#[derive(Debug)]
12pub enum RuntimeError {
13    Kernel(KernelError),
14    Execute(ExecuteError),
15    Storage(StorageError),
16}
17
18impl fmt::Display for RuntimeError {
19    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20        match self {
21            Self::Kernel(error) => write!(f, "{error}"),
22            Self::Execute(error) => write!(f, "{error}"),
23            Self::Storage(error) => write!(f, "{error}"),
24        }
25    }
26}
27
28impl std::error::Error for RuntimeError {}
29
30impl From<KernelError> for RuntimeError {
31    fn from(error: KernelError) -> Self {
32        Self::Kernel(error)
33    }
34}
35
36impl From<ExecuteError> for RuntimeError {
37    fn from(error: ExecuteError) -> Self {
38        Self::Execute(error)
39    }
40}
41
42impl From<StorageError> for RuntimeError {
43    fn from(error: StorageError) -> Self {
44        Self::Storage(error)
45    }
46}
47
48#[derive(Debug)]
49pub struct KernelRuntime<S> {
50    kernel: Kernel,
51    store: S,
52}
53
54#[derive(Debug, Clone, PartialEq)]
55pub struct RuntimeReceipt<T> {
56    pub result: T,
57    pub events: Vec<KernelEvent>,
58}
59
60pub trait RuntimeReceiptResultJson {
61    fn to_receipt_result_json(&self) -> JsonValue;
62}
63
64impl RuntimeReceiptResultJson for ExecuteValue {
65    fn to_receipt_result_json(&self) -> JsonValue {
66        execute_value_to_json(self)
67    }
68}
69
70impl RuntimeReceiptResultJson for Memory {
71    fn to_receipt_result_json(&self) -> JsonValue {
72        memory_to_json(self)
73    }
74}
75
76pub fn runtime_receipt_to_json<T>(receipt: &RuntimeReceipt<T>) -> JsonValue
77where
78    T: RuntimeReceiptResultJson,
79{
80    JsonValue::Object(Map::from_iter([
81        (
82            "result".to_string(),
83            receipt.result.to_receipt_result_json(),
84        ),
85        (
86            "events".to_string(),
87            JsonValue::Array(receipt.events.iter().map(kernel_event_to_json).collect()),
88        ),
89    ]))
90}
91
92impl<S> KernelRuntime<S>
93where
94    S: MemoryStore,
95{
96    pub fn load(store: S) -> Result<Self, RuntimeError> {
97        let kernel = store.load_kernel()?;
98        Ok(Self { kernel, store })
99    }
100
101    pub fn new(kernel: Kernel, store: S) -> Self {
102        Self { kernel, store }
103    }
104
105    pub fn kernel(&self) -> &Kernel {
106        &self.kernel
107    }
108
109    pub fn kernel_mut(&mut self) -> &mut Kernel {
110        &mut self.kernel
111    }
112
113    pub fn store(&self) -> &S {
114        &self.store
115    }
116
117    pub fn save(&self) -> Result<(), RuntimeError> {
118        Ok(self.store.save_kernel(&self.kernel)?)
119    }
120
121    pub fn read(&self, path: impl IntoPath) -> Option<&Value> {
122        self.kernel.read(path)
123    }
124
125    pub fn read_fresh(&mut self, path: impl IntoPath) -> Option<Value> {
126        self.kernel.read_fresh(path)
127    }
128
129    pub fn write(
130        &mut self,
131        path: impl IntoPath,
132        value: impl Into<Value>,
133    ) -> Result<Memory, RuntimeError> {
134        let memory = self.kernel.postulate(path, value)?.clone();
135        self.save()?;
136        Ok(memory)
137    }
138
139    pub fn write_with_receipt(
140        &mut self,
141        path: impl IntoPath,
142        value: impl Into<Value>,
143    ) -> Result<RuntimeReceipt<Memory>, RuntimeError> {
144        let event_cursor = self.kernel.event_cursor();
145        let memory = self.kernel.postulate(path, value)?.clone();
146        self.save()?;
147        let events = self.kernel.drain_events_since(event_cursor);
148        Ok(RuntimeReceipt {
149            result: memory,
150            events,
151        })
152    }
153
154    pub fn execute(
155        &mut self,
156        target: impl AsRef<str>,
157        body: Option<ExecuteValue>,
158    ) -> Result<ExecuteValue, RuntimeError> {
159        let result = self.kernel.execute(target, body)?;
160        self.save()?;
161        Ok(result)
162    }
163
164    pub fn execute_with_receipt(
165        &mut self,
166        target: impl AsRef<str>,
167        body: Option<ExecuteValue>,
168    ) -> Result<RuntimeReceipt<ExecuteValue>, RuntimeError> {
169        let event_cursor = self.kernel.event_cursor();
170        let result = self.kernel.execute(target, body)?;
171        self.save()?;
172        let events = self.kernel.drain_events_since(event_cursor);
173        Ok(RuntimeReceipt { result, events })
174    }
175
176    pub fn events(&self) -> &[KernelEvent] {
177        self.kernel.events()
178    }
179
180    pub fn events_matching(&self, path: impl IntoPath) -> Result<Vec<KernelEvent>, RuntimeError> {
181        Ok(self.kernel.events_matching(path)?)
182    }
183
184    pub fn drain_events(&mut self) -> Vec<KernelEvent> {
185        self.kernel.drain_events()
186    }
187
188    pub fn drain_events_matching(
189        &mut self,
190        path: impl IntoPath,
191    ) -> Result<Vec<KernelEvent>, RuntimeError> {
192        Ok(self.kernel.drain_events_matching(path)?)
193    }
194}