Skip to main content

interstice_abi/schema/
reducer.rs

1use serde::{Deserialize, Serialize};
2
3use crate::interstice_type_def::FieldDef;
4use crate::{ModuleSelection, NodeSelection};
5
6/// Declared table access for a reducer: [`NodeSelection`] + [`ModuleSelection`] + `table_name`.
7/// Use [`ModuleSelection::Current`] for the module that contains the reducer (no embedded crate name);
8/// the runtime matches that against the active call frame / host-call [`ModuleSelection`], like table scans.
9#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, Hash, PartialOrd, Ord)]
10pub struct ReducerTableRef {
11    pub node_selection: NodeSelection,
12    pub module_selection: ModuleSelection,
13    pub table_name: String,
14}
15
16#[derive(Debug, Clone, Deserialize, Serialize)]
17pub struct ReducerSchema {
18    pub name: String,
19    pub arguments: Vec<FieldDef>,
20    pub reads: Vec<ReducerTableRef>,
21    pub inserts: Vec<ReducerTableRef>,
22    pub updates: Vec<ReducerTableRef>,
23    pub deletes: Vec<ReducerTableRef>,
24}
25
26impl ReducerSchema {
27    pub fn new(
28        name: impl Into<String>,
29        arguments: Vec<FieldDef>,
30        reads: Vec<ReducerTableRef>,
31        inserts: Vec<ReducerTableRef>,
32        updates: Vec<ReducerTableRef>,
33        deletes: Vec<ReducerTableRef>,
34    ) -> Self {
35        Self {
36            name: name.into(),
37            arguments,
38            reads,
39            inserts,
40            updates,
41            deletes,
42        }
43    }
44}
45
46#[cfg(test)]
47mod tests {
48    use super::{ReducerSchema, ReducerTableRef};
49    use crate::{FieldDef, IntersticeType, ModuleSelection, NodeSelection, decode, encode};
50
51    #[test]
52    fn reducer_schema_round_trip_preserves_access_lists() {
53        let schema = ReducerSchema::new(
54            "hello",
55            vec![FieldDef {
56                name: "name".to_string(),
57                field_type: IntersticeType::String,
58            }],
59            vec![ReducerTableRef {
60                node_selection: NodeSelection::Current,
61                module_selection: ModuleSelection::Other("hello-example".to_string()),
62                table_name: "users".to_string(),
63            }],
64            vec![ReducerTableRef {
65                node_selection: NodeSelection::Current,
66                module_selection: ModuleSelection::Other("hello-example".to_string()),
67                table_name: "greetings".to_string(),
68            }],
69            vec![ReducerTableRef {
70                node_selection: NodeSelection::Current,
71                module_selection: ModuleSelection::Other("hello-example".to_string()),
72                table_name: "greetings".to_string(),
73            }],
74            vec![ReducerTableRef {
75                node_selection: NodeSelection::Current,
76                module_selection: ModuleSelection::Other("hello-example".to_string()),
77                table_name: "sessions".to_string(),
78            }],
79        );
80
81        let bytes = encode(&schema).expect("encode reducer schema");
82        let decoded: ReducerSchema = decode(&bytes).expect("decode reducer schema");
83
84        assert_eq!(decoded.name, "hello");
85        assert_eq!(decoded.reads.len(), 1);
86        assert_eq!(decoded.reads[0].table_name, "users");
87    }
88}