use crate::result::{CordError, CordResult};
use crate::Width;
pub trait CordEncode {
fn encode_cord(&self, buf: &mut Vec<u8>) -> CordResult<()>;
fn encode_cord_with_width(&self, buf: &mut Vec<u8>, _width: Width) -> CordResult<()> {
self.encode_cord(buf)
}
}
pub trait CordDecode: Sized {
fn decode_cord(input: &mut &[u8]) -> CordResult<Self>;
fn decode_cord_with_width(input: &mut &[u8], _width: Width) -> CordResult<Self> {
Self::decode_cord(input)
}
}
impl CordEncode for () {
fn encode_cord(&self, _buf: &mut Vec<u8>) -> CordResult<()> {
Ok(())
}
}
impl CordEncode for bool {
fn encode_cord(&self, buf: &mut Vec<u8>) -> CordResult<()> {
crate::wire::write_bool(buf, *self);
Ok(())
}
}
macro_rules! impl_encode_fixed {
($($ty:ty),*) => {
$(
impl CordEncode for $ty {
fn encode_cord(&self, buf: &mut Vec<u8>) -> CordResult<()> {
buf.extend_from_slice(&self.to_be_bytes());
Ok(())
}
}
)*
};
}
impl_encode_fixed!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128);
impl CordEncode for f32 {
fn encode_cord(&self, buf: &mut Vec<u8>) -> CordResult<()> {
if self.is_nan() {
return Err(CordError::NanNotAllowed);
}
let v = if *self == 0.0 { 0.0_f32 } else { *self };
buf.extend_from_slice(&v.to_be_bytes());
Ok(())
}
}
impl CordEncode for f64 {
fn encode_cord(&self, buf: &mut Vec<u8>) -> CordResult<()> {
if self.is_nan() {
return Err(CordError::NanNotAllowed);
}
let v = if *self == 0.0 { 0.0_f64 } else { *self };
buf.extend_from_slice(&v.to_be_bytes());
Ok(())
}
}
impl CordEncode for str {
fn encode_cord(&self, buf: &mut Vec<u8>) -> CordResult<()> {
crate::wire::write_str(buf, self, Width::W32)
}
fn encode_cord_with_width(&self, buf: &mut Vec<u8>, width: Width) -> CordResult<()> {
crate::wire::write_str(buf, self, width)
}
}
impl CordEncode for String {
fn encode_cord(&self, buf: &mut Vec<u8>) -> CordResult<()> {
self.as_str().encode_cord(buf)
}
fn encode_cord_with_width(&self, buf: &mut Vec<u8>, width: Width) -> CordResult<()> {
self.as_str().encode_cord_with_width(buf, width)
}
}
impl<T: CordEncode> CordEncode for Option<T> {
fn encode_cord(&self, buf: &mut Vec<u8>) -> CordResult<()> {
match self {
None => {
buf.push(0);
Ok(())
}
Some(v) => {
buf.push(1);
v.encode_cord(buf)
}
}
}
}
impl<T: CordEncode> CordEncode for Vec<T> {
fn encode_cord(&self, buf: &mut Vec<u8>) -> CordResult<()> {
self.encode_cord_with_width(buf, Width::W32)
}
fn encode_cord_with_width(&self, buf: &mut Vec<u8>, width: Width) -> CordResult<()> {
crate::wire::write_length(buf, self.len(), width)?;
for item in self {
item.encode_cord(buf)?;
}
Ok(())
}
}
impl CordEncode for crate::Bytes {
fn encode_cord(&self, buf: &mut Vec<u8>) -> CordResult<()> {
crate::wire::write_bytes(buf, &self.0, Width::W32)
}
fn encode_cord_with_width(&self, buf: &mut Vec<u8>, width: Width) -> CordResult<()> {
crate::wire::write_bytes(buf, &self.0, width)
}
}
impl CordDecode for () {
fn decode_cord(_input: &mut &[u8]) -> CordResult<Self> {
Ok(())
}
}
impl CordDecode for bool {
fn decode_cord(input: &mut &[u8]) -> CordResult<Self> {
crate::wire::read_bool(input)
}
}
macro_rules! impl_decode_fixed {
($(($ty:ty, $n:expr)),*) => {
$(
impl CordDecode for $ty {
fn decode_cord(input: &mut &[u8]) -> CordResult<Self> {
let bytes = crate::wire::read_bytes(input, $n)?;
Ok(<$ty>::from_be_bytes(bytes.try_into().unwrap()))
}
}
)*
};
}
impl_decode_fixed!(
(u8, 1),
(u16, 2),
(u32, 4),
(u64, 8),
(u128, 16),
(i8, 1),
(i16, 2),
(i32, 4),
(i64, 8),
(i128, 16)
);
impl CordDecode for f32 {
fn decode_cord(input: &mut &[u8]) -> CordResult<Self> {
let bytes = crate::wire::read_bytes(input, 4)?;
let v = f32::from_be_bytes(bytes.try_into().unwrap());
if v.is_nan() {
return Err(CordError::NanNotAllowed);
}
if v.to_bits() == (-0.0_f32).to_bits() {
return Err(CordError::NegativeZeroNotAllowed);
}
Ok(v)
}
}
impl CordDecode for f64 {
fn decode_cord(input: &mut &[u8]) -> CordResult<Self> {
let bytes = crate::wire::read_bytes(input, 8)?;
let v = f64::from_be_bytes(bytes.try_into().unwrap());
if v.is_nan() {
return Err(CordError::NanNotAllowed);
}
if v.to_bits() == (-0.0_f64).to_bits() {
return Err(CordError::NegativeZeroNotAllowed);
}
Ok(v)
}
}
impl CordDecode for String {
fn decode_cord(input: &mut &[u8]) -> CordResult<Self> {
Self::decode_cord_with_width(input, Width::W32)
}
fn decode_cord_with_width(input: &mut &[u8], width: Width) -> CordResult<Self> {
let s = crate::wire::read_str(input, width, crate::de::DEFAULT_MAX_LENGTH)?;
Ok(s.to_string())
}
}
impl<T: CordDecode> CordDecode for Option<T> {
fn decode_cord(input: &mut &[u8]) -> CordResult<Self> {
let discriminant = crate::wire::read_bytes(input, 1)?[0];
match discriminant {
0 => Ok(None),
1 => Ok(Some(T::decode_cord(input)?)),
_ => Err(CordError::ValidationError("Invalid option discriminant")),
}
}
}
impl<T: CordDecode> CordDecode for Vec<T> {
fn decode_cord(input: &mut &[u8]) -> CordResult<Self> {
Self::decode_cord_with_width(input, Width::W32)
}
fn decode_cord_with_width(input: &mut &[u8], width: Width) -> CordResult<Self> {
let len = crate::wire::read_length(input, width, crate::de::DEFAULT_MAX_LENGTH)?;
let mut result = Vec::with_capacity(len);
for _ in 0..len {
result.push(T::decode_cord(input)?);
}
Ok(result)
}
}
impl CordDecode for crate::Bytes {
fn decode_cord(input: &mut &[u8]) -> CordResult<Self> {
Self::decode_cord_with_width(input, Width::W32)
}
fn decode_cord_with_width(input: &mut &[u8], width: Width) -> CordResult<Self> {
let data = crate::wire::read_bytes_prefixed(input, width, crate::de::DEFAULT_MAX_LENGTH)?;
Ok(crate::Bytes(data.to_vec()))
}
}
#[cfg(feature = "datetime")]
impl CordEncode for crate::DateTime {
fn encode_cord(&self, buf: &mut Vec<u8>) -> CordResult<()> {
buf.extend_from_slice(&self.chrono.timestamp().to_be_bytes());
buf.extend_from_slice(&self.chrono.timestamp_subsec_nanos().to_be_bytes());
Ok(())
}
}
#[cfg(feature = "datetime")]
impl CordDecode for crate::DateTime {
fn decode_cord(input: &mut &[u8]) -> CordResult<Self> {
let seconds = i64::decode_cord(input)?;
let nanos = u32::decode_cord(input)?;
use chrono::TimeZone;
let chrono = chrono::Utc
.timestamp_opt(seconds, nanos)
.single()
.ok_or(CordError::ValidationError("Invalid datetime"))?;
Ok(crate::DateTime { chrono })
}
}
#[cfg(feature = "uuid")]
impl CordEncode for crate::Uuid {
fn encode_cord(&self, buf: &mut Vec<u8>) -> CordResult<()> {
buf.extend_from_slice(self.inner.as_bytes());
Ok(())
}
}
#[cfg(feature = "uuid")]
impl CordDecode for crate::Uuid {
fn decode_cord(input: &mut &[u8]) -> CordResult<Self> {
let bytes = crate::wire::read_bytes(input, 16)?;
Ok(crate::Uuid {
inner: uuid::Uuid::from_bytes(bytes.try_into().unwrap()),
})
}
}
pub fn encode<T: CordEncode>(value: &T) -> CordResult<Vec<u8>> {
let mut buf = Vec::with_capacity(64);
value.encode_cord(&mut buf)?;
Ok(buf)
}
pub fn decode<T: CordDecode>(bytes: &[u8]) -> CordResult<T> {
let mut input = bytes;
let value = T::decode_cord(&mut input)?;
if !input.is_empty() {
return Err(CordError::ValidationError("Unexpected trailing bytes"));
}
Ok(value)
}