@@ -311,6 +311,8 @@ impl BootInformation {
311
311
/// Public getter to find any Multiboot tag by its type, including
312
312
/// specified and custom ones.
313
313
///
314
+ /// The parameter can be of type `u32`, [`TagType`], or [`TagTypeId`].
315
+ ///
314
316
/// # Specified or Custom Tags
315
317
/// The Multiboot2 specification specifies a list of tags, see [`TagType`].
316
318
/// However, it doesn't forbid to use custom tags. Because of this, there
@@ -320,10 +322,13 @@ impl BootInformation {
320
322
///
321
323
/// ## Use Custom Tags
322
324
/// 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]`.
324
327
///
325
- /// ```ignore
328
+ /// ```rust
329
+ /// use std::ffi::{c_char, CStr};
326
330
/// use multiboot2::TagTypeId;
331
+ ///
327
332
/// #[repr(C, align(8))]
328
333
/// struct CustomTag {
329
334
/// // new type from the lib: has repr(u32)
@@ -334,16 +339,16 @@ impl BootInformation {
334
339
/// }
335
340
///
336
341
/// let tag = bi
337
- /// // this function is now public!
338
- /// .get_tag(0x1337.into())
342
+ /// .get_tag(0x1337)
339
343
/// .unwrap()
340
344
/// // type definition from end user; must be `Sized`!
341
345
/// .cast_tag::<CustomTag>();
342
346
/// let name = &tag.name as *const u8 as *const c_char;
343
347
/// let str = unsafe { CStr::from_ptr(name).to_str().unwrap() };
344
348
/// assert_eq!(str, "name");
345
349
/// ```
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 ( ) ;
347
352
self . tags ( ) . find ( |tag| tag. typ == typ)
348
353
}
349
354
@@ -1516,15 +1521,63 @@ mod tests {
1516
1521
name : u8 ,
1517
1522
}
1518
1523
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 > ( ) ;
1523
1525
1524
1526
// strlen without null byte
1525
1527
let strlen = tag. size as usize - mem:: size_of :: < CommandLineTag > ( ) ;
1526
1528
let bytes = unsafe { slice:: from_raw_parts ( ( & tag. name ) as * const u8 , strlen) } ;
1527
1529
let name = core:: str:: from_utf8 ( bytes) . unwrap ( ) ;
1528
1530
assert_eq ! ( name, "name" ) ;
1529
1531
}
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
+ }
1530
1583
}
0 commit comments