add generic `Idx` type argument to `Buffer` and `Length`

pull/3/head
Szymon Walter 2018-03-20 11:05:56 +01:00
parent 88b1e3b668
commit 7e0af1b8f6
6 changed files with 65 additions and 59 deletions

View File

@ -2,28 +2,30 @@ use core::fmt::{self, Debug, Display};
use core::cmp::Ordering; use core::cmp::Ordering;
#[derive(Clone, Copy, Debug, Hash)] #[derive(Clone, Copy, Debug, Hash)]
pub enum Length { pub enum Length<Idx> {
Unbounded, Unbounded,
Bounded(usize), Bounded(Idx),
} }
impl Length { impl<Idx: Copy> Length<Idx> {
pub fn try_len(&self) -> Option<usize> { pub fn try_len(&self) -> Option<Idx> {
match *self { match *self {
Length::Unbounded => None, Length::Unbounded => None,
Length::Bounded(n) => Some(n), Length::Bounded(n) => Some(n),
} }
} }
pub unsafe fn len(&self) -> usize { pub unsafe fn len(&self) -> Idx {
match *self { match *self {
Length::Unbounded => { Length::Unbounded => panic!(
panic!("attempt to convert `Length::Unbounded` to `usize`") "attempt to convert `Length::Unbounded` to `Length::Idx`"
} ),
Length::Bounded(n) => n, Length::Bounded(n) => n,
} }
} }
}
impl<Idx> Length<Idx> {
pub fn is_bounded(&self) -> bool { pub fn is_bounded(&self) -> bool {
match *self { match *self {
Length::Unbounded => false, Length::Unbounded => false,
@ -32,62 +34,64 @@ impl Length {
} }
} }
impl Display for Length { impl<Idx: Debug> Display for Length<Idx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(self, f) Debug::fmt(self, f)
} }
} }
impl PartialEq for Length { impl<Idx: PartialEq> PartialEq for Length<Idx> {
fn eq(&self, rhs: &Length) -> bool { fn eq(&self, rhs: &Self) -> bool {
match (*self, *rhs) { match (self, rhs) {
(Length::Unbounded, _) => false, (&Length::Unbounded, _) => false,
(_, Length::Unbounded) => false, (_, &Length::Unbounded) => false,
(Length::Bounded(a), Length::Bounded(ref b)) => a.eq(b), (&Length::Bounded(ref a), &Length::Bounded(ref b)) => a.eq(b),
} }
} }
fn ne(&self, rhs: &Length) -> bool { fn ne(&self, rhs: &Self) -> bool {
match (*self, *rhs) { match (self, rhs) {
(Length::Unbounded, _) => false, (&Length::Unbounded, _) => false,
(_, Length::Unbounded) => false, (_, &Length::Unbounded) => false,
(Length::Bounded(a), Length::Bounded(ref b)) => a.ne(b), (&Length::Bounded(ref a), &Length::Bounded(ref b)) => a.ne(b),
} }
} }
} }
impl PartialEq<usize> for Length { impl<Idx: PartialEq> PartialEq<Idx> for Length<Idx> {
fn eq(&self, rhs: &usize) -> bool { fn eq(&self, rhs: &Idx) -> bool {
match *self { match *self {
Length::Unbounded => false, Length::Unbounded => false,
Length::Bounded(n) => n.eq(rhs), Length::Bounded(ref n) => n.eq(rhs),
} }
} }
fn ne(&self, rhs: &usize) -> bool { fn ne(&self, rhs: &Idx) -> bool {
match *self { match *self {
Length::Unbounded => false, Length::Unbounded => false,
Length::Bounded(n) => n.eq(rhs), Length::Bounded(ref n) => n.eq(rhs),
} }
} }
} }
impl PartialOrd for Length { impl<Idx: PartialOrd> PartialOrd for Length<Idx> {
fn partial_cmp(&self, rhs: &Length) -> Option<Ordering> { fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
match (*self, *rhs) { match (self, rhs) {
(Length::Unbounded, Length::Unbounded) => None, (&Length::Unbounded, &Length::Unbounded) => None,
(Length::Unbounded, _) => Some(Ordering::Greater), (&Length::Unbounded, _) => Some(Ordering::Greater),
(_, Length::Unbounded) => Some(Ordering::Less), (_, &Length::Unbounded) => Some(Ordering::Less),
(Length::Bounded(a), Length::Bounded(ref b)) => a.partial_cmp(b), (&Length::Bounded(ref a), &Length::Bounded(ref b)) => {
a.partial_cmp(b)
}
} }
} }
} }
impl PartialOrd<usize> for Length { impl<Idx: PartialOrd> PartialOrd<Idx> for Length<Idx> {
fn partial_cmp(&self, rhs: &usize) -> Option<Ordering> { fn partial_cmp(&self, rhs: &Idx) -> Option<Ordering> {
match *self { match *self {
Length::Unbounded => Some(Ordering::Greater), Length::Unbounded => Some(Ordering::Greater),
Length::Bounded(n) => n.partial_cmp(rhs), Length::Bounded(ref n) => n.partial_cmp(rhs),
} }
} }
} }

View File

@ -11,23 +11,24 @@ use error::Infallible;
pub mod length; pub mod length;
use self::length::Length; use self::length::Length;
pub trait Buffer<T> pub trait Buffer<T, Idx>
where where
[T]: ToOwned, [T]: ToOwned,
Idx: PartialEq + PartialOrd,
{ {
type Error; type Error;
fn len(&self) -> Length; fn len(&self) -> Length<Idx>;
fn commit( fn commit(
&mut self, &mut self,
slice: Option<BufferCommit<T>>, slice: Option<BufferCommit<T>>,
) -> Result<(), Self::Error>; ) -> Result<(), Self::Error>;
unsafe fn slice_unchecked<'a>( unsafe fn slice_unchecked<'a>(
&'a self, &'a self,
range: Range<usize>, range: Range<Idx>,
) -> BufferSlice<'a, T>; ) -> BufferSlice<'a, T>;
fn slice<'a>(&'a self, range: Range<usize>) -> Option<BufferSlice<'a, T>> { fn slice<'a>(&'a self, range: Range<Idx>) -> Option<BufferSlice<'a, T>> {
if self.len() >= range.end && self.len() > range.start { if self.len() >= range.end && self.len() > range.start {
unsafe { Some(self.slice_unchecked(range)) } unsafe { Some(self.slice_unchecked(range)) }
} else { } else {
@ -214,14 +215,14 @@ impl<T> DerefMut for BufferCommit<T> {
macro_rules! impl_slice { macro_rules! impl_slice {
(@inner $buffer:ty $( , $lt:lifetime )* ) => { (@inner $buffer:ty $( , $lt:lifetime )* ) => {
impl<$( $lt, )* T> Buffer<T> for $buffer impl<$( $lt, )* T> Buffer<T, usize> for $buffer
where where
T: Clone, T: Clone,
[T]: ToOwned, [T]: ToOwned,
{ {
type Error = Infallible; type Error = Infallible;
fn len(&self) -> Length { fn len(&self) -> Length<usize> {
Length::Bounded(<Self as AsRef<[T]>>::as_ref(self).len()) Length::Bounded(<Self as AsRef<[T]>>::as_ref(self).len())
} }
@ -272,10 +273,10 @@ mod file {
use super::{Buffer, BufferCommit, BufferSlice}; use super::{Buffer, BufferCommit, BufferSlice};
use super::length::Length; use super::length::Length;
impl Buffer<u8> for RefCell<File> { impl Buffer<u8, usize> for RefCell<File> {
type Error = io::Error; type Error = io::Error;
fn len(&self) -> Length { fn len(&self) -> Length<usize> {
Length::Bounded( Length::Bounded(
self.borrow() self.borrow()
.metadata() .metadata()

View File

@ -2,6 +2,7 @@ use core::mem;
use alloc::Vec; use alloc::Vec;
use error::Error; use error::Error;
use block::Address; // TODO
use buffer::{Buffer, BufferSlice}; use buffer::{Buffer, BufferSlice};
use sys::superblock::Superblock; use sys::superblock::Superblock;
use sys::block_group::BlockGroupDescriptor; use sys::block_group::BlockGroupDescriptor;
@ -20,13 +21,13 @@ impl<T> From<(T, usize)> for Struct<T> {
} }
/// Safe wrapper for raw sys structs /// Safe wrapper for raw sys structs
pub struct Ext2<B: Buffer<u8>> { pub struct Ext2<B: Buffer<u8, usize>> {
buffer: B, buffer: B,
superblock: Struct<Superblock>, superblock: Struct<Superblock>,
block_groups: Struct<Vec<BlockGroupDescriptor>>, block_groups: Struct<Vec<BlockGroupDescriptor>>,
} }
impl<B: Buffer<u8>> Ext2<B> impl<B: Buffer<u8, usize>> Ext2<B>
where where
Error: From<B::Error>, Error: From<B::Error>,
{ {
@ -164,7 +165,7 @@ where
} }
} }
pub struct Inodes<'a, B: 'a + Buffer<u8>> { pub struct Inodes<'a, B: 'a + Buffer<u8, usize>> {
buffer: &'a B, buffer: &'a B,
block_groups: &'a [BlockGroupDescriptor], block_groups: &'a [BlockGroupDescriptor],
block_size: usize, block_size: usize,
@ -174,7 +175,7 @@ pub struct Inodes<'a, B: 'a + Buffer<u8>> {
index: usize, index: usize,
} }
impl<'a, B: 'a + Buffer<u8>> Iterator for Inodes<'a, B> impl<'a, B: 'a + Buffer<u8, usize>> Iterator for Inodes<'a, B>
where where
Error: From<B::Error>, Error: From<B::Error>,
{ {

View File

@ -51,12 +51,12 @@ impl Debug for BlockGroupDescriptor {
} }
impl BlockGroupDescriptor { impl BlockGroupDescriptor {
pub unsafe fn find_descriptor<'a, E>( pub unsafe fn find_descriptor<B: Buffer<u8, usize>>(
haystack: &'a Buffer<u8, Error = E>, haystack: &B,
offset: usize, offset: usize,
) -> Result<(BlockGroupDescriptor, usize), Error> ) -> Result<(BlockGroupDescriptor, usize), Error>
where where
Error: From<E>, Error: From<B::Error>,
{ {
let end = offset + mem::size_of::<BlockGroupDescriptor>(); let end = offset + mem::size_of::<BlockGroupDescriptor>();
if haystack.len() < end { if haystack.len() < end {
@ -70,13 +70,13 @@ impl BlockGroupDescriptor {
Ok(descr) Ok(descr)
} }
pub unsafe fn find_descriptor_table<'a, E>( pub unsafe fn find_descriptor_table<B: Buffer<u8, usize>>(
haystack: &'a Buffer<u8, Error = E>, haystack: &B,
offset: usize, offset: usize,
count: usize, count: usize,
) -> Result<(Vec<BlockGroupDescriptor>, usize), Error> ) -> Result<(Vec<BlockGroupDescriptor>, usize), Error>
where where
Error: From<E>, Error: From<B::Error>,
{ {
let end = offset + count * mem::size_of::<BlockGroupDescriptor>(); let end = offset + count * mem::size_of::<BlockGroupDescriptor>();
if haystack.len() < end { if haystack.len() < end {

View File

@ -96,13 +96,13 @@ impl Debug for Inode {
} }
impl Inode { impl Inode {
pub unsafe fn find_inode<'a, E>( pub unsafe fn find_inode<B: Buffer<u8, usize>>(
haystack: &'a Buffer<u8, Error = E>, haystack: &B,
offset: usize, offset: usize,
size: usize, size: usize,
) -> Result<(Inode, usize), Error> ) -> Result<(Inode, usize), Error>
where where
Error: From<E>, Error: From<B::Error>,
{ {
if size != mem::size_of::<Inode>() { if size != mem::size_of::<Inode>() {
unimplemented!("inodes with a size != 128"); unimplemented!("inodes with a size != 128");

View File

@ -194,11 +194,11 @@ impl Debug for Superblock {
} }
impl Superblock { impl Superblock {
pub unsafe fn find<'a, E>( pub unsafe fn find<B: Buffer<u8, usize>>(
haystack: &'a Buffer<u8, Error = E>, haystack: &B,
) -> Result<(Superblock, usize), Error> ) -> Result<(Superblock, usize), Error>
where where
Error: From<E>, Error: From<B::Error>,
{ {
let offset = 1024; let offset = 1024;
let end = offset + mem::size_of::<Superblock>(); let end = offset + mem::size_of::<Superblock>();