This repository was archived by the owner on Sep 11, 2023. It is now read-only.
File tree 3 files changed +56
-3
lines changed
3 files changed +56
-3
lines changed Original file line number Diff line number Diff line change @@ -29,15 +29,20 @@ pub trait EnumArray<V>: Enum {
29
29
/// Array for enum-map storage.
30
30
///
31
31
/// This trait is inteded for primitive array types (with fixed length).
32
- pub trait Array < V > {
32
+ pub unsafe trait Array < V > {
33
+ // This is necessary duplication because the length in Enum trait can be
34
+ // provided by user and may not be trustworthy for unsafe code.
35
+ const LENGTH : usize ;
36
+
33
37
/// Coerces a reference to the array into a reference to a slice.
34
38
fn slice ( & self ) -> & [ V ] ;
35
39
36
40
/// Coerces a mutable reference to the array into a mutable reference to a slice.
37
41
fn slice_mut ( & mut self ) -> & mut [ V ] ;
38
42
}
39
43
40
- impl < V , const N : usize > Array < V > for [ V ; N ] {
44
+ unsafe impl < V , const N : usize > Array < V > for [ V ; N ] {
45
+ const LENGTH : usize = N ;
41
46
fn slice ( & self ) -> & [ V ] {
42
47
self
43
48
}
Original file line number Diff line number Diff line change 80
80
#[ doc( hidden) ]
81
81
#[ must_use]
82
82
pub fn storage_length ( _: & Self ) -> usize {
83
- K :: LENGTH
83
+ // SAFETY: We need to use LENGTH from K::Array, as K::LENGTH is
84
+ // untrustworthy.
85
+ K :: Array :: LENGTH
84
86
}
85
87
86
88
#[ doc( hidden) ]
Original file line number Diff line number Diff line change @@ -523,3 +523,49 @@ fn map_panic() {
523
523
v + " modified"
524
524
} ) ;
525
525
}
526
+
527
+ macro_rules! make_enum_map_macro_safety_test {
528
+ ( $a: tt $b: tt) => {
529
+ // This is misuse of an API, however we need to test that to ensure safety
530
+ // as we use unsafe code.
531
+ enum E {
532
+ A ,
533
+ B ,
534
+ C ,
535
+ }
536
+
537
+ impl Enum for E {
538
+ const LENGTH : usize = $a;
539
+
540
+ fn from_usize( value: usize ) -> E {
541
+ match value {
542
+ 0 => E :: A ,
543
+ 1 => E :: B ,
544
+ 2 => E :: C ,
545
+ _ => unimplemented!( ) ,
546
+ }
547
+ }
548
+
549
+ fn into_usize( self ) -> usize {
550
+ self as usize
551
+ }
552
+ }
553
+
554
+ impl <V > EnumArray <V > for E {
555
+ type Array = [ V ; $b] ;
556
+ }
557
+
558
+ let map: EnumMap <E , String > = enum_map! { _ => "Hello, world!" . into( ) } ;
559
+ map. into_iter( ) ;
560
+ } ;
561
+ }
562
+
563
+ #[ test]
564
+ fn enum_map_macro_safety_under ( ) {
565
+ make_enum_map_macro_safety_test ! ( 2 3 ) ;
566
+ }
567
+
568
+ #[ test]
569
+ fn enum_map_macro_safety_over ( ) {
570
+ make_enum_map_macro_safety_test ! ( 3 2 ) ;
571
+ }
You can’t perform that action at this time.
0 commit comments