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