<commit_before>extern crate env_logger;

extern crate gluon_base as base;
extern crate gluon_parser as parser;
extern crate gluon_check as check;

use base::pos::{BytePos, CharPos, Location};
use base::types::{Type, TcType};
use check::completion;

mod support;
use support::{MockEnv, typ};

fn find_type(s: &str, location: Location) -> Result<TcType, ()> {
    let env = MockEnv::new();

    let (mut expr, result) = support::typecheck_expr(s);
    assert!(result.is_ok(), "{}", result.unwrap_err());

    completion::find(&env, &mut expr, location)
}

fn suggest(s: &str, location: Location) -> Result<Vec<String>, ()> {
    let env = MockEnv::new();

    let (mut expr, _result) = support::typecheck_partial_expr(s);
    let mut vec: Vec<String> = {
        completion::suggest(&env, &mut expr, location)
            .into_iter()
            .map(|ident| ident.name)
            .collect()
    };
    vec.sort();

    Ok(vec)
}

#[test]
fn identifier() {
    let env = MockEnv::new();

    let (mut expr, result) = support::typecheck_expr("let abc = 1 in abc");
    assert!(result.is_ok(), "{}", result.unwrap_err());

    let result = completion::find(&env,
                                  &mut expr,
                                  Location {
                                      line: 1,
                                      column: CharPos(16),
                                      absolute: BytePos(0),
                                  });
    let expected = Ok(typ("Int"));
    assert_eq!(result, expected);

    let result = completion::find(&env,
                                  &mut expr,
                                  Location {
                                      line: 1,
                                      column: CharPos(17),
                                      absolute: BytePos(0),
                                  });
    let expected = Ok(typ("Int"));
    assert_eq!(result, expected);

    let result = completion::find(&env,
                                  &mut expr,
                                  Location {
                                      line: 1,
                                      column: CharPos(18),
                                      absolute: BytePos(0),
                                  });
    let expected = Ok(typ("Int"));
    assert_eq!(result, expected);

    let result = completion::find(&env,
                                  &mut expr,
                                  Location {
                                      line: 1,
                                      column: CharPos(19),
                                      absolute: BytePos(0),
                                  });
    assert_eq!(result, Err(()));
}

#[test]
fn literal_string() {
    let result = find_type(r#" "asd" "#,
                           Location {
                               line: 1,
                               column: CharPos(2),
                               absolute: BytePos(0),
                           });
    let expected = Ok(typ("String"));

    assert_eq!(result, expected);
}

#[test]
fn in_let() {
    let result = find_type(r#"
let f x = 1
and g x = "asd"
1
"#,
                           Location {
                               line: 3,
                               column: CharPos(15),
                               absolute: BytePos(0),
                           });
    let expected = Ok(typ("String"));

    assert_eq!(result, expected);
}

#[test]
fn function_call() {
    let result = find_type(r#"
let f x = f x
1
"#,
                           Location {
                               line: 2,
                               column: CharPos(11),
                               absolute: BytePos(11),
                           });
    let expected = Ok(Type::function(vec![typ("a0")], typ("a1")));

    assert_eq!(result, expected);
}

#[test]
fn binop() {
    let env = MockEnv::new();

    let (mut expr, result) = support::typecheck_expr(r#"
let (++) l r =
    l #Int+ 1
    r #Float+ 1.0
    l
1 ++ 2.0
"#);
    assert!(result.is_ok(), "{}", result.unwrap_err());

    let result = completion::find(&env,
                                  &mut expr,
                                  Location {
                                      line: 6,
                                      column: CharPos(4),
                                      absolute: BytePos(0),
                                  });
    let expected = Ok(Type::function(vec![typ("Int"), typ("Float")], typ("Int")));
    assert_eq!(result, expected);

    let result = completion::find(&env,
                                  &mut expr,
                                  Location {
                                      line: 6,
                                      column: CharPos(1),
                                      absolute: BytePos(0),
                                  });
    let expected = Ok(typ("Int"));
    assert_eq!(result, expected);

    let result = completion::find(&env,
                                  &mut expr,
                                  Location {
                                      line: 6,
                                      column: CharPos(6),
                                      absolute: BytePos(123),
                                  });
    let expected = Ok(typ("Float"));
    assert_eq!(result, expected);
}

#[test]
fn in_record() {
    let result = find_type(r#"
{
    test = 123,
    s = "asd"
}
"#,
                           Location {
                               line: 3,
                               column: CharPos(14),
                               absolute: BytePos(0),
                           });
    let expected = Ok(typ("Int"));

    assert_eq!(result, expected);
}

#[test]
fn suggest_identifier_when_prefix() {
    let result = suggest(r#"
let test = 1
let tes = ""
let aaa = test
te
"#,
                         Location {
                             line: 5,
                             column: CharPos(1),
                             absolute: BytePos(0),
                         });
    let expected = Ok(vec!["tes".into(), "test".into()]);

    assert_eq!(result, expected);
}

#[test]
fn suggest_arguments() {
    let result = suggest(r#"
let f test =
    \test2 -> tes
123
"#,
                         Location {
                             line: 3,
                             column: CharPos(17),
                             absolute: BytePos(0),
                         });
    let expected = Ok(vec!["test".into(), "test2".into()]);

    assert_eq!(result, expected);
}

#[test]
fn suggest_after_unrelated_type_error() {
    let result = suggest(r#"
let record = { aa = 1, ab = 2, c = "" }
1.0 #Int+ 2
record.a
"#,
                         Location {
                             line: 4,
                             column: CharPos(8),
                             absolute: BytePos(0),
                         });
    let expected = Ok(vec!["aa".into(), "ab".into()]);

    assert_eq!(result, expected);
}

#[test]
fn suggest_through_aliases() {
    let result = suggest(r#"
type Test a = { abc: a -> Int }
type Test2 = Test String
let record: Test2 = { abc = \x -> 0 }
record.ab
"#,
                         Location {
                             line: 5,
                             column: CharPos(8),
                             absolute: BytePos(0),
                         });
    let expected = Ok(vec!["abc".into()]);

    assert_eq!(result, expected);
}

#[test]
fn suggest_after_dot() {
    let result = suggest(r#"
let record = { aa = 1, ab = 2, c = "" }
record.
"#,
                         Location {
                             line: 3,
                             column: CharPos(7),
                             absolute: BytePos(50),
                         });
    let expected = Ok(vec!["aa".into(), "ab".into(), "c".into()]);

    assert_eq!(result, expected);
}

#[test]
fn suggest_from_record_unpack() {
    let result = suggest(r#"
let { aa, c } = { aa = 1, ab = 2, c = "" }
a
"#,
                         Location {
                             line: 3,
                             column: CharPos(1),
                             absolute: BytePos(0),
                         });
    let expected = Ok(vec!["aa".into()]);

    assert_eq!(result, expected);
}

#[test]
fn suggest_on_record_in_field_access() {
    let result = suggest(r#"
let record = { aa = 1, ab = 2, c = "" }
record.aa
"#,
                         Location {
                             line: 3,
                             column: CharPos(4),
                             absolute: BytePos(0),
                         });
    let expected = Ok(vec!["record".into()]);

    assert_eq!(result, expected);
}

#[test]
fn suggest_end_of_identifier() {
    let result = suggest(r#"
let abc = 1
let abb = 2
abc
"#,
                         Location {
                             line: 4,
                             column: CharPos(3),
                             absolute: BytePos(0),
                         });
    let expected = Ok(vec!["abc".into()]);

    assert_eq!(result, expected);
}

#[test]
fn suggest_after_identifier() {
    let result = suggest(r#"
let abc = 1
let abb = 2
abc
"#,
                         Location {
                             line: 4,
                             column: CharPos(5),
                             absolute: BytePos(0),
                         });
    let expected = Ok(vec!["abb".into(), "abc".into()]);

    assert_eq!(result, expected);
}
<commit_msg>test(completion): Add tests for getting the type from a field access expression<commit_after>extern crate env_logger;

extern crate gluon_base as base;
extern crate gluon_parser as parser;
extern crate gluon_check as check;

use base::pos::{BytePos, CharPos, Location};
use base::types::{Field, Type, TcType};
use check::completion;

mod support;
use support::{MockEnv, intern, typ};

fn find_type(s: &str, location: Location) -> Result<TcType, ()> {
    let env = MockEnv::new();

    let (mut expr, result) = support::typecheck_expr(s);
    assert!(result.is_ok(), "{}", result.unwrap_err());

    completion::find(&env, &mut expr, location)
}

fn suggest(s: &str, location: Location) -> Result<Vec<String>, ()> {
    let env = MockEnv::new();

    let (mut expr, _result) = support::typecheck_partial_expr(s);
    let mut vec: Vec<String> = {
        completion::suggest(&env, &mut expr, location)
            .into_iter()
            .map(|ident| ident.name)
            .collect()
    };
    vec.sort();

    Ok(vec)
}

#[test]
fn identifier() {
    let env = MockEnv::new();

    let (mut expr, result) = support::typecheck_expr("let abc = 1 in abc");
    assert!(result.is_ok(), "{}", result.unwrap_err());

    let result = completion::find(&env,
                                  &mut expr,
                                  Location {
                                      line: 1,
                                      column: CharPos(16),
                                      absolute: BytePos(0),
                                  });
    let expected = Ok(typ("Int"));
    assert_eq!(result, expected);

    let result = completion::find(&env,
                                  &mut expr,
                                  Location {
                                      line: 1,
                                      column: CharPos(17),
                                      absolute: BytePos(0),
                                  });
    let expected = Ok(typ("Int"));
    assert_eq!(result, expected);

    let result = completion::find(&env,
                                  &mut expr,
                                  Location {
                                      line: 1,
                                      column: CharPos(18),
                                      absolute: BytePos(0),
                                  });
    let expected = Ok(typ("Int"));
    assert_eq!(result, expected);

    let result = completion::find(&env,
                                  &mut expr,
                                  Location {
                                      line: 1,
                                      column: CharPos(19),
                                      absolute: BytePos(0),
                                  });
    assert_eq!(result, Err(()));
}

#[test]
fn literal_string() {
    let result = find_type(r#" "asd" "#,
                           Location {
                               line: 1,
                               column: CharPos(2),
                               absolute: BytePos(0),
                           });
    let expected = Ok(typ("String"));

    assert_eq!(result, expected);
}

#[test]
fn in_let() {
    let result = find_type(r#"
let f x = 1
and g x = "asd"
1
"#,
                           Location {
                               line: 3,
                               column: CharPos(15),
                               absolute: BytePos(0),
                           });
    let expected = Ok(typ("String"));

    assert_eq!(result, expected);
}

#[test]
fn function_call() {
    let result = find_type(r#"
let f x = f x
1
"#,
                           Location {
                               line: 2,
                               column: CharPos(11),
                               absolute: BytePos(11),
                           });
    let expected = Ok(Type::function(vec![typ("a0")], typ("a1")));

    assert_eq!(result, expected);
}

#[test]
fn binop() {
    let env = MockEnv::new();

    let (mut expr, result) = support::typecheck_expr(r#"
let (++) l r =
    l #Int+ 1
    r #Float+ 1.0
    l
1 ++ 2.0
"#);
    assert!(result.is_ok(), "{}", result.unwrap_err());

    let result = completion::find(&env,
                                  &mut expr,
                                  Location {
                                      line: 6,
                                      column: CharPos(4),
                                      absolute: BytePos(0),
                                  });
    let expected = Ok(Type::function(vec![typ("Int"), typ("Float")], typ("Int")));
    assert_eq!(result, expected);

    let result = completion::find(&env,
                                  &mut expr,
                                  Location {
                                      line: 6,
                                      column: CharPos(1),
                                      absolute: BytePos(0),
                                  });
    let expected = Ok(typ("Int"));
    assert_eq!(result, expected);

    let result = completion::find(&env,
                                  &mut expr,
                                  Location {
                                      line: 6,
                                      column: CharPos(6),
                                      absolute: BytePos(123),
                                  });
    let expected = Ok(typ("Float"));
    assert_eq!(result, expected);
}

#[test]
fn field_access() {
    let env = ast::EmptyEnv::new();
    let typ_env = MockEnv::new();

    let (mut expr, result) = support::typecheck_expr(r#"
let r = { x = 1 }
r.x
"#);
    assert!(result.is_ok(), "{}", result.unwrap_err());

    let result = completion::find(&env,
                                  &typ_env,
                                  &mut expr,
                                  Location {
                                      line: 3,
                                      column: CharPos(1),
                                      absolute: BytePos(0),
                                  });
    let expected = Ok(Type::record(vec![],
                                   vec![Field {
                                            name: intern("x"),
                                            typ: typ("Int"),
                                        }]));
    assert_eq!(result, expected);

    let result = completion::find(&env,
                                  &typ_env,
                                  &mut expr,
                                  Location {
                                      line: 3,
                                      column: CharPos(3),
                                      absolute: BytePos(0),
                                  });
    let expected = Ok(typ("Int"));
    assert_eq!(result, expected);
}

#[test]
fn in_record() {
    let result = find_type(r#"
{
    test = 123,
    s = "asd"
}
"#,
                           Location {
                               line: 3,
                               column: CharPos(14),
                               absolute: BytePos(0),
                           });
    let expected = Ok(typ("Int"));

    assert_eq!(result, expected);
}

#[test]
fn suggest_identifier_when_prefix() {
    let result = suggest(r#"
let test = 1
let tes = ""
let aaa = test
te
"#,
                         Location {
                             line: 5,
                             column: CharPos(1),
                             absolute: BytePos(0),
                         });
    let expected = Ok(vec!["tes".into(), "test".into()]);

    assert_eq!(result, expected);
}

#[test]
fn suggest_arguments() {
    let result = suggest(r#"
let f test =
    \test2 -> tes
123
"#,
                         Location {
                             line: 3,
                             column: CharPos(17),
                             absolute: BytePos(0),
                         });
    let expected = Ok(vec!["test".into(), "test2".into()]);

    assert_eq!(result, expected);
}

#[test]
fn suggest_after_unrelated_type_error() {
    let result = suggest(r#"
let record = { aa = 1, ab = 2, c = "" }
1.0 #Int+ 2
record.a
"#,
                         Location {
                             line: 4,
                             column: CharPos(8),
                             absolute: BytePos(0),
                         });
    let expected = Ok(vec!["aa".into(), "ab".into()]);

    assert_eq!(result, expected);
}

#[test]
fn suggest_through_aliases() {
    let result = suggest(r#"
type Test a = { abc: a -> Int }
type Test2 = Test String
let record: Test2 = { abc = \x -> 0 }
record.ab
"#,
                         Location {
                             line: 5,
                             column: CharPos(8),
                             absolute: BytePos(0),
                         });
    let expected = Ok(vec!["abc".into()]);

    assert_eq!(result, expected);
}

#[test]
fn suggest_after_dot() {
    let result = suggest(r#"
let record = { aa = 1, ab = 2, c = "" }
record.
"#,
                         Location {
                             line: 3,
                             column: CharPos(7),
                             absolute: BytePos(50),
                         });
    let expected = Ok(vec!["aa".into(), "ab".into(), "c".into()]);

    assert_eq!(result, expected);
}

#[test]
fn suggest_from_record_unpack() {
    let result = suggest(r#"
let { aa, c } = { aa = 1, ab = 2, c = "" }
a
"#,
                         Location {
                             line: 3,
                             column: CharPos(1),
                             absolute: BytePos(0),
                         });
    let expected = Ok(vec!["aa".into()]);

    assert_eq!(result, expected);
}

#[test]
fn suggest_on_record_in_field_access() {
    let result = suggest(r#"
let record = { aa = 1, ab = 2, c = "" }
record.aa
"#,
                         Location {
                             line: 3,
                             column: CharPos(4),
                             absolute: BytePos(0),
                         });
    let expected = Ok(vec!["record".into()]);

    assert_eq!(result, expected);
}

#[test]
fn suggest_end_of_identifier() {
    let result = suggest(r#"
let abc = 1
let abb = 2
abc
"#,
                         Location {
                             line: 4,
                             column: CharPos(3),
                             absolute: BytePos(0),
                         });
    let expected = Ok(vec!["abc".into()]);

    assert_eq!(result, expected);
}

#[test]
fn suggest_after_identifier() {
    let result = suggest(r#"
let abc = 1
let abb = 2
abc
"#,
                         Location {
                             line: 4,
                             column: CharPos(5),
                             absolute: BytePos(0),
                         });
    let expected = Ok(vec!["abb".into(), "abc".into()]);

    assert_eq!(result, expected);
}
<|endoftext|>


<commit_before>//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

use filter::Filter;

pub struct FilteredIterator<T, F, I>(F, I)
    where F: Filter<T>,
          I: Iterator<Item = T>;

impl<T, F, I> Iterator for FilteredIterator<T, F, I>
    where F: Filter<T>,
          I: Iterator<Item = T>
{
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        while let Some(next) = self.1.next() {
            if self.0.filter(&next) {
                return Some(next);
            }
        }

        None
    }
}

pub trait FilterWith<T, F: Filter<T>> : Iterator<Item = T> + Sized {
    fn filter_with(self, f: F) -> FilteredIterator<T, F, Self>;
}

impl<I, T, F: Filter<T>> FilterWith<T, F> for I
    where I: Iterator<Item = T>
{
    fn filter_with(self, f: F) -> FilteredIterator<T, F, Self> {
        FilteredIterator(f, self)
    }
}

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

    #[test]
    fn test_filter_with() {
        struct Foo;
        impl Filter<u64> for Foo {
            fn filter(&self, u: &u64) -> bool {
                *u > 5
            }
        }

        let foo = Foo;

        let v : Vec<u64> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
            .into_iter()
            .filter_with(foo)
            .collect();

        assert_eq!(v, vec![6, 7, 8, 9]);
    }
}
<commit_msg>Add extension to filter Result<T, E> by predicate(&T)<commit_after>//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

use filter::Filter;

pub struct FilteredIterator<T, F, I>(F, I)
    where F: Filter<T>,
          I: Iterator<Item = T>;

impl<T, F, I> Iterator for FilteredIterator<T, F, I>
    where F: Filter<T>,
          I: Iterator<Item = T>
{
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        while let Some(next) = self.1.next() {
            if self.0.filter(&next) {
                return Some(next);
            }
        }

        None
    }
}

pub trait FilterWith<T, F: Filter<T>> : Iterator<Item = T> + Sized {
    fn filter_with(self, f: F) -> FilteredIterator<T, F, Self>;
}

impl<I, T, F: Filter<T>> FilterWith<T, F> for I
    where I: Iterator<Item = T>
{
    fn filter_with(self, f: F) -> FilteredIterator<T, F, Self> {
        FilteredIterator(f, self)
    }
}

pub struct FilterOksIter<T, E, I, F>(I, F)
    where F: Filter<T>,
          I: Iterator<Item = Result<T, E>>;

impl<T, E, I, F> Iterator for FilterOksIter<T, E, I, F>
    where F: Filter<T>,
          I: Iterator<Item = Result<T, E>>
{
    type Item = Result<T, E>;

    fn next(&mut self) -> Option<Self::Item> {
        while let Some(next) = self.0.next() {
            match next {
                Err(e) => return Some(Err(e)),
                Ok(t)  => if self.1.filter(&t) {
                    return Some(Ok(t));
                }
            }
        }

        None
    }
}

pub trait FilterOks<T, E, I, F> : Iterator<Item = Result<T, E>>
    where I: Iterator<Item = Result<T, E>>,
          F: Filter<T>
{
    fn filter_oks(self, F) -> FilterOksIter<T, E, I, F>;
}

impl<T, E, I, F> FilterOks<T, E, I, F> for I
    where I: Iterator<Item = Result<T, E>>,
          F: Filter<T>
{
    fn filter_oks(self, f: F) -> FilterOksIter<T, E, I, F> {
        FilterOksIter(self, f)
    }
}

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

    #[test]
    fn test_filter_with() {
        struct Foo;
        impl Filter<u64> for Foo {
            fn filter(&self, u: &u64) -> bool {
                *u > 5
            }
        }

        let foo = Foo;

        let v : Vec<u64> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
            .into_iter()
            .filter_with(foo)
            .collect();

        assert_eq!(v, vec![6, 7, 8, 9]);
    }

    #[test]
    fn test_filter_oks() {
        struct Foo;
        impl Filter<u64> for Foo {
            fn filter(&self, u: &u64) -> bool {
                *u > 5
            }
        }

        let foo = Foo;

        let v : Vec<Result<u64, u64>> =
            vec![Ok(1), Err(2), Ok(3), Err(4), Ok(5), Err(6), Ok(7), Err(8), Ok(9), Err(0)]
            .into_iter()
            .filter_oks(foo)
            .collect();

        assert_eq!(v, vec![Err(2), Err(4), Err(6), Ok(7), Err(8), Ok(9), Err(0)]);
    }
}

<|endoftext|>


<commit_before><commit_msg>impl FromIterator for Response<Vec<T>><commit_after><|endoftext|>


<commit_before>use std;
use std::thread;
use std::sync::mpsc;

pub fn prime_filter(iter_size: usize) -> Vec<bool>{
    if iter_size<100{
        slow_prime_filter(iter_size)
    }else{
        prime_filter_section(0, iter_size)
    }
}

fn case_1(y_sq: usize, iter_size: usize)
    -> (usize, Vec<bool>) {
    //n_1 = 4x^2 + y^2 === 1 (mod 4)
    let (mut n_1, mut to_next_n_1) = (y_sq, 4);
    let offset = n_1;
    let mut temp_filter = vec![false; iter_size-offset];
    loop{
        n_1 += to_next_n_1;
        to_next_n_1 += 8;
        match n_1%60{
            _ if n_1 >= iter_size => break,
            1 | 13 | 17 | 29 | 37 | 41 | 49 | 53 => (),
            _ => continue,
        };

        // println!("1: {}", n_1);
        temp_filter[n_1-offset] ^= true;
    };
    (offset, temp_filter)
}
fn case_2(y_sq: usize, iter_size: usize)
    -> (usize, Vec<bool>) {
    //n_2 = 3x^2 + y^2 === 1 (mod 6)
    let (mut n_2, mut to_next_n_2) = (y_sq, 3);
    let offset = n_2.clone();

    let mut temp_filter = vec![false; iter_size-offset];
    loop {
        n_2 += to_next_n_2;
        to_next_n_2 += 6;
        match n_2%60{
            _ if n_2 >= iter_size => break,
            7 | 19 | 31 | 43 => (),
            _ => continue,
        };
        // println!("2: {}", n_2);
        temp_filter[n_2 - offset] ^= true;
    };
    (offset, temp_filter)
}
fn case_3(y_sq: usize, to_next_y_sq: usize, iter_size: usize)
    -> (usize, Vec<bool>) {
    //n_3 = 3x^2 - y^2 === 11 (mod 12)
    let (mut n_3, mut to_next_n_3) = (2*y_sq, 3*to_next_y_sq);
    let offset = n_3;
    let mut temp_filter = vec![false; iter_size - offset];
    loop {
        n_3 += to_next_n_3;
        to_next_n_3 += 6;
        match n_3%60{
            _ if n_3 >= iter_size => break,
            11 | 23 | 47 | 59 => (),
            _ => continue,
        };
        // println!("3: {}", n_3);
        temp_filter[n_3 - offset] ^= true;
    };
    (offset, temp_filter)
}

fn prime_filter_section(min:usize, max: usize) -> Vec<bool>{
    //Sieve of Atkin
    assert!(min<max);
    let mut prime_filter = vec![false; max-min];
    if (min <= 2) & (max > 2) {prime_filter[2-min] = true;}
    if (min <= 3) & (max > 3) {prime_filter[3-min] = true;}
    if (min <= 5) & (max > 5) {prime_filter[5-min] = true;}

    let (mut y_sq, mut to_next_y_sq) = match min {
        0|1 => (1, 3),
        _ => (min*min, 2*min + 1),
    };
    let (tx, rx) = mpsc::channel();
    while y_sq<max {
        if y_sq%2 == 1 {
            spawned_threads += 1;
            let (y_sq, tx) = (y_sq, tx.clone());
            thread::spawn(move || {
                tx.send(case_1(y_sq, max)).unwrap();
            });
        };
        if y_sq%3 == 1 {

            spawned_threads += 1;
            let (y_sq, to_next_y_sq, tx1) = (y_sq, to_next_y_sq, tx.clone());
            thread::spawn(move || {
                tx1.send(case_2(y_sq, max)).unwrap();
            });
            if y_sq*2<iter_size{
                spawned_threads += 1;
                let tx2 = tx.clone();
                thread::spawn(move || {
                    tx2.send(case_3(y_sq, to_next_y_sq, max)).unwrap();
                });
            }
        };
        if spawned_threads>0{
            for mes in rx.try_iter(){
                spawned_threads -= 1;
                let (offset, temp_filter) = mes;
                for flip_i in temp_filter.into_iter().enumerate()
                                        .filter_map(|x| match x {
                                            (i, true) => Some(i),
                                            _ => None,
                                        }){
                    prime_filter[offset + flip_i - min] ^= true;
                }
            }
        }
        while{ //Do-while
            y_sq += to_next_y_sq;
            to_next_y_sq += 2;
            y_sq%6 == 0
        } {};
    };
    while spawned_threads>0{
        for mes in rx.try_iter(){
            spawned_threads -= 1;
            let (offset, temp_filter) = mes;
            for flip_i in temp_filter.into_iter().enumerate()
                                    .filter_map(|x| match x {
                                        (i, true) => Some(i),
                                        _ => None,
                                    }){
                prime_filter[offset + flip_i - min] ^= true;
            }
        }
    }
    //Eliminate non-squarefree numbers
    let mut n_sq = 49; // 7^2
    let mut next_n_sq = 32; //9^2 - 7^2, skip even numbers.
    while n_sq < iter_size {
        let mut non_sq_free = n_sq;
        while non_sq_free < max {
            if non_sq_free >= min {
                prime_filter[non_sq_free - min] = false;
            }
            while{ //Do-while
                non_sq_free += n_sq + n_sq;
                (non_sq_free%3==0) | (non_sq_free%5==0)
            } {};
        };
        while{ //Do-while
            non_sq_free += n_sq + n_sq;
            (non_sq_free%3==0) | (non_sq_free%5==0)
        } {};
    };
    while{ //Do-while
        n_sq += next_n_sq;
        next_n_sq += 8;
        (n_sq%3==0) | (n_sq%5 == 0)
    } {};
    prime_filter
}
#[cfg(test)]
pub fn old_prime_filter(iter_size: usize) -> std::vec::Vec<bool>{
    slow_prime_filter(iter_size)
}

fn slow_prime_filter(iter_size: usize) -> std::vec::Vec<bool>{
    if iter_size < 5 {
         let mut ret = vec![false, false, true, true];
         ret.truncate(iter_size);
         return ret
     }
    let mut prime_filter = vec![true; iter_size];
    prime_filter[0] = false;
    prime_filter[1] = false;
    let mut cur_num = 2;
    'outer: loop{
        for i in (cur_num+1)..iter_size{
            if 0 == i%cur_num { prime_filter[i] = false; }
        }
        cur_num += 1;
        while !prime_filter[cur_num]{
            if cur_num*cur_num > iter_size {
                break 'outer
            }
            cur_num += 1;
        }
    };
    prime_filter
}
<commit_msg>initialize spawned_threads<commit_after>use std;
use std::thread;
use std::sync::mpsc;

pub fn prime_filter(iter_size: usize) -> Vec<bool>{
    if iter_size<100{
        slow_prime_filter(iter_size)
    }else{
        prime_filter_section(0, iter_size)
    }
}

fn case_1(y_sq: usize, iter_size: usize)
    -> (usize, Vec<bool>) {
    //n_1 = 4x^2 + y^2 === 1 (mod 4)
    let (mut n_1, mut to_next_n_1) = (y_sq, 4);
    let offset = n_1;
    let mut temp_filter = vec![false; iter_size-offset];
    loop{
        n_1 += to_next_n_1;
        to_next_n_1 += 8;
        match n_1%60{
            _ if n_1 >= iter_size => break,
            1 | 13 | 17 | 29 | 37 | 41 | 49 | 53 => (),
            _ => continue,
        };

        // println!("1: {}", n_1);
        temp_filter[n_1-offset] ^= true;
    };
    (offset, temp_filter)
}
fn case_2(y_sq: usize, iter_size: usize)
    -> (usize, Vec<bool>) {
    //n_2 = 3x^2 + y^2 === 1 (mod 6)
    let (mut n_2, mut to_next_n_2) = (y_sq, 3);
    let offset = n_2.clone();

    let mut temp_filter = vec![false; iter_size-offset];
    loop {
        n_2 += to_next_n_2;
        to_next_n_2 += 6;
        match n_2%60{
            _ if n_2 >= iter_size => break,
            7 | 19 | 31 | 43 => (),
            _ => continue,
        };
        // println!("2: {}", n_2);
        temp_filter[n_2 - offset] ^= true;
    };
    (offset, temp_filter)
}
fn case_3(y_sq: usize, to_next_y_sq: usize, iter_size: usize)
    -> (usize, Vec<bool>) {
    //n_3 = 3x^2 - y^2 === 11 (mod 12)
    let (mut n_3, mut to_next_n_3) = (2*y_sq, 3*to_next_y_sq);
    let offset = n_3;
    let mut temp_filter = vec![false; iter_size - offset];
    loop {
        n_3 += to_next_n_3;
        to_next_n_3 += 6;
        match n_3%60{
            _ if n_3 >= iter_size => break,
            11 | 23 | 47 | 59 => (),
            _ => continue,
        };
        // println!("3: {}", n_3);
        temp_filter[n_3 - offset] ^= true;
    };
    (offset, temp_filter)
}

fn prime_filter_section(min:usize, max: usize) -> Vec<bool>{
    //Sieve of Atkin
    assert!(min<max);
    let mut prime_filter = vec![false; max-min];
    if (min <= 2) & (max > 2) {prime_filter[2-min] = true;}
    if (min <= 3) & (max > 3) {prime_filter[3-min] = true;}
    if (min <= 5) & (max > 5) {prime_filter[5-min] = true;}

    let (mut y_sq, mut to_next_y_sq) = match min {
        0|1 => (1, 3),
        _ => (min*min, 2*min + 1),
    };
    let mut spawned_threads = 0;
    let (tx, rx) = mpsc::channel();
    while y_sq<max {
        if y_sq%2 == 1 {
            spawned_threads += 1;
            let (y_sq, tx) = (y_sq, tx.clone());
            thread::spawn(move || {
                tx.send(case_1(y_sq, max)).unwrap();
            });
        };
        if y_sq%3 == 1 {

            spawned_threads += 1;
            let (y_sq, to_next_y_sq, tx1) = (y_sq, to_next_y_sq, tx.clone());
            thread::spawn(move || {
                tx1.send(case_2(y_sq, max)).unwrap();
            });
            if y_sq*2<iter_size{
                spawned_threads += 1;
                let tx2 = tx.clone();
                thread::spawn(move || {
                    tx2.send(case_3(y_sq, to_next_y_sq, max)).unwrap();
                });
            }
        };
        if spawned_threads>0{
            for mes in rx.try_iter(){
                spawned_threads -= 1;
                let (offset, temp_filter) = mes;
                for flip_i in temp_filter.into_iter().enumerate()
                                        .filter_map(|x| match x {
                                            (i, true) => Some(i),
                                            _ => None,
                                        }){
                    prime_filter[offset + flip_i - min] ^= true;
                }
            }
        }
        while{ //Do-while
            y_sq += to_next_y_sq;
            to_next_y_sq += 2;
            y_sq%6 == 0
        } {};
    };
    while spawned_threads>0{
        for mes in rx.try_iter(){
            spawned_threads -= 1;
            let (offset, temp_filter) = mes;
            for flip_i in temp_filter.into_iter().enumerate()
                                    .filter_map(|x| match x {
                                        (i, true) => Some(i),
                                        _ => None,
                                    }){
                prime_filter[offset + flip_i - min] ^= true;
            }
        }
    }
    //Eliminate non-squarefree numbers
    let mut n_sq = 49; // 7^2
    let mut next_n_sq = 32; //9^2 - 7^2, skip even numbers.
    while n_sq < iter_size {
        let mut non_sq_free = n_sq;
        while non_sq_free < max {
            if non_sq_free >= min {
                prime_filter[non_sq_free - min] = false;
            }
            while{ //Do-while
                non_sq_free += n_sq + n_sq;
                (non_sq_free%3==0) | (non_sq_free%5==0)
            } {};
        };
        while{ //Do-while
            non_sq_free += n_sq + n_sq;
            (non_sq_free%3==0) | (non_sq_free%5==0)
        } {};
    };
    while{ //Do-while
        n_sq += next_n_sq;
        next_n_sq += 8;
        (n_sq%3==0) | (n_sq%5 == 0)
    } {};
    prime_filter
}
#[cfg(test)]
pub fn old_prime_filter(iter_size: usize) -> std::vec::Vec<bool>{
    slow_prime_filter(iter_size)
}

fn slow_prime_filter(iter_size: usize) -> std::vec::Vec<bool>{
    if iter_size < 5 {
         let mut ret = vec![false, false, true, true];
         ret.truncate(iter_size);
         return ret
     }
    let mut prime_filter = vec![true; iter_size];
    prime_filter[0] = false;
    prime_filter[1] = false;
    let mut cur_num = 2;
    'outer: loop{
        for i in (cur_num+1)..iter_size{
            if 0 == i%cur_num { prime_filter[i] = false; }
        }
        cur_num += 1;
        while !prime_filter[cur_num]{
            if cur_num*cur_num > iter_size {
                break 'outer
            }
            cur_num += 1;
        }
    };
    prime_filter
}
<|endoftext|>


<commit_before>use std::fmt;
use std::cell::RefCell;

/// Format all iterator elements lazily, separated by `sep`.
///
/// The format value can only be formatted once, after that the iterator is
/// exhausted.
///
/// See [`.format_with()`](../trait.Itertools.html#method.format_with) for more information.
#[derive(Clone)]
pub struct FormatWith<'a, I, F> {
    sep: &'a str,
    /// FormatWith uses interior mutability because Display::fmt takes &self.
    inner: RefCell<Option<(I, F)>>,
}

/// Format all iterator elements lazily, separated by `sep`.
///
/// The format value can only be formatted once, after that the iterator is
/// exhausted.
///
/// See [`.format()`](../trait.Itertools.html#method.format)
/// for more information.
#[derive(Clone)]
pub struct Format<'a, I> {
    sep: &'a str,
    /// Format uses interior mutability because Display::fmt takes &self.
    inner: RefCell<Option<I>>,
}

pub fn new_format<I, F>(iter: I, separator: &str, f: F) -> FormatWith<'_, I, F>
    where I: Iterator,
          F: FnMut(I::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result
{
    FormatWith {
        sep: separator,
        inner: RefCell::new(Some((iter, f))),
    }
}

pub fn new_format_default<I>(iter: I, separator: &str) -> Format<'_, I>
    where I: Iterator,
{
    Format {
        sep: separator,
        inner: RefCell::new(Some(iter)),
    }
}

impl<'a, I, F> fmt::Display for FormatWith<'a, I, F>
    where I: Iterator,
          F: FnMut(I::Item, &mut dyn  FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let (mut iter, mut format) = match self.inner.borrow_mut().take() {
            Some(t) => t,
            None => panic!("FormatWith: was already formatted once"),
        };

        if let Some(fst) = iter.next() {
            format(fst, &mut |disp: &dyn fmt::Display| disp.fmt(f))?;
            for elt in iter {
                if !self.sep.is_empty() {

                    f.write_str(self.sep)?;
                }
                format(elt, &mut |disp: &dyn fmt::Display| disp.fmt(f))?;
            }
        }
        Ok(())
    }
}

impl<'a, I> Format<'a, I>
    where I: Iterator,
{
    fn format<F>(&self, f: &mut fmt::Formatter, mut cb: F) -> fmt::Result
        where F: FnMut(&I::Item, &mut fmt::Formatter) -> fmt::Result,
    {
        let mut iter = match self.inner.borrow_mut().take() {
            Some(t) => t,
            None => panic!("Format: was already formatted once"),
        };

        if let Some(fst) = iter.next() {
            cb(&fst, f)?;
            for elt in iter {
                if !self.sep.is_empty() {
                    f.write_str(self.sep)?;
                }
                cb(&elt, f)?;
            }
        }
        Ok(())
    }
}

macro_rules! impl_format {
    ($($fmt_trait:ident)*) => {
        $(
            impl<'a, I> fmt::$fmt_trait for Format<'a, I>
                where I: Iterator,
                      I::Item: fmt::$fmt_trait,
            {
                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                    self.format(f, fmt::$fmt_trait::fmt)
                }
            }
        )*
    }
}

impl_format!{Display Debug
             UpperExp LowerExp UpperHex LowerHex Octal Binary Pointer}
<commit_msg>Use try_for_each<commit_after>use std::fmt;
use std::cell::RefCell;

/// Format all iterator elements lazily, separated by `sep`.
///
/// The format value can only be formatted once, after that the iterator is
/// exhausted.
///
/// See [`.format_with()`](../trait.Itertools.html#method.format_with) for more information.
#[derive(Clone)]
pub struct FormatWith<'a, I, F> {
    sep: &'a str,
    /// FormatWith uses interior mutability because Display::fmt takes &self.
    inner: RefCell<Option<(I, F)>>,
}

/// Format all iterator elements lazily, separated by `sep`.
///
/// The format value can only be formatted once, after that the iterator is
/// exhausted.
///
/// See [`.format()`](../trait.Itertools.html#method.format)
/// for more information.
#[derive(Clone)]
pub struct Format<'a, I> {
    sep: &'a str,
    /// Format uses interior mutability because Display::fmt takes &self.
    inner: RefCell<Option<I>>,
}

pub fn new_format<I, F>(iter: I, separator: &str, f: F) -> FormatWith<'_, I, F>
    where I: Iterator,
          F: FnMut(I::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result
{
    FormatWith {
        sep: separator,
        inner: RefCell::new(Some((iter, f))),
    }
}

pub fn new_format_default<I>(iter: I, separator: &str) -> Format<'_, I>
    where I: Iterator,
{
    Format {
        sep: separator,
        inner: RefCell::new(Some(iter)),
    }
}

impl<'a, I, F> fmt::Display for FormatWith<'a, I, F>
    where I: Iterator,
          F: FnMut(I::Item, &mut dyn  FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let (mut iter, mut format) = match self.inner.borrow_mut().take() {
            Some(t) => t,
            None => panic!("FormatWith: was already formatted once"),
        };

        if let Some(fst) = iter.next() {
            format(fst, &mut |disp: &dyn fmt::Display| disp.fmt(f))?;
            iter.try_for_each(|elt| {
                if !self.sep.is_empty() {
                    f.write_str(self.sep)?;
                }
                format(elt, &mut |disp: &dyn fmt::Display| disp.fmt(f))
            })?;
        }
        Ok(())
    }
}

impl<'a, I> Format<'a, I>
    where I: Iterator,
{
    fn format<F>(&self, f: &mut fmt::Formatter, mut cb: F) -> fmt::Result
        where F: FnMut(&I::Item, &mut fmt::Formatter) -> fmt::Result,
    {
        let mut iter = match self.inner.borrow_mut().take() {
            Some(t) => t,
            None => panic!("Format: was already formatted once"),
        };

        if let Some(fst) = iter.next() {
            cb(&fst, f)?;
            iter.try_for_each(|elt| {
                if !self.sep.is_empty() {
                    f.write_str(self.sep)?;
                }
                cb(&elt, f)
            })?;
        }
        Ok(())
    }
}

macro_rules! impl_format {
    ($($fmt_trait:ident)*) => {
        $(
            impl<'a, I> fmt::$fmt_trait for Format<'a, I>
                where I: Iterator,
                      I::Item: fmt::$fmt_trait,
            {
                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                    self.format(f, fmt::$fmt_trait::fmt)
                }
            }
        )*
    }
}

impl_format!{Display Debug
             UpperExp LowerExp UpperHex LowerHex Octal Binary Pointer}
<|endoftext|>


<commit_before>// Dependency Graph Library in Rust

//! dglr is a Dependency Graph Library in Rust.
//! In short, you register elements and their dependencies, and then
//! ask for the dependencies of any element in an order that satisfies.
//!
//! Elements are simply &str strings.  You register them with
//! register_dependency() or register_dependencies().
//!
//! Dependenies are (currently) just a list of other elements that
//! the element in question depends on.  [In the future, we may add
//! boolean logic, but currently they are all AND-ed together].
//!
//! Then iterate over .iter() to get the ordered dependencies, and
//! the library does the magic and returns an order which will work.
//! It is possible that other orders also work, but the library's
//! algorithm is deterministic, so you'll always get the same
//! particular one.

#![crate_name = "dglr"]
#![crate_type = "lib"]

// Required for log and rustdoc:
#![feature(phase)]
#[phase(plugin, link)]

extern crate log;

use std::collections::{HashMap,HashSet};
use std::collections::hash_map::{Occupied,Vacant};
use std::iter::{Iterator};
#[allow(unused_imports)]
use std::task;

/// This is the dependency graph.  You can create it yourself, or
/// use the convenience methods of new(), register_dependency() and
/// register_dependencies() to build one up (that must be mutable).
pub struct DepGraph {
    /// List of dependencies.  Key is the element, values are the
    /// other elements that the key element depends upon.
    pub dependencies: HashMap<String,Vec<String>>,

    // (private) target we are trying to satisfy
    target: Option<String>,

    // (private) elements already satisfied
    satisfied: HashSet<String>,

    // (private) current path, for cycle detection
    curpath: HashSet<String>,
}

pub struct DepGraphIterator<'a> {
    depgraph: &'a mut DepGraph
}
pub struct DepGraphSatisfyingIterator<'a> {
    depgraph: &'a mut DepGraph
}

impl DepGraph {

    /// Create an empty DepGraph.
    pub fn new() -> DepGraph
    {
        DepGraph {
            dependencies: HashMap::new(),
            target: None,
            curpath: HashSet::new(),
            satisfied: HashSet::new(),
        }
    }

    /// Add a dependency to a DepGraph.  The thing does not need
    /// to pre-exist, nor do the dependency elements.  But if the
    /// thing does pre-exist, the depends_on will be added to its
    /// existing dependency list.
    pub fn register_dependency<'a>( &mut self,
                                thing: &'a str,
                                depends_on: &'a str )
    {
        match self.dependencies.entry( String::from_str(thing) ) {
            Vacant(entry) => { entry.set( vec![String::from_str(depends_on)] ); },
            Occupied(mut entry) => { (*entry.get_mut()).push(String::from_str(depends_on)); },
        }
    }

    /// Add multiple dependencies of one thing to a DepGraph.  The
    /// thing does not need to pre-exist, nor do the dependency elements.
    /// But if the thing does pre-exist, the depends_on will be added
    /// to its existing dependency list.
    pub fn register_dependencies<'a>( &mut self,
                                  thing: &'a str,
                                  depends_on: &'a[&'a str] )
    {
        let newvec: Vec<String> = depends_on.iter().map(
            |s| String::from_str(*s)).collect();

        match self.dependencies.entry( String::from_str(thing) ) {
            Vacant(entry) => { entry.set( newvec.clone() ); },
            Occupied(mut entry) => { (*entry.get_mut()).push_all(newvec.as_slice()); },
        }
    }

    pub fn set_target<'a>( &mut self, target: &'a str )
    {
        self.target = Some(String::from_str(target));
    }

    pub fn mark_as_satisfied<'a>( &mut self,
                                   things: &'a[&'a str] )
    {
        for thing in things.iter() {
            self.satisfied.insert(String::from_str(*thing));
        }
    }

    fn get_next_dependency(&mut self, thing: &String) -> String
    {
        if self.curpath.contains(thing) {
            panic!("Circular dependency graph at {}",thing);
        }
        self.curpath.insert(thing.clone());

        let deplist = match self.dependencies.find(thing) {
            None => return thing.clone(),
            Some(deplist) => deplist.clone() // ouch
        };

        for n in deplist.iter() {
            if self.satisfied.contains(n) {
                continue;
            }
            return self.get_next_dependency(n);
        }
        // things dependencies are satisfied
        thing.clone()
    }

    pub fn iter<'a>(&'a mut self) -> DepGraphIterator<'a>
    {
        DepGraphIterator {
            depgraph: self
        }
    }

    pub fn satisfying_iter<'a>(&'a mut self) -> DepGraphSatisfyingIterator<'a>
    {
        DepGraphSatisfyingIterator {
            depgraph: self
        }
    }
}

impl<'a> Iterator<String> for DepGraphIterator<'a> {
    fn next(&mut self) -> Option<String>
    {
        let thing = match self.depgraph.target {
            None => return None,
            Some(ref thing) => thing.clone()
        };
        if self.depgraph.satisfied.contains(&thing) {
            return None;
        }
        self.depgraph.curpath.clear();
        Some(self.depgraph.get_next_dependency(&thing))
    }
}

impl<'a> Iterator<String> for DepGraphSatisfyingIterator<'a> {
    fn next(&mut self) -> Option<String>
    {
        let thing = match self.depgraph.target {
            None => return None,
            Some(ref thing) => thing.clone()
        };
        if self.depgraph.satisfied.contains(&thing) {
            return None;
        }
        self.depgraph.curpath.clear();
        let next = self.depgraph.get_next_dependency(&thing);
        self.depgraph.mark_as_satisfied([next.as_slice()]);
        Some(next)
    }
}

#[test]
fn dglr_test_branching() {
    let mut depgraph: DepGraph = DepGraph::new();

    depgraph.register_dependencies("a",&["b","c","d"]);
    depgraph.register_dependency("b","d");
    depgraph.register_dependencies("c",&["e","m","g"]);
    depgraph.register_dependency("e","f");
    depgraph.register_dependency("g","h");
    depgraph.register_dependency("h","i");
    depgraph.register_dependencies("i",&["j","k"]);
    depgraph.register_dependencies("k",&["l","m"]);
    depgraph.register_dependency("m","n");

    depgraph.set_target("a");

    let mut results: Vec<String> = Vec::new();

    loop {
        // detect infinite looping bugs
        assert!(results.len() < 30);

        let thing = match depgraph.iter().next() {
            Some(x) => x,
            None => break,
        };
        depgraph.mark_as_satisfied([thing.as_slice()]);
        results.push(thing);
    }

    assert!( results == vec![String::from_str("d"),
                             String::from_str("b"),
                             String::from_str("f"),
                             String::from_str("e"),
                             String::from_str("n"),
                             String::from_str("m"),
                             String::from_str("j"),
                             String::from_str("l"),
                             String::from_str("k"),
                             String::from_str("i"),
                             String::from_str("h"),
                             String::from_str("g"),
                             String::from_str("c"),
                             String::from_str("a")] );
    //info!("Deps of a = {}",results);
}

#[test]
fn dglr_test_satisfying() {
    let mut depgraph: DepGraph = DepGraph::new();

    depgraph.register_dependencies("a",&["b","c","d"]);
    depgraph.register_dependency("b","d");
    depgraph.register_dependencies("c",&["e"]);

    depgraph.set_target("a");

    let mut results: Vec<String> = Vec::new();

    for thing in depgraph.satisfying_iter() {
        // detect infinite looping bugs
        assert!(results.len() < 30);
        results.push(thing);
    }

    assert!( results == vec![String::from_str("d"),
                             String::from_str("b"),
                             String::from_str("e"),
                             String::from_str("c"),
                             String::from_str("a")] );
    //info!("Deps of a = {}",results);
}

#[test]
fn dglr_test_circular() {

    let task_result = task::try(proc() {
        let mut depgraph: DepGraph = DepGraph::new();
        depgraph.register_dependency("a","b");
        depgraph.register_dependency("b","c");
        depgraph.register_dependency("c","a");
        depgraph.set_target("a");

        let mut results: Vec<String> = Vec::new();

        loop {
            // Detect infinite looping bugs by
            // breaking out successfully (successful
            // proc() means failed test!)
            if results.len() >= 30 { break; }

            let thing = match depgraph.iter().next() {
                Some(x) => x,
                None => break,
            };
            depgraph.mark_as_satisfied([thing.as_slice()]);
            results.push(thing);
        }
    });
    match task_result {
        Ok(_) => panic!("Should have failed at the circular dependency!"),
        Err(_) => () //info!("Successfully detected the circular dependency (ignore task failure)"),
    };
}

#[test]
fn dglr_test_satisfied_stoppage() {

    let mut depgraph: DepGraph = DepGraph::new();
    depgraph.register_dependencies("superconn", []);
    depgraph.register_dependencies("owneruser", ["superconn"]);
    depgraph.register_dependencies("appuser", ["superconn"]);
    depgraph.register_dependencies("database", ["owneruser"]);
    depgraph.register_dependencies("ownerconn", ["database","owneruser"]);
    depgraph.register_dependencies("adminconn", ["database"]);
    depgraph.register_dependencies("extensions", ["database","adminconn"]);
    depgraph.register_dependencies("schema_table", ["database","ownerconn"]);
    depgraph.register_dependencies("schemas", ["ownerconn","extensions","schema_table","appuser"]);
    depgraph.register_dependencies("appconn", ["database","appuser","schemas"]);

    depgraph.set_target("appconn");
    depgraph.mark_as_satisfied(["owneruser","appuser"]);

    let mut results: Vec<String> = Vec::new();

    loop {
        assert!(results.len() < 30);

        let thing = match depgraph.iter().next() {
            Some(x) => x,
            None => break,
        };
        depgraph.mark_as_satisfied([thing.as_slice()]);
        results.push(thing);
    }
    assert!( !results.contains(&String::from_str("superconn")) );
}
<commit_msg>upstream rust: updated<commit_after>// Dependency Graph Library in Rust

//! dglr is a Dependency Graph Library in Rust.
//! In short, you register elements and their dependencies, and then
//! ask for the dependencies of any element in an order that satisfies.
//!
//! Elements are simply &str strings.  You register them with
//! register_dependency() or register_dependencies().
//!
//! Dependenies are (currently) just a list of other elements that
//! the element in question depends on.  [In the future, we may add
//! boolean logic, but currently they are all AND-ed together].
//!
//! Then iterate over .iter() to get the ordered dependencies, and
//! the library does the magic and returns an order which will work.
//! It is possible that other orders also work, but the library's
//! algorithm is deterministic, so you'll always get the same
//! particular one.

#![crate_name = "dglr"]
#![crate_type = "lib"]

// Required for log and rustdoc:
#![feature(phase)]
#[phase(plugin, link)]

extern crate log;

use std::collections::{HashMap,HashSet};
use std::collections::hash_map::{Occupied,Vacant};
use std::iter::{Iterator};
#[allow(unused_imports)]
use std::task;

/// This is the dependency graph.  You can create it yourself, or
/// use the convenience methods of new(), register_dependency() and
/// register_dependencies() to build one up (that must be mutable).
pub struct DepGraph {
    /// List of dependencies.  Key is the element, values are the
    /// other elements that the key element depends upon.
    pub dependencies: HashMap<String,Vec<String>>,

    // (private) target we are trying to satisfy
    target: Option<String>,

    // (private) elements already satisfied
    satisfied: HashSet<String>,

    // (private) current path, for cycle detection
    curpath: HashSet<String>,
}

pub struct DepGraphIterator<'a> {
    depgraph: &'a mut DepGraph
}
pub struct DepGraphSatisfyingIterator<'a> {
    depgraph: &'a mut DepGraph
}

impl DepGraph {

    /// Create an empty DepGraph.
    pub fn new() -> DepGraph
    {
        DepGraph {
            dependencies: HashMap::new(),
            target: None,
            curpath: HashSet::new(),
            satisfied: HashSet::new(),
        }
    }

    /// Add a dependency to a DepGraph.  The thing does not need
    /// to pre-exist, nor do the dependency elements.  But if the
    /// thing does pre-exist, the depends_on will be added to its
    /// existing dependency list.
    pub fn register_dependency<'a>( &mut self,
                                thing: &'a str,
                                depends_on: &'a str )
    {
        match self.dependencies.entry( String::from_str(thing) ) {
            Vacant(entry) => { entry.set( vec![String::from_str(depends_on)] ); },
            Occupied(mut entry) => { (*entry.get_mut()).push(String::from_str(depends_on)); },
        }
    }

    /// Add multiple dependencies of one thing to a DepGraph.  The
    /// thing does not need to pre-exist, nor do the dependency elements.
    /// But if the thing does pre-exist, the depends_on will be added
    /// to its existing dependency list.
    pub fn register_dependencies<'a>( &mut self,
                                  thing: &'a str,
                                  depends_on: &'a[&'a str] )
    {
        let newvec: Vec<String> = depends_on.iter().map(
            |s| String::from_str(*s)).collect();

        match self.dependencies.entry( String::from_str(thing) ) {
            Vacant(entry) => { entry.set( newvec.clone() ); },
            Occupied(mut entry) => { (*entry.get_mut()).push_all(newvec.as_slice()); },
        }
    }

    pub fn set_target<'a>( &mut self, target: &'a str )
    {
        self.target = Some(String::from_str(target));
    }

    pub fn mark_as_satisfied<'a>( &mut self,
                                   things: &'a[&'a str] )
    {
        for thing in things.iter() {
            self.satisfied.insert(String::from_str(*thing));
        }
    }

    fn get_next_dependency(&mut self, thing: &String) -> String
    {
        if self.curpath.contains(thing) {
            panic!("Circular dependency graph at {}",thing);
        }
        self.curpath.insert(thing.clone());

        let deplist = match self.dependencies.get(thing) {
            None => return thing.clone(),
            Some(deplist) => deplist.clone() // ouch
        };

        for n in deplist.iter() {
            if self.satisfied.contains(n) {
                continue;
            }
            return self.get_next_dependency(n);
        }
        // things dependencies are satisfied
        thing.clone()
    }

    pub fn iter<'a>(&'a mut self) -> DepGraphIterator<'a>
    {
        DepGraphIterator {
            depgraph: self
        }
    }

    pub fn satisfying_iter<'a>(&'a mut self) -> DepGraphSatisfyingIterator<'a>
    {
        DepGraphSatisfyingIterator {
            depgraph: self
        }
    }
}

impl<'a> Iterator<String> for DepGraphIterator<'a> {
    fn next(&mut self) -> Option<String>
    {
        let thing = match self.depgraph.target {
            None => return None,
            Some(ref thing) => thing.clone()
        };
        if self.depgraph.satisfied.contains(&thing) {
            return None;
        }
        self.depgraph.curpath.clear();
        Some(self.depgraph.get_next_dependency(&thing))
    }
}

impl<'a> Iterator<String> for DepGraphSatisfyingIterator<'a> {
    fn next(&mut self) -> Option<String>
    {
        let thing = match self.depgraph.target {
            None => return None,
            Some(ref thing) => thing.clone()
        };
        if self.depgraph.satisfied.contains(&thing) {
            return None;
        }
        self.depgraph.curpath.clear();
        let next = self.depgraph.get_next_dependency(&thing);
        self.depgraph.mark_as_satisfied(&[next.as_slice()]);
        Some(next)
    }
}

#[test]
fn dglr_test_branching() {
    let mut depgraph: DepGraph = DepGraph::new();

    depgraph.register_dependencies("a",&["b","c","d"]);
    depgraph.register_dependency("b","d");
    depgraph.register_dependencies("c",&["e","m","g"]);
    depgraph.register_dependency("e","f");
    depgraph.register_dependency("g","h");
    depgraph.register_dependency("h","i");
    depgraph.register_dependencies("i",&["j","k"]);
    depgraph.register_dependencies("k",&["l","m"]);
    depgraph.register_dependency("m","n");

    depgraph.set_target("a");

    let mut results: Vec<String> = Vec::new();

    loop {
        // detect infinite looping bugs
        assert!(results.len() < 30);

        let thing = match depgraph.iter().next() {
            Some(x) => x,
            None => break,
        };
        depgraph.mark_as_satisfied([thing.as_slice()]);
        results.push(thing);
    }

    assert!( results == vec![String::from_str("d"),
                             String::from_str("b"),
                             String::from_str("f"),
                             String::from_str("e"),
                             String::from_str("n"),
                             String::from_str("m"),
                             String::from_str("j"),
                             String::from_str("l"),
                             String::from_str("k"),
                             String::from_str("i"),
                             String::from_str("h"),
                             String::from_str("g"),
                             String::from_str("c"),
                             String::from_str("a")] );
    //info!("Deps of a = {}",results);
}

#[test]
fn dglr_test_satisfying() {
    let mut depgraph: DepGraph = DepGraph::new();

    depgraph.register_dependencies("a",&["b","c","d"]);
    depgraph.register_dependency("b","d");
    depgraph.register_dependencies("c",&["e"]);

    depgraph.set_target("a");

    let mut results: Vec<String> = Vec::new();

    for thing in depgraph.satisfying_iter() {
        // detect infinite looping bugs
        assert!(results.len() < 30);
        results.push(thing);
    }

    assert!( results == vec![String::from_str("d"),
                             String::from_str("b"),
                             String::from_str("e"),
                             String::from_str("c"),
                             String::from_str("a")] );
    //info!("Deps of a = {}",results);
}

#[test]
fn dglr_test_circular() {

    let task_result = task::try(proc() {
        let mut depgraph: DepGraph = DepGraph::new();
        depgraph.register_dependency("a","b");
        depgraph.register_dependency("b","c");
        depgraph.register_dependency("c","a");
        depgraph.set_target("a");

        let mut results: Vec<String> = Vec::new();

        loop {
            // Detect infinite looping bugs by
            // breaking out successfully (successful
            // proc() means failed test!)
            if results.len() >= 30 { break; }

            let thing = match depgraph.iter().next() {
                Some(x) => x,
                None => break,
            };
            depgraph.mark_as_satisfied([thing.as_slice()]);
            results.push(thing);
        }
    });
    match task_result {
        Ok(_) => panic!("Should have failed at the circular dependency!"),
        Err(_) => () //info!("Successfully detected the circular dependency (ignore task failure)"),
    };
}

#[test]
fn dglr_test_satisfied_stoppage() {

    let mut depgraph: DepGraph = DepGraph::new();
    depgraph.register_dependencies("superconn", []);
    depgraph.register_dependencies("owneruser", ["superconn"]);
    depgraph.register_dependencies("appuser", ["superconn"]);
    depgraph.register_dependencies("database", ["owneruser"]);
    depgraph.register_dependencies("ownerconn", ["database","owneruser"]);
    depgraph.register_dependencies("adminconn", ["database"]);
    depgraph.register_dependencies("extensions", ["database","adminconn"]);
    depgraph.register_dependencies("schema_table", ["database","ownerconn"]);
    depgraph.register_dependencies("schemas", ["ownerconn","extensions","schema_table","appuser"]);
    depgraph.register_dependencies("appconn", ["database","appuser","schemas"]);

    depgraph.set_target("appconn");
    depgraph.mark_as_satisfied(["owneruser","appuser"]);

    let mut results: Vec<String> = Vec::new();

    loop {
        assert!(results.len() < 30);

        let thing = match depgraph.iter().next() {
            Some(x) => x,
            None => break,
        };
        depgraph.mark_as_satisfied([thing.as_slice()]);
        results.push(thing);
    }
    assert!( !results.contains(&String::from_str("superconn")) );
}
<|endoftext|>


<commit_before>use prettytable::{format, Table};
use prettytable::row::Row;
use prettytable::cell::Cell;

use rustc_demangle;
use termcolor::{Buffer, BufferWriter, WriteColor};
use std::io::Write;
use termcolor::Color::*;

use Opt;

macro_rules! color_bold {
    ($fmt:ident, $color:ident, $str:expr) => ({
    $fmt.set_color(::termcolor::ColorSpec::new().set_bold(true).set_fg(Some($color)))?;
    write!($fmt, "{}", $str)?;
    $fmt.reset()
    })
}

macro_rules! color {
    ($fmt:ident, $color:ident, $str:expr) => ({
        $fmt.set_color(::termcolor::ColorSpec::new().set_fg(Some($color)))?;
        write!($fmt, "{}", $str)?;
        $fmt.reset()
    })
}

macro_rules! color_dim {
    ($fmt:ident, $color:ident, $str:expr) => ({
        $fmt.set_color(::termcolor::ColorSpec::new().set_fg(Some($color)).set_intense(false))?;
        write!($fmt, "{}", $str)?;
        $fmt.reset()
    })
}

pub fn new_table(title: Row) -> Table {
    let sep = format::LineSeparator::new('-', '|', ' ', ' ');

    let format = format::FormatBuilder::new()
        .column_separator(' ')
        .borders(' ')
        .separators(&[], sep)
        .padding(1, 1)
        .build();

    let mut phdr_table = Table::new();
    phdr_table.set_titles(title);
    phdr_table.set_format(format);
    phdr_table
}

pub fn string_cell (opt: &Opt, string: &str) -> Cell {
    if string.is_empty() {
        Cell::new(&"")
    } else {
        let mut s = if opt.demangle {
            rustc_demangle::demangle(string).to_string()
        } else {
            string.into()
        };
        s.truncate(opt.truncate);
        if s.len() < string.len() { s += "…"; }
        Cell::new(&s).style_spec("FYb")
    }
}

pub fn str_cell (s: &str) -> Cell {
    if s.is_empty() {
        Cell::new(&"")
    } else {
        Cell::new(s).style_spec("FYb")
    }
}

pub fn idx_cell (i: usize) -> Cell {
    let cell = Cell::new(&i.to_string());
    if i % 2 == 0 { cell.style_spec("FdBw") } else { cell.style_spec("FwBd") }
}

pub fn addr_cell (addr: u64) -> Cell {
    Cell::new(&format!("{:>16x} ", addr)).style_spec("Frr")
}

pub fn offsetx_cell (offset: u64) -> Cell {
    Cell::new(&format!("{:#x} ", offset)).style_spec("Fy")
}

pub fn addrx_cell (addr: u64) -> Cell {
    Cell::new(&format!("{:#x} ", addr)).style_spec("Fr")
}

pub fn memx_cell (maddr: u64) -> Cell {
    Cell::new(&format!("{:<#x} ", maddr)).style_spec("bFr")
}

pub fn sz_cell (size: u64) -> Cell {
    Cell::new(&format!("{:<#x} ", size)).style_spec("Fg")
}

pub fn memsz_cell (memsz: u64) -> Cell {
    Cell::new(&format!("{:<#x} ", memsz)).style_spec("bFg")
}

pub fn x_cell (num: u64) -> Cell {
    Cell::new(&format!("{:#x}", num))
}

pub fn cell<T: ToString> (n: T) -> Cell {
    Cell::new(&format!("{}", n.to_string()))
}

pub fn bool_cell (b: bool) -> Cell {
    let cell = Cell::new(&format!("{} ", b));
    if b { cell.style_spec("bFg") } else { cell.style_spec("bFr") }
}

pub fn fmt_hdr(fmt: &mut Buffer, name: &str) -> ::std::io::Result<()> {
    color!(fmt, White, name)
}

pub fn fmt_hdr_size (fmt: &mut Buffer, name: &str, size: usize) -> ::std::io::Result<()> {
    color_dim!(fmt, White, format!("{}({})", name, size))
}

pub fn fmt_header (fmt: &mut Buffer, name: &str, size: usize) -> ::std::io::Result<()> {
    fmt_hdr_size(fmt, name, size)?;
    writeln!(fmt, ":")?;
    Ok(())
}

pub fn fmt_addr (fmt: &mut Buffer, addr: u64) -> ::std::io::Result<()> {
    color!(fmt, Red, format!("{:x}",addr))
}

pub fn fmt_addr_right (fmt: &mut Buffer, addr: u64) -> ::std::io::Result<()> {
    color!(fmt, Red, format!("{:>16x}",addr))
}

pub fn fmt_addrx (fmt: &mut Buffer, addr: u64) -> ::std::io::Result<()> {
    color!(fmt, Red, format!("{:#x}",addr))
}

pub fn fmt_isize (fmt: &mut Buffer, i: isize) -> ::std::io::Result<()> {
    color!(fmt, Red, format!("{}",i))
}

pub fn fmt_off (fmt: &mut Buffer, off: u64) -> ::std::io::Result<()> {
    color!(fmt, Yellow, format!("{:#x}",off))
}

pub fn fmt_string (fmt: &mut Buffer, opt: &Opt, s: &str) -> ::std::io::Result<()> {
    color_bold!(fmt, Yellow, if opt.demangle {
        rustc_demangle::demangle(s).to_string()
    } else {
        s.into()
    })
}

pub fn fmt_str_option(fmt: &mut Buffer, s: &Option<&str>) -> ::std::io::Result<()> {
    if let &Some(ref s) = s{
        fmt_str(fmt, s)
    } else {
        fmt_name_dim(fmt, "None")
    }
}

pub fn fmt_str (fmt: &mut Buffer, s: &str) -> ::std::io::Result<()> {
    color_bold!(fmt, Yellow, s)
}

pub fn fmt_bool (fmt: &mut Buffer, b: bool) -> ::std::io::Result<()> {
    if b {
        fmt.set_color(::termcolor::ColorSpec::new().set_bold(true).set_intense(true).set_fg(Some(Green)))?;
    } else {
        fmt.set_color(::termcolor::ColorSpec::new().set_bold(true).set_intense(true).set_fg(Some(Red)))?;
    }
    write!(fmt, "{}", b)?;
    fmt.reset()
}

pub fn fmt_name_bold (fmt: &mut Buffer, s: &str) -> ::std::io::Result<()> {
    color_bold!(fmt, White, s)
}

pub fn fmt_name_dim (fmt: &mut Buffer, s: &str) -> ::std::io::Result<()> {
    color_dim!(fmt, White, s)
}

pub fn fmt_name_color(fmt: &mut Buffer, s: &str, color: ::termcolor::Color) -> ::std::io::Result<()> {
    color!(fmt, color, s)
}

pub fn fmt_lib (fmt: &mut Buffer, s: &str) -> ::std::io::Result<()> {
    color_bold!(fmt, Blue, s)
}

pub fn fmt_lib_right (fmt: &mut Buffer, s: &str) -> ::std::io::Result<()> {
    color_bold!(fmt, Blue, format!("{:>16}",s))
}

pub fn fmt_cyan (fmt: &mut Buffer, s: &str) -> ::std::io::Result<()> {
    color!(fmt, Cyan, s)
}

pub fn fmt_sz (fmt: &mut Buffer, fmt_sz: u64) -> ::std::io::Result<()> {
    color!(fmt, Green, format!("{:#x}", fmt_sz))
}

pub fn fmt_idx (fmt: &mut Buffer, i: usize) -> ::std::io::Result<()> {
    let index = format!("{:>4}", i);
    if i % 2 == 0 {
        fmt.set_color(::termcolor::ColorSpec::new().set_fg(Some(White)))?;
    } else {
        fmt.set_color(::termcolor::ColorSpec::new().set_bg(Some(White)).set_fg(Some(Black)))?;
    }
    write!(fmt, "{}", index)?;
    fmt.reset()
}

pub fn flush(fmt: &mut Buffer, writer: &BufferWriter, table: Table, color: bool) -> ::std::io::Result<()> {
    writer.print(fmt)?;
    fmt.clear();
    table.print_tty(color);
    Ok(())
}
<commit_msg>format: fix annoying demangled truncation bug<commit_after>use prettytable::{format, Table};
use prettytable::row::Row;
use prettytable::cell::Cell;

use rustc_demangle;
use termcolor::{Buffer, BufferWriter, WriteColor};
use std::io::Write;
use termcolor::Color::*;

use Opt;

macro_rules! color_bold {
    ($fmt:ident, $color:ident, $str:expr) => ({
    $fmt.set_color(::termcolor::ColorSpec::new().set_bold(true).set_fg(Some($color)))?;
    write!($fmt, "{}", $str)?;
    $fmt.reset()
    })
}

macro_rules! color {
    ($fmt:ident, $color:ident, $str:expr) => ({
        $fmt.set_color(::termcolor::ColorSpec::new().set_fg(Some($color)))?;
        write!($fmt, "{}", $str)?;
        $fmt.reset()
    })
}

macro_rules! color_dim {
    ($fmt:ident, $color:ident, $str:expr) => ({
        $fmt.set_color(::termcolor::ColorSpec::new().set_fg(Some($color)).set_intense(false))?;
        write!($fmt, "{}", $str)?;
        $fmt.reset()
    })
}

pub fn new_table(title: Row) -> Table {
    let sep = format::LineSeparator::new('-', '|', ' ', ' ');

    let format = format::FormatBuilder::new()
        .column_separator(' ')
        .borders(' ')
        .separators(&[], sep)
        .padding(1, 1)
        .build();

    let mut phdr_table = Table::new();
    phdr_table.set_titles(title);
    phdr_table.set_format(format);
    phdr_table
}

pub fn string_cell (opt: &Opt, string: &str) -> Cell {
    if string.is_empty() {
        Cell::new(&"")
    } else {
        let mut s = if opt.demangle {
            rustc_demangle::demangle(string).to_string()
        } else {
            string.into()
        };
        if s.len() > opt.truncate { s.truncate(opt.truncate); s += "…"; }
        Cell::new(&s).style_spec("FYb")
    }
}

pub fn str_cell (s: &str) -> Cell {
    if s.is_empty() {
        Cell::new(&"")
    } else {
        Cell::new(s).style_spec("FYb")
    }
}

pub fn idx_cell (i: usize) -> Cell {
    let cell = Cell::new(&i.to_string());
    if i % 2 == 0 { cell.style_spec("FdBw") } else { cell.style_spec("FwBd") }
}

pub fn addr_cell (addr: u64) -> Cell {
    Cell::new(&format!("{:>16x} ", addr)).style_spec("Frr")
}

pub fn offsetx_cell (offset: u64) -> Cell {
    Cell::new(&format!("{:#x} ", offset)).style_spec("Fy")
}

pub fn addrx_cell (addr: u64) -> Cell {
    Cell::new(&format!("{:#x} ", addr)).style_spec("Fr")
}

pub fn memx_cell (maddr: u64) -> Cell {
    Cell::new(&format!("{:<#x} ", maddr)).style_spec("bFr")
}

pub fn sz_cell (size: u64) -> Cell {
    Cell::new(&format!("{:<#x} ", size)).style_spec("Fg")
}

pub fn memsz_cell (memsz: u64) -> Cell {
    Cell::new(&format!("{:<#x} ", memsz)).style_spec("bFg")
}

pub fn x_cell (num: u64) -> Cell {
    Cell::new(&format!("{:#x}", num))
}

pub fn cell<T: ToString> (n: T) -> Cell {
    Cell::new(&format!("{}", n.to_string()))
}

pub fn bool_cell (b: bool) -> Cell {
    let cell = Cell::new(&format!("{} ", b));
    if b { cell.style_spec("bFg") } else { cell.style_spec("bFr") }
}

pub fn fmt_hdr(fmt: &mut Buffer, name: &str) -> ::std::io::Result<()> {
    color!(fmt, White, name)
}

pub fn fmt_hdr_size (fmt: &mut Buffer, name: &str, size: usize) -> ::std::io::Result<()> {
    color_dim!(fmt, White, format!("{}({})", name, size))
}

pub fn fmt_header (fmt: &mut Buffer, name: &str, size: usize) -> ::std::io::Result<()> {
    fmt_hdr_size(fmt, name, size)?;
    writeln!(fmt, ":")?;
    Ok(())
}

pub fn fmt_addr (fmt: &mut Buffer, addr: u64) -> ::std::io::Result<()> {
    color!(fmt, Red, format!("{:x}",addr))
}

pub fn fmt_addr_right (fmt: &mut Buffer, addr: u64) -> ::std::io::Result<()> {
    color!(fmt, Red, format!("{:>16x}",addr))
}

pub fn fmt_addrx (fmt: &mut Buffer, addr: u64) -> ::std::io::Result<()> {
    color!(fmt, Red, format!("{:#x}",addr))
}

pub fn fmt_isize (fmt: &mut Buffer, i: isize) -> ::std::io::Result<()> {
    color!(fmt, Red, format!("{}",i))
}

pub fn fmt_off (fmt: &mut Buffer, off: u64) -> ::std::io::Result<()> {
    color!(fmt, Yellow, format!("{:#x}",off))
}

pub fn fmt_string (fmt: &mut Buffer, opt: &Opt, s: &str) -> ::std::io::Result<()> {
    color_bold!(fmt, Yellow, if opt.demangle {
        rustc_demangle::demangle(s).to_string()
    } else {
        s.into()
    })
}

pub fn fmt_str_option(fmt: &mut Buffer, s: &Option<&str>) -> ::std::io::Result<()> {
    if let &Some(ref s) = s{
        fmt_str(fmt, s)
    } else {
        fmt_name_dim(fmt, "None")
    }
}

pub fn fmt_str (fmt: &mut Buffer, s: &str) -> ::std::io::Result<()> {
    color_bold!(fmt, Yellow, s)
}

pub fn fmt_bool (fmt: &mut Buffer, b: bool) -> ::std::io::Result<()> {
    if b {
        fmt.set_color(::termcolor::ColorSpec::new().set_bold(true).set_intense(true).set_fg(Some(Green)))?;
    } else {
        fmt.set_color(::termcolor::ColorSpec::new().set_bold(true).set_intense(true).set_fg(Some(Red)))?;
    }
    write!(fmt, "{}", b)?;
    fmt.reset()
}

pub fn fmt_name_bold (fmt: &mut Buffer, s: &str) -> ::std::io::Result<()> {
    color_bold!(fmt, White, s)
}

pub fn fmt_name_dim (fmt: &mut Buffer, s: &str) -> ::std::io::Result<()> {
    color_dim!(fmt, White, s)
}

pub fn fmt_name_color(fmt: &mut Buffer, s: &str, color: ::termcolor::Color) -> ::std::io::Result<()> {
    color!(fmt, color, s)
}

pub fn fmt_lib (fmt: &mut Buffer, s: &str) -> ::std::io::Result<()> {
    color_bold!(fmt, Blue, s)
}

pub fn fmt_lib_right (fmt: &mut Buffer, s: &str) -> ::std::io::Result<()> {
    color_bold!(fmt, Blue, format!("{:>16}",s))
}

pub fn fmt_cyan (fmt: &mut Buffer, s: &str) -> ::std::io::Result<()> {
    color!(fmt, Cyan, s)
}

pub fn fmt_sz (fmt: &mut Buffer, fmt_sz: u64) -> ::std::io::Result<()> {
    color!(fmt, Green, format!("{:#x}", fmt_sz))
}

pub fn fmt_idx (fmt: &mut Buffer, i: usize) -> ::std::io::Result<()> {
    let index = format!("{:>4}", i);
    if i % 2 == 0 {
        fmt.set_color(::termcolor::ColorSpec::new().set_fg(Some(White)))?;
    } else {
        fmt.set_color(::termcolor::ColorSpec::new().set_bg(Some(White)).set_fg(Some(Black)))?;
    }
    write!(fmt, "{}", index)?;
    fmt.reset()
}

pub fn flush(fmt: &mut Buffer, writer: &BufferWriter, table: Table, color: bool) -> ::std::io::Result<()> {
    writer.print(fmt)?;
    fmt.clear();
    table.print_tty(color);
    Ok(())
}
<|endoftext|>


<commit_before>
use nom::{IResult, Needed, ErrorKind};

/*
struct Document {
    header: Header,
    body: Vec<Element>,
}

struct Header {}

#[derive(Debug)]
enum ElementData {
    Signed(i64),
    Unsigned(u64),
    Float(f64),
    PlainString(String),
    UTF8String(String),
    Date(u64),
    Master(Vec<Element>),
    Binary(Vec<u8>),
    Unknown(u64),
}

#[derive(Debug)]
pub struct Element {
    id: u64,
    size: u64,
    data: ElementData,
}
*/

pub fn vint(input: &[u8]) -> IResult<&[u8], u64> {
    if input.len() == 0 {
        return IResult::Incomplete(Needed::Size(1));
    }

    let v = input[0];
    let len = v.leading_zeros();

    if len == 8 {
        return IResult::Error(ErrorKind::Custom(100));
    }

    if input.len() <= len as usize {
        return IResult::Incomplete(Needed::Size(1));
    }

    let mut val = (v ^ (1 << (7 - len))) as u64;

    // println!("vint {:08b} {:08b} {:08b} {}", val, v, (1 << (8 - len)), len);

    for i in 0..len as usize {
        val = (val << 8) | input[i + 1] as u64;
    }

    IResult::Done(&input[len as usize + 1..], val)
}

// The ID are represented in the specification as their binary representation
// do not drop the marker bit.
pub fn vid(input: &[u8]) -> IResult<&[u8], u64> {
    if input.len() == 0 {
        return IResult::Incomplete(Needed::Size(1));
    }

    let v = input[0];
    let len = v.leading_zeros();

    if len == 8 {
        return IResult::Error(ErrorKind::Custom(101));
    }

    if input.len() <= len as usize {
        return IResult::Incomplete(Needed::Size(1));
    }

    let mut val = v as u64;

    // println!("vint {:08b} {:08b} {:08b} {}", val, v, (1 << (8 - len)), len);

    for i in 0..len as usize {
        val = (val << 8) | input[i + 1] as u64;
    }

    IResult::Done(&input[len as usize + 1..], val)
}

/*
fn parse_master(input: &[u8], _: u64) -> IResult<&[u8], ElementData> {
    map!(input,
         many0!(parse_element),
         |elem| ElementData::Master(elem))
}

fn parse_uint(input: &[u8], size: u64) -> IResult<&[u8], ElementData> {
    let mut val = 0;

    if size > 8 {
        return IResult::Error(ErrorKind::Custom(1));
    }

    for i in 0..size as usize {
        val = (val << 8) | input[i] as u64;
    }

    IResult::Done(&input[size as usize..], ElementData::Unsigned(val))
}
*/
pub fn parse_uint_data(input: &[u8], size: u64) -> IResult<&[u8], u64> {
    let mut val = 0;

    if size > 8 {
        return IResult::Error(ErrorKind::Custom(102));
    }

    for i in 0..size as usize {
        val = (val << 8) | input[i] as u64;
    }

    IResult::Done(&input[size as usize..], val)
}

pub fn parse_int_data(input: &[u8], size: u64) -> IResult<&[u8], i64> {
    let mut val = 0;

    if size > 8 {
        return IResult::Error(ErrorKind::Custom(103));
    }

    for i in 0..size as usize {
        val = (val << 8) | input[i] as u64;
    }

    //FIXME: is that right?
    IResult::Done(&input[size as usize..], val as i64)
}

/*
fn parse_str(input: &[u8], size: u64) -> IResult<&[u8], ElementData> {
    do_parse!(input,
        s: take_s!(size as usize) >>
        ( ElementData::PlainString(String::from_utf8(s.to_owned()).unwrap()) )
    )
}
*/
pub fn parse_str_data(input: &[u8], size: u64) -> IResult<&[u8], String> {
    do_parse!(input,
        s: take_s!(size as usize) >>
        ( String::from_utf8(s.to_owned()).unwrap() ) //FIXME: maybe do not unwrap here
    )
}

pub fn parse_binary_data(input: &[u8], size: u64) -> IResult<&[u8], Vec<u8>> {
    do_parse!(input,
        s: take_s!(size as usize) >>
        ( s.to_owned() )
    )
}

//FIXME: handle default values
//FIXME: is that really following IEEE_754-1985 ?
pub fn parse_float_data(input: &[u8], size: u64) -> IResult<&[u8], f64> {
    use nom::{be_f32, be_f64};
    if size == 0 {
        IResult::Done(input, 0f64)
    } else if size == 4 {
        map!(input, flat_map!(take!(4), be_f32), |val| val as f64)
    } else if size == 8 {
        flat_map!(input, take!(8), be_f64)
    } else {
        IResult::Error(ErrorKind::Custom(104))
    }
}
/*
fn parse_element_id(input: &[u8], id: u64, size: u64) -> IResult<&[u8], ElementData> {
    // println!("id: 0x{:X} size: {}", id, size);
    if input.len() < size as usize {
        return IResult::Incomplete(Needed::Size(size as usize));
    }

    match id {
        0x1A45DFA3 => parse_master(input, size),
        0x4286 => parse_uint(input, size),
        0x42F7 => parse_uint(input, size),
        0x42F2 => parse_uint(input, size),
        0x42F3 => parse_uint(input, size),
        0x4282 => parse_str(input, size),
        0x4287 => parse_uint(input, size),
        0x4285 => parse_uint(input, size),
        _ => IResult::Done(&input[size as usize..], ElementData::Unknown(id)),
    }
}

named!(pub parse_element<Element>,
    do_parse!(
        id : vid >>
        size: vint >>
        data: call!(parse_element_id, id, size) >>
        (Element { id, size, data })
    )
);
*/
#[macro_export]
macro_rules! ebml_uint (
  ($i: expr, $id:expr) => ({
    use $crate::ebml::{vid, vint, parse_uint_data};
    do_parse!($i,
               verify!(vid, |val:u64| val == $id)
      >> size: vint
      >> data: apply!(parse_uint_data, size)
      >> (data)
    )
  })
);

#[macro_export]
macro_rules! ebml_int (
  ($i: expr, $id:expr) => ({
    use $crate::ebml::{vid, vint, parse_int_data};
    do_parse!($i,
               verify!(vid, |val:u64| val == $id)
      >> size: vint
      >> data: apply!(parse_int_data, size)
      >> (data)
    )
  })
);

#[macro_export]
macro_rules! ebml_float (
  ($i: expr, $id:expr) => ({
    use $crate::ebml::{vid, vint, parse_float_data};
    do_parse!($i,
               verify!(vid, |val:u64| val == $id)
      >> size: vint
      >> data: apply!(parse_float_data, size)
      >> (data)
    )
  })
);

#[macro_export]
macro_rules! ebml_str (
  ($i: expr, $id:expr) => ({
    use $crate::ebml::{vid, vint, parse_str_data};

    do_parse!($i,
               verify!(vid, |val:u64| val == $id)
      >> size: vint
      >> data: apply!(parse_str_data, size)
      >> (data)
    )
  })
);

#[macro_export]
macro_rules! ebml_binary (
  ($i: expr, $id:expr) => ({
    use $crate::ebml::{vid, vint, parse_binary_data};

    do_parse!($i,
               verify!(vid, |val:u64| val == $id)
      >> size: vint
      >> data: apply!(parse_binary_data, size)
      >> (data)
    )
  })
);

#[macro_export]
macro_rules! ebml_master (
  ($i: expr, $id:expr, $submac:ident!( $($args:tt)* )) => ({
    use $crate::ebml::{vid, vint};
    do_parse!($i,
               verify!(vid, |val:u64| val == $id)
      >> size: vint
      >> data: flat_map!(take!(size as usize), $submac!($($args)*))
      >> (data)
    )
  })
);

#[macro_export]
macro_rules! eat_void (
  ($i: expr, $submac:ident!( $($args:tt)* )) => ({
    preceded!($i,
      opt!($crate::ebml::skip_void),
      $submac!($($args)*)
    )
  });
  ($i: expr, $e:expr) => ({
    eat_void!($i, call!($e))
  });
);

named!(pub skip_void,
do_parse!(
  id:   verify!(vid, |val:u64| val == 0xEC) >>
  size: vint >>
  data: take!(size) >>
  (data)
  ));

#[derive(Debug, Clone, PartialEq)]
pub struct EBMLHeader {
    pub version: u64,
    pub read_version: u64,
    pub max_id_length: u64,
    pub max_size_length: u64,
    pub doc_type: String,
    pub doc_type_version: u64,
    pub doc_type_read_version: u64,
}

named!(pub ebml_header<EBMLHeader>,
  ebml_master!(0x1A45DFA3,
    do_parse!(
      t: permutation_opt!(
        complete!(ebml_uint!(0x4286)), // version
        complete!(ebml_uint!(0x42F7)), // read_version
        complete!(ebml_uint!(0x42F2)), // max id length
        complete!(ebml_uint!(0x42F3)), // max size length
        complete!(ebml_str!(0x4282)),  // doctype
        complete!(ebml_uint!(0x4287)), // doctype version
        complete!(ebml_uint!(0x4285)),  // doctype_read version
        complete!(skip_void)?
      ) >>
      ({
        EBMLHeader {
          version:               t.0,
          read_version:          t.1,
          max_id_length:         t.2,
          max_size_length:       t.3,
          doc_type:              t.4,
          doc_type_version:      t.5,
          doc_type_read_version: t.6,

        }
      })
    )
  )
);

#[cfg(test)]
mod tests {
    use super::*;
    use nom::{HexDisplay, Offset};

    const single_stream: &'static [u8] = include_bytes!("../assets/single_stream.mkv");
    const webm: &'static [u8] = include_bytes!("../assets/big-buck-bunny_trailer.webm");

    #[test]
    fn variable_integer() {
        let val01 = [0b10000000];
        //        let val01 = [0b01000000, 0b1];

        match vint(&val01) {
            IResult::Done(_, v) => assert!(0 == v),
            _ => panic!(),
        }
    }

    /*
    #[test]
    fn header() {
        println!("{}", single_stream[..8].to_hex(8));
        println!("{:b} {:b}", single_stream[0], single_stream[1]);
        println!("{:#?}", parse_element(single_stream));
        panic!();
    }*/

    #[test]
    fn mkv_header() {
        println!("{}", single_stream[..8].to_hex(8));
        println!("{:b} {:b}", single_stream[0], single_stream[1]);
        println!("{:?}", ebml_header(&single_stream[..100]));
        panic!();
    }

    #[test]
    fn webm_header() {
        println!("{}", webm[..8].to_hex(8));
        let res = ebml_header(&webm[..100]);
        println!("{:?}", res);

        if let IResult::Done(i, _) = res {
            println!("offset: {} bytes", webm.offset(i));
        }
        panic!();
    }
}
<commit_msg>simplify the ebml header parser<commit_after>
use nom::{IResult, Needed, ErrorKind};

/*
struct Document {
    header: Header,
    body: Vec<Element>,
}

struct Header {}

#[derive(Debug)]
enum ElementData {
    Signed(i64),
    Unsigned(u64),
    Float(f64),
    PlainString(String),
    UTF8String(String),
    Date(u64),
    Master(Vec<Element>),
    Binary(Vec<u8>),
    Unknown(u64),
}

#[derive(Debug)]
pub struct Element {
    id: u64,
    size: u64,
    data: ElementData,
}
*/

pub fn vint(input: &[u8]) -> IResult<&[u8], u64> {
    if input.len() == 0 {
        return IResult::Incomplete(Needed::Size(1));
    }

    let v = input[0];
    let len = v.leading_zeros();

    if len == 8 {
        return IResult::Error(ErrorKind::Custom(100));
    }

    if input.len() <= len as usize {
        return IResult::Incomplete(Needed::Size(1));
    }

    let mut val = (v ^ (1 << (7 - len))) as u64;

    // println!("vint {:08b} {:08b} {:08b} {}", val, v, (1 << (8 - len)), len);

    for i in 0..len as usize {
        val = (val << 8) | input[i + 1] as u64;
    }

    IResult::Done(&input[len as usize + 1..], val)
}

// The ID are represented in the specification as their binary representation
// do not drop the marker bit.
pub fn vid(input: &[u8]) -> IResult<&[u8], u64> {
    if input.len() == 0 {
        return IResult::Incomplete(Needed::Size(1));
    }

    let v = input[0];
    let len = v.leading_zeros();

    if len == 8 {
        return IResult::Error(ErrorKind::Custom(101));
    }

    if input.len() <= len as usize {
        return IResult::Incomplete(Needed::Size(1));
    }

    let mut val = v as u64;

    // println!("vint {:08b} {:08b} {:08b} {}", val, v, (1 << (8 - len)), len);

    for i in 0..len as usize {
        val = (val << 8) | input[i + 1] as u64;
    }

    IResult::Done(&input[len as usize + 1..], val)
}

/*
fn parse_master(input: &[u8], _: u64) -> IResult<&[u8], ElementData> {
    map!(input,
         many0!(parse_element),
         |elem| ElementData::Master(elem))
}

fn parse_uint(input: &[u8], size: u64) -> IResult<&[u8], ElementData> {
    let mut val = 0;

    if size > 8 {
        return IResult::Error(ErrorKind::Custom(1));
    }

    for i in 0..size as usize {
        val = (val << 8) | input[i] as u64;
    }

    IResult::Done(&input[size as usize..], ElementData::Unsigned(val))
}
*/
pub fn parse_uint_data(input: &[u8], size: u64) -> IResult<&[u8], u64> {
    let mut val = 0;

    if size > 8 {
        return IResult::Error(ErrorKind::Custom(102));
    }

    for i in 0..size as usize {
        val = (val << 8) | input[i] as u64;
    }

    IResult::Done(&input[size as usize..], val)
}

pub fn parse_int_data(input: &[u8], size: u64) -> IResult<&[u8], i64> {
    let mut val = 0;

    if size > 8 {
        return IResult::Error(ErrorKind::Custom(103));
    }

    for i in 0..size as usize {
        val = (val << 8) | input[i] as u64;
    }

    //FIXME: is that right?
    IResult::Done(&input[size as usize..], val as i64)
}

/*
fn parse_str(input: &[u8], size: u64) -> IResult<&[u8], ElementData> {
    do_parse!(input,
        s: take_s!(size as usize) >>
        ( ElementData::PlainString(String::from_utf8(s.to_owned()).unwrap()) )
    )
}
*/
pub fn parse_str_data(input: &[u8], size: u64) -> IResult<&[u8], String> {
    do_parse!(input,
        s: take_s!(size as usize) >>
        ( String::from_utf8(s.to_owned()).unwrap() ) //FIXME: maybe do not unwrap here
    )
}

pub fn parse_binary_data(input: &[u8], size: u64) -> IResult<&[u8], Vec<u8>> {
    do_parse!(input,
        s: take_s!(size as usize) >>
        ( s.to_owned() )
    )
}

//FIXME: handle default values
//FIXME: is that really following IEEE_754-1985 ?
pub fn parse_float_data(input: &[u8], size: u64) -> IResult<&[u8], f64> {
    use nom::{be_f32, be_f64};
    if size == 0 {
        IResult::Done(input, 0f64)
    } else if size == 4 {
        map!(input, flat_map!(take!(4), be_f32), |val| val as f64)
    } else if size == 8 {
        flat_map!(input, take!(8), be_f64)
    } else {
        IResult::Error(ErrorKind::Custom(104))
    }
}
/*
fn parse_element_id(input: &[u8], id: u64, size: u64) -> IResult<&[u8], ElementData> {
    // println!("id: 0x{:X} size: {}", id, size);
    if input.len() < size as usize {
        return IResult::Incomplete(Needed::Size(size as usize));
    }

    match id {
        0x1A45DFA3 => parse_master(input, size),
        0x4286 => parse_uint(input, size),
        0x42F7 => parse_uint(input, size),
        0x42F2 => parse_uint(input, size),
        0x42F3 => parse_uint(input, size),
        0x4282 => parse_str(input, size),
        0x4287 => parse_uint(input, size),
        0x4285 => parse_uint(input, size),
        _ => IResult::Done(&input[size as usize..], ElementData::Unknown(id)),
    }
}

named!(pub parse_element<Element>,
    do_parse!(
        id : vid >>
        size: vint >>
        data: call!(parse_element_id, id, size) >>
        (Element { id, size, data })
    )
);
*/
#[macro_export]
macro_rules! ebml_uint (
  ($i: expr, $id:expr) => ({
    use $crate::ebml::{vid, vint, parse_uint_data};
    do_parse!($i,
               verify!(vid, |val:u64| val == $id)
      >> size: vint
      >> data: apply!(parse_uint_data, size)
      >> (data)
    )
  })
);

#[macro_export]
macro_rules! ebml_int (
  ($i: expr, $id:expr) => ({
    use $crate::ebml::{vid, vint, parse_int_data};
    do_parse!($i,
               verify!(vid, |val:u64| val == $id)
      >> size: vint
      >> data: apply!(parse_int_data, size)
      >> (data)
    )
  })
);

#[macro_export]
macro_rules! ebml_float (
  ($i: expr, $id:expr) => ({
    use $crate::ebml::{vid, vint, parse_float_data};
    do_parse!($i,
               verify!(vid, |val:u64| val == $id)
      >> size: vint
      >> data: apply!(parse_float_data, size)
      >> (data)
    )
  })
);

#[macro_export]
macro_rules! ebml_str (
  ($i: expr, $id:expr) => ({
    use $crate::ebml::{vid, vint, parse_str_data};

    do_parse!($i,
               verify!(vid, |val:u64| val == $id)
      >> size: vint
      >> data: apply!(parse_str_data, size)
      >> (data)
    )
  })
);

#[macro_export]
macro_rules! ebml_binary (
  ($i: expr, $id:expr) => ({
    use $crate::ebml::{vid, vint, parse_binary_data};

    do_parse!($i,
               verify!(vid, |val:u64| val == $id)
      >> size: vint
      >> data: apply!(parse_binary_data, size)
      >> (data)
    )
  })
);

#[macro_export]
macro_rules! ebml_master (
  ($i: expr, $id:expr, $submac:ident!( $($args:tt)* )) => ({
    use $crate::ebml::{vid, vint};
    do_parse!($i,
               verify!(vid, |val:u64| val == $id)
      >> size: vint
      >> data: flat_map!(take!(size as usize), $submac!($($args)*))
      >> (data)
    )
  })
);

#[macro_export]
macro_rules! eat_void (
  ($i: expr, $submac:ident!( $($args:tt)* )) => ({
    preceded!($i,
      opt!($crate::ebml::skip_void),
      $submac!($($args)*)
    )
  });
  ($i: expr, $e:expr) => ({
    eat_void!($i, call!($e))
  });
);

named!(pub skip_void,
do_parse!(
  id:   verify!(vid, |val:u64| val == 0xEC) >>
  size: vint >>
  data: take!(size) >>
  (data)
  ));

#[derive(Debug, Clone, PartialEq)]
pub struct EBMLHeader {
    pub version: u64,
    pub read_version: u64,
    pub max_id_length: u64,
    pub max_size_length: u64,
    pub doc_type: String,
    pub doc_type_version: u64,
    pub doc_type_read_version: u64,
}

named!(pub ebml_header<EBMLHeader>,
  ebml_master!(0x1A45DFA3,
    do_parse!(
      t: permutation_opt!(
        ebml_uint!(0x4286), // version
        ebml_uint!(0x42F7), // read_version
        ebml_uint!(0x42F2), // max id length
        ebml_uint!(0x42F3), // max size length
        ebml_str!(0x4282),  // doctype
        ebml_uint!(0x4287), // doctype version
        ebml_uint!(0x4285),  // doctype_read version
        skip_void?
      ) >>
      ({
        EBMLHeader {
          version:               t.0,
          read_version:          t.1,
          max_id_length:         t.2,
          max_size_length:       t.3,
          doc_type:              t.4,
          doc_type_version:      t.5,
          doc_type_read_version: t.6,

        }
      })
    )
  )
);

#[cfg(test)]
mod tests {
    use super::*;
    use nom::{HexDisplay, Offset};

    const single_stream: &'static [u8] = include_bytes!("../assets/single_stream.mkv");
    const webm: &'static [u8] = include_bytes!("../assets/big-buck-bunny_trailer.webm");

    #[test]
    fn variable_integer() {
        let val01 = [0b10000000];
        //        let val01 = [0b01000000, 0b1];

        match vint(&val01) {
            IResult::Done(_, v) => assert!(0 == v),
            _ => panic!(),
        }
    }

    /*
    #[test]
    fn header() {
        println!("{}", single_stream[..8].to_hex(8));
        println!("{:b} {:b}", single_stream[0], single_stream[1]);
        println!("{:#?}", parse_element(single_stream));
        panic!();
    }*/

    #[test]
    fn mkv_header() {
        println!("{}", single_stream[..8].to_hex(8));
        println!("{:b} {:b}", single_stream[0], single_stream[1]);
        println!("{:?}", ebml_header(&single_stream[..100]));
        panic!();
    }

    #[test]
    fn webm_header() {
        println!("{}", webm[..8].to_hex(8));
        let res = ebml_header(&webm[..100]);
        println!("{:?}", res);

        if let IResult::Done(i, _) = res {
            println!("offset: {} bytes", webm.offset(i));
        }
        panic!();
    }
}
<|endoftext|>