@@ -15,75 +15,90 @@ or `a[..end]`. This RFC proposes such methods to fill the gap.
15
15
16
16
# Detailed design
17
17
18
- Add ` get_range ` , ` get_range_mut ` , ` get_range_unchecked ` , ` get_range_unchecked_mut ` to ` SliceExt ` .
19
-
20
- ` get_range ` and ` get_range_mut ` may be implemented roughly as follows:
21
-
18
+ Introduce a ` SliceIndex ` trait which is implemented by types which can index into a slice:
22
19
``` rust
23
- use std :: ops :: {RangeFrom , RangeTo , Range };
24
- use std :: slice :: from_raw_parts;
25
- use core :: slice :: SliceExt ;
26
-
27
- trait Rangeable <T : ? Sized > {
28
- fn start (& self , slice : & T ) -> usize ;
29
- fn end (& self , slice : & T ) -> usize ;
30
- }
20
+ pub trait SliceIndex <T > {
21
+ type Output : ? Sized ;
31
22
32
- impl <T : SliceExt + ? Sized > Rangeable <T > for RangeFrom <usize > {
33
- fn start (& self , _ : & T ) -> usize { self . start }
34
- fn end (& self , slice : & T ) -> usize { slice . len () }
23
+ fn get (self , slice : & [T ]) -> Option <& Self :: Output >;
24
+ fn get_mut (self , slice : & mut [T ]) -> Option <& mut Self :: Output >;
25
+ unsafe fn get_unchecked (self , slice : & [T ]) -> & Self :: Output ;
26
+ unsafe fn get_mut_unchecked (self , slice : & [T ]) -> & mut Self :: Output ;
35
27
}
36
28
37
- impl <T : SliceExt + ? Sized > Rangeable <T > for RangeTo < usize > {
38
- fn start ( & self , _ : & T ) -> usize { 0 }
39
- fn end ( & self , _ : & T ) -> usize { self . end }
29
+ impl <T > SliceIndex <T > for usize {
30
+ type Output = T ;
31
+ // ...
40
32
}
41
33
42
- impl <T : SliceExt + ? Sized > Rangeable <T > for Range <usize > {
43
- fn start (& self , _ : & T ) -> usize { self . start }
44
- fn end (& self , _ : & T ) -> usize { self . end }
34
+ impl <T , R > SliceIndex <T > for R
35
+ where R : RangeArgument <usize >
36
+ {
37
+ type Output = [T ];
38
+ // ...
45
39
}
40
+ ```
46
41
47
- trait GetRangeExt : SliceExt {
48
- fn get_range <R : Rangeable <Self >>(& self , range : R ) -> Option <& [Self :: Item ]>;
49
- }
42
+ Alter the ` Index ` , ` IndexMut ` , ` get ` , ` get_mut ` , ` get_unchecked ` , and ` get_mut_unchecked `
43
+ implementations to be generic over ` SliceIndex ` :
44
+ ``` rust
45
+ impl <T > [T ] {
46
+ pub fn get <I >(& self , idx : I ) -> Option <I :: Output >
47
+ where I : SliceIndex <T >
48
+ {
49
+ idx . get (self )
50
+ }
50
51
51
- impl <T > GetRangeExt for [T ] {
52
- fn get_range <R : Rangeable <Self >>(& self , range : R ) -> Option <& [T ]> {
53
- let start = range . start (self );
54
- let end = range . end (self );
52
+ pub fn get_mut <I >(& mut self , idx : I ) -> Option <I :: Output >
53
+ where I : SliceIndex <T >
54
+ {
55
+ idx . get_mut (self )
56
+ }
55
57
56
- if start > end { return None ; }
57
- if end > self . len () { return None ; }
58
+ pub unsafe fn get_unchecked <I >(& self , idx : I ) -> I :: Output
59
+ where I : SliceIndex <T >
60
+ {
61
+ idx . get_unchecked (self )
62
+ }
58
63
59
- unsafe { Some (from_raw_parts (self . as_ptr (). offset (start as isize ), end - start )) }
64
+ pub unsafe fn get_mut_unchecked <I >(& mut self , idx : I ) -> I :: Output
65
+ where I : SliceIndex <T >
66
+ {
67
+ idx . get_mut_unchecked (self )
60
68
}
61
69
}
62
70
63
- fn main () {
64
- let a = [1 , 2 , 3 , 4 , 5 ];
71
+ impl <T , I > Index <I > for [T ]
72
+ where I : SliceIndex <T >
73
+ {
74
+ type Output = I :: Output ;
65
75
66
- assert_eq! (a . get_range (1 .. ), Some (& a [1 .. ]));
67
- assert_eq! (a . get_range (.. 3 ), Some (& a [.. 3 ]));
68
- assert_eq! (a . get_range (2 .. 5 ), Some (& a [2 .. 5 ]));
69
- assert_eq! (a . get_range (.. 6 ), None );
70
- assert_eq! (a . get_range (4 .. 2 ), None );
76
+ fn index (& self , idx : I ) -> & I :: Output {
77
+ self . get (idx ). expect (" out of bounds slice access" )
78
+ }
71
79
}
72
- ```
73
80
74
- ` get_range_unchecked ` and ` get_range_unchecked_mut ` should be the unchecked versions of the methods
75
- above.
81
+ impl <T , I > IndexMut <I > for [T ]
82
+ where I : SliceIndex <T >
83
+ {
84
+ fn index_mut (& self , idx : I ) -> & mut I :: Output {
85
+ self . get_mut (idx ). expect (" out of bounds slice access" )
86
+ }
87
+ }
88
+ ```
76
89
77
90
# Drawbacks
78
91
79
- - Are these methods worth adding to ` std ` ? Are such use cases common to justify such extention?
92
+ - The ` SliceIndex ` trait is unfortunate - it's tuned for exactly the set of methods it's used by.
93
+ It only exists because inherent methods cannot be overloaded the same way that trait
94
+ implementations can be. It would most likely remain unstable indefinitely.
80
95
81
96
# Alternatives
82
97
83
98
- Stay as is.
84
- - Could there be any other (and better!) total functions that serve the similar purpose?
99
+ - A previous version of this RFC introduced new ` get_slice ` etc methods rather than overloading
100
+ ` get ` etc. This avoids the utility trait but is somewhat less ergonomic.
85
101
86
102
# Unresolved questions
87
103
88
- - Naming, naming, naming: Is ` get_range ` the most suitable name? How about ` get_slice ` , or just
89
- ` slice ` ? Or any others?
104
+ None
0 commit comments