use std::sync::Arc;
use bytes::Bytes;
use serde::Serialize;
use crate::error::Result;
use crate::frame::Codec as FrameCodec;
pub trait Codec: Send + Sync {
fn frame_codec(&self) -> FrameCodec;
fn encode_value(&self, value: &serde_json::Value) -> Result<Bytes>;
fn decode_value(&self, bytes: &[u8]) -> Result<serde_json::Value>;
}
impl<T> CodecExt for T
where
T: Codec + ?Sized,
{
fn encode<T2: Serialize + ?Sized>(&self, value: &T2) -> Result<Bytes> {
let v = serde_json::to_value(value)?;
self.encode_value(&v)
}
fn decode<T2: serde::de::DeserializeOwned>(&self, bytes: &[u8]) -> Result<T2> {
let v = self.decode_value(bytes)?;
Ok(serde_json::from_value(v)?)
}
}
pub trait CodecExt: Codec {
fn encode<T: Serialize + ?Sized>(&self, value: &T) -> Result<Bytes>;
fn decode<T: serde::de::DeserializeOwned>(&self, bytes: &[u8]) -> Result<T>;
}
pub fn negotiate(server: &[Arc<dyn Codec>], client: &[FrameCodec]) -> Result<Arc<dyn Codec>> {
for want in client {
if let Some(c) = server.iter().find(|c| c.frame_codec() == *want) {
return Ok(c.clone());
}
}
Err(crate::error::RiftError::Frame(
crate::error::FrameReject::CodecUnsupported(format!("client offered {:?}", client)),
))
}