external_sort 0.1.2

Provides the ability to perform external sorts on structs, which allows for rapid sorting of large data streams.
Documentation
use rand;
use serde::{Deserialize, Serialize};

use std::env;
use std::fs;

use external_sort::{ExternalSorter, ExternallySortable};

#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd, Ord)]
struct Num {
    the_num: u8,
}

impl Num {
    fn new(num: u8) -> Num {
        Num { the_num: num }
    }
}

impl ExternallySortable for Num {
    fn get_size(&self) -> u64 {
        1
    }
}

#[test]
fn sort() {
    let unsorted = vec![
        Num::new(5),
        Num::new(2),
        Num::new(1),
        Num::new(3),
        Num::new(4),
    ];
    let sorted = vec![
        Num::new(1),
        Num::new(2),
        Num::new(3),
        Num::new(4),
        Num::new(5),
    ];
    let iter = ExternalSorter::new(2, None)
        .sort(unsorted.into_iter())
        .unwrap();
    for (idx, i) in iter.enumerate() {
        assert_eq!(i.unwrap().the_num, sorted[idx].the_num);
    }
}

#[test]
fn reverse() {
    let unsorted = vec![
        Num::new(5),
        Num::new(2),
        Num::new(1),
        Num::new(3),
        Num::new(4),
    ];
    let sorted = vec![
        Num::new(5),
        Num::new(4),
        Num::new(3),
        Num::new(2),
        Num::new(1),
    ];
    let iter = ExternalSorter::new(16, None)
        .sort_by(unsorted.into_iter(), |a, b| b.cmp(a))
        .unwrap();
    for (idx, i) in iter.enumerate() {
        assert_eq!(i.unwrap().the_num, sorted[idx].the_num);
    }
}

#[test]
fn zero_buff() {
    let unsorted = vec![
        Num::new(5),
        Num::new(2),
        Num::new(1),
        Num::new(3),
        Num::new(4),
    ];
    let sorted = vec![
        Num::new(1),
        Num::new(2),
        Num::new(3),
        Num::new(4),
        Num::new(5),
    ];
    let iter = ExternalSorter::new(0, None)
        .sort(unsorted.into_iter())
        .unwrap();
    for (idx, i) in iter.enumerate() {
        assert_eq!(i.unwrap().the_num, sorted[idx].the_num);
    }
}

#[test]
fn large_buff() {
    let unsorted = vec![
        Num::new(5),
        Num::new(2),
        Num::new(1),
        Num::new(3),
        Num::new(4),
    ];
    let sorted = vec![
        Num::new(1),
        Num::new(2),
        Num::new(3),
        Num::new(4),
        Num::new(5),
    ];
    let iter = ExternalSorter::new(999999999, None)
        .sort(unsorted.into_iter())
        .unwrap();
    for (idx, i) in iter.enumerate() {
        assert_eq!(i.unwrap().the_num, sorted[idx].the_num);
    }
}

#[test]
fn reuse() {
    let unsorted = vec![
        Num::new(5),
        Num::new(2),
        Num::new(1),
        Num::new(3),
        Num::new(4),
    ];
    let sorted = vec![
        Num::new(1),
        Num::new(2),
        Num::new(3),
        Num::new(4),
        Num::new(5),
    ];
    let iter = ExternalSorter::new(2, None)
        .sort(unsorted.clone().into_iter())
        .unwrap();
    for (idx, i) in iter.enumerate() {
        assert_eq!(i.unwrap().the_num, sorted[idx].the_num);
    }
    let iter2 = ExternalSorter::new(2, None)
        .sort(unsorted.into_iter())
        .unwrap();
    for (idx, i) in iter2.enumerate() {
        assert_eq!(i.unwrap().the_num, sorted[idx].the_num);
    }
}

#[test]
fn large() {
    let mut unsorted = Vec::new();
    for _ in 0..10_000 {
        unsorted.push(Num::new(rand::random()));
    }
    let iter = ExternalSorter::new(100, None)
        .sort(unsorted.into_iter())
        .unwrap();
    let mut last = 0;
    for i in iter {
        let n = i.unwrap().the_num;
        assert!(n >= last);
        last = n;
    }
}

#[test]
fn handle_fail() {
    let mut unsorted = Vec::new();
    for _ in 0..10_000 {
        unsorted.push(Num::new(rand::random()));
    }
    let r = env::temp_dir().join("external_sort_test");
    fs::create_dir_all(r.clone()).unwrap();

    let iter = ExternalSorter::new(100, Some(r.clone()))
        .sort(unsorted.into_iter())
        .unwrap();
    fs::remove_dir_all(r.clone()).unwrap();
    let mut fail = false;
    for i in iter {
        if i.is_err() {
            fail = true;
        }
    }
    assert!(fail);
}