use crate::core::{trim_cr, trim_end, SimpleLines};
use std::clone::Clone;
use std::default::Default;
use std::fmt::Debug;
use std::io;
use std::slice;
pub trait HeadWriter {
fn write_head<W>(&self, writer: W, start_byte: u8) -> io::Result<()>
where
W: io::Write;
}
impl<'a> HeadWriter for &'a [u8] {
fn write_head<W>(&self, mut writer: W, start_byte: u8) -> io::Result<()>
where
W: io::Write,
{
write!(writer, "{}", start_byte as char)?;
writer.write_all(self)?;
writer.write_all(b"\n")
}
}
macro_rules! impl_write_head {
($t:ty) => {
impl HeadWriter for $t {
fn write_head<W>(&self, writer: W, start_byte: u8) -> io::Result<()>
where
W: io::Write,
{
(&self[..]).write_head(writer, start_byte)
}
}
};
}
impl_write_head!(&Vec<u8>);
impl_write_head!(&[u8; 1]);
impl_write_head!(&[u8; 2]);
impl_write_head!(&[u8; 3]);
impl_write_head!(&[u8; 4]);
impl_write_head!(&[u8; 5]);
impl_write_head!(&[u8; 6]);
impl_write_head!(&[u8; 7]);
impl_write_head!(&[u8; 8]);
impl_write_head!(&[u8; 9]);
impl_write_head!(&[u8; 10]);
impl_write_head!(&[u8; 11]);
impl_write_head!(&[u8; 12]);
impl_write_head!(&[u8; 13]);
impl_write_head!(&[u8; 14]);
impl_write_head!(&[u8; 15]);
impl_write_head!(&[u8; 16]);
impl_write_head!(&[u8; 17]);
impl_write_head!(&[u8; 18]);
impl_write_head!(&[u8; 19]);
impl_write_head!(&[u8; 20]);
impl<'a> HeadWriter for &'a str {
fn write_head<W>(&self, writer: W, start_byte: u8) -> io::Result<()>
where
W: io::Write,
{
self.as_bytes().write_head(writer, start_byte)
}
}
impl<'a> HeadWriter for &String {
fn write_head<W>(&self, writer: W, start_byte: u8) -> io::Result<()>
where
W: io::Write,
{
self.as_str().write_head(writer, start_byte)
}
}
impl<'a> HeadWriter for (&'a [u8], Option<&'a [u8]>) {
fn write_head<W>(&self, mut writer: W, start_byte: u8) -> io::Result<()>
where
W: io::Write,
{
write!(writer, "{}", start_byte)?;
writer.write_all(self.0)?;
writer.write_all(b" ")?;
if let Some(desc) = self.1 {
writer.write_all(desc)?;
}
Ok(())
}
}
impl<'a> HeadWriter for (&Vec<u8>, Option<&Vec<u8>>) {
fn write_head<W>(&self, writer: W, start_byte: u8) -> io::Result<()>
where
W: io::Write,
{
(self.0.as_slice(), self.1.map(|d| d.as_slice())).write_head(writer, start_byte)
}
}
impl<'a> HeadWriter for (&'a str, Option<&str>) {
fn write_head<W>(&self, writer: W, start_byte: u8) -> io::Result<()>
where
W: io::Write,
{
(self.0.as_bytes(), self.1.map(|d| d.as_bytes())).write_head(writer, start_byte)
}
}
impl<'a> HeadWriter for (&String, Option<&String>) {
fn write_head<W>(&self, writer: W, start_byte: u8) -> io::Result<()>
where
W: io::Write,
{
(self.0.as_str(), self.1.map(|d| d.as_str())).write_head(writer, start_byte)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct Position {
pub(crate) line: u64,
pub(crate) byte: u64,
pub(crate) record: u64,
}
impl Position {
#[inline]
pub fn new() -> Position {
Position::default()
}
#[inline]
pub fn line(&self) -> u64 {
self.line
}
#[inline]
pub fn byte(&self) -> u64 {
self.byte
}
#[inline]
pub fn record(&self) -> u64 {
self.record
}
#[inline]
pub fn set_line(&mut self, line: u64) -> &mut Self {
self.line = line;
self
}
#[inline]
pub fn set_byte(&mut self, byte: u64) -> &mut Self {
self.byte = byte;
self
}
#[inline]
pub fn set_record(&mut self, idx: u64) -> &mut Self {
self.record = idx;
self
}
}
pub struct LinePositionIter<'a> {
data: &'a [u8],
pos_iter: slice::Windows<'a, usize>,
}
impl<'a> LinePositionIter<'a> {
#[inline]
pub fn new(buffer: &'a [u8], positions: &'a [usize]) -> Self {
LinePositionIter {
data: buffer,
pos_iter: positions.windows(2),
}
}
}
impl<'a> Iterator for LinePositionIter<'a> {
type Item = &'a [u8];
#[inline]
fn next(&mut self) -> Option<&'a [u8]> {
self.pos_iter
.next()
.map(|pos| trim_cr(&self.data[pos[0]..pos[1] - 1]))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.pos_iter.size_hint()
}
}
impl<'a> DoubleEndedIterator for LinePositionIter<'a> {
#[inline]
fn next_back(&mut self) -> Option<&'a [u8]> {
self.pos_iter
.next_back()
.map(|pos| trim_cr(&self.data[pos[0]..pos[1] - 1]))
}
}
impl<'a> ExactSizeIterator for LinePositionIter<'a> {}
#[derive(Debug)]
enum ParseType<'a> {
One(Option<&'a [u8]>),
Many(SimpleLines<'a>),
}
#[derive(Debug)]
pub struct LineSearchIter<'a> {
inner: ParseType<'a>,
}
impl<'a> LineSearchIter<'a> {
#[inline]
pub fn new(text: &'a [u8], one_line: bool) -> Self {
let inner = if one_line {
ParseType::One(Some(trim_end(text)))
} else {
ParseType::Many(SimpleLines::new(text))
};
LineSearchIter { inner }
}
}
impl<'a> Iterator for LineSearchIter<'a> {
type Item = &'a [u8];
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match self.inner {
ParseType::One(ref mut l) => l.take(),
ParseType::Many(ref mut parser) => parser.next(),
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
match self.inner {
ParseType::One(_) => (1, Some(1)),
ParseType::Many(ref parser) => parser.size_hint(),
}
}
}
impl<'a> DoubleEndedIterator for LineSearchIter<'a> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
match self.inner {
ParseType::One(ref mut l) => l.take(),
ParseType::Many(ref mut parser) => parser.next_back(),
}
}
}