mysql_common/binlog/
jsondiff.rs
1use std::{borrow::Cow, convert::TryFrom, io};
10
11use crate::{
12 io::ParseBuf,
13 misc::raw::{bytes::LenEnc, Const, RawBytes, RawInt},
14 proto::MyDeserialize,
15};
16
17use super::jsonb;
18
19#[allow(non_camel_case_types)]
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
22#[repr(u8)]
23pub enum JsonDiffOperation {
24 REPLACE,
26 INSERT,
28 REMOVE,
30}
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, thiserror::Error)]
33#[error("Unknown JsonDiff operation {}", _0)]
34#[repr(transparent)]
35pub struct UnknownJsonDiffOperation(pub u8);
36
37impl From<UnknownJsonDiffOperation> for u8 {
38 fn from(x: UnknownJsonDiffOperation) -> Self {
39 x.0
40 }
41}
42
43impl TryFrom<u8> for JsonDiffOperation {
44 type Error = UnknownJsonDiffOperation;
45
46 fn try_from(value: u8) -> Result<Self, Self::Error> {
47 match value {
48 0 => Ok(Self::REPLACE),
49 1 => Ok(Self::INSERT),
50 2 => Ok(Self::REMOVE),
51 x => Err(UnknownJsonDiffOperation(x)),
52 }
53 }
54}
55
56#[derive(Debug, Clone, PartialEq)]
61pub struct JsonDiff<'a> {
62 path: RawBytes<'a, LenEnc>,
63 operation: Const<JsonDiffOperation, u8>,
64 value: Option<jsonb::Value<'a>>,
65}
66
67impl<'a> JsonDiff<'a> {
68 pub fn path(&'a self) -> &'a [u8] {
70 self.path.as_bytes()
71 }
72
73 pub fn path_str(&'a self) -> Cow<'a, str> {
75 self.path.as_str()
76 }
77
78 pub fn operation(&self) -> JsonDiffOperation {
80 *self.operation
81 }
82
83 pub fn value(&'a self) -> Option<&'a jsonb::Value<'a>> {
85 self.value.as_ref()
86 }
87
88 pub fn into_owned(self) -> JsonDiff<'static> {
90 JsonDiff {
91 path: self.path.into_owned(),
92 operation: self.operation,
93 value: self.value.map(|x| x.into_owned()),
94 }
95 }
96}
97
98impl<'de> MyDeserialize<'de> for JsonDiff<'de> {
99 const SIZE: Option<usize> = None;
100 type Ctx = ();
101
102 fn deserialize((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
103 let operation: Const<JsonDiffOperation, u8> = buf.parse(())?;
104 let path = buf.parse(())?;
105 let value = if *operation != JsonDiffOperation::REMOVE {
106 let len: RawInt<LenEnc> = buf.parse(())?;
107 let mut value: ParseBuf = buf.parse(*len as usize)?;
108 Some(value.parse(())?)
109 } else {
110 None
111 };
112
113 Ok(Self {
114 path,
115 operation,
116 value,
117 })
118 }
119}