1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
/// A trait describing how to encode/decode a websocket message. This is provided to allow users to
/// use their own websocket library instead of the default one.
///
/// Typically the `Input` and `Output` message types will be the same, but they're defined
/// separately to allow for flexibility (e.g., if the underlying websocket client uses distinct
/// types for sending vs receiving, like validating UTF-8 only for outgoing messages).
///
/// # Example
///
/// ```
/// use vtubestudio::codec::MessageCodec;
///
/// // Custom websocket message type
/// pub enum Message {
/// Text(String),
/// Binary(Vec<u8>),
/// Ping(Vec<u8>),
/// Pong(Vec<u8>),
/// Close,
/// }
///
/// #[derive(Debug, Clone)]
/// pub struct MyCustomMessageCodec;
///
/// impl MessageCodec for MyCustomMessageCodec {
/// type Input = Message;
/// type Output = Message;
/// type Error = std::convert::Infallible;
///
/// fn decode(msg: Self::Input) -> Result<Option<String>, Self::Error> {
/// Ok(match msg {
/// Message::Text(s) => Some(s),
/// _ => None,
/// })
/// }
///
/// fn encode(text: String) -> Self::Output {
/// Message::Text(text)
/// }
/// }
/// ```
pub trait MessageCodec {
/// The underlying incoming message type.
type Input;
/// The underlying outgoing message type.
type Output;
/// Error type returned on decode failure.
type Error;
/// Decodes a websocket text message. `None` values are ignored (E.g., for disregarding ping
/// messages).
fn decode(msg: Self::Input) -> Result<Option<String>, Self::Error>;
/// Converts a string into a websocket text message.
fn encode(text: String) -> Self::Output;
}
crate::cfg_feature! {
#![feature = "tokio-tungstenite"]
/// A codec describing how to encode/decode
/// [`tungstenite::Message`](::tokio_tungstenite::tungstenite::Message)s.
#[derive(Debug, Clone)]
pub struct TungsteniteCodec;
}
#[cfg(feature = "tokio-tungstenite")]
mod tungstenite {
use super::*;
use std::convert::Infallible;
use tokio_tungstenite::tungstenite;
impl MessageCodec for TungsteniteCodec {
type Input = tungstenite::Message;
type Output = tungstenite::Message;
type Error = Infallible;
fn decode(msg: Self::Input) -> Result<Option<String>, Self::Error> {
Ok(match msg {
Self::Input::Text(s) => Some(s),
_ => None,
})
}
fn encode(text: String) -> Self::Output {
Self::Output::Text(text)
}
}
}