Much simpler IOList, not obviously slower
This commit is contained in:
parent
c834f4b04a
commit
911f149892
|
@ -1,37 +1,29 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cell::RefCell;
|
use std::cmp::Ordering;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
#[derive(Eq, Debug)]
|
#[derive(Eq, Debug)]
|
||||||
pub struct IOList {
|
pub struct IOList {
|
||||||
chunks: RefCell<Vec<Vec<u8>>>,
|
chunks: Vec<Vec<u8>>,
|
||||||
len: usize,
|
len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IOList {
|
impl IOList {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
IOList {
|
IOList {
|
||||||
chunks: RefCell::new(Vec::new()),
|
chunks: vec![],
|
||||||
len: 0,
|
len: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rightmost_chunk(&mut self) -> &mut Vec<u8> {
|
fn rightmost_chunk(&mut self) -> &mut Vec<u8> {
|
||||||
let cs = self.chunks.get_mut();
|
if self.chunks.is_empty() {
|
||||||
if cs.is_empty() {
|
self.chunks.push(vec![]);
|
||||||
cs.push(Vec::new());
|
|
||||||
}
|
}
|
||||||
cs.last_mut().unwrap()
|
self.chunks.last_mut().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn consolidate(&self) {
|
pub fn len(&self) -> usize {
|
||||||
if self.chunks.borrow().len() != 1 {
|
|
||||||
let bs = self.chunks.replace(Vec::new()).concat();
|
|
||||||
self.chunks.borrow_mut().push(bs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn len(&mut self) -> usize {
|
|
||||||
self.len
|
self.len
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,41 +36,97 @@ impl IOList {
|
||||||
pub fn write_all(&mut self, cow: Cow<'_, [u8]>) {
|
pub fn write_all(&mut self, cow: Cow<'_, [u8]>) {
|
||||||
self.len += cow.len();
|
self.len += cow.len();
|
||||||
match cow {
|
match cow {
|
||||||
Cow::Borrowed(bs) => self.chunks.get_mut().push(bs.to_owned()),
|
Cow::Borrowed(bs) => self.chunks.push(bs.to_owned()),
|
||||||
Cow::Owned(bs) => self.chunks.get_mut().push(bs),
|
Cow::Owned(bs) => self.chunks.push(bs),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn append(&mut self, mut iol: IOList) {
|
pub fn append(&mut self, mut iol: IOList) {
|
||||||
self.len += iol.len();
|
self.len += iol.len();
|
||||||
self.chunks.get_mut().append(&mut iol.chunks.take());
|
self.chunks.append(&mut iol.chunks);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_to<W: io::Write>(self, mut w: W) -> io::Result<()> {
|
pub fn write_to<W: io::Write>(self, mut w: W) -> io::Result<()> {
|
||||||
for chunk in self.chunks.take() {
|
for chunk in self.chunks {
|
||||||
w.write_all(&chunk)?;
|
w.write_all(&chunk)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn iter<'a>(&'a self) -> IOListIterator<'a> {
|
||||||
|
IOListIterator { chunks: self.chunks.iter(), chunk: None }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct IOListIterator<'a> {
|
||||||
|
chunks: std::slice::Iter<'a, Vec<u8>>,
|
||||||
|
chunk: Option<std::slice::Iter<'a, u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for IOListIterator<'a> {
|
||||||
|
type Item = u8;
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
loop {
|
||||||
|
if self.chunk.is_none() {
|
||||||
|
self.chunk = self.chunks.next().map(|v| v.iter());
|
||||||
|
if self.chunk.is_none() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
match self.chunk.as_mut().unwrap().next() {
|
||||||
|
None => {
|
||||||
|
self.chunk = None;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Some(b) => return Some(*b),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoIterator for &'a IOList {
|
||||||
|
type Item = u8;
|
||||||
|
type IntoIter = IOListIterator<'a>;
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.iter()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::cmp::PartialEq for IOList {
|
impl std::cmp::PartialEq for IOList {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
self.consolidate();
|
let mut a = self.iter();
|
||||||
other.consolidate();
|
let mut b = other.iter();
|
||||||
self.chunks.borrow().last().unwrap() == other.chunks.borrow().last().unwrap()
|
loop {
|
||||||
|
let v = a.next();
|
||||||
|
if v != b.next() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if v.is_none() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::cmp::Ord for IOList {
|
impl std::cmp::Ord for IOList {
|
||||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
self.consolidate();
|
let mut a = self.iter();
|
||||||
other.consolidate();
|
let mut b = other.iter();
|
||||||
self.chunks.borrow().last().unwrap().cmp(other.chunks.borrow().last().unwrap())
|
loop {
|
||||||
|
match (a.next(), b.next()) {
|
||||||
|
(None, None) => return Ordering::Equal,
|
||||||
|
(Some(av), Some(bv)) => match av.cmp(&bv) {
|
||||||
|
Ordering::Equal => continue,
|
||||||
|
other => return other,
|
||||||
|
},
|
||||||
|
(Some(_), None) => return Ordering::Greater,
|
||||||
|
(None, Some(_)) => return Ordering::Less,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::cmp::PartialOrd for IOList {
|
impl PartialOrd for IOList {
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||||
Some(self.cmp(other))
|
Some(self.cmp(other))
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,7 @@ impl<W: io::Write> PackedWriter<W> {
|
||||||
|
|
||||||
pub fn finish_item(&mut self) -> io::Result<()> {
|
pub fn finish_item(&mut self) -> io::Result<()> {
|
||||||
if self.buffer.len() > 0 {
|
if self.buffer.len() > 0 {
|
||||||
let mut buffer = std::mem::replace(&mut self.buffer, IOList::new());
|
let buffer = std::mem::replace(&mut self.buffer, IOList::new());
|
||||||
match self.items.last_mut() {
|
match self.items.last_mut() {
|
||||||
Some(iols) => iols.push(buffer),
|
Some(iols) => iols.push(buffer),
|
||||||
None => {
|
None => {
|
||||||
|
@ -127,7 +127,7 @@ impl<W: io::Write> PackedWriter<W> {
|
||||||
items.sort();
|
items.sort();
|
||||||
}
|
}
|
||||||
self.write_tag(tag);
|
self.write_tag(tag);
|
||||||
for mut i in items {
|
for i in items {
|
||||||
varint(&mut self.buffer, i.len());
|
varint(&mut self.buffer, i.len());
|
||||||
self.buffer.append(i);
|
self.buffer.append(i);
|
||||||
}
|
}
|
||||||
|
@ -409,7 +409,7 @@ impl<W: io::Write> Writer for PackedWriter<W>
|
||||||
}
|
}
|
||||||
chunks.sort();
|
chunks.sort();
|
||||||
self.write_tag(Tag::Dictionary);
|
self.write_tag(Tag::Dictionary);
|
||||||
for (mut ki, mut vi) in chunks {
|
for (ki, vi) in chunks {
|
||||||
varint(&mut self.buffer, ki.len());
|
varint(&mut self.buffer, ki.len());
|
||||||
self.buffer.append(ki);
|
self.buffer.append(ki);
|
||||||
varint(&mut self.buffer, vi.len());
|
varint(&mut self.buffer, vi.len());
|
||||||
|
|
Loading…
Reference in New Issue