@@ -53,16 +53,14 @@ pub fn fill_bytes_via_next<R: RngCore + ?Sized>(rng: &mut R, dest: &mut [u8]) {
53
53
}
54
54
55
55
trait Observable : Copy {
56
- type Bytes : AsRef < [ u8 ] > ;
57
- fn to_le_bytes ( self ) -> Self :: Bytes ;
56
+ fn to_le ( self ) -> Self ;
58
57
59
58
// Contract: observing self is memory-safe (implies no uninitialised padding)
60
59
fn as_byte_slice ( x : & [ Self ] ) -> & [ u8 ] ;
61
60
}
62
61
impl Observable for u32 {
63
- type Bytes = [ u8 ; 4 ] ;
64
- fn to_le_bytes ( self ) -> Self :: Bytes {
65
- self . to_le_bytes ( )
62
+ fn to_le ( self ) -> Self {
63
+ self . to_le ( )
66
64
}
67
65
fn as_byte_slice ( x : & [ Self ] ) -> & [ u8 ] {
68
66
let ptr = x. as_ptr ( ) as * const u8 ;
@@ -71,9 +69,8 @@ impl Observable for u32 {
71
69
}
72
70
}
73
71
impl Observable for u64 {
74
- type Bytes = [ u8 ; 8 ] ;
75
- fn to_le_bytes ( self ) -> Self :: Bytes {
76
- self . to_le_bytes ( )
72
+ fn to_le ( self ) -> Self {
73
+ self . to_le ( )
77
74
}
78
75
fn as_byte_slice ( x : & [ Self ] ) -> & [ u8 ] {
79
76
let ptr = x. as_ptr ( ) as * const u8 ;
@@ -82,28 +79,20 @@ impl Observable for u64 {
82
79
}
83
80
}
84
81
85
- fn fill_via_chunks < T : Observable > ( src : & [ T ] , dest : & mut [ u8 ] ) -> ( usize , usize ) {
82
+ fn fill_via_chunks < T : Observable > ( src : & mut [ T ] , dest : & mut [ u8 ] ) -> ( usize , usize ) {
86
83
let size = core:: mem:: size_of :: < T > ( ) ;
87
84
let byte_len = min ( src. len ( ) * size, dest. len ( ) ) ;
88
85
let num_chunks = ( byte_len + size - 1 ) / size;
89
86
90
- if cfg ! ( target_endian = "little" ) {
91
- // On LE we can do a simple copy, which is 25-50% faster:
92
- dest[ ..byte_len] . copy_from_slice ( & T :: as_byte_slice ( & src[ ..num_chunks] ) [ ..byte_len] ) ;
93
- } else {
94
- // This code is valid on all arches, but slower than the above:
95
- let mut i = 0 ;
96
- let mut iter = dest[ ..byte_len] . chunks_exact_mut ( size) ;
97
- for chunk in & mut iter {
98
- chunk. copy_from_slice ( src[ i] . to_le_bytes ( ) . as_ref ( ) ) ;
99
- i += 1 ;
100
- }
101
- let chunk = iter. into_remainder ( ) ;
102
- if !chunk. is_empty ( ) {
103
- chunk. copy_from_slice ( & src[ i] . to_le_bytes ( ) . as_ref ( ) [ ..chunk. len ( ) ] ) ;
87
+ // Byte-swap for portability of results:
88
+ if cfg ! ( target_endian = "big" ) {
89
+ for x in & mut src[ ..num_chunks] {
90
+ * x = x. to_le ( ) ;
104
91
}
105
92
}
106
93
94
+ dest[ ..byte_len] . copy_from_slice ( & T :: as_byte_slice ( & src[ ..num_chunks] ) [ ..byte_len] ) ;
95
+
107
96
( num_chunks, byte_len)
108
97
}
109
98
@@ -112,6 +101,9 @@ fn fill_via_chunks<T: Observable>(src: &[T], dest: &mut [u8]) -> (usize, usize)
112
101
///
113
102
/// The return values are `(consumed_u32, filled_u8)`.
114
103
///
104
+ /// On big-endian systems, endianness of `src[..consumed_u32]` values is
105
+ /// swapped. No other adjustments to `src` are made.
106
+ ///
115
107
/// `filled_u8` is the number of filled bytes in `dest`, which may be less than
116
108
/// the length of `dest`.
117
109
/// `consumed_u32` is the number of words consumed from `src`, which is the same
@@ -137,21 +129,25 @@ fn fill_via_chunks<T: Observable>(src: &[T], dest: &mut [u8]) -> (usize, usize)
137
129
/// }
138
130
/// }
139
131
/// ```
140
- pub fn fill_via_u32_chunks ( src : & [ u32 ] , dest : & mut [ u8 ] ) -> ( usize , usize ) {
132
+ pub fn fill_via_u32_chunks ( src : & mut [ u32 ] , dest : & mut [ u8 ] ) -> ( usize , usize ) {
141
133
fill_via_chunks ( src, dest)
142
134
}
143
135
144
136
/// Implement `fill_bytes` by reading chunks from the output buffer of a block
145
137
/// based RNG.
146
138
///
147
139
/// The return values are `(consumed_u64, filled_u8)`.
140
+ ///
141
+ /// On big-endian systems, endianness of `src[..consumed_u64]` values is
142
+ /// swapped. No other adjustments to `src` are made.
143
+ ///
148
144
/// `filled_u8` is the number of filled bytes in `dest`, which may be less than
149
145
/// the length of `dest`.
150
146
/// `consumed_u64` is the number of words consumed from `src`, which is the same
151
147
/// as `filled_u8 / 8` rounded up.
152
148
///
153
149
/// See `fill_via_u32_chunks` for an example.
154
- pub fn fill_via_u64_chunks ( src : & [ u64 ] , dest : & mut [ u8 ] ) -> ( usize , usize ) {
150
+ pub fn fill_via_u64_chunks ( src : & mut [ u64 ] , dest : & mut [ u8 ] ) -> ( usize , usize ) {
155
151
fill_via_chunks ( src, dest)
156
152
}
157
153
@@ -175,33 +171,41 @@ mod test {
175
171
176
172
#[ test]
177
173
fn test_fill_via_u32_chunks ( ) {
178
- let src = [ 1 , 2 , 3 ] ;
174
+ let src_orig = [ 1 , 2 , 3 ] ;
175
+
176
+ let mut src = src_orig;
179
177
let mut dst = [ 0u8 ; 11 ] ;
180
- assert_eq ! ( fill_via_u32_chunks( & src, & mut dst) , ( 3 , 11 ) ) ;
178
+ assert_eq ! ( fill_via_u32_chunks( & mut src, & mut dst) , ( 3 , 11 ) ) ;
181
179
assert_eq ! ( dst, [ 1 , 0 , 0 , 0 , 2 , 0 , 0 , 0 , 3 , 0 , 0 ] ) ;
182
180
181
+ let mut src = src_orig;
183
182
let mut dst = [ 0u8 ; 13 ] ;
184
- assert_eq ! ( fill_via_u32_chunks( & src, & mut dst) , ( 3 , 12 ) ) ;
183
+ assert_eq ! ( fill_via_u32_chunks( & mut src, & mut dst) , ( 3 , 12 ) ) ;
185
184
assert_eq ! ( dst, [ 1 , 0 , 0 , 0 , 2 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 ] ) ;
186
185
186
+ let mut src = src_orig;
187
187
let mut dst = [ 0u8 ; 5 ] ;
188
- assert_eq ! ( fill_via_u32_chunks( & src, & mut dst) , ( 2 , 5 ) ) ;
188
+ assert_eq ! ( fill_via_u32_chunks( & mut src, & mut dst) , ( 2 , 5 ) ) ;
189
189
assert_eq ! ( dst, [ 1 , 0 , 0 , 0 , 2 ] ) ;
190
190
}
191
191
192
192
#[ test]
193
193
fn test_fill_via_u64_chunks ( ) {
194
- let src = [ 1 , 2 ] ;
194
+ let src_orig = [ 1 , 2 ] ;
195
+
196
+ let mut src = src_orig;
195
197
let mut dst = [ 0u8 ; 11 ] ;
196
- assert_eq ! ( fill_via_u64_chunks( & src, & mut dst) , ( 2 , 11 ) ) ;
198
+ assert_eq ! ( fill_via_u64_chunks( & mut src, & mut dst) , ( 2 , 11 ) ) ;
197
199
assert_eq ! ( dst, [ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 2 , 0 , 0 ] ) ;
198
200
201
+ let mut src = src_orig;
199
202
let mut dst = [ 0u8 ; 17 ] ;
200
- assert_eq ! ( fill_via_u64_chunks( & src, & mut dst) , ( 2 , 16 ) ) ;
203
+ assert_eq ! ( fill_via_u64_chunks( & mut src, & mut dst) , ( 2 , 16 ) ) ;
201
204
assert_eq ! ( dst, [ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ) ;
202
205
206
+ let mut src = src_orig;
203
207
let mut dst = [ 0u8 ; 5 ] ;
204
- assert_eq ! ( fill_via_u64_chunks( & src, & mut dst) , ( 1 , 5 ) ) ;
208
+ assert_eq ! ( fill_via_u64_chunks( & mut src, & mut dst) , ( 1 , 5 ) ) ;
205
209
assert_eq ! ( dst, [ 1 , 0 , 0 , 0 , 0 ] ) ;
206
210
}
207
211
}
0 commit comments