mirx 0.45.0

MIRX binary image format — flat & chunk-based container for ahead-of-time UI assets
Documentation
use super::*;
use alloc::{vec, vec::Vec};

#[test]
fn element_size_and_default_omission_have_one_canonical_record() {
    assert_eq!(Rle::default(), Rle::new());
    for element in 1..=4 {
        let codec = Rle::new().with_element_size(element).unwrap();
        assert_eq!(codec.element_size(), element);
        let record = codec.record();
        assert_eq!(record.id(), CodingId::RLE);
        assert_eq!(record.revision(), 1);
        assert_eq!(
            record.params(),
            if element == 1 {
                &[][..]
            } else {
                core::slice::from_ref(&element)
            }
        );
        assert_eq!(Rle::from_record(record), Ok(codec));
    }
    for size in [0, 5, 255] {
        assert_eq!(
            Rle::new().with_element_size(size),
            Err(RleError::InvalidElementSize(size))
        );
    }
    for params in [&[0][..], &[1], &[5], &[2, 0]] {
        assert_eq!(
            Rle::from_record(CodingRecord::new(CodingId::RLE, 1, params)),
            Err(RleError::UnexpectedParameters)
        );
    }
    assert_eq!(
        Rle::from_record(CodingRecord::new(CodingId::PIXEL, 1, &[])),
        Err(RleError::UnexpectedCoding(CodingId::PIXEL))
    );
    assert_eq!(
        Rle::from_record(CodingRecord::new(CodingId::RLE, 2, &[])),
        Err(RleError::UnsupportedRevision(2))
    );
}

#[test]
fn canonical_encoding_selects_actual_size_and_stable_ties() {
    let codec = Rle::new();
    for (input, expected) in [
        (&[1, 1][..], &[0x81, 1][..]),
        (&[1, 1, 2][..], &[0x81, 1, 0, 2][..]),
        (&[1, 1, 2, 3, 3, 4][..], &[5, 1, 1, 2, 3, 3, 4][..]),
    ] {
        let mut out = [0xad; 16];
        assert_eq!(codec.encoded_len(input), Ok(expected.len()));
        assert_eq!(codec.encode_into(input, &mut out), Ok(expected.len()));
        assert_eq!(&out[..expected.len()], expected);
        assert!(out[expected.len()..].iter().all(|b| *b == 0xad));
    }
    let codec = codec.with_element_size(2).unwrap();
    let samples = [1, 2, 1, 2, 1, 3, 3, 1];
    let expected = [0x81, 1, 2, 1, 1, 3, 3, 1];
    let mut encoded = [0; 16];
    assert_eq!(
        codec.encode_into(&samples, &mut encoded),
        Ok(expected.len())
    );
    assert_eq!(&encoded[..expected.len()], expected);
    let plan = codec.plan(&expected, samples.len()).unwrap();
    assert_eq!(plan.codec(), codec);
    assert_eq!(plan.input(), expected);
    assert_eq!(plan.decoded_len(), samples.len());
    let mut out = [0xad; 12];
    assert_eq!(plan.decode_into(&mut out), Ok(samples.len()));
    assert_eq!(&out[..8], samples);
    assert_eq!(&out[8..], &[0xad; 4]);
}

#[test]
fn every_control_is_positive_bounded_and_independent() {
    for element in 1..=4 {
        let codec = Rle::new().with_element_size(element).unwrap();
        for control in 0..=255u8 {
            let count = usize::from(control & 127) + 1;
            let literal = control & 128 == 0;
            let body = if literal {
                count * usize::from(element)
            } else {
                usize::from(element)
            };
            let mut input = vec![control];
            input.extend((0..body).map(|i| i as u8));
            let mut output = vec![0; count * usize::from(element)];
            codec
                .plan(&input, output.len())
                .unwrap()
                .decode_into(&mut output)
                .unwrap();
            if literal {
                assert_eq!(output, input[1..]);
            } else {
                for value in output.chunks_exact(usize::from(element)) {
                    assert_eq!(value, &input[1..]);
                }
            }
        }
    }
    let codec = Rle::new();
    let mut encoded = [0; 8];
    assert_eq!(codec.encode_into(&[9; 129], &mut encoded), Ok(4));
    assert_eq!(&encoded[..4], &[255, 9, 0, 9]);
    let literal: Vec<_> = (0..128).collect();
    let mut encoded = [0; 129];
    assert_eq!(codec.encode_into(&literal, &mut encoded), Ok(129));
    assert_eq!(encoded[0], 127);
}

#[test]
fn count_truncation_overflow_and_capacity_errors_precede_writes() {
    let codec = Rle::new();
    let mut out = [0xad; 8];
    assert!(codec.encode_into(&[1, 2, 3], &mut out[..3]).is_err());
    assert_eq!(out, [0xad; 8]);
    assert!(
        codec
            .plan(&[2, 1, 2, 3], 3)
            .unwrap()
            .decode_into(&mut out[..2])
            .is_err()
    );
    assert_eq!(out, [0xad; 8]);
    assert!(matches!(
        codec.plan(&[0x81, 3], 1),
        Err(RleError::OutputOverflow { .. })
    ));
    assert!(matches!(
        codec.plan(&[0x81], 2),
        Err(RleError::Truncated { .. })
    ));
    assert!(matches!(
        codec.plan(&[1, 3], 2),
        Err(RleError::Truncated { .. })
    ));
    assert!(matches!(
        codec.plan(&[0, 3, 0], 1),
        Err(RleError::TrailingData { .. })
    ));
    assert_eq!(codec.encoded_bound(usize::MAX), Err(RleError::SizeOverflow));
    let two = codec.with_element_size(2).unwrap();
    assert!(matches!(
        two.plan(&[], 1),
        Err(RleError::PartialElement { .. })
    ));
    assert!(matches!(
        two.encoded_len(&[1]),
        Err(RleError::PartialElement { .. })
    ));
    assert!(matches!(
        two.encode_into(&[1], &mut out),
        Err(RleError::PartialElement { .. })
    ));
    assert_eq!(out, [0xad; 8]);
    assert_eq!(codec.encoded_len(&[]), Ok(0));
    assert_eq!(codec.encode_into(&[], &mut out), Ok(0));
    assert_eq!(codec.plan(&[], 0).unwrap().decode_into(&mut out), Ok(0));
    assert_eq!(out, [0xad; 8]);
}