23
23
#![ allow( unused) ]
24
24
25
25
use core:: intrinsics:: transmute;
26
+ use core:: ptr:: copy_nonoverlapping;
26
27
use core:: slice;
27
28
use core:: cmp:: min;
28
29
use core:: mem:: size_of;
@@ -82,21 +83,34 @@ macro_rules! impl_uint_from_fill {
82
83
}
83
84
84
85
macro_rules! fill_via_chunks {
85
- ( $src: expr, $dest: expr, $N: expr) => ( {
86
- let chunk_size_u8 = min( $src. len( ) * $N, $dest. len( ) ) ;
87
- let chunk_size = ( chunk_size_u8 + $N - 1 ) / $N;
88
-
89
- // Convert to little-endian:
90
- for ref mut x in $src[ 0 ..chunk_size] . iter_mut( ) {
91
- * * x = ( * x) . to_le( ) ;
86
+ ( $src: expr, $dst: expr, $size: expr) => ( {
87
+ let chunk_size_u8 = min( $src. len( ) * $size, $dst. len( ) ) ;
88
+ let chunk_size = ( chunk_size_u8 + $size - 1 ) / $size;
89
+ if cfg!( target_endian="little" ) {
90
+ // Unsafe code copied from `byteorder::write_slice_native`.
91
+ unsafe {
92
+ copy_nonoverlapping(
93
+ $src. as_ptr( ) as * const u8 ,
94
+ $dst. as_mut_ptr( ) ,
95
+ chunk_size_u8) ;
96
+ }
97
+ } else {
98
+ // Unsafe code copied from `byteorder::write_slice` and
99
+ // `byteorder::write_num_bytes`, with the addition to copy only
100
+ // `chunk.len()`.
101
+ // Byteorder assumes we want to copy only complete integers, while
102
+ // for us the destination may need only a part of the last integer.
103
+ for ( & n, chunk) in $src. iter( ) . zip( $dst. chunks_mut( $size) ) {
104
+ unsafe {
105
+ // N.B. https://github.com/rust-lang/rust/issues/22776
106
+ let bytes = transmute:: <_, [ u8 ; $size] >( n. to_le( ) ) ;
107
+ copy_nonoverlapping( ( & bytes) . as_ptr( ) ,
108
+ chunk. as_mut_ptr( ) ,
109
+ chunk. len( ) ) ;
110
+ }
111
+ }
92
112
}
93
113
94
- let bytes = unsafe { slice:: from_raw_parts( $src. as_ptr( ) as * const u8 ,
95
- $src. len( ) * $N) } ;
96
-
97
- let dest_chunk = & mut $dest[ 0 ..chunk_size_u8] ;
98
- dest_chunk. copy_from_slice( & bytes[ 0 ..chunk_size_u8] ) ;
99
-
100
114
( chunk_size, chunk_size_u8)
101
115
} ) ;
102
116
}
@@ -111,10 +125,6 @@ macro_rules! fill_via_chunks {
111
125
/// `consumed_u32` is the number of words consumed from `src`, which is the same
112
126
/// as `filled_u8 / 4` rounded up.
113
127
///
114
- /// Note that on big-endian systems values in the output buffer `src` are
115
- /// mutated. `src[0..consumed_u32]` get converted to little-endian before
116
- /// copying.
117
- ///
118
128
/// # Example
119
129
/// (from `IsaacRng`)
120
130
///
@@ -135,7 +145,7 @@ macro_rules! fill_via_chunks {
135
145
/// }
136
146
/// }
137
147
/// ```
138
- pub fn fill_via_u32_chunks ( src : & mut [ u32 ] , dest : & mut [ u8 ] ) -> ( usize , usize ) {
148
+ pub fn fill_via_u32_chunks ( src : & [ u32 ] , dest : & mut [ u8 ] ) -> ( usize , usize ) {
139
149
fill_via_chunks ! ( src, dest, 4 )
140
150
}
141
151
@@ -148,12 +158,8 @@ pub fn fill_via_u32_chunks(src: &mut [u32], dest: &mut [u8]) -> (usize, usize) {
148
158
/// `consumed_u64` is the number of words consumed from `src`, which is the same
149
159
/// as `filled_u8 / 8` rounded up.
150
160
///
151
- /// Note that on big-endian systems values in the output buffer `src` are
152
- /// mutated. `src[0..consumed_u64]` get converted to little-endian before
153
- /// copying.
154
- ///
155
161
/// See `fill_via_u32_chunks` for an example.
156
- pub fn fill_via_u64_chunks ( src : & mut [ u64 ] , dest : & mut [ u8 ] ) -> ( usize , usize ) {
162
+ pub fn fill_via_u64_chunks ( src : & [ u64 ] , dest : & mut [ u8 ] ) -> ( usize , usize ) {
157
163
fill_via_chunks ! ( src, dest, 8 )
158
164
}
159
165
0 commit comments