1use std::{borrow::Cow, io};
2
3use crate::{
4 constants::SessionStateType,
5 io::ParseBuf,
6 misc::raw::{bytes::EofBytes, int::LenEnc, RawBytes},
7 proto::{MyDeserialize, MySerialize},
8};
9
10#[derive(Clone, Eq, PartialEq, Debug)]
24pub enum SessionStateChange<'a> {
25 IsTracked(bool),
26 Schema(Schema<'a>),
27 SystemVariables(Vec<SystemVariable<'a>>),
28 Gtids(Gtids<'a>),
29 TransactionCharacteristics(TransactionCharacteristics<'a>),
30 TransactionState(TransactionState<'a>),
31 Unsupported(Unsupported<'a>),
32}
33
34impl SessionStateChange<'_> {
35 pub fn into_owned(self) -> SessionStateChange<'static> {
36 match self {
37 SessionStateChange::SystemVariables(x) => SessionStateChange::SystemVariables(
38 x.into_iter().map(SystemVariable::into_owned).collect(),
39 ),
40 SessionStateChange::Schema(schema) => SessionStateChange::Schema(schema.into_owned()),
41 SessionStateChange::IsTracked(x) => SessionStateChange::IsTracked(x),
42 SessionStateChange::Gtids(x) => SessionStateChange::Gtids(x.into_owned()),
43 SessionStateChange::TransactionCharacteristics(x) => {
44 SessionStateChange::TransactionCharacteristics(x.into_owned())
45 }
46 SessionStateChange::TransactionState(x) => {
47 SessionStateChange::TransactionState(x.into_owned())
48 }
49 SessionStateChange::Unsupported(x) => SessionStateChange::Unsupported(x.into_owned()),
50 }
51 }
52}
53
54impl<'de> MyDeserialize<'de> for SessionStateChange<'de> {
55 const SIZE: Option<usize> = None;
56 type Ctx = SessionStateType;
57
58 fn deserialize(ty: SessionStateType, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
59 match ty {
60 SessionStateType::SESSION_TRACK_SYSTEM_VARIABLES => {
61 let mut vars = Vec::new();
62 while !buf.is_empty() {
63 vars.push(buf.parse_unchecked(())?);
64 }
65 Ok(SessionStateChange::SystemVariables(vars))
66 }
67 SessionStateType::SESSION_TRACK_SCHEMA => {
68 buf.parse_unchecked(()).map(SessionStateChange::Schema)
69 }
70 SessionStateType::SESSION_TRACK_STATE_CHANGE => {
71 let is_tracked: RawBytes<'_, LenEnc> = buf.parse_unchecked(())?;
72 Ok(SessionStateChange::IsTracked(is_tracked.as_bytes() == b"1"))
73 }
74 SessionStateType::SESSION_TRACK_GTIDS => {
76 Ok(SessionStateChange::Gtids(buf.parse_unchecked(())?))
77 }
78 SessionStateType::SESSION_TRACK_TRANSACTION_CHARACTERISTICS => Ok(
79 SessionStateChange::TransactionCharacteristics(buf.parse_unchecked(())?),
80 ),
81 SessionStateType::SESSION_TRACK_TRANSACTION_STATE => buf
82 .parse_unchecked(())
83 .map(SessionStateChange::TransactionState),
84 }
85 }
86}
87
88impl MySerialize for SessionStateChange<'_> {
89 fn serialize(&self, buf: &mut Vec<u8>) {
90 match self {
91 SessionStateChange::SystemVariables(vars) => {
92 for var in vars {
93 var.serialize(&mut *buf);
94 }
95 }
96 SessionStateChange::Schema(schema) => schema.serialize(buf),
97 SessionStateChange::IsTracked(is_tracked) => {
98 if *is_tracked {
99 b"\x011".serialize(buf);
100 } else {
101 b"\x010".serialize(buf);
102 }
103 }
104 SessionStateChange::Gtids(x) => x.serialize(buf),
105 SessionStateChange::TransactionCharacteristics(x) => x.serialize(buf),
106 SessionStateChange::TransactionState(x) => x.serialize(buf),
107 SessionStateChange::Unsupported(x) => x.serialize(buf),
108 }
109 }
110}
111
112#[derive(Debug, Clone, PartialEq, Eq, Hash)]
116pub struct Gtids<'a>(RawBytes<'a, EofBytes>);
117
118impl<'a> Gtids<'a> {
119 pub fn new(gtid_set: impl Into<Cow<'a, [u8]>>) -> Self {
120 Self(RawBytes::new(gtid_set))
121 }
122
123 pub fn as_bytes(&self) -> &[u8] {
125 self.0.as_bytes()
126 }
127
128 pub fn as_str(&self) -> Cow<'_, str> {
130 self.0.as_str()
131 }
132
133 pub fn into_owned(self) -> Gtids<'static> {
135 Gtids(self.0.into_owned())
136 }
137}
138
139impl<'de> MyDeserialize<'de> for Gtids<'de> {
140 const SIZE: Option<usize> = None;
141 type Ctx = ();
142
143 fn deserialize((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
144 buf.parse_unchecked(()).map(Self)
145 }
146}
147
148impl MySerialize for Gtids<'_> {
149 fn serialize(&self, buf: &mut Vec<u8>) {
150 self.0.serialize(buf);
151 }
152}
153
154#[derive(Debug, Clone, PartialEq, Eq, Hash)]
158pub struct Schema<'a>(RawBytes<'a, LenEnc>);
159
160impl<'a> Schema<'a> {
161 pub fn new(schema_name: impl Into<Cow<'a, [u8]>>) -> Self {
162 Self(RawBytes::new(schema_name))
163 }
164
165 pub fn as_bytes(&self) -> &[u8] {
167 self.0.as_bytes()
168 }
169
170 pub fn as_str(&self) -> Cow<'_, str> {
172 self.0.as_str()
173 }
174
175 pub fn into_owned(self) -> Schema<'static> {
177 Schema(self.0.into_owned())
178 }
179}
180
181impl<'de> MyDeserialize<'de> for Schema<'de> {
182 const SIZE: Option<usize> = None;
183 type Ctx = ();
184
185 fn deserialize((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
186 buf.parse_unchecked(()).map(Self)
187 }
188}
189
190impl MySerialize for Schema<'_> {
191 fn serialize(&self, buf: &mut Vec<u8>) {
192 self.0.serialize(buf);
193 }
194}
195
196#[derive(Debug, Clone, PartialEq, Eq, Hash)]
199pub struct SystemVariable<'a> {
200 name: RawBytes<'a, LenEnc>,
201 value: RawBytes<'a, LenEnc>,
202}
203
204impl<'a> SystemVariable<'a> {
205 pub fn new(name: impl Into<Cow<'a, [u8]>>, value: impl Into<Cow<'a, [u8]>>) -> Self {
206 Self {
207 name: RawBytes::new(name),
208 value: RawBytes::new(value),
209 }
210 }
211
212 pub fn name_bytes(&self) -> &[u8] {
214 self.name.as_bytes()
215 }
216
217 pub fn name_str(&self) -> Cow<'_, str> {
219 self.name.as_str()
220 }
221
222 pub fn value_bytes(&self) -> &[u8] {
224 self.value.as_bytes()
225 }
226
227 pub fn value_str(&self) -> Cow<'_, str> {
229 self.value.as_str()
230 }
231
232 pub fn into_owned(self) -> SystemVariable<'static> {
234 SystemVariable {
235 name: self.name.into_owned(),
236 value: self.value.into_owned(),
237 }
238 }
239}
240
241impl<'de> MyDeserialize<'de> for SystemVariable<'de> {
242 const SIZE: Option<usize> = None;
243 type Ctx = ();
244
245 fn deserialize((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
246 Ok(Self {
247 name: buf.parse_unchecked(())?,
248 value: buf.parse_unchecked(())?,
249 })
250 }
251}
252
253impl MySerialize for SystemVariable<'_> {
254 fn serialize(&self, buf: &mut Vec<u8>) {
255 self.name.serialize(&mut *buf);
256 self.value.serialize(buf);
257 }
258}
259
260#[derive(Debug, Clone, PartialEq, Eq, Hash)]
265pub struct TransactionCharacteristics<'a>(RawBytes<'a, LenEnc>);
266
267impl<'a> TransactionCharacteristics<'a> {
268 pub fn new(value: impl Into<Cow<'a, [u8]>>) -> Self {
269 Self(RawBytes::new(value))
270 }
271
272 pub fn as_bytes(&self) -> &[u8] {
274 self.0.as_bytes()
275 }
276
277 pub fn as_str(&self) -> Cow<'_, str> {
279 self.0.as_str()
280 }
281
282 pub fn into_owned(self) -> TransactionCharacteristics<'static> {
284 TransactionCharacteristics(self.0.into_owned())
285 }
286}
287
288impl<'de> MyDeserialize<'de> for TransactionCharacteristics<'de> {
289 const SIZE: Option<usize> = None;
290 type Ctx = ();
291
292 fn deserialize((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
293 buf.parse_unchecked(()).map(Self)
294 }
295}
296
297impl MySerialize for TransactionCharacteristics<'_> {
298 fn serialize(&self, buf: &mut Vec<u8>) {
299 self.0.serialize(buf);
300 }
301}
302
303#[derive(Debug, Clone, PartialEq, Eq, Hash)]
308pub struct TransactionState<'a>(RawBytes<'a, LenEnc>);
309
310impl<'a> TransactionState<'a> {
311 pub fn new(value: impl Into<Cow<'a, [u8]>>) -> Self {
312 Self(RawBytes::new(value))
313 }
314
315 pub fn as_bytes(&self) -> &[u8] {
317 self.0.as_bytes()
318 }
319
320 pub fn as_str(&self) -> Cow<'_, str> {
322 self.0.as_str()
323 }
324
325 pub fn into_owned(self) -> TransactionState<'static> {
327 TransactionState(self.0.into_owned())
328 }
329}
330
331impl<'de> MyDeserialize<'de> for TransactionState<'de> {
332 const SIZE: Option<usize> = None;
333 type Ctx = ();
334
335 fn deserialize((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
336 buf.parse_unchecked(()).map(Self)
337 }
338}
339
340impl MySerialize for TransactionState<'_> {
341 fn serialize(&self, buf: &mut Vec<u8>) {
342 self.0.serialize(buf);
343 }
344}
345
346#[derive(Debug, Clone, PartialEq, Eq, Hash)]
348pub struct Unsupported<'a>(RawBytes<'a, LenEnc>);
349
350impl<'a> Unsupported<'a> {
351 pub fn new(value: impl Into<Cow<'a, [u8]>>) -> Self {
352 Self(RawBytes::new(value))
353 }
354
355 pub fn as_bytes(&self) -> &[u8] {
357 self.0.as_bytes()
358 }
359
360 pub fn as_str(&self) -> Cow<'_, str> {
362 self.0.as_str()
363 }
364
365 pub fn into_owned(self) -> Unsupported<'static> {
367 Unsupported(self.0.into_owned())
368 }
369}
370
371impl<'de> MyDeserialize<'de> for Unsupported<'de> {
372 const SIZE: Option<usize> = None;
373 type Ctx = ();
374
375 fn deserialize((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
376 buf.parse_unchecked(()).map(Self)
377 }
378}
379
380impl MySerialize for Unsupported<'_> {
381 fn serialize(&self, buf: &mut Vec<u8>) {
382 self.0.serialize(buf);
383 }
384}