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}