Skip to content

Commit 9395926

Browse files
committed
multiboot2: get_tag consumes Into<TagTypeId>
1 parent 27b7a84 commit 9395926

File tree

2 files changed

+63
-10
lines changed

2 files changed

+63
-10
lines changed

multiboot2/src/lib.rs

+62-9
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,8 @@ impl BootInformation {
317317
/// Public getter to find any Multiboot tag by its type, including
318318
/// specified and custom ones.
319319
///
320+
/// The parameter can be of type `u32`, [`TagType`], or [`TagTypeId`].
321+
///
320322
/// # Specified or Custom Tags
321323
/// The Multiboot2 specification specifies a list of tags, see [`TagType`].
322324
/// However, it doesn't forbid to use custom tags. Because of this, there
@@ -326,10 +328,13 @@ impl BootInformation {
326328
///
327329
/// ## Use Custom Tags
328330
/// The following example shows how you may use this interface to parse custom tags from
329-
/// the MBI.
331+
/// the MBI. Custom tags must be `Sized`. Hence, they are not allowed to contain a field such
332+
/// as `name: [u8]`.
330333
///
331-
/// ```ignore
334+
/// ```rust
335+
/// use std::ffi::{c_char, CStr};
332336
/// use multiboot2::TagTypeId;
337+
///
333338
/// #[repr(C, align(8))]
334339
/// struct CustomTag {
335340
/// // new type from the lib: has repr(u32)
@@ -340,16 +345,16 @@ impl BootInformation {
340345
/// }
341346
///
342347
/// let tag = bi
343-
/// // this function is now public!
344-
/// .get_tag(0x1337.into())
348+
/// .get_tag(0x1337)
345349
/// .unwrap()
346350
/// // type definition from end user; must be `Sized`!
347351
/// .cast_tag::<CustomTag>();
348352
/// let name = &tag.name as *const u8 as *const c_char;
349353
/// let str = unsafe { CStr::from_ptr(name).to_str().unwrap() };
350354
/// assert_eq!(str, "name");
351355
/// ```
352-
pub fn get_tag(&self, typ: TagType) -> Option<&Tag> {
356+
pub fn get_tag(&self, typ: impl Into<TagTypeId>) -> Option<&Tag> {
357+
let typ = typ.into();
353358
self.tags().find(|tag| tag.typ == typ)
354359
}
355360

@@ -1537,15 +1542,63 @@ mod tests {
15371542
name: u8,
15381543
}
15391544

1540-
let tag = bi
1541-
.get_tag(CUSTOM_TAG_ID.into())
1542-
.unwrap()
1543-
.cast_tag::<CustomTag>();
1545+
let tag = bi.get_tag(CUSTOM_TAG_ID).unwrap().cast_tag::<CustomTag>();
15441546

15451547
// strlen without null byte
15461548
let strlen = tag.size as usize - mem::size_of::<CommandLineTag>();
15471549
let bytes = unsafe { slice::from_raw_parts((&tag.name) as *const u8, strlen) };
15481550
let name = core::str::from_utf8(bytes).unwrap();
15491551
assert_eq!(name, "name");
15501552
}
1553+
1554+
/// Tests that `get_tag` can consume multiple types that implement `Into<TagTypeId>`
1555+
#[test]
1556+
fn get_tag_into_variants() {
1557+
#[repr(C, align(8))]
1558+
struct Bytes([u8; 32]);
1559+
let bytes: Bytes = Bytes([
1560+
32,
1561+
0,
1562+
0,
1563+
0, // total_size
1564+
0,
1565+
0,
1566+
0,
1567+
0, // reserved
1568+
TagType::Cmdline.val().to_ne_bytes()[0],
1569+
TagType::Cmdline.val().to_ne_bytes()[1],
1570+
TagType::Cmdline.val().to_ne_bytes()[2],
1571+
TagType::Cmdline.val().to_ne_bytes()[3],
1572+
13,
1573+
0,
1574+
0,
1575+
0, // tag size
1576+
110,
1577+
97,
1578+
109,
1579+
101, // ASCII string 'name'
1580+
0,
1581+
0,
1582+
0,
1583+
0, // null byte + padding
1584+
0,
1585+
0,
1586+
0,
1587+
0, // end tag type
1588+
8,
1589+
0,
1590+
0,
1591+
0, // end tag size
1592+
]);
1593+
1594+
let addr = bytes.0.as_ptr() as usize;
1595+
let bi = unsafe { load(addr) };
1596+
let bi = bi.unwrap();
1597+
1598+
let _tag = bi.get_tag(TagType::Cmdline).unwrap();
1599+
1600+
let _tag = bi.get_tag(1).unwrap();
1601+
1602+
let _tag = bi.get_tag(TagTypeId::new(1)).unwrap();
1603+
}
15511604
}

multiboot2/src/tag_type.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ pub enum TagType {
3535
/// Tag `1`: Additional command line string.
3636
/// For example `''` or `'--my-custom-option foo --provided by_grub`, if
3737
/// your GRUB config contains `multiboot2 /boot/multiboot2-binary.elf --my-custom-option foo --provided by_grub`
38-
Cmdline, /* 1 */
38+
Cmdline,
3939
/// Tag `2`: Name of the bootloader, e.g. 'GRUB 2.04-1ubuntu44.2'
4040
BootLoaderName,
4141
/// Tag `3`: Additional Multiboot modules, which are BLOBs provided in

0 commit comments

Comments
 (0)