rewrite how block addresses are constructed
This commit is contained in:
parent
677c072b45
commit
2966b628fa
37
src/block.rs
37
src/block.rs
|
@ -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));
|
||||||
|
|
Reference in a new issue