1use sim_kernel::{Cx, Error, Expr, Result, Symbol};
9
10use crate::contract::{Draft, Operation};
11use crate::dispatch::LensRegistry;
12
13impl LensRegistry {
14 pub fn render(&self, cx: &mut Cx, lens_id: &Symbol, value: &Expr) -> Result<Expr> {
16 let lens = self
17 .get(lens_id)
18 .ok_or_else(|| Error::HostError(format!("unknown lens {lens_id}")))?;
19 let view = lens
20 .view
21 .as_ref()
22 .ok_or_else(|| Error::HostError(format!("lens {lens_id} is not a view")))?;
23 let scene = view.encode(cx, value)?;
24 sim_lib_scene::validate_scene(&scene).map_err(|error| {
25 Error::HostError(format!("view {lens_id} produced an invalid scene: {error}"))
26 })?;
27 Ok(scene)
28 }
29
30 pub fn propose(
33 &self,
34 cx: &mut Cx,
35 lens_id: &Symbol,
36 value: &Expr,
37 intent: &Expr,
38 ) -> Result<Draft> {
39 sim_lib_intent::validate_intent(intent)
40 .map_err(|error| Error::HostError(format!("invalid intent: {error}")))?;
41 let editor = self.editor_of(lens_id)?;
42 editor.decode(cx, value, intent)
43 }
44
45 pub fn commit(&self, cx: &mut Cx, lens_id: &Symbol, draft: &Draft) -> Result<Operation> {
47 if !draft.committable {
48 return Err(Error::HostError(format!(
49 "draft is not committable ({} diagnostic(s))",
50 draft.diagnostics.len()
51 )));
52 }
53 self.editor_of(lens_id)?.commit(cx, draft)
54 }
55
56 fn editor_of(&self, lens_id: &Symbol) -> Result<std::sync::Arc<dyn crate::contract::Editor>> {
57 let lens = self
58 .get(lens_id)
59 .ok_or_else(|| Error::HostError(format!("unknown lens {lens_id}")))?;
60 lens.editor
61 .clone()
62 .ok_or_else(|| Error::HostError(format!("lens {lens_id} is not an editor")))
63 }
64}