use collections::slice::{mod, AsSlice, SlicePrelude};
use collections::vec::{mod, Vec};
use core::clone::Clone;
use core::cmp::{Eq, PartialEq, Ord, PartialOrd, Ordering};
use core::fmt;
use core::mem;
use core::num::ToPrimitive;
use core::iter::{mod, order, Extend, AdditiveIterator, Iterator, FromIterator};
use core::iter::{DoubleEndedIterator, ExactSize};
use core::option::{mod, Some, None, Option};
use core::result::{Ok, Err};
use iobuf::Iobuf;
use BufSpan::{Empty, One, Many};
use SpanIter::{Opt, Lot};
use SpanMoveIter::{MoveOpt, MoveLot};
pub enum BufSpan<Buf> {
Empty,
One (Buf),
Many(Vec<Buf>),
}
impl<Buf: Iobuf> Clone for BufSpan<Buf> {
#[inline]
fn clone(&self) -> BufSpan<Buf> {
match *self {
Empty => Empty,
One(ref b) => One ((*b).clone()),
Many(ref v) => Many((*v).clone()),
}
}
}
impl<Buf: Iobuf> fmt::Show for BufSpan<Buf> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut first_time = true;
for b in self.iter() {
if !first_time {
try!(write!(f, "\n"));
}
try!(b.fmt(f));
first_time = false;
}
Ok(())
}
}
impl<Buf: Iobuf> FromIterator<Buf> for BufSpan<Buf> {
#[inline]
fn from_iter<T: Iterator<Buf>>(iterator: T) -> BufSpan<Buf> {
let mut ret = BufSpan::new();
ret.extend(iterator);
ret
}
}
impl<Buf: Iobuf> Extend<Buf> for BufSpan<Buf> {
#[inline]
fn extend<T: Iterator<Buf>>(&mut self, mut iterator: T) {
for x in iterator {
self.push(x);
}
}
}
impl<Buf: Iobuf> BufSpan<Buf> {
#[inline]
pub fn new() -> BufSpan<Buf> {
BufSpan::Empty
}
#[inline]
pub fn from_buf(b: Buf) -> BufSpan<Buf> {
if b.is_empty() { Empty } else { One(b) }
}
#[inline]
pub fn is_empty(&self) -> bool {
match *self {
Empty => true,
_ => false,
}
}
#[inline]
fn try_to_extend(&mut self, b: Buf) -> Option<Buf> {
if b.len() == 0 { return None; }
match *self {
Empty => {},
One(ref mut b0) => {
match b0.extend_with(&b) {
Ok (()) => return None,
Err(()) => return Some(b),
}
}
Many(ref mut v) => {
let last = v.last_mut().unwrap();
match last.extend_with(&b) {
Ok (()) => return None,
Err(()) => return Some(b),
}
}
}
*self = One(b);
None
}
#[inline]
pub fn push(&mut self, b: Buf) {
match self.try_to_extend(b) {
None => {},
Some(b) => self.slow_push(b),
}
}
fn slow_push(&mut self, b: Buf) {
let this = mem::replace(self, Empty);
*self =
match this {
Empty => One(b),
One(b0) => {
let mut v = Vec::with_capacity(2);
v.push(b0);
v.push(b);
Many(v)
},
Many(mut bs) => { bs.push(b); Many(bs) }
};
}
#[inline]
pub fn iter<'a>(&'a self) -> SpanIter<'a, Buf> {
match *self {
Empty => Opt(None.into_iter()),
One (ref b) => Opt(Some(b).into_iter()),
Many(ref v) => Lot(v.as_slice().iter()),
}
}
#[inline]
pub fn into_iter(self) -> SpanMoveIter<Buf> {
match self {
Empty => MoveOpt(None.into_iter()),
One (b) => MoveOpt(Some(b).into_iter()),
Many(v) => MoveLot(v.into_iter()),
}
}
#[inline]
pub fn iter_bytes<'a>(&'a self) -> ByteIter<'a, Buf> {
self.iter()
.flat_map(|buf| unsafe { buf.as_window_slice().iter() })
.map(|&b| b)
}
#[inline]
pub fn byte_equal<Buf2: Iobuf>(&self, other: &BufSpan<Buf2>) -> bool {
self.count_bytes_cmp(other.count_bytes() as uint) == Ordering::Equal
&& self.iter_bytes().zip(other.iter_bytes()).all(|(a, b)| a == b)
}
#[inline]
pub fn byte_equal_slice(&self, other: &[u8]) -> bool {
self.count_bytes_cmp(other.len()) == Ordering::Equal
&& self.iter_bytes().zip(other.iter()).all(|(a, &b)| a == b)
}
#[inline]
pub fn count_bytes(&self) -> u32 {
match *self {
Empty => 0,
One (ref b) => b.len(),
Many(ref v) => v.iter().map(|b| b.len()).sum(),
}
}
#[inline]
pub fn count_bytes_cmp(&self, other: uint) -> Ordering {
let mut other =
match other.to_u32() {
None => return Ordering::Less,
Some(other) => other,
};
match *self {
Empty => 0.cmp(&other),
One (ref b) => b.len().cmp(&other),
Many(ref v) => {
for b in v.iter() {
let len = b.len();
if len > other { return Ordering::Greater }
other -= len;
}
if other == 0 { Ordering::Equal }
else { Ordering::Less }
}
}
}
#[inline]
pub fn append(&mut self, other: BufSpan<Buf>) {
if self.is_empty() {
*self = other;
} else {
self.extend(other.into_iter())
}
}
#[inline]
pub fn starts_with(&self, other: &[u8]) -> bool {
if self.count_bytes_cmp(other.len()) == Ordering::Less { return false }
self.iter_bytes().zip(other.iter()).all(|(a, b)| a == *b)
}
#[inline]
pub fn ends_with(&self, other: &[u8]) -> bool {
if self.count_bytes_cmp(other.len()) == Ordering::Less { return false }
self.iter_bytes().rev().zip(other.iter().rev()).all(|(a, b)| a == *b)
}
}
impl<Buf: Iobuf> PartialEq for BufSpan<Buf> {
fn eq(&self, other: &BufSpan<Buf>) -> bool {
self.byte_equal(other)
}
}
impl<Buf: Iobuf> Eq for BufSpan<Buf> {}
impl<Buf: Iobuf> PartialOrd for BufSpan<Buf> {
fn partial_cmp(&self, other: &BufSpan<Buf>) -> Option<Ordering> {
order::partial_cmp(self.iter_bytes(), other.iter_bytes())
}
}
impl<Buf: Iobuf> Ord for BufSpan<Buf> {
fn cmp(&self, other: &BufSpan<Buf>) -> Ordering {
order::cmp(self.iter_bytes(), other.iter_bytes())
}
}
pub type ByteIter<'a, Buf> =
iter::Map<'static, &'a u8, u8,
iter::FlatMap<'static, &'a Buf,
SpanIter<'a, Buf>,
slice::Items<'a, u8>>>;
pub enum SpanIter<'a, Buf: 'a> {
Opt(option::Item<&'a Buf>),
Lot(slice::Items<'a, Buf>),
}
impl<'a, Buf: Iobuf> Clone for SpanIter<'a, Buf> {
#[inline(always)]
fn clone(&self) -> SpanIter<'a, Buf> {
match *self {
Opt(ref iter) => Opt((*iter).clone()),
Lot(ref iter) => Lot((*iter).clone()),
}
}
}
impl<'a, Buf: Iobuf> Iterator<&'a Buf> for SpanIter<'a, Buf> {
#[inline(always)]
fn next(&mut self) -> Option<&'a Buf> {
match *self {
Opt(ref mut iter) => iter.next(),
Lot(ref mut iter) => iter.next(),
}
}
#[inline(always)]
fn size_hint(&self) -> (uint, Option<uint>) {
match *self {
Opt(ref iter) => iter.size_hint(),
Lot(ref iter) => iter.size_hint(),
}
}
}
impl<'a, Buf: Iobuf> DoubleEndedIterator<&'a Buf> for SpanIter<'a, Buf> {
#[inline(always)]
fn next_back(&mut self) -> Option<&'a Buf> {
match *self {
Opt(ref mut iter) => iter.next_back(),
Lot(ref mut iter) => iter.next_back(),
}
}
}
impl<'a, Buf: Iobuf> ExactSize<&'a Buf> for SpanIter<'a, Buf> {}
pub enum SpanMoveIter<Buf> {
MoveOpt(option::Item<Buf>),
MoveLot(vec::MoveItems<Buf>),
}
impl<Buf: Iobuf> Iterator<Buf> for SpanMoveIter<Buf> {
#[inline(always)]
fn next(&mut self) -> Option<Buf> {
match *self {
MoveOpt(ref mut iter) => iter.next(),
MoveLot(ref mut iter) => iter.next(),
}
}
#[inline(always)]
fn size_hint(&self) -> (uint, Option<uint>) {
match *self {
MoveOpt(ref iter) => iter.size_hint(),
MoveLot(ref iter) => iter.size_hint(),
}
}
}
impl<Buf: Iobuf> DoubleEndedIterator<Buf> for SpanMoveIter<Buf> {
#[inline(always)]
fn next_back(&mut self) -> Option<Buf> {
match *self {
MoveOpt(ref mut iter) => iter.next_back(),
MoveLot(ref mut iter) => iter.next_back(),
}
}
}
impl<Buf: Iobuf> ExactSize<Buf> for SpanMoveIter<Buf> {}