use std::io::Cursor;
use std::panic::{AssertUnwindSafe, catch_unwind};
use anyhow::{Result, anyhow};
use aws_lc_rs::aead::NONCE_LEN;
use bincode_next::{Decode, config::standard, decode_from_slice};
use bytes::Buf as _;
pub(crate) mod encframe;
pub(crate) mod frame;
const USIZE_LENGTH: usize = 8;
const DECODE_LIMIT: usize = 65536;
pub(crate) fn decode_frame<T: Decode<()>>(data: &[u8]) -> Result<T> {
let config = standard().with_limit::<DECODE_LIMIT>();
match catch_unwind(AssertUnwindSafe(|| decode_from_slice::<T, _>(data, config))) {
Ok(Ok((frame, _))) => Ok(frame),
Ok(Err(e)) => Err(e.into()),
Err(_) => Err(anyhow!("frame decode panicked on malformed input")),
}
}
pub(crate) fn get_usize<'a>(src: &mut Cursor<&'a [u8]>) -> Result<Option<&'a [u8]>> {
if src.remaining() < USIZE_LENGTH {
Ok(None)
} else {
let start = usize::try_from(src.position())?;
let end = start + USIZE_LENGTH;
src.set_position(u64::try_from(end)?);
Ok(Some(&src.get_ref()[start..end]))
}
}
pub(crate) fn get_nonce<'a>(src: &mut Cursor<&'a [u8]>) -> Result<Option<&'a [u8]>> {
if src.remaining() < NONCE_LEN {
Ok(None)
} else {
let start = usize::try_from(src.position())?;
let end = start + NONCE_LEN;
src.set_position(u64::try_from(end)?);
Ok(Some(&src.get_ref()[start..end]))
}
}
pub(crate) fn get_bytes<'a>(src: &mut Cursor<&'a [u8]>, length: usize) -> Result<Option<&'a [u8]>> {
if src.remaining() < length {
Ok(None)
} else {
let start = usize::try_from(src.position())?;
let end = start + length;
src.set_position(u64::try_from(end)?);
Ok(Some(&src.get_ref()[start..end]))
}
}