multiboot2_common/
test_utils.rs

1//! Various test utilities.
2
3#![allow(missing_docs)]
4
5use crate::{Header, MaybeDynSized, Tag};
6use core::borrow::Borrow;
7use core::mem;
8use core::ops::Deref;
9
10/// Helper to 8-byte align the underlying bytes, as mandated in the Multiboot2
11/// spec.
12///
13/// With this type, one can create manual and raw Multiboot2 boot information or
14/// just the bytes for simple tags, in a manual and raw approach.
15#[derive(Debug)]
16#[repr(C, align(8))]
17pub struct AlignedBytes<const N: usize>(pub [u8; N]);
18
19impl<const N: usize> AlignedBytes<N> {
20    /// Creates a new type.
21    #[must_use]
22    pub const fn new(bytes: [u8; N]) -> Self {
23        Self(bytes)
24    }
25}
26
27impl<const N: usize> Borrow<[u8; N]> for AlignedBytes<N> {
28    fn borrow(&self) -> &[u8; N] {
29        &self.0
30    }
31}
32
33impl<const N: usize> Borrow<[u8]> for AlignedBytes<N> {
34    fn borrow(&self) -> &[u8] {
35        &self.0
36    }
37}
38
39impl<const N: usize> Deref for AlignedBytes<N> {
40    type Target = [u8; N];
41
42    fn deref(&self) -> &Self::Target {
43        &self.0
44    }
45}
46
47/// Dummy test header.
48#[derive(Clone, Debug, PartialEq, Eq)]
49#[repr(C, align(8))]
50pub struct DummyTestHeader {
51    typ: u32,
52    size: u32,
53}
54
55impl DummyTestHeader {
56    #[must_use]
57    pub const fn new(typ: u32, size: u32) -> Self {
58        Self { typ, size }
59    }
60
61    #[must_use]
62    pub const fn typ(&self) -> u32 {
63        self.typ
64    }
65
66    #[must_use]
67    pub const fn size(&self) -> u32 {
68        self.size
69    }
70}
71
72impl Header for DummyTestHeader {
73    fn payload_len(&self) -> usize {
74        self.size as usize - mem::size_of::<Self>()
75    }
76
77    fn set_size(&mut self, total_size: usize) {
78        self.size = total_size as u32;
79    }
80}
81
82#[derive(Debug, PartialEq, Eq, ptr_meta::Pointee)]
83#[repr(C, align(8))]
84pub struct DummyDstTag {
85    header: DummyTestHeader,
86    payload: [u8],
87}
88
89impl DummyDstTag {
90    const BASE_SIZE: usize = mem::size_of::<DummyTestHeader>();
91
92    #[must_use]
93    pub const fn header(&self) -> &DummyTestHeader {
94        &self.header
95    }
96
97    #[must_use]
98    pub const fn payload(&self) -> &[u8] {
99        &self.payload
100    }
101}
102
103impl MaybeDynSized for DummyDstTag {
104    type Header = DummyTestHeader;
105
106    const BASE_SIZE: usize = mem::size_of::<DummyTestHeader>();
107
108    fn dst_len(header: &Self::Header) -> Self::Metadata {
109        header.size as usize - Self::BASE_SIZE
110    }
111}
112
113impl Tag for DummyDstTag {
114    type IDType = u32;
115    const ID: Self::IDType = 42;
116}
117
118#[cfg(test)]
119mod tests {
120    use core::mem;
121    use core::ptr::addr_of;
122
123    use crate::ALIGNMENT;
124
125    use super::*;
126
127    #[test]
128    fn abi() {
129        assert_eq!(mem::align_of::<AlignedBytes<0>>(), ALIGNMENT);
130
131        let bytes = AlignedBytes([0]);
132        assert_eq!(bytes.as_ptr().align_offset(8), 0);
133        assert_eq!((addr_of!(bytes[0])).align_offset(8), 0);
134
135        let bytes = AlignedBytes([0, 1, 2, 3, 4, 5, 6, 7]);
136        assert_eq!(bytes.as_ptr().align_offset(8), 0);
137        assert_eq!((addr_of!(bytes[0])).align_offset(8), 0);
138
139        let bytes = AlignedBytes([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
140        assert_eq!(bytes.as_ptr().align_offset(8), 0);
141        assert_eq!((addr_of!(bytes[0])).align_offset(8), 0);
142        assert_eq!((addr_of!(bytes[7])).align_offset(8), 1);
143        assert_eq!((addr_of!(bytes[8])).align_offset(8), 0);
144        assert_eq!((addr_of!(bytes[9])).align_offset(8), 7);
145    }
146}