use crate::errors::{error, nil};
use crate::types::string;
use std::sync::Mutex;
pub struct Body {
inner: Mutex<BodyInner>,
}
impl Default for Body {
fn default() -> Self { Body::empty() }
}
enum BodyInner {
Buffered { data: Vec<u8>, pos: usize, closed: bool },
}
impl Body {
pub(crate) fn from_bytes(data: Vec<u8>) -> Self {
Body { inner: Mutex::new(BodyInner::Buffered { data, pos: 0, closed: false }) }
}
pub(crate) fn empty() -> Self {
Body::from_bytes(Vec::new())
}
#[allow(non_snake_case)]
pub fn Close(&self) -> error {
let mut g = self.inner.lock().unwrap();
match &mut *g {
BodyInner::Buffered { closed, .. } => { *closed = true; }
}
nil
}
#[allow(non_snake_case)]
pub fn Bytes(&self) -> crate::types::slice<u8> {
let mut out: Vec<u8> = Vec::new();
self.drain_into(&mut out);
out.into()
}
#[allow(non_snake_case)]
pub fn String(&self) -> string {
let b = self.Bytes();
String::from_utf8_lossy(&b).into_owned().into()
}
fn drain_into(&self, out: &mut Vec<u8>) {
let mut g = self.inner.lock().unwrap();
match &mut *g {
BodyInner::Buffered { data, pos, closed } => {
if *closed { return; }
out.extend_from_slice(&data[*pos..]);
*pos = data.len();
}
}
}
}
impl std::io::Read for Body {
fn read(&mut self, p: &mut [u8]) -> std::io::Result<usize> {
let mut g = self.inner.lock().unwrap();
match &mut *g {
BodyInner::Buffered { data, pos, closed } => {
if *closed { return Ok(0); }
let remaining = data.len() - *pos;
if remaining == 0 { return Ok(0); }
let n = remaining.min(p.len());
p[..n].copy_from_slice(&data[*pos..*pos + n]);
*pos += n;
Ok(n)
}
}
}
}