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