libribzip2 0.4.0

a bzip2 library written in pure rust
Documentation
pub fn rle(input: &[u8]) -> Vec<u8> {
    let mut output = Vec::<u8>::new();
    let mut counter: usize = 0;
    let mut last = None;
    for current in input.iter() {
        counter += 1;
        if let Some(last_byte) = last {
            if last_byte != *current || counter > 255 {
                if counter >= 5 {
                    for _ in 0..4 {
                        output.push(last_byte);
                    }
                    output.push((counter - 5) as u8);
                } else {
                    for _ in 0..counter - 1 {
                        output.push(last_byte);
                    }
                }
                counter = 1;
            }
        }

        last = Some(*current);
    }

    if let Some(last_byte) = last {
        if counter >= 4 {
            for _ in 0..4 {
                output.push(last_byte);
            }
            output.push((counter - 4) as u8);
        } else {
            for _ in 0..counter {
                output.push(last_byte);
            }
        }
    }

    output
}

pub(crate) fn inverse_rle(input: &[u8]) -> Vec<u8> {
    let mut output = vec![];
    let mut equal_count = 0;
    let mut previous = None;
    for el in input {
        if let Some(&previous) = previous {
            if equal_count == 3 {
                output.append(&mut vec![previous; usize::from(*el)]);
                equal_count = 0;
            } else if previous == *el {
                equal_count += 1;
                output.push(*el);
            } else {
                output.push(*el);
                equal_count = 0;
            }
        } else {
            output.push(*el);
        }
        previous = Some(el);
    }
    output
}

#[cfg(test)]
mod test {
    use super::*;
    #[test]
    pub fn keeps_three_byte_sequences() {
        assert_eq!(rle(&[1, 1, 1]), vec![1, 1, 1]);
    }

    #[test]
    pub fn adds_overflow_to_sequence() {
        assert_eq!(rle(&[1, 1, 1, 1]), vec![1, 1, 1, 1, 0]);
    }

    #[test]
    pub fn larger_numbers() {
        assert_eq!(rle(&[1, 1, 1, 1, 1]), vec![1, 1, 1, 1, 1]);
    }

    #[test]
    pub fn mixed_sequences() {
        assert_eq!(rle(&[1, 1, 1, 1, 2, 2, 2]), vec![1, 1, 1, 1, 0, 2, 2, 2]);
    }

    #[test]
    pub fn mixed_sequences_with_length() {
        assert_eq!(
            rle(&[1, 1, 1, 1, 1, 2, 2, 2, 2, 2]),
            vec![1, 1, 1, 1, 1, 2, 2, 2, 2, 1]
        );
    }

    #[test]
    pub fn mixed_sequences_with_and_without_length() {
        assert_eq!(rle(&[1, 1, 1, 2, 2, 2, 2, 2]), vec![1, 1, 1, 2, 2, 2, 2, 1]);
    }

    #[test]
    pub fn mixed_sequences_with_and_without_length_2() {
        assert_eq!(rle(&[1, 1, 1, 1, 2, 2, 2]), vec![1, 1, 1, 1, 0, 2, 2, 2]);
    }

    #[test]
    pub fn even_longer_sequences() {
        assert_eq!(
            rle(&[1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3]),
            vec![1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3]
        );
    }

    #[test]
    pub fn max_block_length() {
        assert_eq!(
            rle(&std::iter::repeat(3).take(255).collect::<Vec<u8>>()),
            vec![3, 3, 3, 3, 251]
        );
    }

    #[test]
    pub fn more_than_max_block_length() {
        assert_eq!(
            rle(&std::iter::repeat(3).take(256).collect::<Vec<u8>>()),
            vec![3, 3, 3, 3, 251, 3]
        );
    }
    #[test]
    pub fn twice_max_block_length() {
        assert_eq!(
            rle(&std::iter::repeat(3).take(510).collect::<Vec<u8>>()),
            vec![3, 3, 3, 3, 251, 3, 3, 3, 3, 251]
        );
    }

    #[test]
    pub fn inverse_rle_works() {
        assert_eq!(
            inverse_rle(&[1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3]),
            vec![1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3]
        );
    }

    #[test]
    pub fn inverse_mixed_sequences_with_and_without_length_2() {
        assert_eq!(
            inverse_rle(&[1, 1, 1, 1, 0, 2, 2, 2]),
            vec![1, 1, 1, 1, 2, 2, 2]
        );
    }
}