Skip to main content

sim_lib_view_expr_tree/
codec.rs

1//! SurfaceCodec identity and reversible contract implementation.
2
3use sim_kernel::{Cx, Diagnostic, Error, Expr, Result, Symbol};
4use sim_lib_view::{Draft, Operation, SurfaceCaps, SurfaceCodec};
5
6use crate::{intent, scene};
7
8/// Stable registry id for the expression-tree reversible surface.
9pub const EXPRESSION_TREE_SURFACE_CODEC_ID: &str = "surface:expression-tree";
10
11/// Returns the expression-tree surface registry symbol.
12pub fn expression_tree_surface_codec_symbol() -> Symbol {
13    Symbol::new(EXPRESSION_TREE_SURFACE_CODEC_ID)
14}
15
16/// Reversible, stateless codec for a revisioned expression-tree snapshot.
17#[derive(Clone, Copy, Debug, Default)]
18pub struct ExpressionTreeSurfaceCodec;
19
20impl ExpressionTreeSurfaceCodec {
21    /// Builds the expression-tree surface codec.
22    pub const fn new() -> Self {
23        Self
24    }
25}
26
27impl SurfaceCodec for ExpressionTreeSurfaceCodec {
28    fn encode(&self, _cx: &mut Cx, value: &Expr, caps: &SurfaceCaps) -> Result<Expr> {
29        scene::encode(value, caps)
30    }
31
32    fn decode(&self, _cx: &mut Cx, value: &Expr, submitted: &Expr) -> Result<Draft> {
33        match intent::decode(value, submitted) {
34            Ok(command) => Ok(Draft::clean(value.clone(), command)),
35            Err(error) => Ok(Draft::rejected(
36                value.clone(),
37                Diagnostic::error(error.to_string())
38                    .with_code(Symbol::qualified("expr-tree-view", "invalid-intent")),
39            )),
40        }
41    }
42
43    fn commit(&self, _cx: &mut Cx, draft: &Draft) -> Result<Operation> {
44        if !draft.committable || !draft.diagnostics.is_empty() {
45            return Err(Error::HostError(
46                "expression-tree draft is not committable".to_owned(),
47            ));
48        }
49        intent::commit(&draft.proposed)
50    }
51}