righ_ovsdb/protocol/
codec.rs1use tokio_util::{
2 bytes::{Buf, BufMut, BytesMut},
3 codec::{Decoder, Encoder},
4};
5
6use super::Message;
7
8#[derive(Debug)]
9enum BufferTag {
10 Obj,
11 Str,
12}
13
14#[derive(thiserror::Error, Debug)]
16pub enum CodecError {
17 #[error("Error encoding data")]
19 Encode(#[source] serde_json::Error),
20 #[error("Error decoding data")]
22 Decode(#[source] serde_json::Error),
23 #[error("Corrupted data stream: {0}")]
25 DataStreamCorrupted(String),
26 #[error("Unexpected IO Error")]
28 Io(#[from] std::io::Error),
29}
30
31#[derive(Default, Debug)]
36pub struct Codec {
37 data: Vec<u8>,
38 tags: Vec<BufferTag>,
39}
40
41#[allow(missing_docs)]
42impl Codec {
43 pub fn new() -> Self {
45 Self::default()
46 }
47
48 pub fn try_decode_message(
49 &mut self,
50 src: &[u8],
51 ) -> Result<(Option<Message>, usize), CodecError> {
52 let mut offset = 0;
53
54 while offset < src.len() {
55 match self.tags.last() {
56 Some(BufferTag::Str) => {
57 if let Some(n) = &src[offset..].iter().position(|&c| c == b'"') {
58 offset += n + 1;
59 self.tags.pop();
60 continue;
61 } else {
62 break;
63 }
64 }
65 Some(BufferTag::Obj) => {
66 if let Some(n) = &src[offset..]
67 .iter()
68 .position(|&c| [b'"', b'{', b'}'].contains(&c))
69 {
70 offset += n;
71 let char = src[offset];
72 offset += 1;
73 match &char {
74 b'"' => self.tags.push(BufferTag::Str),
75 b'{' => self.tags.push(BufferTag::Obj),
76 b'}' => {
77 self.tags.pop();
78 if self.tags.is_empty() {
79 self.data.extend_from_slice(src);
81 let msg: Message =
87 match serde_json::from_slice(&self.data.to_vec()) {
88 Ok(msg) => msg,
89 Err(err) => {
90 eprintln!("Failed to decode message: {err}");
91 return Err(CodecError::Decode(err));
92 }
93 };
94 self.data.clear();
95 return Ok((Some(msg), offset));
96 }
97 }
98 _ => unreachable!(),
99 }
100 } else {
101 break;
102 }
103 }
104 None => {
105 if let Some(n) = &src[offset..].iter().position(|&c| c == b'{') {
106 offset += n + 1;
107 self.tags.push(BufferTag::Obj);
108 } else {
109 return Err(CodecError::DataStreamCorrupted(
110 "No openening tag found in data stream.".to_string(),
111 ));
112 }
113 }
114 }
115 }
116
117 self.data.extend_from_slice(src);
118 Ok((None, src.len()))
119 }
120}
121
122impl Decoder for Codec {
123 type Item = Message;
124 type Error = CodecError;
125
126 fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
127 let (res, consume) = self.try_decode_message(src.chunk())?;
128 src.advance(consume);
129 Ok(res)
130 }
131}
132
133impl Encoder<Message> for Codec {
134 type Error = CodecError;
135
136 fn encode(&mut self, item: Message, dst: &mut BytesMut) -> Result<(), Self::Error> {
137 let data = serde_json::to_vec(&item).map_err(CodecError::Encode)?;
138 dst.reserve(data.len());
139 dst.put_slice(&data);
140 println!(
141 "Sent: {}",
142 String::from_utf8(dst.clone().to_vec()).expect("message encode")
143 );
144 Ok(())
145 }
146}