use crate::courierust_bytes::Bytes;
use crate::courierust_error::Error;
use crate::Result;
use std::sync::mpsc::{Receiver, TryRecvError};
#[derive(Default)]
pub enum Body {
#[default]
Empty,
Bytes(Bytes),
Channel(Receiver<Result<Bytes>>),
}
impl Body {
pub fn is_empty(&self) -> bool {
match self {
Self::Empty => true,
Self::Bytes(b) => b.is_empty(),
Self::Channel(_) => false,
}
}
pub fn is_bytes(&self) -> bool {
matches!(self, Self::Bytes(_))
}
pub fn as_bytes(&self) -> Option<&[u8]> {
match self {
Self::Bytes(b) => Some(b),
_ => None,
}
}
pub fn try_next_chunk(&mut self) -> Result<Option<Bytes>> {
match self {
Self::Channel(rx) => match rx.try_recv() {
Ok(chunk) => chunk.map(Some),
Err(TryRecvError::Empty) => Ok(None),
Err(TryRecvError::Disconnected) => Ok(None),
},
_ => Ok(None),
}
}
pub fn collect(self) -> Result<Bytes> {
match self {
Self::Empty => Ok(Bytes::new()),
Self::Bytes(b) => Ok(b),
Self::Channel(rx) => {
let mut out = Vec::new();
while let Ok(chunk) = rx.recv() {
let b = chunk?;
out.extend_from_slice(&b);
}
Ok(Bytes::from(out))
}
}
}
pub fn len(&self) -> Option<usize> {
match self {
Self::Empty => Some(0),
Self::Bytes(b) => Some(b.len()),
Self::Channel(_) => None,
}
}
}
impl From<Bytes> for Body {
fn from(b: Bytes) -> Self {
if b.is_empty() {
Self::Empty
} else {
Self::Bytes(b)
}
}
}
impl From<Vec<u8>> for Body {
fn from(v: Vec<u8>) -> Self {
Self::from(Bytes::from(v))
}
}
impl From<&'static [u8]> for Body {
fn from(b: &'static [u8]) -> Self {
Self::from(Bytes::from_static(b))
}
}
impl From<&'static str> for Body {
fn from(s: &'static str) -> Self {
Self::from(Bytes::from_static(s.as_bytes()))
}
}
impl From<String> for Body {
fn from(s: String) -> Self {
Self::from(Bytes::from(s))
}
}
impl From<Receiver<Result<Bytes>>> for Body {
fn from(rx: Receiver<Result<Bytes>>) -> Self {
Self::Channel(rx)
}
}
impl std::fmt::Debug for Body {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Empty => write!(f, "Body::Empty"),
Self::Bytes(b) => write!(f, "Body::Bytes({} bytes)", b.len()),
Self::Channel(_) => write!(f, "Body::Channel"),
}
}
}
pub struct BodySender {
tx: std::sync::mpsc::Sender<Result<Bytes>>,
}
impl BodySender {
pub fn from_sender(tx: std::sync::mpsc::Sender<Result<Bytes>>) -> Self {
Self { tx }
}
pub fn send(&self, chunk: Bytes) -> Result<()> {
self.tx
.send(Ok(chunk))
.map_err(|_| Error::canceled("body receiver dropped"))
}
pub fn send_bytes(&self, chunk: &[u8]) -> Result<()> {
self.send(Bytes::from(chunk))
}
pub fn send_result(&self, result: Result<Bytes>) -> Result<()> {
self.tx
.send(result)
.map_err(|_| Error::canceled("body receiver dropped"))
}
pub fn fail(&self, err: Error) {
let _ = self.tx.send(Err(err));
}
}
pub fn channel() -> (BodySender, Body) {
let (tx, rx) = std::sync::mpsc::channel::<Result<Bytes>>();
(BodySender { tx }, Body::Channel(rx))
}