use bytes::Bytes;
#[derive(Debug, thiserror::Error)]
#[error("deserialization error: {0}")]
pub struct SerdeError(pub String);
#[diagnostic::on_unimplemented(
message = "the type `{Self}` is not a valid serializer/deserializer for `{T}`",
label = "does not implement `Serde<{T}>`",
note = "implement `Serde<{T}>` for `{Self}` or verify that the type parameter `{T}` matches the deserialized type of this serde"
)]
pub trait Serde<T>: Send + Sync + 'static {
fn serialize(&self, value: &T) -> Bytes;
fn deserialize(&self, bytes: &[u8]) -> Result<T, SerdeError>;
}
#[diagnostic::on_unimplemented(
message = "the serde type `{Self}` is not associated with any target model type",
label = "does not implement `SerdeAssociate`",
note = "implement `SerdeAssociate` for `{Self}` and define `type Target = ...;` to map this Serde to its model type"
)]
pub trait SerdeAssociate {
type Target: Send + Sync + 'static;
}
#[derive(Debug, Clone, Copy)]
pub struct Consumed<KS, VS> {
pub(crate) key_serde: KS,
pub(crate) value_serde: VS,
}
impl<KS, VS> Consumed<KS, VS> {
#[must_use]
pub fn with(key_serde: KS, value_serde: VS) -> Self {
Self {
key_serde,
value_serde,
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct Produced<KS, VS> {
pub(crate) key_serde: KS,
pub(crate) value_serde: VS,
}
impl<KS, VS> Produced<KS, VS> {
#[must_use]
pub fn with(key_serde: KS, value_serde: VS) -> Self {
Self {
key_serde,
value_serde,
}
}
}
pub(crate) struct SerdeArc<T>(pub(crate) std::sync::Arc<dyn Serde<T>>);
impl<T> Clone for SerdeArc<T> {
fn clone(&self) -> Self {
SerdeArc(std::sync::Arc::clone(&self.0))
}
}
impl<T: Send + Sync + 'static> Serde<T> for SerdeArc<T> {
fn serialize(&self, value: &T) -> Bytes {
self.0.serialize(value)
}
fn deserialize(&self, bytes: &[u8]) -> Result<T, SerdeError> {
self.0.deserialize(bytes)
}
}
impl<T: Send + Sync + 'static> SerdeAssociate for SerdeArc<T> {
type Target = T;
}
#[derive(Debug, Clone, Copy, Default)]
pub struct BytesSerde;
impl Serde<Bytes> for BytesSerde {
fn serialize(&self, value: &Bytes) -> Bytes {
value.clone()
}
fn deserialize(&self, bytes: &[u8]) -> Result<Bytes, SerdeError> {
Ok(Bytes::copy_from_slice(bytes))
}
}
impl SerdeAssociate for BytesSerde {
type Target = Bytes;
}
#[derive(Debug, Clone, Copy, Default)]
pub struct StringSerde;
impl Serde<String> for StringSerde {
fn serialize(&self, value: &String) -> Bytes {
Bytes::copy_from_slice(value.as_bytes())
}
fn deserialize(&self, bytes: &[u8]) -> Result<String, SerdeError> {
String::from_utf8(bytes.to_vec()).map_err(|e| SerdeError(e.to_string()))
}
}
impl SerdeAssociate for StringSerde {
type Target = String;
}
#[derive(Debug, Clone, Copy, Default)]
pub struct I64Serde;
impl Serde<i64> for I64Serde {
fn serialize(&self, value: &i64) -> Bytes {
Bytes::copy_from_slice(&value.to_be_bytes())
}
fn deserialize(&self, bytes: &[u8]) -> Result<i64, SerdeError> {
let arr: [u8; 8] = bytes
.try_into()
.map_err(|_| SerdeError(format!("expected 8 bytes, got {}", bytes.len())))?;
Ok(i64::from_be_bytes(arr))
}
}
impl SerdeAssociate for I64Serde {
type Target = i64;
}
#[diagnostic::on_unimplemented(
message = "the type `{Self}` does not have a default Serde implementation",
label = "no default Serde association found for this type",
note = "implement `DefaultSerde` for `{Self}` or specify/override the serde explicitly using `.with_key_serde()` or `.with_value_serde()`"
)]
pub trait DefaultSerde: Send + Sync + 'static + Sized {
type Serde: SerdeAssociate<Target = Self> + Serde<Self> + Clone + Default + 'static;
}
impl DefaultSerde for String {
type Serde = StringSerde;
}
impl DefaultSerde for i64 {
type Serde = I64Serde;
}
impl DefaultSerde for bytes::Bytes {
type Serde = BytesSerde;
}
impl<KS, VS> From<(KS, VS)> for Consumed<KS, VS> {
fn from((key_serde, value_serde): (KS, VS)) -> Self {
Self::with(key_serde, value_serde)
}
}
impl<KS, VS> From<(KS, VS)> for Produced<KS, VS> {
fn from((key_serde, value_serde): (KS, VS)) -> Self {
Self::with(key_serde, value_serde)
}
}
#[cfg(test)]
mod tests {
use super::*;
use assert2::check;
#[test]
fn string_serde_round_trips() {
let s = StringSerde;
let b = s.serialize(&"héllo".to_string());
check!(s.deserialize(&b).unwrap() == "héllo");
}
#[test]
fn i64_serde_is_big_endian_8_bytes() {
let s = I64Serde;
let b = s.serialize(&1i64);
check!(b.as_ref() == [0, 0, 0, 0, 0, 0, 0, 1]);
check!(s.deserialize(&b).unwrap() == 1);
check!(s.deserialize(&[0, 1]).is_err());
}
#[test]
fn bytes_serde_is_identity() {
let s = BytesSerde;
let b = s.serialize(&bytes::Bytes::from_static(b"xy"));
check!(s.deserialize(&b).unwrap() == bytes::Bytes::from_static(b"xy"));
}
}