diff --git a/src/store/mod.rs b/src/store/mod.rs index cd8a34e..99a01e8 100644 --- a/src/store/mod.rs +++ b/src/store/mod.rs @@ -1,3 +1,5 @@ +use std::io::{Read, Seek, SeekFrom}; + pub(crate) mod local; pub(crate) mod server; @@ -86,3 +88,61 @@ impl From for HashType { } } } + +struct EncryptionStream { + data: Vec, + pos: usize, +} + +impl Read for EncryptionStream { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + let range = self.pos..(self.pos + buf.len()).clamp(0, self.data.len() - buf.len()); + let size = range.len(); + buf.copy_from_slice(&self.data[range]); + Ok(size) + } +} + +impl Seek for EncryptionStream { + fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result { + let cur = self.pos; + + let newpos = match pos { + SeekFrom::Start(x) => { + if x > self.data.len() as u64 { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + "Seek position out of buffer bounds.", + )); + } + x + } + SeekFrom::End(x) => { + if x > self.data.len() as i64 { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + "Seek position out of buffer bounds.", + )); + } + + (self.data.len() as i64 - x) as u64 + } + SeekFrom::Current(x) => { + let new = self.pos as i64 + x; + + if new < 0 || new > self.data.len() as i64 { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + "Seek position out of buffer bounds.", + )); + } + + new as u64 + } + }; + + self.pos = newpos as usize; + + Ok(cur as u64) + } +}