use std::{
error::Error,
io::{BufRead, Write},
};
use ipld_core::codec::Codec as IpldCodec;
use serde::{Deserialize, Serialize};
use serde_ipld_dagcbor::{codec::DagCborCodec, error::CodecError};
#[cfg(feature = "dag_json")]
use serde_ipld_dagjson::{codec::DagJsonCodec, error::CodecError as JsonError};
pub trait Codec<T>: Sized {
type EncodingError: Error;
type DecodingError: Error;
fn multicodec_code(&self) -> u64;
fn try_from_tags(code: &[u64]) -> Option<Self>;
fn encode_payload<W: Write>(
&self,
payload: &T,
buffer: &mut W,
) -> Result<(), Self::EncodingError>;
fn decode_payload<R: BufRead>(&self, reader: &mut R) -> Result<T, Self::DecodingError>;
}
impl<T: Serialize + for<'de> Deserialize<'de>> Codec<T> for DagCborCodec {
type EncodingError = CodecError;
type DecodingError = CodecError;
fn multicodec_code(&self) -> u64 {
<DagCborCodec as IpldCodec<T>>::CODE
}
fn try_from_tags(code: &[u64]) -> Option<Self> {
if code.is_empty() {
return None;
}
if code.len() > 1 {
return None;
}
if *code.first()? == <DagCborCodec as IpldCodec<T>>::CODE {
Some(DagCborCodec)
} else {
None
}
}
fn encode_payload<W: Write>(
&self,
payload: &T,
buffer: &mut W,
) -> Result<(), Self::EncodingError> {
DagCborCodec::encode(buffer, payload)
}
fn decode_payload<R: BufRead>(&self, reader: &mut R) -> Result<T, Self::DecodingError> {
DagCborCodec::decode(reader)
}
}
#[cfg(feature = "dag_json")]
impl<T: Serialize + for<'de> Deserialize<'de>> Codec<T> for DagJsonCodec {
type EncodingError = JsonError;
type DecodingError = JsonError;
fn multicodec_code(&self) -> u64 {
<DagJsonCodec as IpldCodec<T>>::CODE
}
fn try_from_tags(code: &[u64]) -> Option<Self> {
if code.is_empty() {
return None;
}
if code.len() > 1 {
return None;
}
if code[0] == <DagJsonCodec as IpldCodec<T>>::CODE {
Some(DagJsonCodec)
} else {
None
}
}
fn encode_payload<W: Write>(
&self,
payload: &T,
buffer: &mut W,
) -> Result<(), Self::EncodingError> {
DagJsonCodec::encode(buffer, payload)
}
fn decode_payload<R: BufRead>(&self, reader: &mut R) -> Result<T, Self::DecodingError> {
DagJsonCodec::decode(reader)
}
}