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),
}
}
}