1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
4#[serde(rename_all = "lowercase")]
5pub enum Mode {
6 State,
7 Append,
8 List,
9}
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum Operation {
13 Upsert,
14 Patch,
15 Delete,
16 Create,
17 Snapshot,
18}
19
20impl std::str::FromStr for Operation {
21 type Err = std::convert::Infallible;
22
23 fn from_str(s: &str) -> Result<Self, Self::Err> {
24 Ok(match s {
25 "upsert" => Operation::Upsert,
26 "patch" => Operation::Patch,
27 "delete" => Operation::Delete,
28 "create" => Operation::Create,
29 "snapshot" => Operation::Snapshot,
30 _ => Operation::Upsert,
31 })
32 }
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize)]
36pub struct Frame {
37 pub mode: Mode,
38 #[serde(rename = "entity")]
39 pub entity: String,
40 pub op: String,
41 #[serde(default)]
42 pub key: String,
43 pub data: serde_json::Value,
44 #[serde(default)]
45 pub append: Vec<String>,
46}
47
48impl Frame {
49 pub fn entity_name(&self) -> &str {
50 &self.entity
51 }
52
53 pub fn operation(&self) -> Operation {
54 self.op.parse().unwrap()
55 }
56
57 pub fn is_snapshot(&self) -> bool {
58 self.op == "snapshot"
59 }
60}
61
62#[derive(Debug, Clone, Serialize, Deserialize)]
63pub struct SnapshotEntity {
64 pub key: String,
65 pub data: serde_json::Value,
66}
67
68pub fn parse_frame(bytes: &[u8]) -> Result<Frame, serde_json::Error> {
69 let text = String::from_utf8_lossy(bytes);
70 serde_json::from_str(&text)
71}
72
73pub fn parse_snapshot_entities(data: &serde_json::Value) -> Vec<SnapshotEntity> {
74 match data {
75 serde_json::Value::Array(arr) => arr
76 .iter()
77 .filter_map(|v| serde_json::from_value(v.clone()).ok())
78 .collect(),
79 _ => Vec::new(),
80 }
81}