use core::cmp::min;
use bytes::BufMut;
use crate::{
codec::Compact1CodecOpinion,
decoder::{DecError, Decoder, MeasureBuf},
encoder::{EncError, Encoder, ImprovidentBufMut},
};
#[derive(Default)]
pub struct StringOpinion {
max_len: u32,
}
impl StringOpinion {
#[inline]
pub fn new(max_len: u32) -> Self {
Self { max_len }
}
}
impl Compact1CodecOpinion<String> for StringOpinion {
fn encode<B: ImprovidentBufMut>(
&self,
encoder: &mut Encoder<B>,
what: &String,
) -> Result<(), EncError>
where
Self: Sized,
{
let bytes = what.len();
if bytes > min(self.max_len, crate::vu29::VU29_MAX_4BYTE) as usize {
return Err(EncError::ContainerTooLong);
}
crate::vu29::encode_vu29(encoder.buf.deref_mut(), bytes as u32)?;
encoder.buf.put_slice(what.as_bytes());
Ok(())
}
fn decode<B: MeasureBuf>(&self, decoder: &mut Decoder<B>) -> Result<String, DecError>
where
String: Sized,
{
let num_bytes = crate::vu29::decode_vu29(&mut decoder.buf)?;
if num_bytes > self.max_len {
return Err(DecError::ContainerTooLong);
}
let mut out = vec![0u8; num_bytes as usize];
decoder.buf.try_copy_to_slice(&mut out)?;
String::from_utf8(out).map_err(|_| DecError::Utf8Decode)
}
}
#[derive(Default)]
pub struct BytesOpinion {
max_len: u32,
}
impl BytesOpinion {
#[inline]
pub fn new(max_len: u32) -> Self {
Self { max_len }
}
}
impl Compact1CodecOpinion<Vec<u8>> for BytesOpinion {
fn encode<B: ImprovidentBufMut>(
&self,
encoder: &mut Encoder<B>,
what: &Vec<u8>,
) -> Result<(), EncError>
where
Self: Sized,
{
let bytes = what.len();
if bytes > min(self.max_len, crate::vu29::VU29_MAX_4BYTE) as usize {
return Err(EncError::ContainerTooLong);
}
crate::vu29::encode_vu29(encoder.buf.deref_mut(), bytes as u32)?;
encoder.buf.put_slice(what);
Ok(())
}
fn decode<B: MeasureBuf>(&self, decoder: &mut Decoder<B>) -> Result<Vec<u8>, DecError>
where
String: Sized,
{
let num_bytes = crate::vu29::decode_vu29(&mut decoder.buf)?;
if num_bytes > self.max_len {
return Err(DecError::ContainerTooLong);
}
let mut out = vec![0u8; num_bytes as usize];
decoder.buf.try_copy_to_slice(&mut out)?;
Ok(out)
}
}
pub struct VecOpinion<TO> {
max_len: u32,
inner: TO,
}
impl<TO> VecOpinion<TO> {
pub fn new(max_len: u32, inner: TO) -> Self {
Self { inner, max_len }
}
}
impl<T, TO: Compact1CodecOpinion<T>> Compact1CodecOpinion<Vec<T>> for VecOpinion<TO> {
fn encode<B: ImprovidentBufMut>(
&self,
encoder: &mut Encoder<B>,
what: &Vec<T>,
) -> Result<(), EncError>
where
Self: Sized,
{
let items = what.len();
if items > min(self.max_len, crate::vu29::VU29_MAX_4BYTE) as usize {
return Err(EncError::ContainerTooLong);
}
crate::vu29::encode_vu29(encoder.buf.deref_mut(), items as u32)?;
for item in what {
self.inner.encode(encoder, item)?;
}
Ok(())
}
fn decode<B: MeasureBuf>(&self, decoder: &mut Decoder<B>) -> Result<Vec<T>, DecError>
where
Vec<T>: Sized,
{
let num_items = crate::vu29::decode_vu29(&mut decoder.buf)?;
if num_items > self.max_len {
return Err(DecError::ContainerTooLong);
}
let mut out = Vec::with_capacity(num_items as usize);
for _ in 0..num_items {
out.push(self.inner.decode(decoder)?);
}
Ok(out)
}
}