real_time_sqlx/operations/
serialize.rs

1//! Serialize and deserialize database operations from JSON
2
3use serde::{Deserialize, Serialize};
4
5use crate::{error::DeserializeError, queries::serialize::FinalType};
6
7/// Generic JSON object type
8pub type JsonObject = serde_json::Map<String, serde_json::Value>;
9
10/// Coerce a JSON value to a JSON object
11pub fn object_from_value(value: serde_json::Value) -> Result<JsonObject, DeserializeError> {
12    match value {
13        serde_json::Value::Object(obj) => Ok(obj),
14        value => Err(DeserializeError::IncompatibleValue(value)),
15    }
16}
17
18/// Coerce a JSON value to a JSON object array
19pub fn object_array_from_value(
20    value: serde_json::Value,
21) -> Result<Vec<JsonObject>, DeserializeError> {
22    match value {
23        serde_json::Value::Array(array) => {
24            let mut objects = Vec::new();
25            for item in array {
26                objects.push(object_from_value(item)?);
27            }
28            Ok(objects)
29        }
30        value => Err(DeserializeError::IncompatibleValue(value)),
31    }
32}
33
34/// Entities related to a specific table
35pub trait Tabled {
36    fn get_table(&self) -> &str;
37}
38
39/// An incoming granular operation to be performed in the database
40/// The data can be partial or complete, depending on the operation.
41#[derive(Debug, Clone, Serialize, Deserialize)]
42#[serde(tag = "type")]
43pub enum GranularOperation {
44    #[serde(rename = "create")]
45    Create { table: String, data: JsonObject },
46    #[serde(rename = "create_many")]
47    CreateMany {
48        table: String,
49        data: Vec<JsonObject>,
50    },
51    #[serde(rename = "update")]
52    Update {
53        table: String,
54        id: FinalType,
55        data: JsonObject,
56    },
57    #[serde(rename = "delete")]
58    Delete { table: String, id: FinalType },
59}
60
61impl Tabled for GranularOperation {
62    /// Helper method to get the table name from the operation
63    fn get_table(&self) -> &str {
64        match self {
65            GranularOperation::Create { table, .. } => table,
66            GranularOperation::CreateMany { table, .. } => table,
67            GranularOperation::Update { table, .. } => table,
68            GranularOperation::Delete { table, .. } => table,
69        }
70    }
71}
72
73/// An outgoing operation notification to be sent to clients
74/// The data sent back is always complete, hence the generic parameter.
75#[derive(Debug, Clone, Serialize, Deserialize)]
76#[serde(tag = "type")]
77pub enum OperationNotification<T> {
78    #[serde(rename = "create")]
79    Create { table: String, data: T },
80    #[serde(rename = "create_many")]
81    CreateMany { table: String, data: Vec<T> },
82    #[serde(rename = "update")]
83    Update {
84        table: String,
85        id: FinalType,
86        data: T,
87    },
88    #[serde(rename = "delete")]
89    Delete {
90        table: String,
91        id: FinalType,
92        data: T,
93    },
94}
95
96impl<T> Tabled for OperationNotification<T> {
97    /// Helper method to get the table name from the operation
98    fn get_table(&self) -> &str {
99        match self {
100            OperationNotification::Create { table, .. } => table,
101            OperationNotification::CreateMany { table, .. } => table,
102            OperationNotification::Update { table, .. } => table,
103            OperationNotification::Delete { table, .. } => table,
104        }
105    }
106}