use std::{fmt, io, mem, ops};
use bytes::{Bytes, BytesMut};
use crate::{decode, encode};
use crate::decode::{BytesSource, DecodeError, IntoSource, Pos};
use crate::mode::Mode;
#[derive(Clone)]
pub struct Captured {
bytes: Bytes,
mode: Mode,
start: Pos,
}
impl Captured {
pub(crate) fn new(bytes: Bytes, mode: Mode, start: Pos) -> Self {
Captured { bytes, mode, start }
}
pub fn from_values<V: encode::Values>(mode: Mode, values: V) -> Self {
let mut builder = Self::builder(mode);
builder.extend(values);
builder.freeze()
}
pub fn empty(mode: Mode) -> Self {
Captured {
bytes: Bytes::new(),
mode,
start: Pos::default(),
}
}
pub fn builder(mode: Mode) -> CapturedBuilder {
CapturedBuilder::new(mode)
}
pub fn into_builder(self) -> CapturedBuilder {
self.into()
}
pub fn decode<F, T>(
self, op: F
) -> Result<T, DecodeError<<BytesSource as decode::Source>::Error>>
where
F: FnOnce(
&mut decode::Constructed<BytesSource>
) -> Result<T, DecodeError<<BytesSource as decode::Source>::Error>>
{
self.mode.decode(self.bytes, op)
}
pub fn decode_partial<F, T>(
&mut self, op: F
) -> Result<T, DecodeError<<BytesSource as decode::Source>::Error>>
where
F: FnOnce(
&mut decode::Constructed<&mut BytesSource>
) -> Result<T, DecodeError<<BytesSource as decode::Source>::Error>>
{
let mut source = mem::replace(
&mut self.bytes, Bytes::new()
).into_source();
let res = self.mode.decode(&mut source, op);
self.bytes = source.into_bytes();
res
}
pub fn into_bytes(self) -> Bytes {
self.bytes
}
pub fn as_slice(&self) -> &[u8] {
self.bytes.as_ref()
}
}
impl ops::Deref for Captured {
type Target = Bytes;
fn deref(&self) -> &Bytes {
&self.bytes
}
}
impl AsRef<Bytes> for Captured {
fn as_ref(&self) -> &Bytes {
&self.bytes
}
}
impl AsRef<[u8]> for Captured {
fn as_ref(&self) -> &[u8] {
self.bytes.as_ref()
}
}
impl IntoSource for Captured {
type Source = BytesSource;
fn into_source(self) -> Self::Source {
BytesSource::with_offset(self.bytes, self.start)
}
}
impl encode::Values for Captured {
fn encoded_len(&self, mode: Mode) -> usize {
assert!(
!(self.mode != mode && mode != Mode::Ber),
"Trying to encode a captured value with incompatible mode"
);
self.bytes.len()
}
fn write_encoded<W: io::Write>(
&self,
mode: Mode,
target: &mut W
) -> Result<(), io::Error> {
assert!(
!(self.mode != mode && mode != Mode::Ber),
"Trying to encode a captured value with incompatible mode"
);
target.write_all(self.bytes.as_ref())
}
}
impl fmt::Debug for Captured {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[ ")?;
for (i, &v) in self.bytes.iter().enumerate() {
write!(f, "{:02x} ", v)?;
if i % 4 == 3 {
write!(f, " ")?;
}
}
write!(f, "]")
}
}
pub struct CapturedBuilder {
bytes: BytesMut,
mode: Mode,
}
impl CapturedBuilder {
pub fn new(mode: Mode) -> Self {
CapturedBuilder {
bytes: BytesMut::new(),
mode
}
}
pub fn with_capacity(capacity: usize, mode: Mode) -> Self {
CapturedBuilder {
bytes: BytesMut::with_capacity(capacity),
mode
}
}
pub fn extend<V: encode::Values>(&mut self, values: V) {
values.write_encoded(
self.mode,
&mut CapturedWriter(&mut self.bytes)
).unwrap()
}
pub fn freeze(self) -> Captured {
Captured::new(self.bytes.freeze(), self.mode, Pos::default())
}
}
impl From<Captured> for CapturedBuilder {
fn from(src: Captured) -> Self {
CapturedBuilder {
bytes: src.bytes.as_ref().into(),
mode: src.mode
}
}
}
struct CapturedWriter<'a>(&'a mut BytesMut);
impl<'a> io::Write for CapturedWriter<'a> {
fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
self.0.extend_from_slice(buf);
Ok(buf.len())
}
fn flush(&mut self) -> Result<(), io::Error> {
Ok(())
}
}