managed_heap/
address.rs

1use crate::block::header::BlockHeader;
2use crate::block::Block;
3use core::ptr::NonNull;
4use std::ops::{Add, Deref};
5
6#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
7pub struct Address {
8    ptr: usize,
9}
10
11impl Address {
12    pub(crate) fn new(ptr: NonNull<BlockHeader>) -> Self {
13        unsafe {
14            Address {
15                ptr: ptr.as_ptr().add(1) as usize,
16            }
17        }
18    }
19
20    fn from_usize_ptr(ptr: *mut usize) -> Self {
21        Address { ptr: ptr as usize }
22    }
23}
24
25impl Address {
26    #[inline]
27    pub fn as_mut(&mut self) -> *mut usize {
28        self.ptr as *mut usize
29    }
30
31    pub fn write(&mut self, value: usize) {
32        let ptr = self.as_mut();
33        unsafe {
34            *ptr = value;
35        }
36    }
37}
38
39impl From<Block> for Address {
40    fn from(value: Block) -> Address {
41        let ptr: NonNull<BlockHeader> = value.into();
42        Address::new(ptr)
43    }
44}
45
46impl Into<Block> for Address {
47    fn into(self) -> Block {
48        unsafe {
49            let ptr = (self.ptr as *mut usize).offset(-1) as *mut BlockHeader;
50            Block::from(ptr)
51        }
52    }
53}
54
55impl Into<usize> for Address {
56    fn into(self) -> usize {
57        self.ptr
58    }
59}
60
61impl From<usize> for Address {
62    fn from(value: usize) -> Address {
63        Address { ptr: value }
64    }
65}
66
67impl Add<usize> for Address {
68    type Output = Address;
69
70    /// Adds a value to the address. If the value is greater than the block
71    /// size, the result is undefined behaviour.
72    #[inline]
73    fn add(self, value: usize) -> Self {
74        unsafe { Address::from_usize_ptr((self.ptr as *mut usize).add(value)) }
75    }
76}
77
78impl Deref for Address {
79    type Target = usize;
80
81    fn deref(&self) -> &usize {
82        unsafe { (self.ptr as *mut usize).as_ref().unwrap() }
83    }
84}
85
86#[cfg(test)]
87mod tests {
88    use super::*;
89    use std::mem;
90
91    #[test]
92    fn test_address_has_same_size_as_usize() {
93        assert_eq!(mem::size_of::<usize>(), mem::size_of::<Address>());
94    }
95}