use std::borrow::Cow; use std::cell::RefCell; use std::io; #[derive(Eq, Debug)] pub struct IOList { chunks: RefCell>>, len: usize, } impl IOList { pub fn new() -> Self { IOList { chunks: RefCell::new(Vec::new()), len: 0, } } fn rightmost_chunk(&mut self) -> &mut Vec { let cs = self.chunks.get_mut(); if cs.is_empty() { cs.push(Vec::new()); } cs.last_mut().unwrap() } fn consolidate(&self) { 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 } pub fn write(&mut self, b: u8) { self.rightmost_chunk().push(b); self.len += 1; } #[inline(always)] pub fn write_all(&mut self, cow: Cow<'_, [u8]>) { self.len += cow.len(); match cow { Cow::Borrowed(bs) => self.chunks.get_mut().push(bs.to_owned()), Cow::Owned(bs) => self.chunks.get_mut().push(bs), } } pub fn append(&mut self, mut iol: IOList) { self.len += iol.len(); self.chunks.get_mut().append(&mut iol.chunks.take()); } pub fn write_to(self, mut w: W) -> io::Result<()> { for chunk in self.chunks.take() { w.write_all(&chunk)?; } Ok(()) } } impl std::cmp::PartialEq for IOList { fn eq(&self, other: &Self) -> bool { self.consolidate(); other.consolidate(); self.chunks.borrow().last().unwrap() == other.chunks.borrow().last().unwrap() } } impl std::cmp::Ord for IOList { fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.consolidate(); other.consolidate(); self.chunks.borrow().last().unwrap().cmp(other.chunks.borrow().last().unwrap()) } } impl std::cmp::PartialOrd for IOList { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } }