/// Cashaddr encodes its data in 5-bit chunks. The spec defines how a stream
/// of bits should be broken up into these 5-bit chunks, which this function performs.
///
/// Every 5 bits in a stream gets its own byte, right aligned. If there are any bits
/// leftover that don't fill a full 5-bit group, they are padded with zeros on the right
/// to create a 5-bit group and placed one last byte the same way. For example:
///
/// Given 3 bytes with bits labeled alphabetically:
///    [abcdefgh, ijklmnop, qrstuvwx]
/// This function converts to 5 bytes in the form:
///    [000abcde, 000fghij, 000klmno, 000pqrst, 000uvwx0]
///
/// The same idea works in reverse during decoding, going from 5bits to 8bits.
Cashaddr encodes its data in 5-bit chunks. The spec defines how a stream
of bits should be broken up into these 5-bit chunks, which this function performs.

Every 5 bits in a stream gets its own byte, right aligned. If there are any bits
leftover that don't fill a full 5-bit group, they are padded with zeros on the right
to create a 5-bit group and placed one last byte the same way. For example.

Given 3 bytes with bits labeled alphabetically:
[abcdefgh, ijklmnop, qrstuvwx]
This function converts to 5 bytes in the form:
[000abcde, 000fghij, 000klmno, 000pqrst, 000uvwx0]

The same idea works in reverse during decoding, going from 5bits to 8bits.
Cashaddr encodes its data in 5 - bit chunks . The spec defines how a stream of bits should be broken up into these 5 - bit chunks which this function performs . Every 5 bits in a stream gets its own byte right aligned . If there are any bits leftover that don ' t fill a full 5 - bit group they are padded with zeros on the right to create a 5 - bit group and placed one last byte the same way . For example . Given 3 bytes with bits labeled alphabetically : [ abcdefgh ijklmnop qrstuvwx ] This function converts to 5 bytes in the form : [ 000abcde 000fghij 000klmno 000pqrst 000uvwx0 ] The same idea works in reverse during decoding going from 5bits to 8bits .
fn convert_bits(data: &[u8], inbits: u8, outbits: u8, pad: bool) -> Vec<u8> {
    assert!(inbits <= 8 && outbits <= 8);
    // num_bytes = ceil(len * 8 / 5)
    let num_bytes = (data.len() * inbits as usize + outbits as usize - 1) / outbits as usize;
    let mut ret = Vec::with_capacity(num_bytes);
    let mut acc: u16 = 0; // accumulator of bits
    let mut num: u8 = 0; // num bits in acc
    let groupmask = (1 << outbits) - 1;
    for d in data.iter() {
        // We push each input chunk into a 16-bit accumulator
        acc = (acc << inbits) | (*d as u16);
        num += inbits;
        // Then we extract all the output groups we can
        while num > outbits {
            ret.push((acc >> num - outbits) as u8);
            acc = acc & !(groupmask << num - outbits);
            num = num - outbits;
        }
    }
    if pad {
        // If there's some bits left, pad and add it
        if num > 0 {
            ret.push((acc << outbits - num) as u8);
        }
    } else {
        // If there's some bits left, figure out if we need to remove padding and add it
        let padding = (data.len() * inbits as usize) % outbits as usize;
        if num as usize > padding {
            ret.push((acc >> padding) as u8);
        }
    }
    ret
}
fn convert_bits ( data : & [ u8 ] , inbits : u8 , outbits : u8 , pad : bool ) -> Vec < u8 > { assert ! ( inbits 8 outbits 8 ) ; // num_bytes = ceil(len * 8 / 5) let num_bytes = ( data . len ( ) * inbits as usize + outbits as usize - 1 ) / outbits as usize ; let mut ret = Vec :: with_capacity ( num_bytes ) ; let mut acc : u16 = 0 ; // accumulator of bits let mut num : u8 = 0 ; // num bits in acc let groupmask = ( 1 << outbits ) - 1 ; for d in data . iter ( ) { // We push each input chunk into a 16-bit accumulator acc = ( acc << inbits ) | ( * d as u16 ) ; num += inbits ; // Then we extract all the output groups we can while num > outbits { ret . push ( ( acc >> num - outbits ) as u8 ) ; acc = acc & ! ( groupmask << num - outbits ) ; num = num - outbits ; } } if pad { // If there's some bits left, pad and add it if num > 0 { ret . push ( ( acc << outbits - num ) as u8 ) ; } } else { // If there's some bits left, figure out if we need to remove padding and add it let padding = ( data . len ( ) * inbits as usize ) % outbits as usize ; if num as usize > padding { ret . push ( ( acc >> padding ) as u8 ) ; } } ret }
Cashaddr encodes its data in 5-bit chunks.
Cashaddr encodes its data in 5 - bit chunks .
data
&[u8]
inbits
u8
outbits
u8
pad
bool