use std::io::Cursor;
use std::{
io::{BufReader, Write},
sync::Arc,
};
use crate::bufreader::IndexedBufReader;
use crate::ReadByLine;
use crate::{index::Index, Indexable, IndexableFile, Result};
pub trait Anyable: AsRef<[u8]> + Clone + Send + Sync {}
impl<T: AsRef<[u8]> + Clone + Send + Sync> Anyable for T {}
#[derive(Debug)]
pub struct IndexedReader<T: Anyable> {
data: ArcAny<T>,
pub(crate) reader: IndexedBufReader<Cursor<ArcAny<T>>>,
}
#[derive(Debug, Clone)]
pub struct ArcAny<T: Anyable>(Arc<T>);
impl<T: Anyable> AsRef<[u8]> for ArcAny<T> {
fn as_ref(&self) -> &[u8] {
self.0.as_ref().as_ref()
}
}
impl<T: Anyable> From<T> for ArcAny<T> {
fn from(s: T) -> Self {
Self(Arc::new(s))
}
}
impl From<&str> for ArcAny<String> {
fn from(s: &str) -> Self {
Self(Arc::new(s.to_owned()))
}
}
impl<T: Anyable> From<&T> for ArcAny<T> {
fn from(s: &T) -> Self {
Self(Arc::new(s.to_owned()))
}
}
impl<T: Anyable> IndexedReader<T> {
pub fn new<U: Into<ArcAny<T>>>(s: U) -> Result<IndexedReader<T>> {
let arc = s.into();
let mut reader = BufReader::new(Cursor::new(arc.clone()));
let index = Index::parse_index(&mut reader)?;
Ok(Self::from_reader(arc, reader, Arc::new(index)))
}
pub fn new_raw<U: Into<ArcAny<T>>>(s: U) -> Result<IndexedReader<T>> {
let arc = s.into();
let mut reader = BufReader::new(Cursor::new(arc.clone()));
let index = Index::build(&mut reader)?;
Ok(Self::from_reader(arc, reader, Arc::new(index)))
}
pub fn new_custom<U: Into<ArcAny<T>>>(s: U, index: Arc<Index>) -> IndexedReader<T> {
let arc = s.into();
let reader = BufReader::new(Cursor::new(arc.clone()));
Self::from_reader(arc, reader, index)
}
fn from_reader(
data: ArcAny<T>,
reader: BufReader<Cursor<ArcAny<T>>>,
index: Arc<Index>,
) -> IndexedReader<T> {
let reader = IndexedBufReader::new(reader, index);
Self { data, reader }
}
}
impl<T: Anyable> Indexable for IndexedReader<T> {
#[inline]
fn get_index(&self) -> &Index {
&self.reader.index
}
}
impl<T: Anyable> IndexableFile for IndexedReader<T> {
#[inline(always)]
fn read_current_line(&mut self, buf: &mut Vec<u8>, line: usize) -> Result<usize> {
self.reader.read_current_line(buf, line)
}
#[inline(always)]
fn seek_line(&mut self, line: usize) -> Result<()> {
self.reader.seek_line(line)
}
#[inline(always)]
fn write_to<W: Write + Unpin + Send>(&mut self, writer: &mut W) -> Result<usize> {
self.reader.write_to(writer)
}
}
impl<T: Anyable> Clone for IndexedReader<T> {
#[inline(always)]
fn clone(&self) -> Self {
let new_arc = self.data.clone();
Self {
reader: self
.reader
.duplicate(BufReader::with_capacity(1, Cursor::new(new_arc.clone()))),
data: new_arc,
}
}
}
impl<T: Anyable> ReadByLine for IndexedReader<T> {}