rewrite how block addresses are constructed

This commit is contained in:
Szymon Walter 2018-03-20 10:30:40 +01:00
parent 677c072b45
commit 2966b628fa

View file

@ -42,9 +42,7 @@ pub struct Address<S: Size> {
} }
impl<S: Size> Address<S> { impl<S: Size> Address<S> {
pub fn new(block: usize, offset: usize) -> Address<S> { pub unsafe fn new_unchecked(block: usize, offset: usize) -> Address<S> {
let block = block + (offset >> (S::LOG_SIZE + 10));
let offset = offset & S::OFFSET_MASK;
let _phantom = PhantomData; let _phantom = PhantomData;
Address { Address {
block, block,
@ -53,6 +51,12 @@ impl<S: Size> Address<S> {
} }
} }
pub fn new(block: usize, offset: isize) -> Address<S> {
let block = (block as isize + (offset >> (S::LOG_SIZE + 10))) as usize;
let offset = offset.abs() as usize & S::OFFSET_MASK;
unsafe { Address::new_unchecked(block, offset) }
}
pub fn into_index(&self) -> Option<usize> { pub fn into_index(&self) -> Option<usize> {
self.block self.block
.checked_shl(S::LOG_SIZE + 10) .checked_shl(S::LOG_SIZE + 10)
@ -102,29 +106,27 @@ impl<S: Size> From<usize> for Address<S> {
fn from(idx: usize) -> Address<S> { fn from(idx: usize) -> Address<S> {
let block = idx >> (S::LOG_SIZE + 10); let block = idx >> (S::LOG_SIZE + 10);
let offset = idx & S::OFFSET_MASK; let offset = idx & S::OFFSET_MASK;
Address::new(block, offset) Address::new(block, offset as isize)
} }
} }
impl<S: Size> Add for Address<S> { impl<S: Size> 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> {
let offset = self.offset + rhs.offset; Address::new(
let block = offset >> (S::LOG_SIZE + 10); self.block + rhs.block,
let offset = offset & S::OFFSET_MASK; (self.offset + rhs.offset) as isize,
Address::new(self.block + rhs.block + block, offset) )
} }
} }
impl<S: Size> Sub for Address<S> { impl<S: Size> Sub for Address<S> {
type Output = Address<S>; type Output = Address<S>;
fn sub(mut self, rhs: Address<S>) -> Address<S> { fn sub(self, rhs: Address<S>) -> Address<S> {
if rhs.offset > self.offset { Address::new(
self.offset += S::SIZE; self.block + rhs.block,
self.block -= 1; self.offset as isize - rhs.offset as isize,
} )
let offset = self.offset - rhs.offset;
Address::new(self.block - rhs.block, offset)
} }
} }
@ -139,6 +141,11 @@ mod tests {
Address::<Size1024>::new(1, 0), Address::<Size1024>::new(1, 0),
); );
assert_eq!(
Address::<Size1024>::new(2, -512),
Address::<Size1024>::new(1, 512),
);
let a = Address::<Size2048>::new(0, 1024); let a = Address::<Size2048>::new(0, 1024);
let b = Address::<Size2048>::new(0, 1024); let b = Address::<Size2048>::new(0, 1024);
assert_eq!(a + b, Address::<Size2048>::new(1, 0)); assert_eq!(a + b, Address::<Size2048>::new(1, 0));