reqrio 0.2.0

A lightweight, high concurrency HTTP request library
Documentation
use crate::error::HlsResult;
use reqtls::WriteExt;
use std::fmt::{Debug, Formatter};
use std::io::{Cursor, Read};
use std::ops::Range;

pub struct Reader<'a> {
    buffer: &'a mut [u8],
    pos: usize,
}
impl<'a> Reader<'a> {
    pub fn new(buffer: &'a mut [u8]) -> Self {
        Self { buffer, pos: 0 }
    }

    pub fn filled(&self) -> &[u8] {
        &self.buffer[..self.pos]
    }

    pub fn unfilled_len(&self) -> usize {
        self.buffer.len() - self.pos
    }

    pub fn unfilled(&mut self) -> &mut [u8] {
        &mut self.buffer[self.pos..]
    }

    pub fn is_empty(&self) -> bool {
        self.pos >= self.buffer.len()
    }
}

impl<'a> WriteExt for Reader<'a> {
    fn as_ptr(&self) -> *const u8 {
        self.buffer.as_ptr()
    }

    fn as_mut_ptr(&mut self) -> *mut u8 {
        self.buffer.as_mut_ptr()
    }

    fn add_len(&mut self, len: usize) {
        self.pos += len
    }

    fn offset(&self) -> Range<usize> {
        0..self.pos
    }
}

pub struct RefReader<R> {
    bufs: Vec<Cursor<R>>,
    pos: usize,
    wrote: bool,
}

impl<R: AsRef<[u8]>> Default for RefReader<R> {
    fn default() -> Self {
        RefReader {
            bufs: vec![],
            pos: 0,
            wrote: false,
        }
    }
}

impl<'a> RefReader<StrCow<'a>> {
    pub fn add_str(&mut self, s: &'a str) {
        self.bufs.push(Cursor::new(StrCow::Borrowed(s)))
    }

    pub fn add_string(&mut self, s: String) {
        self.bufs.push(Cursor::new(StrCow::Owned(s)))
    }
}

impl<R: AsRef<[u8]>> RefReader<R> {
    pub fn new_buf(buf: R) -> RefReader<R> {
        RefReader {
            bufs: vec![Cursor::new(buf)],
            pos: 0,
            wrote: false,
        }
    }
    pub fn add_buf(&mut self, buf: R) {
        self.bufs.push(Cursor::new(buf));
    }

    pub fn wrote(&self) -> bool {
        self.wrote
    }
}

impl<R: AsRef<[u8]>> ReadExt for RefReader<R> {
    fn wrote(&self) -> bool {
        self.wrote
    }
    fn len(&self) -> usize {
        self.bufs.iter().map(|x| x.get_ref().as_ref().len()).sum()
    }
    fn read(&mut self, buf: &mut Reader) -> HlsResult<usize> {
        let start = buf.offset().end;
        for (index, reader) in self.bufs.iter_mut().enumerate() {
            if index < self.pos {
                continue;
            }
            loop {
                if buf.is_empty() {
                    return Ok(buf.offset().end - start);
                }
                let len = reader.read(buf.unfilled())?;
                if len == 0 {
                    self.pos += 1;
                    break;
                }
                buf.add_len(len);
            }
        }
        self.wrote = true;
        Ok(buf.offset().end - start)
    }
}

pub trait ReadExt {
    fn wrote(&self) -> bool;
    fn len(&self) -> usize;
    fn read(&mut self, buf: &mut Reader) -> HlsResult<usize>;
}

pub enum StrCow<'a> {
    Borrowed(&'a str),
    Owned(String),
}

impl<'a> StrCow<'a> {
    pub fn len(&self) -> usize {
        match self {
            StrCow::Borrowed(b) => b.len(),
            StrCow::Owned(o) => o.len(),
        }
    }
}

impl<'a> AsRef<[u8]> for StrCow<'a> {
    fn as_ref(&self) -> &[u8] {
        match self {
            StrCow::Borrowed(v) => v.as_bytes(),
            StrCow::Owned(o) => o.as_bytes(),
        }
    }
}

impl<'a> AsRef<str> for StrCow<'a> {
    fn as_ref(&self) -> &str {
        match self {
            StrCow::Borrowed(b) => b,
            StrCow::Owned(o) => o.as_str(),
        }
    }
}

impl<'a> Debug for StrCow<'a> {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            StrCow::Borrowed(b) => write!(f, "{}", b),
            StrCow::Owned(o) => write!(f, "{}", o),
        }
    }
}