1use crate::primitives::RawJson;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum MsgKind {
12 Request,
13 Response,
14}
15
16#[derive(Debug, Clone, PartialEq)]
17pub struct Message {
18 pub msg_kind: MsgKind,
19 pub frames: Vec<Frame>,
20}
21
22pub mod frame_type {
25 pub const END: u8 = 0x00;
26 pub const REQ_HEADER: u8 = 0x01;
27 pub const PUSH_COMMIT: u8 = 0x02;
28 pub const PULL_HEADER: u8 = 0x03;
29 pub const SUBSCRIPTION: u8 = 0x04;
30 pub const RESP_HEADER: u8 = 0x10;
31 pub const PUSH_RESULT: u8 = 0x11;
32 pub const SUB_START: u8 = 0x12;
33 pub const COMMIT: u8 = 0x13;
34 pub const SEGMENT_REF: u8 = 0x14;
35 pub const SEGMENT_INLINE: u8 = 0x15;
36 pub const SUB_END: u8 = 0x16;
37 pub const LEASE: u8 = 0x19;
38 pub const ERROR: u8 = 0x1F;
39
40 pub const REQUEST_TYPES: &[u8] = &[REQ_HEADER, PUSH_COMMIT, PULL_HEADER, SUBSCRIPTION];
41 pub const RESPONSE_TYPES: &[u8] = &[
42 RESP_HEADER,
43 PUSH_RESULT,
44 SUB_START,
45 COMMIT,
46 SEGMENT_REF,
47 SEGMENT_INLINE,
48 SUB_END,
49 LEASE,
50 ERROR,
51 ];
52}
53
54#[derive(Debug, Clone, Copy, PartialEq, Eq)]
55pub enum Op {
56 Upsert,
57 Delete,
58}
59
60impl Op {
61 pub fn name(self) -> &'static str {
62 match self {
63 Op::Upsert => "upsert",
64 Op::Delete => "delete",
65 }
66 }
67}
68
69#[derive(Debug, Clone, Copy, PartialEq, Eq)]
70pub enum SubStatus {
71 Active,
72 Revoked,
73 Reset,
74}
75
76impl SubStatus {
77 pub fn name(self) -> &'static str {
78 match self {
79 SubStatus::Active => "active",
80 SubStatus::Revoked => "revoked",
81 SubStatus::Reset => "reset",
82 }
83 }
84}
85
86#[derive(Debug, Clone, Copy, PartialEq, Eq)]
87pub enum PushStatus {
88 Applied,
89 Cached,
90 Rejected,
91}
92
93impl PushStatus {
94 pub fn name(self) -> &'static str {
95 match self {
96 PushStatus::Applied => "applied",
97 PushStatus::Cached => "cached",
98 PushStatus::Rejected => "rejected",
99 }
100 }
101}
102
103#[derive(Debug, Clone, Copy, PartialEq, Eq)]
104pub enum MediaType {
105 Rows,
106 Sqlite,
107}
108
109impl MediaType {
110 pub fn name(self) -> &'static str {
111 match self {
112 MediaType::Rows => "rows",
113 MediaType::Sqlite => "sqlite",
114 }
115 }
116}
117
118#[derive(Debug, Clone, PartialEq)]
120pub struct Operation {
121 pub table: String,
122 pub row_id: String,
123 pub op: Op,
124 pub base_version: Option<i64>,
125 pub payload: Option<Vec<u8>>,
127}
128
129#[derive(Debug, Clone, PartialEq)]
131pub struct Change {
132 pub table_index: u16,
133 pub row_id: String,
134 pub op: Op,
135 pub row_version: Option<i64>,
136 pub scopes: Vec<(String, String)>,
137 pub row: Option<Vec<u8>>,
139}
140
141#[derive(Debug, Clone, PartialEq)]
143pub enum OpResult {
144 Applied {
145 op_index: i32,
146 },
147 Conflict {
148 op_index: i32,
149 code: String,
150 message: String,
151 server_version: i64,
152 server_row: Vec<u8>,
153 },
154 Error {
155 op_index: i32,
156 code: String,
157 message: String,
158 retryable: bool,
159 },
160}
161
162#[derive(Debug, Clone, PartialEq)]
163pub enum Frame {
164 ReqHeader {
165 client_id: String,
166 schema_version: i32,
167 },
168 PushCommit {
169 client_commit_id: String,
170 operations: Vec<Operation>,
171 },
172 PullHeader {
173 limit_commits: i32,
174 limit_snapshot_rows: i32,
175 max_snapshot_pages: i32,
176 accept: u8,
177 },
178 Subscription {
179 id: String,
180 table: String,
181 scopes: Vec<(String, Vec<String>)>,
182 params: Option<RawJson>,
183 cursor: i64,
184 bootstrap_state: Option<RawJson>,
185 },
186 RespHeader {
187 required_schema_version: Option<i32>,
188 latest_schema_version: Option<i32>,
189 },
190 Lease {
192 lease_id: String,
193 expires_at_ms: i64,
194 },
195 PushResult {
196 client_commit_id: String,
197 status: PushStatus,
198 commit_seq: Option<i64>,
199 results: Vec<OpResult>,
200 },
201 SubStart {
202 id: String,
203 status: SubStatus,
204 reason_code: String,
205 effective_scopes: Vec<(String, Vec<String>)>,
206 bootstrap: bool,
207 },
208 Commit {
209 commit_seq: i64,
210 created_at_ms: i64,
211 actor_id: String,
212 tables: Vec<String>,
213 changes: Vec<Change>,
214 },
215 SegmentRef {
216 segment_id: String,
217 media_type: MediaType,
218 table: String,
219 byte_length: i64,
220 row_count: i64,
221 as_of_commit_seq: i64,
222 scope_digest: String,
223 row_cursor: Option<String>,
224 next_row_cursor: Option<String>,
225 url: Option<String>,
226 url_expires_at_ms: Option<i64>,
227 },
228 SegmentInline { payload: Vec<u8> },
231 SubEnd {
232 next_cursor: i64,
233 bootstrap_state: Option<RawJson>,
234 },
235 Error {
236 code: String,
237 message: String,
238 category: String,
239 retryable: bool,
240 recommended_action: String,
241 details: Option<RawJson>,
242 },
243 Unknown { frame_type: u8, payload: Vec<u8> },
246}