use crate::{EncodeValue, Encoder, Length, Result, Tagged};
#[cfg(feature = "alloc")]
use {crate::ErrorKind, alloc::vec::Vec, core::iter};
pub trait Encodable {
fn encoded_len(&self) -> Result<Length>;
fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()>;
fn encode_to_slice<'a>(&self, buf: &'a mut [u8]) -> Result<&'a [u8]> {
let mut encoder = Encoder::new(buf);
self.encode(&mut encoder)?;
encoder.finish()
}
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
fn encode_to_vec(&self, buf: &mut Vec<u8>) -> Result<Length> {
let expected_len = usize::try_from(self.encoded_len()?)?;
buf.reserve(expected_len);
buf.extend(iter::repeat(0).take(expected_len));
let mut encoder = Encoder::new(buf);
self.encode(&mut encoder)?;
let actual_len = encoder.finish()?.len();
if expected_len != actual_len {
return Err(ErrorKind::Incomplete {
expected_len: expected_len.try_into()?,
actual_len: actual_len.try_into()?,
}
.into());
}
actual_len.try_into()
}
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
fn to_vec(&self) -> Result<Vec<u8>> {
let mut buf = Vec::new();
self.encode_to_vec(&mut buf)?;
Ok(buf)
}
}
impl<T> Encodable for T
where
T: EncodeValue + Tagged,
{
fn encoded_len(&self) -> Result<Length> {
self.value_len().and_then(|len| len.for_tlv())
}
fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> {
self.header()?.encode(encoder)?;
self.encode_value(encoder)
}
}