- `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<S>` as the only
 addressing (indexing) type
sync
Szymon Walter 2018-03-22 09:37:22 +01:00
parent 19b5c4e4d2
commit 67e0b63f4b
8 changed files with 243 additions and 267 deletions

109
src/fs.rs
View File

@ -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<T, S: Size> {
struct Struct<T, S: SectorSize> {
pub inner: T,
pub offset: Address<S>,
}
impl<T, S: Size> From<(T, Address<S>)> for Struct<T, S> {
impl<T, S: SectorSize> From<(T, Address<S>)> for Struct<T, S> {
#[inline]
fn from((inner, offset): (T, Address<S>)) -> Struct<T, S> {
Struct { inner, offset }
@ -25,13 +25,13 @@ impl<T, S: Size> From<(T, Address<S>)> for Struct<T, S> {
}
/// Safe wrapper for raw sys structs
pub struct Ext2<S: Size, V: Volume<u8, Address<S>>> {
pub struct Ext2<S: SectorSize, V: Volume<u8, S>> {
volume: V,
superblock: Struct<Superblock, S>,
block_groups: Struct<Vec<BlockGroupDescriptor>, S>,
}
impl<S: Size, V: Volume<u8, Address<S>>> Ext2<S, V> {
impl<S: SectorSize, V: Volume<u8, S>> Ext2<S, V> {
pub fn new(volume: V) -> Result<Ext2<S, V>, Error> {
let superblock = unsafe { Struct::from(Superblock::find(&volume)?) };
let block_groups_offset = Address::with_block_size(
@ -87,10 +87,10 @@ impl<S: Size, V: Volume<u8, Address<S>>> Ext2<S, V> {
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<usize, Error> {
let total_size = inode.size();
let block_size = self.block_size();
@ -113,30 +113,30 @@ impl<S: Size, V: Volume<u8, Address<S>>> Ext2<S, V> {
Ok(offset)
}
pub fn write_inode<'a>(
&'a self,
_inode: &(Inode<'a, S, V>, Address<S>),
pub fn write_inode<'vol>(
&'vol self,
_inode: &(Inode<'vol, S, V>, Address<S>),
_buf: &[u8],
) -> Result<usize, Error> {
unimplemented!()
}
pub fn root_inode<'a>(&'a self) -> (Inode<'a, S, V>, Address<S>) {
pub fn root_inode<'vol>(&'vol self) -> (Inode<'vol, S, V>, Address<S>) {
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<S>)> {
) -> Option<(Inode<'vol, S, V>, Address<S>)> {
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<S: Size, V: Volume<u8, Address<S>>> Ext2<S, V> {
(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::<Inode<'a, S, V>>()
mem::size_of::<Inode<'vol, S, V>>()
} else {
// note: inodes bigger than 128 are not supported
self.superblock().inode_size as usize
@ -214,15 +214,15 @@ impl<S: Size, V: Volume<u8, Address<S>>> Ext2<S, V> {
}
}
impl<S: Size, V: Volume<u8, Address<S>>> Debug for Ext2<S, V> {
impl<S: SectorSize, V: Volume<u8, S>> Debug for Ext2<S, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Ext2<{}>", S::SIZE)
}
}
pub struct Inodes<'a, S: 'a + Size, V: 'a + Volume<u8, Address<S>>> {
fs: &'a Ext2<S, V>,
block_groups: &'a [BlockGroupDescriptor],
pub struct Inodes<'vol, S: 'vol + SectorSize, V: 'vol + Volume<u8, S>> {
fs: &'vol Ext2<S, V>,
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<u8, Address<S>>> {
index: usize,
}
impl<'a, S: Size, V: 'a + Volume<u8, Address<S>>> Iterator
for Inodes<'a, S, V>
impl<'vol, S: SectorSize, V: 'vol + Volume<u8, S>> Iterator
for Inodes<'vol, S, V>
{
type Item = (Inode<'a, S, V>, Address<S>);
type Item = (Inode<'vol, S, V>, Address<S>);
fn next(&mut self) -> Option<Self::Item> {
if self.index < self.inodes_count {
@ -260,24 +260,26 @@ impl<'a, S: Size, V: 'a + Volume<u8, Address<S>>> Iterator
}
#[derive(Debug, Clone)]
pub struct Inode<'a, S: 'a + Size, V: 'a + Volume<u8, Address<S>>> {
fs: &'a Ext2<S, V>,
pub struct Inode<'vol, S: 'vol + SectorSize, V: 'vol + Volume<u8, S>> {
fs: &'vol Ext2<S, V>,
inner: RawInode,
}
impl<'a, S: 'a + Size, V: 'a + Volume<u8, Address<S>>> Inode<'a, S, V> {
pub fn new(fs: &'a Ext2<S, V>, inner: RawInode) -> Inode<'a, S, V> {
impl<'vol, S: 'vol + SectorSize, V: 'vol + Volume<u8, S>> Inode<'vol, S, V> {
pub fn new(fs: &'vol Ext2<S, V>, 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<Directory<'a, 'b, S, V>> {
pub fn directory<'inode>(
&'inode self,
) -> Option<Directory<'vol, 'inode, S, V>> {
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<u8, Address<S>>> 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<S: Size, V: Volume<u8, Address<S>>>(
fn block_index<S: SectorSize, V: Volume<u8, S>>(
volume: &V,
block: u32,
index: usize,
@ -437,16 +439,20 @@ impl<'a, S: 'a + Size, V: 'a + Volume<u8, Address<S>>> Inode<'a, S, V> {
}
}
pub struct InodeBlocks<'a: 'b, 'b, S: 'a + Size, V: 'a + Volume<u8, Address<S>>>
{
inode: &'b Inode<'a, S, V>,
pub struct InodeBlocks<
'vol: 'inode,
'inode,
S: 'vol + SectorSize,
V: 'vol + Volume<u8, S>,
> {
inode: &'inode Inode<'vol, S, V>,
index: usize,
}
impl<'a, 'b, S: Size, V: 'a + Volume<u8, Address<S>>> Iterator
for InodeBlocks<'a, 'b, S, V>
impl<'vol, 'inode, S: SectorSize, V: 'vol + Volume<u8, S>> Iterator
for InodeBlocks<'vol, 'inode, S, V>
{
type Item = Result<(VolumeSlice<'a, u8, Address<S>>, Address<S>), Error>;
type Item = Result<(VolumeSlice<'vol, u8, S>, Address<S>), Error>;
fn next(&mut self) -> Option<Self::Item> {
let block = self.inode.try_block(self.index);
@ -473,17 +479,22 @@ impl<'a, 'b, S: Size, V: 'a + Volume<u8, Address<S>>> Iterator
}
}
pub struct Directory<'a: 'b, 'b, S: 'a + Size, V: 'a + Volume<u8, Address<S>>> {
blocks: InodeBlocks<'a, 'b, S, V>,
pub struct Directory<
'vol: 'inode,
'inode,
S: 'vol + SectorSize,
V: 'vol + Volume<u8, S>,
> {
blocks: InodeBlocks<'vol, 'inode, S, V>,
offset: usize,
buffer: Option<VolumeSlice<'a, u8, Address<S>>>,
buffer: Option<VolumeSlice<'vol, u8, S>>,
block_size: usize,
}
impl<'a, 'b, S: Size, V: 'a + Volume<u8, Address<S>>> Iterator
for Directory<'a, 'b, S, V>
impl<'vol, 'inode, S: SectorSize, V: 'vol + Volume<u8, S>> Iterator
for Directory<'vol, 'inode, S, V>
{
type Item = Result<DirectoryEntry<'a>, Error>;
type Item = Result<DirectoryEntry<'vol>, Error>;
fn next(&mut self) -> Option<Self::Item> {
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<u8, Address<S>>>(
fs: &'a Ext2<S, V>,
inode: Inode<'a, S, V>,
fn walk<'vol, S: SectorSize, V: Volume<u8, S>>(
fs: &'vol Ext2<S, V>,
inode: Inode<'vol, S, V>,
name: String,
) {
inode.directory().map(|dir| {

View File

@ -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<S: Size> {
pub struct Address<S: SectorSize> {
sector: u32,
offset: u32,
_phantom: PhantomData<S>,
}
impl<S: Size> Address<S> {
impl<S: SectorSize> Address<S> {
pub unsafe fn new_unchecked(sector: u32, offset: u32) -> Address<S> {
assert!((offset as usize) < S::SIZE, "offset out of sector bounds");
let _phantom = PhantomData;
@ -96,7 +96,7 @@ impl<S: Size> Address<S> {
}
}
impl<S: Size> Step for Address<S> {
impl<S: SectorSize> Step for Address<S> {
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
if end.sector >= start.sector {
Some(end.sector as usize - start.sector as usize)
@ -128,7 +128,7 @@ impl<S: Size> Step for Address<S> {
}
}
impl<S: Size> Debug for Address<S> {
impl<S: SectorSize> Debug for Address<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let name = format!("Address<{}>", S::SIZE);
f.debug_struct(&name)
@ -138,19 +138,19 @@ impl<S: Size> Debug for Address<S> {
}
}
impl<S: Size> Display for Address<S> {
impl<S: SectorSize> Display for Address<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}:{}", self.sector, self.offset)
}
}
impl<S: Size> LowerHex for Address<S> {
impl<S: SectorSize> LowerHex for Address<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:x}:{:x}", self.sector, self.offset)
}
}
impl<S: Size> From<u64> for Address<S> {
impl<S: SectorSize> From<u64> for Address<S> {
fn from(idx: u64) -> Address<S> {
let sector = idx >> S::LOG_SIZE;
let offset = idx & S::OFFSET_MASK as u64;
@ -158,7 +158,7 @@ impl<S: Size> From<u64> for Address<S> {
}
}
impl<S: Size> From<usize> for Address<S> {
impl<S: SectorSize> From<usize> for Address<S> {
fn from(idx: usize) -> Address<S> {
let sector = idx >> S::LOG_SIZE;
let offset = idx & S::OFFSET_MASK as usize;
@ -166,7 +166,7 @@ impl<S: Size> From<usize> for Address<S> {
}
}
impl<S: Size> Add for Address<S> {
impl<S: SectorSize> Add for Address<S> {
type Output = Address<S>;
fn add(self, rhs: Address<S>) -> Address<S> {
Address::new(
@ -176,7 +176,7 @@ impl<S: Size> Add for Address<S> {
}
}
impl<S: Size> Sub for Address<S> {
impl<S: SectorSize> Sub for Address<S> {
type Output = Address<S>;
fn sub(self, rhs: Address<S>) -> Address<S> {
Address::new(

View File

@ -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<S: Size, V: Volume<u8, Address<S>>>(
pub unsafe fn find_descriptor<S: SectorSize, V: Volume<u8, S>>(
haystack: &V,
offset: Address<S>,
) -> Result<(BlockGroupDescriptor, Address<S>), Error> {
@ -73,7 +73,7 @@ impl BlockGroupDescriptor {
Ok(descr)
}
pub unsafe fn find_descriptor_table<S: Size, V: Volume<u8, Address<S>>>(
pub unsafe fn find_descriptor_table<S: SectorSize, V: Volume<u8, S>>(
haystack: &V,
offset: Address<S>,
count: usize,

View File

@ -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<S: Size, V: Volume<u8, Address<S>>>(
pub unsafe fn find_inode<S: SectorSize, V: Volume<u8, S>>(
haystack: &V,
offset: Address<S>,
size: usize,

View File

@ -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<S: Size, V: Volume<u8, Address<S>>>(
pub unsafe fn find<S: SectorSize, V: Volume<u8, S>>(
haystack: &V,
) -> Result<(Superblock, Address<S>), Error> {
let offset = Address::from(1024_usize);

View File

@ -1,97 +0,0 @@
use core::fmt::{self, Debug, Display};
use core::cmp::Ordering;
#[derive(Clone, Copy, Debug, Hash)]
pub enum Length<Idx> {
Unbounded,
Bounded(Idx),
}
impl<Idx: Copy> Length<Idx> {
pub fn try_len(&self) -> Option<Idx> {
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<Idx> Length<Idx> {
pub fn is_bounded(&self) -> bool {
match *self {
Length::Unbounded => false,
Length::Bounded(_) => true,
}
}
}
impl<Idx: Debug> Display for Length<Idx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(self, f)
}
}
impl<Idx: PartialEq> PartialEq for Length<Idx> {
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<Idx: PartialEq> PartialEq<Idx> for Length<Idx> {
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<Idx: PartialOrd> PartialOrd for Length<Idx> {
fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
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<Idx: PartialOrd> PartialOrd<Idx> for Length<Idx> {
fn partial_cmp(&self, rhs: &Idx) -> Option<Ordering> {
match *self {
Length::Unbounded => Some(Ordering::Greater),
Length::Bounded(ref n) => n.partial_cmp(rhs),
}
}
}

View File

@ -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<T, Idx>
where
[T]: ToOwned,
Idx: PartialEq + PartialOrd,
{
pub trait Volume<T: Clone, S: SectorSize> {
type Error: Into<Error>;
fn size(&self) -> Length<Idx>;
fn size(&self) -> Size<S>;
fn commit(
&mut self,
slice: Option<VolumeCommit<T, Idx>>,
slice: Option<VolumeCommit<T, S>>,
) -> Result<(), Self::Error>;
unsafe fn slice_unchecked<'a>(
&'a self,
range: Range<Idx>,
) -> VolumeSlice<'a, T, Idx>;
range: Range<Address<S>>,
) -> VolumeSlice<'a, T, S>;
fn slice<'a>(
&'a self,
range: Range<Idx>,
) -> Result<VolumeSlice<'a, T, Idx>, Self::Error>;
range: Range<Address<S>>,
) -> Result<VolumeSlice<'a, T, S>, 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<S>,
}
impl<T, Idx: Default> VolumeSlice<'static, T, Idx>
where
[T]: ToOwned,
{
pub fn with_static(inner: &'static [T]) -> VolumeSlice<'static, T, Idx> {
impl<T: Clone, S: SectorSize> 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<T, Idx> VolumeSlice<'static, T, Idx>
where
[T]: ToOwned,
{
pub fn new_owned(
inner: <[T] as ToOwned>::Owned,
index: Idx,
) -> VolumeSlice<'static, T, Idx> {
index: Address<S>,
) -> 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<S>) -> 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<S> {
self.index
}
}
impl<'a, Idx: Copy> VolumeSlice<'a, u8, Idx> {
pub unsafe fn dynamic_cast<T: Copy>(&self) -> (T, Idx) {
impl<'a, S: SectorSize> VolumeSlice<'a, u8, S> {
pub unsafe fn dynamic_cast<T: Copy>(&self) -> (T, Address<S>) {
assert!(self.inner.len() >= mem::size_of::<T>());
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<T: Copy>(
cast: &'a T,
index: Idx,
) -> VolumeSlice<'a, u8, Idx> {
index: Address<S>,
) -> VolumeSlice<'a, u8, S> {
let len = mem::size_of::<T>();
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<Owned = Vec<T>>,
{
pub fn commit(self) -> Option<VolumeCommit<T, Idx>> {
impl<'a, T: Clone, S: SectorSize> VolumeSlice<'a, T, S> {
pub fn commit(self) -> Option<VolumeCommit<T, S>> {
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<T, Idx> {
pub struct VolumeCommit<T, S: SectorSize> {
inner: Vec<T>,
index: Idx,
index: Address<S>,
}
impl<T, Idx: Default> VolumeCommit<T, Idx> {
pub fn with_vec(inner: Vec<T>) -> VolumeCommit<T, Idx> {
impl<T: Clone, S: SectorSize> VolumeCommit<T, S> {
pub fn with_vec(inner: Vec<T>) -> VolumeCommit<T, S> {
VolumeCommit {
inner,
index: Idx::default(),
index: Address::new(0, 0),
}
}
}
impl<T, Idx> VolumeCommit<T, Idx> {
pub fn new(inner: Vec<T>, index: Idx) -> VolumeCommit<T, Idx> {
impl<T: Clone, S: SectorSize> VolumeCommit<T, S> {
pub fn new(inner: Vec<T>, index: Address<S>) -> VolumeCommit<T, S> {
VolumeCommit { inner, index }
}
@ -188,24 +153,24 @@ impl<T, Idx> VolumeCommit<T, Idx> {
self.inner
}
pub fn at_index(&self) -> &Idx {
&self.index
pub fn address(&self) -> Address<S> {
self.index
}
}
impl<T, Idx> AsRef<[T]> for VolumeCommit<T, Idx> {
impl<T: Clone, S: SectorSize> AsRef<[T]> for VolumeCommit<T, S> {
fn as_ref(&self) -> &[T] {
self.inner.as_ref()
}
}
impl<T, Idx> AsMut<[T]> for VolumeCommit<T, Idx> {
impl<T: Clone, S: SectorSize> AsMut<[T]> for VolumeCommit<T, S> {
fn as_mut(&mut self) -> &mut [T] {
self.inner.as_mut()
}
}
impl<T, Idx> Deref for VolumeCommit<T, Idx> {
impl<T: Clone, S: SectorSize> Deref for VolumeCommit<T, S> {
type Target = [T];
fn deref(&self) -> &Self::Target {
@ -213,7 +178,7 @@ impl<T, Idx> Deref for VolumeCommit<T, Idx> {
}
}
impl<T, Idx> DerefMut for VolumeCommit<T, Idx> {
impl<T: Clone, S: SectorSize> DerefMut for VolumeCommit<T, S> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_mut()
}
@ -221,26 +186,23 @@ impl<T, Idx> DerefMut for VolumeCommit<T, Idx> {
macro_rules! impl_slice {
(@inner $volume:ty $( , $lt:lifetime )* ) => {
impl<$( $lt, )* S: Size, T> Volume<T, Address<S>>
impl<$( $lt, )* T: Clone, S: SectorSize> Volume<T, S>
for $volume
where
T: Clone,
[T]: ToOwned,
{
type Error = Error;
fn size(&self) -> Length<Address<S>> {
Length::Bounded(
fn size(&self) -> Size<S> {
Size::Bounded(
Address::from(<Self as AsRef<[T]>>::as_ref(self).len())
)
}
fn commit(
&mut self,
slice: Option<VolumeCommit<T, Address<S>>>,
slice: Option<VolumeCommit<T, S>>,
) -> 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<Address<S>>,
) -> VolumeSlice<'a, T, Address<S>> {
) -> 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<Address<S>>,
) -> Result<VolumeSlice<'a, T, Address<S>>, Self::Error> {
) -> Result<VolumeSlice<'a, T, S>, 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<S: Size> Volume<u8, Address<S>> for RefCell<File> {
impl<S: SectorSize> Volume<u8, S> for RefCell<File> {
type Error = io::Error;
fn size(&self) -> Length<Address<S>> {
Length::Bounded(
fn size(&self) -> Size<S> {
Size::Bounded(
self.borrow()
.metadata()
.map(|data| Address::from(data.len()))
@ -318,11 +280,11 @@ mod file {
fn commit(
&mut self,
slice: Option<VolumeCommit<u8, Address<S>>>,
slice: Option<VolumeCommit<u8, S>>,
) -> 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<Address<S>>,
) -> VolumeSlice<'a, u8, Address<S>> {
) -> 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<Address<S>>,
) -> Result<VolumeSlice<'a, u8, Address<S>>, Self::Error> {
) -> Result<VolumeSlice<'a, u8, S>, Self::Error> {
let index = range.start;
let mut vec = Vec::with_capacity((range.end - range.start)
.into_index()

100
src/volume/size.rs Normal file
View File

@ -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<S: SectorSize> {
Unbounded,
Bounded(Address<S>),
}
impl<S: SectorSize> Size<S> {
pub fn try_len(&self) -> Option<Address<S>> {
match *self {
Size::Unbounded => None,
Size::Bounded(n) => Some(n),
}
}
pub unsafe fn len(&self) -> Address<S> {
match *self {
Size::Unbounded => panic!(
"attempt to convert `Size::Unbounded` to a concrete length"
),
Size::Bounded(n) => n,
}
}
}
impl<S: SectorSize> Size<S> {
pub fn is_bounded(&self) -> bool {
match *self {
Size::Unbounded => false,
Size::Bounded(_) => true,
}
}
}
impl<S: SectorSize> Display for Size<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Size::Unbounded => write!(f, "Unbounded"),
Size::Bounded(n) => write!(f, "Bounded({})", n),
}
}
}
impl<S: SectorSize> PartialEq for Size<S> {
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<S: SectorSize> PartialEq<Address<S>> for Size<S> {
fn eq(&self, rhs: &Address<S>) -> bool {
match *self {
Size::Unbounded => false,
Size::Bounded(ref n) => n.eq(rhs),
}
}
fn ne(&self, rhs: &Address<S>) -> bool {
match *self {
Size::Unbounded => false,
Size::Bounded(ref n) => n.eq(rhs),
}
}
}
impl<S: SectorSize> PartialOrd for Size<S> {
fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
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<S: SectorSize> PartialOrd<Address<S>> for Size<S> {
fn partial_cmp(&self, rhs: &Address<S>) -> Option<Ordering> {
match *self {
Size::Unbounded => Some(Ordering::Greater),
Size::Bounded(ref n) => n.partial_cmp(rhs),
}
}
}