fountaincode 0.0.8

Implementation of the Luby Transform Code in Rust
Documentation
extern crate rand;
extern crate fountaincode;

use self::fountaincode::ltcode::{Encoder, EncoderType, Decoder};
use self::fountaincode::ltcode::CatchResult::*;

use rand::{thread_rng, Rng};


fn encode_decode_random(total_len: usize, chunk_len: usize) {
    let s:String = thread_rng().gen_ascii_chars().take(total_len).collect();
    let buf = s.into_bytes();
    let len = buf.len();
    let to_compare = buf.clone();

    let enc = Encoder::new(buf, chunk_len, EncoderType::Random);
    let mut dec = Decoder::new(len, chunk_len);

    for drop in enc {
        match dec.catch(drop) {
            Missing(stats) => {
                println!("Missing blocks {:?}", stats);
            }
            Finished(data, stats) => {
                assert_eq!(to_compare.len(), data.len());
                for i in 0..len {
                    println!("stats: {:?}", stats);
                    assert_eq!(to_compare[i], data[i]);
                }
                println!("Finished, stas: {:?}", stats);
                return
            }
        }
    }
}

fn encode_decode_systematic(total_len: usize, chunk_len: usize) {
    let s:String = thread_rng().gen_ascii_chars().take(total_len).collect();
    let buf = s.into_bytes();
    let len = buf.len();
    let to_compare = buf.clone();

    let enc = Encoder::new(buf, chunk_len, EncoderType::Systematic);
    let mut dec = Decoder::new(len, chunk_len);

    let mut cnt_drops = 0;

    for drop in enc {
        cnt_drops += 1;
        match dec.catch(drop) {
            Missing(stats) => {
                //a systematic encoder and no loss on channel should only need k symbols
                assert_eq!(stats.cnt_chunks-stats.unknown_chunks, cnt_drops)
            }
            Finished(data, stats) => {
                assert_eq!(to_compare.len(), data.len());
                assert_eq!(stats.cnt_chunks, cnt_drops);
                for i in 0..len {
                    assert_eq!(to_compare[i], data[i]);
                }
                return
            }
        }
    }
}

fn encode_decode_systematic_with_loss(total_len: usize, chunk_len: usize, loss: f32) {
    let s:String = thread_rng().gen_ascii_chars().take(total_len).collect();
    let buf = s.into_bytes();
    let len = buf.len();
    let to_compare = buf.clone();

    let enc = Encoder::new(buf, chunk_len, EncoderType::Systematic);
    let mut dec = Decoder::new(len, chunk_len);

    let mut loss_rng = thread_rng();

    for drop in enc {
        if loss_rng.next_f32() > loss {
            match dec.catch(drop) {
                Missing(_) => {
                    //a systematic encoder and no loss on channel should only need k symbols
                    //assert_eq!(stats.cnt_chunks-stats.unknown_chunks, cnt_drops)
                }
                Finished(data, _) => {
                    assert_eq!(to_compare.len(), data.len());
                    for i in 0..len {
                        assert_eq!(to_compare[i], data[i]);
                    }
                    return
                }
            }
        }
    }
}



#[test]
fn test_encode_decode_simple() {
    encode_decode_random(1_024, 512);
}

#[test]
fn encode_decode_with_uneven_sizes_random() {
    for size in 1000..1100 {
        for chunk in 100..130 {
            encode_decode_random(size, chunk);
        }
    }
}

#[test]
fn small_test_systematic_encoder() {
    encode_decode_systematic(1300, 128);
}

#[test]
fn combinations_encode_decode_with_uneven_sizes_systematic() {
    for size in 1000..1100 {
        for chunk in 100..130 {
            encode_decode_systematic(size, chunk);
        }
    }
}

#[test]
fn small_encode_decode_with_loss_begin_with_systematic() {
    encode_decode_systematic_with_loss(8, 2, 0.1);
}

#[test]
fn combinations_encode_decode_with_loss_begin_with_systematic() {
    for size in 1000..1100 {
        for chunk in 100..130 {
            for loss in vec![0.1, 0.3, 0.5, 0.9] {
                 encode_decode_systematic_with_loss(size, chunk, loss);
            }
        }
    }
}