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<S>` as the only addressing (indexing) type
This commit is contained in:
parent
e0e2807425
commit
36f13bea2a
109
src/fs.rs
109
src/fs.rs
|
@ -6,18 +6,18 @@ use core::nonzero::NonZero;
|
||||||
use alloc::Vec;
|
use alloc::Vec;
|
||||||
|
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use sector::{Address, Size};
|
use sector::{Address, SectorSize};
|
||||||
use volume::{Volume, VolumeSlice};
|
use volume::{Volume, VolumeSlice};
|
||||||
use sys::superblock::Superblock;
|
use sys::superblock::Superblock;
|
||||||
use sys::block_group::BlockGroupDescriptor;
|
use sys::block_group::BlockGroupDescriptor;
|
||||||
use sys::inode::Inode as RawInode;
|
use sys::inode::Inode as RawInode;
|
||||||
|
|
||||||
struct Struct<T, S: Size> {
|
struct Struct<T, S: SectorSize> {
|
||||||
pub inner: T,
|
pub inner: T,
|
||||||
pub offset: Address<S>,
|
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]
|
#[inline]
|
||||||
fn from((inner, offset): (T, Address<S>)) -> Struct<T, S> {
|
fn from((inner, offset): (T, Address<S>)) -> Struct<T, S> {
|
||||||
Struct { inner, offset }
|
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
|
/// 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,
|
volume: V,
|
||||||
superblock: Struct<Superblock, S>,
|
superblock: Struct<Superblock, S>,
|
||||||
block_groups: Struct<Vec<BlockGroupDescriptor>, 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> {
|
pub fn new(volume: V) -> Result<Ext2<S, V>, Error> {
|
||||||
let superblock = unsafe { Struct::from(Superblock::find(&volume)?) };
|
let superblock = unsafe { Struct::from(Superblock::find(&volume)?) };
|
||||||
let block_groups_offset = Address::with_block_size(
|
let block_groups_offset = Address::with_block_size(
|
||||||
|
@ -87,10 +87,10 @@ impl<S: Size, V: Volume<u8, Address<S>>> Ext2<S, V> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_inode<'a>(
|
pub fn read_inode<'vol>(
|
||||||
&'a self,
|
&'vol self,
|
||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
inode: &Inode<'a, S, V>,
|
inode: &Inode<'vol, S, V>,
|
||||||
) -> Result<usize, Error> {
|
) -> Result<usize, Error> {
|
||||||
let total_size = inode.size();
|
let total_size = inode.size();
|
||||||
let block_size = self.block_size();
|
let block_size = self.block_size();
|
||||||
|
@ -113,30 +113,30 @@ impl<S: Size, V: Volume<u8, Address<S>>> Ext2<S, V> {
|
||||||
Ok(offset)
|
Ok(offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_inode<'a>(
|
pub fn write_inode<'vol>(
|
||||||
&'a self,
|
&'vol self,
|
||||||
_inode: &(Inode<'a, S, V>, Address<S>),
|
_inode: &(Inode<'vol, S, V>, Address<S>),
|
||||||
_buf: &[u8],
|
_buf: &[u8],
|
||||||
) -> Result<usize, Error> {
|
) -> Result<usize, Error> {
|
||||||
unimplemented!()
|
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()
|
self.inode_nth(2).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inode_nth<'a>(
|
pub fn inode_nth<'vol>(
|
||||||
&'a self,
|
&'vol self,
|
||||||
index: usize,
|
index: usize,
|
||||||
) -> Option<(Inode<'a, S, V>, Address<S>)> {
|
) -> Option<(Inode<'vol, S, V>, Address<S>)> {
|
||||||
self.inodes_nth(index).next()
|
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)
|
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");
|
assert!(index > 0, "inodes are 1-indexed");
|
||||||
Inodes {
|
Inodes {
|
||||||
fs: self,
|
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)
|
(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 {
|
if self.version().0 == 0 {
|
||||||
mem::size_of::<Inode<'a, S, V>>()
|
mem::size_of::<Inode<'vol, S, V>>()
|
||||||
} else {
|
} else {
|
||||||
// note: inodes bigger than 128 are not supported
|
// note: inodes bigger than 128 are not supported
|
||||||
self.superblock().inode_size as usize
|
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 {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "Ext2<{}>", S::SIZE)
|
write!(f, "Ext2<{}>", S::SIZE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Inodes<'a, S: 'a + Size, V: 'a + Volume<u8, Address<S>>> {
|
pub struct Inodes<'vol, S: 'vol + SectorSize, V: 'vol + Volume<u8, S>> {
|
||||||
fs: &'a Ext2<S, V>,
|
fs: &'vol Ext2<S, V>,
|
||||||
block_groups: &'a [BlockGroupDescriptor],
|
block_groups: &'vol [BlockGroupDescriptor],
|
||||||
log_block_size: u32,
|
log_block_size: u32,
|
||||||
inode_size: usize,
|
inode_size: usize,
|
||||||
inodes_per_group: usize,
|
inodes_per_group: usize,
|
||||||
|
@ -230,10 +230,10 @@ pub struct Inodes<'a, S: 'a + Size, V: 'a + Volume<u8, Address<S>>> {
|
||||||
index: usize,
|
index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, S: Size, V: 'a + Volume<u8, Address<S>>> Iterator
|
impl<'vol, S: SectorSize, V: 'vol + Volume<u8, S>> Iterator
|
||||||
for Inodes<'a, S, V>
|
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> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
if self.index < self.inodes_count {
|
if self.index < self.inodes_count {
|
||||||
|
@ -260,24 +260,26 @@ impl<'a, S: Size, V: 'a + Volume<u8, Address<S>>> Iterator
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Inode<'a, S: 'a + Size, V: 'a + Volume<u8, Address<S>>> {
|
pub struct Inode<'vol, S: 'vol + SectorSize, V: 'vol + Volume<u8, S>> {
|
||||||
fs: &'a Ext2<S, V>,
|
fs: &'vol Ext2<S, V>,
|
||||||
inner: RawInode,
|
inner: RawInode,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, S: 'a + Size, V: 'a + Volume<u8, Address<S>>> Inode<'a, S, V> {
|
impl<'vol, S: 'vol + SectorSize, V: 'vol + Volume<u8, S>> Inode<'vol, S, V> {
|
||||||
pub fn new(fs: &'a Ext2<S, V>, inner: RawInode) -> Inode<'a, S, V> {
|
pub fn new(fs: &'vol Ext2<S, V>, inner: RawInode) -> Inode<'vol, S, V> {
|
||||||
Inode { fs, inner }
|
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 {
|
InodeBlocks {
|
||||||
inode: self,
|
inode: self,
|
||||||
index: 0,
|
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;
|
use sys::inode::TypePerm;
|
||||||
if unsafe { self.inner.type_perm.contains(TypePerm::DIRECTORY) } {
|
if unsafe { self.inner.type_perm.contains(TypePerm::DIRECTORY) } {
|
||||||
Some(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
|
// - that's n/4 blocks with n/4 pointers each = (n/4)^2
|
||||||
// number of blocks in triply table: (block_size/4)^3
|
// 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,
|
volume: &V,
|
||||||
block: u32,
|
block: u32,
|
||||||
index: usize,
|
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>>>
|
pub struct InodeBlocks<
|
||||||
{
|
'vol: 'inode,
|
||||||
inode: &'b Inode<'a, S, V>,
|
'inode,
|
||||||
|
S: 'vol + SectorSize,
|
||||||
|
V: 'vol + Volume<u8, S>,
|
||||||
|
> {
|
||||||
|
inode: &'inode Inode<'vol, S, V>,
|
||||||
index: usize,
|
index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b, S: Size, V: 'a + Volume<u8, Address<S>>> Iterator
|
impl<'vol, 'inode, S: SectorSize, V: 'vol + Volume<u8, S>> Iterator
|
||||||
for InodeBlocks<'a, 'b, S, V>
|
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> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
let block = self.inode.try_block(self.index);
|
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>>> {
|
pub struct Directory<
|
||||||
blocks: InodeBlocks<'a, 'b, S, V>,
|
'vol: 'inode,
|
||||||
|
'inode,
|
||||||
|
S: 'vol + SectorSize,
|
||||||
|
V: 'vol + Volume<u8, S>,
|
||||||
|
> {
|
||||||
|
blocks: InodeBlocks<'vol, 'inode, S, V>,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
buffer: Option<VolumeSlice<'a, u8, Address<S>>>,
|
buffer: Option<VolumeSlice<'vol, u8, S>>,
|
||||||
block_size: usize,
|
block_size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b, S: Size, V: 'a + Volume<u8, Address<S>>> Iterator
|
impl<'vol, 'inode, S: SectorSize, V: 'vol + Volume<u8, S>> Iterator
|
||||||
for Directory<'a, 'b, S, V>
|
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> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
if self.buffer.is_none() || self.offset >= self.block_size {
|
if self.buffer.is_none() || self.offset >= self.block_size {
|
||||||
|
@ -533,7 +544,7 @@ mod tests {
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
|
||||||
use sector::{Address, Size, Size512};
|
use sector::{Address, SectorSize, Size512};
|
||||||
use volume::Volume;
|
use volume::Volume;
|
||||||
|
|
||||||
use super::{Ext2, Inode};
|
use super::{Ext2, Inode};
|
||||||
|
@ -675,9 +686,9 @@ mod tests {
|
||||||
fn walkdir() {
|
fn walkdir() {
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
fn walk<'a, S: Size, V: Volume<u8, Address<S>>>(
|
fn walk<'vol, S: SectorSize, V: Volume<u8, S>>(
|
||||||
fs: &'a Ext2<S, V>,
|
fs: &'vol Ext2<S, V>,
|
||||||
inode: Inode<'a, S, V>,
|
inode: Inode<'vol, S, V>,
|
||||||
name: String,
|
name: String,
|
||||||
) {
|
) {
|
||||||
inode.directory().map(|dir| {
|
inode.directory().map(|dir| {
|
||||||
|
|
|
@ -4,7 +4,7 @@ use core::ops::{Add, Sub};
|
||||||
use core::fmt::{self, Debug, Display, LowerHex};
|
use core::fmt::{self, Debug, Display, LowerHex};
|
||||||
use core::iter::Step;
|
use core::iter::Step;
|
||||||
|
|
||||||
pub trait Size: Clone + Copy + PartialOrd {
|
pub trait SectorSize: Clone + Copy + PartialEq + PartialOrd {
|
||||||
// log_sector_size = log_2(sector_size)
|
// log_sector_size = log_2(sector_size)
|
||||||
const LOG_SIZE: u32;
|
const LOG_SIZE: u32;
|
||||||
const SIZE: usize = 1 << Self::LOG_SIZE;
|
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)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||||
pub struct Size512;
|
pub struct Size512;
|
||||||
impl Size for Size512 {
|
impl SectorSize for Size512 {
|
||||||
const LOG_SIZE: u32 = 9;
|
const LOG_SIZE: u32 = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||||
pub struct Size1024;
|
pub struct Size1024;
|
||||||
impl Size for Size1024 {
|
impl SectorSize for Size1024 {
|
||||||
const LOG_SIZE: u32 = 10;
|
const LOG_SIZE: u32 = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||||
pub struct Size2048;
|
pub struct Size2048;
|
||||||
impl Size for Size2048 {
|
impl SectorSize for Size2048 {
|
||||||
const LOG_SIZE: u32 = 11;
|
const LOG_SIZE: u32 = 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||||
pub struct Size4096;
|
pub struct Size4096;
|
||||||
impl Size for Size4096 {
|
impl SectorSize for Size4096 {
|
||||||
const LOG_SIZE: u32 = 12;
|
const LOG_SIZE: u32 = 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Address in a physical sector
|
/// Address in a physical sector
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||||
pub struct Address<S: Size> {
|
pub struct Address<S: SectorSize> {
|
||||||
sector: u32,
|
sector: u32,
|
||||||
offset: u32,
|
offset: u32,
|
||||||
_phantom: PhantomData<S>,
|
_phantom: PhantomData<S>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Size> Address<S> {
|
impl<S: SectorSize> Address<S> {
|
||||||
pub unsafe fn new_unchecked(sector: u32, offset: u32) -> Address<S> {
|
pub unsafe fn new_unchecked(sector: u32, offset: u32) -> Address<S> {
|
||||||
assert!((offset as usize) < S::SIZE, "offset out of sector bounds");
|
assert!((offset as usize) < S::SIZE, "offset out of sector bounds");
|
||||||
let _phantom = PhantomData;
|
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> {
|
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
|
||||||
if end.sector >= start.sector {
|
if end.sector >= start.sector {
|
||||||
Some(end.sector as usize - start.sector as usize)
|
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 {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
let name = format!("Address<{}>", S::SIZE);
|
let name = format!("Address<{}>", S::SIZE);
|
||||||
f.debug_struct(&name)
|
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 {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{}:{}", self.sector, self.offset)
|
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 {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{:x}:{:x}", self.sector, self.offset)
|
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> {
|
fn from(idx: u64) -> Address<S> {
|
||||||
let sector = idx >> S::LOG_SIZE;
|
let sector = idx >> S::LOG_SIZE;
|
||||||
let offset = idx & S::OFFSET_MASK as u64;
|
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> {
|
fn from(idx: usize) -> Address<S> {
|
||||||
let sector = idx >> S::LOG_SIZE;
|
let sector = idx >> S::LOG_SIZE;
|
||||||
let offset = idx & S::OFFSET_MASK as usize;
|
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>;
|
type Output = Address<S>;
|
||||||
fn add(self, rhs: Address<S>) -> Address<S> {
|
fn add(self, rhs: Address<S>) -> Address<S> {
|
||||||
Address::new(
|
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>;
|
type Output = Address<S>;
|
||||||
fn sub(self, rhs: Address<S>) -> Address<S> {
|
fn sub(self, rhs: Address<S>) -> Address<S> {
|
||||||
Address::new(
|
Address::new(
|
||||||
|
|
|
@ -4,7 +4,7 @@ use core::fmt::{self, Debug};
|
||||||
use alloc::Vec;
|
use alloc::Vec;
|
||||||
|
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use sector::{Address, Size};
|
use sector::{Address, SectorSize};
|
||||||
use volume::Volume;
|
use volume::Volume;
|
||||||
|
|
||||||
/// The Block Group Descriptor Table contains a descriptor for each block group
|
/// The Block Group Descriptor Table contains a descriptor for each block group
|
||||||
|
@ -52,7 +52,7 @@ impl Debug for BlockGroupDescriptor {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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,
|
haystack: &V,
|
||||||
offset: Address<S>,
|
offset: Address<S>,
|
||||||
) -> Result<(BlockGroupDescriptor, Address<S>), Error> {
|
) -> Result<(BlockGroupDescriptor, Address<S>), Error> {
|
||||||
|
@ -73,7 +73,7 @@ impl BlockGroupDescriptor {
|
||||||
Ok(descr)
|
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,
|
haystack: &V,
|
||||||
offset: Address<S>,
|
offset: Address<S>,
|
||||||
count: usize,
|
count: usize,
|
||||||
|
|
|
@ -2,7 +2,7 @@ use core::mem;
|
||||||
use core::fmt::{self, Debug};
|
use core::fmt::{self, Debug};
|
||||||
|
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use sector::{Address, Size};
|
use sector::{Address, SectorSize};
|
||||||
use volume::Volume;
|
use volume::Volume;
|
||||||
|
|
||||||
/// An inode is a structure on the disk that represents a file, directory,
|
/// An inode is a structure on the disk that represents a file, directory,
|
||||||
|
@ -97,7 +97,7 @@ impl Debug for Inode {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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,
|
haystack: &V,
|
||||||
offset: Address<S>,
|
offset: Address<S>,
|
||||||
size: usize,
|
size: usize,
|
||||||
|
|
|
@ -2,7 +2,7 @@ use core::mem;
|
||||||
use core::fmt::{self, Debug};
|
use core::fmt::{self, Debug};
|
||||||
|
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use sector::{Address, Size};
|
use sector::{Address, SectorSize};
|
||||||
use volume::Volume;
|
use volume::Volume;
|
||||||
|
|
||||||
/// Ext2 signature (0xef53), used to help confirm the presence of Ext2 on a
|
/// 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.
|
/// First non-reserved inode in file system.
|
||||||
pub first_inode: u32,
|
pub first_inode: u32,
|
||||||
/// Size of each inode structure in bytes.
|
/// SectorSize of each inode structure in bytes.
|
||||||
pub inode_size: u16,
|
pub inode_size: u16,
|
||||||
/// Block group that this superblock is part of (if backup copy)
|
/// Block group that this superblock is part of (if backup copy)
|
||||||
pub block_group: u16,
|
pub block_group: u16,
|
||||||
|
@ -195,7 +195,7 @@ impl Debug for Superblock {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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,
|
haystack: &V,
|
||||||
) -> Result<(Superblock, Address<S>), Error> {
|
) -> Result<(Superblock, Address<S>), Error> {
|
||||||
let offset = Address::from(1024_usize);
|
let offset = Address::from(1024_usize);
|
||||||
|
|
|
@ -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),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,62 +7,47 @@ use alloc::boxed::Box;
|
||||||
use alloc::borrow::{Cow, ToOwned};
|
use alloc::borrow::{Cow, ToOwned};
|
||||||
|
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use sector::{Address, Size};
|
use sector::{Address, SectorSize};
|
||||||
|
|
||||||
pub mod length;
|
pub mod size;
|
||||||
use self::length::Length;
|
use self::size::Size;
|
||||||
|
|
||||||
pub trait Volume<T, Idx>
|
pub trait Volume<T: Clone, S: SectorSize> {
|
||||||
where
|
|
||||||
[T]: ToOwned,
|
|
||||||
Idx: PartialEq + PartialOrd,
|
|
||||||
{
|
|
||||||
type Error: Into<Error>;
|
type Error: Into<Error>;
|
||||||
|
|
||||||
fn size(&self) -> Length<Idx>;
|
fn size(&self) -> Size<S>;
|
||||||
fn commit(
|
fn commit(
|
||||||
&mut self,
|
&mut self,
|
||||||
slice: Option<VolumeCommit<T, Idx>>,
|
slice: Option<VolumeCommit<T, S>>,
|
||||||
) -> Result<(), Self::Error>;
|
) -> Result<(), Self::Error>;
|
||||||
unsafe fn slice_unchecked<'a>(
|
unsafe fn slice_unchecked<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
range: Range<Idx>,
|
range: Range<Address<S>>,
|
||||||
) -> VolumeSlice<'a, T, Idx>;
|
) -> VolumeSlice<'a, T, S>;
|
||||||
|
|
||||||
fn slice<'a>(
|
fn slice<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
range: Range<Idx>,
|
range: Range<Address<S>>,
|
||||||
) -> Result<VolumeSlice<'a, T, Idx>, Self::Error>;
|
) -> Result<VolumeSlice<'a, T, S>, Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct VolumeSlice<'a, T: 'a, Idx>
|
pub struct VolumeSlice<'a, T: 'a + Clone, S: SectorSize> {
|
||||||
where
|
|
||||||
[T]: ToOwned,
|
|
||||||
{
|
|
||||||
inner: Cow<'a, [T]>,
|
inner: Cow<'a, [T]>,
|
||||||
index: Idx,
|
index: Address<S>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, Idx: Default> VolumeSlice<'static, T, Idx>
|
impl<T: Clone, S: SectorSize> VolumeSlice<'static, T, S> {
|
||||||
where
|
pub fn with_static(inner: &'static [T]) -> VolumeSlice<'static, T, S> {
|
||||||
[T]: ToOwned,
|
|
||||||
{
|
|
||||||
pub fn with_static(inner: &'static [T]) -> VolumeSlice<'static, T, Idx> {
|
|
||||||
VolumeSlice {
|
VolumeSlice {
|
||||||
inner: Cow::Borrowed(inner),
|
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(
|
pub fn new_owned(
|
||||||
inner: <[T] as ToOwned>::Owned,
|
inner: <[T] as ToOwned>::Owned,
|
||||||
index: Idx,
|
index: Address<S>,
|
||||||
) -> VolumeSlice<'static, T, Idx> {
|
) -> VolumeSlice<'static, T, S> {
|
||||||
VolumeSlice {
|
VolumeSlice {
|
||||||
inner: Cow::Owned(inner),
|
inner: Cow::Owned(inner),
|
||||||
index,
|
index,
|
||||||
|
@ -70,11 +55,8 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T, Idx> VolumeSlice<'a, T, Idx>
|
impl<'a, T: Clone, S: SectorSize> VolumeSlice<'a, T, S> {
|
||||||
where
|
pub fn new(inner: &'a [T], index: Address<S>) -> VolumeSlice<'a, T, S> {
|
||||||
[T]: ToOwned,
|
|
||||||
{
|
|
||||||
pub fn new(inner: &'a [T], index: Idx) -> VolumeSlice<'a, T, Idx> {
|
|
||||||
VolumeSlice {
|
VolumeSlice {
|
||||||
inner: Cow::Borrowed(inner),
|
inner: Cow::Borrowed(inner),
|
||||||
index,
|
index,
|
||||||
|
@ -88,13 +70,13 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn at_index(&self) -> &Idx {
|
pub fn address(&self) -> Address<S> {
|
||||||
&self.index
|
self.index
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Idx: Copy> VolumeSlice<'a, u8, Idx> {
|
impl<'a, S: SectorSize> VolumeSlice<'a, u8, S> {
|
||||||
pub unsafe fn dynamic_cast<T: Copy>(&self) -> (T, Idx) {
|
pub unsafe fn dynamic_cast<T: Copy>(&self) -> (T, Address<S>) {
|
||||||
assert!(self.inner.len() >= mem::size_of::<T>());
|
assert!(self.inner.len() >= mem::size_of::<T>());
|
||||||
let index = self.index;
|
let index = self.index;
|
||||||
let cast = mem::transmute_copy(self.inner.as_ptr().as_ref().unwrap());
|
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>(
|
pub fn from_cast<T: Copy>(
|
||||||
cast: &'a T,
|
cast: &'a T,
|
||||||
index: Idx,
|
index: Address<S>,
|
||||||
) -> VolumeSlice<'a, u8, Idx> {
|
) -> VolumeSlice<'a, u8, S> {
|
||||||
let len = mem::size_of::<T>();
|
let len = mem::size_of::<T>();
|
||||||
let ptr = cast as *const T as *const u8;
|
let ptr = cast as *const T as *const u8;
|
||||||
let slice = unsafe { slice::from_raw_parts(ptr, len) };
|
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>
|
impl<'a, T: Clone, S: SectorSize> VolumeSlice<'a, T, S> {
|
||||||
where
|
pub fn commit(self) -> Option<VolumeCommit<T, S>> {
|
||||||
[T]: ToOwned<Owned = Vec<T>>,
|
|
||||||
{
|
|
||||||
pub fn commit(self) -> Option<VolumeCommit<T, Idx>> {
|
|
||||||
if self.is_mutated() {
|
if self.is_mutated() {
|
||||||
Some(VolumeCommit::new(self.inner.into_owned(), self.index))
|
Some(VolumeCommit::new(self.inner.into_owned(), self.index))
|
||||||
} else {
|
} else {
|
||||||
|
@ -125,29 +104,19 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T, Idx> AsRef<[T]> for VolumeSlice<'a, T, Idx>
|
impl<'a, T: Clone, S: SectorSize> AsRef<[T]> for VolumeSlice<'a, T, S> {
|
||||||
where
|
|
||||||
[T]: ToOwned,
|
|
||||||
{
|
|
||||||
fn as_ref(&self) -> &[T] {
|
fn as_ref(&self) -> &[T] {
|
||||||
self.inner.as_ref()
|
self.inner.as_ref()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T, Idx> AsMut<[T]> for VolumeSlice<'a, T, Idx>
|
impl<'a, T: Clone, S: SectorSize> AsMut<[T]> for VolumeSlice<'a, T, S> {
|
||||||
where
|
|
||||||
[T]: ToOwned,
|
|
||||||
<[T] as ToOwned>::Owned: AsMut<[T]>,
|
|
||||||
{
|
|
||||||
fn as_mut(&mut self) -> &mut [T] {
|
fn as_mut(&mut self) -> &mut [T] {
|
||||||
self.inner.to_mut().as_mut()
|
self.inner.to_mut().as_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T, Idx> Deref for VolumeSlice<'a, T, Idx>
|
impl<'a, T: Clone, S: SectorSize> Deref for VolumeSlice<'a, T, S> {
|
||||||
where
|
|
||||||
[T]: ToOwned,
|
|
||||||
{
|
|
||||||
type Target = [T];
|
type Target = [T];
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
|
@ -155,32 +124,28 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T, Idx> DerefMut for VolumeSlice<'a, T, Idx>
|
impl<'a, T: Clone, S: SectorSize> DerefMut for VolumeSlice<'a, T, S> {
|
||||||
where
|
|
||||||
[T]: ToOwned,
|
|
||||||
<[T] as ToOwned>::Owned: AsMut<[T]>,
|
|
||||||
{
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
self.as_mut()
|
self.as_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct VolumeCommit<T, Idx> {
|
pub struct VolumeCommit<T, S: SectorSize> {
|
||||||
inner: Vec<T>,
|
inner: Vec<T>,
|
||||||
index: Idx,
|
index: Address<S>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, Idx: Default> VolumeCommit<T, Idx> {
|
impl<T: Clone, S: SectorSize> VolumeCommit<T, S> {
|
||||||
pub fn with_vec(inner: Vec<T>) -> VolumeCommit<T, Idx> {
|
pub fn with_vec(inner: Vec<T>) -> VolumeCommit<T, S> {
|
||||||
VolumeCommit {
|
VolumeCommit {
|
||||||
inner,
|
inner,
|
||||||
index: Idx::default(),
|
index: Address::new(0, 0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, Idx> VolumeCommit<T, Idx> {
|
impl<T: Clone, S: SectorSize> VolumeCommit<T, S> {
|
||||||
pub fn new(inner: Vec<T>, index: Idx) -> VolumeCommit<T, Idx> {
|
pub fn new(inner: Vec<T>, index: Address<S>) -> VolumeCommit<T, S> {
|
||||||
VolumeCommit { inner, index }
|
VolumeCommit { inner, index }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,24 +153,24 @@ impl<T, Idx> VolumeCommit<T, Idx> {
|
||||||
self.inner
|
self.inner
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn at_index(&self) -> &Idx {
|
pub fn address(&self) -> Address<S> {
|
||||||
&self.index
|
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] {
|
fn as_ref(&self) -> &[T] {
|
||||||
self.inner.as_ref()
|
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] {
|
fn as_mut(&mut self) -> &mut [T] {
|
||||||
self.inner.as_mut()
|
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];
|
type Target = [T];
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
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 {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
self.as_mut()
|
self.as_mut()
|
||||||
}
|
}
|
||||||
|
@ -221,26 +186,23 @@ impl<T, Idx> DerefMut for VolumeCommit<T, Idx> {
|
||||||
|
|
||||||
macro_rules! impl_slice {
|
macro_rules! impl_slice {
|
||||||
(@inner $volume:ty $( , $lt:lifetime )* ) => {
|
(@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
|
for $volume
|
||||||
where
|
|
||||||
T: Clone,
|
|
||||||
[T]: ToOwned,
|
|
||||||
{
|
{
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn size(&self) -> Length<Address<S>> {
|
fn size(&self) -> Size<S> {
|
||||||
Length::Bounded(
|
Size::Bounded(
|
||||||
Address::from(<Self as AsRef<[T]>>::as_ref(self).len())
|
Address::from(<Self as AsRef<[T]>>::as_ref(self).len())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn commit(
|
fn commit(
|
||||||
&mut self,
|
&mut self,
|
||||||
slice: Option<VolumeCommit<T, Address<S>>>,
|
slice: Option<VolumeCommit<T, S>>,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
slice.map(|slice| {
|
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();
|
let end = index + slice.as_ref().len();
|
||||||
// XXX: it would be much better to drop the contents of dst
|
// XXX: it would be much better to drop the contents of dst
|
||||||
// and move the contents of slice instead of cloning
|
// and move the contents of slice instead of cloning
|
||||||
|
@ -254,7 +216,7 @@ macro_rules! impl_slice {
|
||||||
unsafe fn slice_unchecked<'a>(
|
unsafe fn slice_unchecked<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
range: Range<Address<S>>,
|
range: Range<Address<S>>,
|
||||||
) -> VolumeSlice<'a, T, Address<S>> {
|
) -> VolumeSlice<'a, T, S> {
|
||||||
let index = range.start;
|
let index = range.start;
|
||||||
let range = range.start.into_index() as usize
|
let range = range.start.into_index() as usize
|
||||||
..range.end.into_index() as usize;
|
..range.end.into_index() as usize;
|
||||||
|
@ -267,7 +229,7 @@ macro_rules! impl_slice {
|
||||||
fn slice<'a>(
|
fn slice<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
range: Range<Address<S>>,
|
range: Range<Address<S>>,
|
||||||
) -> Result<VolumeSlice<'a, T, Address<S>>, Self::Error> {
|
) -> Result<VolumeSlice<'a, T, S>, Self::Error> {
|
||||||
if self.size() >= range.end {
|
if self.size() >= range.end {
|
||||||
unsafe { Ok(self.slice_unchecked(range)) }
|
unsafe { Ok(self.slice_unchecked(range)) }
|
||||||
} else {
|
} else {
|
||||||
|
@ -299,16 +261,16 @@ mod file {
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
|
||||||
use sector::{Address, Size};
|
use sector::{Address, SectorSize};
|
||||||
|
|
||||||
use super::{Volume, VolumeCommit, VolumeSlice};
|
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;
|
type Error = io::Error;
|
||||||
|
|
||||||
fn size(&self) -> Length<Address<S>> {
|
fn size(&self) -> Size<S> {
|
||||||
Length::Bounded(
|
Size::Bounded(
|
||||||
self.borrow()
|
self.borrow()
|
||||||
.metadata()
|
.metadata()
|
||||||
.map(|data| Address::from(data.len()))
|
.map(|data| Address::from(data.len()))
|
||||||
|
@ -318,11 +280,11 @@ mod file {
|
||||||
|
|
||||||
fn commit(
|
fn commit(
|
||||||
&mut self,
|
&mut self,
|
||||||
slice: Option<VolumeCommit<u8, Address<S>>>,
|
slice: Option<VolumeCommit<u8, S>>,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
slice
|
slice
|
||||||
.map(|slice| {
|
.map(|slice| {
|
||||||
let index = *slice.at_index();
|
let index = slice.address();
|
||||||
let mut refmut = self.borrow_mut();
|
let mut refmut = self.borrow_mut();
|
||||||
refmut
|
refmut
|
||||||
.seek(SeekFrom::Start(index.into_index()))
|
.seek(SeekFrom::Start(index.into_index()))
|
||||||
|
@ -335,7 +297,7 @@ mod file {
|
||||||
unsafe fn slice_unchecked<'a>(
|
unsafe fn slice_unchecked<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
range: Range<Address<S>>,
|
range: Range<Address<S>>,
|
||||||
) -> VolumeSlice<'a, u8, Address<S>> {
|
) -> VolumeSlice<'a, u8, S> {
|
||||||
let index = range.start;
|
let index = range.start;
|
||||||
let len = range.end - range.start;
|
let len = range.end - range.start;
|
||||||
let mut vec = Vec::with_capacity(len.into_index() as usize);
|
let mut vec = Vec::with_capacity(len.into_index() as usize);
|
||||||
|
@ -353,7 +315,7 @@ mod file {
|
||||||
fn slice<'a>(
|
fn slice<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
range: Range<Address<S>>,
|
range: Range<Address<S>>,
|
||||||
) -> Result<VolumeSlice<'a, u8, Address<S>>, Self::Error> {
|
) -> Result<VolumeSlice<'a, u8, S>, Self::Error> {
|
||||||
let index = range.start;
|
let index = range.start;
|
||||||
let mut vec = Vec::with_capacity((range.end - range.start)
|
let mut vec = Vec::with_capacity((range.end - range.start)
|
||||||
.into_index()
|
.into_index()
|
||||||
|
|
100
src/volume/size.rs
Normal file
100
src/volume/size.rs
Normal 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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in a new issue