From 36f13bea2ae7755172ac55e375d57b3dcce699f0 Mon Sep 17 00:00:00 2001 From: Szymon Walter Date: Thu, 22 Mar 2018 09:37:22 +0100 Subject: [PATCH] Reformat - `length::Length` was renamed as `size::Size` to better reflect the purpose - `sector::Size` was renamed as `sector::SectorSize` - lifetime names were given meaning (etc. `'vol`, `'inode`) - `Volume` and `Length` were changed to be generic over `S: SectorSize`, instead of `Idx` and now use `Address` as the only addressing (indexing) type --- src/fs.rs | 109 +++++++++++++++------------- src/sector.rs | 30 ++++---- src/sys/block_group.rs | 6 +- src/sys/inode.rs | 4 +- src/sys/superblock.rs | 6 +- src/volume/length.rs | 97 ------------------------- src/volume/mod.rs | 158 ++++++++++++++++------------------------- src/volume/size.rs | 100 ++++++++++++++++++++++++++ 8 files changed, 243 insertions(+), 267 deletions(-) delete mode 100644 src/volume/length.rs create mode 100644 src/volume/size.rs diff --git a/src/fs.rs b/src/fs.rs index 2742d5a..c4bd554 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -6,18 +6,18 @@ use core::nonzero::NonZero; use alloc::Vec; use error::Error; -use sector::{Address, Size}; +use sector::{Address, SectorSize}; use volume::{Volume, VolumeSlice}; use sys::superblock::Superblock; use sys::block_group::BlockGroupDescriptor; use sys::inode::Inode as RawInode; -struct Struct { +struct Struct { pub inner: T, pub offset: Address, } -impl From<(T, Address)> for Struct { +impl From<(T, Address)> for Struct { #[inline] fn from((inner, offset): (T, Address)) -> Struct { Struct { inner, offset } @@ -25,13 +25,13 @@ impl From<(T, Address)> for Struct { } /// Safe wrapper for raw sys structs -pub struct Ext2>> { +pub struct Ext2> { volume: V, superblock: Struct, block_groups: Struct, S>, } -impl>> Ext2 { +impl> Ext2 { pub fn new(volume: V) -> Result, Error> { let superblock = unsafe { Struct::from(Superblock::find(&volume)?) }; let block_groups_offset = Address::with_block_size( @@ -87,10 +87,10 @@ impl>> Ext2 { Ok(()) } - pub fn read_inode<'a>( - &'a self, + pub fn read_inode<'vol>( + &'vol self, buf: &mut [u8], - inode: &Inode<'a, S, V>, + inode: &Inode<'vol, S, V>, ) -> Result { let total_size = inode.size(); let block_size = self.block_size(); @@ -113,30 +113,30 @@ impl>> Ext2 { Ok(offset) } - pub fn write_inode<'a>( - &'a self, - _inode: &(Inode<'a, S, V>, Address), + pub fn write_inode<'vol>( + &'vol self, + _inode: &(Inode<'vol, S, V>, Address), _buf: &[u8], ) -> Result { unimplemented!() } - pub fn root_inode<'a>(&'a self) -> (Inode<'a, S, V>, Address) { + pub fn root_inode<'vol>(&'vol self) -> (Inode<'vol, S, V>, Address) { self.inode_nth(2).unwrap() } - pub fn inode_nth<'a>( - &'a self, + pub fn inode_nth<'vol>( + &'vol self, index: usize, - ) -> Option<(Inode<'a, S, V>, Address)> { + ) -> Option<(Inode<'vol, S, V>, Address)> { self.inodes_nth(index).next() } - pub fn inodes<'a>(&'a self) -> Inodes<'a, S, V> { + pub fn inodes<'vol>(&'vol self) -> Inodes<'vol, S, V> { self.inodes_nth(1) } - pub fn inodes_nth<'a>(&'a self, index: usize) -> Inodes<'a, S, V> { + pub fn inodes_nth<'vol>(&'vol self, index: usize) -> Inodes<'vol, S, V> { assert!(index > 0, "inodes are 1-indexed"); Inodes { fs: self, @@ -162,9 +162,9 @@ impl>> Ext2 { (self.superblock().rev_major, self.superblock().rev_minor) } - pub fn inode_size<'a>(&'a self) -> usize { + pub fn inode_size<'vol>(&'vol self) -> usize { if self.version().0 == 0 { - mem::size_of::>() + mem::size_of::>() } else { // note: inodes bigger than 128 are not supported self.superblock().inode_size as usize @@ -214,15 +214,15 @@ impl>> Ext2 { } } -impl>> Debug for Ext2 { +impl> Debug for Ext2 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Ext2<{}>", S::SIZE) } } -pub struct Inodes<'a, S: 'a + Size, V: 'a + Volume>> { - fs: &'a Ext2, - block_groups: &'a [BlockGroupDescriptor], +pub struct Inodes<'vol, S: 'vol + SectorSize, V: 'vol + Volume> { + fs: &'vol Ext2, + block_groups: &'vol [BlockGroupDescriptor], log_block_size: u32, inode_size: usize, inodes_per_group: usize, @@ -230,10 +230,10 @@ pub struct Inodes<'a, S: 'a + Size, V: 'a + Volume>> { index: usize, } -impl<'a, S: Size, V: 'a + Volume>> Iterator - for Inodes<'a, S, V> +impl<'vol, S: SectorSize, V: 'vol + Volume> Iterator + for Inodes<'vol, S, V> { - type Item = (Inode<'a, S, V>, Address); + type Item = (Inode<'vol, S, V>, Address); fn next(&mut self) -> Option { if self.index < self.inodes_count { @@ -260,24 +260,26 @@ impl<'a, S: Size, V: 'a + Volume>> Iterator } #[derive(Debug, Clone)] -pub struct Inode<'a, S: 'a + Size, V: 'a + Volume>> { - fs: &'a Ext2, +pub struct Inode<'vol, S: 'vol + SectorSize, V: 'vol + Volume> { + fs: &'vol Ext2, inner: RawInode, } -impl<'a, S: 'a + Size, V: 'a + Volume>> Inode<'a, S, V> { - pub fn new(fs: &'a Ext2, inner: RawInode) -> Inode<'a, S, V> { +impl<'vol, S: 'vol + SectorSize, V: 'vol + Volume> Inode<'vol, S, V> { + pub fn new(fs: &'vol Ext2, inner: RawInode) -> Inode<'vol, S, V> { Inode { fs, inner } } - pub fn blocks<'b>(&'b self) -> InodeBlocks<'a, 'b, S, V> { + pub fn blocks<'inode>(&'inode self) -> InodeBlocks<'vol, 'inode, S, V> { InodeBlocks { inode: self, index: 0, } } - pub fn directory<'b>(&'b self) -> Option> { + pub fn directory<'inode>( + &'inode self, + ) -> Option> { use sys::inode::TypePerm; if unsafe { self.inner.type_perm.contains(TypePerm::DIRECTORY) } { Some(Directory { @@ -313,7 +315,7 @@ impl<'a, S: 'a + Size, V: 'a + Volume>> Inode<'a, S, V> { // - that's n/4 blocks with n/4 pointers each = (n/4)^2 // number of blocks in triply table: (block_size/4)^3 - fn block_index>>( + fn block_index>( volume: &V, block: u32, index: usize, @@ -437,16 +439,20 @@ impl<'a, S: 'a + Size, V: 'a + Volume>> Inode<'a, S, V> { } } -pub struct InodeBlocks<'a: 'b, 'b, S: 'a + Size, V: 'a + Volume>> -{ - inode: &'b Inode<'a, S, V>, +pub struct InodeBlocks< + 'vol: 'inode, + 'inode, + S: 'vol + SectorSize, + V: 'vol + Volume, +> { + inode: &'inode Inode<'vol, S, V>, index: usize, } -impl<'a, 'b, S: Size, V: 'a + Volume>> Iterator - for InodeBlocks<'a, 'b, S, V> +impl<'vol, 'inode, S: SectorSize, V: 'vol + Volume> Iterator + for InodeBlocks<'vol, 'inode, S, V> { - type Item = Result<(VolumeSlice<'a, u8, Address>, Address), Error>; + type Item = Result<(VolumeSlice<'vol, u8, S>, Address), Error>; fn next(&mut self) -> Option { let block = self.inode.try_block(self.index); @@ -473,17 +479,22 @@ impl<'a, 'b, S: Size, V: 'a + Volume>> Iterator } } -pub struct Directory<'a: 'b, 'b, S: 'a + Size, V: 'a + Volume>> { - blocks: InodeBlocks<'a, 'b, S, V>, +pub struct Directory< + 'vol: 'inode, + 'inode, + S: 'vol + SectorSize, + V: 'vol + Volume, +> { + blocks: InodeBlocks<'vol, 'inode, S, V>, offset: usize, - buffer: Option>>, + buffer: Option>, block_size: usize, } -impl<'a, 'b, S: Size, V: 'a + Volume>> Iterator - for Directory<'a, 'b, S, V> +impl<'vol, 'inode, S: SectorSize, V: 'vol + Volume> Iterator + for Directory<'vol, 'inode, S, V> { - type Item = Result, Error>; + type Item = Result, Error>; fn next(&mut self) -> Option { if self.buffer.is_none() || self.offset >= self.block_size { @@ -533,7 +544,7 @@ mod tests { use std::fs::File; use std::cell::RefCell; - use sector::{Address, Size, Size512}; + use sector::{Address, SectorSize, Size512}; use volume::Volume; use super::{Ext2, Inode}; @@ -675,9 +686,9 @@ mod tests { fn walkdir() { use std::str; - fn walk<'a, S: Size, V: Volume>>( - fs: &'a Ext2, - inode: Inode<'a, S, V>, + fn walk<'vol, S: SectorSize, V: Volume>( + fs: &'vol Ext2, + inode: Inode<'vol, S, V>, name: String, ) { inode.directory().map(|dir| { diff --git a/src/sector.rs b/src/sector.rs index 2d24b02..911f93a 100644 --- a/src/sector.rs +++ b/src/sector.rs @@ -4,7 +4,7 @@ use core::ops::{Add, Sub}; use core::fmt::{self, Debug, Display, LowerHex}; use core::iter::Step; -pub trait Size: Clone + Copy + PartialOrd { +pub trait SectorSize: Clone + Copy + PartialEq + PartialOrd { // log_sector_size = log_2(sector_size) const LOG_SIZE: u32; const SIZE: usize = 1 << Self::LOG_SIZE; @@ -13,37 +13,37 @@ pub trait Size: Clone + Copy + PartialOrd { #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct Size512; -impl Size for Size512 { +impl SectorSize for Size512 { const LOG_SIZE: u32 = 9; } #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct Size1024; -impl Size for Size1024 { +impl SectorSize for Size1024 { const LOG_SIZE: u32 = 10; } #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct Size2048; -impl Size for Size2048 { +impl SectorSize for Size2048 { const LOG_SIZE: u32 = 11; } #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct Size4096; -impl Size for Size4096 { +impl SectorSize for Size4096 { const LOG_SIZE: u32 = 12; } /// Address in a physical sector #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] -pub struct Address { +pub struct Address { sector: u32, offset: u32, _phantom: PhantomData, } -impl Address { +impl Address { pub unsafe fn new_unchecked(sector: u32, offset: u32) -> Address { assert!((offset as usize) < S::SIZE, "offset out of sector bounds"); let _phantom = PhantomData; @@ -96,7 +96,7 @@ impl Address { } } -impl Step for Address { +impl Step for Address { fn steps_between(start: &Self, end: &Self) -> Option { if end.sector >= start.sector { Some(end.sector as usize - start.sector as usize) @@ -128,7 +128,7 @@ impl Step for Address { } } -impl Debug for Address { +impl Debug for Address { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let name = format!("Address<{}>", S::SIZE); f.debug_struct(&name) @@ -138,19 +138,19 @@ impl Debug for Address { } } -impl Display for Address { +impl Display for Address { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}:{}", self.sector, self.offset) } } -impl LowerHex for Address { +impl LowerHex for Address { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:x}:{:x}", self.sector, self.offset) } } -impl From for Address { +impl From for Address { fn from(idx: u64) -> Address { let sector = idx >> S::LOG_SIZE; let offset = idx & S::OFFSET_MASK as u64; @@ -158,7 +158,7 @@ impl From for Address { } } -impl From for Address { +impl From for Address { fn from(idx: usize) -> Address { let sector = idx >> S::LOG_SIZE; let offset = idx & S::OFFSET_MASK as usize; @@ -166,7 +166,7 @@ impl From for Address { } } -impl Add for Address { +impl Add for Address { type Output = Address; fn add(self, rhs: Address) -> Address { Address::new( @@ -176,7 +176,7 @@ impl Add for Address { } } -impl Sub for Address { +impl Sub for Address { type Output = Address; fn sub(self, rhs: Address) -> Address { Address::new( diff --git a/src/sys/block_group.rs b/src/sys/block_group.rs index fc9b00d..cb669a5 100644 --- a/src/sys/block_group.rs +++ b/src/sys/block_group.rs @@ -4,7 +4,7 @@ use core::fmt::{self, Debug}; use alloc::Vec; use error::Error; -use sector::{Address, Size}; +use sector::{Address, SectorSize}; use volume::Volume; /// The Block Group Descriptor Table contains a descriptor for each block group @@ -52,7 +52,7 @@ impl Debug for BlockGroupDescriptor { } impl BlockGroupDescriptor { - pub unsafe fn find_descriptor>>( + pub unsafe fn find_descriptor>( haystack: &V, offset: Address, ) -> Result<(BlockGroupDescriptor, Address), Error> { @@ -73,7 +73,7 @@ impl BlockGroupDescriptor { Ok(descr) } - pub unsafe fn find_descriptor_table>>( + pub unsafe fn find_descriptor_table>( haystack: &V, offset: Address, count: usize, diff --git a/src/sys/inode.rs b/src/sys/inode.rs index c121985..40b9288 100644 --- a/src/sys/inode.rs +++ b/src/sys/inode.rs @@ -2,7 +2,7 @@ use core::mem; use core::fmt::{self, Debug}; use error::Error; -use sector::{Address, Size}; +use sector::{Address, SectorSize}; use volume::Volume; /// An inode is a structure on the disk that represents a file, directory, @@ -97,7 +97,7 @@ impl Debug for Inode { } impl Inode { - pub unsafe fn find_inode>>( + pub unsafe fn find_inode>( haystack: &V, offset: Address, size: usize, diff --git a/src/sys/superblock.rs b/src/sys/superblock.rs index 276c97a..c81a776 100644 --- a/src/sys/superblock.rs +++ b/src/sys/superblock.rs @@ -2,7 +2,7 @@ use core::mem; use core::fmt::{self, Debug}; use error::Error; -use sector::{Address, Size}; +use sector::{Address, SectorSize}; use volume::Volume; /// Ext2 signature (0xef53), used to help confirm the presence of Ext2 on a @@ -106,7 +106,7 @@ pub struct Superblock { /// First non-reserved inode in file system. pub first_inode: u32, - /// Size of each inode structure in bytes. + /// SectorSize of each inode structure in bytes. pub inode_size: u16, /// Block group that this superblock is part of (if backup copy) pub block_group: u16, @@ -195,7 +195,7 @@ impl Debug for Superblock { } impl Superblock { - pub unsafe fn find>>( + pub unsafe fn find>( haystack: &V, ) -> Result<(Superblock, Address), Error> { let offset = Address::from(1024_usize); diff --git a/src/volume/length.rs b/src/volume/length.rs deleted file mode 100644 index a370002..0000000 --- a/src/volume/length.rs +++ /dev/null @@ -1,97 +0,0 @@ -use core::fmt::{self, Debug, Display}; -use core::cmp::Ordering; - -#[derive(Clone, Copy, Debug, Hash)] -pub enum Length { - Unbounded, - Bounded(Idx), -} - -impl Length { - pub fn try_len(&self) -> Option { - match *self { - Length::Unbounded => None, - Length::Bounded(n) => Some(n), - } - } - - pub unsafe fn len(&self) -> Idx { - match *self { - Length::Unbounded => panic!( - "attempt to convert `Length::Unbounded` to `Length::Idx`" - ), - Length::Bounded(n) => n, - } - } -} - -impl Length { - pub fn is_bounded(&self) -> bool { - match *self { - Length::Unbounded => false, - Length::Bounded(_) => true, - } - } -} - -impl Display for Length { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - Debug::fmt(self, f) - } -} - -impl PartialEq for Length { - fn eq(&self, rhs: &Self) -> bool { - match (self, rhs) { - (&Length::Unbounded, _) => false, - (_, &Length::Unbounded) => false, - (&Length::Bounded(ref a), &Length::Bounded(ref b)) => a.eq(b), - } - } - - fn ne(&self, rhs: &Self) -> bool { - match (self, rhs) { - (&Length::Unbounded, _) => false, - (_, &Length::Unbounded) => false, - (&Length::Bounded(ref a), &Length::Bounded(ref b)) => a.ne(b), - } - } -} - -impl PartialEq for Length { - fn eq(&self, rhs: &Idx) -> bool { - match *self { - Length::Unbounded => false, - Length::Bounded(ref n) => n.eq(rhs), - } - } - - fn ne(&self, rhs: &Idx) -> bool { - match *self { - Length::Unbounded => false, - Length::Bounded(ref n) => n.eq(rhs), - } - } -} - -impl PartialOrd for Length { - fn partial_cmp(&self, rhs: &Self) -> Option { - match (self, rhs) { - (&Length::Unbounded, &Length::Unbounded) => None, - (&Length::Unbounded, _) => Some(Ordering::Greater), - (_, &Length::Unbounded) => Some(Ordering::Less), - (&Length::Bounded(ref a), &Length::Bounded(ref b)) => { - a.partial_cmp(b) - } - } - } -} - -impl PartialOrd for Length { - fn partial_cmp(&self, rhs: &Idx) -> Option { - match *self { - Length::Unbounded => Some(Ordering::Greater), - Length::Bounded(ref n) => n.partial_cmp(rhs), - } - } -} diff --git a/src/volume/mod.rs b/src/volume/mod.rs index 197fba1..c5eaebf 100644 --- a/src/volume/mod.rs +++ b/src/volume/mod.rs @@ -7,62 +7,47 @@ use alloc::boxed::Box; use alloc::borrow::{Cow, ToOwned}; use error::Error; -use sector::{Address, Size}; +use sector::{Address, SectorSize}; -pub mod length; -use self::length::Length; +pub mod size; +use self::size::Size; -pub trait Volume -where - [T]: ToOwned, - Idx: PartialEq + PartialOrd, -{ +pub trait Volume { type Error: Into; - fn size(&self) -> Length; + fn size(&self) -> Size; fn commit( &mut self, - slice: Option>, + slice: Option>, ) -> Result<(), Self::Error>; unsafe fn slice_unchecked<'a>( &'a self, - range: Range, - ) -> VolumeSlice<'a, T, Idx>; + range: Range>, + ) -> VolumeSlice<'a, T, S>; fn slice<'a>( &'a self, - range: Range, - ) -> Result, Self::Error>; + range: Range>, + ) -> Result, Self::Error>; } -pub struct VolumeSlice<'a, T: 'a, Idx> -where - [T]: ToOwned, -{ +pub struct VolumeSlice<'a, T: 'a + Clone, S: SectorSize> { inner: Cow<'a, [T]>, - index: Idx, + index: Address, } -impl VolumeSlice<'static, T, Idx> -where - [T]: ToOwned, -{ - pub fn with_static(inner: &'static [T]) -> VolumeSlice<'static, T, Idx> { +impl VolumeSlice<'static, T, S> { + pub fn with_static(inner: &'static [T]) -> VolumeSlice<'static, T, S> { VolumeSlice { inner: Cow::Borrowed(inner), - index: Idx::default(), + index: Address::new(0, 0), } } -} -impl VolumeSlice<'static, T, Idx> -where - [T]: ToOwned, -{ pub fn new_owned( inner: <[T] as ToOwned>::Owned, - index: Idx, - ) -> VolumeSlice<'static, T, Idx> { + index: Address, + ) -> VolumeSlice<'static, T, S> { VolumeSlice { inner: Cow::Owned(inner), index, @@ -70,11 +55,8 @@ where } } -impl<'a, T, Idx> VolumeSlice<'a, T, Idx> -where - [T]: ToOwned, -{ - pub fn new(inner: &'a [T], index: Idx) -> VolumeSlice<'a, T, Idx> { +impl<'a, T: Clone, S: SectorSize> VolumeSlice<'a, T, S> { + pub fn new(inner: &'a [T], index: Address) -> VolumeSlice<'a, T, S> { VolumeSlice { inner: Cow::Borrowed(inner), index, @@ -88,13 +70,13 @@ where } } - pub fn at_index(&self) -> &Idx { - &self.index + pub fn address(&self) -> Address { + self.index } } -impl<'a, Idx: Copy> VolumeSlice<'a, u8, Idx> { - pub unsafe fn dynamic_cast(&self) -> (T, Idx) { +impl<'a, S: SectorSize> VolumeSlice<'a, u8, S> { + pub unsafe fn dynamic_cast(&self) -> (T, Address) { assert!(self.inner.len() >= mem::size_of::()); let index = self.index; let cast = mem::transmute_copy(self.inner.as_ptr().as_ref().unwrap()); @@ -103,8 +85,8 @@ impl<'a, Idx: Copy> VolumeSlice<'a, u8, Idx> { pub fn from_cast( cast: &'a T, - index: Idx, - ) -> VolumeSlice<'a, u8, Idx> { + index: Address, + ) -> VolumeSlice<'a, u8, S> { let len = mem::size_of::(); let ptr = cast as *const T as *const u8; let slice = unsafe { slice::from_raw_parts(ptr, len) }; @@ -112,11 +94,8 @@ impl<'a, Idx: Copy> VolumeSlice<'a, u8, Idx> { } } -impl<'a, T, Idx> VolumeSlice<'a, T, Idx> -where - [T]: ToOwned>, -{ - pub fn commit(self) -> Option> { +impl<'a, T: Clone, S: SectorSize> VolumeSlice<'a, T, S> { + pub fn commit(self) -> Option> { if self.is_mutated() { Some(VolumeCommit::new(self.inner.into_owned(), self.index)) } else { @@ -125,29 +104,19 @@ where } } -impl<'a, T, Idx> AsRef<[T]> for VolumeSlice<'a, T, Idx> -where - [T]: ToOwned, -{ +impl<'a, T: Clone, S: SectorSize> AsRef<[T]> for VolumeSlice<'a, T, S> { fn as_ref(&self) -> &[T] { self.inner.as_ref() } } -impl<'a, T, Idx> AsMut<[T]> for VolumeSlice<'a, T, Idx> -where - [T]: ToOwned, - <[T] as ToOwned>::Owned: AsMut<[T]>, -{ +impl<'a, T: Clone, S: SectorSize> AsMut<[T]> for VolumeSlice<'a, T, S> { fn as_mut(&mut self) -> &mut [T] { self.inner.to_mut().as_mut() } } -impl<'a, T, Idx> Deref for VolumeSlice<'a, T, Idx> -where - [T]: ToOwned, -{ +impl<'a, T: Clone, S: SectorSize> Deref for VolumeSlice<'a, T, S> { type Target = [T]; fn deref(&self) -> &Self::Target { @@ -155,32 +124,28 @@ where } } -impl<'a, T, Idx> DerefMut for VolumeSlice<'a, T, Idx> -where - [T]: ToOwned, - <[T] as ToOwned>::Owned: AsMut<[T]>, -{ +impl<'a, T: Clone, S: SectorSize> DerefMut for VolumeSlice<'a, T, S> { fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut() } } -pub struct VolumeCommit { +pub struct VolumeCommit { inner: Vec, - index: Idx, + index: Address, } -impl VolumeCommit { - pub fn with_vec(inner: Vec) -> VolumeCommit { +impl VolumeCommit { + pub fn with_vec(inner: Vec) -> VolumeCommit { VolumeCommit { inner, - index: Idx::default(), + index: Address::new(0, 0), } } } -impl VolumeCommit { - pub fn new(inner: Vec, index: Idx) -> VolumeCommit { +impl VolumeCommit { + pub fn new(inner: Vec, index: Address) -> VolumeCommit { VolumeCommit { inner, index } } @@ -188,24 +153,24 @@ impl VolumeCommit { self.inner } - pub fn at_index(&self) -> &Idx { - &self.index + pub fn address(&self) -> Address { + self.index } } -impl AsRef<[T]> for VolumeCommit { +impl AsRef<[T]> for VolumeCommit { fn as_ref(&self) -> &[T] { self.inner.as_ref() } } -impl AsMut<[T]> for VolumeCommit { +impl AsMut<[T]> for VolumeCommit { fn as_mut(&mut self) -> &mut [T] { self.inner.as_mut() } } -impl Deref for VolumeCommit { +impl Deref for VolumeCommit { type Target = [T]; fn deref(&self) -> &Self::Target { @@ -213,7 +178,7 @@ impl Deref for VolumeCommit { } } -impl DerefMut for VolumeCommit { +impl DerefMut for VolumeCommit { fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut() } @@ -221,26 +186,23 @@ impl DerefMut for VolumeCommit { macro_rules! impl_slice { (@inner $volume:ty $( , $lt:lifetime )* ) => { - impl<$( $lt, )* S: Size, T> Volume> + impl<$( $lt, )* T: Clone, S: SectorSize> Volume for $volume - where - T: Clone, - [T]: ToOwned, { type Error = Error; - fn size(&self) -> Length> { - Length::Bounded( + fn size(&self) -> Size { + Size::Bounded( Address::from(>::as_ref(self).len()) ) } fn commit( &mut self, - slice: Option>>, + slice: Option>, ) -> Result<(), Self::Error> { slice.map(|slice| { - let index = slice.at_index().into_index() as usize; + let index = slice.address().into_index() as usize; let end = index + slice.as_ref().len(); // XXX: it would be much better to drop the contents of dst // and move the contents of slice instead of cloning @@ -254,7 +216,7 @@ macro_rules! impl_slice { unsafe fn slice_unchecked<'a>( &'a self, range: Range>, - ) -> VolumeSlice<'a, T, Address> { + ) -> VolumeSlice<'a, T, S> { let index = range.start; let range = range.start.into_index() as usize ..range.end.into_index() as usize; @@ -267,7 +229,7 @@ macro_rules! impl_slice { fn slice<'a>( &'a self, range: Range>, - ) -> Result>, Self::Error> { + ) -> Result, Self::Error> { if self.size() >= range.end { unsafe { Ok(self.slice_unchecked(range)) } } else { @@ -299,16 +261,16 @@ mod file { use std::fs::File; use std::cell::RefCell; - use sector::{Address, Size}; + use sector::{Address, SectorSize}; use super::{Volume, VolumeCommit, VolumeSlice}; - use super::length::Length; + use super::size::Size; - impl Volume> for RefCell { + impl Volume for RefCell { type Error = io::Error; - fn size(&self) -> Length> { - Length::Bounded( + fn size(&self) -> Size { + Size::Bounded( self.borrow() .metadata() .map(|data| Address::from(data.len())) @@ -318,11 +280,11 @@ mod file { fn commit( &mut self, - slice: Option>>, + slice: Option>, ) -> Result<(), Self::Error> { slice .map(|slice| { - let index = *slice.at_index(); + let index = slice.address(); let mut refmut = self.borrow_mut(); refmut .seek(SeekFrom::Start(index.into_index())) @@ -335,7 +297,7 @@ mod file { unsafe fn slice_unchecked<'a>( &'a self, range: Range>, - ) -> VolumeSlice<'a, u8, Address> { + ) -> VolumeSlice<'a, u8, S> { let index = range.start; let len = range.end - range.start; let mut vec = Vec::with_capacity(len.into_index() as usize); @@ -353,7 +315,7 @@ mod file { fn slice<'a>( &'a self, range: Range>, - ) -> Result>, Self::Error> { + ) -> Result, Self::Error> { let index = range.start; let mut vec = Vec::with_capacity((range.end - range.start) .into_index() diff --git a/src/volume/size.rs b/src/volume/size.rs new file mode 100644 index 0000000..3c6b4d0 --- /dev/null +++ b/src/volume/size.rs @@ -0,0 +1,100 @@ +use core::fmt::{self, Display}; +use core::cmp::Ordering; + +use sector::{Address, SectorSize}; + +#[derive(Clone, Copy, Debug, Hash)] +pub enum Size { + Unbounded, + Bounded(Address), +} + +impl Size { + pub fn try_len(&self) -> Option> { + match *self { + Size::Unbounded => None, + Size::Bounded(n) => Some(n), + } + } + + pub unsafe fn len(&self) -> Address { + match *self { + Size::Unbounded => panic!( + "attempt to convert `Size::Unbounded` to a concrete length" + ), + Size::Bounded(n) => n, + } + } +} + +impl Size { + pub fn is_bounded(&self) -> bool { + match *self { + Size::Unbounded => false, + Size::Bounded(_) => true, + } + } +} + +impl Display for Size { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Size::Unbounded => write!(f, "Unbounded"), + Size::Bounded(n) => write!(f, "Bounded({})", n), + } + } +} + +impl PartialEq for Size { + fn eq(&self, rhs: &Self) -> bool { + match (self, rhs) { + (&Size::Unbounded, _) => false, + (_, &Size::Unbounded) => false, + (&Size::Bounded(ref a), &Size::Bounded(ref b)) => a.eq(b), + } + } + + fn ne(&self, rhs: &Self) -> bool { + match (self, rhs) { + (&Size::Unbounded, _) => false, + (_, &Size::Unbounded) => false, + (&Size::Bounded(ref a), &Size::Bounded(ref b)) => a.ne(b), + } + } +} + +impl PartialEq> for Size { + fn eq(&self, rhs: &Address) -> bool { + match *self { + Size::Unbounded => false, + Size::Bounded(ref n) => n.eq(rhs), + } + } + + fn ne(&self, rhs: &Address) -> bool { + match *self { + Size::Unbounded => false, + Size::Bounded(ref n) => n.eq(rhs), + } + } +} + +impl PartialOrd for Size { + fn partial_cmp(&self, rhs: &Self) -> Option { + match (self, rhs) { + (&Size::Unbounded, &Size::Unbounded) => None, + (&Size::Unbounded, _) => Some(Ordering::Greater), + (_, &Size::Unbounded) => Some(Ordering::Less), + (&Size::Bounded(ref a), &Size::Bounded(ref b)) => a.partial_cmp(b), + } + } +} + +impl PartialOrd> for Size { + fn partial_cmp(&self, rhs: &Address) -> Option { + match *self { + Size::Unbounded => Some(Ordering::Greater), + Size::Bounded(ref n) => n.partial_cmp(rhs), + } + } +}