diff --git a/CHANGELOG.md b/CHANGELOG.md index a8ed0cc..0bad50a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +* **0.9.3:** + * Added `as_u32_slice` and `as_u16_slice` to `Align4`. + * *Removed* the requirement for inputs to `include_aligned_bytes!` to be a + multiple of 4 bytes. + * Added `as_usize` to all the screeblock address types. * **0.9.2:** * Adds support for more BIOS functions, though not all functions are as clearly documented as I'd like. diff --git a/src/lib.rs b/src/lib.rs index 2a4fd6e..72f6af0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -110,15 +110,41 @@ pub mod video; #[repr(C, align(4))] pub struct Align4(pub T); -/// As [`include_bytes!`] but the value is wrapped in [`Align4`] -/// -/// ## Panics -/// * The included number of bytes must be a multiple of 4. +impl Align4<[u8; N]> { + /// Views these bytes as a slice of `u32` + /// ## Panics + /// * If the number of bytes isn't a multiple of 4 + pub fn as_u32_slice(&self) -> &[u32] { + assert!(self.0.len() % 4 == 0); + // Safety: our struct is aligned to 4, so the pointer will already be + // aligned, we only need to check the length + unsafe { + let data: *const u8 = self.0.as_ptr(); + let len: usize = self.0.len(); + core::slice::from_raw_parts(data.cast::(), len / 4) + } + } + + /// Views these bytes as a slice of `u16` + /// ## Panics + /// * If the number of bytes isn't a multiple of 2 + pub fn as_u16_slice(&self) -> &[u16] { + assert!(self.0.len() % 2 == 0); + // Safety: our struct is aligned to 4, so the pointer will already be + // aligned, we only need to check the length + unsafe { + let data: *const u8 = self.0.as_ptr(); + let len: usize = self.0.len(); + core::slice::from_raw_parts(data.cast::(), len / 2) + } + } +} + +/// Works like [`include_bytes!`], but the value is wrapped in [`Align4`]. #[macro_export] macro_rules! include_aligned_bytes { ($file:expr $(,)?) => {{ let LONG_NAME_THAT_DOES_NOT_CLASH = *include_bytes!($file); - assert!(LONG_NAME_THAT_DOES_NOT_CLASH.len() % 4 == 0); Align4(LONG_NAME_THAT_DOES_NOT_CLASH) }}; } diff --git a/src/mmio.rs b/src/mmio.rs index c171215..ee10342 100644 --- a/src/mmio.rs +++ b/src/mmio.rs @@ -247,6 +247,12 @@ macro_rules! make_me_a_screenblock_addr { assert!(index <= $max_index); Self { block: unsafe { VolBlock::new(screenblock_addr(index)) } } } + + #[inline] + #[must_use] + pub const fn as_usize(self) -> usize { + self.block.as_usize() + } #[inline] #[must_use]