Skip to content

Commit ff60f05

Browse files
committed
multiboot2: get_tag consumes Into<TagTypeId>
1 parent 73e97a0 commit ff60f05

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
@@ -322,6 +322,8 @@ impl BootInformation {
322322
/// Public getter to find any Multiboot tag by its type, including
323323
/// specified and custom ones.
324324
///
325+
/// The parameter can be of type `u32`, [`TagType`], or [`TagTypeId`].
326+
///
325327
/// # Specified or Custom Tags
326328
/// The Multiboot2 specification specifies a list of tags, see [`TagType`].
327329
/// However, it doesn't forbid to use custom tags. Because of this, there
@@ -331,10 +333,13 @@ impl BootInformation {
331333
///
332334
/// ## Use Custom Tags
333335
/// The following example shows how you may use this interface to parse custom tags from
334-
/// the MBI.
336+
/// the MBI. Custom tags must be `Sized`. Hence, they are not allowed to contain a field such
337+
/// as `name: [u8]`.
335338
///
336-
/// ```ignore
339+
/// ```rust
340+
/// use std::ffi::{c_char, CStr};
337341
/// use multiboot2::TagTypeId;
342+
///
338343
/// #[repr(C, align(8))]
339344
/// struct CustomTag {
340345
/// // new type from the lib: has repr(u32)
@@ -345,16 +350,16 @@ impl BootInformation {
345350
/// }
346351
///
347352
/// let tag = bi
348-
/// // this function is now public!
349-
/// .get_tag(0x1337.into())
353+
/// .get_tag(0x1337)
350354
/// .unwrap()
351355
/// // type definition from end user; must be `Sized`!
352356
/// .cast_tag::<CustomTag>();
353357
/// let name = &tag.name as *const u8 as *const c_char;
354358
/// let str = unsafe { CStr::from_ptr(name).to_str().unwrap() };
355359
/// assert_eq!(str, "name");
356360
/// ```
357-
pub fn get_tag(&self, typ: TagType) -> Option<&Tag> {
361+
pub fn get_tag(&self, typ: impl Into<TagTypeId>) -> Option<&Tag> {
362+
let typ = typ.into();
358363
self.tags().find(|tag| tag.typ == typ)
359364
}
360365

@@ -1548,15 +1553,63 @@ mod tests {
15481553
name: u8,
15491554
}
15501555

1551-
let tag = bi
1552-
.get_tag(CUSTOM_TAG_ID.into())
1553-
.unwrap()
1554-
.cast_tag::<CustomTag>();
1556+
let tag = bi.get_tag(CUSTOM_TAG_ID).unwrap().cast_tag::<CustomTag>();
15551557

15561558
// strlen without null byte
15571559
let strlen = tag.size as usize - mem::size_of::<CommandLineTag>();
15581560
let bytes = unsafe { slice::from_raw_parts((&tag.name) as *const u8, strlen) };
15591561
let name = core::str::from_utf8(bytes).unwrap();
15601562
assert_eq!(name, "name");
15611563
}
1564+
1565+
/// Tests that `get_tag` can consume multiple types that implement `Into<TagTypeId>`
1566+
#[test]
1567+
fn get_tag_into_variants() {
1568+
#[repr(C, align(8))]
1569+
struct Bytes([u8; 32]);
1570+
let bytes: Bytes = Bytes([
1571+
32,
1572+
0,
1573+
0,
1574+
0, // total_size
1575+
0,
1576+
0,
1577+
0,
1578+
0, // reserved
1579+
TagType::Cmdline.val().to_ne_bytes()[0],
1580+
TagType::Cmdline.val().to_ne_bytes()[1],
1581+
TagType::Cmdline.val().to_ne_bytes()[2],
1582+
TagType::Cmdline.val().to_ne_bytes()[3],
1583+
13,
1584+
0,
1585+
0,
1586+
0, // tag size
1587+
110,
1588+
97,
1589+
109,
1590+
101, // ASCII string 'name'
1591+
0,
1592+
0,
1593+
0,
1594+
0, // null byte + padding
1595+
0,
1596+
0,
1597+
0,
1598+
0, // end tag type
1599+
8,
1600+
0,
1601+
0,
1602+
0, // end tag size
1603+
]);
1604+
1605+
let addr = bytes.0.as_ptr() as usize;
1606+
let bi = unsafe { load(addr) };
1607+
let bi = bi.unwrap();
1608+
1609+
let _tag = bi.get_tag(TagType::Cmdline).unwrap();
1610+
1611+
let _tag = bi.get_tag(1).unwrap();
1612+
1613+
let _tag = bi.get_tag(TagTypeId::new(1)).unwrap();
1614+
}
15621615
}

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)