Skip to content

Commit c2039c8

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

File tree

1 file changed

+58
-7
lines changed

1 file changed

+58
-7
lines changed

multiboot2/src/lib.rs

Lines changed: 58 additions & 7 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
@@ -334,16 +336,16 @@ impl BootInformation {
334336
/// }
335337
///
336338
/// let tag = bi
337-
/// // this function is now public!
338-
/// .get_tag(0x1337.into())
339+
/// .get_tag(0x1337)
339340
/// .unwrap()
340341
/// // type definition from end user; must be `Sized`!
341342
/// .cast_tag::<CustomTag>();
342343
/// let name = &tag.name as *const u8 as *const c_char;
343344
/// let str = unsafe { CStr::from_ptr(name).to_str().unwrap() };
344345
/// assert_eq!(str, "name");
345346
/// ```
346-
pub fn get_tag(&self, typ: TagType) -> Option<&Tag> {
347+
pub fn get_tag(&self, typ: impl Into<TagTypeId>) -> Option<&Tag> {
348+
let typ = typ.into();
347349
self.tags().find(|tag| tag.typ == typ)
348350
}
349351

@@ -1516,15 +1518,64 @@ mod tests {
15161518
name: u8,
15171519
}
15181520

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

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

0 commit comments

Comments
 (0)