use std::ops::Index;
use std::fmt::{self, Write};
use std::io::{self, Read};
use std::iter::FromIterator;
use std::slice;
#[derive(Clone, Default)]
pub struct StrStack {
data: String,
ends: Vec<usize>,
}
impl Index<usize> for StrStack {
type Output = str;
#[inline]
fn index(&self, index: usize) -> &str {
unsafe {
assert!(index < self.len(), "index out of bounds");
self.get_unchecked(index)
}
}
}
#[derive(Clone)]
pub struct Iter<'a> {
data: &'a str,
ends: &'a [usize],
}
impl fmt::Debug for StrStack {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_list().entries(self.iter()).finish()
}
}
impl<'a> Iterator for Iter<'a> {
type Item = &'a str;
#[inline]
fn next(&mut self) -> Option<&'a str> {
unsafe {
let len = self.ends.len();
if len == 1 {
None
} else {
let start = *self.ends.get_unchecked(0);
let end = *self.ends.get_unchecked(1);
self.ends = slice::from_raw_parts(self.ends.as_ptr().offset(1), len - 1);
Some(self.data.slice_unchecked(start, end))
}
}
}
fn count(self) -> usize {
self.size_hint().0
}
fn last(mut self) -> Option<&'a str> {
self.next_back()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.ends.len() - 1;
(len, Some(len))
}
}
impl<'a> ExactSizeIterator for Iter<'a> {}
impl<'a> DoubleEndedIterator for Iter<'a> {
#[inline]
fn next_back(&mut self) -> Option<&'a str> {
unsafe {
let len = self.ends.len();
if len == 1 {
None
} else {
let start = *self.ends.get_unchecked(len-2);
let end = *self.ends.get_unchecked(len-1);
self.ends = slice::from_raw_parts(self.ends.as_ptr(), len - 1);
Some(self.data.slice_unchecked(start, end))
}
}
}
}
impl<'a> IntoIterator for &'a StrStack {
type IntoIter = Iter<'a>;
type Item = &'a str;
#[inline]
fn into_iter(self) -> Iter<'a> {
self.iter()
}
}
impl StrStack {
#[inline]
pub fn new() -> StrStack {
StrStack::with_capacity(0, 0)
}
#[inline]
pub fn with_capacity(bytes: usize, strings: usize) -> StrStack {
let mut stack = StrStack {
data: String::with_capacity(bytes),
ends: Vec::with_capacity(strings+1)
};
stack.ends.push(0);
stack
}
#[inline]
pub fn push(&mut self, s: &str) -> usize {
self.data.push_str(s);
self.ends.push(self.data.len());
self.len() - 1
}
#[inline]
pub fn iter(&self) -> Iter {
Iter {
data: &self.data,
ends: &self.ends,
}
}
#[inline]
pub fn pop(&mut self) -> bool {
if self.ends.len() <= 1 {
false
} else {
self.ends.pop();
self.data.truncate(*self.ends.last().unwrap());
true
}
}
#[inline]
pub fn clear(&mut self) {
self.ends.truncate(1);
self.data.clear();
}
#[inline]
pub fn len(&self) -> usize {
self.ends.len() - 1
}
#[inline]
pub fn truncate(&mut self, len: usize) {
self.ends.truncate(len.saturating_add(1));
self.data.truncate(*self.ends.last().unwrap());
}
pub fn consume<R: io::Read>(&mut self, mut source: R) -> io::Result<usize> {
match source.read_to_string(&mut self.data) {
Ok(_) => {
self.ends.push(self.data.len());
Ok(self.len() - 1)
},
Err(e) => Err(e),
}
}
#[inline]
pub fn writer(&mut self) -> Writer {
Writer(self)
}
#[inline]
pub fn write_fmt(&mut self, args: fmt::Arguments) -> usize {
let mut writer = self.writer();
let _ = writer.write_fmt(args);
writer.finish()
}
#[inline]
pub unsafe fn get_unchecked(&self, index: usize) -> &str {
let start = *self.ends.get_unchecked(index);
let end = *self.ends.get_unchecked(index+1);
self.data.slice_unchecked(start, end)
}
}
impl<S> Extend<S> for StrStack where S: AsRef<str> {
fn extend<T>(&mut self, iterator: T) where T: IntoIterator<Item=S> {
let iterator = iterator.into_iter();
let (min, _) = iterator.size_hint();
self.ends.reserve(min);
for v in iterator {
self.push(v.as_ref());
}
}
}
impl<S> FromIterator<S> for StrStack where S: AsRef<str> {
fn from_iter<T>(iterator: T) -> Self where T: IntoIterator<Item=S> {
let mut stack = StrStack::new();
stack.extend(iterator);
stack
}
}
pub struct Writer<'a>(&'a mut StrStack);
impl<'a> Writer<'a> {
#[inline]
pub fn finish(self) -> usize {
self.0.len()
}
}
impl<'a> fmt::Write for Writer<'a> {
#[inline]
fn write_str(&mut self, s: &str) -> fmt::Result {
self.0.data.push_str(s);
Ok(())
}
#[inline]
fn write_char(&mut self, c: char) -> fmt::Result {
self.0.data.push(c);
Ok(())
}
}
impl<'a> Drop for Writer<'a> {
fn drop(&mut self) {
self.0.ends.push(self.0.data.len());
}
}
#[test]
fn test_basic() {
let mut stack = StrStack::new();
let first = stack.push("one");
let second = stack.push("two");
let third = stack.push("three");
assert_eq!(&stack[first], "one");
assert_eq!(&stack[second], "two");
assert_eq!(&stack[third], "three");
assert_eq!(stack.len(), 3);
assert!(stack.pop());
assert_eq!(stack.len(), 2);
assert_eq!(&stack[first], "one");
assert_eq!(&stack[second], "two");
assert!(stack.pop());
assert!(stack.pop());
assert_eq!(stack.len(), 0);
assert!(!stack.pop());
}
#[test]
fn test_consume() {
let mut stack = StrStack::new();
let idx = stack.consume("testing".as_bytes()).unwrap();
assert_eq!(&stack[idx], "testing");
}
#[test]
fn test_writer() {
let mut stack = StrStack::new();
let first = {
let mut w = stack.writer();
write!(w, "{}", "first ").unwrap();
write!(w, "{}", "second").unwrap();
w.finish()
};
let second = {
let mut w = stack.writer();
write!(w, "{}", "third ").unwrap();
write!(w, "{}", "fourth").unwrap();
w.finish()
};
assert_eq!(&stack[first], "first second");
assert_eq!(&stack[second], "third fourth");
}
#[test]
fn test_iter() {
let mut stack = StrStack::new();
stack.push("one");
stack.push("two");
stack.push("three");
let v1: Vec<_> = stack.iter().collect();
let v2: Vec<_> = stack.iter().rev().collect();
assert_eq!(&v1[..], &["one", "two", "three"]);
assert_eq!(&v2[..], &["three", "two", "one"]);
}