use serde::{de::DeserializeOwned, Serialize};
use crate::error::Result;
pub trait CodecType: Clone + Send + Sync + 'static {
fn encode<T: Serialize>(value: &T) -> Result<Vec<u8>>;
fn decode<T: DeserializeOwned>(data: &[u8]) -> Result<T>;
}
#[cfg(feature = "msgpack")]
#[derive(Debug, Clone, Copy, Default)]
pub struct MsgPackCodec;
#[cfg(feature = "msgpack")]
impl CodecType for MsgPackCodec {
fn encode<T: Serialize>(value: &T) -> Result<Vec<u8>> {
Ok(rmp_serde::to_vec(value)?)
}
fn decode<T: DeserializeOwned>(data: &[u8]) -> Result<T> {
Ok(rmp_serde::from_slice(data)?)
}
}
#[cfg(feature = "json")]
#[derive(Debug, Clone, Copy, Default)]
pub struct JsonCodec;
#[cfg(feature = "json")]
impl CodecType for JsonCodec {
fn encode<T: Serialize>(value: &T) -> Result<Vec<u8>> {
Ok(serde_json::to_vec(value)?)
}
fn decode<T: DeserializeOwned>(data: &[u8]) -> Result<T> {
Ok(serde_json::from_slice(data)?)
}
}
pub trait Encode {
fn encode(&self) -> Result<Vec<u8>>;
}
pub trait Decode: Sized {
fn decode(data: &[u8]) -> Result<Self>;
}
pub trait Codec: Encode + Decode {}
#[cfg(feature = "msgpack")]
pub type DefaultCodec = MsgPackCodec;
#[cfg(all(feature = "json", not(feature = "msgpack")))]
pub type DefaultCodec = JsonCodec;
#[cfg(test)]
mod tests {
use super::*;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
struct TestMessage {
id: u64,
content: String,
}
#[cfg(feature = "msgpack")]
#[test]
fn test_msgpack_encode_decode_roundtrip() {
let msg = TestMessage {
id: 42,
content: "hello world".to_string(),
};
let encoded = MsgPackCodec::encode(&msg).unwrap();
let decoded: TestMessage = MsgPackCodec::decode(&encoded).unwrap();
assert_eq!(msg, decoded);
}
#[cfg(feature = "msgpack")]
#[test]
fn test_msgpack_is_compact() {
let msg = TestMessage {
id: 1,
content: "test".to_string(),
};
let encoded = MsgPackCodec::encode(&msg).unwrap();
assert!(!encoded.is_empty());
let json = serde_json::to_vec(&msg).unwrap();
assert!(encoded.len() <= json.len());
}
#[cfg(feature = "json")]
#[test]
fn test_json_encode_decode_roundtrip() {
let msg = TestMessage {
id: 42,
content: "hello world".to_string(),
};
let encoded = JsonCodec::encode(&msg).unwrap();
let decoded: TestMessage = JsonCodec::decode(&encoded).unwrap();
assert_eq!(msg, decoded);
}
#[cfg(feature = "json")]
#[test]
fn test_json_is_readable() {
let msg = TestMessage {
id: 1,
content: "test".to_string(),
};
let encoded = JsonCodec::encode(&msg).unwrap();
let json_str = std::str::from_utf8(&encoded).unwrap();
assert!(json_str.contains("\"id\":1"));
assert!(json_str.contains("\"content\":\"test\""));
}
}