<commit_before>    // module for triangulating a simple polygon using ear clipping

use std::collections::HashSet;
use std::fmt;

#[derive(Debug, PartialEq, Clone, Copy)]
pub struct Point {
    x: f32,
    y: f32
}
impl Point {
    pub fn new(x: f32, y: f32) -> Point {
        Point { x: x, y: y }
    }
}

impl fmt::Display for Point {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({}, {})", self.x, self.y)
    }
}

#[derive(Debug, PartialEq)]
struct Vertex {
    index: usize,
    prev_index: usize,
    next_index: usize,
    is_convex: bool,
    is_ear: bool
}
impl Vertex {
    fn new(index: usize, prev_index: usize, next_index: usize) -> Vertex {
        Vertex { index: index, prev_index: prev_index, next_index: next_index, is_convex: false, is_ear: false }
    }
}

fn compare_to_line(v_test: &Point, v_prev: &Point, v_next: &Point) -> f32 {
    // returns negative if test is left of line, positive if right, 0 if colinear
    (v_test.x - v_prev.x)*(v_next.y - v_prev.y) - (v_test.y - v_prev.y)*(v_next.x - v_prev.x)
}

fn is_convex(v_test: &Point, v_prev: &Point, v_next: &Point) -> bool {
    // point is convex if right of line made by prev->next
    compare_to_line(v_test, v_prev, v_next) > 0.0f32
}

fn is_in_triangle(v_test: &Point, v0: &Point, v1: &Point, v2: &Point) -> bool {
    if compare_to_line(v_test, v0, v1) >= 0.0f32 { return false; }
    if compare_to_line(v_test, v1, v2) >= 0.0f32 { return false; }
    if compare_to_line(v_test, v2, v0) >= 0.0f32 { return false; }
    true
}

// note: this function assumes v_test is convex!
fn is_ear(points: &Vec<Point>, reflex_set: &HashSet<usize>, v_test: &Vertex) -> bool {
    for r in reflex_set {
        if *r == v_test.prev_index || *r == v_test.next_index {
            continue;
        }
        if is_in_triangle(&points[*r],
                          &points[v_test.prev_index],
                          &points[v_test.index],
                          &points[v_test.next_index]) {
            return false;
        }
    }
    true
}

fn make_vertex_vec(n: usize) -> Vec<Vertex> {
    let mut vertices = Vec::with_capacity(n);
    vertices.push(Vertex::new(0, n-1, 1));
    for i in 1..(n-1) {
        vertices.push(Vertex::new(i, i-1, i+1));
    }
    vertices.push(Vertex::new(n-1, n-2, 0));
    vertices
}

#[derive(Debug, Eq, PartialEq)]
enum VertexType {
    Reflex,
    Convex,
    Ear
}

fn classify_vertex(points: &Vec<Point>, v_test: &mut Vertex, reflex_set: &HashSet<usize>) -> VertexType {
    if is_convex(&points[v_test.index], &points[v_test.prev_index], &points[v_test.next_index]) {
        v_test.is_convex = true;
        if is_ear(&points, reflex_set, &v_test) {
            v_test.is_ear = true;
             return VertexType::Ear;
        } else {
            return VertexType::Convex;
        }
    } else {
        return VertexType::Reflex;
    }
}

fn fill_sets(points: &Vec<Point>, vertices: &mut Vec<Vertex>) -> (HashSet<usize>, HashSet<usize>) {
    let mut ear_set = HashSet::new();
    let mut reflex_set = HashSet::new();

    for v in vertices.iter_mut() {
        if classify_vertex(points, v, &reflex_set) == VertexType::Reflex {
            reflex_set.insert(v.index);
        }
    }

    for mut v in vertices.iter_mut() {
        match classify_vertex(points, v, &reflex_set) {
            VertexType::Reflex => (),
            VertexType::Convex => {
                v.is_convex = true;
            }
            VertexType::Ear => {
                v.is_convex = true;
                v.is_ear = true;
                ear_set.insert(v.index);
            }
        }
    }
    (ear_set, reflex_set)
}

fn remove_vertex(vertices: &mut Vec<Vertex>, i_test: usize) {

    let prev_index = vertices[i_test].prev_index;
    let next_index = vertices[i_test].next_index;
    vertices[prev_index].next_index = next_index;
    vertices[next_index].prev_index = prev_index;
}

fn push_triangle(triangles: &mut Vec<usize>, i_test: usize, i_prev: usize, i_next: usize) {
    triangles.push(i_prev);
    triangles.push(i_test);
    triangles.push(i_next);
}

pub fn triangulate(points: &Vec<Point>) -> Result<Vec<usize>, &'static str> {
    let mut n = points.len();
    if n < 4 {
        if n == 3 {
            return Ok(vec![0, 1, 2]);
        }  else {
            return Err("Not enough vertices to triangulate");
        }
    }

    let mut vertices = make_vertex_vec(n);
    let (mut ear_set, mut reflex_set) = fill_sets(points, &mut vertices);

    let mut triangles = Vec::with_capacity(3 * (n - 2));

    loop {
        let ear_index = match ear_set.iter().next() {
            Some(i) => *i,
            None => return Err("Expected an ear in the ear set but found None")
        };

        ear_set.remove(&ear_index);
        let prev_index;
        let next_index;
        {
            let vertex = &vertices[ear_index];
            prev_index = vertex.prev_index;
            next_index = vertex.next_index;
        }
        push_triangle(&mut triangles, ear_index, prev_index, next_index);
        remove_vertex(&mut vertices, ear_index);
        n -= 1;

        if n == 3 {
            let ear_index = match ear_set.iter().next() {
                Some(i) => *i,
                None => return Err("Expected an ear in the ear set but found None")
            };
            let prev_index;
            let next_index;
            {
                let vertex = &vertices[ear_index];
                prev_index = vertex.prev_index;
                next_index = vertex.next_index;
            }
            push_triangle(&mut triangles, ear_index, prev_index, next_index);
            return Ok(triangles);
        }

        {
            let ref mut v_prev = vertices[prev_index];
            if v_prev.is_ear {
                if !is_ear(&points, &reflex_set, v_prev) {
                    v_prev.is_ear = false;
                    ear_set.remove(&prev_index);
                }
            } else {
                if is_convex(&points[prev_index], &points[v_prev.prev_index], &points[v_prev.next_index]) {
                    if !v_prev.is_convex {
                        v_prev.is_convex = true;
                        reflex_set.remove(&prev_index);
                    }
                    if is_ear(points, &reflex_set, v_prev) {
                        ear_set.insert(prev_index);
                    }
                }
            }
        }

        {
            let ref mut v_next = vertices[next_index];
            if v_next.is_ear {
                if !is_ear(&points, &reflex_set, v_next) {
                    v_next.is_ear = false;
                    ear_set.remove(&next_index);
                }
            } else {
                if is_convex(&points[next_index], &points[v_next.prev_index], &points[v_next.next_index]) {
                    if !v_next.is_convex {
                        v_next.is_convex = true;
                        reflex_set.remove(&next_index);
                    }
                    if is_ear(&points, &reflex_set, v_next) {
                        ear_set.insert(next_index);
                    }
                }
            }
        }
    }
}
#[cfg(test)]
mod tests {
    use super::Point;
    use super::compare_to_line;
    use super::is_convex;
    use super::is_in_triangle;
    use super::triangulate;

    #[test]
    fn test_compare_to_line() {
        let test = Point::new(0.2f32, 1.2f32);
        let v0 = Point::new(0.1f32,  0.1f32);
        let v1 = Point::new(0.5f32, 0.5f32);

        assert!(compare_to_line(&test, &v0, &v1) < 0.0f32);

        let test = Point::new(0.2f32, -1.0f32);

        assert!(compare_to_line(&test, &v0, &v1) > 0.0f32);

        let test = Point::new(v0.x + (v1.x - v0.x) * 0.2f32, v0.y + (v1.y - v0.y) * 0.2f32);

        assert_eq!(compare_to_line(&test, &v0, &v1), 0.0f32);
    }

    #[test]
    fn test_is_convex() {
        let test = Point::new(0.2f32, 1.2f32);
        let v0 = Point::new(0.1f32, 0.1f32);
        let v1 = Point::new(0.5f32, 0.5f32);

        assert_eq!(is_convex(&test, &v0, &v1), false);

        let test = Point::new(0.2f32, -1.0f32);

        assert!(is_convex(&test, &v0, &v1));

        let test = Point::new(v0.x + (v1.x - v0.x) * 0.2f32, v0.y + (v1.y - v0.y) * 0.2f32);

        assert_eq!(is_convex(&test, &v0, &v1), false);
    }

    #[test]
    fn test_is_in_triangle() {
        let v0 = Point::new(0.1f32, 0.1f32);
        let v1 = Point::new(0.7f32, -0.2f32);
        let v2 = Point::new(0.5f32, 0.5f32);

        let test = Point::new(0.2f32, 1.2f32);
        assert_eq!(is_in_triangle(&test, &v0, &v1, &v2), false);

        let test = Point::new(0.4f32, 0.2f32);
        assert!(is_in_triangle(&test, &v0, &v1, &v2));

        let test = Point::new(v2.x + (v0.x - v2.x) * 0.25f32, v2.y + (v0.y - v2.y) * 0.25f32);
        assert_eq!(is_in_triangle(&test, &v0, &v1, &v2), false);
    }

    fn is_expected_triangle(v0: &usize, v1: &usize, v2: &usize, expected: &(usize, usize, usize)) -> bool {
        if *v0 == expected.0 && *v1 == expected.1 && *v2 == expected.2 {
            println!("{}, {}, {} is expected triangle", *v0, *v1, *v2);
            return true;
        }
        if *v1 == expected.0 && *v2 == expected.1 && *v0 == expected.2 {
            println!("{}, {}, {} is expected triangle", *v0, *v1, *v2);
            return true;
        }
        if *v2 == expected.0 && *v0 == expected.1 && *v1 == expected.2 {
            println!("{}, {}, {} is expected triangle", *v0, *v1, *v2);
            return true;
        }
        println!("{}, {}, {}, did not match {}, {}, {}", *v0, *v1, *v2, expected.0, expected.1, expected.2);
        false
    }

    fn is_same_triangulation(triangles: &Vec<usize>, mut expected: Vec<(usize, usize, usize)>) -> bool {
        let n = triangles.len() / 3;
        for i in 0..n {
            let mut matched = false;
            let mut match_index = 0;
            for (index, ex) in expected.iter().enumerate() {
                if is_expected_triangle(&triangles[i*3], &triangles[i*3+1], &triangles[i*3+2], ex) {
                    matched = true;
                    match_index = index;
                    break;
                }
            }
            if matched {
                expected.remove(match_index);
            } else {
                return false;
            }
        }
        true
    }

    #[test]
    fn test_triangulate_square() {
        let points = vec![ Point::new(0.0f32, 0.0f32),
                           Point::new(1.0f32, 0.0f32),
                           Point::new(1.0f32, 1.0f32),
                           Point::new(0.0f32, 1.0f32) ];

        let triangles = triangulate(&points).unwrap();

        for i in 0..(triangles.len() / 3) {
            println!("{}, {}, {}", triangles[i*3], triangles[i*3+1], triangles[i*3+2]);
        }

        // there are two valid triangulations of a square, up-right diagonal
        // and down-right diagonal, so we try both
        assert!(is_same_triangulation(&triangles, vec![(0, 1, 2), (0, 2, 3)]) ||
                is_same_triangulation(&triangles, vec![(0, 1, 3), (3, 1, 2)]));
    }

    #[test]
    fn test_triangulate_reflex() {
        let points = vec![ Point::new(0.0f32, 0.0f32),
                            Point::new(5.0f32, 0.0f32),
                            Point::new(2.0f32, 2.0f32),
                            Point::new(5.0f32, 4.0f32),
                            Point::new(0.0f32, 4.0f32) ];

        let triangles = triangulate(&points).unwrap();

        for i in 0..(triangles.len() / 3) {
            println!("{}, {}, {}", triangles[i*3], triangles[i*3+1], triangles[i*3+2]);
        }

        assert!(is_same_triangulation(&triangles, vec![(0, 1, 2), (0, 2, 4), (4, 2, 3)]));
    }
}<commit_msg>looks like it works now!<commit_after>    // module for triangulating a simple polygon using ear clipping

use std::collections::HashSet;
use std::fmt;

#[derive(Debug, PartialEq, Clone, Copy)]
pub struct Point {
    x: f32,
    y: f32
}
impl Point {
    pub fn new(x: f32, y: f32) -> Point {
        Point { x: x, y: y }
    }
}

impl fmt::Display for Point {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({}, {})", self.x, self.y)
    }
}

#[derive(Debug, PartialEq)]
struct Vertex {
    index: usize,
    prev_index: usize,
    next_index: usize,
    is_convex: bool,
    is_ear: bool
}
impl Vertex {
    fn new(index: usize, prev_index: usize, next_index: usize) -> Vertex {
        Vertex { index: index, prev_index: prev_index, next_index: next_index, is_convex: false, is_ear: false }
    }
}

fn compare_to_line(v_test: &Point, v_prev: &Point, v_next: &Point) -> f32 {
    // returns negative if test is left of line, positive if right, 0 if colinear
    (v_test.x - v_prev.x)*(v_next.y - v_prev.y) - (v_test.y - v_prev.y)*(v_next.x - v_prev.x)
}

fn is_convex(v_test: &Point, v_prev: &Point, v_next: &Point) -> bool {
    // point is convex if right of line made by prev->next
    compare_to_line(v_test, v_prev, v_next) > 0.0f32
}

fn is_in_triangle(v_test: &Point, v0: &Point, v1: &Point, v2: &Point) -> bool {
    if compare_to_line(v_test, v0, v1) >= 0.0f32 { return false; }
    if compare_to_line(v_test, v1, v2) >= 0.0f32 { return false; }
    if compare_to_line(v_test, v2, v0) >= 0.0f32 { return false; }
    true
}

// note: this function assumes v_test is convex!
fn is_ear(points: &Vec<Point>, reflex_set: &HashSet<usize>, v_test: &Vertex) -> bool {
    println!("is_ear({}), prev={}, next={}", v_test.index, v_test.prev_index, v_test.next_index);
    for r in reflex_set {
        if *r == v_test.prev_index || *r == v_test.next_index {
            println!("{} is adjacent, doesn't count", r);
            continue;
        }
        if is_in_triangle(&points[*r],
                          &points[v_test.prev_index],
                          &points[v_test.index],
                          &points[v_test.next_index]) {
            println!("{} is in triangle {},{},{}, not an ear", r, v_test.prev_index, v_test.index, v_test.next_index);
            return false;
        }
    }
    println!("{},{},{}, is an ear", v_test.prev_index, v_test.index, v_test.next_index);
    true
}

fn make_vertex_vec(n: usize) -> Vec<Vertex> {
    let mut vertices = Vec::with_capacity(n);
    vertices.push(Vertex::new(0, n-1, 1));
    for i in 1..(n-1) {
        vertices.push(Vertex::new(i, i-1, i+1));
    }
    vertices.push(Vertex::new(n-1, n-2, 0));
    vertices
}

#[derive(Debug, Eq, PartialEq)]
enum VertexType {
    Reflex,
    Convex,
    Ear
}

fn classify_vertex(points: &Vec<Point>, v_test: &mut Vertex, reflex_set: &HashSet<usize>) -> VertexType {
    if is_convex(&points[v_test.index], &points[v_test.prev_index], &points[v_test.next_index]) {
        if is_ear(&points, reflex_set, &v_test) {
             return VertexType::Ear;
        } else {
            return VertexType::Convex;
        }
    } else {
        return VertexType::Reflex;
    }
}

fn fill_sets(points: &Vec<Point>, vertices: &mut Vec<Vertex>) -> (HashSet<usize>, HashSet<usize>) {
    let mut ear_set = HashSet::new();
    let mut reflex_set = HashSet::new();

    for v in vertices.iter_mut() {
        if classify_vertex(points, v, &reflex_set) == VertexType::Reflex {
            reflex_set.insert(v.index);
        }
    }

    for mut v in vertices.iter_mut() {
        match classify_vertex(points, v, &reflex_set) {
            VertexType::Reflex => (),
            VertexType::Convex => {
                v.is_convex = true;
            }
            VertexType::Ear => {
                v.is_convex = true;
                v.is_ear = true;
                ear_set.insert(v.index);
            }
        }
    }

    (ear_set, reflex_set)
}

fn remove_vertex(vertices: &mut Vec<Vertex>, i_test: usize) {

    let prev_index = vertices[i_test].prev_index;
    let next_index = vertices[i_test].next_index;
    vertices[prev_index].next_index = next_index;
    vertices[next_index].prev_index = prev_index;
}

fn push_triangle(triangles: &mut Vec<usize>, i_test: usize, i_prev: usize, i_next: usize) {
    triangles.push(i_prev);
    triangles.push(i_test);
    triangles.push(i_next);
}

pub fn triangulate(points: &Vec<Point>) -> Result<Vec<usize>, &'static str> {
    let mut n = points.len();
    if n < 4 {
        if n == 3 {
            return Ok(vec![0, 1, 2]);
        }  else {
            return Err("Not enough vertices to triangulate");
        }
    }

    let mut vertices = make_vertex_vec(n);
    let (mut ear_set, mut reflex_set) = fill_sets(points, &mut vertices);

    let mut triangles = Vec::with_capacity(3 * (n - 2));

    loop {
        let ear_index = match ear_set.iter().next() {
            Some(i) => *i,
            None => return Err("Expected an ear in the ear set but found None")
        };

        ear_set.remove(&ear_index);

        let prev_index;
        let next_index;
        {
            let vertex = &vertices[ear_index];
            prev_index = vertex.prev_index;
            next_index = vertex.next_index;
        }
        push_triangle(&mut triangles, ear_index, prev_index, next_index);
        remove_vertex(&mut vertices, ear_index);
        n -= 1;

        if n == 3 {
            let ear_index = match ear_set.iter().next() {
                Some(i) => *i,
                None => return Err("Expected an ear in the ear set but found None")
            };
            let prev_index;
            let next_index;
            {
                let vertex = &vertices[ear_index];
                prev_index = vertex.prev_index;
                next_index = vertex.next_index;
            }
            push_triangle(&mut triangles, ear_index, prev_index, next_index);
            return Ok(triangles);
        }

        {
            let ref mut v_prev = vertices[prev_index];
            if v_prev.is_ear {
                if !is_ear(&points, &reflex_set, v_prev) {
                    v_prev.is_ear = false;
                    ear_set.remove(&prev_index);
                }
            } else {
                if is_convex(&points[prev_index], &points[v_prev.prev_index], &points[v_prev.next_index]) {
                    if !v_prev.is_convex {
                        v_prev.is_convex = true;
                        reflex_set.remove(&prev_index);
                    }

                    if is_ear(&points, &reflex_set, v_prev) {
                        ear_set.insert(prev_index);
                    }
                }
            }
        }

        {
            let ref mut v_next = vertices[next_index];
            if v_next.is_ear {
                if !is_ear(&points, &reflex_set, v_next) {
                    v_next.is_ear = false;
                    ear_set.remove(&next_index);
                }
            } else {
                if is_convex(&points[next_index], &points[v_next.prev_index], &points[v_next.next_index]) {
                    if !v_next.is_convex {
                        v_next.is_convex = true;
                        reflex_set.remove(&next_index);
                    }

                    if is_ear(&points, &reflex_set, v_next) {
                        ear_set.insert(next_index);
                    }
                }
            }
        }
    }
}
#[cfg(test)]
mod tests {
    use super::Point;
    use super::compare_to_line;
    use super::is_convex;
    use super::is_in_triangle;
    use super::triangulate;

    #[test]
    fn test_compare_to_line() {
        let test = Point::new(0.2f32, 1.2f32);
        let v0 = Point::new(0.1f32,  0.1f32);
        let v1 = Point::new(0.5f32, 0.5f32);

        assert!(compare_to_line(&test, &v0, &v1) < 0.0f32);

        let test = Point::new(0.2f32, -1.0f32);

        assert!(compare_to_line(&test, &v0, &v1) > 0.0f32);

        let test = Point::new(v0.x + (v1.x - v0.x) * 0.2f32, v0.y + (v1.y - v0.y) * 0.2f32);

        assert_eq!(compare_to_line(&test, &v0, &v1), 0.0f32);
    }

    #[test]
    fn test_is_convex() {
        let test = Point::new(0.2f32, 1.2f32);
        let v0 = Point::new(0.1f32, 0.1f32);
        let v1 = Point::new(0.5f32, 0.5f32);

        assert_eq!(is_convex(&test, &v0, &v1), false);

        let test = Point::new(0.2f32, -1.0f32);

        assert!(is_convex(&test, &v0, &v1));

        let test = Point::new(v0.x + (v1.x - v0.x) * 0.2f32, v0.y + (v1.y - v0.y) * 0.2f32);

        assert_eq!(is_convex(&test, &v0, &v1), false);
    }

    #[test]
    fn test_is_in_triangle() {
        let v0 = Point::new(0.1f32, 0.1f32);
        let v1 = Point::new(0.7f32, -0.2f32);
        let v2 = Point::new(0.5f32, 0.5f32);

        let test = Point::new(0.2f32, 1.2f32);
        assert_eq!(is_in_triangle(&test, &v0, &v1, &v2), false);

        let test = Point::new(0.4f32, 0.2f32);
        assert!(is_in_triangle(&test, &v0, &v1, &v2));

        let test = Point::new(v2.x + (v0.x - v2.x) * 0.25f32, v2.y + (v0.y - v2.y) * 0.25f32);
        assert_eq!(is_in_triangle(&test, &v0, &v1, &v2), false);
    }

    fn is_expected_triangle(v0: &usize, v1: &usize, v2: &usize, expected: &(usize, usize, usize)) -> bool {
        if *v0 == expected.0 && *v1 == expected.1 && *v2 == expected.2 {
            println!("{}, {}, {} is expected triangle", *v0, *v1, *v2);
            return true;
        }
        if *v1 == expected.0 && *v2 == expected.1 && *v0 == expected.2 {
            println!("{}, {}, {} is expected triangle", *v0, *v1, *v2);
            return true;
        }
        if *v2 == expected.0 && *v0 == expected.1 && *v1 == expected.2 {
            println!("{}, {}, {} is expected triangle", *v0, *v1, *v2);
            return true;
        }
        println!("{}, {}, {}, did not match {}, {}, {}", *v0, *v1, *v2, expected.0, expected.1, expected.2);
        false
    }

    fn is_same_triangulation(triangles: &Vec<usize>, mut expected: Vec<(usize, usize, usize)>) -> bool {
        let n = triangles.len() / 3;
        for i in 0..n {
            let mut matched = false;
            let mut match_index = 0;
            for (index, ex) in expected.iter().enumerate() {
                if is_expected_triangle(&triangles[i*3], &triangles[i*3+1], &triangles[i*3+2], ex) {
                    matched = true;
                    match_index = index;
                    break;
                }
            }
            if matched {
                expected.remove(match_index);
            } else {
                return false;
            }
        }
        true
    }

    #[test]
    fn test_triangulate_square() {
        let points = vec![ Point::new(0.0f32, 0.0f32),
                           Point::new(1.0f32, 0.0f32),
                           Point::new(1.0f32, 1.0f32),
                           Point::new(0.0f32, 1.0f32) ];

        let triangles = triangulate(&points).unwrap();

        for i in 0..(triangles.len() / 3) {
            println!("{}, {}, {}", triangles[i*3], triangles[i*3+1], triangles[i*3+2]);
        }

        // there are two valid triangulations of a square, up-right diagonal
        // and down-right diagonal, so we try both
        assert!(is_same_triangulation(&triangles, vec![(0, 1, 2), (0, 2, 3)]) ||
                is_same_triangulation(&triangles, vec![(0, 1, 3), (3, 1, 2)]));
    }

    #[test]
    fn test_triangulate_reflex() {
        let points = vec![ Point::new(0.0f32, 0.0f32),
                            Point::new(5.0f32, 0.0f32),
                            Point::new(2.0f32, 2.0f32),
                            Point::new(5.0f32, 4.0f32),
                            Point::new(0.0f32, 4.0f32) ];

        let triangles = triangulate(&points).unwrap();

        for i in 0..(triangles.len() / 3) {
            println!("{}, {}, {}", triangles[i*3], triangles[i*3+1], triangles[i*3+2]);
        }

        assert!(is_same_triangulation(&triangles, vec![(0, 1, 2), (0, 2, 4), (4, 2, 3)]));
    }
}<|endoftext|>


<commit_before>#![macro_use]

#[macro_use]
extern crate log;
extern crate libc;

mod util;

mod blocksplitter;
#[cfg(feature = "longest-match-cache")]
mod cache;
mod deflate;
mod gzip_container;
mod hash;
mod katajainen;
mod lz77;
mod tree;
mod zlib_container;

/// Options used throughout the program.
pub struct Options {
    /// Whether to print output
    pub verbose: bool,
    /// Whether to print more detailed output
    pub verbose_more: bool,
    /// Maximum amount of times to rerun forward and backward pass to optimize LZ77
    /// compression cost. Good values: 10, 15 for small files, 5 for files over
    /// several MB in size or it will be too slow.
    pub numiterations: i32,
    /// If true, splits the data in multiple deflate blocks with optimal choice
    /// for the block boundaries. Block splitting gives better compression. Default:
    /// true (1).
    pub blocksplitting: bool,
    /// If true, chooses the optimal block split points only after doing the iterative
    /// LZ77 compression. If false, chooses the block split points first, then does
    /// iterative LZ77 on each individual block. Depending on the file, either first
    /// or last gives the best compression. Default: false (0).
    pub blocksplittinglast: bool,
    /// Maximum amount of blocks to split into (0 for unlimited, but this can give
    /// extreme results that hurt compression on some files). Default value: 15.
    pub blocksplittingmax: i32,
}

impl Options {
    pub fn new() -> Options {
        Options {
            verbose: false,
            verbose_more: false,
            numiterations: 15,
            blocksplitting: true,
            blocksplittinglast: false,
            blocksplittingmax: 15,
        }
    }
}

/// Output format
#[derive(Clone, Copy)]
pub enum Format {
    GZIP,
    ZLIB,
    DEFLATE,
}

/**
 * Compresses according to the given output format and appends the result to the
 * output.
 *
 * options: global program options
 * output_type: the output format to use
 * out: pointer to the dynamic output array to which the result is appended. Must
 *   be freed after use
 * outsize: pointer to the dynamic output array size
 */
pub unsafe fn compress(options: *const Options, output_type: Format, input: *const u8, insize: usize, out: *mut *mut u8, outsize: *mut usize) {
    match output_type {
        Format::GZIP    => gzip_container::compress(options, input, insize, out, outsize),
        Format::ZLIB    => zlib_container::compress(options, input, insize, out, outsize),
        Format::DEFLATE => {
            let mut bp: u8 = 0;
            deflate::deflate(options, 2 /* Dynamic block */, true, input, insize, &mut bp, out, outsize)
        },
    }
}

pub fn decompress(bytes: &[u8]) -> &[u8] {
    bytes
}

#[cfg(test)]
mod test {
    extern crate compress;
    extern crate flate2;

    use libc::{c_void, size_t};
    use libc::funcs::c95::string::memcmp;
    use std::ptr::{null, null_mut};

    use super::*;

    unsafe fn roundtrip(format: Format, bytes: &[u8]) {
        let mut options = Options::new();
        let mut compressed: *mut u8 = null_mut();
        let mut compressed_size: usize = 0;
        compress(&options, format, bytes.as_ptr(), bytes.len(), &mut compressed, &mut compressed_size);
        let decompressed = compressed; // decompress(compressed);
        assert!(memcmp(bytes.as_ptr() as *const c_void, decompressed as *const c_void, bytes.len() as size_t) == 0);
    }

    #[test]
    fn test1() {
        unsafe {
            roundtrip(Format::GZIP, b"");
            roundtrip(Format::GZIP, b"1");
            roundtrip(Format::GZIP, b"foobar");

            roundtrip(Format::ZLIB, b"");
            roundtrip(Format::ZLIB, b"1");
            roundtrip(Format::ZLIB, b"foobar");

            roundtrip(Format::DEFLATE, b"");
            roundtrip(Format::DEFLATE, b"1");
            roundtrip(Format::DEFLATE, b"foobar");
        }
    }
}
<commit_msg>Allow unused stuff for now<commit_after>#![macro_use]
#![allow(unused)]

#[macro_use]
extern crate log;
extern crate libc;

mod util;

mod blocksplitter;
#[cfg(feature = "longest-match-cache")]
mod cache;
mod deflate;
mod gzip_container;
mod hash;
mod katajainen;
mod lz77;
mod tree;
mod zlib_container;

/// Options used throughout the program.
pub struct Options {
    /// Whether to print output
    pub verbose: bool,
    /// Whether to print more detailed output
    pub verbose_more: bool,
    /// Maximum amount of times to rerun forward and backward pass to optimize LZ77
    /// compression cost. Good values: 10, 15 for small files, 5 for files over
    /// several MB in size or it will be too slow.
    pub numiterations: i32,
    /// If true, splits the data in multiple deflate blocks with optimal choice
    /// for the block boundaries. Block splitting gives better compression. Default:
    /// true (1).
    pub blocksplitting: bool,
    /// If true, chooses the optimal block split points only after doing the iterative
    /// LZ77 compression. If false, chooses the block split points first, then does
    /// iterative LZ77 on each individual block. Depending on the file, either first
    /// or last gives the best compression. Default: false (0).
    pub blocksplittinglast: bool,
    /// Maximum amount of blocks to split into (0 for unlimited, but this can give
    /// extreme results that hurt compression on some files). Default value: 15.
    pub blocksplittingmax: i32,
}

impl Options {
    pub fn new() -> Options {
        Options {
            verbose: false,
            verbose_more: false,
            numiterations: 15,
            blocksplitting: true,
            blocksplittinglast: false,
            blocksplittingmax: 15,
        }
    }
}

/// Output format
#[derive(Clone, Copy)]
pub enum Format {
    GZIP,
    ZLIB,
    DEFLATE,
}

/**
 * Compresses according to the given output format and appends the result to the
 * output.
 *
 * options: global program options
 * output_type: the output format to use
 * out: pointer to the dynamic output array to which the result is appended. Must
 *   be freed after use
 * outsize: pointer to the dynamic output array size
 */
pub unsafe fn compress(options: *const Options, output_type: Format, input: *const u8, insize: usize, out: *mut *mut u8, outsize: *mut usize) {
    match output_type {
        Format::GZIP    => gzip_container::compress(options, input, insize, out, outsize),
        Format::ZLIB    => zlib_container::compress(options, input, insize, out, outsize),
        Format::DEFLATE => {
            let mut bp: u8 = 0;
            deflate::deflate(options, 2 /* Dynamic block */, true, input, insize, &mut bp, out, outsize)
        },
    }
}

pub fn decompress(bytes: &[u8]) -> &[u8] {
    bytes
}

#[cfg(test)]
mod test {
    extern crate compress;
    extern crate flate2;

    use libc::{c_void, size_t};
    use libc::funcs::c95::string::memcmp;
    use std::ptr::{null, null_mut};

    use super::*;

    unsafe fn roundtrip(format: Format, bytes: &[u8]) {
        let mut options = Options::new();
        let mut compressed: *mut u8 = null_mut();
        let mut compressed_size: usize = 0;
        compress(&options, format, bytes.as_ptr(), bytes.len(), &mut compressed, &mut compressed_size);
        let decompressed = compressed; // decompress(compressed);
        assert!(memcmp(bytes.as_ptr() as *const c_void, decompressed as *const c_void, bytes.len() as size_t) == 0);
    }

    #[test]
    fn test1() {
        unsafe {
            roundtrip(Format::GZIP, b"");
            roundtrip(Format::GZIP, b"1");
            roundtrip(Format::GZIP, b"foobar");

            roundtrip(Format::ZLIB, b"");
            roundtrip(Format::ZLIB, b"1");
            roundtrip(Format::ZLIB, b"foobar");

            roundtrip(Format::DEFLATE, b"");
            roundtrip(Format::DEFLATE, b"1");
            roundtrip(Format::DEFLATE, b"foobar");
        }
    }
}
<|endoftext|>


<commit_before>extern crate walkdir;

use std::path::PathBuf;
use walkdir::WalkDir;

#[derive(Debug)]
struct Repository {
  root: String,
  path: String,
}

fn get_local_repositories(filter: Box<Fn(&str) -> bool>, unique: bool) -> Vec<Repository> {
  let mut dst = Vec::new();

  let roots = get_local_repos_roots();
  for root in roots {
    for entry in WalkDir::new(&root).follow_links(true).into_iter().flat_map(|e| e.ok()) {
      if entry.depth() == 3 {
        let buf = PathBuf::from(format!("{}", entry.path().display()));
        let entry = vec![".git", ".svn", ".hg", "_darcs"].into_iter().find(|&e| {
          if !filter(format!("{}", buf.display()).as_str()) {
            return false;
          }
          let mut buf = buf.clone();
          buf.push(e);
          buf.exists()
        });
        if entry.is_some() {
          dst.push(Repository {
            root: root.clone(),
            path: format!("{}", buf.display()).replace(&format!("{}/", root), ""),
          });
        }
      }
    }
  }

  dst
}

pub fn command_list(exact: bool, fullpath: bool, unique: bool, query: Option<String>) -> i32 {
  let filter: Box<Fn(&str) -> bool> = {
    if let Some(query) = query {
      if exact {
        Box::new(move |s: &str| s == query)
      } else {
        Box::new(move |s: &str| s.contains(&query))
      }
    } else {
      Box::new(|_| true)
    }
  };

  let repos = get_local_repositories(filter, unique);
  for repo in repos {
    if fullpath {
      let mut repo_path = std::path::PathBuf::from(repo.root);
      repo_path.push(repo.path);
      println!("{}", repo_path.display());
    } else {
      println!("{}", repo.path);
    }
  }

  0
}

fn git_config(key: &str) -> String {
  let output = std::process::Command::new("git")
    .args(&["config", "--path", "--null", "--get-all", key])
    .output()
    .expect("failed to execute git");
  let len = output.stdout.len();
  String::from_utf8(Vec::from(&output.stdout[0..len - 1])).unwrap()
}

fn get_local_repos_roots() -> Vec<String> {
  let mut local_repo_roots;

  let env_root: String = std::env::var("GHQ_ROOT").unwrap_or("".to_owned());
  if env_root == "" {
    local_repo_roots = vec![git_config("ghq.root")];
  } else {
    local_repo_roots = env_root.split(":").map(|s| s.to_owned()).collect();
  }

  if local_repo_roots.len() == 0 {
    let mut ghq_path = std::env::home_dir().unwrap();
    ghq_path.push(".ghq");
    local_repo_roots.push(format!("{}", ghq_path.display()));
  }

  assert!(local_repo_roots.len() >= 1);

  local_repo_roots
}

pub fn command_root(all: bool) -> i32 {
  let roots = get_local_repos_roots();
  if all {
    for root in roots {
      println!("{}", root);
    }
  } else {
    println!("{}", roots[0]);
  }
  0
}
<commit_msg>WIP: implement<commit_after>extern crate walkdir;

use std::path::PathBuf;
use walkdir::WalkDir;

#[derive(Debug)]
struct Repository {
  root: String,
  path: String,
}

fn get_local_repositories(filter: Box<Fn(&str) -> bool>, unique: bool) -> Vec<Repository> {
  let mut dst = Vec::new();

  let roots = get_local_repos_roots();
  for root in roots {
    for entry in WalkDir::new(&root).follow_links(true).into_iter().filter_map(|e| e.ok()) {
      let path = format!("{}", entry.path().display()).replace(&format!("{}/", root), "");
      if entry.depth() == 3 {

        let entry = vec![".git", ".svn", ".hg", "_darcs"].into_iter().find(|&e| {
          let mut buf = PathBuf::from(format!("{}", entry.path().display()));
          if !filter(buf.file_name().unwrap().to_str().unwrap()) {
            return false;
          }
          buf.push(e);
          buf.exists()
        });

        if entry.is_some() {
          dst.push(Repository {
            root: root.clone(),
            path: path,
          });
        }
      }
    }
  }

  dst
}

pub fn command_list(exact: bool, fullpath: bool, unique: bool, query: Option<String>) -> i32 {
  let filter: Box<Fn(&str) -> bool> = {
    if let Some(query) = query {
      if exact {
        Box::new(move |s: &str| s == query)
      } else {
        Box::new(move |s: &str| s.contains(&query))
      }
    } else {
      Box::new(|_| true)
    }
  };

  let repos = get_local_repositories(filter, unique);
  for repo in repos {
    if fullpath {
      let mut repo_path = std::path::PathBuf::from(repo.root);
      repo_path.push(repo.path);
      println!("{}", repo_path.display());
    } else {
      println!("{}", repo.path);
    }
  }

  0
}

fn git_config(key: &str) -> String {
  let output = std::process::Command::new("git")
    .args(&["config", "--path", "--null", "--get-all", key])
    .output()
    .expect("failed to execute git");
  let len = output.stdout.len();
  String::from_utf8(Vec::from(&output.stdout[0..len - 1])).unwrap()
}

fn get_local_repos_roots() -> Vec<String> {
  let mut local_repo_roots;

  let env_root: String = std::env::var("GHQ_ROOT").unwrap_or("".to_owned());
  if env_root == "" {
    local_repo_roots = vec![git_config("ghq.root")];
  } else {
    local_repo_roots = env_root.split(":").map(|s| s.to_owned()).collect();
  }

  if local_repo_roots.len() == 0 {
    let mut ghq_path = std::env::home_dir().unwrap();
    ghq_path.push(".ghq");
    local_repo_roots.push(format!("{}", ghq_path.display()));
  }

  assert!(local_repo_roots.len() >= 1);

  local_repo_roots
}

pub fn command_root(all: bool) -> i32 {
  let roots = get_local_repos_roots();
  if all {
    for root in roots {
      println!("{}", root);
    }
  } else {
    println!("{}", roots[0]);
  }
  0
}
<|endoftext|>


<commit_before>use std::{io, result, collections};
use message::{WriteMessage,
              ReadMessage,
              Startup,
              Request,
              Response,
              Query
              };
use std::io::{IoResult};

pub mod message;

fn startup_request() -> Request {
  let mut body = collections::HashMap::new();
  body.insert("CQL_VERSION".to_string(), "3.0.0".to_string());

  Startup(body)
}

pub struct Client {
  buf: io::BufferedStream<io::TcpStream>
}

impl Client {
  pub fn query(&mut self, query: String, consistency: message::Consistency) -> IoResult<Response> {
    let query = Query(query, consistency);
    try!(self.buf.write_message(&query));
    try!(self.buf.flush());

    Ok(try!(self.buf.read_message()))
  }
}

pub fn connect(ip: String, port: u16) -> io::IoResult<Client> {

  let stream = try!(io::TcpStream::connect(ip.as_slice(), port));

  let startup_msg = startup_request();
  let mut buf = io::BufferedStream::new(stream);
  try!(buf.write_message(&startup_msg));
  try!(buf.flush());

  let msg = buf.read_message().unwrap();
  match msg {
    message::Ready => {
      println!("No auth required by server - moving on");
      let cli = Client { buf: buf };
      result::Ok(cli)
    },
    message::Authenticate(_) => {
      println!("Auth required - sending credentials - maybe");
      let cli = Client { buf: buf };
      result::Ok(cli)
    },
    _ => {
      println!("Bad response - response was {}", msg);
      Err(io::IoError {
        kind: io::ConnectionFailed,
        desc: "Invalid response after startup",
        detail: None
      })
    }
  }
}

#[test]
fn connect_and_query() {
  let mut client = connect("127.0.0.1".to_string(), 9042).unwrap();

  let result = client.query("DROP KEYSPACE IF EXISTS testing".to_string(), message::Quorum);
  println!("Result of DROP KEYSPACE was {}", result);

  let query = "CREATE KEYSPACE testing
               WITH replication = {
                 'class' : 'SimpleStrategy',
                 'replication_factor' : 1
               }".to_string();
  let result = client.query(query, message::Quorum);
  println!("Result of CREATE KEYSPACE was {}", result);

  let result = client.query("USE testing".to_string(), message::Quorum);
  println!("Result of USE was {}", result);

  let query = "CREATE TABLE users (
    user_id varchar PRIMARY KEY,
    first varchar,
    last varchar,
    age int,
    height float
    )".to_string();

  let result = client.query(query, message::Quorum);
  println!("Result of CREATE TABLE was {}", result);

  let query = "INSERT INTO users (user_id, first, last, age, height)
               VALUES ('jsmith', 'John', 'Smith', 42, 12.1);".to_string();
  let result = client.query(query, message::Quorum);
  println!("Result of INSERT was {}", result);

  let result = client.query("SELECT * FROM users".to_string(), message::Quorum);
  println!("Result of SELECT was {}", result);
}
<commit_msg>Updating to run on 0.13<commit_after>use std::{io, result, collections};
use message::{WriteMessage,
              ReadMessage,
              Startup,
              Request,
              Response,
              Query
              };
use std::io::{IoResult};

pub mod message;

fn startup_request() -> Request {
  let mut body = collections::HashMap::new();
  body.insert("CQL_VERSION".to_string(), "3.0.0".to_string());

  Startup(body)
}

pub struct Client {
  buf: io::BufferedStream<io::TcpStream>
}

impl Client {
  pub fn query(&mut self, query: String, consistency: message::Consistency) -> IoResult<Response> {
    let query = Query(query, consistency);
    try!(self.buf.write_message(&query));
    try!(self.buf.flush());

    Ok(try!(self.buf.read_message()))
  }
}

pub fn connect(addr: String) -> io::IoResult<Client> {

  let stream = try!(io::TcpStream::connect(addr.as_slice()));

  let startup_msg = startup_request();
  let mut buf = io::BufferedStream::new(stream);
  try!(buf.write_message(&startup_msg));
  try!(buf.flush());

  let msg = try!(buf.read_message());
  match msg {
    message::Ready => {
      println!("No auth required by server - moving on");
      let cli = Client { buf: buf };
      result::Ok(cli)
    },
    message::Authenticate(_) => {
      println!("Auth required - sending credentials - maybe");
      let cli = Client { buf: buf };
      result::Ok(cli)
    },
    _ => {
      println!("Bad response - response was {}", msg);
      Err(io::IoError {
        kind: io::ConnectionFailed,
        desc: "Invalid response after startup",
        detail: None
      })
    }
  }
}

#[test]
fn connect_and_query() {
  let mut client = connect("127.0.0.1:9042".to_string()).unwrap();

  let result = client.query("DROP KEYSPACE IF EXISTS testing".to_string(), message::Quorum);
  println!("Result of DROP KEYSPACE was {}", result);

  let query = "CREATE KEYSPACE testing
               WITH replication = {
                 'class' : 'SimpleStrategy',
                 'replication_factor' : 1
               }".to_string();
  let result = client.query(query, message::Quorum);
  println!("Result of CREATE KEYSPACE was {}", result);

  let result = client.query("USE testing".to_string(), message::Quorum);
  println!("Result of USE was {}", result);

  let query = "CREATE TABLE users (
    user_id varchar PRIMARY KEY,
    first varchar,
    last varchar,
    age int,
    height float
    )".to_string();

  let result = client.query(query, message::Quorum);
  println!("Result of CREATE TABLE was {}", result);

  let query = "INSERT INTO users (user_id, first, last, age, height)
               VALUES ('jsmith', 'John', 'Smith', 42, 12.1);".to_string();
  let result = client.query(query, message::Quorum);
  println!("Result of INSERT was {}", result);

  let result = client.query("SELECT * FROM users".to_string(), message::Quorum);
  println!("Result of SELECT was {}", result);
}
<|endoftext|>


<commit_before>//! Demoscene framework.
//!
//! # Foreword
//!
//! This framework is intented to be used to build up [demos](https://en.wikipedia.org/wiki/Demoscene)
//! as a primary purpose. Everything was designed to quickly write demoscene effects and edit them
//! into an audiovisual executable. However, because a lot was added – especially for debugging
//! purposes, it *should* be possible to use this framework for other purposes as well – among
//! *simulations*, *animations* and *video games*.
//!
//! # Design
//!
//! This framework was designed to be *simple* and *flexible*. Following that path, it’s not
//! impossible that some of its features get moved out of the framework to become a set of
//! dependencies – so that people who don’t want those features can just preclude them from the
//! compilation chain.
//!
//! Up to now, the framework provides you with several modules:
//!
//! - **audio**: this module gives you the ability to play a soundtrack (no streaming implemented
//!   yet though; the whole soundtrack is loaded into memory) and interact with basic yet useful
//!   information about playback (play, pause, toggle, track length, track cursor, etc.)
//! - **bootstrapping**: this module abstracts over the underlying technologies and provides several
//!   simple types that can be used to interact with the demo, such as initialization, default
//!   event handling, and so on
//! - **camera**: provides some camera features for both release and debugging purposes
//! - **color**: color types
//! - **edit**: everything you need to edit your demo – it provides types and functions to reason
//!   about timelines, tracks, cuts and clips, hence easing the overall making of a demo
//! - **gui**: this module provides some GUI code that you can use to build nice debugging
//!   interfaces – up to now, it’s not designed for release code, but it might be at some time
//! - **linear**: linear algebra
//! - **model**: this module provides all the code required to abstract other meshes and add them
//!   the concept of *materials*
//! - **object**: linked to **models**, this module adds the concept of *space properties* to
//!   *models* – so that you can actually have them in your scenes
//! - **overlay**: this module provides 2D primitives and rendering functions
//! - **projection**: projection trait and functions
//! - **shader**: provides
//! - **extra**: some extra (but not mandatory) other modules

#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(conservative_impl_trait)]
#![feature(const_fn)]
#![feature(macro_reexport)]
#![feature(slice_patterns)]

extern crate alto;
extern crate any_cache;
extern crate cargo;
extern crate cgmath;
extern crate chrono;
#[macro_reexport(crate_authors, crate_name, crate_version)]
extern crate clap;
extern crate image;
#[macro_reexport(gtup, uniform_interface, uniform_interface_build_struct, uniform_interface,
                 uniform_interface_impl_trait, uniform_interface_impl_trait_map)]
pub extern crate luminance;
extern crate libloading;
extern crate luminance_glfw;
extern crate glsl;
#[macro_use]
extern crate nom;
extern crate num_traits;
//extern crate rusttype; // FIXME: uncomment when we support text render back
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate tempdir;
extern crate vorbis;
extern crate wavefront_obj;
extern crate warmy;

#[macro_use]
pub mod report;
#[macro_use]
pub mod sys;

pub mod audio;
//pub mod gui;
pub mod linear;
//pub mod overlay;
//pub mod text;

pub mod anim;
pub mod render;
pub mod scene;
<commit_msg>Remove conservative_impl_trait as feature gated.<commit_after>//! Demoscene framework.
//!
//! # Foreword
//!
//! This framework is intented to be used to build up [demos](https://en.wikipedia.org/wiki/Demoscene)
//! as a primary purpose. Everything was designed to quickly write demoscene effects and edit them
//! into an audiovisual executable. However, because a lot was added – especially for debugging
//! purposes, it *should* be possible to use this framework for other purposes as well – among
//! *simulations*, *animations* and *video games*.
//!
//! # Design
//!
//! This framework was designed to be *simple* and *flexible*. Following that path, it’s not
//! impossible that some of its features get moved out of the framework to become a set of
//! dependencies – so that people who don’t want those features can just preclude them from the
//! compilation chain.
//!
//! Up to now, the framework provides you with several modules:
//!
//! - **audio**: this module gives you the ability to play a soundtrack (no streaming implemented
//!   yet though; the whole soundtrack is loaded into memory) and interact with basic yet useful
//!   information about playback (play, pause, toggle, track length, track cursor, etc.)
//! - **bootstrapping**: this module abstracts over the underlying technologies and provides several
//!   simple types that can be used to interact with the demo, such as initialization, default
//!   event handling, and so on
//! - **camera**: provides some camera features for both release and debugging purposes
//! - **color**: color types
//! - **edit**: everything you need to edit your demo – it provides types and functions to reason
//!   about timelines, tracks, cuts and clips, hence easing the overall making of a demo
//! - **gui**: this module provides some GUI code that you can use to build nice debugging
//!   interfaces – up to now, it’s not designed for release code, but it might be at some time
//! - **linear**: linear algebra
//! - **model**: this module provides all the code required to abstract other meshes and add them
//!   the concept of *materials*
//! - **object**: linked to **models**, this module adds the concept of *space properties* to
//!   *models* – so that you can actually have them in your scenes
//! - **overlay**: this module provides 2D primitives and rendering functions
//! - **projection**: projection trait and functions
//! - **shader**: provides
//! - **extra**: some extra (but not mandatory) other modules

#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(const_fn)]
#![feature(macro_reexport)]
#![feature(slice_patterns)]

extern crate alto;
extern crate any_cache;
extern crate cargo;
extern crate cgmath;
extern crate chrono;
#[macro_reexport(crate_authors, crate_name, crate_version)]
extern crate clap;
extern crate image;
#[macro_reexport(gtup, uniform_interface, uniform_interface_build_struct, uniform_interface,
                 uniform_interface_impl_trait, uniform_interface_impl_trait_map)]
pub extern crate luminance;
extern crate libloading;
extern crate luminance_glfw;
extern crate glsl;
#[macro_use]
extern crate nom;
extern crate num_traits;
//extern crate rusttype; // FIXME: uncomment when we support text render back
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate tempdir;
extern crate vorbis;
extern crate wavefront_obj;
extern crate warmy;

#[macro_use]
pub mod report;
#[macro_use]
pub mod sys;

pub mod audio;
//pub mod gui;
pub mod linear;
//pub mod overlay;
//pub mod text;

pub mod anim;
pub mod render;
pub mod scene;
<|endoftext|>


<commit_before>//! A generic [Markov chain](https://en.wikipedia.org/wiki/Markov_chain) for almost any type. This
//! uses HashMaps internally, and so Eq and Hash are both required.
//!
//! # Examples
//!
//! ```
//! use markov::Chain;
//!
//! let mut chain = Chain::for_strings();
//! chain.feed_str("I like cats and I like dogs.");
//! println!("{}", chain.generate_str());
//! ```
//!
//! ```
//! use markov::Chain;
//!
//! let mut chain = Chain::new(0u8, 255);
//! chain.feed(vec![1u8, 2, 3, 5]).feed(vec![3u8, 9, 2]);
//! println!("{}", chain.generate());
//! ```
#![experimental]
#![feature(slicing_syntax)]
#![warn(missing_docs)]

use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::hash::Hash;
use std::io::{BufferedReader, File};
use std::rand::{Rng, task_rng};
use std::rc::Rc;

/// A generic [Markov chain](https://en.wikipedia.org/wiki/Markov_chain) for almost any type. This
/// uses HashMaps internally, and so Eq and Hash are both required.
pub struct Chain<T: Eq + Hash> {
    map: HashMap<Rc<T>, HashMap<Rc<T>, uint>>,
    start: Rc<T>,
    end: Rc<T>,
}

impl<T: Eq + Hash> Chain<T> {
    /// Constructs a new Markov chain using the given tokens as the marked starting and ending
    /// points for generation.
    ///
    /// I'm trying to test something: I referrenced it online.
    pub fn new(start: T, end: T) -> Chain<T> {
        let start = Rc::new(start);
        let end = Rc::new(end);
        Chain {
            map: {
                let mut map = HashMap::new();
                map.insert(start.clone(), HashMap::new());
                map
            },
            start: start, end: end
        }
    }

    /// Determines whether or not the chain is empty. A chain is considered empty if nothing has
    /// been fed into it.
    pub fn is_empty(&self) -> bool {
        self.map[self.start.clone()].is_empty()
    }

    /// Feeds the chain a collection of tokens. This operation is O(n) where n is the number of
    /// tokens to be fed into the chain.
    pub fn feed(&mut self, tokens: Vec<T>) -> &mut Chain<T> {
        if tokens.len() == 0 { return self }
        let mut toks = Vec::new();
        toks.push(self.start.clone());
        toks.extend(tokens.into_iter().map(|token| {
            let rc = Rc::new(token);
            if !self.map.contains_key(&rc) {
                self.map.insert(rc.clone(), HashMap::new());
            }
            rc
        }));
        toks.push(self.end.clone());
        for p in toks.windows(2) {
            (&mut self.map[p[0]]).add(p[1].clone());
        }
        self
    }

    /// Generates a collection of tokens from the chain. This operation is O(mn) where m is the
    /// length of the generated collection, and n is the number of possible states from a given
    /// state.
    pub fn generate(&self) -> Vec<Rc<T>> {
        let mut ret = Vec::new();
        let mut curs = self.start.clone();
        while curs != self.end {
            curs = self.map[curs].next();
            ret.push(curs.clone());
        }
        ret.pop();
        ret
    }

    /// Generates a collection of tokens from the chain, starting with the given token. This
    /// operation is O(mn) where m is the length of the generated collection, and n is the number
    /// of possible states from a given state. This returns an empty vector if the token is not
    /// found.
    pub fn generate_from_token(&self, token: T) -> Vec<Rc<T>> {
        let token = Rc::new(token);
        if !self.map.contains_key(&token) { return Vec::new() }
        let mut ret = vec![token.clone()];
        let mut curs = token;
        while curs != self.end {
            curs = self.map[curs].next();
            ret.push(curs.clone());
        }
        ret.pop();
        ret
    }
}

impl Chain<String> {
    /// Creates a new Chain intended specifically for strings. This uses the Unicode start of text
    /// and end of text control characters as the starting and ending tokens for the chain.
    pub fn for_strings() -> Chain<String> {
        Chain::new("\u{0002}".into_string(), "\u{0003}".into_string())
    }

    /// Feeds a string of text into the chain.
    pub fn feed_str(&mut self, string: &str) -> &mut Chain<String> {
        self.feed(string.split_str(" ").map(|s| s.into_string()).collect())
    }

    /// Feeds a properly formatted file into the chain. This file should be formatted such that
    /// each line is a new sentence. Punctuation may be included if it is desired.
    pub fn feed_file(&mut self, path: &Path) -> &mut Chain<String> {
        let mut reader = BufferedReader::new(File::open(path));
        for line in reader.lines() {
            let line = line.unwrap();
            let words: Vec<_> = line.split([' ', '\t', '\n', '\r'][])
                                    .filter(|word| !word.is_empty())
                                    .collect();
            self.feed(words.iter().map(|s| s.into_string()).collect());
        }
        self
    }

    /// Generates a random string of text.
    pub fn generate_str(&self) -> String {
        let vec = self.generate();
        let mut ret = String::new();
        for s in vec.iter() {
            ret.push_str(s[]);
            ret.push_str(" ");
        }
        let len = ret.len();
        ret.truncate(len - 1);
        ret
    }

    /// Generates a random string of text starting with the desired token. This returns an empty
    /// string if the token is not found.
    pub fn generate_str_from_token(&self, string: &str) -> String {
        let vec = self.generate_from_token(string.into_string());
        let mut ret = String::new();
        for s in vec.iter() {
            ret.push_str(s[]);
            ret.push_str(" ");
        }
        let len = ret.len();
        if len > 0 {
            ret.truncate(len - 1);
        }
        ret
    }
}

/// A collection of states for the Markov chain.
trait States<T: PartialEq> {
    /// Adds a state to this states collection.
    fn add(&mut self, token: Rc<T>);
    /// Gets the next state from this collection of states.
    fn next(&self) -> Rc<T>;
}

impl<T: Eq + Hash> States<T> for HashMap<Rc<T>, uint> {
    fn add(&mut self, token: Rc<T>) {
        match self.entry(token) {
            Occupied(mut e) => *e.get_mut() += 1,
            Vacant(e) => { e.set(1); },
        }
    }

    fn next(&self) -> Rc<T> {
        let mut sum = 0;
        for &value in self.values() {
            sum += value;
        }
        let mut rng = task_rng();
        let cap = rng.gen_range(0, sum);
        sum = 0;
        for (key, &value) in self.iter() {
            sum += value;
            if sum > cap {
                return key.clone()
            }
        }
        unreachable!("The random number generator failed.")
    }
}

#[cfg(test)]
mod test {
    use super::Chain;

    #[test]
    fn new() {
        Chain::new(0u, 100u);
        Chain::for_strings();
    }

    #[test]
    fn is_empty() {
        let mut chain = Chain::new(0u, 100u);
        assert!(chain.is_empty());
        chain.feed(vec![1u, 2u, 3u]);
        assert!(!chain.is_empty());
    }

    #[test]
    fn feed() {
        let mut chain = Chain::new(0u, 100u);
        chain.feed(vec![3u, 5u, 10u]).feed(vec![5u, 12u]);
    }

    #[test]
    fn generate() {
        let mut chain = Chain::new(0u, 100u);
        chain.feed(vec![3u, 5u, 10u]).feed(vec![5u, 12u]);
        let v = chain.generate().map_in_place(|v| *v);
        assert!([vec![3u, 5u, 10u], vec![3u, 5u, 12u], vec![5u, 10u], vec![5u, 12u]].contains(&v));
    }

    #[test]
    fn generate_from_token() {
        let mut chain = Chain::new(0u, 100u);
        chain.feed(vec![3u, 5u, 10u]).feed(vec![5u, 12u]);
        let v = chain.generate_from_token(5u).map_in_place(|v| *v);
        assert!([vec![5u, 10u], vec![5u, 12u]].contains(&v));
    }

    #[test]
    fn generate_from_unfound_token() {
        let mut chain = Chain::new(0u, 100u);
        chain.feed(vec![3u, 5u, 10u]).feed(vec![5u, 12u]);
        let v = chain.generate_from_token(9u).map_in_place(|v| *v);
        assert_eq!(v, vec![]);
    }

    #[test]
    fn feed_str() {
        let mut chain = Chain::for_strings();
        chain.feed_str("I like cats and dogs");
    }

    #[test]
    fn generate_str() {
        let mut chain = Chain::for_strings();
        chain.feed_str("I like cats").feed_str("I hate cats");
        assert!(["I like cats", "I hate cats"].contains(&chain.generate_str()[]));
    }

    #[test]
    fn generate_str_from_token() {
        let mut chain = Chain::for_strings();
        chain.feed_str("I like cats").feed_str("cats are cute");
        assert!(["cats", "cats are cute"].contains(&chain.generate_str_from_token("cats")[]));
    }

    #[test]
    fn generate_str_from_unfound_token() {
        let mut chain = Chain::for_strings();
        chain.feed_str("I like cats").feed_str("cats are cute");
        assert_eq!(chain.generate_str_from_token("test"), "");
    }
}
<commit_msg>Removed spelling mistake.<commit_after>//! A generic [Markov chain](https://en.wikipedia.org/wiki/Markov_chain) for almost any type. This
//! uses HashMaps internally, and so Eq and Hash are both required.
//!
//! # Examples
//!
//! ```
//! use markov::Chain;
//!
//! let mut chain = Chain::for_strings();
//! chain.feed_str("I like cats and I like dogs.");
//! println!("{}", chain.generate_str());
//! ```
//!
//! ```
//! use markov::Chain;
//!
//! let mut chain = Chain::new(0u8, 255);
//! chain.feed(vec![1u8, 2, 3, 5]).feed(vec![3u8, 9, 2]);
//! println!("{}", chain.generate());
//! ```
#![experimental]
#![feature(slicing_syntax)]
#![warn(missing_docs)]

use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::hash::Hash;
use std::io::{BufferedReader, File};
use std::rand::{Rng, task_rng};
use std::rc::Rc;

/// A generic [Markov chain](https://en.wikipedia.org/wiki/Markov_chain) for almost any type. This
/// uses HashMaps internally, and so Eq and Hash are both required.
pub struct Chain<T: Eq + Hash> {
    map: HashMap<Rc<T>, HashMap<Rc<T>, uint>>,
    start: Rc<T>,
    end: Rc<T>,
}

impl<T: Eq + Hash> Chain<T> {
    /// Constructs a new Markov chain using the given tokens as the marked starting and ending
    /// points for generation.
    pub fn new(start: T, end: T) -> Chain<T> {
        let start = Rc::new(start);
        let end = Rc::new(end);
        Chain {
            map: {
                let mut map = HashMap::new();
                map.insert(start.clone(), HashMap::new());
                map
            },
            start: start, end: end
        }
    }

    /// Determines whether or not the chain is empty. A chain is considered empty if nothing has
    /// been fed into it.
    pub fn is_empty(&self) -> bool {
        self.map[self.start.clone()].is_empty()
    }

    /// Feeds the chain a collection of tokens. This operation is O(n) where n is the number of
    /// tokens to be fed into the chain.
    pub fn feed(&mut self, tokens: Vec<T>) -> &mut Chain<T> {
        if tokens.len() == 0 { return self }
        let mut toks = Vec::new();
        toks.push(self.start.clone());
        toks.extend(tokens.into_iter().map(|token| {
            let rc = Rc::new(token);
            if !self.map.contains_key(&rc) {
                self.map.insert(rc.clone(), HashMap::new());
            }
            rc
        }));
        toks.push(self.end.clone());
        for p in toks.windows(2) {
            (&mut self.map[p[0]]).add(p[1].clone());
        }
        self
    }

    /// Generates a collection of tokens from the chain. This operation is O(mn) where m is the
    /// length of the generated collection, and n is the number of possible states from a given
    /// state.
    pub fn generate(&self) -> Vec<Rc<T>> {
        let mut ret = Vec::new();
        let mut curs = self.start.clone();
        while curs != self.end {
            curs = self.map[curs].next();
            ret.push(curs.clone());
        }
        ret.pop();
        ret
    }

    /// Generates a collection of tokens from the chain, starting with the given token. This
    /// operation is O(mn) where m is the length of the generated collection, and n is the number
    /// of possible states from a given state. This returns an empty vector if the token is not
    /// found.
    pub fn generate_from_token(&self, token: T) -> Vec<Rc<T>> {
        let token = Rc::new(token);
        if !self.map.contains_key(&token) { return Vec::new() }
        let mut ret = vec![token.clone()];
        let mut curs = token;
        while curs != self.end {
            curs = self.map[curs].next();
            ret.push(curs.clone());
        }
        ret.pop();
        ret
    }
}

impl Chain<String> {
    /// Creates a new Chain intended specifically for strings. This uses the Unicode start of text
    /// and end of text control characters as the starting and ending tokens for the chain.
    pub fn for_strings() -> Chain<String> {
        Chain::new("\u{0002}".into_string(), "\u{0003}".into_string())
    }

    /// Feeds a string of text into the chain.
    pub fn feed_str(&mut self, string: &str) -> &mut Chain<String> {
        self.feed(string.split_str(" ").map(|s| s.into_string()).collect())
    }

    /// Feeds a properly formatted file into the chain. This file should be formatted such that
    /// each line is a new sentence. Punctuation may be included if it is desired.
    pub fn feed_file(&mut self, path: &Path) -> &mut Chain<String> {
        let mut reader = BufferedReader::new(File::open(path));
        for line in reader.lines() {
            let line = line.unwrap();
            let words: Vec<_> = line.split([' ', '\t', '\n', '\r'][])
                                    .filter(|word| !word.is_empty())
                                    .collect();
            self.feed(words.iter().map(|s| s.into_string()).collect());
        }
        self
    }

    /// Generates a random string of text.
    pub fn generate_str(&self) -> String {
        let vec = self.generate();
        let mut ret = String::new();
        for s in vec.iter() {
            ret.push_str(s[]);
            ret.push_str(" ");
        }
        let len = ret.len();
        ret.truncate(len - 1);
        ret
    }

    /// Generates a random string of text starting with the desired token. This returns an empty
    /// string if the token is not found.
    pub fn generate_str_from_token(&self, string: &str) -> String {
        let vec = self.generate_from_token(string.into_string());
        let mut ret = String::new();
        for s in vec.iter() {
            ret.push_str(s[]);
            ret.push_str(" ");
        }
        let len = ret.len();
        if len > 0 {
            ret.truncate(len - 1);
        }
        ret
    }
}

/// A collection of states for the Markov chain.
trait States<T: PartialEq> {
    /// Adds a state to this states collection.
    fn add(&mut self, token: Rc<T>);
    /// Gets the next state from this collection of states.
    fn next(&self) -> Rc<T>;
}

impl<T: Eq + Hash> States<T> for HashMap<Rc<T>, uint> {
    fn add(&mut self, token: Rc<T>) {
        match self.entry(token) {
            Occupied(mut e) => *e.get_mut() += 1,
            Vacant(e) => { e.set(1); },
        }
    }

    fn next(&self) -> Rc<T> {
        let mut sum = 0;
        for &value in self.values() {
            sum += value;
        }
        let mut rng = task_rng();
        let cap = rng.gen_range(0, sum);
        sum = 0;
        for (key, &value) in self.iter() {
            sum += value;
            if sum > cap {
                return key.clone()
            }
        }
        unreachable!("The random number generator failed.")
    }
}

#[cfg(test)]
mod test {
    use super::Chain;

    #[test]
    fn new() {
        Chain::new(0u, 100u);
        Chain::for_strings();
    }

    #[test]
    fn is_empty() {
        let mut chain = Chain::new(0u, 100u);
        assert!(chain.is_empty());
        chain.feed(vec![1u, 2u, 3u]);
        assert!(!chain.is_empty());
    }

    #[test]
    fn feed() {
        let mut chain = Chain::new(0u, 100u);
        chain.feed(vec![3u, 5u, 10u]).feed(vec![5u, 12u]);
    }

    #[test]
    fn generate() {
        let mut chain = Chain::new(0u, 100u);
        chain.feed(vec![3u, 5u, 10u]).feed(vec![5u, 12u]);
        let v = chain.generate().map_in_place(|v| *v);
        assert!([vec![3u, 5u, 10u], vec![3u, 5u, 12u], vec![5u, 10u], vec![5u, 12u]].contains(&v));
    }

    #[test]
    fn generate_from_token() {
        let mut chain = Chain::new(0u, 100u);
        chain.feed(vec![3u, 5u, 10u]).feed(vec![5u, 12u]);
        let v = chain.generate_from_token(5u).map_in_place(|v| *v);
        assert!([vec![5u, 10u], vec![5u, 12u]].contains(&v));
    }

    #[test]
    fn generate_from_unfound_token() {
        let mut chain = Chain::new(0u, 100u);
        chain.feed(vec![3u, 5u, 10u]).feed(vec![5u, 12u]);
        let v = chain.generate_from_token(9u).map_in_place(|v| *v);
        assert_eq!(v, vec![]);
    }

    #[test]
    fn feed_str() {
        let mut chain = Chain::for_strings();
        chain.feed_str("I like cats and dogs");
    }

    #[test]
    fn generate_str() {
        let mut chain = Chain::for_strings();
        chain.feed_str("I like cats").feed_str("I hate cats");
        assert!(["I like cats", "I hate cats"].contains(&chain.generate_str()[]));
    }

    #[test]
    fn generate_str_from_token() {
        let mut chain = Chain::for_strings();
        chain.feed_str("I like cats").feed_str("cats are cute");
        assert!(["cats", "cats are cute"].contains(&chain.generate_str_from_token("cats")[]));
    }

    #[test]
    fn generate_str_from_unfound_token() {
        let mut chain = Chain::for_strings();
        chain.feed_str("I like cats").feed_str("cats are cute");
        assert_eq!(chain.generate_str_from_token("test"), "");
    }
}
<|endoftext|>


<commit_before>#![feature(no_std)]
#![no_std]

pub use elf_sections::{ElfSectionsTag, ElfSection, ElfSectionIter, ElfSectionType, ElfSectionFlags};
pub use memory_map::{MemoryMapTag, MemoryArea, MemoryAreaIter};

mod elf_sections;
mod memory_map;

pub unsafe fn load(address: usize) -> &'static BootInformation {
    let multiboot = &*(address as *const BootInformation);
    assert!(multiboot.has_valid_end_tag());
    multiboot
}

#[repr(C)]
pub struct BootInformation {
    pub total_size: u32,
    _reserved: u32,
    first_tag: Tag,
}

impl BootInformation {
    pub fn elf_sections_tag(&self) -> Option<&'static ElfSectionsTag> {
        self.get_tag(9).map(|tag| unsafe{&*(tag as *const Tag as *const ElfSectionsTag)})
    }

    pub fn memory_area_tag(&self) -> Option<&'static MemoryMapTag> {
        self.get_tag(6).map(|tag| unsafe{&*(tag as *const Tag as *const MemoryMapTag)})
    }

    fn has_valid_end_tag(&self) -> bool {
        const END_TAG: Tag = Tag{typ:0, size:8};

        let self_ptr = self as *const _;
        let end_tag_addr = self_ptr as usize + (self.total_size - END_TAG.size) as usize;
        let end_tag = unsafe{&*(end_tag_addr as *const Tag)};

        end_tag.typ == END_TAG.typ && end_tag.size == END_TAG.size
    }

    fn get_tag(&self, typ: u32) -> Option<&'static Tag> {
        self.tags().find(|tag| tag.typ == typ)
    }

    fn tags(&self) -> TagIter {
        TagIter{current: &self.first_tag as *const _}
    }
}

#[repr(C)]
struct Tag {
    typ: u32,
    size: u32,
    // tag specific fields
}

struct TagIter {
    current: *const Tag,
}

impl Iterator for TagIter {
    type Item = &'static Tag;

    fn next(&mut self) -> Option<&'static Tag> {
        match unsafe{&*self.current} {
            &Tag{typ:0, size:8} => None, // end tag
            tag => {
                // go to next tag
                let mut tag_addr = self.current as usize;
                tag_addr += tag.size as usize;
                tag_addr = ((tag_addr-1) & !0x7) + 0x8; //align at 8 byte
                self.current = tag_addr as *const _;

                Some(tag)
            },
        }
    }
}
<commit_msg>Rename `memory_area_tag` to `memory_map_tag`<commit_after>#![feature(no_std)]
#![no_std]

pub use elf_sections::{ElfSectionsTag, ElfSection, ElfSectionIter, ElfSectionType, ElfSectionFlags};
pub use memory_map::{MemoryMapTag, MemoryArea, MemoryAreaIter};

mod elf_sections;
mod memory_map;

pub unsafe fn load(address: usize) -> &'static BootInformation {
    let multiboot = &*(address as *const BootInformation);
    assert!(multiboot.has_valid_end_tag());
    multiboot
}

#[repr(C)]
pub struct BootInformation {
    pub total_size: u32,
    _reserved: u32,
    first_tag: Tag,
}

impl BootInformation {
    pub fn elf_sections_tag(&self) -> Option<&'static ElfSectionsTag> {
        self.get_tag(9).map(|tag| unsafe{&*(tag as *const Tag as *const ElfSectionsTag)})
    }

    pub fn memory_map_tag(&self) -> Option<&'static MemoryMapTag> {
        self.get_tag(6).map(|tag| unsafe{&*(tag as *const Tag as *const MemoryMapTag)})
    }

    fn has_valid_end_tag(&self) -> bool {
        const END_TAG: Tag = Tag{typ:0, size:8};

        let self_ptr = self as *const _;
        let end_tag_addr = self_ptr as usize + (self.total_size - END_TAG.size) as usize;
        let end_tag = unsafe{&*(end_tag_addr as *const Tag)};

        end_tag.typ == END_TAG.typ && end_tag.size == END_TAG.size
    }

    fn get_tag(&self, typ: u32) -> Option<&'static Tag> {
        self.tags().find(|tag| tag.typ == typ)
    }

    fn tags(&self) -> TagIter {
        TagIter{current: &self.first_tag as *const _}
    }
}

#[repr(C)]
struct Tag {
    typ: u32,
    size: u32,
    // tag specific fields
}

struct TagIter {
    current: *const Tag,
}

impl Iterator for TagIter {
    type Item = &'static Tag;

    fn next(&mut self) -> Option<&'static Tag> {
        match unsafe{&*self.current} {
            &Tag{typ:0, size:8} => None, // end tag
            tag => {
                // go to next tag
                let mut tag_addr = self.current as usize;
                tag_addr += tag.size as usize;
                tag_addr = ((tag_addr-1) & !0x7) + 0x8; //align at 8 byte
                self.current = tag_addr as *const _;

                Some(tag)
            },
        }
    }
}
<|endoftext|>


<commit_before>//! # quicksort
//!
//! Quicksort is an efficient in-line sorting algorithm created by Tony Hoare.
//!

use std::cmp::Ordering;

/// In-line sorting of a slice of T.
///
/// ```rust
/// # use ironsort::quicksort;
/// let presorted: Vec<u64> = vec![1, 1, 2, 3, 3, 4, 5, 5, 6, 9];
/// let mut vector: Vec<u64> = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3];
/// quicksort(&mut vector);
///
/// assert_eq!(vector, presorted.as_slice());
/// ```
#[inline]
pub fn quicksort<T: Ord>(vec: &mut [T]) {
    quicksort_by(vec, &|x, y| x.cmp(y))
}

pub fn quicksort_by<T: PartialOrd, F>(vec: &mut [T], cmp: &F)
    where F: Fn(&T, &T) -> Ordering {

    let len: usize = vec.len();
    if len <= 1 {
        return;
    }

    vec.swap(0, len / 2);
    let pivot: usize = 0;

    let mut left: usize = 0;
    let mut right:usize = vec.len() - 1;

    while left < right {
        while left < len && cmp(&vec[left], &vec[pivot]) != Ordering::Greater {
            left += 1
        }
        while cmp(&vec[right], &vec[pivot]) == Ordering::Greater {
            right -= 1
        }

        if left < right {
            vec.swap(left, right);
        }
    }

    vec.swap(pivot, right);
    quicksort_by(&mut vec[0..right], cmp);
    quicksort_by(&mut vec[right+1..], cmp);
}

#[cfg(test)]
extern crate rand;

#[cfg(test)]
mod tests {
    use rand::{self, Rng};
    use super::*;

    #[test]
    fn test_vec_of_u64() {
        let presorted: Vec<u64> = vec![1, 1, 2, 3, 3, 4, 5, 5, 6, 9];
        let mut vector: Vec<u64> = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3];
        quicksort(&mut vector);

        assert_eq!(vector, presorted.as_slice());
    }

    #[test]
    fn test_vec_of_u8() {
        let presorted = "        Tabcdeeefghhijklmnoooopqrrstuuvwxyz".to_string().into_bytes();
        let mut vector = "The quick brown fox jumps over the lazy dog".to_string().into_bytes();
        quicksort(&mut vector);

        assert_eq!(presorted, vector);
    }

    #[test]
    fn test_array_of_u8() {
        let presorted: [u8; 10] = [1, 2, 3, 4, 5, 5, 5, 7, 9, 10];
        let mut vector: [u8; 10] = [7, 5, 3, 2, 5, 1, 4, 5, 9, 10];
        quicksort(&mut vector);

        assert_eq!(presorted, vector);
    }

    #[test]
    fn test_random() {
        let mut rng = rand::thread_rng();

        for _ in 0u64 .. 10_000u64 {
            let len: usize = rng.gen();
            let mut vector = rng.gen_iter()
                                .take((len % 64) + 1)
                                .collect::<Vec<usize>>();
            quicksort(&mut vector);

            for i in 0 .. vector.len() - 1 {
                assert!(vector[i] <= vector[i + 1])
            }
        }
    }
}
<commit_msg>quicksort_by: Add missing whitespace<commit_after>//! # quicksort
//!
//! Quicksort is an efficient in-line sorting algorithm created by Tony Hoare.
//!

use std::cmp::Ordering;

/// In-line sorting of a slice of T.
///
/// ```rust
/// # use ironsort::quicksort;
/// let presorted: Vec<u64> = vec![1, 1, 2, 3, 3, 4, 5, 5, 6, 9];
/// let mut vector: Vec<u64> = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3];
/// quicksort(&mut vector);
///
/// assert_eq!(vector, presorted.as_slice());
/// ```
#[inline]
pub fn quicksort<T: Ord>(vec: &mut [T]) {
    quicksort_by(vec, &|x, y| x.cmp(y))
}

pub fn quicksort_by<T: PartialOrd, F>(vec: &mut [T], cmp: &F)
    where F: Fn(&T, &T) -> Ordering {

    let len: usize = vec.len();
    if len <= 1 {
        return;
    }

    vec.swap(0, len / 2);
    let pivot: usize = 0;

    let mut left: usize = 0;
    let mut right: usize = vec.len() - 1;

    while left < right {
        while left < len && cmp(&vec[left], &vec[pivot]) != Ordering::Greater {
            left += 1
        }
        while cmp(&vec[right], &vec[pivot]) == Ordering::Greater {
            right -= 1
        }

        if left < right {
            vec.swap(left, right);
        }
    }

    vec.swap(pivot, right);
    quicksort_by(&mut vec[0..right], cmp);
    quicksort_by(&mut vec[right+1..], cmp);
}

#[cfg(test)]
extern crate rand;

#[cfg(test)]
mod tests {
    use rand::{self, Rng};
    use super::*;

    #[test]
    fn test_vec_of_u64() {
        let presorted: Vec<u64> = vec![1, 1, 2, 3, 3, 4, 5, 5, 6, 9];
        let mut vector: Vec<u64> = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3];
        quicksort(&mut vector);

        assert_eq!(vector, presorted.as_slice());
    }

    #[test]
    fn test_vec_of_u8() {
        let presorted = "        Tabcdeeefghhijklmnoooopqrrstuuvwxyz".to_string().into_bytes();
        let mut vector = "The quick brown fox jumps over the lazy dog".to_string().into_bytes();
        quicksort(&mut vector);

        assert_eq!(presorted, vector);
    }

    #[test]
    fn test_array_of_u8() {
        let presorted: [u8; 10] = [1, 2, 3, 4, 5, 5, 5, 7, 9, 10];
        let mut vector: [u8; 10] = [7, 5, 3, 2, 5, 1, 4, 5, 9, 10];
        quicksort(&mut vector);

        assert_eq!(presorted, vector);
    }

    #[test]
    fn test_random() {
        let mut rng = rand::thread_rng();

        for _ in 0u64 .. 10_000u64 {
            let len: usize = rng.gen();
            let mut vector = rng.gen_iter()
                                .take((len % 64) + 1)
                                .collect::<Vec<usize>>();
            quicksort(&mut vector);

            for i in 0 .. vector.len() - 1 {
                assert!(vector[i] <= vector[i + 1])
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate nix;
extern crate cargo;
extern crate gimli;
extern crate object;
extern crate memmap;
extern crate coveralls_api;
extern crate fallible_iterator;
extern crate rustc_demangle;
extern crate syn;
extern crate proc_macro2;
#[macro_use]
extern crate clap;
#[macro_use]
extern crate lazy_static;
extern crate serde;
extern crate serde_json;
extern crate quick_xml;
extern crate regex;
extern crate walkdir;

use std::env;
use std::io;
use std::ffi::CString;
use std::path::{Path, PathBuf};
use std::process::Command;
use nix::unistd::*;
use cargo::util::Config as CargoConfig;
use cargo::core::{Workspace, Package};
use cargo::ops;

pub mod config;
pub mod test_loader;
pub mod breakpoint;
pub mod report;
pub mod traces;
mod statemachine;
mod source_analysis;

/// Should be unnecessary with a future nix crate release.
mod personality;
mod ptrace_control;

use config::*;
use test_loader::*;
use ptrace_control::*;
use statemachine::*;
use traces::*;

pub fn run(config: Config) -> Result<(), i32> {
    let result = launch_tarpaulin(&config)?;
    report_coverage(&config, &result);
    Ok(())
}

/// Launches tarpaulin with the given configuration.
pub fn launch_tarpaulin(config: &Config) -> Result<TraceMap, i32> {
    let mut cargo_config = CargoConfig::default().unwrap();
    let flag_quiet = if config.verbose {
        None
    } else {
        Some(true)
    };
    // This shouldn't fail so no checking the error.
    let _ = cargo_config.configure(0u32, flag_quiet, &None, false, false, &[]);

    let workspace = Workspace::new(config.manifest.as_path(), &cargo_config).map_err(|_| 1i32)?;

    setup_environment(&cargo_config);

    let mut copt = ops::CompileOptions::default(&cargo_config, ops::CompileMode::Test);
    match copt.filter {
        ops::CompileFilter::Default{ref mut required_features_filterable} => {
            *required_features_filterable = true;
        },
        _ => {},
    }
    copt.features = config.features.as_slice();
    copt.all_features = config.all_features;
    copt.spec = match ops::Packages::from_flags(workspace.is_virtual(), config.all, &config.exclude, &config.packages) {
        Ok(spec) => spec,
        Err(e) => {
            println!("Error getting Packages from workspace {}", e);
            return Err(-1)
        }
    };
    if config.verbose {
        println!("Running Tarpaulin");
    }
    if !config.skip_clean {
        if config.verbose {
            println!("Cleaning project");
        }
        // Clean isn't expected to fail and if it does it likely won't have an effect
        let clean_opt = ops::CleanOptions {
            config: &cargo_config,
            spec: &[],
            target: None,
            release: false,
        };
        let _ = ops::clean(&workspace, &clean_opt);
    }
    let mut result = TraceMap::new();
    println!("Building project");
    let compilation = ops::compile(&workspace, &copt);
    match compilation {
        Ok(comp) => {
            for &(ref package, ref _target_kind, ref name, ref path) in &comp.tests {
                if config.verbose {
                    println!("Processing {}", name);
                }
                if let Some(res) = get_test_coverage(&workspace, package, path.as_path(), &config, false) {
                    result.merge(&res);
                }
                if config.run_ignored {
                    if let Some(res) = get_test_coverage(&workspace, package, path.as_path(),
                                                         &config, true) {
                        result.merge(&res);
                    }
                }
            }
            result.dedup();
            Ok(result)
        },
        Err(e) => {
            if config.verbose{
                println!("Error: failed to compile: {}", e);
            }
            Err(-1)
        },
    }
}

fn setup_environment(cargo_config: &CargoConfig) {
    let rustflags = "RUSTFLAGS";
    let mut value = "-C relocation-model=dynamic-no-pic -C link-dead-code -C opt-level=0".to_string();
    let env_linker = env::var(rustflags)
                        .ok()
                        .and_then(|flags| flags.split(' ')
                                               .map(str::trim)
                                               .filter(|s| !s.is_empty())
                                               .skip_while(|s| !s.contains("linker="))
                                               .next()
                                               .map(|s| s.trim_left_matches("linker="))
                                               .map(PathBuf::from));

    let target_linker = env_linker.or_else(|| {
        fn get_target_path(cargo_config: &CargoConfig, triple: &str) -> Option<PathBuf> {
            cargo_config.get_path(&format!("target.{}.linker", triple)).unwrap().map(|v| v.val)
        }

        let host = get_target_path(&cargo_config, &cargo_config.rustc().unwrap().host);
        match cargo_config.get_string("build.target").unwrap().map(|s| s.val) {
            Some(triple) => get_target_path(&cargo_config, &triple),
            None => host,
        }
    });

    // For Linux (and most everything that isn't Windows) it is fair to
    // assume the default linker is `cc` and that `cc` is GCC based.
    let mut linker_cmd = Command::new(&target_linker.unwrap_or_else(|| PathBuf::from("cc")));
    linker_cmd.arg("-v");
    if let Ok(linker_output) = linker_cmd.output() {
        if String::from_utf8_lossy(&linker_output.stderr).contains("--enable-default-pie") {
            value.push_str("-C link-arg=-no-pie ");
        }
    }
    if let Ok(vtemp) = env::var(rustflags) {
        value.push_str(vtemp.as_ref());
    }
    env::set_var(rustflags, value);

}

/// Reports the test coverage using the users preferred method. See config.rs
/// or help text for details.
pub fn report_coverage(config: &Config, result: &TraceMap) {
    if !result.is_empty() {
        println!("Coverage Results");
        if config.verbose {
            for (ref key, ref value) in result.iter() {
                let path = config.strip_project_path(key);
                for v in value.iter() {
                    println!("{}:{} - {}", path.display(), v.line, v.stats);
                }
            }
            println!("");
        }
        for file in result.files() {
            let path = config.strip_project_path(file);
            println!("{}: {}/{}", path.display(), result.covered_in_path(&file), result.coverable_in_path(&file));
        }
        let percent = result.coverage_percentage() * 100.0f64;
        // Put file filtering here
        println!("\n{:.2}% coverage, {}/{} lines covered", percent,
                 result.total_covered(), result.total_coverable());
        if config.is_coveralls() {
            report::coveralls::export(result, config);
            println!("Coverage data sent");
        }

        for g in &config.generate {
            match g {
                &OutputFile::Xml => {
                    report::cobertura::export(result, config);
                },
                _ => {
                    println!("Format currently unsupported");
                },
            }
        }
    } else {
        println!("No coverage results collected.");
    }

}

/// Returns the coverage statistics for a test executable in the given workspace
pub fn get_test_coverage(project: &Workspace,
                         package: &Package,
                         test: &Path,
                         config: &Config,
                         ignored: bool) -> Option<TraceMap> {
    if !test.exists() {
        return None;
    }
    match fork() {
        Ok(ForkResult::Parent{ child }) => {
            match collect_coverage(project, test, child, config) {
                Ok(t) => {
                    Some(t)
                },
                Err(e) => {
                    println!("Error occurred: {}", e);
                    None
                },
            }
        }
        Ok(ForkResult::Child) => {
            println!("Launching test");
            execute_test(test, package, ignored, config);
            None
        }
        Err(err) => {
            println!("Failed to run {}", test.display());
            println!("Error {}", err);
            None
        }
    }

}

/// Collects the coverage data from the launched test
fn collect_coverage(project: &Workspace,
                    test_path: &Path,
                    test: Pid,
                    config: &Config) -> io::Result<TraceMap> {
    let mut traces = generate_tracemap(project, test_path, config)?;
    {
        let (mut state, mut data) = create_state_machine(test, &mut traces, config);
        loop {
            state = state.step(&mut data, config);
            if state.is_finished() {
                break;
            }
        }
        if let Some(m) = data.error_message {
            println!("{}", m);
        }
        if state == TestState::Abort  {
            println!("Can't collect coverage data. Exiting");
            std::process::exit(1);
        }
    }
    Ok(traces)
}

/// Launches the test executable
fn execute_test(test: &Path, package: &Package, ignored: bool, config: &Config) {
    let exec_path = CString::new(test.to_str().unwrap()).unwrap();
    match personality::disable_aslr() {
        Ok(_) => {},
        Err(e) => println!("ASLR disable failed: {}", e),
    }
    request_trace().expect("Failed to trace");
    println!("running {}", test.display());
    if let Some(parent) = package.manifest_path().parent() {
        let _ = env::set_current_dir(parent);
    }

    let mut envars: Vec<CString> = vec![CString::new("RUST_TEST_THREADS=1").unwrap()];
    for (key, value) in env::vars() {
        let mut temp = String::new();
        temp.push_str(key.as_str());
        temp.push('=');
        temp.push_str(value.as_str());
        envars.push(CString::new(temp).unwrap());
    }
    let mut argv = if ignored {
        vec![exec_path.clone(), CString::new("--ignored").unwrap()]
    } else {
        vec![exec_path.clone()]
    };
    if config.verbose {
        envars.push(CString::new("RUST_BACKTRACE=1").unwrap());
    } else {
        argv.push(CString::new("--quiet").unwrap());
    }
    for s in &config.varargs {
        argv.push(CString::new(s.as_bytes()).unwrap_or_default());
    }
    execve(&exec_path, &argv, envars.as_slice())
        .unwrap();
}

<commit_msg>Sorted spaces issue in rustflags<commit_after>extern crate nix;
extern crate cargo;
extern crate gimli;
extern crate object;
extern crate memmap;
extern crate coveralls_api;
extern crate fallible_iterator;
extern crate rustc_demangle;
extern crate syn;
extern crate proc_macro2;
#[macro_use]
extern crate clap;
#[macro_use]
extern crate lazy_static;
extern crate serde;
extern crate serde_json;
extern crate quick_xml;
extern crate regex;
extern crate walkdir;

use std::env;
use std::io;
use std::ffi::CString;
use std::path::{Path, PathBuf};
use std::process::Command;
use nix::unistd::*;
use cargo::util::Config as CargoConfig;
use cargo::core::{Workspace, Package};
use cargo::ops;

pub mod config;
pub mod test_loader;
pub mod breakpoint;
pub mod report;
pub mod traces;
mod statemachine;
mod source_analysis;

/// Should be unnecessary with a future nix crate release.
mod personality;
mod ptrace_control;

use config::*;
use test_loader::*;
use ptrace_control::*;
use statemachine::*;
use traces::*;

pub fn run(config: Config) -> Result<(), i32> {
    let result = launch_tarpaulin(&config)?;
    report_coverage(&config, &result);
    Ok(())
}

/// Launches tarpaulin with the given configuration.
pub fn launch_tarpaulin(config: &Config) -> Result<TraceMap, i32> {
    let mut cargo_config = CargoConfig::default().unwrap();
    let flag_quiet = if config.verbose {
        None
    } else {
        Some(true)
    };
    // This shouldn't fail so no checking the error.
    let _ = cargo_config.configure(0u32, flag_quiet, &None, false, false, &[]);

    let workspace = Workspace::new(config.manifest.as_path(), &cargo_config).map_err(|_| 1i32)?;

    setup_environment(&cargo_config);

    let mut copt = ops::CompileOptions::default(&cargo_config, ops::CompileMode::Test);
    match copt.filter {
        ops::CompileFilter::Default{ref mut required_features_filterable} => {
            *required_features_filterable = true;
        },
        _ => {},
    }
    copt.features = config.features.as_slice();
    copt.all_features = config.all_features;
    copt.spec = match ops::Packages::from_flags(workspace.is_virtual(), config.all, &config.exclude, &config.packages) {
        Ok(spec) => spec,
        Err(e) => {
            println!("Error getting Packages from workspace {}", e);
            return Err(-1)
        }
    };
    if config.verbose {
        println!("Running Tarpaulin");
    }
    if !config.skip_clean {
        if config.verbose {
            println!("Cleaning project");
        }
        // Clean isn't expected to fail and if it does it likely won't have an effect
        let clean_opt = ops::CleanOptions {
            config: &cargo_config,
            spec: &[],
            target: None,
            release: false,
        };
        let _ = ops::clean(&workspace, &clean_opt);
    }
    let mut result = TraceMap::new();
    println!("Building project");
    let compilation = ops::compile(&workspace, &copt);
    match compilation {
        Ok(comp) => {
            for &(ref package, ref _target_kind, ref name, ref path) in &comp.tests {
                if config.verbose {
                    println!("Processing {}", name);
                }
                if let Some(res) = get_test_coverage(&workspace, package, path.as_path(), &config, false) {
                    result.merge(&res);
                }
                if config.run_ignored {
                    if let Some(res) = get_test_coverage(&workspace, package, path.as_path(),
                                                         &config, true) {
                        result.merge(&res);
                    }
                }
            }
            result.dedup();
            Ok(result)
        },
        Err(e) => {
            if config.verbose{
                println!("Error: failed to compile: {}", e);
            }
            Err(-1)
        },
    }
}

fn setup_environment(cargo_config: &CargoConfig) {
    let rustflags = "RUSTFLAGS";
    let mut value = " -C relocation-model=dynamic-no-pic -C link-dead-code -C opt-level=0 ".to_string();
    let env_linker = env::var(rustflags)
                        .ok()
                        .and_then(|flags| flags.split(' ')
                                               .map(str::trim)
                                               .filter(|s| !s.is_empty())
                                               .skip_while(|s| !s.contains("linker="))
                                               .next()
                                               .map(|s| s.trim_left_matches("linker="))
                                               .map(PathBuf::from));

    let target_linker = env_linker.or_else(|| {
        fn get_target_path(cargo_config: &CargoConfig, triple: &str) -> Option<PathBuf> {
            cargo_config.get_path(&format!("target.{}.linker", triple)).unwrap().map(|v| v.val)
        }

        let host = get_target_path(&cargo_config, &cargo_config.rustc().unwrap().host);
        match cargo_config.get_string("build.target").unwrap().map(|s| s.val) {
            Some(triple) => get_target_path(&cargo_config, &triple),
            None => host,
        }
    });

    // For Linux (and most everything that isn't Windows) it is fair to
    // assume the default linker is `cc` and that `cc` is GCC based.
    let mut linker_cmd = Command::new(&target_linker.unwrap_or_else(|| PathBuf::from("cc")));
    linker_cmd.arg("-v");
    if let Ok(linker_output) = linker_cmd.output() {
        if String::from_utf8_lossy(&linker_output.stderr).contains("--enable-default-pie") {
            value.push_str("-C link-arg=-no-pie ");
        }
    }
    if let Ok(vtemp) = env::var(rustflags) {
        value.push_str(vtemp.as_ref());
    }
    env::set_var(rustflags, value);
}

/// Reports the test coverage using the users preferred method. See config.rs
/// or help text for details.
pub fn report_coverage(config: &Config, result: &TraceMap) {
    if !result.is_empty() {
        println!("Coverage Results");
        if config.verbose {
            for (ref key, ref value) in result.iter() {
                let path = config.strip_project_path(key);
                for v in value.iter() {
                    println!("{}:{} - {}", path.display(), v.line, v.stats);
                }
            }
            println!("");
        }
        for file in result.files() {
            let path = config.strip_project_path(file);
            println!("{}: {}/{}", path.display(), result.covered_in_path(&file), result.coverable_in_path(&file));
        }
        let percent = result.coverage_percentage() * 100.0f64;
        // Put file filtering here
        println!("\n{:.2}% coverage, {}/{} lines covered", percent,
                 result.total_covered(), result.total_coverable());
        if config.is_coveralls() {
            report::coveralls::export(result, config);
            println!("Coverage data sent");
        }

        for g in &config.generate {
            match g {
                &OutputFile::Xml => {
                    report::cobertura::export(result, config);
                },
                _ => {
                    println!("Format currently unsupported");
                },
            }
        }
    } else {
        println!("No coverage results collected.");
    }

}

/// Returns the coverage statistics for a test executable in the given workspace
pub fn get_test_coverage(project: &Workspace,
                         package: &Package,
                         test: &Path,
                         config: &Config,
                         ignored: bool) -> Option<TraceMap> {
    if !test.exists() {
        return None;
    }
    match fork() {
        Ok(ForkResult::Parent{ child }) => {
            match collect_coverage(project, test, child, config) {
                Ok(t) => {
                    Some(t)
                },
                Err(e) => {
                    println!("Error occurred: {}", e);
                    None
                },
            }
        }
        Ok(ForkResult::Child) => {
            println!("Launching test");
            execute_test(test, package, ignored, config);
            None
        }
        Err(err) => {
            println!("Failed to run {}", test.display());
            println!("Error {}", err);
            None
        }
    }

}

/// Collects the coverage data from the launched test
fn collect_coverage(project: &Workspace,
                    test_path: &Path,
                    test: Pid,
                    config: &Config) -> io::Result<TraceMap> {
    let mut traces = generate_tracemap(project, test_path, config)?;
    {
        let (mut state, mut data) = create_state_machine(test, &mut traces, config);
        loop {
            state = state.step(&mut data, config);
            if state.is_finished() {
                break;
            }
        }
        if let Some(m) = data.error_message {
            println!("{}", m);
        }
        if state == TestState::Abort  {
            println!("Can't collect coverage data. Exiting");
            std::process::exit(1);
        }
    }
    Ok(traces)
}

/// Launches the test executable
fn execute_test(test: &Path, package: &Package, ignored: bool, config: &Config) {
    let exec_path = CString::new(test.to_str().unwrap()).unwrap();
    match personality::disable_aslr() {
        Ok(_) => {},
        Err(e) => println!("ASLR disable failed: {}", e),
    }
    request_trace().expect("Failed to trace");
    println!("running {}", test.display());
    if let Some(parent) = package.manifest_path().parent() {
        let _ = env::set_current_dir(parent);
    }

    let mut envars: Vec<CString> = vec![CString::new("RUST_TEST_THREADS=1").unwrap()];
    for (key, value) in env::vars() {
        let mut temp = String::new();
        temp.push_str(key.as_str());
        temp.push('=');
        temp.push_str(value.as_str());
        envars.push(CString::new(temp).unwrap());
    }
    let mut argv = if ignored {
        vec![exec_path.clone(), CString::new("--ignored").unwrap()]
    } else {
        vec![exec_path.clone()]
    };
    if config.verbose {
        envars.push(CString::new("RUST_BACKTRACE=1").unwrap());
    } else {
        argv.push(CString::new("--quiet").unwrap());
    }
    for s in &config.varargs {
        argv.push(CString::new(s.as_bytes()).unwrap_or_default());
    }
    execve(&exec_path, &argv, envars.as_slice())
        .unwrap();
}

<|endoftext|>