use std::{borrow::Cow, io};
use crate::{
constants::SessionStateType,
io::ParseBuf,
misc::raw::{bytes::EofBytes, int::LenEnc, RawBytes},
proto::{MyDeserialize, MySerialize},
};
#[derive(Clone, Eq, PartialEq, Debug)]
pub enum SessionStateChange<'a> {
IsTracked(bool),
Schema(Schema<'a>),
SystemVariables(Vec<SystemVariable<'a>>),
Gtids(Gtids<'a>),
TransactionCharacteristics(TransactionCharacteristics<'a>),
TransactionState(TransactionState<'a>),
Unsupported(Unsupported<'a>),
}
impl<'a> SessionStateChange<'a> {
pub fn into_owned(self) -> SessionStateChange<'static> {
match self {
SessionStateChange::SystemVariables(x) => SessionStateChange::SystemVariables(
x.into_iter().map(SystemVariable::into_owned).collect(),
),
SessionStateChange::Schema(schema) => SessionStateChange::Schema(schema.into_owned()),
SessionStateChange::IsTracked(x) => SessionStateChange::IsTracked(x),
SessionStateChange::Gtids(x) => SessionStateChange::Gtids(x.into_owned()),
SessionStateChange::TransactionCharacteristics(x) => {
SessionStateChange::TransactionCharacteristics(x.into_owned())
}
SessionStateChange::TransactionState(x) => {
SessionStateChange::TransactionState(x.into_owned())
}
SessionStateChange::Unsupported(x) => SessionStateChange::Unsupported(x.into_owned()),
}
}
}
impl<'de> MyDeserialize<'de> for SessionStateChange<'de> {
const SIZE: Option<usize> = None;
type Ctx = SessionStateType;
fn deserialize(ty: SessionStateType, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
match ty {
SessionStateType::SESSION_TRACK_SYSTEM_VARIABLES => {
let mut vars = Vec::new();
while !buf.is_empty() {
vars.push(buf.parse_unchecked(())?);
}
Ok(SessionStateChange::SystemVariables(vars))
}
SessionStateType::SESSION_TRACK_SCHEMA => {
buf.parse_unchecked(()).map(SessionStateChange::Schema)
}
SessionStateType::SESSION_TRACK_STATE_CHANGE => {
let is_tracked: RawBytes<'_, LenEnc> = buf.parse_unchecked(())?;
Ok(SessionStateChange::IsTracked(is_tracked.as_bytes() == b"1"))
}
SessionStateType::SESSION_TRACK_GTIDS => {
Ok(SessionStateChange::Gtids(buf.parse_unchecked(())?))
}
SessionStateType::SESSION_TRACK_TRANSACTION_CHARACTERISTICS => Ok(
SessionStateChange::TransactionCharacteristics(buf.parse_unchecked(())?),
),
SessionStateType::SESSION_TRACK_TRANSACTION_STATE => buf
.parse_unchecked(())
.map(SessionStateChange::TransactionState),
}
}
}
impl MySerialize for SessionStateChange<'_> {
fn serialize(&self, buf: &mut Vec<u8>) {
match self {
SessionStateChange::SystemVariables(vars) => {
for var in vars {
var.serialize(&mut *buf);
}
}
SessionStateChange::Schema(schema) => schema.serialize(buf),
SessionStateChange::IsTracked(is_tracked) => {
if *is_tracked {
b"\x011".serialize(buf);
} else {
b"\x010".serialize(buf);
}
}
SessionStateChange::Gtids(x) => x.serialize(buf),
SessionStateChange::TransactionCharacteristics(x) => x.serialize(buf),
SessionStateChange::TransactionState(x) => x.serialize(buf),
SessionStateChange::Unsupported(x) => x.serialize(buf),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Gtids<'a>(RawBytes<'a, EofBytes>);
impl<'a> Gtids<'a> {
pub fn new(gtid_set: impl Into<Cow<'a, [u8]>>) -> Self {
Self(RawBytes::new(gtid_set))
}
pub fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
pub fn as_str(&self) -> Cow<'_, str> {
self.0.as_str()
}
pub fn into_owned(self) -> Gtids<'static> {
Gtids(self.0.into_owned())
}
}
impl<'de> MyDeserialize<'de> for Gtids<'de> {
const SIZE: Option<usize> = None;
type Ctx = ();
fn deserialize((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
buf.parse_unchecked(()).map(Self)
}
}
impl MySerialize for Gtids<'_> {
fn serialize(&self, buf: &mut Vec<u8>) {
self.0.serialize(buf);
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Schema<'a>(RawBytes<'a, LenEnc>);
impl<'a> Schema<'a> {
pub fn new(schema_name: impl Into<Cow<'a, [u8]>>) -> Self {
Self(RawBytes::new(schema_name))
}
pub fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
pub fn as_str(&self) -> Cow<'_, str> {
self.0.as_str()
}
pub fn into_owned(self) -> Schema<'static> {
Schema(self.0.into_owned())
}
}
impl<'de> MyDeserialize<'de> for Schema<'de> {
const SIZE: Option<usize> = None;
type Ctx = ();
fn deserialize((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
buf.parse_unchecked(()).map(Self)
}
}
impl MySerialize for Schema<'_> {
fn serialize(&self, buf: &mut Vec<u8>) {
self.0.serialize(buf);
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SystemVariable<'a> {
name: RawBytes<'a, LenEnc>,
value: RawBytes<'a, LenEnc>,
}
impl<'a> SystemVariable<'a> {
pub fn new(name: impl Into<Cow<'a, [u8]>>, value: impl Into<Cow<'a, [u8]>>) -> Self {
Self {
name: RawBytes::new(name),
value: RawBytes::new(value),
}
}
pub fn name_bytes(&self) -> &[u8] {
self.name.as_bytes()
}
pub fn name_str(&self) -> Cow<'_, str> {
self.name.as_str()
}
pub fn value_bytes(&self) -> &[u8] {
self.value.as_bytes()
}
pub fn value_str(&self) -> Cow<'_, str> {
self.value.as_str()
}
pub fn into_owned(self) -> SystemVariable<'static> {
SystemVariable {
name: self.name.into_owned(),
value: self.value.into_owned(),
}
}
}
impl<'de> MyDeserialize<'de> for SystemVariable<'de> {
const SIZE: Option<usize> = None;
type Ctx = ();
fn deserialize((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
Ok(Self {
name: buf.parse_unchecked(())?,
value: buf.parse_unchecked(())?,
})
}
}
impl MySerialize for SystemVariable<'_> {
fn serialize(&self, buf: &mut Vec<u8>) {
self.name.serialize(&mut *buf);
self.value.serialize(buf);
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct TransactionCharacteristics<'a>(RawBytes<'a, LenEnc>);
impl<'a> TransactionCharacteristics<'a> {
pub fn new(value: impl Into<Cow<'a, [u8]>>) -> Self {
Self(RawBytes::new(value))
}
pub fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
pub fn as_str(&self) -> Cow<'_, str> {
self.0.as_str()
}
pub fn into_owned(self) -> TransactionCharacteristics<'static> {
TransactionCharacteristics(self.0.into_owned())
}
}
impl<'de> MyDeserialize<'de> for TransactionCharacteristics<'de> {
const SIZE: Option<usize> = None;
type Ctx = ();
fn deserialize((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
buf.parse_unchecked(()).map(Self)
}
}
impl MySerialize for TransactionCharacteristics<'_> {
fn serialize(&self, buf: &mut Vec<u8>) {
self.0.serialize(buf);
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct TransactionState<'a>(RawBytes<'a, LenEnc>);
impl<'a> TransactionState<'a> {
pub fn new(value: impl Into<Cow<'a, [u8]>>) -> Self {
Self(RawBytes::new(value))
}
pub fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
pub fn as_str(&self) -> Cow<'_, str> {
self.0.as_str()
}
pub fn into_owned(self) -> TransactionState<'static> {
TransactionState(self.0.into_owned())
}
}
impl<'de> MyDeserialize<'de> for TransactionState<'de> {
const SIZE: Option<usize> = None;
type Ctx = ();
fn deserialize((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
buf.parse_unchecked(()).map(Self)
}
}
impl MySerialize for TransactionState<'_> {
fn serialize(&self, buf: &mut Vec<u8>) {
self.0.serialize(buf);
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Unsupported<'a>(RawBytes<'a, LenEnc>);
impl<'a> Unsupported<'a> {
pub fn new(value: impl Into<Cow<'a, [u8]>>) -> Self {
Self(RawBytes::new(value))
}
pub fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
pub fn as_str(&self) -> Cow<'_, str> {
self.0.as_str()
}
pub fn into_owned(self) -> Unsupported<'static> {
Unsupported(self.0.into_owned())
}
}
impl<'de> MyDeserialize<'de> for Unsupported<'de> {
const SIZE: Option<usize> = None;
type Ctx = ();
fn deserialize((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
buf.parse_unchecked(()).map(Self)
}
}
impl MySerialize for Unsupported<'_> {
fn serialize(&self, buf: &mut Vec<u8>) {
self.0.serialize(buf);
}
}