use positioned_io::{ReadAt, Size, WriteAt}; use std::io::{Read, Seek, SeekFrom, Write}; use crate::{ sectored_buf::SectoredBuf, BlockMeta, Cursor, Decompose, FlushMeta, MetaAccess, Positioned, ReadDual, Result, SecretStream, Sectored, Split, TryCompose, TrySeek, WriteDual, }; pub use private::Accessor; mod private { use super::*; pub struct Accessor { inner: SectoredBuf>>, } impl + Size> Accessor { pub fn new(inner: T) -> Result> { let meta: &BlockMeta = inner.as_ref(); let key = meta.body.block_key()?.clone(); let inner = SecretStream::new(key).try_compose(Cursor::new(inner))?; Ok(Self { inner: SectoredBuf::new().try_compose(inner)?, }) } } impl Accessor { pub fn get_ref(&self) -> &T { self.inner.get_ref().get_ref().get_ref() } pub fn get_mut(&mut self) -> &mut T { self.inner.get_mut().get_mut().get_mut() } } impl + Size> Read for Accessor { fn read(&mut self, buf: &mut [u8]) -> std::io::Result { self.inner.read(buf) } } impl Write for Accessor { fn write(&mut self, buf: &[u8]) -> std::io::Result { self.inner.write(buf) } fn flush(&mut self) -> std::io::Result<()> { self.inner.flush() } } impl Seek for Accessor { fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result { self.inner.seek(pos) } } impl + Size> AsRef for Accessor { fn as_ref(&self) -> &U { self.inner.get_ref().as_ref() } } impl + Size> AsMut for Accessor { fn as_mut(&mut self) -> &mut U { self.inner.get_mut().as_mut() } } impl Decompose for Accessor { fn into_inner(self) -> T { self.inner.into_inner().into_inner().into_inner() } } impl FlushMeta for Accessor { fn flush_meta(&mut self) -> Result<()> { self.get_mut().flush_meta() } } impl Sectored for Accessor { fn sector_sz(&self) -> usize { self.inner.sector_sz() } } impl Size for Accessor { fn size(&self) -> std::io::Result> { self.inner.get_ref().size() } } impl WriteDual for Accessor { fn write_from(&mut self, read: R, count: usize) -> std::io::Result { self.inner.write_from(read, count) } } impl + Size> ReadDual for Accessor { fn read_into(&mut self, write: W, count: usize) -> std::io::Result { self.inner.read_into(write, count) } } impl Positioned for Accessor { fn pos(&self) -> usize { self.inner.pos() } } impl + Size> TrySeek for Accessor { fn try_seek(&mut self, seek_from: SeekFrom) -> std::io::Result<()> { self.inner.try_seek(seek_from) } } impl Split, T> for Accessor { fn split(self) -> (Accessor<&'static [u8]>, T) { let (sectored_buf, inner) = self.inner.split(); let (secret_stream, inner) = inner.split(); let (cursor, inner) = inner.split(); let new_inner = SectoredBuf::combine(sectored_buf, SecretStream::combine(secret_stream, cursor)); (Accessor { inner: new_inner }, inner) } fn combine(left: Accessor<&'static [u8]>, right: T) -> Self { let (sectored_buf, inner) = left.inner.split(); let (secret_stream, inner) = inner.split(); let (cursor, ..) = inner.split(); let new_inner = SectoredBuf::combine( sectored_buf, SecretStream::combine(secret_stream, Cursor::combine(cursor, right)), ); Accessor { inner: new_inner } } } } #[cfg(test)] mod test { use super::*; use crate::test_helpers::{make_block_with, node_creds}; #[test] fn can_wrap_block_ref() { let block = make_block_with(node_creds()) .into_inner() .into_inner() .into_inner(); let mut accessor = Accessor::new(block).expect("failed to wrap block"); const EXPECTED: &[u8] = &[1u8; 8]; accessor.write_all(EXPECTED).expect("write failed"); accessor.flush().expect("flush failed"); accessor.rewind().expect("rewind failed"); let block = accessor.into_inner(); let mut wrapped = Accessor::new(&block).expect("failed to wrap block reference"); let mut actual = [0u8; EXPECTED.len()]; wrapped.read(&mut actual).expect("read failed"); assert_eq!(EXPECTED, actual); } }