sim_table_core/
citizen_fields.rs1use sim_kernel::{Error, Expr, Result, Symbol};
8
9use crate::{TablePath, decode_table_op};
10
11pub mod entries {
13 use super::*;
14
15 pub fn encode(entries: &[(Symbol, Expr)]) -> Expr {
17 Expr::Map(
18 entries
19 .iter()
20 .map(|(key, value)| (Expr::Symbol(key.clone()), value.clone()))
21 .collect(),
22 )
23 }
24
25 pub fn decode(expr: &Expr) -> Result<Vec<(Symbol, Expr)>> {
28 let Expr::Map(entries) = expr else {
29 return Err(field_error("entries", "expected map"));
30 };
31 entries
32 .iter()
33 .map(|(key, value)| {
34 let Expr::Symbol(key) = key else {
35 return Err(field_error("entries", "expected symbol key"));
36 };
37 Ok((key.clone(), value.clone()))
38 })
39 .collect()
40 }
41}
42
43pub mod expr_list {
45 use super::*;
46
47 pub fn encode(items: &[Expr]) -> Expr {
49 Expr::List(items.to_vec())
50 }
51
52 pub fn decode(expr: &Expr) -> Result<Vec<Expr>> {
55 let Expr::List(items) = expr else {
56 return Err(field_error("items", "expected list"));
57 };
58 Ok(items.clone())
59 }
60}
61
62pub mod symbol {
64 use super::*;
65
66 pub fn encode(symbol: &Symbol) -> Expr {
68 Expr::Symbol(symbol.clone())
69 }
70
71 pub fn decode(expr: &Expr) -> Result<Symbol> {
73 let Expr::Symbol(symbol) = expr else {
74 return Err(field_error("symbol", "expected symbol"));
75 };
76 Ok(symbol.clone())
77 }
78}
79
80pub mod path_segments {
82 use super::*;
83
84 pub fn encode(segments: &[String]) -> Expr {
86 Expr::List(
87 segments
88 .iter()
89 .map(|segment| Expr::String(segment.clone()))
90 .collect(),
91 )
92 }
93
94 pub fn decode(expr: &Expr) -> Result<Vec<String>> {
97 let Expr::List(items) = expr else {
98 return Err(field_error("path", "expected list"));
99 };
100 let mut path = TablePath::new();
101 for item in items {
102 let Expr::String(segment) = item else {
103 return Err(field_error("path", "expected string segment"));
104 };
105 path.push(segment)
106 .map_err(|_| field_error("path", format!("illegal segment {segment:?}")))?;
107 }
108 Ok(path.segments().to_vec())
109 }
110}
111
112pub mod table_op_expr {
114 use super::*;
115
116 pub fn encode(op: &Expr) -> Expr {
118 op.clone()
119 }
120
121 pub fn decode(expr: &Expr) -> Result<Expr> {
124 decode_table_op(expr)
125 .map_err(|err| field_error("operation", format!("invalid table operation: {err:?}")))?;
126 Ok(expr.clone())
127 }
128}
129
130fn field_error(field: &str, message: impl Into<String>) -> Error {
131 Error::Eval(format!("table citizen field {field}: {}", message.into()))
132}