pub mod envelope;
pub mod frame;
pub mod payloads;
#[cfg(feature = "build")]
pub mod build;
pub use envelope::{Agent, AgentId};
pub use frame::Kind;
use serde::de::DeserializeOwned;
use serde::Serialize;
pub trait WireCodec: Clone + Send + Sync + 'static {
fn name(&self) -> &'static str;
fn encode<T: Serialize>(&self, value: &T) -> Result<Vec<u8>, Box<dyn std::error::Error + Send + Sync>>;
fn encode_into<T: Serialize>(
&self,
value: &T,
buf: &mut Vec<u8>,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
buf.extend_from_slice(&self.encode(value)?);
Ok(())
}
fn decode<T: DeserializeOwned>(&self, bytes: &[u8]) -> Result<T, Box<dyn std::error::Error + Send + Sync>>;
fn is_text(&self) -> bool {
false
}
}
#[cfg(feature = "json")]
#[derive(Debug, Clone, Copy, Default)]
pub struct JsonCodec;
#[cfg(feature = "json")]
impl WireCodec for JsonCodec {
fn name(&self) -> &'static str {
"json"
}
fn encode<T: Serialize>(&self, value: &T) -> Result<Vec<u8>, Box<dyn std::error::Error + Send + Sync>> {
serde_json::to_vec(value).map_err(Into::into)
}
fn encode_into<T: Serialize>(
&self,
value: &T,
buf: &mut Vec<u8>,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
serde_json::to_writer(buf, value).map_err(Into::into)
}
fn decode<T: DeserializeOwned>(&self, bytes: &[u8]) -> Result<T, Box<dyn std::error::Error + Send + Sync>> {
serde_json::from_slice(bytes).map_err(Into::into)
}
fn is_text(&self) -> bool {
true
}
}
#[cfg(feature = "msgpack")]
#[derive(Debug, Clone, Copy, Default)]
pub struct MsgPackCodec;
#[cfg(feature = "msgpack")]
impl WireCodec for MsgPackCodec {
fn name(&self) -> &'static str {
"msgpack"
}
fn encode<T: Serialize>(&self, value: &T) -> Result<Vec<u8>, Box<dyn std::error::Error + Send + Sync>> {
rmp_serde::to_vec(value).map_err(Into::into)
}
fn encode_into<T: Serialize>(
&self,
value: &T,
buf: &mut Vec<u8>,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
rmp_serde::encode::write(buf, value).map_err(Into::into)
}
fn decode<T: DeserializeOwned>(&self, bytes: &[u8]) -> Result<T, Box<dyn std::error::Error + Send + Sync>> {
rmp_serde::from_slice(bytes).map_err(Into::into)
}
}
#[cfg(all(test, feature = "json"))]
mod tests {
use super::*;
use serde::Deserialize;
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Move {
player: u32,
dx: f32,
}
#[test]
fn a_value_survives_a_round_trip() {
let codec = JsonCodec;
let original = Move { player: 7, dx: -1.5 };
let bytes = codec.encode(&original).unwrap();
let decoded: Move = codec.decode(&bytes).unwrap();
assert_eq!(decoded, original);
}
#[test]
fn decoding_the_wrong_shape_is_an_error_not_a_panic() {
let codec = JsonCodec;
let bytes = codec.encode(&"not a move").unwrap();
assert!(codec.decode::<Move>(&bytes).is_err());
}
#[test]
fn the_name_reaches_error_messages() {
assert_eq!(JsonCodec.name(), "json");
}
}