@@ -15,7 +15,8 @@ pub use self::primitive::*;
15
15
/// break invariants. Therefore auditing this module should be sufficient.
16
16
mod primitive {
17
17
use core:: ops:: {
18
- Bound , Index , Range , RangeFrom , RangeFull , RangeInclusive , RangeTo , RangeToInclusive ,
18
+ Bound , Index , IndexMut , Range , RangeFrom , RangeFull , RangeInclusive , RangeTo ,
19
+ RangeToInclusive ,
19
20
} ;
20
21
21
22
use super :: PushBytesError ;
@@ -43,53 +44,69 @@ mod primitive {
43
44
pub struct PushBytes ( [ u8 ] ) ;
44
45
45
46
impl PushBytes {
46
- /// Creates `&Self ` without checking the length.
47
+ /// Creates `&PushBytes ` without checking the length.
47
48
///
48
49
/// # Safety
49
50
///
50
- /// The caller is responsible for checking that the length is less than the [`LIMIT`] .
51
+ /// The caller is responsible for checking that the length is less than the 2^32 .
51
52
unsafe fn from_slice_unchecked ( bytes : & [ u8 ] ) -> & Self {
53
+ // SAFETY: The caller must guarantee that bytes.len() < 2^32.
54
+ // If that is the case the conversion is sound because &[u8] and &PushBytes
55
+ // have the same layout (because of #[repr(transparent)] on PushBytes).
52
56
& * ( bytes as * const [ u8 ] as * const PushBytes )
53
57
}
54
58
55
- /// Creates `&mut Self ` without checking the length.
59
+ /// Creates `&mut PushBytes ` without checking the length.
56
60
///
57
61
/// # Safety
58
62
///
59
- /// The caller is responsible for checking that the length is less than the [`LIMIT`] .
63
+ /// The caller is responsible for checking that the length is less than the 2^32 .
60
64
unsafe fn from_mut_slice_unchecked ( bytes : & mut [ u8 ] ) -> & mut Self {
65
+ // SAFETY: The caller must guarantee that bytes.len() < 2^32.
66
+ // If that is the case the conversion is sound because &mut [u8] and &mut PushBytes
67
+ // have the same layout (because of #[repr(transparent)] on PushBytes).
61
68
& mut * ( bytes as * mut [ u8 ] as * mut PushBytes )
62
69
}
63
70
64
- /// Creates an empty `PushBytes`.
71
+ /// Creates an empty `& PushBytes`.
65
72
pub fn empty ( ) -> & ' static Self {
66
- // 0 < LIMIT
73
+ // SAFETY: 0 < 2^32.
67
74
unsafe { Self :: from_slice_unchecked ( & [ ] ) }
68
75
}
69
76
70
77
/// Returns the underlying bytes.
71
78
pub fn as_bytes ( & self ) -> & [ u8 ] { & self . 0 }
72
79
73
- /// Returns the underlying mutbale bytes.
80
+ /// Returns the underlying mutable bytes.
74
81
pub fn as_mut_bytes ( & mut self ) -> & mut [ u8 ] { & mut self . 0 }
75
82
}
76
83
77
84
macro_rules! delegate_index {
78
85
( $( $type: ty) ,* $( , ) ?) => {
79
86
$(
80
- /// Script subslicing operation - read [slicing safety](#slicing-safety)!
81
87
impl Index <$type> for PushBytes {
82
88
type Output = Self ;
83
89
84
90
#[ inline]
85
91
#[ track_caller]
86
92
fn index( & self , index: $type) -> & Self :: Output {
87
- // Slicing can not make slices longer
93
+ // SAFETY: Slicing can not make slices longer.
88
94
unsafe {
89
95
Self :: from_slice_unchecked( & self . 0 [ index] )
90
96
}
91
97
}
92
98
}
99
+
100
+ impl IndexMut <$type> for PushBytes {
101
+ #[ inline]
102
+ #[ track_caller]
103
+ fn index_mut( & mut self , index: $type) -> & mut Self :: Output {
104
+ // SAFETY: Slicing can not make slices longer.
105
+ unsafe {
106
+ Self :: from_mut_slice_unchecked( & mut self . 0 [ index] )
107
+ }
108
+ }
109
+ }
93
110
) *
94
111
}
95
112
}
@@ -112,12 +129,18 @@ mod primitive {
112
129
fn index ( & self , index : usize ) -> & Self :: Output { & self . 0 [ index] }
113
130
}
114
131
132
+ impl IndexMut < usize > for PushBytes {
133
+ #[ inline]
134
+ #[ track_caller]
135
+ fn index_mut ( & mut self , index : usize ) -> & mut Self :: Output { & mut self . 0 [ index] }
136
+ }
137
+
115
138
impl < ' a > TryFrom < & ' a [ u8 ] > for & ' a PushBytes {
116
139
type Error = PushBytesError ;
117
140
118
141
fn try_from ( bytes : & ' a [ u8 ] ) -> Result < Self , Self :: Error > {
119
142
check_limit ( bytes. len ( ) ) ?;
120
- // We've just checked the length
143
+ // SAFETY: We've just checked the length.
121
144
Ok ( unsafe { PushBytes :: from_slice_unchecked ( bytes) } )
122
145
}
123
146
}
@@ -127,7 +150,7 @@ mod primitive {
127
150
128
151
fn try_from ( bytes : & ' a mut [ u8 ] ) -> Result < Self , Self :: Error > {
129
152
check_limit ( bytes. len ( ) ) ?;
130
- // We've just checked the length
153
+ // SAFETY: We've just checked the length.
131
154
Ok ( unsafe { PushBytes :: from_mut_slice_unchecked ( bytes) } )
132
155
}
133
156
}
@@ -139,15 +162,15 @@ mod primitive {
139
162
fn from( bytes: & ' a [ u8 ; $len] ) -> Self {
140
163
// Check that the macro wasn't called with a wrong number.
141
164
const _: ( ) = [ ( ) ; 1 ] [ ( $len >= 0x100000000u64 ) as usize ] ;
142
- // We know the size of array statically and we checked macro input.
165
+ // SAFETY: We know the size of array statically and we checked macro input.
143
166
unsafe { PushBytes :: from_slice_unchecked( bytes) }
144
167
}
145
168
}
146
169
147
170
impl <' a> From <& ' a mut [ u8 ; $len] > for & ' a mut PushBytes {
148
171
fn from( bytes: & ' a mut [ u8 ; $len] ) -> Self {
149
172
// Macro check already above, no need to duplicate.
150
- // We know the size of array statically and we checked macro input.
173
+ // SAFETY: We know the size of array statically and we checked macro input.
151
174
unsafe { PushBytes :: from_mut_slice_unchecked( bytes) }
152
175
}
153
176
}
0 commit comments