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;
#[derive(Clone, Copy, Debug, Hash)]
pub enum Length {
pub enum Length<Idx> {
Unbounded,
Bounded(usize),
Bounded(Idx),
}
impl Length {
pub fn try_len(&self) -> Option<usize> {
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) -> usize {
pub unsafe fn len(&self) -> Idx {
match *self {
Length::Unbounded => {
panic!("attempt to convert `Length::Unbounded` to `usize`")
}
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,
@ -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 {
Debug::fmt(self, f)
}
}
impl PartialEq for Length {
fn eq(&self, rhs: &Length) -> bool {
match (*self, *rhs) {
(Length::Unbounded, _) => false,
(_, Length::Unbounded) => false,
(Length::Bounded(a), Length::Bounded(ref b)) => a.eq(b),
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: &Length) -> bool {
match (*self, *rhs) {
(Length::Unbounded, _) => false,
(_, Length::Unbounded) => false,
(Length::Bounded(a), Length::Bounded(ref b)) => a.ne(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<usize> for Length {
fn eq(&self, rhs: &usize) -> bool {
impl<Idx: PartialEq> PartialEq<Idx> for Length<Idx> {
fn eq(&self, rhs: &Idx) -> bool {
match *self {
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 {
Length::Unbounded => false,
Length::Bounded(n) => n.eq(rhs),
Length::Bounded(ref n) => n.eq(rhs),
}
}
}
impl PartialOrd for Length {
fn partial_cmp(&self, rhs: &Length) -> Option<Ordering> {
match (*self, *rhs) {
(Length::Unbounded, Length::Unbounded) => None,
(Length::Unbounded, _) => Some(Ordering::Greater),
(_, Length::Unbounded) => Some(Ordering::Less),
(Length::Bounded(a), Length::Bounded(ref b)) => a.partial_cmp(b),
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 PartialOrd<usize> for Length {
fn partial_cmp(&self, rhs: &usize) -> Option<Ordering> {
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(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;
use self::length::Length;
pub trait Buffer<T>
pub trait Buffer<T, Idx>
where
[T]: ToOwned,
Idx: PartialEq + PartialOrd,
{
type Error;
fn len(&self) -> Length;
fn len(&self) -> Length<Idx>;
fn commit(
&mut self,
slice: Option<BufferCommit<T>>,
) -> Result<(), Self::Error>;
unsafe fn slice_unchecked<'a>(
&'a self,
range: Range<usize>,
range: Range<Idx>,
) -> 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 {
unsafe { Some(self.slice_unchecked(range)) }
} else {
@ -214,14 +215,14 @@ impl<T> DerefMut for BufferCommit<T> {
macro_rules! impl_slice {
(@inner $buffer:ty $( , $lt:lifetime )* ) => {
impl<$( $lt, )* T> Buffer<T> for $buffer
impl<$( $lt, )* T> Buffer<T, usize> for $buffer
where
T: Clone,
[T]: ToOwned,
{
type Error = Infallible;
fn len(&self) -> Length {
fn len(&self) -> Length<usize> {
Length::Bounded(<Self as AsRef<[T]>>::as_ref(self).len())
}
@ -272,10 +273,10 @@ mod file {
use super::{Buffer, BufferCommit, BufferSlice};
use super::length::Length;
impl Buffer<u8> for RefCell<File> {
impl Buffer<u8, usize> for RefCell<File> {
type Error = io::Error;
fn len(&self) -> Length {
fn len(&self) -> Length<usize> {
Length::Bounded(
self.borrow()
.metadata()

View File

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

View File

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

View File

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

View File

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