@@ -15,120 +15,167 @@ pub use bitfield_struct_derive::bitfield;
1515///
1616/// FIXME: Use mutable reference as soon as `const_mut_refs` is stable
1717#[ inline( always) ]
18- pub fn bit_copy ( dst : & mut [ u8 ] , dst_off : usize , src : & [ u8 ] , src_off : usize , len : usize ) {
18+ pub const fn bit_copy < const D : usize > (
19+ mut dst : [ u8 ; D ] ,
20+ dst_off : usize ,
21+ src : & [ u8 ] ,
22+ src_off : usize ,
23+ len : usize ,
24+ ) -> [ u8 ; D ] {
1925 debug_assert ! ( len > 0 ) ;
2026 debug_assert ! ( dst. len( ) * 8 >= dst_off + len) ;
2127 debug_assert ! ( src. len( ) * 8 >= src_off + len) ;
2228
23- // normalize input
24- let dst = & mut dst[ dst_off / 8 ..] ;
25- let src = & src[ src_off / 8 ..] ;
26- let dst_off = dst_off % 8 ;
27- let src_off = src_off % 8 ;
28-
29- if len < ( 8 - dst_off) {
29+ if len == 1 {
30+ let dst_i = dst_off / 8 ;
31+ dst[ dst_i] = single_bit ( dst[ dst_i] , dst_off % 8 , src, src_off) ;
32+ dst
33+ } else if len < ( 8 - ( dst_off % 8 ) ) {
3034 // edge case if there are less then one byte to be copied
31- single_byte ( & mut dst[ 0 ] , dst_off, src, src_off, len) ;
32- } else if dst_off == src_off {
33- copy_aligned ( dst, src, dst_off, len) ;
35+ let dst_i = dst_off / 8 ;
36+ dst[ dst_i] = single_byte ( dst[ dst_i] , dst_off % 8 , src, src_off, len) ;
37+ dst
38+ } else if dst_off % 8 == src_off % 8 {
39+ copy_aligned ( dst, dst_off / 8 , src, src_off / 8 , dst_off % 8 , len)
40+ } else {
41+ copy_unaligned ( dst, dst_off, src, src_off, len)
42+ }
43+ }
44+
45+ #[ inline( always) ]
46+ pub const fn is_bit_set ( src : & [ u8 ] , i : usize ) -> bool {
47+ debug_assert ! ( i < src. len( ) * 8 ) ;
48+ ( src[ i / 8 ] >> ( i % 8 ) ) & 1 != 0
49+ }
50+
51+ #[ inline( always) ]
52+ const fn single_bit ( dst : u8 , dst_off : usize , src : & [ u8 ] , src_off : usize ) -> u8 {
53+ debug_assert ! ( dst_off < 8 ) ;
54+ if is_bit_set ( src, src_off) {
55+ dst | ( 1 << dst_off)
3456 } else {
35- copy_unaligned ( dst, dst_off , src , src_off , len ) ;
57+ dst & ! ( 1 << dst_off )
3658 }
3759}
3860
3961#[ inline( always) ]
40- fn single_byte ( dst : & mut u8 , dst_off : usize , src : & [ u8 ] , src_off : usize , len : usize ) {
62+ const fn single_byte ( dst : u8 , dst_off : usize , src : & [ u8 ] , src_off : usize , len : usize ) -> u8 {
63+ debug_assert ! ( dst_off < 8 ) ;
64+
65+ let src_i = src_off / 8 ;
66+ let src_off = src_off % 8 ;
67+
4168 let mask = ( u8:: MAX >> ( 8 - len) ) << dst_off;
42- * dst &= !mask;
43- * dst |= ( ( src[ 0 ] >> src_off) << dst_off) & mask;
69+ let mut dst = dst & !mask;
70+ dst |= ( ( src[ src_i ] >> src_off) << dst_off) & mask;
4471
4572 // exceeding a single byte of the src buffer
4673 if len + src_off > 8 {
47- * dst |= ( src[ 1 ] << ( 8 - src_off + dst_off) ) & mask;
74+ dst |= ( src[ src_i + 1 ] << ( 8 - src_off + dst_off) ) & mask;
4875 }
76+ dst
4977}
5078
5179#[ inline( always) ]
52- fn copy_unaligned (
53- mut dst : & mut [ u8 ] ,
54- dst_off : usize ,
55- mut src : & [ u8 ] ,
80+ const fn copy_unaligned < const D : usize > (
81+ mut dst : [ u8 ; D ] ,
82+ mut dst_off : usize ,
83+ src : & [ u8 ] ,
5684 mut src_off : usize ,
5785 mut len : usize ,
58- ) {
59- debug_assert ! ( 0 < dst_off && dst_off < 8 && 0 < src_off && src_off < 8 ) ;
86+ ) -> [ u8 ; D ] {
87+ debug_assert ! ( src_off % 8 != 0 && dst_off % 8 != 0 ) ;
6088 debug_assert ! ( dst. len( ) * 8 >= dst_off + len) ;
6189 debug_assert ! ( src. len( ) * 8 >= src_off + len) ;
6290
91+ let mut dst_i = dst_off / 8 ;
92+ dst_off %= 8 ;
93+ let mut src_i = src_off / 8 ;
94+ src_off %= 8 ;
95+
6396 // copy dst prefix -> byte-align dst
6497 if dst_off > 0 {
6598 let prefix = 8 - dst_off;
6699 let mask = u8:: MAX << dst_off;
67- dst[ 0 ] &= !mask;
68- dst[ 0 ] |= ( src[ 0 ] >> src_off) << dst_off;
100+ dst[ dst_i ] &= !mask;
101+ dst[ dst_i ] |= ( src[ src_i ] >> src_off) << dst_off;
69102
70103 // exceeding a single byte of the src buffer
71104 src_off += prefix;
72105 if let Some ( reminder) = src_off. checked_sub ( 8 ) {
73- src = & src [ 1 .. ] ;
106+ src_i += 1 ;
74107 if reminder > 0 {
75- dst[ 0 ] |= src[ 0 ] << ( dst_off + reminder)
108+ dst[ dst_i ] |= src[ src_i ] << ( dst_off + reminder)
76109 }
77110 src_off = reminder
78111 }
79- dst = & mut dst [ 1 .. ] ;
112+ dst_i += 1 ;
80113 len -= prefix;
81114 }
82115
83116 // copy middle
84- for i in 0 ..len / 8 {
85- dst[ i] = ( src[ i] >> src_off) | ( src[ i + 1 ] << ( 8 - src_off) ) ;
117+ let mut i = 0 ;
118+ while i < len / 8 {
119+ dst[ dst_i + i] = ( src[ src_i + i] >> src_off) | ( src[ src_i + i + 1 ] << ( 8 - src_off) ) ;
120+ i += 1 ;
86121 }
87122
88123 // suffix
89124 let suffix = len % 8 ;
90125 if suffix > 0 {
91126 let last = len / 8 ;
92127 let mask = u8:: MAX >> ( 8 - suffix) ;
93- dst[ last] &= !mask;
94- dst[ last] |= src[ last] >> src_off;
128+ dst[ dst_i + last] &= !mask;
129+ dst[ dst_i + last] |= src[ src_i + last] >> src_off;
95130
96131 // exceeding a single byte of the src buffer
97132 if suffix + src_off > 8 {
98- dst[ last] |= ( src[ last + 1 ] << ( 8 - src_off) ) & mask;
133+ dst[ dst_i + last] |= ( src[ src_i + last + 1 ] << ( 8 - src_off) ) & mask;
99134 }
100135 }
136+ dst
101137}
102138#[ inline( always) ]
103- fn copy_aligned ( mut dst : & mut [ u8 ] , mut src : & [ u8 ] , off : usize , mut len : usize ) {
104- debug_assert ! ( 0 < off && off < 8 ) ;
105- debug_assert ! ( dst. len( ) * 8 >= off + len) ;
106- debug_assert ! ( src. len( ) * 8 >= off + len) ;
139+ const fn copy_aligned < const D : usize > (
140+ mut dst : [ u8 ; D ] ,
141+ mut dst_i : usize ,
142+ src : & [ u8 ] ,
143+ mut src_i : usize ,
144+ off : usize ,
145+ mut len : usize ,
146+ ) -> [ u8 ; D ] {
147+ debug_assert ! ( off < 8 ) ;
148+ debug_assert ! ( dst. len( ) * 8 >= dst_i * 8 + len) ;
149+ debug_assert ! ( src. len( ) * 8 >= src_i * 8 + len) ;
107150
108151 // copy prefix -> byte-align dst
109152 if off > 0 {
110- let prefix = 8 - off;
111- let mask = u8:: MAX << off;
112- dst[ 0 ] &= !mask;
113- dst[ 0 ] |= src[ 0 ] & mask;
153+ let prefix = 8 - ( off % 8 ) ;
154+ let mask = u8:: MAX << ( off % 8 ) ;
155+ dst[ dst_i ] &= !mask;
156+ dst[ dst_i ] |= src[ src_i ] & mask;
114157
115- src = & src [ 1 .. ] ;
116- dst = & mut dst [ 1 .. ] ;
158+ src_i += 1 ;
159+ dst_i += 1 ;
117160 len -= prefix;
118161 }
119162
120163 // copy middle
121- let bytes = len / 8 ;
122- dst[ ..bytes] . copy_from_slice ( & src[ ..bytes] ) ;
164+ let mut i = 0 ;
165+ while i < len / 8 {
166+ dst[ dst_i + i] = src[ src_i + i] ;
167+ i += 1 ;
168+ }
123169
124170 // copy suffix
125171 let suffix = len % 8 ;
126172 if suffix > 0 {
127173 let last = len / 8 ;
128174 let mask = u8:: MAX >> ( 8 - suffix) ;
129- dst[ last] &= !mask;
130- dst[ last] |= src[ last] ;
175+ dst[ dst_i + last] &= !mask;
176+ dst[ dst_i + last] |= src[ src_i + last] ;
131177 }
178+ dst
132179}
133180
134181#[ cfg( test) ]
@@ -140,90 +187,90 @@ mod test {
140187 #[ test]
141188 fn copy_bits_single_bit ( ) {
142189 // single byte
143- let src = & [ 0b00100000 ] ;
144- let dst = & mut [ 0b10111111 ] ;
145- super :: bit_copy ( dst, 6 , src, 5 , 1 ) ;
146- assert_eq ! ( dst, & [ 0b11111111 ] ) ;
190+ let src = [ 0b00100000 ] ;
191+ let dst = [ 0b10111111 ] ;
192+ let dst = super :: bit_copy ( dst, 6 , & src, 5 , 1 ) ;
193+ assert_eq ! ( dst, [ 0b11111111 ] ) ;
147194 // reversed
148- let src = & [ !0b00100000 ] ;
149- let dst = & mut [ !0b10111111 ] ;
150- super :: bit_copy ( dst, 6 , src, 5 , 1 ) ;
151- assert_eq ! ( dst, & [ !0b11111111 ] ) ;
195+ let src = [ !0b00100000 ] ;
196+ let dst = [ !0b10111111 ] ;
197+ let dst = super :: bit_copy ( dst, 6 , & src, 5 , 1 ) ;
198+ assert_eq ! ( dst, [ !0b11111111 ] ) ;
152199 }
153200
154201 #[ test]
155202 fn copy_bits_single_byte ( ) {
156203 // single byte
157- let src = & [ 0b00111000 ] ;
158- let dst = & mut [ 0b10001111 ] ;
159- super :: bit_copy ( dst, 4 , src, 3 , 3 ) ;
160- assert_eq ! ( dst, & [ 0b11111111 ] ) ;
204+ let src = [ 0b00111000 ] ;
205+ let dst = [ 0b10001111 ] ;
206+ let dst = super :: bit_copy ( dst, 4 , & src, 3 , 3 ) ;
207+ assert_eq ! ( dst, [ 0b11111111 ] ) ;
161208 // reversed
162- let src = & [ !0b00111000 ] ;
163- let dst = & mut [ !0b10001111 ] ;
164- super :: bit_copy ( dst, 4 , src, 3 , 3 ) ;
165- assert_eq ! ( dst, & [ !0b11111111 ] ) ;
209+ let src = [ !0b00111000 ] ;
210+ let dst = [ !0b10001111 ] ;
211+ let dst = super :: bit_copy ( dst, 4 , & src, 3 , 3 ) ;
212+ assert_eq ! ( dst, [ !0b11111111 ] ) ;
166213 }
167214
168215 #[ test]
169216 fn copy_bits_unaligned ( ) {
170217 // two to single byte
171- let src = & [ 0b00000000 , 0b11000000 , 0b00000111 , 0b00000000 ] ;
172- let dst = & mut [ 0b00000000 , 0b00000000 , 0b00000000 , 0b00000000 ] ;
173- super :: bit_copy ( dst, 17 , src, 14 , 5 ) ;
174- assert_eq ! ( dst, & [ 0b00000000 , 0b00000000 , 0b00111110 , 0b0000000 ] ) ;
218+ let src = [ 0b00000000 , 0b11000000 , 0b00000111 , 0b00000000 ] ;
219+ let dst = [ 0b00000000 , 0b00000000 , 0b00000000 , 0b00000000 ] ;
220+ let dst = super :: bit_copy ( dst, 17 , & src, 14 , 5 ) ;
221+ assert_eq ! ( dst, [ 0b00000000 , 0b00000000 , 0b00111110 , 0b0000000 ] ) ;
175222 // reversed
176- let src = & [ !0b00000000 , !0b11000000 , !0b00000111 , !0b00000000 ] ;
177- let dst = & mut [ !0b00000000 , !0b00000000 , !0b00000000 , !0b00000000 ] ;
178- super :: bit_copy ( dst, 17 , src, 14 , 5 ) ;
179- assert_eq ! ( dst, & [ !0b00000000 , !0b00000000 , !0b00111110 , !0b0000000 ] ) ;
223+ let src = [ !0b00000000 , !0b11000000 , !0b00000111 , !0b00000000 ] ;
224+ let dst = [ !0b00000000 , !0b00000000 , !0b00000000 , !0b00000000 ] ;
225+ let dst = super :: bit_copy ( dst, 17 , & src, 14 , 5 ) ;
226+ assert_eq ! ( dst, [ !0b00000000 , !0b00000000 , !0b00111110 , !0b0000000 ] ) ;
180227
181228 // over two bytes
182- let src = & [ 0b00000000 , 0b11000000 , 0b00000111 , 0b00000000 ] ;
183- let dst = & mut [ 0b00000000 , 0b00000000 , 0b00000000 , 0b00000000 ] ;
184- super :: bit_copy ( dst, 23 , src, 14 , 5 ) ;
185- assert_eq ! ( dst, & [ 0b00000000 , 0b00000000 , 0b10000000 , 0b00001111 ] ) ;
229+ let src = [ 0b00000000 , 0b11000000 , 0b00000111 , 0b00000000 ] ;
230+ let dst = [ 0b00000000 , 0b00000000 , 0b00000000 , 0b00000000 ] ;
231+ let dst = super :: bit_copy ( dst, 23 , & src, 14 , 5 ) ;
232+ assert_eq ! ( dst, [ 0b00000000 , 0b00000000 , 0b10000000 , 0b00001111 ] ) ;
186233 // reversed
187- let src = & [ !0b00000000 , !0b11000000 , !0b00000111 , !0b00000000 ] ;
188- let dst = & mut [ !0b00000000 , !0b00000000 , !0b00000000 , !0b00000000 ] ;
189- super :: bit_copy ( dst, 23 , src, 14 , 5 ) ;
190- assert_eq ! ( dst, & [ !0b00000000 , !0b00000000 , !0b10000000 , !0b00001111 ] ) ;
234+ let src = [ !0b00000000 , !0b11000000 , !0b00000111 , !0b00000000 ] ;
235+ let dst = [ !0b00000000 , !0b00000000 , !0b00000000 , !0b00000000 ] ;
236+ let dst = super :: bit_copy ( dst, 23 , & src, 14 , 5 ) ;
237+ assert_eq ! ( dst, [ !0b00000000 , !0b00000000 , !0b10000000 , !0b00001111 ] ) ;
191238
192239 // over three bytes
193- let src = & [ 0b11000000 , 0b11111111 , 0b00000111 , 0b00000000 ] ;
194- let dst = & mut [ 0b00000000 , 0b00000000 , 0b00000000 , 0b00000000 ] ;
195- super :: bit_copy ( dst, 15 , src, 6 , 13 ) ;
196- assert_eq ! ( dst, & [ 0b00000000 , 0b10000000 , 0b11111111 , 0b00001111 ] ) ;
240+ let src = [ 0b11000000 , 0b11111111 , 0b00000111 , 0b00000000 ] ;
241+ let dst = [ 0b00000000 , 0b00000000 , 0b00000000 , 0b00000000 ] ;
242+ let dst = super :: bit_copy ( dst, 15 , & src, 6 , 13 ) ;
243+ assert_eq ! ( dst, [ 0b00000000 , 0b10000000 , 0b11111111 , 0b00001111 ] ) ;
197244 // reversed
198- let src = & [ !0b11000000 , !0b11111111 , !0b00000111 , !0b00000000 ] ;
199- let dst = & mut [ !0b00000000 , !0b00000000 , !0b00000000 , !0b00000000 ] ;
200- super :: bit_copy ( dst, 15 , src, 6 , 13 ) ;
201- assert_eq ! ( dst, & [ !0b00000000 , !0b10000000 , !0b11111111 , !0b00001111 ] ) ;
245+ let src = [ !0b11000000 , !0b11111111 , !0b00000111 , !0b00000000 ] ;
246+ let dst = [ !0b00000000 , !0b00000000 , !0b00000000 , !0b00000000 ] ;
247+ let dst = super :: bit_copy ( dst, 15 , & src, 6 , 13 ) ;
248+ assert_eq ! ( dst, [ !0b00000000 , !0b10000000 , !0b11111111 , !0b00001111 ] ) ;
202249 }
203250
204251 #[ test]
205252 fn copy_bits_aligned ( ) {
206253 // over two bytes
207- let src = & [ 0b00000000 , 0b11000000 , 0b00000111 , 0b00000000 ] ;
208- let dst = & mut [ 0b00000000 , 0b00000000 , 0b00000000 , 0b00000000 ] ;
209- super :: bit_copy ( dst, 14 , src, 14 , 5 ) ;
254+ let src = [ 0b00000000 , 0b11000000 , 0b00000111 , 0b00000000 ] ;
255+ let dst = [ 0b00000000 , 0b00000000 , 0b00000000 , 0b00000000 ] ;
256+ let dst = super :: bit_copy ( dst, 14 , & src, 14 , 5 ) ;
210257 assert_eq ! ( dst, src) ;
211258 // reversed
212- let src = & [ !0b00000000 , !0b11000000 , !0b00000111 , !0b00000000 ] ;
213- let dst = & mut [ !0b00000000 , !0b00000000 , !0b00000000 , !0b00000000 ] ;
214- super :: bit_copy ( dst, 14 , src, 14 , 5 ) ;
259+ let src = [ !0b00000000 , !0b11000000 , !0b00000111 , !0b00000000 ] ;
260+ let dst = [ !0b00000000 , !0b00000000 , !0b00000000 , !0b00000000 ] ;
261+ let dst = super :: bit_copy ( dst, 14 , & src, 14 , 5 ) ;
215262 assert_eq ! ( dst, src) ;
216263
217264 // over three bytes
218- let src = & [ 0b11000000 , 0b11100111 , 0b00000111 , 0b00000000 ] ;
219- let dst = & mut [ 0b00000000 , 0b00000000 , 0b00000000 , 0b00000000 ] ;
220- super :: bit_copy ( dst, 14 , src, 6 , 13 ) ;
221- assert_eq ! ( dst, & [ 0b00000000 , 0b11000000 , 0b11100111 , 0b00000111 ] ) ;
265+ let src = [ 0b11000000 , 0b11100111 , 0b00000111 , 0b00000000 ] ;
266+ let dst = [ 0b00000000 , 0b00000000 , 0b00000000 , 0b00000000 ] ;
267+ let dst = super :: bit_copy ( dst, 14 , & src, 6 , 13 ) ;
268+ assert_eq ! ( dst, [ 0b00000000 , 0b11000000 , 0b11100111 , 0b00000111 ] ) ;
222269 // reversed
223- let src = & [ !0b11000000 , !0b11100111 , !0b00000111 , !0b00000000 ] ;
224- let dst = & mut [ !0b00000000 , !0b00000000 , !0b00000000 , !0b00000000 ] ;
225- super :: bit_copy ( dst, 14 , src, 6 , 13 ) ;
226- assert_eq ! ( dst, & [ !0b00000000 , !0b11000000 , !0b11100111 , !0b00000111 ] ) ;
270+ let src = [ !0b11000000 , !0b11100111 , !0b00000111 , !0b00000000 ] ;
271+ let dst = [ !0b00000000 , !0b00000000 , !0b00000000 , !0b00000000 ] ;
272+ let dst = super :: bit_copy ( dst, 14 , & src, 6 , 13 ) ;
273+ assert_eq ! ( dst, [ !0b00000000 , !0b11000000 , !0b11100111 , !0b00000111 ] ) ;
227274 }
228275
229276 #[ test]
0 commit comments