1use crate::array::Array;
2use crate::object::Object;
3use crate::statements::DefineTableStatement;
4use crate::thing::Thing;
5use crate::value::Value;
6use crate::vs::to_u128_be;
7use derive::Store;
8use revision::revisioned;
9use serde::{Deserialize, Serialize};
10use std::collections::{BTreeMap, HashMap};
11use std::fmt::{self, Display, Formatter};
12
13#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
15#[revisioned(revision = 1)]
16pub enum TableMutation {
17 Set(Thing, Value),
20 Del(Thing),
21 Def(DefineTableStatement),
22}
23
24impl From<DefineTableStatement> for Value {
25 #[inline]
26 fn from(v: DefineTableStatement) -> Self {
27 let mut h = HashMap::<&str, Value>::new();
28 if let Some(id) = v.id {
29 h.insert("id", id.into());
30 }
31 h.insert("name", v.name.0.into());
32 Value::Object(Object::from(h))
33 }
34}
35
36#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
37#[revisioned(revision = 1)]
38pub struct TableMutations(pub String, pub Vec<TableMutation>);
39
40impl TableMutations {
41 pub fn new(tb: String) -> Self {
42 Self(tb, Vec::new())
43 }
44}
45
46#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
47#[revisioned(revision = 1)]
48pub struct DatabaseMutation(pub Vec<TableMutations>);
49
50impl DatabaseMutation {
51 pub fn new() -> Self {
52 Self(Vec::new())
53 }
54}
55
56impl Default for DatabaseMutation {
57 fn default() -> Self {
58 Self::new()
59 }
60}
61#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
63#[revisioned(revision = 1)]
64pub struct ChangeSet(pub [u8; 10], pub DatabaseMutation);
65
66impl TableMutation {
67 pub fn into_value(self) -> Value {
68 let (k, v) = match self {
69 TableMutation::Set(_t, v) => ("update".to_string(), v),
70 TableMutation::Del(t) => {
71 let mut h = BTreeMap::<String, Value>::new();
72 h.insert("id".to_string(), Value::Thing(t));
73 let o = Object::from(h);
74 ("delete".to_string(), Value::Object(o))
75 }
76 TableMutation::Def(t) => ("define_table".to_string(), Value::from(t)),
77 };
78
79 let mut h = BTreeMap::<String, Value>::new();
80 h.insert(k, v);
81 let o = crate::object::Object::from(h);
82 Value::Object(o)
83 }
84}
85
86impl DatabaseMutation {
87 pub fn into_value(self) -> Value {
88 let mut changes = Vec::<Value>::new();
89 for tbs in self.0 {
90 for tb in tbs.1 {
91 changes.push(tb.into_value());
92 }
93 }
94 Value::Array(Array::from(changes))
95 }
96}
97
98impl ChangeSet {
99 pub fn into_value(self) -> Value {
100 let mut m = BTreeMap::<String, Value>::new();
101 let vs = to_u128_be(self.0);
102 m.insert("versionstamp".to_string(), Value::from(vs));
103 m.insert("changes".to_string(), self.1.into_value());
104 let so: Object = m.into();
105 Value::Object(so)
106 }
107}
108
109impl Display for TableMutation {
110 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
111 match self {
112 TableMutation::Set(id, v) => write!(f, "SET {} {}", id, v),
113 TableMutation::Del(id) => write!(f, "DEL {}", id),
114 TableMutation::Def(t) => write!(f, "{}", t),
115 }
116 }
117}
118
119impl Display for TableMutations {
120 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
121 let tb = &self.0;
122 let muts = &self.1;
123 write!(f, "{}", tb)?;
124 muts.iter().try_for_each(|v| write!(f, "{}", v))
125 }
126}
127
128impl Display for DatabaseMutation {
129 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
130 let x = &self.0;
131
132 x.iter().try_for_each(|v| write!(f, "{}", v))
133 }
134}
135
136impl Display for ChangeSet {
137 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
138 let x = &self.1;
139
140 write!(f, "{}", x)
141 }
142}
143
144#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
146#[revisioned(revision = 1)]
147pub struct WriteMutationSet(pub Vec<TableMutations>);
148
149impl WriteMutationSet {
150 pub fn new() -> Self {
151 Self(Vec::new())
152 }
153}
154
155impl Default for WriteMutationSet {
156 fn default() -> Self {
157 Self::new()
158 }
159}
160
161#[cfg(test)]
162mod tests {
163 #[test]
164 fn serialization() {
165 use super::*;
166 use std::collections::HashMap;
167 let cs = ChangeSet(
168 [0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
169 DatabaseMutation(vec![TableMutations(
170 "mytb".to_string(),
171 vec![
172 TableMutation::Set(
173 Thing::from(("mytb".to_string(), "tobie".to_string())),
174 Value::Object(Object::from(HashMap::from([
175 (
176 "id",
177 Value::from(Thing::from(("mytb".to_string(), "tobie".to_string()))),
178 ),
179 ("note", Value::from("surreal")),
180 ]))),
181 ),
182 TableMutation::Del(Thing::from(("mytb".to_string(), "tobie".to_string()))),
183 TableMutation::Def(DefineTableStatement {
184 name: "mytb".into(),
185 ..DefineTableStatement::default()
186 }),
187 ],
188 )]),
189 );
190 let v = cs.into_value().into_json();
191 let s = serde_json::to_string(&v).unwrap();
192 assert_eq!(
193 s,
194 r#"{"changes":[{"update":{"id":"mytb:tobie","note":"surreal"}},{"delete":{"id":"mytb:tobie"}},{"define_table":{"name":"mytb"}}],"versionstamp":1}"#
195 );
196 }
197}