Writing a iterator to provide the individual bits supplied by an iterator of bytes means you can count them with
fn count_bits<I : Iterator<Item=bool>>(it : I) -> i32{
let mut a=0;
for i in it {
if i {a+=1};
}
return a;
}
Counting bits in an array of bytes would need something like this let p:[u8;6] = [1,2,54,2,3,6];
let result = count_bits(bits(p.iter().cloned()));
Checking what that generates in asm https://godbolt.org/g/iTyfapThe core of the code is
.LBB0_4:
mov esi, edx ;edx has the current mask of the bit we are looking at
and esi, ecx ;ecx is the byte we are examining
cmp esi, 1 ;check the bit to see if it is set (note using carry not zero flag)
sbb eax, -1 ;fun way to conditionally add 1
.LBB0_1:
shr edx ;shift mask to the next bit
jne .LBB0_4 ;if mask still has a bit in it, go do the next bit otherwise continue to get the next byte
cmp rbx, r12 ;r12 has the memory location of where we should stop. Are we there yet?
je .LBB0_5 ; if we are there, jump out. we're all done
movzx ecx, byte ptr [rbx] ;get the next byte
inc rbx ; advance the pointer
mov edx, 128 ; set a new mask starting at the top bit
jmp .LBB0_4 ; go get the next bit
.LBB0_5:
Apart from magical bit counting instructions this is close to what I would have written in asm mysef. That really impressed me. I'm still a little wary of hitting a performance cliff. I worry that I can easily add something that will mean the optimiser bails on the whole chain, but so far I'm trusting Rust more than I have trusted any other Optimiser.If this produces simiarly nice code (I haven't checked yet) I'll be very happy
for (dest,source) in self.buffer.iter_mut().zip(data) { *dest=source }