Mohammed Naser | 3415a2a | 2025-03-06 21:16:12 -0500 | [diff] [blame^] | 1 | use serde::de::{self, SeqAccess, Visitor}; |
| 2 | use serde::{Deserialize, Deserializer, Serialize}; |
| 3 | use std::collections::HashMap; |
| 4 | use std::fmt; |
| 5 | use std::marker::PhantomData; |
| 6 | |
| 7 | #[derive(Debug, Deserialize)] |
| 8 | pub struct DatabaseSchema { |
| 9 | pub name: String, |
| 10 | |
| 11 | pub version: String, |
| 12 | |
| 13 | #[serde(rename = "cksum")] |
| 14 | pub checksum: Option<String>, |
| 15 | |
| 16 | pub tables: HashMap<String, TableSchema>, |
| 17 | } |
| 18 | |
| 19 | #[derive(Debug, Deserialize)] |
| 20 | pub struct TableSchema { |
| 21 | pub columns: HashMap<String, ColumnSchema>, |
| 22 | |
| 23 | #[serde(rename = "maxRows")] |
| 24 | pub max_rows: Option<u64>, |
| 25 | |
| 26 | #[serde(rename = "isRoot")] |
| 27 | pub is_root: Option<bool>, |
| 28 | |
| 29 | #[serde(rename = "indexes")] |
| 30 | pub indexes: Option<Vec<Vec<String>>>, |
| 31 | } |
| 32 | |
| 33 | #[derive(Debug, Deserialize)] |
| 34 | pub struct ColumnSchema { |
| 35 | pub r#type: serde_json::Value, |
| 36 | |
| 37 | #[serde(rename = "ephemeral")] |
| 38 | pub ephemeral: Option<bool>, |
| 39 | |
| 40 | #[serde(rename = "mutable")] |
| 41 | pub mutable: Option<bool>, |
| 42 | } |
| 43 | |
| 44 | #[derive(Debug, Default, Deserialize, Serialize)] |
| 45 | pub struct MonitorRequest { |
| 46 | #[serde(skip_serializing_if = "Option::is_none")] |
| 47 | pub columns: Option<Vec<String>>, |
| 48 | |
| 49 | #[serde(skip_serializing_if = "Option::is_none")] |
| 50 | pub select: Option<MonitorRequestSelect>, |
| 51 | } |
| 52 | |
| 53 | #[derive(Debug, Deserialize, Serialize)] |
| 54 | pub struct MonitorRequestSelect { |
| 55 | initial: Option<bool>, |
| 56 | insert: Option<bool>, |
| 57 | delete: Option<bool>, |
| 58 | modify: Option<bool>, |
| 59 | } |
| 60 | |
| 61 | pub type TableUpdate<T> = HashMap<String, TableUpdateRows<T>>; |
| 62 | pub type TableUpdateRows<T> = HashMap<String, T>; |
| 63 | |
| 64 | #[derive(Debug, Deserialize)] |
| 65 | pub struct RowUpdate<T> { |
| 66 | pub old: Option<T>, |
| 67 | pub new: Option<T>, |
| 68 | } |
| 69 | |
| 70 | #[derive(Debug)] |
| 71 | pub struct UpdateNotification<T> { |
| 72 | pub id: Option<String>, |
| 73 | pub message: TableUpdate<T>, |
| 74 | } |
| 75 | |
| 76 | impl<'de, T> Deserialize<'de> for UpdateNotification<T> |
| 77 | where |
| 78 | T: Deserialize<'de>, |
| 79 | { |
| 80 | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> |
| 81 | where |
| 82 | D: Deserializer<'de>, |
| 83 | { |
| 84 | // Define a visitor that carries a PhantomData for T. |
| 85 | struct UpdateNotificationVisitor<T> { |
| 86 | marker: PhantomData<T>, |
| 87 | } |
| 88 | |
| 89 | impl<'de, T> Visitor<'de> for UpdateNotificationVisitor<T> |
| 90 | where |
| 91 | T: Deserialize<'de>, |
| 92 | { |
| 93 | type Value = UpdateNotification<T>; |
| 94 | |
| 95 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { |
| 96 | formatter |
| 97 | .write_str("an array with two elements: Option<String> and a TableUpdate<T>") |
| 98 | } |
| 99 | |
| 100 | fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error> |
| 101 | where |
| 102 | A: SeqAccess<'de>, |
| 103 | { |
| 104 | let id: Option<String> = seq |
| 105 | .next_element()? |
| 106 | .ok_or_else(|| de::Error::invalid_length(0, &self))?; |
| 107 | let message: TableUpdate<T> = seq |
| 108 | .next_element()? |
| 109 | .ok_or_else(|| de::Error::invalid_length(1, &self))?; |
| 110 | |
| 111 | Ok(UpdateNotification { id, message }) |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | // Start deserializing using the visitor. |
| 116 | deserializer.deserialize_seq(UpdateNotificationVisitor { |
| 117 | marker: PhantomData, |
| 118 | }) |
| 119 | } |
| 120 | } |