use embedded_io_async::{Read, Write};
use futures::{Sink, Stream};
use crate::{
ReadError, WriteError, decode::Decoder, encode::Encoder, functions, state::ReadWriteState,
};
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct FramedCore<'buf, C, RW> {
pub codec: C,
pub inner: RW,
pub state: ReadWriteState<'buf>,
}
impl<'buf, C, RW> FramedCore<'buf, C, RW> {
pub const fn new(codec: C, inner: RW, state: ReadWriteState<'buf>) -> Self {
Self {
codec,
inner,
state,
}
}
#[inline]
pub const fn codec(&self) -> &C {
&self.codec
}
#[inline]
pub const fn codec_mut(&mut self) -> &mut C {
&mut self.codec
}
#[inline]
pub const fn inner(&self) -> &RW {
&self.inner
}
#[inline]
pub const fn inner_mut(&mut self) -> &mut RW {
&mut self.inner
}
#[inline]
pub fn into_parts(self) -> (C, RW, ReadWriteState<'buf>) {
(self.codec, self.inner, self.state)
}
#[inline]
pub const fn from_parts(codec: C, inner: RW, state: ReadWriteState<'buf>) -> Self {
Self {
codec,
inner,
state,
}
}
#[inline]
pub const fn framable(&self) -> usize {
self.state.read.framable()
}
pub async fn maybe_next<'this>(
&'this mut self,
) -> Option<Result<Option<C::Item>, ReadError<RW::Error, C::Error>>>
where
C: Decoder<'this>,
RW: Read,
{
functions::maybe_next(&mut self.state.read, &mut self.codec, &mut self.inner).await
}
pub async fn next<'this, U>(
&'this mut self,
map: fn(<C as Decoder<'_>>::Item) -> U,
) -> Option<Result<U, ReadError<RW::Error, C::Error>>>
where
U: 'static,
C: for<'a> Decoder<'a>,
RW: Read,
{
functions::next(&mut self.state.read, &mut self.codec, &mut self.inner, map).await
}
pub fn stream<U>(
&mut self,
map: fn(<C as Decoder<'_>>::Item) -> U,
) -> impl Stream<Item = Result<U, ReadError<RW::Error, C::Error>>> + '_
where
U: 'static,
C: for<'a> Decoder<'a>,
RW: Read,
{
futures::stream::unfold((self, false), move |(this, errored)| async move {
if errored {
return None;
}
match this.next(map).await {
Some(Ok(item)) => Some((Ok(item), (this, false))),
Some(Err(err)) => Some((Err(err), (this, true))),
None => None,
}
})
}
pub async fn send<I>(&mut self, item: I) -> Result<(), WriteError<RW::Error, C::Error>>
where
C: Encoder<I>,
RW: Write,
{
functions::send(
&mut self.state.write,
&mut self.codec,
&mut self.inner,
item,
)
.await
}
pub fn sink<'this, I>(
&'this mut self,
) -> impl Sink<I, Error = WriteError<RW::Error, C::Error>> + 'this
where
I: 'this,
C: Encoder<I>,
RW: Write,
{
futures::sink::unfold(self, |this, item: I| async move {
this.send(item).await?;
Ok::<_, WriteError<RW::Error, C::Error>>(this)
})
}
}