use bytes::{Bytes, BytesMut};
use http_body::{Body, Frame, SizeHint};
use std::fmt::{self, Debug, Formatter};
use std::marker::PhantomPinned;
use std::pin::Pin;
use std::task::{Context, Poll};
use crate::{Error, Result};
const MAX_FRAME_LEN: usize = 8192;
#[must_use = "streams do nothing unless polled"]
pub struct ByteBuffer {
buf: BytesMut,
_pin: PhantomPinned,
}
impl ByteBuffer {
pub fn new(data: &[u8]) -> Self {
let unique = Bytes::copy_from_slice(data);
Self {
buf: BytesMut::from(unique),
_pin: PhantomPinned,
}
}
pub fn is_empty(&self) -> bool {
self.buf.is_empty()
}
pub fn len(&self) -> usize {
self.buf.len()
}
}
impl ByteBuffer {
fn project(self: Pin<&mut Self>) -> Pin<&mut BytesMut> {
unsafe { Pin::map_unchecked_mut(self, |this| &mut this.buf) }
}
}
impl Body for ByteBuffer {
type Data = Bytes;
type Error = Error;
fn poll_frame(
self: Pin<&mut Self>,
_: &mut Context<'_>,
) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
let mut buf = self.project();
let len = buf.len().min(MAX_FRAME_LEN);
if len == 0 {
return Poll::Ready(None);
}
let data = buf.split_to(len).freeze();
let frame = Frame::data(data);
Poll::Ready(Some(Ok(frame)))
}
fn is_end_stream(&self) -> bool {
self.is_empty()
}
fn size_hint(&self) -> SizeHint {
let len = self.len().try_into().ok();
len.map_or_else(SizeHint::new, SizeHint::with_exact)
}
}
impl Debug for ByteBuffer {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("ByteBuffer").finish()
}
}
impl Default for ByteBuffer {
fn default() -> Self {
Self::new(&[])
}
}
impl From<Bytes> for ByteBuffer {
fn from(bytes: Bytes) -> Self {
Self::new(&bytes)
}
}
impl From<Vec<u8>> for ByteBuffer {
fn from(vec: Vec<u8>) -> Self {
Self::new(vec.as_slice())
}
}
impl From<&'static [u8]> for ByteBuffer {
fn from(slice: &'static [u8]) -> Self {
Self::new(slice)
}
}
impl From<String> for ByteBuffer {
fn from(string: String) -> Self {
Self::new(string.as_bytes())
}
}
impl From<&'static str> for ByteBuffer {
fn from(slice: &'static str) -> Self {
Self::new(slice.as_bytes())
}
}