diff --git a/src/addr.rs b/src/addr.rs index d3bec6a8..246529e1 100644 --- a/src/addr.rs +++ b/src/addr.rs @@ -1,7 +1,7 @@ //! Physical and virtual addresses manipulation -#[cfg(feature = "step_trait")] use core::convert::TryFrom; +use core::convert::TryInto; use core::fmt; #[cfg(feature = "step_trait")] use core::iter::Step; @@ -403,6 +403,108 @@ impl Step for VirtAddr { } } +impl TryFrom for VirtAddr { + type Error = VirtAddrNotValid; + + #[inline] + fn try_from(addr: u64) -> Result { + Self::try_new(addr) + } +} + +// if `target_pointer_width > 64`, we would need a different error type +#[cfg(any( + target_pointer_width = "16", + target_pointer_width = "32", + target_pointer_width = "64" +))] +impl TryFrom for VirtAddr { + type Error = VirtAddrNotValid; + + #[inline] + fn try_from(addr: usize) -> Result { + Self::try_new(addr.try_into().unwrap()) + } +} + +// if `target_pointer_width > 64`, we would need a different error type +// (and `as` would truncate) +#[cfg(any( + target_pointer_width = "16", + target_pointer_width = "32", + target_pointer_width = "64" +))] +impl TryFrom<*const T> for VirtAddr { + type Error = VirtAddrNotValid; + + #[inline] + fn try_from(addr: *const T) -> Result { + Self::try_new(addr as u64) + } +} + +// if `target_pointer_width > 64`, we would need a different error type +// (and `as` would truncate) +#[cfg(any( + target_pointer_width = "16", + target_pointer_width = "32", + target_pointer_width = "64" +))] +impl TryFrom<*mut T> for VirtAddr { + type Error = VirtAddrNotValid; + + #[inline] + fn try_from(addr: *mut T) -> Result { + Self::try_new(addr as u64) + } +} + +impl From for VirtAddr { + #[inline] + fn from(addr: u32) -> Self { + Self::new(addr.into()) + } +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +impl From<&T> for VirtAddr { + #[inline] + fn from(addr: &T) -> Self { + Self::new(addr as *const _ as u64) + } +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +impl From<&mut T> for VirtAddr { + #[inline] + fn from(addr: &mut T) -> Self { + Self::new(addr as *mut _ as u64) + } +} + +impl From for u64 { + #[inline] + fn from(addr: VirtAddr) -> Self { + addr.0 + } +} + +#[cfg(target_pointer_width = "64")] +impl From for *const T { + #[inline] + fn from(addr: VirtAddr) -> Self { + addr.0 as *const T + } +} + +#[cfg(target_pointer_width = "64")] +impl From for *mut T { + #[inline] + fn from(addr: VirtAddr) -> Self { + addr.0 as *mut T + } +} + /// A passed `u64` was not a valid physical address. /// /// This means that bits 52 to 64 were not all null. @@ -632,6 +734,29 @@ impl Sub for PhysAddr { } } +impl TryFrom for PhysAddr { + type Error = PhysAddrNotValid; + + #[inline] + fn try_from(addr: u64) -> Result { + Self::try_new(addr) + } +} + +impl From for PhysAddr { + #[inline] + fn from(addr: u32) -> Self { + Self::new(addr.into()) + } +} + +impl From for u64 { + #[inline] + fn from(addr: PhysAddr) -> Self { + addr.0 + } +} + /// Align address downwards. /// /// Returns the greatest `x` with alignment `align` so that `x <= addr`.