Skip to content

Commit 3984b4a

Browse files
committed
multiboot2: get_tag consumes Into<TagTypeId>
1 parent 6d499ac commit 3984b4a

File tree

2 files changed

+63
-10
lines changed

2 files changed

+63
-10
lines changed

multiboot2/src/lib.rs

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,8 @@ impl BootInformation {
311311
/// Public getter to find any Multiboot tag by its type, including
312312
/// specified and custom ones.
313313
///
314+
/// The parameter can be of type `u32`, [`TagType`], or [`TagTypeId`].
315+
///
314316
/// # Specified or Custom Tags
315317
/// The Multiboot2 specification specifies a list of tags, see [`TagType`].
316318
/// However, it doesn't forbid to use custom tags. Because of this, there
@@ -320,10 +322,13 @@ impl BootInformation {
320322
///
321323
/// ## Use Custom Tags
322324
/// The following example shows how you may use this interface to parse custom tags from
323-
/// the MBI.
325+
/// the MBI. Custom tags must be `Sized`. Hence, they are not allowed to contain a field such
326+
/// as `name: [u8]`.
324327
///
325-
/// ```ignore
328+
/// ```rust
329+
/// use std::ffi::{c_char, CStr};
326330
/// use multiboot2::TagTypeId;
331+
///
327332
/// #[repr(C, align(8))]
328333
/// struct CustomTag {
329334
/// // new type from the lib: has repr(u32)
@@ -334,16 +339,16 @@ impl BootInformation {
334339
/// }
335340
///
336341
/// let tag = bi
337-
/// // this function is now public!
338-
/// .get_tag(0x1337.into())
342+
/// .get_tag(0x1337)
339343
/// .unwrap()
340344
/// // type definition from end user; must be `Sized`!
341345
/// .cast_tag::<CustomTag>();
342346
/// let name = &tag.name as *const u8 as *const c_char;
343347
/// let str = unsafe { CStr::from_ptr(name).to_str().unwrap() };
344348
/// assert_eq!(str, "name");
345349
/// ```
346-
pub fn get_tag(&self, typ: TagType) -> Option<&Tag> {
350+
pub fn get_tag(&self, typ: impl Into<TagTypeId>) -> Option<&Tag> {
351+
let typ = typ.into();
347352
self.tags().find(|tag| tag.typ == typ)
348353
}
349354

@@ -1516,15 +1521,63 @@ mod tests {
15161521
name: u8,
15171522
}
15181523

1519-
let tag = bi
1520-
.get_tag(CUSTOM_TAG_ID.into())
1521-
.unwrap()
1522-
.cast_tag::<CustomTag>();
1524+
let tag = bi.get_tag(CUSTOM_TAG_ID).unwrap().cast_tag::<CustomTag>();
15231525

15241526
// strlen without null byte
15251527
let strlen = tag.size as usize - mem::size_of::<CommandLineTag>();
15261528
let bytes = unsafe { slice::from_raw_parts((&tag.name) as *const u8, strlen) };
15271529
let name = core::str::from_utf8(bytes).unwrap();
15281530
assert_eq!(name, "name");
15291531
}
1532+
1533+
/// Tests that `get_tag` can consume multiple types that implement `Into<TagTypeId>`
1534+
#[test]
1535+
fn get_tag_into_variants() {
1536+
#[repr(C, align(8))]
1537+
struct Bytes([u8; 32]);
1538+
let bytes: Bytes = Bytes([
1539+
32,
1540+
0,
1541+
0,
1542+
0, // total_size
1543+
0,
1544+
0,
1545+
0,
1546+
0, // reserved
1547+
TagType::Cmdline.val().to_ne_bytes()[0],
1548+
TagType::Cmdline.val().to_ne_bytes()[1],
1549+
TagType::Cmdline.val().to_ne_bytes()[2],
1550+
TagType::Cmdline.val().to_ne_bytes()[3],
1551+
13,
1552+
0,
1553+
0,
1554+
0, // tag size
1555+
110,
1556+
97,
1557+
109,
1558+
101, // ASCII string 'name'
1559+
0,
1560+
0,
1561+
0,
1562+
0, // null byte + padding
1563+
0,
1564+
0,
1565+
0,
1566+
0, // end tag type
1567+
8,
1568+
0,
1569+
0,
1570+
0, // end tag size
1571+
]);
1572+
1573+
let addr = bytes.0.as_ptr() as usize;
1574+
let bi = unsafe { load(addr) };
1575+
let bi = bi.unwrap();
1576+
1577+
let _tag = bi.get_tag(TagType::Cmdline).unwrap();
1578+
1579+
let _tag = bi.get_tag(1).unwrap();
1580+
1581+
let _tag = bi.get_tag(TagTypeId::new(1)).unwrap();
1582+
}
15301583
}

multiboot2/src/tag_type.rs

Lines changed: 1 addition & 1 deletion
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)