From: Kostya Shishkov Date: Fri, 29 May 2020 16:49:26 +0000 (+0200) Subject: core/io: introduce GrowableMemoryWriter X-Git-Url: https://git.nihav.org/?a=commitdiff_plain;h=422e87e4397fc168e568e629b8a0f2b6a9f01ad8;p=nihav.git core/io: introduce GrowableMemoryWriter --- diff --git a/nihav-core/src/io/byteio.rs b/nihav-core/src/io/byteio.rs index e7bb6c3..ff899fc 100644 --- a/nihav-core/src/io/byteio.rs +++ b/nihav-core/src/io/byteio.rs @@ -652,6 +652,16 @@ pub struct FileWriter { file: File, } +/// Bytestream writer to memory. +/// +/// Unlike [`MemoryWriter`] which writes to an array of fixed size, `GrowableMemoryWriter` grows output size when output size exceeds capacity. +/// +/// [`MemoryWriter`]: ./struct.MemoryWriter.html +pub struct GrowableMemoryWriter<'a> { + buf: &'a mut Vec, + pos: usize, +} + impl<'a> ByteWriter<'a> { /// Constructs a new instance of `ByteWriter`. pub fn new(io: &'a mut ByteIO) -> Self { ByteWriter { io } } @@ -831,6 +841,86 @@ impl<'a> ByteIO for MemoryWriter<'a> { } } +impl<'a> GrowableMemoryWriter<'a> { + + /// Constructs a new instance of `GrowableMemoryWriter`. + pub fn new_write(buf: &'a mut Vec) -> Self { + GrowableMemoryWriter { buf, pos: 0 } + } + + fn real_seek(&mut self, pos: i64) -> ByteIOResult { + if pos < 0 || (pos as usize) > self.buf.len() { + return Err(ByteIOError::WrongRange) + } + self.pos = pos as usize; + Ok(pos as u64) + } +} + +impl<'a> ByteIO for GrowableMemoryWriter<'a> { + #[allow(unused_variables)] + fn read_byte(&mut self) -> ByteIOResult { + Err(ByteIOError::NotImplemented) + } + + #[allow(unused_variables)] + fn peek_byte(&mut self) -> ByteIOResult { + Err(ByteIOError::NotImplemented) + } + + #[allow(unused_variables)] + fn read_buf(&mut self, buf: &mut [u8]) -> ByteIOResult { + Err(ByteIOError::NotImplemented) + } + + #[allow(unused_variables)] + fn read_buf_some(&mut self, buf: &mut [u8]) -> ByteIOResult { + Err(ByteIOError::NotImplemented) + } + + #[allow(unused_variables)] + fn peek_buf(&mut self, buf: &mut [u8]) -> ByteIOResult { + Err(ByteIOError::NotImplemented) + } + + fn write_buf(&mut self, buf: &[u8]) -> ByteIOResult<()> { + if self.pos + buf.len() > self.buf.len() { + self.buf.resize(self.pos + buf.len(), 0); + } + for i in 0..buf.len() { + self.buf[self.pos + i] = buf[i]; + } + self.pos += buf.len(); + Ok(()) + } + + fn tell(&mut self) -> u64 { + self.pos as u64 + } + + fn seek(&mut self, pos: SeekFrom) -> ByteIOResult { + let cur_pos = self.pos as i64; + let cur_size = self.buf.len() as i64; + match pos { + SeekFrom::Start(x) => self.real_seek(x as i64), + SeekFrom::Current(x) => self.real_seek(cur_pos + x), + SeekFrom::End(x) => self.real_seek(cur_size + x), + } + } + + fn is_eof(&self) -> bool { + self.pos >= self.buf.len() + } + + fn is_seekable(&mut self) -> bool { + true + } + + fn size(&mut self) -> i64 { + self.buf.len() as i64 + } +} + impl FileWriter { /// Constructs a new instance of `FileWriter`. pub fn new_write(file: File) -> Self {