use bytes::Bytes;
use derive_more::{Debug, Display, Error};
#[derive(Debug, Display, Error)]
#[display("codec error: {_0}")]
#[error(ignore)]
pub struct CodecError(pub String);
impl CodecError {
pub fn new(msg: impl Into<String>) -> Self {
Self(msg.into())
}
}
pub trait CodecConfig: Clone + Send + Sync + 'static {
fn max_size(&self) -> usize;
fn max_depth(&self) -> usize;
fn allow_batch(&self) -> bool;
fn max_batch_size(&self) -> usize;
}
#[derive(Clone, Debug)]
pub struct DefaultCodecConfig {
max_size: usize,
max_depth: usize,
allow_batch: bool,
max_batch_size: usize,
}
impl DefaultCodecConfig {
pub const fn new() -> Self {
Self {
max_size: 1024 * 1024, max_depth: 32,
allow_batch: true,
max_batch_size: 100,
}
}
pub const fn with_max_size(mut self, size: usize) -> Self {
self.max_size = size;
self
}
pub const fn with_max_depth(mut self, depth: usize) -> Self {
self.max_depth = depth;
self
}
pub const fn with_allow_batch(mut self, allow: bool) -> Self {
self.allow_batch = allow;
self
}
pub const fn with_max_batch_size(mut self, size: usize) -> Self {
self.max_batch_size = size;
self
}
}
impl Default for DefaultCodecConfig {
fn default() -> Self {
Self::new()
}
}
impl CodecConfig for DefaultCodecConfig {
fn max_size(&self) -> usize {
self.max_size
}
fn max_depth(&self) -> usize {
self.max_depth
}
fn allow_batch(&self) -> bool {
self.allow_batch
}
fn max_batch_size(&self) -> usize {
self.max_batch_size
}
}
pub trait Decode: Sized {
fn decode<C: CodecConfig>(bytes: &[u8], config: &C) -> Result<Self, CodecError>;
fn decode_bytes<C: CodecConfig>(bytes: &Bytes, config: &C) -> Result<Self, CodecError> {
Self::decode(bytes.as_ref(), config)
}
}
pub trait Encode {
fn encode(&self) -> Result<Bytes, CodecError>;
fn encode_vec(&self) -> Result<Vec<u8>, CodecError> {
self.encode().map(|b| b.to_vec())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_codec_config() {
let config = DefaultCodecConfig::new();
assert_eq!(config.max_size(), 1024 * 1024);
assert_eq!(config.max_depth(), 32);
assert!(config.allow_batch());
assert_eq!(config.max_batch_size(), 100);
}
#[test]
fn test_codec_config_builder() {
let config = DefaultCodecConfig::new()
.with_max_size(512)
.with_max_depth(16)
.with_allow_batch(false)
.with_max_batch_size(10);
assert_eq!(config.max_size(), 512);
assert_eq!(config.max_depth(), 16);
assert!(!config.allow_batch());
assert_eq!(config.max_batch_size(), 10);
}
#[test]
fn test_codec_error_display() {
let error = CodecError::new("invalid json");
assert!(error.to_string().contains("invalid json"));
}
}