1use std::fmt;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
9pub enum WsMessage {
10 Text(String),
11 Binary(Vec<u8>),
12}
13
14#[derive(Debug)]
16pub enum EncodeError {
17 Json(serde_json::Error),
18 Custom(String),
19}
20
21impl fmt::Display for EncodeError {
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 match self {
24 EncodeError::Json(e) => write!(f, "JSON encode error: {e}"),
25 EncodeError::Custom(msg) => write!(f, "encode error: {msg}"),
26 }
27 }
28}
29
30impl std::error::Error for EncodeError {}
31
32impl From<serde_json::Error> for EncodeError {
33 fn from(e: serde_json::Error) -> Self {
34 EncodeError::Json(e)
35 }
36}
37
38#[derive(Debug)]
40pub enum DecodeError {
41 Json(serde_json::Error),
42 UnexpectedBinary,
43 UnexpectedText,
44 InvalidData(String),
45}
46
47impl fmt::Display for DecodeError {
48 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49 match self {
50 DecodeError::Json(e) => write!(f, "JSON decode error: {e}"),
51 DecodeError::UnexpectedBinary => write!(f, "expected text frame, got binary"),
52 DecodeError::UnexpectedText => write!(f, "expected binary frame, got text"),
53 DecodeError::InvalidData(msg) => write!(f, "invalid data: {msg}"),
54 }
55 }
56}
57
58impl std::error::Error for DecodeError {}
59
60impl From<serde_json::Error> for DecodeError {
61 fn from(e: serde_json::Error) -> Self {
62 DecodeError::Json(e)
63 }
64}
65
66pub trait WsCodec: Sized {
72 fn encode(&self) -> Result<WsMessage, EncodeError>;
73 fn decode(msg: WsMessage) -> Result<Self, DecodeError>;
74}
75
76impl<T: serde::Serialize + serde::de::DeserializeOwned> WsCodec for T {
78 fn encode(&self) -> Result<WsMessage, EncodeError> {
79 Ok(WsMessage::Text(serde_json::to_string(self)?))
80 }
81
82 fn decode(msg: WsMessage) -> Result<Self, DecodeError> {
83 match msg {
84 WsMessage::Text(text) => Ok(serde_json::from_str(&text)?),
85 WsMessage::Binary(_) => Err(DecodeError::UnexpectedBinary),
86 }
87 }
88}
89
90pub enum NoMessages {}
96
97impl Clone for NoMessages {
98 fn clone(&self) -> Self {
99 match *self {}
100 }
101}
102
103impl WsCodec for NoMessages {
104 fn encode(&self) -> Result<WsMessage, EncodeError> {
105 match *self {}
106 }
107
108 fn decode(_msg: WsMessage) -> Result<Self, DecodeError> {
109 Err(DecodeError::InvalidData(
110 "this endpoint does not accept messages in this direction".into(),
111 ))
112 }
113}