<commit_before>#![feature(test)]
#![feature(plugin)]
#![plugin(quickcheck_macros)]

//
// cargo test listedit::experiments -- --nocapture
//

extern crate adapton ;
extern crate test;
extern crate quickcheck;
extern crate rand;

use adapton::adapton_sigs::* ;
use adapton::collection::*;
use adapton::engine;
use adapton::naive;

type Edits = Vec<CursorEdit<u32, Dir2>>;

fn compare_naive_and_cached(edits: &Edits) -> bool {
    let reduction = ListReduce::Max;
    let mut n_st = naive::AdaptonFromScratch::new();
    let mut e_st = engine::Engine::new();

    let results_1 = Experiment::run(&mut n_st, edits.clone(), reduction.clone());
    let results_2 = Experiment::run(&mut e_st, edits.clone(), reduction.clone());

    let mut idx = 0;
    for (a, b) in results_1.iter().zip(results_2.iter()) {
        if a.0 != b.0 {
            println!("after edit {}: {:?}: expected {:?} to be {:?}, but found {:?}",
                     idx, edits[idx], &reduction, a.0, b.0);
            return false;
        }
        idx += 1;
    }

    true
}

#[test]
fn ensure_consistency_randomly() {
    let rng = rand::thread_rng();
    let mut gen = quickcheck::StdGen::new(rng, 100);
    for _ in 0..100 {
        let testv = <Edits as quickcheck::Arbitrary>::arbitrary(&mut gen);
        if !compare_naive_and_cached(&testv) {
            panic!("{:?}", testv);
        }
    }
}

#[test]
fn ensure_consistency_regression_testcase1() { assert!( compare_naive_and_cached(&testcase1())) }

#[test]
fn ensure_consistency_regression_testcase2() { assert!( compare_naive_and_cached(&testcase2())) }

fn testcase1 () -> Edits {
    vec![
        CursorEdit::Insert(Dir2::Left, 36), CursorEdit::Insert(Dir2::Right, 44), CursorEdit::Remove(Dir2::Right), CursorEdit::Remove(Dir2::Right),
        CursorEdit::Insert(Dir2::Left, 86), CursorEdit::Insert(Dir2::Left, 11), CursorEdit::Insert(Dir2::Right, 22), CursorEdit::Insert(Dir2::Right, 23),
        CursorEdit::Insert(Dir2::Left, 41), CursorEdit::Remove(Dir2::Right),
        CursorEdit::Insert(Dir2::Right, 13), CursorEdit::Insert(Dir2::Left, 21), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 41),
        CursorEdit::Insert(Dir2::Left, 71), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 22), CursorEdit::Replace(Dir2::Left, 11), CursorEdit::Goto(Dir2::Right),
        CursorEdit::Insert(Dir2::Right, 76), CursorEdit::Insert(Dir2::Left, 45), CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Left, 12), CursorEdit::Insert(Dir2::Right, 14),
        CursorEdit::Goto(Dir2::Right), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 35), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Left, 39),
        CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Right, 43), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 36), CursorEdit::Insert(Dir2::Left, 85),
        CursorEdit::Insert(Dir2::Left, 11), CursorEdit::Insert(Dir2::Left, 93), CursorEdit::Insert(Dir2::Right, 52), CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Right)
       ]
}

fn testcase2 () -> Edits {
    vec![CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Left, 86), CursorEdit::Insert(Dir2::Left, 76), CursorEdit::Insert(Dir2::Right, 39), CursorEdit::Goto(Dir2::Right),
         CursorEdit::Insert(Dir2::Right, 63), CursorEdit::Goto(Dir2::Right), CursorEdit::Replace(Dir2::Left, 54), CursorEdit::Remove(Dir2::Left),
         CursorEdit::Insert(Dir2::Right, 77), CursorEdit::Insert(Dir2::Right, 32), CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Left),
         CursorEdit::Replace(Dir2::Right, 57), CursorEdit::Goto(Dir2::Right), CursorEdit::Replace(Dir2::Left, 6), CursorEdit::Remove(Dir2::Right),
         CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Left, 81), CursorEdit::Goto(Dir2::Right), CursorEdit::Goto(Dir2::Left),
         CursorEdit::Remove(Dir2::Right), CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Right),
         CursorEdit::Insert(Dir2::Right, 76), CursorEdit::Replace(Dir2::Left, 72), CursorEdit::Insert(Dir2::Left, 51), CursorEdit::Remove(Dir2::Right), CursorEdit::Insert(Dir2::Left, 49),
         CursorEdit::Remove(Dir2::Left), CursorEdit::Goto(Dir2::Right), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Left, 6),
         CursorEdit::Insert(Dir2::Right, 82), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 89), CursorEdit::Goto(Dir2::Right),
         CursorEdit::Insert(Dir2::Left, 9), CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Left, 26), CursorEdit::Replace(Dir2::Left, 35),
         CursorEdit::Goto(Dir2::Left), CursorEdit::Remove(Dir2::Left), CursorEdit::Goto(Dir2::Right), CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Left),
         CursorEdit::Remove(Dir2::Left), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Left, 5), CursorEdit::Insert(Dir2::Left, 75),
         CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Left, 32), CursorEdit::Replace(Dir2::Right, 74), CursorEdit::Insert(Dir2::Left, 77),
         CursorEdit::Insert(Dir2::Left, 71), CursorEdit::Insert(Dir2::Left, 44), CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Right, 81),
         CursorEdit::Insert(Dir2::Left, 61), CursorEdit::Insert(Dir2::Right, 92), CursorEdit::Insert(Dir2::Left, 68), CursorEdit::Replace(Dir2::Right, 42),
         CursorEdit::Insert(Dir2::Right, 81), CursorEdit::Goto(Dir2::Right), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 31),
         CursorEdit::Insert(Dir2::Right, 72), CursorEdit::Insert(Dir2::Right, 70), CursorEdit::Insert(Dir2::Left, 87), CursorEdit::Insert(Dir2::Right, 95),
         CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Left), CursorEdit::Replace(Dir2::Right, 96), CursorEdit::Goto(Dir2::Right),
         CursorEdit::Goto(Dir2::Left), CursorEdit::Remove(Dir2::Left), CursorEdit::Goto(Dir2::Left)]
}
<commit_msg>added another failing testcase<commit_after>#![feature(test)]
#![feature(plugin)]
#![plugin(quickcheck_macros)]

//
// cargo test listedit::experiments -- --nocapture
//

extern crate adapton ;
extern crate test;
extern crate quickcheck;
extern crate rand;

use adapton::adapton_sigs::* ;
use adapton::collection::*;
use adapton::engine;
use adapton::naive;

type Edits = Vec<CursorEdit<u32, Dir2>>;

fn compare_naive_and_cached(edits: &Edits) -> bool {
    let reduction = ListReduce::Max;
    let mut n_st = naive::AdaptonFromScratch::new();
    let mut e_st = engine::Engine::new();

    let results_1 = Experiment::run(&mut n_st, edits.clone(), reduction.clone());
    let results_2 = Experiment::run(&mut e_st, edits.clone(), reduction.clone());

    let mut idx = 0;
    for (a, b) in results_1.iter().zip(results_2.iter()) {
        if a.0 != b.0 {
            println!("After edit {}, {:?}, expected {:?} to be {:?}, but found {:?}.",
                     idx, edits[idx], &reduction, a.0, b.0);
            return false;
        }
        idx += 1;
    }

    true
}

#[test]
fn ensure_consistency_randomly() {
    let rng = rand::thread_rng();
    let mut gen = quickcheck::StdGen::new(rng, 100);
    for _ in 0..100 {
        let testv = <Edits as quickcheck::Arbitrary>::arbitrary(&mut gen);
        if !compare_naive_and_cached(&testv) {
            panic!("{:?}", testv);
        }
    }
}

#[test]
fn ensure_consistency_regression_testcase1() { assert!( compare_naive_and_cached(&testcase1())) }

#[test]
fn ensure_consistency_regression_testcase2() { assert!( compare_naive_and_cached(&testcase2())) }

#[test]
fn ensure_consistency_regression_testcase3() { assert!( compare_naive_and_cached(&testcase3())) }

fn testcase1 () -> Edits {
    vec![
        CursorEdit::Insert(Dir2::Left, 36), CursorEdit::Insert(Dir2::Right, 44), CursorEdit::Remove(Dir2::Right), CursorEdit::Remove(Dir2::Right),
        CursorEdit::Insert(Dir2::Left, 86), CursorEdit::Insert(Dir2::Left, 11), CursorEdit::Insert(Dir2::Right, 22), CursorEdit::Insert(Dir2::Right, 23),
        CursorEdit::Insert(Dir2::Left, 41), CursorEdit::Remove(Dir2::Right),
        CursorEdit::Insert(Dir2::Right, 13), CursorEdit::Insert(Dir2::Left, 21), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 41),
        CursorEdit::Insert(Dir2::Left, 71), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 22), CursorEdit::Replace(Dir2::Left, 11), CursorEdit::Goto(Dir2::Right),
        CursorEdit::Insert(Dir2::Right, 76), CursorEdit::Insert(Dir2::Left, 45), CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Left, 12), CursorEdit::Insert(Dir2::Right, 14),
        CursorEdit::Goto(Dir2::Right), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 35), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Left, 39),
        CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Right, 43), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 36), CursorEdit::Insert(Dir2::Left, 85),
        CursorEdit::Insert(Dir2::Left, 11), CursorEdit::Insert(Dir2::Left, 93), CursorEdit::Insert(Dir2::Right, 52), CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Right)
       ]
}

fn testcase2 () -> Edits {
    vec![CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Left, 86), CursorEdit::Insert(Dir2::Left, 76), CursorEdit::Insert(Dir2::Right, 39), CursorEdit::Goto(Dir2::Right),
         CursorEdit::Insert(Dir2::Right, 63), CursorEdit::Goto(Dir2::Right), CursorEdit::Replace(Dir2::Left, 54), CursorEdit::Remove(Dir2::Left),
         CursorEdit::Insert(Dir2::Right, 77), CursorEdit::Insert(Dir2::Right, 32), CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Left),
         CursorEdit::Replace(Dir2::Right, 57), CursorEdit::Goto(Dir2::Right), CursorEdit::Replace(Dir2::Left, 6), CursorEdit::Remove(Dir2::Right),
         CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Left, 81), CursorEdit::Goto(Dir2::Right), CursorEdit::Goto(Dir2::Left),
         CursorEdit::Remove(Dir2::Right), CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Right),
         CursorEdit::Insert(Dir2::Right, 76), CursorEdit::Replace(Dir2::Left, 72), CursorEdit::Insert(Dir2::Left, 51), CursorEdit::Remove(Dir2::Right), CursorEdit::Insert(Dir2::Left, 49),
         CursorEdit::Remove(Dir2::Left), CursorEdit::Goto(Dir2::Right), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Left, 6),
         CursorEdit::Insert(Dir2::Right, 82), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 89), CursorEdit::Goto(Dir2::Right),
         CursorEdit::Insert(Dir2::Left, 9), CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Left, 26), CursorEdit::Replace(Dir2::Left, 35),
         CursorEdit::Goto(Dir2::Left), CursorEdit::Remove(Dir2::Left), CursorEdit::Goto(Dir2::Right), CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Left),
         CursorEdit::Remove(Dir2::Left), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Left, 5), CursorEdit::Insert(Dir2::Left, 75),
         CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Left, 32), CursorEdit::Replace(Dir2::Right, 74), CursorEdit::Insert(Dir2::Left, 77),
         CursorEdit::Insert(Dir2::Left, 71), CursorEdit::Insert(Dir2::Left, 44), CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Right, 81),
         CursorEdit::Insert(Dir2::Left, 61), CursorEdit::Insert(Dir2::Right, 92), CursorEdit::Insert(Dir2::Left, 68), CursorEdit::Replace(Dir2::Right, 42),
         CursorEdit::Insert(Dir2::Right, 81), CursorEdit::Goto(Dir2::Right), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 31),
         CursorEdit::Insert(Dir2::Right, 72), CursorEdit::Insert(Dir2::Right, 70), CursorEdit::Insert(Dir2::Left, 87), CursorEdit::Insert(Dir2::Right, 95),
         CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Left), CursorEdit::Replace(Dir2::Right, 96), CursorEdit::Goto(Dir2::Right),
         CursorEdit::Goto(Dir2::Left), CursorEdit::Remove(Dir2::Left), CursorEdit::Goto(Dir2::Left)]
}

fn testcase3 () -> Edits {
    vec![CursorEdit::Insert(Dir2::Left, 86), CursorEdit::Insert(Dir2::Right, 37), CursorEdit::Remove(Dir2::Left), CursorEdit::Insert(Dir2::Left, 42),
         CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Left, 68), CursorEdit::Insert(Dir2::Right, 18), CursorEdit::Remove(Dir2::Left),
         CursorEdit::Remove(Dir2::Right), CursorEdit::Goto(Dir2::Right), CursorEdit::Replace(Dir2::Left, 68), CursorEdit::Insert(Dir2::Left, 82),
         CursorEdit::Insert(Dir2::Right, 30), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Left, 78), CursorEdit::Insert(Dir2::Right, 88), CursorEdit::Insert(Dir2::Left, 38),
         CursorEdit::Insert(Dir2::Right, 91), CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Right, 67), CursorEdit::Insert(Dir2::Right, 3),
         CursorEdit::Remove(Dir2::Right), CursorEdit::Insert(Dir2::Right, 16), CursorEdit::Insert(Dir2::Left, 4), CursorEdit::Insert(Dir2::Right, 29),
         CursorEdit::Insert(Dir2::Right, 92), CursorEdit::Insert(Dir2::Left, 79), CursorEdit::Replace(Dir2::Left, 88), CursorEdit::Goto(Dir2::Right),
         CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Left, 25), CursorEdit::Insert(Dir2::Left, 46), CursorEdit::Goto(Dir2::Left), CursorEdit::Goto(Dir2::Left),
         CursorEdit::Insert(Dir2::Left, 18), CursorEdit::Insert(Dir2::Left, 1), CursorEdit::Insert(Dir2::Right, 43), CursorEdit::Goto(Dir2::Left), CursorEdit::Remove(Dir2::Left),
         CursorEdit::Insert(Dir2::Right, 93), CursorEdit::Goto(Dir2::Left), CursorEdit::Insert(Dir2::Right, 10), CursorEdit::Remove(Dir2::Left),
         CursorEdit::Insert(Dir2::Right, 34), CursorEdit::Remove(Dir2::Left), CursorEdit::Replace(Dir2::Left, 47), CursorEdit::Goto(Dir2::Right),
         CursorEdit::Insert(Dir2::Left, 56), CursorEdit::Insert(Dir2::Left, 36), CursorEdit::Replace(Dir2::Right, 99), CursorEdit::Insert(Dir2::Right, 19),
         CursorEdit::Insert(Dir2::Right, 35), CursorEdit::Goto(Dir2::Right), CursorEdit::Insert(Dir2::Right, 94), CursorEdit::Replace(Dir2::Right, 58), CursorEdit::Goto(Dir2::Right),
         CursorEdit::Insert(Dir2::Left, 71)]
}
<|endoftext|>


<commit_before>
extern crate twelve_bit;

use twelve_bit::u12::*;

// MARK: - Tests - Non-Failable Conversions - From Smaller Types

#[test]
pub fn test_from_u8() {
  assert_eq!(u16::from(U12::from(0u8)), 0u16);
  assert_eq!(u16::from(U12::from(15u8)), 15u16);
  assert_eq!(u16::from(U12::from(255u8)), 255u16);
}

// MARK: - Tests - Non-Failable Conversions - Into Larger Types

pub fn test_into_larger_types() {
  let into_16_max: u16 = U12::max_value().into();
  let into_16_min: u16 = U12::min_value().into();
  assert_eq!(into_16_max, 4095u16);
  assert_eq!(into_16_min, 0u16);

  let into_32_max: u32 = U12::max_value().into();
  let into_32_min: u32 = U12::min_value().into();
  assert_eq!(into_32_max, 4095u32);
  assert_eq!(into_32_min, 0u32);

  let into_64_max: u64 = U12::max_value().into();
  let into_64_min: u64 = U12::min_value().into();
  assert_eq!(into_64_max, 4095u64);
  assert_eq!(into_64_min, 0u64);

  let into_usize_max: usize = U12::max_value().into();
  let into_usize_min: usize = U12::min_value().into();
  assert_eq!(into_usize_max, 4095usize);
  assert_eq!(into_usize_min, 0usize);
}

// MARK: - Tests - Failable Conversions - From Larger Types

#[test]
pub fn test_failable_into_with_u16() {
  assert_eq!(0u16.failable_into(), Some(U12::min_value()));
  assert_eq!(0u16.unchecked_into(), U12::min_value());
  assert_eq!(15u16.failable_into(), Some(U12::from(15)));
  assert_eq!(15u16.unchecked_into(), U12::from(15));
  assert_eq!(4096u16.failable_into(), None);
  assert_eq!(u16::max_value().failable_into(), None);
}

#[test]
#[should_panic]
pub fn test_unchecked_into_with_u16() {
  let _ = 4096u16.unchecked_into();
}

#[test]
pub fn test_failable_into_with_u32() {
  assert_eq!(0u32.failable_into(), Some(U12::min_value()));
  assert_eq!(0u32.unchecked_into(), U12::min_value());
  assert_eq!(15u32.failable_into(), Some(U12::from(15u8)));
  assert_eq!(15u32.unchecked_into(), U12::from(15));
  assert_eq!(4096u32.failable_into(), None);
  assert_eq!(u32::max_value().failable_into(), None);
}

#[test]
#[should_panic]
pub fn test_unchecked_into_with_u32() {
  let _ = 4096u32.unchecked_into();
}

#[test]
pub fn test_failable_into_with_u64() {
  assert_eq!(0u64.failable_into(), Some(U12::min_value()));
  assert_eq!(0u64.unchecked_into(), U12::min_value());
  assert_eq!(15u64.failable_into(), Some(U12::from(15u8)));
  assert_eq!(15u64.unchecked_into(), U12::from(15));
  assert_eq!(4096u64.failable_into(), None);
  assert_eq!(u64::max_value().failable_into(), None);
}

#[test]
#[should_panic]
pub fn test_unchecked_into_with_u64() {
  let _ = 4096u64.unchecked_into();
}

#[test]
pub fn test_failable_into_with_usize() {
  assert_eq!(0usize.failable_into(), Some(U12::min_value()));
  assert_eq!(0usize.unchecked_into(), U12::min_value());
  assert_eq!(15usize.failable_into(), Some(U12::from(15u8)));
  assert_eq!(15usize.unchecked_into(), U12::from(15));
  assert_eq!(4096usize.failable_into(), None);
  assert_eq!(usize::max_value().failable_into(), None);
}

#[test]
#[should_panic]
pub fn test_unchecked_into_with_usize() {
  let _ = 4096usize.unchecked_into();
}
<commit_msg>Syntax errors and Default.<commit_after>
extern crate twelve_bit;

use twelve_bit::u12::*;

// MARK: - Tests - Non-Failable Conversions - From Smaller Types

#[test]
fn test_from_u8() {
  assert_eq!(u16::from(U12::from(0u8)), 0u16);
  assert_eq!(u16::from(U12::from(15u8)), 15u16);
  assert_eq!(u16::from(U12::from(255u8)), 255u16);
}

// MARK: - Tests - Non-Failable Conversions - Into Larger Types

#[test]
fn test_into_larger_types() {
  let into_16_max: u16 = U12::max_value().into();
  let into_16_min: u16 = U12::min_value().into();
  assert_eq!(into_16_max, 4095u16);
  assert_eq!(into_16_min, 0u16);

  let into_32_max: u32 = U12::max_value().into();
  let into_32_min: u32 = U12::min_value().into();
  assert_eq!(into_32_max, 4095u32);
  assert_eq!(into_32_min, 0u32);

  let into_64_max: u64 = U12::max_value().into();
  let into_64_min: u64 = U12::min_value().into();
  assert_eq!(into_64_max, 4095u64);
  assert_eq!(into_64_min, 0u64);

  let into_usize_max: usize = U12::max_value().into();
  let into_usize_min: usize = U12::min_value().into();
  assert_eq!(into_usize_max, 4095usize);
  assert_eq!(into_usize_min, 0usize);
}

// MARK: - Tests - Failable Conversions - From Larger Types

#[test]
fn test_failable_into_with_u16() {
  assert_eq!(0u16.failable_into(), Some(U12::min_value()));
  assert_eq!(0u16.unchecked_into(), U12::min_value());
  assert_eq!(15u16.failable_into(), Some(U12::from(15)));
  assert_eq!(15u16.unchecked_into(), U12::from(15));
  assert_eq!(4096u16.failable_into(), None);
  assert_eq!(u16::max_value().failable_into(), None);
}

#[test]
#[should_panic]
fn test_unchecked_into_with_u16() {
  let _ = 4096u16.unchecked_into();
}

#[test]
fn test_failable_into_with_u32() {
  assert_eq!(0u32.failable_into(), Some(U12::min_value()));
  assert_eq!(0u32.unchecked_into(), U12::min_value());
  assert_eq!(15u32.failable_into(), Some(U12::from(15u8)));
  assert_eq!(15u32.unchecked_into(), U12::from(15));
  assert_eq!(4096u32.failable_into(), None);
  assert_eq!(u32::max_value().failable_into(), None);
}

#[test]
#[should_panic]
fn test_unchecked_into_with_u32() {
  let _ = 4096u32.unchecked_into();
}

#[test]
fn test_failable_into_with_u64() {
  assert_eq!(0u64.failable_into(), Some(U12::min_value()));
  assert_eq!(0u64.unchecked_into(), U12::min_value());
  assert_eq!(15u64.failable_into(), Some(U12::from(15u8)));
  assert_eq!(15u64.unchecked_into(), U12::from(15));
  assert_eq!(4096u64.failable_into(), None);
  assert_eq!(u64::max_value().failable_into(), None);
}

#[test]
#[should_panic]
fn test_unchecked_into_with_u64() {
  let _ = 4096u64.unchecked_into();
}

#[test]
fn test_failable_into_with_usize() {
  assert_eq!(0usize.failable_into(), Some(U12::min_value()));
  assert_eq!(0usize.unchecked_into(), U12::min_value());
  assert_eq!(15usize.failable_into(), Some(U12::from(15u8)));
  assert_eq!(15usize.unchecked_into(), U12::from(15));
  assert_eq!(4096usize.failable_into(), None);
  assert_eq!(usize::max_value().failable_into(), None);
}

#[test]
#[should_panic]
fn test_unchecked_into_with_usize() {
  let _ = 4096usize.unchecked_into();
}

// MARK: - Tests - Default Value

#[test]
fn test_default() {
  assert_eq!(U12::default(), U12::min_value());
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use errors::RedisError;
use results::RedisResult;
use redis::RedisClient;

pub struct RedisCommand {
    cmd: Vec<u8>,
}

impl<'a> From<&'a mut RedisCommand> for &'a[u8] {
    fn from(command: &mut RedisCommand) -> &[u8] {
        &command.cmd[..]
    }
}

impl RedisCommand {
    pub fn new() -> RedisCommand {
        RedisCommand {
            cmd: vec![],
        }
    }

    pub fn add_cmd<C>(&mut self, command: C) -> &mut RedisCommand where C: ToString {
        self.cmd.extend(command.to_string().into_bytes());
        self
    }

    pub fn add_arg<A>(&mut self, arg: A) -> &mut RedisCommand where A: ToString{
        self.cmd.extend([32].iter().cloned());
        self.cmd.extend(arg.to_string().into_bytes());
        self
    }

    pub fn add_args<A>(&mut self, args: Vec<A>) -> &mut RedisCommand where A: ToString{
        for arg in args {
            self.cmd.extend([32].iter().cloned());
            self.cmd.extend(arg.to_string().into_bytes());
        }
        self
    }

    pub fn add_arg_map(&mut self, args: HashMap<String, String>) -> &mut RedisCommand {
        for (arg, value) in args {
            self.cmd.extend([32].iter().cloned());
            self.cmd.extend(arg.to_string().into_bytes());
            self.cmd.extend([32].iter().cloned());
            self.cmd.extend(value.to_string().into_bytes());
        }
        self
    }

    pub fn add_binary_arg(&mut self, arg: &[u8]) -> &mut RedisCommand {
        self.cmd.extend([32].iter().cloned());
        self.cmd.extend(arg.iter().cloned());
        self
    }

    pub fn end(&mut self) -> &mut RedisCommand {
        self.cmd.extend([13, 10].iter().cloned());
        self
    }
}

macro_rules! generate_command_traits {
    ($(
        fn $func_name:ident$(<$($gen_id:ident: $gen_type:ident),*>)*($($arg_name:ident: $arg_type:ty),*)  {
            $($cmd:ident $bo:expr;)+
        }
    )*)
    =>
    (
        pub trait CommandBuilder {
            $(
                fn $func_name$(<$($gen_id : $gen_type),*>)* (&mut self $(,$arg_name: $arg_type)*) -> &mut RedisCommand;
            )*
        }

        impl CommandBuilder for RedisCommand{
            $(
                fn $func_name$(<$($gen_id : $gen_type),*>)* (&mut self $(,$arg_name: $arg_type)*) -> &mut RedisCommand {
                    $(self.$cmd($bo));*;
                    self.end()
                }
            )*
        }

        pub trait CommandSender {
            $(
                fn $func_name<R: From<RedisResult>, $($($gen_id : $gen_type),*)*> (&mut self $(,$arg_name: $arg_type)*) -> Result<R, RedisError>;
            )*
        }

        impl CommandSender for RedisClient{
            $(
                fn $func_name<R: From<RedisResult>, $($($gen_id : $gen_type),*)*> (&mut self $(,$arg_name: $arg_type)*) -> Result<R, RedisError> {
                    let cmd = &mut RedisCommand::new();
                    cmd.$func_name($($arg_name),*);

                    let res = try!(self.exec_redis_command(cmd));
                    Ok(res.convert::<R>())
                }
            )*
        }
    )
}

generate_command_traits!{
    fn append<K: ToString, V: ToString>(key: K, value: V) {
        add_cmd("APPEND");
        add_arg(key);
        add_arg(value);
    }

    fn auth<P: ToString>(password: P) {
        add_cmd("AUTH");
        add_arg(password);
    }

    fn bgrewriteaof() {
        add_cmd("BGREWRITEAOF");
    }

    fn bgsave() {
        add_cmd("BGSAVE");
    }

    fn bitcount<K: ToString>(key: K) {
        add_cmd("BITCOUNT");
        add_arg(key);
    }

    fn bitcount_range<K: ToString>(key: K, start_range: i64, end_range: i64) {
        add_cmd("BITCOUNT");
        add_arg(key);
        add_arg(start_range);
        add_arg(end_range);
    }

    fn del<K: ToString>(key: K) {
        add_cmd("DEL");
        add_arg(key);
    }

    fn mdel<K: ToString>(keys: Vec<K>){
        add_cmd("DEL");
        add_args(keys);
    }

    fn discard() {
        add_cmd("DISCARD");
    }

    fn exec() {
        add_cmd("EXEC");
    }

    fn exists<K: ToString>(key: K) {
        add_cmd("EXISTS");
        add_arg(key);
    }

    fn mexists<K: ToString>(keys: Vec<K>){
        add_cmd("EXISTS");
        add_args(keys);
    }

    fn expire<K: ToString>(key: K, expiry: i64) {
        add_cmd("EXPIRE");
        add_arg(key);
        add_arg(expiry);
    }

    fn expireat<K: ToString>(key: K, timestamp: i64) {
        add_cmd("EXPIREAT");
        add_arg(key);
        add_arg(timestamp);
    }

    fn get<K: ToString>(key: K) {
        add_cmd("GET");
        add_arg(key);
    }

    fn getrange<K: ToString>(key: K, start_range: i64, end_range: i64) {
        add_cmd("GETRANGE");
        add_arg(key);
        add_arg(start_range);
        add_arg(end_range);
    }

    fn hdel<K: ToString, F: ToString>(key: K, field: F) {
        add_cmd("HDEL");
        add_arg(key);
        add_arg(field);
    }

    fn hmdel<K: ToString, V: ToString>(key: K, fields: Vec<V>) {
        add_cmd("HDEL");
        add_arg(key);
        add_args(fields);
    }

    fn hexists<K: ToString, F: ToString>(key: K, field: F) {
        add_cmd("HEXISTS");
        add_arg(key);
        add_arg(field);
    }

    fn hget<K: ToString, F: ToString>(key: K, field: F) {
        add_cmd("HGET");
        add_arg(key);
        add_arg(field);
    }

    fn hgetall<K: ToString>(key: K) {
        add_cmd("HGETALL");
        add_arg(key);
    }

    fn hincrby<K: ToString, F: ToString>(key: K, field: F, increment: i64) {
        add_cmd("HINCRBY");
        add_arg(key);
        add_arg(field);
        add_arg(increment);
    }

    fn hincrbyfloat<K: ToString, F: ToString>(key: K, field: F, increment: f64) {
        add_cmd("HINCRBYBYFLOAT");
        add_arg(key);
        add_arg(field);
        add_arg(increment);
    }

    fn hkeys<K: ToString>(key: K) {
        add_cmd("HKEYS");
        add_arg(key);
    }

    fn hlen<K: ToString>(key: K) {
        add_cmd("HLEN");
        add_arg(key);
    }

    fn hmget<K: ToString>(key: K, fields: Vec<String>) {
        add_cmd("HMGET");
        add_arg(key);
        add_args(fields);
    }

    fn hmset<K: ToString>(key: K, fields: HashMap<String, String>) {
        add_cmd("HMSET");
        add_arg(key);
        add_arg_map(fields);
    }

    fn hset<K: ToString, F: ToString, V: ToString>(key: K, field: F, value: V) {
        add_cmd("HSET");
        add_arg(key);
        add_arg(field);
        add_arg(value);
    }

    fn hstrlen<K: ToString, F: ToString>(key: K, field: F) {
        add_cmd("HSTRLEN");
        add_arg(key);
        add_arg(field);
    }

    fn hsetnx<K: ToString, F: ToString, V: ToString>(key: K, field: F, value: V) {
        add_cmd("HSETNX");
        add_arg(key);
        add_arg(field);
        add_arg(value);
    }

    fn hvals<K: ToString>(key: K) {
        add_cmd("HVALS");
        add_arg(key);
    }

    fn multi() {
        add_cmd("MULTI");
    }

    fn select(db_index: i32){
        add_cmd("SELECT");
        add_arg(db_index);
    }

    fn set<K: ToString, V: ToString>(key: K, value: V) {
        add_cmd("SET");
        add_arg(key);
        add_arg(value);
    }

    fn set_binary<K: ToString>(key: K, value: &[u8]) {
        add_cmd("SET");
        add_arg(key);
        add_binary_arg(value);
    }

    fn setex<K: ToString, V: ToString>(key: K, value: V, expiry: i64) {
        add_cmd("SET");
        add_arg(key);
        add_arg(value);
        add_arg("EX");
        add_arg(expiry);
    }

    fn psetex<K: ToString, V: ToString>(key: K, value: V, expiry: i64) {
        add_cmd("SET");
        add_arg(key);
        add_arg(value);
        add_arg("PX");
        add_arg(expiry);
    }

    fn setnx<K: ToString, V: ToString>(key: K, value: V) {
        add_cmd("SET");
        add_arg(key);
        add_arg(value);
        add_arg("NX");
    }

    fn setxx<K: ToString, V: ToString>(key: K, value: V) {
        add_cmd("SET");
        add_arg(key);
        add_arg(value);
        add_arg("XX");
    }

    fn setex_nx<K: ToString, V: ToString>(key: K, value: V, expiry: i64) {
        add_cmd("SET");
        add_arg(key);
        add_arg(value);
        add_arg("EX");
        add_arg(expiry);
        add_arg("NX");
    }

    fn setex_xx<K: ToString, V: ToString>(key: K, value: V, expiry: i64) {
        add_cmd("SET");
        add_arg(key);
        add_arg(value);
        add_arg("EX");
        add_arg(expiry);
        add_arg("NX");
    }

    fn psetex_nx<K: ToString, V: ToString>(key: K, value: V, expiry: i64) {
        add_cmd("SET");
        add_arg(key);
        add_arg(value);
        add_arg("PX");
        add_arg(expiry);
        add_arg("NX");
    }

    fn psetex_xx<K: ToString, V: ToString>(key: K, value: V, expiry: i64) {
        add_cmd("SET");
        add_arg(key);
        add_arg(value);
        add_arg("PX");
        add_arg(expiry);
        add_arg("XX");
    }

    fn ttl<K: ToString>(key: K) {
        add_cmd("TTL");
        add_arg(key);
    }

    fn unwatch() {
        add_cmd("UNWATCH");
    }

    fn watch<K: ToString>(key: K) {
        add_cmd("WATCH");
        add_arg(key);
    }

    fn mwatch<K: ToString>(keys: Vec<K>) {
        add_cmd("WATCH");
        add_args(keys);
    }

    fn zadd<K: ToString, V: ToString>(key: K, score: f64, member: V) {
        add_cmd("ZADD");
        add_arg(key);
        add_arg(score);
        add_arg(member);
    }

    fn zadd_binary<K: ToString>(key: K, score: f64, member: &[u8]) {
        add_cmd("ZADD");
        add_arg(key);
        add_arg(score);
        add_binary_arg(member);
    }

    fn zaddnx<K: ToString, V: ToString>(score: f64, key: K, member: V) {
        add_cmd("ZADD");
        add_arg(key);
        add_arg("NX");
        add_arg(score);
        add_arg(member);
    }

    fn zaddxx<K: ToString, V: ToString>(score: f64, key: K, member: V) {
        add_cmd("ZADD");
        add_arg(key);
        add_arg("XX");
        add_arg(score);
        add_arg(member);
    }

    fn zaddnx_ch<K: ToString, V: ToString>(score: f64, key: K, member: V) {
        add_cmd("ZADD");
        add_arg(key);
        add_arg("NX");
        add_arg("CH");
        add_arg(score);
        add_arg(member);
    }

    fn zaddxx_ch<K: ToString, V: ToString>(score: f64, key: K, member: V) {
        add_cmd("ZADD");
        add_arg(key);
        add_arg("XX");
        add_arg("CH");
        add_arg(score);
        add_arg(member);
    }

    fn zcard<K: ToString>(key: K) {
        add_cmd("ZCARD");
        add_arg(key);
    }

    fn zcount<K: ToString, S: ToString, E: ToString>(key: K, start_range: S, end_range: E) {
        add_cmd("ZCOUNT");
        add_arg(key);
        add_arg(start_range);
        add_arg(end_range);
    }

    fn zincrby<K: ToString, V: ToString>(key: K, increment: f64, member: V) {
        add_cmd("ZINCRBY");
        add_arg(key);
        add_arg(increment);
        add_arg(member);
    }

    fn zrange<K: ToString, S: ToString, E: ToString>(key: K, start_range: S, end_range: E) {
        add_cmd("ZRANGE");
        add_arg(key);
        add_arg(start_range);
        add_arg(end_range);
    }

    fn zrange_with_scores<K: ToString, S: ToString, E: ToString>(key: K, start_range: S, end_range: E) {
        add_cmd("ZRANGE");
        add_arg(key);
        add_arg(start_range);
        add_arg(end_range);
        add_arg("WITHSCORES");
    }

}

<commit_msg>add more commands<commit_after>use std::collections::HashMap;
use errors::RedisError;
use results::RedisResult;
use redis::RedisClient;

pub struct RedisCommand {
    cmd: Vec<u8>,
}

impl<'a> From<&'a mut RedisCommand> for &'a[u8] {
    fn from(command: &mut RedisCommand) -> &[u8] {
        &command.cmd[..]
    }
}

impl RedisCommand {
    pub fn new() -> RedisCommand {
        RedisCommand {
            cmd: vec![],
        }
    }

    pub fn add_cmd<C>(&mut self, command: C) -> &mut RedisCommand where C: ToString {
        self.cmd.extend(command.to_string().into_bytes());
        self
    }

    pub fn add_arg<A>(&mut self, arg: A) -> &mut RedisCommand where A: ToString {
        self.cmd.extend([32].iter().cloned());
        self.cmd.extend(arg.to_string().into_bytes());
        self
    }

    pub fn add_args<A>(&mut self, args: Vec<A>) -> &mut RedisCommand where A: ToString {
        for arg in args {
            self.cmd.extend([32].iter().cloned());
            self.cmd.extend(arg.to_string().into_bytes());
        }
        self
    }

    pub fn add_arg_map(&mut self, args: HashMap<String, String>) -> &mut RedisCommand {
        for (arg, value) in args {
            self.cmd.extend([32].iter().cloned());
            self.cmd.extend(arg.to_string().into_bytes());
            self.cmd.extend([32].iter().cloned());
            self.cmd.extend(value.to_string().into_bytes());
        }
        self
    }

    pub fn add_binary_arg(&mut self, arg: &[u8]) -> &mut RedisCommand {
        self.cmd.extend([32].iter().cloned());
        self.cmd.extend(arg.iter().cloned());
        self
    }

    pub fn end(&mut self) -> &mut RedisCommand {
        self.cmd.extend([13, 10].iter().cloned());
        self
    }
}

macro_rules! generate_command_traits {
    ($(
        fn $func_name:ident$(<$($gen_id:ident: $gen_type:ident),*>)*($($arg_name:ident: $arg_type:ty),*)  {
            $($cmd:ident $bo:expr;)+
        }
    )*)
    =>
    (
        pub trait CommandBuilder {
            $(
                fn $func_name$(<$($gen_id : $gen_type),*>)* (&mut self $(,$arg_name: $arg_type)*) -> &mut RedisCommand;
            )*
        }

        impl CommandBuilder for RedisCommand{
            $(
                fn $func_name$(<$($gen_id : $gen_type),*>)* (&mut self $(,$arg_name: $arg_type)*) -> &mut RedisCommand {
                    $(self.$cmd($bo));*;
                    self.end()
                }
            )*
        }

        pub trait CommandSender {
            $(
                fn $func_name<R: From<RedisResult>, $($($gen_id : $gen_type),*)*> (&mut self $(,$arg_name: $arg_type)*) -> Result<R, RedisError>;
            )*
        }

        impl CommandSender for RedisClient{
            $(
                fn $func_name<R: From<RedisResult>, $($($gen_id : $gen_type),*)*> (&mut self $(,$arg_name: $arg_type)*) -> Result<R, RedisError> {
                    let cmd = &mut RedisCommand::new();
                    cmd.$func_name($($arg_name),*);

                    let res = try!(self.exec_redis_command(cmd));
                    Ok(res.convert::<R>())
                }
            )*
        }
    )
}

generate_command_traits!{
    fn append<K: ToString, V: ToString>(key: K, value: V) {
        add_cmd("APPEND");
        add_arg(key);
        add_arg(value);
    }

    fn auth<P: ToString>(password: P) {
        add_cmd("AUTH");
        add_arg(password);
    }

    fn bgrewriteaof() {
        add_cmd("BGREWRITEAOF");
    }

    fn bgsave() {
        add_cmd("BGSAVE");
    }

    fn bitcount<K: ToString>(key: K) {
        add_cmd("BITCOUNT");
        add_arg(key);
    }

    fn bitcount_range<K: ToString>(key: K, start_range: i64, end_range: i64) {
        add_cmd("BITCOUNT");
        add_arg(key);
        add_arg(start_range);
        add_arg(end_range);
    }

    fn del<K: ToString>(key: K) {
        add_cmd("DEL");
        add_arg(key);
    }

    fn mdel<K: ToString>(keys: Vec<K>){
        add_cmd("DEL");
        add_args(keys);
    }

    fn discard() {
        add_cmd("DISCARD");
    }

    fn exec() {
        add_cmd("EXEC");
    }

    fn exists<K: ToString>(key: K) {
        add_cmd("EXISTS");
        add_arg(key);
    }

    fn mexists<K: ToString>(keys: Vec<K>){
        add_cmd("EXISTS");
        add_args(keys);
    }

    fn expire<K: ToString>(key: K, expiry: i64) {
        add_cmd("EXPIRE");
        add_arg(key);
        add_arg(expiry);
    }

    fn expireat<K: ToString>(key: K, timestamp: i64) {
        add_cmd("EXPIREAT");
        add_arg(key);
        add_arg(timestamp);
    }

    fn get<K: ToString>(key: K) {
        add_cmd("GET");
        add_arg(key);
    }

    fn getrange<K: ToString>(key: K, start_range: i64, end_range: i64) {
        add_cmd("GETRANGE");
        add_arg(key);
        add_arg(start_range);
        add_arg(end_range);
    }

    fn hdel<K: ToString, F: ToString>(key: K, field: F) {
        add_cmd("HDEL");
        add_arg(key);
        add_arg(field);
    }

    fn hmdel<K: ToString, V: ToString>(key: K, fields: Vec<V>) {
        add_cmd("HDEL");
        add_arg(key);
        add_args(fields);
    }

    fn hexists<K: ToString, F: ToString>(key: K, field: F) {
        add_cmd("HEXISTS");
        add_arg(key);
        add_arg(field);
    }

    fn hget<K: ToString, F: ToString>(key: K, field: F) {
        add_cmd("HGET");
        add_arg(key);
        add_arg(field);
    }

    fn hgetall<K: ToString>(key: K) {
        add_cmd("HGETALL");
        add_arg(key);
    }

    fn hincrby<K: ToString, F: ToString>(key: K, field: F, increment: i64) {
        add_cmd("HINCRBY");
        add_arg(key);
        add_arg(field);
        add_arg(increment);
    }

    fn hincrbyfloat<K: ToString, F: ToString>(key: K, field: F, increment: f64) {
        add_cmd("HINCRBYBYFLOAT");
        add_arg(key);
        add_arg(field);
        add_arg(increment);
    }

    fn hkeys<K: ToString>(key: K) {
        add_cmd("HKEYS");
        add_arg(key);
    }

    fn hlen<K: ToString>(key: K) {
        add_cmd("HLEN");
        add_arg(key);
    }

    fn hmget<K: ToString>(key: K, fields: Vec<String>) {
        add_cmd("HMGET");
        add_arg(key);
        add_args(fields);
    }

    fn hmset<K: ToString>(key: K, fields: HashMap<String, String>) {
        add_cmd("HMSET");
        add_arg(key);
        add_arg_map(fields);
    }

    fn hset<K: ToString, F: ToString, V: ToString>(key: K, field: F, value: V) {
        add_cmd("HSET");
        add_arg(key);
        add_arg(field);
        add_arg(value);
    }

    fn hstrlen<K: ToString, F: ToString>(key: K, field: F) {
        add_cmd("HSTRLEN");
        add_arg(key);
        add_arg(field);
    }

    fn hsetnx<K: ToString, F: ToString, V: ToString>(key: K, field: F, value: V) {
        add_cmd("HSETNX");
        add_arg(key);
        add_arg(field);
        add_arg(value);
    }

    fn hvals<K: ToString>(key: K) {
        add_cmd("HVALS");
        add_arg(key);
    }

    fn multi() {
        add_cmd("MULTI");
    }

    fn select(db_index: i32){
        add_cmd("SELECT");
        add_arg(db_index);
    }

    fn set<K: ToString, V: ToString>(key: K, value: V) {
        add_cmd("SET");
        add_arg(key);
        add_arg(value);
    }

    fn set_binary<K: ToString>(key: K, value: &[u8]) {
        add_cmd("SET");
        add_arg(key);
        add_binary_arg(value);
    }

    fn setex<K: ToString, V: ToString>(key: K, value: V, expiry: i64) {
        add_cmd("SET");
        add_arg(key);
        add_arg(value);
        add_arg("EX");
        add_arg(expiry);
    }

    fn psetex<K: ToString, V: ToString>(key: K, value: V, expiry: i64) {
        add_cmd("SET");
        add_arg(key);
        add_arg(value);
        add_arg("PX");
        add_arg(expiry);
    }

    fn setnx<K: ToString, V: ToString>(key: K, value: V) {
        add_cmd("SET");
        add_arg(key);
        add_arg(value);
        add_arg("NX");
    }

    fn setxx<K: ToString, V: ToString>(key: K, value: V) {
        add_cmd("SET");
        add_arg(key);
        add_arg(value);
        add_arg("XX");
    }

    fn setex_nx<K: ToString, V: ToString>(key: K, value: V, expiry: i64) {
        add_cmd("SET");
        add_arg(key);
        add_arg(value);
        add_arg("EX");
        add_arg(expiry);
        add_arg("NX");
    }

    fn setex_xx<K: ToString, V: ToString>(key: K, value: V, expiry: i64) {
        add_cmd("SET");
        add_arg(key);
        add_arg(value);
        add_arg("EX");
        add_arg(expiry);
        add_arg("NX");
    }

    fn psetex_nx<K: ToString, V: ToString>(key: K, value: V, expiry: i64) {
        add_cmd("SET");
        add_arg(key);
        add_arg(value);
        add_arg("PX");
        add_arg(expiry);
        add_arg("NX");
    }

    fn psetex_xx<K: ToString, V: ToString>(key: K, value: V, expiry: i64) {
        add_cmd("SET");
        add_arg(key);
        add_arg(value);
        add_arg("PX");
        add_arg(expiry);
        add_arg("XX");
    }

    fn ttl<K: ToString>(key: K) {
        add_cmd("TTL");
        add_arg(key);
    }

    fn unwatch() {
        add_cmd("UNWATCH");
    }

    fn watch<K: ToString>(key: K) {
        add_cmd("WATCH");
        add_arg(key);
    }

    fn mwatch<K: ToString>(keys: Vec<K>) {
        add_cmd("WATCH");
        add_args(keys);
    }

    fn zadd<K: ToString, V: ToString>(key: K, score: f64, member: V) {
        add_cmd("ZADD");
        add_arg(key);
        add_arg(score);
        add_arg(member);
    }

    fn zadd_binary<K: ToString>(key: K, score: f64, member: &[u8]) {
        add_cmd("ZADD");
        add_arg(key);
        add_arg(score);
        add_binary_arg(member);
    }

    fn zaddnx<K: ToString, V: ToString>(score: f64, key: K, member: V) {
        add_cmd("ZADD");
        add_arg(key);
        add_arg("NX");
        add_arg(score);
        add_arg(member);
    }

    fn zaddxx<K: ToString, V: ToString>(score: f64, key: K, member: V) {
        add_cmd("ZADD");
        add_arg(key);
        add_arg("XX");
        add_arg(score);
        add_arg(member);
    }

    fn zaddnx_ch<K: ToString, V: ToString>(score: f64, key: K, member: V) {
        add_cmd("ZADD");
        add_arg(key);
        add_arg("NX");
        add_arg("CH");
        add_arg(score);
        add_arg(member);
    }

    fn zaddxx_ch<K: ToString, V: ToString>(score: f64, key: K, member: V) {
        add_cmd("ZADD");
        add_arg(key);
        add_arg("XX");
        add_arg("CH");
        add_arg(score);
        add_arg(member);
    }

    fn zcard<K: ToString>(key: K) {
        add_cmd("ZCARD");
        add_arg(key);
    }

    fn zcount<K: ToString, S: ToString, E: ToString>(key: K, start_range: S, end_range: E) {
        add_cmd("ZCOUNT");
        add_arg(key);
        add_arg(start_range);
        add_arg(end_range);
    }

    fn zincrby<K: ToString, V: ToString>(key: K, increment: f64, member: V) {
        add_cmd("ZINCRBY");
        add_arg(key);
        add_arg(increment);
        add_arg(member);
    }

    fn zlexcount<K: ToString, S: ToString, E: ToString>(key: K, min: S, max: E) {
        add_cmd("ZLEXCOUNT");
        add_arg(key);
        add_arg(min);
        add_arg(max);
    }

    fn zrem<K: ToString, M: ToString>(key: K, member: M) {
        add_cmd("ZREM");
        add_arg(key);
        add_arg(member);
    }

    fn mzrem<K: ToString, M: ToString>(key: K, members: Vec<M>) {
        add_cmd("ZREM");
        add_arg(key);
        add_args(members);
    }

    fn zrange<K: ToString, S: ToString, E: ToString>(key: K, start_range: S, end_range: E) {
        add_cmd("ZRANGE");
        add_arg(key);
        add_arg(start_range);
        add_arg(end_range);
    }

    fn zrange_with_scores<K: ToString, S: ToString, E: ToString>(key: K, start_range: S, end_range: E) {
        add_cmd("ZRANGE");
        add_arg(key);
        add_arg(start_range);
        add_arg(end_range);
        add_arg("WITHSCORES");
    }

    fn zrevrange<K: ToString, S: ToString, E: ToString>(key: K, start_range: S, end_range: E) {
        add_cmd("ZREVRANGE");
        add_arg(key);
        add_arg(start_range);
        add_arg(end_range);
    }

    fn zrevrange_with_scores<K: ToString, S: ToString, E: ToString>(key: K, start_range: S, end_range: E) {
        add_cmd("ZREVRANGE");
        add_arg(key);
        add_arg(start_range);
        add_arg(end_range);
        add_arg("WITHSCORES");
    }

}

<|endoftext|>


<commit_before>//! Future-aware synchronization
//!
//! This module is enabled with the **`sync`** feature flag.
//!
//! Tasks sometimes need to communicate with each other. This module contains
//! two basic abstractions for doing so:
//!
//! - [oneshot](oneshot/index.html), a way of sending a single value
//!   from one task to another.
//! - [mpsc](mpsc/index.html), a multi-producer, single-consumer channel for
//!   sending values between tasks.
//! - [`Mutex`](struct.Mutex.html), an asynchronous `Mutex`-like type.
//! - [watch](watch/index.html), a single-producer, multi-consumer channel that
//!   only stores the **most recently** sent value.

pub use tokio_sync::{mpsc, oneshot, watch};
pub use tokio_sync::{Mutex, MutexGuard};
<commit_msg>Export sync::Barrier from tokio::sync (#1577)<commit_after>//! Future-aware synchronization
//!
//! This module is enabled with the **`sync`** feature flag.
//!
//! Tasks sometimes need to communicate with each other. This module contains
//! two basic abstractions for doing so:
//!
//! - [oneshot](oneshot/index.html), a way of sending a single value
//!   from one task to another.
//! - [mpsc](mpsc/index.html), a multi-producer, single-consumer channel for
//!   sending values between tasks.
//! - [`Mutex`](struct.Mutex.html), an asynchronous `Mutex`-like type.
//! - [watch](watch/index.html), a single-producer, multi-consumer channel that
//!   only stores the **most recently** sent value.

pub use tokio_sync::Barrier;
pub use tokio_sync::{mpsc, oneshot, watch};
pub use tokio_sync::{Mutex, MutexGuard};
<|endoftext|>


<commit_before>use std::io::IoResult;
use std::io::fs::{mod, PathExtensions};
use std::sync::atomics;
use std::{io, os};

use cargo::util::realpath;

static CARGO_INTEGRATION_TEST_DIR : &'static str = "cargo-integration-tests";

local_data_key!(task_id: uint)

static mut NEXT_ID: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;

pub fn root() -> Path {
    let my_id = *task_id.get().unwrap();
    let path = os::self_exe_path().unwrap()
                  .join(CARGO_INTEGRATION_TEST_DIR)
                  .join(format!("test-{}", my_id));
    realpath(&path).unwrap()
}

pub fn home() -> Path {
    root().join("home")
}

pub trait PathExt {
    fn rm_rf(&self) -> IoResult<()>;
    fn mkdir_p(&self) -> IoResult<()>;
    fn move_into_the_past(&self) -> IoResult<()>;
}

impl PathExt for Path {
    /* Technically there is a potential race condition, but we don't
     * care all that much for our tests
     */
    fn rm_rf(&self) -> IoResult<()> {
        if self.exists() {
            // On windows, apparently git checks out the database with objects
            // set to the permission 444, and apparently you can't unlink a file
            // with permissions 444 because you don't have write permissions.
            // Whow knew!
            //
            // If the rmdir fails due to a permission denied error, then go back
            // and change everything to have write permissions, then remove
            // everything.
            match fs::rmdir_recursive(self) {
                Err(io::IoError { kind: io::PermissionDenied, .. }) => {}
                e => return e,
            }
            for path in try!(fs::walk_dir(self)) {
                try!(fs::chmod(&path, io::UserRWX));
            }
            fs::rmdir_recursive(self)
        } else {
            Ok(())
        }
    }

    fn mkdir_p(&self) -> IoResult<()> {
        fs::mkdir_recursive(self, io::UserDir)
    }

    fn move_into_the_past(&self) -> IoResult<()> {
        if self.is_file() {
            try!(time_travel(self));
        } else {
            for f in try!(fs::walk_dir(self)) {
                if !f.is_file() { continue }
                try!(time_travel(&f));
            }
        }
        return Ok(());

        fn time_travel(path: &Path) -> IoResult<()> {
            let stat = try!(path.stat());

            let hour = 1000 * 3600;
            let newtime = stat.modified - hour;

            // Sadly change_file_times has the same failure mode as the above
            // rmdir_recursive :(
            match fs::change_file_times(path, newtime, newtime) {
                Err(io::IoError { kind: io::PermissionDenied, .. }) => {}
                e => return e,
            }
            try!(fs::chmod(path, stat.perm | io::UserWrite));
            fs::change_file_times(path, newtime, newtime)
        }
    }
}

/// Ensure required test directories exist and are empty
pub fn setup() {
    let my_id = unsafe { NEXT_ID.fetch_add(1, atomics::SeqCst) };
    task_id.replace(Some(my_id));
    debug!("path setup; root={}; home={}", root().display(), home().display());
    root().rm_rf().unwrap();
    home().mkdir_p().unwrap();
}
<commit_msg>Shorten the cargo integration test directory name<commit_after>use std::io::IoResult;
use std::io::fs::{mod, PathExtensions};
use std::sync::atomics;
use std::{io, os};

use cargo::util::realpath;

static CARGO_INTEGRATION_TEST_DIR : &'static str = "cit";

local_data_key!(task_id: uint)

static mut NEXT_ID: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;

pub fn root() -> Path {
    let my_id = *task_id.get().unwrap();
    let path = os::self_exe_path().unwrap()
                  .join(CARGO_INTEGRATION_TEST_DIR)
                  .join(format!("test-{}", my_id));
    realpath(&path).unwrap()
}

pub fn home() -> Path {
    root().join("home")
}

pub trait PathExt {
    fn rm_rf(&self) -> IoResult<()>;
    fn mkdir_p(&self) -> IoResult<()>;
    fn move_into_the_past(&self) -> IoResult<()>;
}

impl PathExt for Path {
    /* Technically there is a potential race condition, but we don't
     * care all that much for our tests
     */
    fn rm_rf(&self) -> IoResult<()> {
        if self.exists() {
            // On windows, apparently git checks out the database with objects
            // set to the permission 444, and apparently you can't unlink a file
            // with permissions 444 because you don't have write permissions.
            // Whow knew!
            //
            // If the rmdir fails due to a permission denied error, then go back
            // and change everything to have write permissions, then remove
            // everything.
            match fs::rmdir_recursive(self) {
                Err(io::IoError { kind: io::PermissionDenied, .. }) => {}
                e => return e,
            }
            for path in try!(fs::walk_dir(self)) {
                try!(fs::chmod(&path, io::UserRWX));
            }
            fs::rmdir_recursive(self)
        } else {
            Ok(())
        }
    }

    fn mkdir_p(&self) -> IoResult<()> {
        fs::mkdir_recursive(self, io::UserDir)
    }

    fn move_into_the_past(&self) -> IoResult<()> {
        if self.is_file() {
            try!(time_travel(self));
        } else {
            for f in try!(fs::walk_dir(self)) {
                if !f.is_file() { continue }
                try!(time_travel(&f));
            }
        }
        return Ok(());

        fn time_travel(path: &Path) -> IoResult<()> {
            let stat = try!(path.stat());

            let hour = 1000 * 3600;
            let newtime = stat.modified - hour;

            // Sadly change_file_times has the same failure mode as the above
            // rmdir_recursive :(
            match fs::change_file_times(path, newtime, newtime) {
                Err(io::IoError { kind: io::PermissionDenied, .. }) => {}
                e => return e,
            }
            try!(fs::chmod(path, stat.perm | io::UserWrite));
            fs::change_file_times(path, newtime, newtime)
        }
    }
}

/// Ensure required test directories exist and are empty
pub fn setup() {
    let my_id = unsafe { NEXT_ID.fetch_add(1, atomics::SeqCst) };
    task_id.replace(Some(my_id));
    debug!("path setup; root={}; home={}", root().display(), home().display());
    root().rm_rf().unwrap();
    home().mkdir_p().unwrap();
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate criterion;
#[macro_use]
extern crate serde_derive;

use std::collections::BTreeMap;
use std::fs::{create_dir_all, File};
use std::io::Write;
use std::path::Path;

use criterion::profiler::Profiler;
use criterion::Criterion;
use handlebars::{to_json, Context, Handlebars, Template};
// use pprof::protos::Message;
// use pprof::ProfilerGuard;
use serde_json::value::Value as Json;

// #[derive(Default)]
// struct CpuProfiler<'a> {
//     guard: Option<ProfilerGuard<'a>>,
// }

// impl<'a> Profiler for CpuProfiler<'a> {
//     fn start_profiling(&mut self, _benchmark_id: &str, benchmark_dir: &Path) {
//         create_dir_all(&benchmark_dir).unwrap();

//         let guard = ProfilerGuard::new(100).unwrap();
//         self.guard = Some(guard);
//     }

//     fn stop_profiling(&mut self, benchmark_id: &str, benchmark_dir: &Path) {
//         if let Ok(ref report) = self.guard.as_ref().unwrap().report().build() {
//             let fg_file_name = benchmark_dir.join(format!("{}.svg", benchmark_id));
//             let fg_file = File::create(fg_file_name).unwrap();
//             report.flamegraph(fg_file).unwrap();

//             let pb_file_name = benchmark_dir.join(format!("{}.pb", benchmark_id));
//             let mut pb_file = File::create(pb_file_name).unwrap();
//             let profile = report.pprof().unwrap();

//             let mut content = Vec::new();
//             profile.encode(&mut content).unwrap();
//             pb_file.write_all(&content).unwrap();
//         };

//         self.guard = None;
//     }
// }

// fn profiled() -> Criterion {
//     Criterion::default().with_profiler(CpuProfiler::default())
// }

#[derive(Serialize)]
struct DataWrapper {
    v: String,
}

#[derive(Serialize)]
struct RowWrapper {
    real: Vec<DataWrapper>,
    dummy: Vec<DataWrapper>,
}

#[derive(Serialize)]
struct NestedRowWrapper {
    parent: Vec<Vec<DataWrapper>>,
}

static SOURCE: &'static str = "

    <title>{{year}}</title>

CSL {{year}}

    {{#each teams}}

      {{name}}: {{score}}

    {{/each}}

";

fn make_data() -> BTreeMap<String, Json> {
    let mut data = BTreeMap::new();

    data.insert("year".to_string(), to_json("2015"));

    let mut teams = Vec::new();

    for v in vec![
        ("Jiangsu", 43u16),
        ("Beijing", 27u16),
        ("Guangzhou", 22u16),
        ("Shandong", 12u16),
    ]
    .iter()
    {
        let (name, score) = *v;
        let mut t = BTreeMap::new();
        t.insert("name".to_string(), to_json(name));
        t.insert("score".to_string(), to_json(score));
        teams.push(t)
    }

    data.insert("teams".to_string(), to_json(&teams));
    data
}

fn parse_template(c: &mut Criterion) {
    c.bench_function("parse_template", move |b| {
        b.iter(|| Template::compile(SOURCE).ok().unwrap())
    });
}

fn render_template(c: &mut Criterion) {
    let mut handlebars = Handlebars::new();
    handlebars
        .register_template_string("table", SOURCE)
        .ok()
        .expect("Invalid template format");

    let ctx = Context::wraps(make_data()).unwrap();
    c.bench_function("render_template", move |b| {
        b.iter(|| handlebars.render_with_context("table", &ctx).ok().unwrap())
    });
}

fn large_loop_helper(c: &mut Criterion) {
    let mut handlebars = Handlebars::new();
    handlebars
        .register_template_string("test", "BEFORE\n{{#each real}}{{this.v}}{{/each}}AFTER")
        .ok()
        .expect("Invalid template format");

    let real: Vec<DataWrapper> = (1..1000)
        .map(|i| DataWrapper {
            v: format!("n={}", i),
        })
        .collect();
    let dummy: Vec<DataWrapper> = (1..1000)
        .map(|i| DataWrapper {
            v: format!("n={}", i),
        })
        .collect();
    let rows = RowWrapper { real, dummy };

    let ctx = Context::wraps(&rows).unwrap();
    c.bench_function("large_loop_helper", move |b| {
        b.iter(|| handlebars.render_with_context("test", &ctx).ok().unwrap())
    });
}

fn large_loop_helper_with_context_creation(c: &mut Criterion) {
    let mut handlebars = Handlebars::new();
    handlebars
        .register_template_string("test", "BEFORE\n{{#each real}}{{this.v}}{{/each}}AFTER")
        .ok()
        .expect("Invalid template format");

    let real: Vec<DataWrapper> = (1..1000)
        .map(|i| DataWrapper {
            v: format!("n={}", i),
        })
        .collect();
    let dummy: Vec<DataWrapper> = (1..1000)
        .map(|i| DataWrapper {
            v: format!("n={}", i),
        })
        .collect();
    let rows = RowWrapper { real, dummy };

    c.bench_function("large_loop_helper_with_context_creation", move |b| {
        b.iter(|| handlebars.render("test", &rows).ok().unwrap())
    });
}

fn large_nested_loop(c: &mut Criterion) {
    let mut handlebars = Handlebars::new();
    handlebars
        .register_template_string(
            "test",
            "BEFORE\n{{#each parent as |child|}}{{#each child}}{{this.v}}{{/each}}{{/each}}AFTER",
        )
        .ok()
        .expect("Invalid template format");

    let parent: Vec<Vec<DataWrapper>> = (1..100)
        .map(|_| {
            (1..10)
                .map(|v| DataWrapper {
                    v: format!("v={}", v),
                })
                .collect()
        })
        .collect();

    let rows = NestedRowWrapper { parent };

    let ctx = Context::wraps(&rows).unwrap();
    c.bench_function("large_nested_loop", move |b| {
        b.iter(|| handlebars.render_with_context("test", &ctx).ok().unwrap())
    });
}

criterion_group!(
    name = benches;
    // config = profiled();
    targets = parse_template, render_template, large_loop_helper, large_loop_helper_with_context_creation,
    large_nested_loop
);
criterion_main!(benches);
<commit_msg>(test) fix benchmark<commit_after>#[macro_use]
extern crate criterion;
#[macro_use]
extern crate serde_derive;

use std::collections::BTreeMap;
// use std::fs::{create_dir_all, File};
// use std::io::Write;
// use std::path::Path;

// use criterion::profiler::Profiler;
use criterion::Criterion;
use handlebars::{to_json, Context, Handlebars, Template};
// use pprof::protos::Message;
// use pprof::ProfilerGuard;
use serde_json::value::Value as Json;

// #[derive(Default)]
// struct CpuProfiler<'a> {
//     guard: Option<ProfilerGuard<'a>>,
// }

// impl<'a> Profiler for CpuProfiler<'a> {
//     fn start_profiling(&mut self, _benchmark_id: &str, benchmark_dir: &Path) {
//         create_dir_all(&benchmark_dir).unwrap();

//         let guard = ProfilerGuard::new(100).unwrap();
//         self.guard = Some(guard);
//     }

//     fn stop_profiling(&mut self, benchmark_id: &str, benchmark_dir: &Path) {
//         if let Ok(ref report) = self.guard.as_ref().unwrap().report().build() {
//             let fg_file_name = benchmark_dir.join(format!("{}.svg", benchmark_id));
//             let fg_file = File::create(fg_file_name).unwrap();
//             report.flamegraph(fg_file).unwrap();

//             let pb_file_name = benchmark_dir.join(format!("{}.pb", benchmark_id));
//             let mut pb_file = File::create(pb_file_name).unwrap();
//             let profile = report.pprof().unwrap();

//             let mut content = Vec::new();
//             profile.encode(&mut content).unwrap();
//             pb_file.write_all(&content).unwrap();
//         };

//         self.guard = None;
//     }
// }

// fn profiled() -> Criterion {
//     Criterion::default().with_profiler(CpuProfiler::default())
// }

#[derive(Serialize)]
struct DataWrapper {
    v: String,
}

#[derive(Serialize)]
struct RowWrapper {
    real: Vec<DataWrapper>,
    dummy: Vec<DataWrapper>,
}

#[derive(Serialize)]
struct NestedRowWrapper {
    parent: Vec<Vec<DataWrapper>>,
}

static SOURCE: &'static str = "

    <title>{{year}}</title>

CSL {{year}}

    {{#each teams}}

      {{name}}: {{score}}

    {{/each}}

";

fn make_data() -> BTreeMap<String, Json> {
    let mut data = BTreeMap::new();

    data.insert("year".to_string(), to_json("2015"));

    let mut teams = Vec::new();

    for v in vec![
        ("Jiangsu", 43u16),
        ("Beijing", 27u16),
        ("Guangzhou", 22u16),
        ("Shandong", 12u16),
    ]
    .iter()
    {
        let (name, score) = *v;
        let mut t = BTreeMap::new();
        t.insert("name".to_string(), to_json(name));
        t.insert("score".to_string(), to_json(score));
        teams.push(t)
    }

    data.insert("teams".to_string(), to_json(&teams));
    data
}

fn parse_template(c: &mut Criterion) {
    c.bench_function("parse_template", move |b| {
        b.iter(|| Template::compile(SOURCE).ok().unwrap())
    });
}

fn render_template(c: &mut Criterion) {
    let mut handlebars = Handlebars::new();
    handlebars
        .register_template_string("table", SOURCE)
        .ok()
        .expect("Invalid template format");

    let ctx = Context::wraps(make_data()).unwrap();
    c.bench_function("render_template", move |b| {
        b.iter(|| handlebars.render_with_context("table", &ctx).ok().unwrap())
    });
}

fn large_loop_helper(c: &mut Criterion) {
    let mut handlebars = Handlebars::new();
    handlebars
        .register_template_string("test", "BEFORE\n{{#each real}}{{this.v}}{{/each}}AFTER")
        .ok()
        .expect("Invalid template format");

    let real: Vec<DataWrapper> = (1..1000)
        .map(|i| DataWrapper {
            v: format!("n={}", i),
        })
        .collect();
    let dummy: Vec<DataWrapper> = (1..1000)
        .map(|i| DataWrapper {
            v: format!("n={}", i),
        })
        .collect();
    let rows = RowWrapper { real, dummy };

    let ctx = Context::wraps(&rows).unwrap();
    c.bench_function("large_loop_helper", move |b| {
        b.iter(|| handlebars.render_with_context("test", &ctx).ok().unwrap())
    });
}

fn large_loop_helper_with_context_creation(c: &mut Criterion) {
    let mut handlebars = Handlebars::new();
    handlebars
        .register_template_string("test", "BEFORE\n{{#each real}}{{this.v}}{{/each}}AFTER")
        .ok()
        .expect("Invalid template format");

    let real: Vec<DataWrapper> = (1..1000)
        .map(|i| DataWrapper {
            v: format!("n={}", i),
        })
        .collect();
    let dummy: Vec<DataWrapper> = (1..1000)
        .map(|i| DataWrapper {
            v: format!("n={}", i),
        })
        .collect();
    let rows = RowWrapper { real, dummy };

    c.bench_function("large_loop_helper_with_context_creation", move |b| {
        b.iter(|| handlebars.render("test", &rows).ok().unwrap())
    });
}

fn large_nested_loop(c: &mut Criterion) {
    let mut handlebars = Handlebars::new();
    handlebars
        .register_template_string(
            "test",
            "BEFORE\n{{#each parent as |child|}}{{#each child}}{{this.v}}{{/each}}{{/each}}AFTER",
        )
        .ok()
        .expect("Invalid template format");

    let parent: Vec<Vec<DataWrapper>> = (1..100)
        .map(|_| {
            (1..10)
                .map(|v| DataWrapper {
                    v: format!("v={}", v),
                })
                .collect()
        })
        .collect();

    let rows = NestedRowWrapper { parent };

    let ctx = Context::wraps(&rows).unwrap();
    c.bench_function("large_nested_loop", move |b| {
        b.iter(|| handlebars.render_with_context("test", &ctx).ok().unwrap())
    });
}

// criterion_group!(
//     name = benches;
//     config = profiled();
//     targets = parse_template, render_template, large_loop_helper, large_loop_helper_with_context_creation,
//     large_nested_loop
// );
criterion_group!(
    benches,
    parse_template,
    render_template,
    large_loop_helper,
    large_loop_helper_with_context_creation,
    large_nested_loop
);
criterion_main!(benches);
<|endoftext|>


<commit_before>#![feature(phase, slicing_syntax)]
#![allow(unused_must_use)]

#[phase(plugin)]
extern crate regex_macros;
extern crate regex;
extern crate core;
extern crate getopts;

use std::io::{stdin, stderr, BufferedWriter};
use std::io::stdio::{stdout_raw};
use std::os::{args, set_exit_status};
use std::{uint, str};

use getopts::{getopts, optopt, optflag, usage};

use Alignment::{Left, Right, Centered};

struct DynVec<T> {
    vec: Vec<T>,
    default: T,
}

impl<T: Clone> DynVec<T> {
    fn new(default: T) -> DynVec<T> {
        DynVec { vec: Vec::new(), default: default }
    }

    fn get(&self, i: uint) -> T {
        if i < self.vec.len() {
            self.vec[i].clone()
        } else {
            self.default.clone()
        }
    }

    fn set(&mut self, index: uint, v: T) {
        let l = self.vec.len();
        if index >= l {
            self.vec.grow(index - l + 1u, self.default.clone());
        }
        self.vec[index] = v
    }

    fn push(&mut self, v: T) {
        self.default = v.clone();
        self.vec.push(v);
    }
}

#[deriving(Clone)]
enum Alignment {
    Left,
    Right,
    Centered,
}

struct Opts {
    str_delim: char,
    out_sep:   Vec<u8>,
    until:     uint,
    unicode:   bool,
    align:     DynVec<Alignment>,
    max_width: DynVec<uint>,
}

fn parse_opts() -> Result<Opts, ()> {
    let args = args();
    let prog_name = &args[0];

    let opts = [
        optopt("o", "", "set the output separator", "output separator"),
        optopt("s", "", "set the string delimiter", "string delimiter"),
        optopt("u", "", "set the maximum column", "until"),
        optflag("U", "", "read as UTF8 and use unicode width"),
        optflag("h", "", "print this help menu"),
    ];
    let matches = match getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => {
            println!("{}", f);
            set_exit_status(1);
            return Err(());
        }
    };
    if matches.opt_present("h") {
        print!("{}", usage(prog_name[], &opts));
        return Err(());
    }
    let unicode = matches.opt_present("U");
    let out_sep = match matches.opt_str("o") {
        Some(s) => s.into_bytes(),
        None => " ".to_string().into_bytes(),
    };
    let str_delim = match matches.opt_str("s") {
        Some(s) => {
            match s.len() {
                0 => 0u8 as char,
                _ => s.as_bytes()[0] as char,
            }
        },
        None => '"',
    };
    let until = match matches.opt_str("u") {
        Some(s) => match s.parse() {
            Some(u) => u,
            None => {
                let _ = writeln!(&mut stderr(), "-u argument has to be a number");
                set_exit_status(1);
                return Err(());
            },
        },
        None => uint::MAX,
    };
    let mut align = DynVec::new(Left);
    let mut max_width = DynVec::new(0u);
    if matches.free.len() > 0 {
        let fmt = &matches.free[0];
        let test = regex!(r"(\d*)([<>=])");
        for c in test.captures_iter(fmt[]) {
            match c.at(1).unwrap() {
                p if p.len() > 0 => max_width.push(p.parse().unwrap()),
                _ => max_width.push(0),
            }
            match c.at(2).unwrap() {
                "<" => align.push(Left),
                ">" => align.push(Right),
                "=" => align.push(Centered),
                _ => unreachable!(),
            }
        }
        max_width.push(0);
    }
    Ok(Opts {
        str_delim: str_delim,
        out_sep: out_sep,
        until: until,
        unicode: unicode,
        align: align,
        max_width: max_width
    })
}

struct Words {
    line: Vec<u8>,
    words: Vec<(uint, uint)>,
}

impl Words {
    fn new(line: Vec<u8>, str_delim: char, until: uint) -> Words {
        let mut words = Vec::new();
        let mut pos = 0;
        loop {
            pos += match line[pos..].iter().position(|&c| !(c as char).is_whitespace()) {
                Some(i) => i,
                None => break,
            };
            if words.len() == until {
                let end = match line[pos..].iter().position(|&c| c=='\n' as u8) {
                    Some(e) => pos + e,
                    None => line.len(),
                };
                words.push((pos, end));
                break;
            }
            let start = pos;
            let mut esc = false;
            let mut string = false;
            for (i, &c) in line[start..].iter().enumerate() {
                if !esc && c == str_delim as u8 {
                    string = !string;
                }
                esc = !esc && c == '\\' as u8;
                if c == '\n' as u8 || (!string && (c == ' ' as u8 || c == '\t' as u8)) {
                    pos += i;
                    break;
                }
            }
            words.push((start, pos));
        }
        Words { line: line, words: words }
    }

    fn iter<'a>(&'a self) -> WordIter<'a> {
        WordIter {
            pos: 0,
            line: &self.line,
            words: &self.words,
        }
    }
}

struct WordIter<'a> {
    pos: uint,
    line: &'a Vec<u8>,
    words: &'a Vec<(uint, uint)>,
}

impl<'a> Iterator<&'a [u8]> for WordIter<'a> {
    fn next(&mut self) -> Option<&'a [u8]> {
        if self.pos < self.words.len() {
            let (start, end) = self.words[self.pos];
            self.pos += 1;
            Some(self.line[start..end])
        } else {
            None
        }
    }
}

fn is_indent(c: u8) -> bool {
    c == ' ' as u8 || c == '\t' as u8
}

fn unsafe_byte_unicode_width(s: &[u8]) -> uint {
    unsafe { str::from_utf8_unchecked(s).width(false) }
}

fn read_as_bytes(opts: &mut Opts) -> (Option<Vec<u8>>, Vec<Words>) {
    let mut stdin = stdin();
    let mut indent: Option<Vec<u8>> = None;
    let mut lines = Vec::new();
    loop {
        let line = match stdin.read_until('\n' as u8) {
            Ok(l) => l,
            Err(..) => break,
        };
        if indent.is_none() {
            let tmp = line.iter().map(|c| *c).take_while(|c| is_indent(*c)).collect();
            indent = Some(tmp);
        }
        let line = Words::new(line, opts.str_delim, opts.until);
        for (i, word) in line.iter().enumerate() {
            if word.len() > opts.max_width.get(i) {
                opts.max_width.set(i, word.len());
            }
        }
        lines.push(line);
    }
    (indent, lines)
}

fn read_as_unicode(opts: &mut Opts) -> (Option<Vec<u8>>, Vec<Words>) {
    let mut stdin = stdin();
    let mut indent: Option<Vec<u8>> = None;
    let mut lines = Vec::new();
    loop {
        // Unicode validation up here
        let line = match stdin.read_line() {
            Ok(l) => l.into_bytes(),
            Err(..) => break,
        };
        if indent.is_none() {
            let tmp = line.iter().map(|c| *c).take_while(|c| is_indent(*c)).collect();
            indent = Some(tmp);
        }
        let line = Words::new(line, opts.str_delim, opts.until);
        for (i, word) in line.iter().enumerate() {
            let width = unsafe_byte_unicode_width(word);
            if width > opts.max_width.get(i) {
                opts.max_width.set(i, width);
            }
        }
        lines.push(line);
    }
    (indent, lines)
}

fn main() {
    let mut opts = match parse_opts() {
        Ok(o) => o,
        Err(..) => return,
    };

    let (indent, lines) = if opts.unicode {
        read_as_unicode(&mut opts)
    } else {
        read_as_bytes(&mut opts)
    };
    if lines.len() == 0 {
        return;
    }
    let indent = indent.unwrap();
    let padding = {
        let max_max_width = *opts.max_width.vec.iter().max().unwrap_or(&0);
        Vec::from_elem(max_max_width, ' ' as u8)
    };

    let mut stdout = BufferedWriter::new(stdout_raw());
    for line in lines.iter() {
        if line.words.len() > 0 {
            stdout.write(indent[]);
        }
        let mut words = line.iter().enumerate().peekable();
        while let Some((i, word)) = words.next() {
            let pad = opts.max_width.get(i) - if opts.unicode {
                unsafe_byte_unicode_width(word)
            } else {
                word.len()
            };
            match opts.align.get(i) {
                Left => {
                    stdout.write(word);
                    if words.peek().is_some() {
                        stdout.write(padding[0..pad]);
                    }
                },
                Right => {
                    stdout.write(padding[0..pad]);
                    stdout.write(word);
                },
                Centered => {
                    stdout.write(padding[0..pad/2]);
                    stdout.write(word);
                    if words.peek().is_some() {
                        stdout.write(padding[0..pad-pad/2]);
                    }
                },
            }
            if words.peek().is_some() {
                stdout.write(opts.out_sep[]);
            }
        }
        stdout.write_str("\n");
    }
}
<commit_msg>use byte literals<commit_after>#![feature(phase, slicing_syntax)]
#![allow(unused_must_use)]

#[phase(plugin)]
extern crate regex_macros;
extern crate regex;
extern crate core;
extern crate getopts;

use std::io::{stdin, stderr, BufferedWriter};
use std::io::stdio::{stdout_raw};
use std::os::{args, set_exit_status};
use std::{uint, str};

use getopts::{getopts, optopt, optflag, usage};

use Alignment::{Left, Right, Centered};

struct DynVec<T> {
    vec: Vec<T>,
    default: T,
}

impl<T: Clone> DynVec<T> {
    fn new(default: T) -> DynVec<T> {
        DynVec { vec: Vec::new(), default: default }
    }

    fn get(&self, i: uint) -> T {
        if i < self.vec.len() {
            self.vec[i].clone()
        } else {
            self.default.clone()
        }
    }

    fn set(&mut self, index: uint, v: T) {
        let l = self.vec.len();
        if index >= l {
            self.vec.grow(index - l + 1u, self.default.clone());
        }
        self.vec[index] = v
    }

    fn push(&mut self, v: T) {
        self.default = v.clone();
        self.vec.push(v);
    }
}

#[deriving(Clone)]
enum Alignment {
    Left,
    Right,
    Centered,
}

struct Opts {
    str_delim: char,
    out_sep:   Vec<u8>,
    until:     uint,
    unicode:   bool,
    align:     DynVec<Alignment>,
    max_width: DynVec<uint>,
}

fn parse_opts() -> Result<Opts, ()> {
    let args = args();
    let prog_name = &args[0];

    let opts = [
        optopt("o", "", "set the output separator", "output separator"),
        optopt("s", "", "set the string delimiter", "string delimiter"),
        optopt("u", "", "set the maximum column", "until"),
        optflag("U", "", "read as UTF8 and use unicode width"),
        optflag("h", "", "print this help menu"),
    ];
    let matches = match getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => {
            println!("{}", f);
            set_exit_status(1);
            return Err(());
        }
    };
    if matches.opt_present("h") {
        print!("{}", usage(prog_name[], &opts));
        return Err(());
    }
    let unicode = matches.opt_present("U");
    let out_sep = match matches.opt_str("o") {
        Some(s) => s.into_bytes(),
        None => " ".to_string().into_bytes(),
    };
    let str_delim = match matches.opt_str("s") {
        Some(s) => {
            match s.len() {
                0 => 0u8 as char,
                _ => s.as_bytes()[0] as char,
            }
        },
        None => '"',
    };
    let until = match matches.opt_str("u") {
        Some(s) => match s.parse() {
            Some(u) => u,
            None => {
                let _ = writeln!(&mut stderr(), "-u argument has to be a number");
                set_exit_status(1);
                return Err(());
            },
        },
        None => uint::MAX,
    };
    let mut align = DynVec::new(Left);
    let mut max_width = DynVec::new(0u);
    if matches.free.len() > 0 {
        let fmt = &matches.free[0];
        let test = regex!(r"(\d*)([<>=])");
        for c in test.captures_iter(fmt[]) {
            match c.at(1).unwrap() {
                p if p.len() > 0 => max_width.push(p.parse().unwrap()),
                _ => max_width.push(0),
            }
            match c.at(2).unwrap() {
                "<" => align.push(Left),
                ">" => align.push(Right),
                "=" => align.push(Centered),
                _ => unreachable!(),
            }
        }
        max_width.push(0);
    }
    Ok(Opts {
        str_delim: str_delim,
        out_sep: out_sep,
        until: until,
        unicode: unicode,
        align: align,
        max_width: max_width
    })
}

struct Words {
    line: Vec<u8>,
    words: Vec<(uint, uint)>,
}

impl Words {
    fn new(line: Vec<u8>, str_delim: char, until: uint) -> Words {
        let mut words = Vec::new();
        let mut pos = 0;
        loop {
            pos += match line[pos..].iter().position(|&c| !(c as char).is_whitespace()) {
                Some(i) => i,
                None => break,
            };
            if words.len() == until {
                let end = match line[pos..].iter().position(|&c| c == b'\n') {
                    Some(e) => pos + e,
                    None => line.len(),
                };
                words.push((pos, end));
                break;
            }
            let start = pos;
            let mut esc = false;
            let mut string = false;
            for (i, &c) in line[start..].iter().enumerate() {
                if !esc && c == str_delim as u8 {
                    string = !string;
                }
                esc = !esc && c == b'\\';
                if c == b'\n' || (!string && (c == b' ' || c == b'\t')) {
                    pos += i;
                    break;
                }
            }
            words.push((start, pos));
        }
        Words { line: line, words: words }
    }

    fn iter<'a>(&'a self) -> WordIter<'a> {
        WordIter {
            pos: 0,
            line: &self.line,
            words: &self.words,
        }
    }
}

struct WordIter<'a> {
    pos: uint,
    line: &'a Vec<u8>,
    words: &'a Vec<(uint, uint)>,
}

impl<'a> Iterator<&'a [u8]> for WordIter<'a> {
    fn next(&mut self) -> Option<&'a [u8]> {
        if self.pos < self.words.len() {
            let (start, end) = self.words[self.pos];
            self.pos += 1;
            Some(self.line[start..end])
        } else {
            None
        }
    }
}

fn is_indent(c: u8) -> bool {
    c == b' ' || c == b'\t'
}

fn unsafe_byte_unicode_width(s: &[u8]) -> uint {
    unsafe { str::from_utf8_unchecked(s).width(false) }
}

fn read_as_bytes(opts: &mut Opts) -> (Option<Vec<u8>>, Vec<Words>) {
    let mut stdin = stdin();
    let mut indent: Option<Vec<u8>> = None;
    let mut lines = Vec::new();
    loop {
        let line = match stdin.read_until(b'\n') {
            Ok(l) => l,
            Err(..) => break,
        };
        if indent.is_none() {
            let tmp = line.iter().map(|c| *c).take_while(|c| is_indent(*c)).collect();
            indent = Some(tmp);
        }
        let line = Words::new(line, opts.str_delim, opts.until);
        for (i, word) in line.iter().enumerate() {
            if word.len() > opts.max_width.get(i) {
                opts.max_width.set(i, word.len());
            }
        }
        lines.push(line);
    }
    (indent, lines)
}

fn read_as_unicode(opts: &mut Opts) -> (Option<Vec<u8>>, Vec<Words>) {
    let mut stdin = stdin();
    let mut indent: Option<Vec<u8>> = None;
    let mut lines = Vec::new();
    loop {
        // Unicode validation up here
        let line = match stdin.read_line() {
            Ok(l) => l.into_bytes(),
            Err(..) => break,
        };
        if indent.is_none() {
            let tmp = line.iter().map(|c| *c).take_while(|c| is_indent(*c)).collect();
            indent = Some(tmp);
        }
        let line = Words::new(line, opts.str_delim, opts.until);
        for (i, word) in line.iter().enumerate() {
            let width = unsafe_byte_unicode_width(word);
            if width > opts.max_width.get(i) {
                opts.max_width.set(i, width);
            }
        }
        lines.push(line);
    }
    (indent, lines)
}

fn main() {
    let mut opts = match parse_opts() {
        Ok(o) => o,
        Err(..) => return,
    };

    let (indent, lines) = if opts.unicode {
        read_as_unicode(&mut opts)
    } else {
        read_as_bytes(&mut opts)
    };
    if lines.len() == 0 {
        return;
    }
    let indent = indent.unwrap();
    let padding = {
        let max_max_width = *opts.max_width.vec.iter().max().unwrap_or(&0);
        Vec::from_elem(max_max_width, b' ')
    };

    let mut stdout = BufferedWriter::new(stdout_raw());
    for line in lines.iter() {
        if line.words.len() > 0 {
            stdout.write(indent[]);
        }
        let mut words = line.iter().enumerate().peekable();
        while let Some((i, word)) = words.next() {
            let pad = opts.max_width.get(i) - if opts.unicode {
                unsafe_byte_unicode_width(word)
            } else {
                word.len()
            };
            match opts.align.get(i) {
                Left => {
                    stdout.write(word);
                    if words.peek().is_some() {
                        stdout.write(padding[0..pad]);
                    }
                },
                Right => {
                    stdout.write(padding[0..pad]);
                    stdout.write(word);
                },
                Centered => {
                    stdout.write(padding[0..pad/2]);
                    stdout.write(word);
                    if words.peek().is_some() {
                        stdout.write(padding[0..pad-pad/2]);
                    }
                },
            }
            if words.peek().is_some() {
                stdout.write(opts.out_sep[]);
            }
        }
        stdout.write_str("\n");
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 The xi-editor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[macro_use]
extern crate log;
extern crate chrono;
extern crate fern;

extern crate dirs;

extern crate xi_core_lib;
extern crate xi_rpc;

use std::collections::HashMap;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};

use xi_core_lib::XiCore;
use xi_rpc::RpcLoop;

const XI_LOG_DIR: &str = "xi-core";
const XI_LOG_FILE: &str = "xi-core.log";

fn get_logging_directory_path<P: AsRef<Path>>(directory: P) -> Result<PathBuf, io::Error> {
    match dirs::data_local_dir() {
        Some(mut log_dir) => {
            log_dir.push(directory);
            Ok(log_dir)
        }
        None => Err(
            io::Error::new(
                io::ErrorKind::NotFound,
                "No standard logging directory known for this platform",
            )
        ),
    }
}

fn path_for_log_file<P: AsRef<Path>>(filename: P) -> Result<PathBuf, io::Error> {
    let mut logging_directory = get_logging_directory_path(get_logfile_directory_name())?;
    // Create the logging directory
    fs::create_dir_all(&logging_directory)?;
    // Pushing the filename to the end
    logging_directory.push(filename.as_ref());
    Ok(logging_directory)
}

fn setup_logging() -> Result<(), fern::InitError> {
    let level_filter = match std::env::var("XI_LOG") {
        Ok(level) => match level.to_lowercase().as_ref() {
            "trace" => log::LevelFilter::Trace,
            "debug" => log::LevelFilter::Debug,
            _ => log::LevelFilter::Info,
        },
        // Default to info
        Err(_) => log::LevelFilter::Info,
    };

    let mut fern_dispatch = fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "{}[{}][{}] {}",
                chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
                record.target(),
                record.level(),
                message,
            ))
        }).level(level_filter)
        .chain(io::stderr());

    let path_result = path_for_log_file(get_logfile_file_name());
    // If the logging_file_path returned successfully, add the logfile capability to fern
    if let Ok(logging_file_path) = &path_result {
        fern_dispatch = fern_dispatch.chain(fern::log_file(logging_file_path)?);
    }

    // Start fern
    fern_dispatch.apply()?;

    // Log details of the fern setup using fern/log
    match &path_result {
        Err(e) => {
            let message = "There was an issue getting the path for the log file";
            warn!("{}: {:?}, falling back to stderr.", message, e);
        }
        Ok(logging_file_path) => info!("Logging to the following file: {:?}", logging_file_path),
    }

    info!("Logging with fern is setup");
    Ok(())
}

fn prepare_logging_path(logfile_config: LogfileConfig) -> Result<PathBuf, io::Error> {
    // Use the file name set in logfile_config or fallback to the default
    let logfile_file_name = match logfile_config.file {
        Some(file_name) => file_name,
        None => XI_LOG_FILE.to_string(),
    };
    // Use the directory name set in logfile_config or fallback to the default
    let logfile_directory_name = match logfile_config.directory {
        Some(dir) => dir,
        None => XI_LOG_DIR.to_string(),
    };

    let mut logging_directory_path = get_logging_directory_path(logfile_directory_name)?;

    // Add the file name & return the full path
    logging_directory_path.push(logfile_file_name);
    Ok(logging_directory_path)
}

struct LogfileConfig {
    directory: Option<String>,
    file: Option<String>,
}

fn get_flags() -> HashMap<String, Option<String>> {
    let mut flags: HashMap<String, Option<String>> = HashMap::new();

    let flag_prefix = "-";
    let mut args_itterator = std::env::args().peekable();
    while let Some(arg) = args_itterator.next() {
        if arg.starts_with(flag_prefix) {
            let key = arg.trim_left_matches(flag_prefix).to_string();

            // Check the next argument doesn't start with the flag prefix
            // map_or accounts for peek returning an Option
            let next_arg_not_a_flag: bool = args_itterator.peek().map_or(false, |val| !val.starts_with(flag_prefix));
            if next_arg_not_a_flag {
                flags.insert(key, args_itterator.next());
            }
        }
    }
    flags
}

fn main() {
    let mut state = XiCore::new();
    let stdin = io::stdin();
    let stdout = io::stdout();
    let mut rpc_looper = RpcLoop::new(stdout);

    if let Err(e) = setup_logging() {
        eprintln!(
            "[ERROR] setup_logging returned error, logging disabled: {:?}",
            e
        );
    }

    match rpc_looper.mainloop(|| stdin.lock(), &mut state) {
        Ok(_) => (),
        Err(err) => error!("xi-core exited with error:\n{:?}", err),
    }
}
<commit_msg>Getting the flags and extracting the values to put into the config<commit_after>// Copyright 2016 The xi-editor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[macro_use]
extern crate log;
extern crate chrono;
extern crate fern;

extern crate dirs;

extern crate xi_core_lib;
extern crate xi_rpc;

use std::collections::HashMap;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};

use xi_core_lib::XiCore;
use xi_rpc::RpcLoop;

const XI_LOG_DIR: &str = "xi-core";
const XI_LOG_FILE: &str = "xi-core.log";

fn get_logging_directory_path<P: AsRef<Path>>(directory: P) -> Result<PathBuf, io::Error> {
    match dirs::data_local_dir() {
        Some(mut log_dir) => {
            log_dir.push(directory);
            Ok(log_dir)
        }
        None => Err(
            io::Error::new(
                io::ErrorKind::NotFound,
                "No standard logging directory known for this platform",
            )
        ),
    }
}

fn path_for_log_file<P: AsRef<Path>>(filename: P) -> Result<PathBuf, io::Error> {
    let mut logging_directory = get_logging_directory_path(get_logfile_directory_name())?;
    // Create the logging directory
    fs::create_dir_all(&logging_directory)?;
    // Pushing the filename to the end
    logging_directory.push(filename.as_ref());
    Ok(logging_directory)
}

fn setup_logging() -> Result<(), fern::InitError> {
    let level_filter = match std::env::var("XI_LOG") {
        Ok(level) => match level.to_lowercase().as_ref() {
            "trace" => log::LevelFilter::Trace,
            "debug" => log::LevelFilter::Debug,
            _ => log::LevelFilter::Info,
        },
        // Default to info
        Err(_) => log::LevelFilter::Info,
    };

    let mut fern_dispatch = fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "{}[{}][{}] {}",
                chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
                record.target(),
                record.level(),
                message,
            ))
        }).level(level_filter)
        .chain(io::stderr());

    let path_result = path_for_log_file(get_logfile_file_name());
    // If the logging_file_path returned successfully, add the logfile capability to fern
    if let Ok(logging_file_path) = &path_result {
        fern_dispatch = fern_dispatch.chain(fern::log_file(logging_file_path)?);
    }

    // Start fern
    fern_dispatch.apply()?;

    // Log details of the fern setup using fern/log
    match &path_result {
        Err(e) => {
            let message = "There was an issue getting the path for the log file";
            warn!("{}: {:?}, falling back to stderr.", message, e);
        }
        Ok(logging_file_path) => info!("Logging to the following file: {:?}", logging_file_path),
    }

    info!("Logging with fern is setup");
    Ok(())
}

fn prepare_logging_path(logfile_config: LogfileConfig) -> Result<PathBuf, io::Error> {
    // Use the file name set in logfile_config or fallback to the default
    let logfile_file_name = match logfile_config.file {
        Some(file_name) => file_name,
        None => XI_LOG_FILE.to_string(),
    };
    // Use the directory name set in logfile_config or fallback to the default
    let logfile_directory_name = match logfile_config.directory {
        Some(dir) => dir,
        None => XI_LOG_DIR.to_string(),
    };

    let mut logging_directory_path = get_logging_directory_path(logfile_directory_name)?;

    // Add the file name & return the full path
    logging_directory_path.push(logfile_file_name);
    Ok(logging_directory_path)
}

struct LogfileConfig {
    directory: Option<String>,
    file: Option<String>,
}

fn get_flags() -> HashMap<String, Option<String>> {
    let mut flags: HashMap<String, Option<String>> = HashMap::new();

    let flag_prefix = "-";
    let mut args_itterator = std::env::args().peekable();
    while let Some(arg) = args_itterator.next() {
        if arg.starts_with(flag_prefix) {
            let key = arg.trim_left_matches(flag_prefix).to_string();

            // Check the next argument doesn't start with the flag prefix
            // map_or accounts for peek returning an Option
            let next_arg_not_a_flag: bool = args_itterator.peek().map_or(false, |val| !val.starts_with(flag_prefix));
            if next_arg_not_a_flag {
                flags.insert(key, args_itterator.next());
            }
        }
    }
    flags
}

fn main() {
    let mut state = XiCore::new();
    let stdin = io::stdin();
    let stdout = io::stdout();
    let mut rpc_looper = RpcLoop::new(stdout);

    let flags: HashMap<String, Option<String>> = get_flags();

    // If the key is set, get the Option within
    let log_dir_flag_option = flags.get("log-dir").cloned().unwrap_or(None);
    let log_file_flag_option = flags.get("log-file").cloned().unwrap_or(None);

    let logfile_config = LogfileConfig {
        directory: log_dir_flag_option,
        file: log_file_flag_option,
    };

    if let Err(e) = setup_logging() {
        eprintln!(
            "[ERROR] setup_logging returned error, logging disabled: {:?}",
            e
        );
    }

    match rpc_looper.mainloop(|| stdin.lock(), &mut state) {
        Ok(_) => (),
        Err(err) => error!("xi-core exited with error:\n{:?}", err),
    }
}
<|endoftext|>


<commit_before>extern crate kiss3d;
extern crate nalgebra as na;

use kiss3d::light::Light;
use kiss3d::window::Window;
use na::vector;
use na::{Translation, UnitQuaternion, Vector3};

fn main() {
    env_logger::init();
    let mut window = Window::new("Kiss3d: cube");
    let mut c = window.add_cube(0.1, 0.1, 0.1);

    c.set_color(0.0, 1.0, 0.0);

    window.set_light(Light::StickToCamera);

    let rot = UnitQuaternion::from_axis_angle(&Vector3::y_axis(), 0.014);

    let rot_1 = UnitQuaternion::from_axis_angle(&Vector3::x_axis(), -0.5);
    c.append_rotation(&rot_1);

    //c.append_translation(&Translation{ vector: vector!(0.05, 0.05, 0.05) });

    let mut c2 = window.add_cube(0.1, 0.1, 0.1);
    c2.set_color(0.0, 0.0, 1.0);
    c2.append_translation(&Translation{ vector: vector!(0.1, 0.1, 0.1) });
    c2.append_rotation(&rot_1);

    while window.render() {
        c.append_rotation(&rot);
        c2.append_rotation(&rot);
    }
}<commit_msg>Display planes solution in rust.<commit_after>extern crate kiss3d;
extern crate nalgebra as na;

use kiss3d::light::Light;
use kiss3d::window::Window;
use na::vector;
use na::{Translation, UnitQuaternion, Vector3};

fn main() {
    env_logger::init();
    let mut window = Window::new("Kiss3d: cube");
    window.set_light(Light::StickToCamera);

    let mut cubes = Vec::new();
    for _ in 0..27 {
        let c = window.add_cube(0.08, 0.08, 0.08);
        cubes.push(c);
    }

    for i in 0..9 {
        cubes[i].set_color(1., 0., 0.);
    }
    for i in 9..27 {
        cubes[i].set_color(0., 1., 0.);
    }
    for i in 18..27 {
        cubes[i].set_color(0., 0., 1.);
    }

    let rot1 = UnitQuaternion::from_axis_angle(&Vector3::x_axis(), -0.5);
    for i in 0..27 {
        cubes[i].append_rotation(&rot1);
    }

    for i in 0..27 {
        let r = (i % 3) as f32 * 0.1;
        let c = (i / 9) as f32 * 0.1;
        let d = (i % 9) as f32 * 0.05;
        cubes[i].append_translation(&Translation { vector: vector!(r, c, d) });
    }

    let rot = UnitQuaternion::from_axis_angle(&Vector3::y_axis(), 0.014);
    while window.render() {
        for i in 0..27 {
            cubes[i].append_rotation(&rot);
        }
    }
}<|endoftext|>


<commit_before>struct Record {
	// TODO: do we even need this?
	len: uint,
	data: Vec<u8>,
}

impl Record {
	/* move semantics, no copy */
	pub fn new(len: uint, data: Vec<u8>) -> Record {
		Record {len: len, data: data}
	}

	pub fn get_data<'a>(&'a self) -> &'a [u8] {
		self.data.as_slice()
	}
}

struct SPSegment;

/* our newtype struct: create a TID type as an alias to u64 */
struct TID(u64);

impl SPSegment {
	pub fn insert(r: Record) -> TID {
		TID(0_u64)
	}

	pub fn remove(tid: TID) -> bool {
		false
	}

	pub fn lookup(tid: TID) -> Record {
		// TODO
		Record {len: 1, data: vec!(1)}
	}

	pub fn update(tid: TID, r: Record) -> bool {
		false
	}
}

#[test]
fn main() {
}
<commit_msg>Added data structure to contain schema<commit_after>enum SqlType {
	Char(uint),
	Varchar(uint),
	Integer,
}

enum SqlAttribute {
	Null,
	NotNull,
}

struct Column {
	name: ~str,
	datatype: SqlType,
	attributes: Vec<SqlAttribute>,
}

struct Relation {
	name: ~str,
	columns: Vec<Column>,
}

struct Schema {
	relations: Vec<Relation>,
}

struct Record {
	// TODO: do we even need this?
	len: uint,
	data: Vec<u8>,
}

impl Record {
	/* move semantics, no copy */
	pub fn new(len: uint, data: Vec<u8>) -> Record {
		Record {len: len, data: data}
	}

	pub fn get_data<'a>(&'a self) -> &'a [u8] {
		self.data.as_slice()
	}
}

struct SPSegment;

/* our newtype struct: create a TID type as an alias to u64 */
struct TID(u64);

impl SPSegment {
	pub fn insert(r: Record) -> TID {
		TID(0_u64)
	}

	pub fn remove(tid: TID) -> bool {
		false
	}

	pub fn lookup(tid: TID) -> Record {
		// TODO
		Record {len: 1, data: vec!(1)}
	}

	pub fn update(tid: TID, r: Record) -> bool {
		false
	}
}

#[test]
fn main() {
}
<|endoftext|>