<commit_before>#![allow(dead_code)]

extern crate plank_errors;
extern crate plank_syntax;
extern crate plank_frontend;
extern crate plank_ir;
extern crate plank_interpreter;

mod test_parser;

use std::fs;
use std::io::prelude::*;
use plank_errors::reporter::Diagnostic;

fn build_code(source: &str) -> Result<plank_ir::Program, Vec<Diagnostic>> {
    let reporter = plank_errors::Reporter::new();
    let tokens = plank_syntax::lex(source, reporter.clone());
    let program = plank_syntax::parse(tokens, reporter.clone());
    plank_frontend::compile(&program, reporter.clone()).map_err(|()| {
        reporter.get_diagnostics()
    })
}

#[derive(Debug)]
enum TestResult {
    BuildFail(Vec<Diagnostic>),
    BadBuildPass(Vec<test_parser::Error>),
    BuildErrorMismatch(Vec<Diagnostic>, Vec<test_parser::Error>),
    IoMismatch { expected: Vec<u8>, got: Vec<u8> },
    MalformedTest(test_parser::ParseError),
    InterpreterExit(i32),
    InterpreterError(plank_interpreter::Error),
    Ok,
}

fn match_build_errors(expected: Vec<test_parser::Error>, got: Vec<Diagnostic>) -> TestResult {
    let mut unmatched = Vec::new();
    for err in expected {
        let mut matched = false;
        for actual in &got {
            if let Some(span) = actual.primary_span {
                if span.start.line == err.line && actual.message.contains(&err.message) {
                    matched = true;
                    break;
                }
            }
        }
        if !matched {
            unmatched.push(err);
        }
    }
    if unmatched.is_empty() {
        TestResult::Ok
    } else {
        TestResult::BuildErrorMismatch(got, unmatched)
    }
}

fn interpret_program(program: plank_ir::Program, input: Vec<u8>, output: Vec<u8>) -> TestResult {
    let mut input = ::std::io::Cursor::new(input);
    let mut actual_output = Vec::new();
    match plank_interpreter::run_program(&program, &mut input, &mut actual_output) {
        Ok(0) if actual_output == output => TestResult::Ok,
        Ok(0) => TestResult::IoMismatch { expected: output, got: actual_output },
        Ok(code) => TestResult::InterpreterExit(code),
        Err(e) => TestResult::InterpreterError(e),
    }
}

fn run_test(source: &str) -> TestResult {
    let expectation = match test_parser::parse_test(source) {
        Ok(e) => e,
        Err(e) => return TestResult::MalformedTest(e),
    };
    match expectation {
        test_parser::Expectation::BuildErrors(errors) => {
            match build_code(source) {
                Ok(_) => TestResult::BadBuildPass(errors),
                Err(got) => match_build_errors(errors, got),
            }
        }
        test_parser::Expectation::Io { input, output} => {
            match build_code(source) {
                Ok(program) => interpret_program(program, input, output),
                Err(e) => TestResult::BuildFail(e),
            }
        }
        test_parser::Expectation::BuildSuccess => {
            match build_code(source) {
                Ok(_) => TestResult::Ok,
                Err(e) => TestResult::BuildFail(e),
            }
        }
    }
}

fn main() {
    for dir in TEST_DIRS {
        let entries = fs::read_dir(dir).expect("failed to read dir");
        for entry in entries {
            let entry = entry.unwrap();
            if !entry.file_type().unwrap().is_file() {
                continue;
            }
            let mut file = fs::File::open(entry.path()).unwrap();
            let mut contents = String::new();
            file.read_to_string(&mut contents).unwrap();
            let test_result = run_test(&contents);
            if let TestResult::Ok = test_result {
                println!("test {} ... ok", entry.path().display());
            } else {
                println!("test {} ... FAIL", entry.path().display());
                println!("{:?}", test_result);
            }
        }
    }
}

const TEST_DIRS: &'static [&'static str] = &[
    "./examples",
    "./tests/compile-fail",
    "./tests/pass",
];
<commit_msg>improve failure reporting in test runner<commit_after>#![allow(dead_code)]

extern crate plank_errors;
extern crate plank_syntax;
extern crate plank_frontend;
extern crate plank_ir;
extern crate plank_interpreter;

mod test_parser;

use std::fs;
use std::io;
use std::io::prelude::*;
use plank_errors::reporter::Diagnostic;

fn build_code(source: &str) -> Result<plank_ir::Program, Vec<Diagnostic>> {
    let reporter = plank_errors::Reporter::new();
    let tokens = plank_syntax::lex(source, reporter.clone());
    let program = plank_syntax::parse(tokens, reporter.clone());
    plank_frontend::compile(&program, reporter.clone()).map_err(|()| {
        reporter.get_diagnostics()
    })
}

#[derive(Debug)]
enum TestResult {
    BuildFail(Vec<Diagnostic>),
    BadBuildPass(Vec<test_parser::Error>),
    BuildErrorMismatch(Vec<Diagnostic>, Vec<test_parser::Error>),
    IoMismatch { expected: Vec<u8>, got: Vec<u8> },
    MalformedTest(test_parser::ParseError),
    InterpreterExit(i32),
    InterpreterError(plank_interpreter::Error),
    Ok,
}

fn match_build_errors(expected: Vec<test_parser::Error>, got: Vec<Diagnostic>) -> TestResult {
    let mut unmatched = Vec::new();
    for err in expected {
        let mut matched = false;
        for actual in &got {
            if let Some(span) = actual.primary_span {
                if span.start.line == err.line && actual.message.contains(&err.message) {
                    matched = true;
                    break;
                }
            }
        }
        if !matched {
            unmatched.push(err);
        }
    }
    if unmatched.is_empty() {
        TestResult::Ok
    } else {
        TestResult::BuildErrorMismatch(got, unmatched)
    }
}

fn interpret_program(program: plank_ir::Program, input: Vec<u8>, output: Vec<u8>) -> TestResult {
    let mut input = ::std::io::Cursor::new(input);
    let mut actual_output = Vec::new();
    match plank_interpreter::run_program(&program, &mut input, &mut actual_output) {
        Ok(0) if actual_output == output => TestResult::Ok,
        Ok(0) => TestResult::IoMismatch { expected: output, got: actual_output },
        Ok(code) => TestResult::InterpreterExit(code),
        Err(e) => TestResult::InterpreterError(e),
    }
}

fn run_test(source: &str) -> TestResult {
    let expectation = match test_parser::parse_test(source) {
        Ok(e) => e,
        Err(e) => return TestResult::MalformedTest(e),
    };
    match expectation {
        test_parser::Expectation::BuildErrors(errors) => {
            match build_code(source) {
                Ok(_) => TestResult::BadBuildPass(errors),
                Err(got) => match_build_errors(errors, got),
            }
        }
        test_parser::Expectation::Io { input, output} => {
            match build_code(source) {
                Ok(program) => interpret_program(program, input, output),
                Err(e) => TestResult::BuildFail(e),
            }
        }
        test_parser::Expectation::BuildSuccess => {
            match build_code(source) {
                Ok(_) => TestResult::Ok,
                Err(e) => TestResult::BuildFail(e),
            }
        }
    }
}

fn run_tests() -> io::Result<Vec<(String, String, TestResult)>> {
    let mut test_results = Vec::new();
    for dir in TEST_DIRS {
        for entry in fs::read_dir(dir)? {
            let entry = entry?;
            if !entry.file_type()?.is_file() {
                continue;
            }
            let mut file = fs::File::open(entry.path())?;
            let mut source = String::new();
            file.read_to_string(&mut source)?;
            let test_result = run_test(&source);
            let test_name = entry.path().display().to_string();
            if let TestResult::Ok = test_result {
                println!("test {} ... ok", test_name);
            } else {
                println!("test {} ... FAIL", test_name);
            }
            test_results.push((test_name, source, test_result));
        }
    }
    Ok(test_results)
}

fn print_expected_errors(errors: &[test_parser::Error]) {
    for err in errors {
        println!("at line {}: {}", err.line + 1, err.message);
    }
}

fn print_output(out: &[u8]) {
    for &byte in out {
        if byte < 32 || byte >= 127 || byte == b'\\' {
            print!("\\x{:>02X}", byte);
        } else {
            print!("{}", byte as char);
        }
    }
    println!();
}

fn report_results(results: &[(String, String, TestResult)]) {
    let mut passed = 0;
    for &(ref name, ref source, ref result) in results {
        match *result {
            TestResult::Ok => passed += 1,
            TestResult::BuildFail(ref diagnostics) => {
                println!("========================================");
                println!("test {}", name);
                println!("unexpected build failure");
                plank_errors::printer::print_diagnostics(source, diagnostics);
                println!();
            }
            TestResult::BadBuildPass(ref expected) => {
                println!("========================================");
                println!("test {}", name);
                println!("build passed but expected failure");
                print_expected_errors(expected);
            }
            TestResult::BuildErrorMismatch(ref got, ref expected) => {
                println!("========================================");
                println!("test {}", name);
                println!("build error mismatch");
                println!(">> unmatched errors:");
                print_expected_errors(expected);
                println!(">> actual errors:");
                plank_errors::printer::print_diagnostics(source, got);
                println!();
            }
            TestResult::IoMismatch { ref expected, ref got } => {
                println!("========================================");
                println!("test {}", name);
                println!("wrong output");
                print!("Expected: ");
                print_output(expected);
                print!("Got:      ");
                print_output(got);
                println!();
            }
            TestResult::MalformedTest(ref err) => {
                println!("========================================");
                println!("test {}", name);
                println!("malformed test");
                println!("{}", err);
                println!();
            }
            TestResult::InterpreterExit(code) => {
                println!("========================================");
                println!("test {}", name);
                println!("interpreted program exited with code {}", code);
                println!();
            }
            TestResult::InterpreterError(ref err) => {
                println!("========================================");
                println!("test {}", name);
                println!("interpreted program crashed");
                match *err {
                    plank_interpreter::Error::BadDeref => {
                        println!("invalid memory access");
                    }
                    plank_interpreter::Error::DivisionByZero => {
                        println!("division by zero");
                    }
                    plank_interpreter::Error::MissingSymbol(_) => {
                        println!("missing symbol definition");
                    }
                    plank_interpreter::Error::Io(ref err) => {
                        println!("io error: {}", err);
                    }
                }
                println!();
            }
        }
    }
    println!("========================================");
    println!("tests:  {}", results.len());
    println!("passed: {}", passed);
    println!("failed: {}", results.len() - passed);
}

fn main() {
    match run_tests() {
        Ok(results) => report_results(&results),
        Err(e) => println!("io error: {}", e),
    }
}

const TEST_DIRS: &'static [&'static str] = &[
    // test examples because obviously we want the
    // examples people come accross to build successfully
    "./examples",
    "./tests/compile-fail",
    "./tests/pass",
];
<|endoftext|>


<commit_before>#![feature(test)]

extern crate concrust;
extern crate test;
#[macro_use]
extern crate expectest;

pub use concrust::queue::ArrayBlockingQueue;
pub use concrust::queue::BlockingQueue;

pub use expectest::prelude::be_ok;

pub use std::thread;
pub use std::thread::JoinHandle;
pub use std::sync::{Arc, Barrier};

const NUMBER_OF_ELEMENTS: i64 = 1000;

#[bench]
fn consumer_producer_default_queue_size(bencher: &mut test::Bencher) {
    // queue size will be 16
    let queue: ArrayBlockingQueue<i64> = ArrayBlockingQueue::new();
    let barrier = Arc::new(Barrier::new(3));
    let result = sum(NUMBER_OF_ELEMENTS);
    bencher.iter(
        || {
            let c_handle = spawn_consumer(&queue, &barrier);
            let p_handle = spawn_producer(&queue, &barrier);
            barrier.wait();
            expect!(c_handle.join()).to(be_ok().value(result));
            p_handle.join()
        }
    );
}

#[bench]
fn consumer_producer_small_queue_size(bencher: &mut test::Bencher) {
            let queue_size = (NUMBER_OF_ELEMENTS / 20) as usize;
            // queue size will be 1000 / 20 >> 64
            let queue: ArrayBlockingQueue<i64> = ArrayBlockingQueue::with_capacity(queue_size);
            let barrier = Arc::new(Barrier::new(3));
            let result = sum(NUMBER_OF_ELEMENTS);
            bencher.iter(
                || {
                    let c_handle = spawn_consumer(&queue, &barrier);
                    let p_handle = spawn_producer(&queue, &barrier);
                    barrier.wait();
                    expect!(c_handle.join()).to(be_ok().value(result));
                    p_handle.join()
                }
            );
        }

#[bench]
fn consumer_producer_large_queue_size(bencher: &mut test::Bencher) {
    let queue_size = (NUMBER_OF_ELEMENTS / 2) as usize;
    // queue size will be 1000 / 2 >> 512
    let queue: ArrayBlockingQueue<i64> = ArrayBlockingQueue::with_capacity(queue_size);
    let barrier = Arc::new(Barrier::new(3));
    let result = sum(NUMBER_OF_ELEMENTS);
    bencher.iter(
        || {
            let c_handle = spawn_consumer(&queue, &barrier);
            let p_handle = spawn_producer(&queue, &barrier);
            barrier.wait();
            expect!(c_handle.join()).to(be_ok().value(result));
            p_handle.join()
        }
    );
}

pub fn sum(last: i64) -> i64 {
    (last - 1) * last / 2
}

pub fn spawn_consumer<'q, 'b>(queue: &'q ArrayBlockingQueue<i64>, barrier: &'b Arc<Barrier>) -> JoinHandle<i64> {
    let consume = queue.clone();
    let barrier_cons = barrier.clone();
    thread::spawn(
        move || {
            barrier_cons.wait();
            let mut sum = 0;
            for _ in 0..NUMBER_OF_ELEMENTS {
                sum += consume.dequeue();
            }
            sum
        }
    )
}

pub fn spawn_producer<'q, 'b>(queue: &'q ArrayBlockingQueue<i64>, barrier: &'b Arc<Barrier>) -> JoinHandle<()> {
    let produce = queue.clone();
    let barrier_prod = barrier.clone();
    thread::spawn(
        move || {
            barrier_prod.wait();
            for i in 0..NUMBER_OF_ELEMENTS {
                produce.enqueue(i);
            }
        }
    )
}
<commit_msg>MCMP SCMP benchmarks<commit_after>#![feature(test)]

extern crate concrust;
extern crate test;
#[macro_use]
extern crate expectest;

pub use concrust::queue::ArrayBlockingQueue;
pub use concrust::queue::BlockingQueue;

pub use expectest::prelude::{be_equal_to, be_ok};

pub use std::thread;
pub use std::thread::JoinHandle;
pub use std::sync::{Arc, Barrier};
pub use std::result::Result;

const NUMBER_OF_ELEMENTS: i64 = 1000;
const NUMBER_OF_PROCCESS: i64 = 5;

#[bench]
fn multiple_consumers_multiple_producer_default_queue_size(bencher: &mut test::Bencher) {
    let (operation_number, expected_result) = multiple_consumers_producer_setup();
    bencher.iter(
        || {
            let actual_result = multiple_consumers_multiple_producer_iter(
                ArrayBlockingQueue::new(),
                Arc::new(Barrier::new(11)),
                operation_number
            );
            expect!(actual_result).to(be_equal_to(expected_result));
        }
    );
}

#[bench]
fn multiple_consumers_multiple_producer_small_queue_size(bencher: &mut test::Bencher) {
    let (operation_number, expected_result) = multiple_consumers_producer_setup();
    bencher.iter(
        || {
            let actual_result = multiple_consumers_multiple_producer_iter(
                ArrayBlockingQueue::with_capacity((NUMBER_OF_ELEMENTS / 20) as usize),
                Arc::new(Barrier::new(11)),
                operation_number
            );
            expect!(actual_result).to(be_equal_to(expected_result));
        }
    );
}

#[bench]
fn multiple_consumers_multiple_producer_large_queue_size(bencher: &mut test::Bencher) {
    let (operation_number, expected_result) = multiple_consumers_producer_setup();
    bencher.iter(
        || {
            let actual_result = multiple_consumers_multiple_producer_iter(
                ArrayBlockingQueue::with_capacity((NUMBER_OF_ELEMENTS / 2) as usize),
                Arc::new(Barrier::new(11)),
                operation_number
            );
            expect!(actual_result).to(be_equal_to(expected_result));
        }
    );
}

fn multiple_consumers_multiple_producer_iter(queue: ArrayBlockingQueue<i64>, barrier: Arc<Barrier>, oper: i64) -> i64 {
    let mut consumers = Vec::with_capacity(NUMBER_OF_PROCCESS as usize);
    for _ in 0..NUMBER_OF_PROCCESS {
        consumers.push(spawn_consumer(&queue, &barrier, oper));
        spawn_producer(&queue, &barrier, oper);
    }
    barrier.wait();
    consumers.into_iter().map(|c| c.join().unwrap()).fold(0, |acc, v| { acc + v } )
}

fn multiple_consumers_producer_setup() -> (i64, i64) {
    let operation_number = NUMBER_OF_ELEMENTS / NUMBER_OF_PROCCESS;
    (operation_number, sum(operation_number) * NUMBER_OF_PROCCESS)
}

#[bench]
fn single_consumers_multiple_producer_default_queue_size(bencher: &mut test::Bencher) {
    let (operation_number, expected_result) = multiple_consumers_producer_setup();
    bencher.iter(
        || {
            let actual_result = single_consumers_multiple_producer_iter(
                ArrayBlockingQueue::new(),
                Arc::new(Barrier::new(7)),
                operation_number
            );
            expect!(actual_result).to(be_equal_to(expected_result))
        }
    );
}

#[bench]
fn single_consumers_multiple_producer_small_queue_size(bencher: &mut test::Bencher) {
    let (operation_number, expected_result) = multiple_consumers_producer_setup();
    bencher.iter(
        || {
            let actual_result = single_consumers_multiple_producer_iter(
                ArrayBlockingQueue::with_capacity((NUMBER_OF_PROCCESS / 20) as usize),
                Arc::new(Barrier::new(7)),
                operation_number
            );
            expect!(actual_result).to(be_equal_to(expected_result))
        }
    );
}

#[bench]
fn single_consumers_multiple_producer_large_queue_size(bencher: &mut test::Bencher) {
    let (oper, expected_result) = multiple_consumers_producer_setup();
    bencher.iter(
        || {
            let actual_result = single_consumers_multiple_producer_iter(
                ArrayBlockingQueue::with_capacity((NUMBER_OF_PROCCESS / 2) as usize),
                Arc::new(Barrier::new(7)),
                oper
            );
            expect!(actual_result).to(be_equal_to(expected_result))
        }
    );
}

fn single_consumers_multiple_producer_iter(queue: ArrayBlockingQueue<i64>, barrier: Arc<Barrier>, oper: i64) -> i64{
    let c_handle = spawn_consumer(&queue, &barrier, NUMBER_OF_PROCCESS);
    for _ in 0..NUMBER_OF_PROCCESS {
        spawn_producer(&queue, &barrier, oper);
    }
    barrier.wait();
    c_handle.join().unwrap()
}

#[bench]
fn single_consumer_single_producer_default_queue_size(bencher: &mut test::Bencher) {
    let expected_result = single_consumer_single_producer_setup();
    bencher.iter(
        || {
            let actual_result = single_consumer_single_producer_iter(
                ArrayBlockingQueue::new(),
                Arc::new(Barrier::new(3))
            );
            expect!(actual_result).to(be_equal_to(expected_result));
        }
    );
}

#[bench]
fn single_consumer_single_producer_small_queue_size(bencher: &mut test::Bencher) {
    let expected_result = single_consumer_single_producer_setup();
    bencher.iter(
        || {
            let actual_result = single_consumer_single_producer_iter(
                ArrayBlockingQueue::with_capacity((NUMBER_OF_ELEMENTS / 20) as usize),
                Arc::new(Barrier::new(3))
            );
            expect!(actual_result).to(be_equal_to(expected_result));
        }
    );
}

#[bench]
fn single_consumer_single_producer_large_queue_size(bencher: &mut test::Bencher) {
    let expected_result = single_consumer_single_producer_setup();
    bencher.iter(
        || {
            let actual_result = single_consumer_single_producer_iter(
                ArrayBlockingQueue::with_capacity((NUMBER_OF_ELEMENTS / 2) as usize),
                Arc::new(Barrier::new(3))
            );
            expect!(actual_result).to(be_equal_to(expected_result));
        }
    );
}

fn single_consumer_single_producer_iter(queue: ArrayBlockingQueue<i64>, barrier: Arc<Barrier>) -> i64 {
    let handle = spawn_consumer(&queue, &barrier, NUMBER_OF_ELEMENTS);
    spawn_producer(&queue, &barrier, NUMBER_OF_ELEMENTS);
    barrier.wait();
    handle.join().unwrap()
}

fn single_consumer_single_producer_setup() -> i64 {
    sum(NUMBER_OF_ELEMENTS)
}

pub fn sum(last: i64) -> i64 {
    (last - 1) * last / 2
}

pub fn spawn_consumer<'q, 'b>(queue: &'q ArrayBlockingQueue<i64>, barrier: &'b Arc<Barrier>, oper: i64) -> JoinHandle<i64> {
    let consume = queue.clone();
    let barrier_cons = barrier.clone();
    thread::spawn(
        move || {
            barrier_cons.wait();
            let mut sum = 0;
            for _ in 0..oper {
                sum += consume.dequeue();
            }
            sum
        }
    )
}

pub fn spawn_producer<'q, 'b>(queue: &'q ArrayBlockingQueue<i64>, barrier: &'b Arc<Barrier>, oper: i64) {
    let produce = queue.clone();
    let barrier_prod = barrier.clone();
    thread::spawn(
        move || {
            barrier_prod.wait();
            for i in 0..oper {
                produce.enqueue(i);
            }
        }
    );
}
<|endoftext|>


<commit_before>
#[allow(unused_variables)]
fn main() {
// BEGIN_CODE
    let mut vals = [-1, -2, -3, 1, 2, 3, 0];
    let p = 2;

    vals.sort_by(|a :&isize, b :&isize|
                    a.pow(p).cmp(&b.pow(p)));

// END_CODE
}

<commit_msg>Minor change<commit_after>#[allow(unused_variables)]
fn main() {
// BEGIN_CODE
    let mut vals = [-1, -2, -3, 1, 2, 3, 0];
    let p = 2;

    vals.sort_by(|a :&isize, b :&isize|
                    a.pow(p).cmp(&b.pow(p)));

// END_CODE
}

<|endoftext|>


<commit_before>use std::ascii::AsciiExt;

pub fn camel_case(name: &str) -> String {
    let mut new_word: bool = true;
    name.chars().fold("".to_string(), |mut result, ch| {
        if ch == '-' || ch == '_' || ch == ' ' {
            new_word = true;
            result
        } else {
            result.push(if new_word { ch.to_ascii_uppercase() } else { ch.to_ascii_lowercase() });
            new_word = false;
            result
        }
    })
}

pub fn snake_case(name: &str) -> String {
    match name {
        "type"   => "amqp_type".to_string(),
        "return" => "amqp_return".to_string(),
        name     => {
            let mut new_word: bool = false;
            name.chars().fold("".to_string(), |mut result, ch| {
                if ch == '-' || ch == '_' || ch == ' ' {
                    new_word = true;
                    result
                } else {
                    if new_word || (result.len() > 0 && ch.is_uppercase()) {
                        result.push('_');
                        new_word = false;
                    }
                    result.push(ch.to_ascii_lowercase());
                    result
                }
            })
        }
    }
}

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

    #[test]
    fn test_camel_case() {
        assert_eq!(camel_case(""), "");
        assert_eq!(camel_case("foobar"), "Foobar");
        assert_eq!(camel_case("foo_bar"), "FooBar");
        assert_eq!(camel_case("_foo__bar baz-zzz"), "FooBarBazZzz");
    }

    #[test]
    fn test_snake_case() {
        assert_eq!(snake_case(""), "");
        assert_eq!(snake_case("Foobar"), "foobar");
        assert_eq!(snake_case("FooBar"), "foo_bar");
        assert_eq!(snake_case("Foo-BarBaz_zzz"), "foo_bar_baz_zzz");
    }
}
<commit_msg>codegen: tweak snake_case<commit_after>use std::ascii::AsciiExt;

pub fn camel_case(name: &str) -> String {
    let mut new_word = true;
    name.chars().fold("".to_string(), |mut result, ch| {
        if ch == '-' || ch == '_' || ch == ' ' {
            new_word = true;
            result
        } else {
            result.push(if new_word { ch.to_ascii_uppercase() } else { ch.to_ascii_lowercase() });
            new_word = false;
            result
        }
    })
}

pub fn snake_case(name: &str) -> String {
    match name {
        "type"   => "amqp_type".to_string(),
        "return" => "amqp_return".to_string(),
        name     => {
            let mut new_word       = false;
            let mut last_was_upper = false;
            name.chars().fold("".to_string(), |mut result, ch| {
                if ch == '-' || ch == '_' || ch == ' ' {
                    new_word = true;
                    result
                } else {
                    let uppercase = ch.is_uppercase();
                    if new_word || (!last_was_upper && result.len() > 0 && uppercase) {
                        result.push('_');
                        new_word = false;
                    }
                    last_was_upper = uppercase;
                    result.push(if uppercase { ch.to_ascii_lowercase() } else { ch });
                    result
                }
            })
        }
    }
}

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

    #[test]
    fn test_camel_case() {
        assert_eq!(camel_case(""),                  "");
        assert_eq!(camel_case("foobar"),            "Foobar");
        assert_eq!(camel_case("foo_bar"),           "FooBar");
        assert_eq!(camel_case("_foo__bar baz-zzz"), "FooBarBazZzz");
    }

    #[test]
    fn test_snake_case() {
        assert_eq!(snake_case(""),               "");
        assert_eq!(snake_case("Foobar"),         "foobar");
        assert_eq!(snake_case("FooBar"),         "foo_bar");
        assert_eq!(snake_case("Foo-BarBaz_zzz"), "foo_bar_baz_zzz");
    }

    #[test]
    fn test_snake_case_uint() {
        /* special case: we want UInt to be converted as uint */
        assert_eq!(snake_case("UInt"),     "uint");
        assert_eq!(snake_case("LongUInt"), "long_uint");
    }
}
<|endoftext|>


<commit_before>//! Provides functions for maintaining database schema.
//!
//! A database migration always provides procedures to update the schema, as well as to revert
//! itself. Diesel's migrations are versioned, and run in order. Diesel also takes care of tracking
//! which migrations have already been run automatically. Your migrations don't need to be
//! idempotent, as Diesel will ensure no migration is run twice unless it has been reverted.
//!
//! Migrations should be placed in a `/migrations` directory at the root of your project (the same
//! directory as `Cargo.toml`). When any of these functions are run, Diesel will search for the
//! migrations directory in the current directory and its parents, stopping when it finds the
//! directory containing `Cargo.toml`.
//!
//! Individual migrations should be a folder containing exactly two files, `up.sql` and `down.sql`.
//! `up.sql` will be used to run the migration, while `down.sql` will be used for reverting it. The
//! folder itself should have the structure `{version}_{migration_name}`. It is recommended that
//! you use the timestamp of creation for the version.
//!
//! ## Example
//!
//! ```text
//! # Directory Structure
//! - 20151219180527_create_users
//!     - up.sql
//!     - down.sql
//! - 20160107082941_create_posts
//!     - up.sql
//!     - down.sql
//! ```
//!
//! ```sql
//! -- 20151219180527_create_users/up.sql
//! CREATE TABLE users (
//!   id SERIAL PRIMARY KEY,
//!   name VARCHAR NOT NULL,
//!   hair_color VARCHAR
//! );
//! ```
//!
//! ```sql
//! -- 20151219180527_create_users/down.sql
//! DROP TABLE users;
//! ```
//!
//! ```sql
//! -- 20160107082941_create_posts/up.sql
//! CREATE TABLE posts (
//!   id SERIAL PRIMARY KEY,
//!   user_id INTEGER NOT NULL,
//!   title VARCHAR NOT NULL,
//!   body TEXT
//! );
//! ```
//!
//! ```sql
//! -- 20160107082941_create_posts/down.sql
//! DROP TABLE posts;
//! ```
mod migration;
#[doc(hidden)]
pub mod connection;
mod migration_error;
#[doc(hidden)]
pub mod schema;

#[doc(inline)]
pub use self::connection::MigrationConnection;
#[doc(inline)]
pub use self::migration::*;
pub use self::migration_error::*;

use std::fs::DirEntry;
use std::io::{stdout, Write};

use expression::expression_methods::*;
use query_dsl::*;
use self::migration_error::MigrationError::*;
use self::schema::__diesel_schema_migrations::dsl::*;
use {Connection, QueryResult};

use std::env;
use std::path::{PathBuf, Path};

/// Runs all migrations that have not yet been run. This function will print all progress to
/// stdout. This function will return an `Err` if some error occurs reading the migrations, or if
/// any migration fails to run. Each migration is run in its own transaction, so some migrations
/// may be committed, even if a later migration fails to run.
///
/// It should be noted that this runs all migrations that have not already been run, regardless of
/// whether or not their version is later than the latest run migration. This is generally not a
/// problem, and eases the more common case of two developers generating independent migrations on
/// a branch. Whoever created the second one will eventually need to run the first when both
/// branches are merged.
///
/// See the [module level documentation](index.html) for information on how migrations should be
/// structured, and where Diesel will look for them by default.
pub fn run_pending_migrations<Conn>(conn: &Conn) -> Result<(), RunMigrationsError> where
    Conn: MigrationConnection,
{
    let migrations_dir = try!(find_migrations_directory());
    run_pending_migrations_in_directory(conn, &migrations_dir, &mut stdout())
}

#[doc(hidden)]
pub fn run_pending_migrations_in_directory<Conn>(conn: &Conn, migrations_dir: &Path, output: &mut Write)
    -> Result<(), RunMigrationsError> where
        Conn: MigrationConnection,
{
    let all_migrations = try!(migrations_in_directory(migrations_dir));
    run_migrations(conn, all_migrations, output)
}

/// Reverts the last migration that was run. Returns the version that was reverted. Returns an
/// `Err` if no migrations have ever been run.
///
/// See the [module level documentation](index.html) for information on how migrations should be
/// structured, and where Diesel will look for them by default.
pub fn revert_latest_migration<Conn>(conn: &Conn) -> Result<String, RunMigrationsError> where
    Conn: MigrationConnection,
{
    try!(setup_database(conn));
    let latest_migration_version = try!(conn.latest_run_migration_version());
    revert_migration_with_version(conn, &latest_migration_version, &mut stdout())
        .map(|_| latest_migration_version)
}

#[doc(hidden)]
pub fn revert_migration_with_version<Conn: Connection>(conn: &Conn, ver: &str, output: &mut Write)
    -> Result<(), RunMigrationsError>
{
    migration_with_version(ver)
        .map_err(|e| e.into())
        .and_then(|m| revert_migration(conn, m, output))
}

#[doc(hidden)]
pub fn run_migration_with_version<Conn>(conn: &Conn, ver: &str, output: &mut Write)
    -> Result<(), RunMigrationsError> where
        Conn: MigrationConnection,
{
    migration_with_version(ver)
        .map_err(|e| e.into())
        .and_then(|m| run_migration(conn, &*m, output))
}

fn migration_with_version(ver: &str) -> Result<Box<Migration>, MigrationError> {
    let migrations_dir = try!(find_migrations_directory());
    let all_migrations = try!(migrations_in_directory(&migrations_dir));
    let migration = all_migrations.into_iter().find(|m| {
        m.version() == ver
    });
    match migration {
        Some(m) => Ok(m),
        None => Err(UnknownMigrationVersion(ver.into())),
    }
}

#[doc(hidden)]
pub fn setup_database<Conn: Connection>(conn: &Conn) -> QueryResult<usize> {
    conn.setup_helper_functions();
    create_schema_migrations_table_if_needed(conn)
}

fn create_schema_migrations_table_if_needed<Conn: Connection>(conn: &Conn) -> QueryResult<usize> {
    conn.silence_notices(|| {
        conn.execute("CREATE TABLE IF NOT EXISTS __diesel_schema_migrations (
            version VARCHAR PRIMARY KEY NOT NULL,
            run_on TIMESTAMP NOT NULL DEFAULT 'now'
        )")
    })
}

#[doc(hidden)]
pub fn migration_paths_in_directory(path: &Path) -> Result<Vec<DirEntry>, MigrationError> {
    try!(path.read_dir())
        .filter_map(|entry| {
            let entry = match entry {
                Ok(e) => e,
                Err(e) => return Some(Err(e.into())),
            };
            if !entry.file_name().to_string_lossy().starts_with(".") {
                Some(Ok(entry))
            } else {
                None
            }
        }).collect()
}

fn migrations_in_directory(path: &Path) -> Result<Vec<Box<Migration>>, MigrationError> {
    use self::migration::migration_from;

    try!(migration_paths_in_directory(path)).iter().map(|e| {
        migration_from(e.path())
    }).collect()
}

/// Run all pending migrations in the given list. Apps should likely be calling
/// `run_pending_migrations` or `run_pending_migrations_in_directory` instead.
pub fn run_migrations<Conn, List, M>(
    conn: &Conn,
    migrations: List,
    output: &mut Write,
) -> Result<(), RunMigrationsError> where
    Conn: MigrationConnection,
    List: IntoIterator<Item=M>,
    M: ::std::ops::Deref<Target=Migration>,
{
    try!(setup_database(conn));
    let already_run = try!(conn.previously_run_migration_versions());
    let mut pending_migrations: Vec<_> = migrations.into_iter()
        .filter(|m| {
            !already_run.contains(&m.version().to_string())
        }).collect();

    pending_migrations.sort_by(|a, b| a.version().cmp(b.version()));
    for migration in pending_migrations {
        try!(run_migration(conn, &*migration, output));
    }
    Ok(())
}

fn run_migration<Conn>(conn: &Conn, migration: &Migration, output: &mut Write)
    -> Result<(), RunMigrationsError> where
        Conn: MigrationConnection,
{
    conn.transaction(|| {
        try!(writeln!(output, "Running migration {}", migration.version()));
        try!(migration.run(conn));
        try!(conn.insert_new_migration(migration.version()));
        Ok(())
    }).map_err(|e| e.into())
}

fn revert_migration<Conn: Connection>(conn: &Conn, migration: Box<Migration>, output: &mut Write)
    -> Result<(), RunMigrationsError>
{
    try!(conn.transaction(|| {
        try!(writeln!(output, "Rolling back migration {}", migration.version()));
        try!(migration.revert(conn));
        let target = __diesel_schema_migrations.filter(version.eq(migration.version()));
        try!(::delete(target).execute(conn));
        Ok(())
    }));
    Ok(())
}

/// Returns the directory containing migrations. Will look at for
/// $PWD/migrations. If it is not found, it will search the parents of the
/// current directory, until it reaches the root directory.  Returns
/// `MigrationError::MigrationDirectoryNotFound` if no directory is found.
pub fn find_migrations_directory() -> Result<PathBuf, MigrationError> {
    search_for_migrations_directory(&try!(env::current_dir()))
}

/// Searches for the migrations directory relative to the given path. See
/// `find_migrations_directory` for more details.
pub fn search_for_migrations_directory(path: &Path) -> Result<PathBuf, MigrationError> {
    let migration_path = path.join("migrations");
    if migration_path.is_dir() {
        Ok(migration_path)
    } else {
        path.parent().map(search_for_migrations_directory)
            .unwrap_or(Err(MigrationError::MigrationDirectoryNotFound))
    }
}

#[cfg(test)]
mod tests {
    extern crate tempdir;

    use super::*;

    use self::tempdir::TempDir;
    use std::fs;

    #[test]
    fn migration_directory_not_found_if_no_migration_dir_exists() {
        let dir = TempDir::new("diesel").unwrap();

        assert_eq!(Err(MigrationError::MigrationDirectoryNotFound),
            search_for_migrations_directory(dir.path()));
    }

    #[test]
    fn migration_directory_defaults_to_pwd_slash_migrations() {
        let dir = TempDir::new("diesel").unwrap();
        let temp_path = dir.path().canonicalize().unwrap();
        let migrations_path = temp_path.join("migrations");

        fs::create_dir(&migrations_path).unwrap();

        assert_eq!(Ok(migrations_path), search_for_migrations_directory(&temp_path));
    }

    #[test]
    fn migration_directory_checks_parents() {
        let dir = TempDir::new("diesel").unwrap();
        let temp_path = dir.path().canonicalize().unwrap();
        let migrations_path = temp_path.join("migrations");
        let child_path = temp_path.join("child");

        fs::create_dir(&child_path).unwrap();
        fs::create_dir(&migrations_path).unwrap();

        assert_eq!(Ok(migrations_path), search_for_migrations_directory(&child_path));
    }
}
<commit_msg>Use CURRENT_TIMESTAMP as default for run_on in migrations table<commit_after>//! Provides functions for maintaining database schema.
//!
//! A database migration always provides procedures to update the schema, as well as to revert
//! itself. Diesel's migrations are versioned, and run in order. Diesel also takes care of tracking
//! which migrations have already been run automatically. Your migrations don't need to be
//! idempotent, as Diesel will ensure no migration is run twice unless it has been reverted.
//!
//! Migrations should be placed in a `/migrations` directory at the root of your project (the same
//! directory as `Cargo.toml`). When any of these functions are run, Diesel will search for the
//! migrations directory in the current directory and its parents, stopping when it finds the
//! directory containing `Cargo.toml`.
//!
//! Individual migrations should be a folder containing exactly two files, `up.sql` and `down.sql`.
//! `up.sql` will be used to run the migration, while `down.sql` will be used for reverting it. The
//! folder itself should have the structure `{version}_{migration_name}`. It is recommended that
//! you use the timestamp of creation for the version.
//!
//! ## Example
//!
//! ```text
//! # Directory Structure
//! - 20151219180527_create_users
//!     - up.sql
//!     - down.sql
//! - 20160107082941_create_posts
//!     - up.sql
//!     - down.sql
//! ```
//!
//! ```sql
//! -- 20151219180527_create_users/up.sql
//! CREATE TABLE users (
//!   id SERIAL PRIMARY KEY,
//!   name VARCHAR NOT NULL,
//!   hair_color VARCHAR
//! );
//! ```
//!
//! ```sql
//! -- 20151219180527_create_users/down.sql
//! DROP TABLE users;
//! ```
//!
//! ```sql
//! -- 20160107082941_create_posts/up.sql
//! CREATE TABLE posts (
//!   id SERIAL PRIMARY KEY,
//!   user_id INTEGER NOT NULL,
//!   title VARCHAR NOT NULL,
//!   body TEXT
//! );
//! ```
//!
//! ```sql
//! -- 20160107082941_create_posts/down.sql
//! DROP TABLE posts;
//! ```
mod migration;
#[doc(hidden)]
pub mod connection;
mod migration_error;
#[doc(hidden)]
pub mod schema;

#[doc(inline)]
pub use self::connection::MigrationConnection;
#[doc(inline)]
pub use self::migration::*;
pub use self::migration_error::*;

use std::fs::DirEntry;
use std::io::{stdout, Write};

use expression::expression_methods::*;
use query_dsl::*;
use self::migration_error::MigrationError::*;
use self::schema::__diesel_schema_migrations::dsl::*;
use {Connection, QueryResult};

use std::env;
use std::path::{PathBuf, Path};

/// Runs all migrations that have not yet been run. This function will print all progress to
/// stdout. This function will return an `Err` if some error occurs reading the migrations, or if
/// any migration fails to run. Each migration is run in its own transaction, so some migrations
/// may be committed, even if a later migration fails to run.
///
/// It should be noted that this runs all migrations that have not already been run, regardless of
/// whether or not their version is later than the latest run migration. This is generally not a
/// problem, and eases the more common case of two developers generating independent migrations on
/// a branch. Whoever created the second one will eventually need to run the first when both
/// branches are merged.
///
/// See the [module level documentation](index.html) for information on how migrations should be
/// structured, and where Diesel will look for them by default.
pub fn run_pending_migrations<Conn>(conn: &Conn) -> Result<(), RunMigrationsError> where
    Conn: MigrationConnection,
{
    let migrations_dir = try!(find_migrations_directory());
    run_pending_migrations_in_directory(conn, &migrations_dir, &mut stdout())
}

#[doc(hidden)]
pub fn run_pending_migrations_in_directory<Conn>(conn: &Conn, migrations_dir: &Path, output: &mut Write)
    -> Result<(), RunMigrationsError> where
        Conn: MigrationConnection,
{
    let all_migrations = try!(migrations_in_directory(migrations_dir));
    run_migrations(conn, all_migrations, output)
}

/// Reverts the last migration that was run. Returns the version that was reverted. Returns an
/// `Err` if no migrations have ever been run.
///
/// See the [module level documentation](index.html) for information on how migrations should be
/// structured, and where Diesel will look for them by default.
pub fn revert_latest_migration<Conn>(conn: &Conn) -> Result<String, RunMigrationsError> where
    Conn: MigrationConnection,
{
    try!(setup_database(conn));
    let latest_migration_version = try!(conn.latest_run_migration_version());
    revert_migration_with_version(conn, &latest_migration_version, &mut stdout())
        .map(|_| latest_migration_version)
}

#[doc(hidden)]
pub fn revert_migration_with_version<Conn: Connection>(conn: &Conn, ver: &str, output: &mut Write)
    -> Result<(), RunMigrationsError>
{
    migration_with_version(ver)
        .map_err(|e| e.into())
        .and_then(|m| revert_migration(conn, m, output))
}

#[doc(hidden)]
pub fn run_migration_with_version<Conn>(conn: &Conn, ver: &str, output: &mut Write)
    -> Result<(), RunMigrationsError> where
        Conn: MigrationConnection,
{
    migration_with_version(ver)
        .map_err(|e| e.into())
        .and_then(|m| run_migration(conn, &*m, output))
}

fn migration_with_version(ver: &str) -> Result<Box<Migration>, MigrationError> {
    let migrations_dir = try!(find_migrations_directory());
    let all_migrations = try!(migrations_in_directory(&migrations_dir));
    let migration = all_migrations.into_iter().find(|m| {
        m.version() == ver
    });
    match migration {
        Some(m) => Ok(m),
        None => Err(UnknownMigrationVersion(ver.into())),
    }
}

#[doc(hidden)]
pub fn setup_database<Conn: Connection>(conn: &Conn) -> QueryResult<usize> {
    conn.setup_helper_functions();
    create_schema_migrations_table_if_needed(conn)
}

fn create_schema_migrations_table_if_needed<Conn: Connection>(conn: &Conn) -> QueryResult<usize> {
    conn.silence_notices(|| {
        conn.execute("CREATE TABLE IF NOT EXISTS __diesel_schema_migrations (
            version VARCHAR PRIMARY KEY NOT NULL,
            run_on TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
        )")
    })
}

#[doc(hidden)]
pub fn migration_paths_in_directory(path: &Path) -> Result<Vec<DirEntry>, MigrationError> {
    try!(path.read_dir())
        .filter_map(|entry| {
            let entry = match entry {
                Ok(e) => e,
                Err(e) => return Some(Err(e.into())),
            };
            if !entry.file_name().to_string_lossy().starts_with(".") {
                Some(Ok(entry))
            } else {
                None
            }
        }).collect()
}

fn migrations_in_directory(path: &Path) -> Result<Vec<Box<Migration>>, MigrationError> {
    use self::migration::migration_from;

    try!(migration_paths_in_directory(path)).iter().map(|e| {
        migration_from(e.path())
    }).collect()
}

/// Run all pending migrations in the given list. Apps should likely be calling
/// `run_pending_migrations` or `run_pending_migrations_in_directory` instead.
pub fn run_migrations<Conn, List, M>(
    conn: &Conn,
    migrations: List,
    output: &mut Write,
) -> Result<(), RunMigrationsError> where
    Conn: MigrationConnection,
    List: IntoIterator<Item=M>,
    M: ::std::ops::Deref<Target=Migration>,
{
    try!(setup_database(conn));
    let already_run = try!(conn.previously_run_migration_versions());
    let mut pending_migrations: Vec<_> = migrations.into_iter()
        .filter(|m| {
            !already_run.contains(&m.version().to_string())
        }).collect();

    pending_migrations.sort_by(|a, b| a.version().cmp(b.version()));
    for migration in pending_migrations {
        try!(run_migration(conn, &*migration, output));
    }
    Ok(())
}

fn run_migration<Conn>(conn: &Conn, migration: &Migration, output: &mut Write)
    -> Result<(), RunMigrationsError> where
        Conn: MigrationConnection,
{
    conn.transaction(|| {
        try!(writeln!(output, "Running migration {}", migration.version()));
        try!(migration.run(conn));
        try!(conn.insert_new_migration(migration.version()));
        Ok(())
    }).map_err(|e| e.into())
}

fn revert_migration<Conn: Connection>(conn: &Conn, migration: Box<Migration>, output: &mut Write)
    -> Result<(), RunMigrationsError>
{
    try!(conn.transaction(|| {
        try!(writeln!(output, "Rolling back migration {}", migration.version()));
        try!(migration.revert(conn));
        let target = __diesel_schema_migrations.filter(version.eq(migration.version()));
        try!(::delete(target).execute(conn));
        Ok(())
    }));
    Ok(())
}

/// Returns the directory containing migrations. Will look at for
/// $PWD/migrations. If it is not found, it will search the parents of the
/// current directory, until it reaches the root directory.  Returns
/// `MigrationError::MigrationDirectoryNotFound` if no directory is found.
pub fn find_migrations_directory() -> Result<PathBuf, MigrationError> {
    search_for_migrations_directory(&try!(env::current_dir()))
}

/// Searches for the migrations directory relative to the given path. See
/// `find_migrations_directory` for more details.
pub fn search_for_migrations_directory(path: &Path) -> Result<PathBuf, MigrationError> {
    let migration_path = path.join("migrations");
    if migration_path.is_dir() {
        Ok(migration_path)
    } else {
        path.parent().map(search_for_migrations_directory)
            .unwrap_or(Err(MigrationError::MigrationDirectoryNotFound))
    }
}

#[cfg(test)]
mod tests {
    extern crate tempdir;

    use super::*;

    use self::tempdir::TempDir;
    use std::fs;

    #[test]
    fn migration_directory_not_found_if_no_migration_dir_exists() {
        let dir = TempDir::new("diesel").unwrap();

        assert_eq!(Err(MigrationError::MigrationDirectoryNotFound),
            search_for_migrations_directory(dir.path()));
    }

    #[test]
    fn migration_directory_defaults_to_pwd_slash_migrations() {
        let dir = TempDir::new("diesel").unwrap();
        let temp_path = dir.path().canonicalize().unwrap();
        let migrations_path = temp_path.join("migrations");

        fs::create_dir(&migrations_path).unwrap();

        assert_eq!(Ok(migrations_path), search_for_migrations_directory(&temp_path));
    }

    #[test]
    fn migration_directory_checks_parents() {
        let dir = TempDir::new("diesel").unwrap();
        let temp_path = dir.path().canonicalize().unwrap();
        let migrations_path = temp_path.join("migrations");
        let child_path = temp_path.join("child");

        fs::create_dir(&child_path).unwrap();
        fs::create_dir(&migrations_path).unwrap();

        assert_eq!(Ok(migrations_path), search_for_migrations_directory(&child_path));
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Rich Lane.

// 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.

extern mod cgmath;
extern mod noise;

use std;

use cgmath::array::Array;
use cgmath::vector::Vector;
use cgmath::vector::Vec3;

use noise::Perlin;

use CHUNK_SIZE;

#[repr(u8)]
#[deriving(Eq)]
pub enum BlockType {
    BlockAir = 0,
    BlockGrass = 1,
    BlockStone = 2,
    BlockDirt = 3,
    BlockWater = 4,
}

pub struct Block {
    blocktype: BlockType,
}

impl Block {
    pub fn is_opaque(&self) -> bool {
        self.blocktype != BlockAir
    }
}

pub struct TerrainGenerator {
    perlin1 : Perlin,
    perlin2 : Perlin,
    perlin3 : Perlin,
    perlin4 : Perlin,
}

pub struct Terrain {
    priv blocks: [[[Block, ..CHUNK_SIZE+2], ..CHUNK_SIZE+2], ..CHUNK_SIZE+2],
}

impl TerrainGenerator {
    pub fn new(seed: u32) -> TerrainGenerator {
        TerrainGenerator {
            perlin1: Perlin::from_seed([seed as uint]),
            perlin2: Perlin::from_seed([seed as uint * 7]),
            perlin3: Perlin::from_seed([seed as uint * 13]),
            perlin4: Perlin::from_seed([seed as uint * 17]),
        }
    }

    pub fn gen(&self, p: Vec3<f64>) -> ~Terrain {
        let def_block = Block { blocktype: BlockAir };
        let mut t = ~Terrain {
            blocks: [[[def_block, ..CHUNK_SIZE+2], ..CHUNK_SIZE+2], ..CHUNK_SIZE+2],
        };

        let water_height = -12.0;
        let base_variance = 10.0;

        for block_x in std::iter::range(-1, CHUNK_SIZE+1) {
            for block_z in std::iter::range(-1, CHUNK_SIZE+1) {
                let noise1 = self.perlin1.gen([
                    (p.x + block_x as f64) * 0.07,
                    (p.z + block_z as f64) * 0.04
                ]);
                let noise2 = self.perlin2.gen([
                    (p.x + block_x as f64) * 0.05,
                    (p.z + block_z as f64) * 0.05
                ]);
                let noise3 = self.perlin3.gen([
                    (p.x + block_x as f64) * 0.005,
                    (p.z + block_z as f64) * 0.005
                ]);
                let noise4 = self.perlin4.gen([
                    (p.x + block_x as f64) * 0.001,
                    (p.z + block_z as f64) * 0.001
                ]);

                let height =
                    noise4 * 10.0 +
                    base_variance *
                        (noise3 + 1.0).powf(&2.5) *
                        noise1;

                let dirt_height = 4.0 + noise2 * 8.0;

                for block_y in range(-1, CHUNK_SIZE+1) {
                    let mut blocktype = BlockAir;
                    let v = p.add_v(&Vec3::new(block_x as f64, block_y as f64, block_z as f64));

                    if v.y < height {
                        if v.y > height - dirt_height {
                            if v.y > height - 2.0 {
                                blocktype = BlockGrass;
                            } else {
                                blocktype = BlockDirt;
                            }
                        } else {
                            blocktype = BlockStone;
                        }
                    }

                    if blocktype == BlockAir && v.y < water_height {
                        blocktype = BlockWater;
                    }

                    if blocktype != BlockAir && blocktype != BlockWater {
                        let caviness = (0.5 - v.y.clamp(&30.0, &128.0) * 0.005);
                        let warp_v = Vec3::new(v.x * 0.01, v.y * 0.01, v.z * 0.01);
                        let warp = Vec3::new(
                            self.perlin2.gen(warp_v.as_slice()),
                            self.perlin3.gen(warp_v.as_slice()),
                            self.perlin4.gen(warp_v.as_slice())).mul_s(2.0);
                        let cave_v = v.mul_v(&Vec3::new(0.05, 0.08, 0.05)).add_v(&warp);
                        let cave = self.perlin1.gen(cave_v.as_slice()) * 0.5 + 0.5;

                        if cave < caviness {
                            blocktype = BlockAir;
                        }
                    }

                    if blocktype != BlockAir {
                        let block = t.get_mut(block_x, block_y, block_z);
                        block.blocktype = blocktype;
                    }
                }
            }
        }

        return t;
    }
}

impl Terrain {
    pub fn get<'a>(&'a self, x: int, y: int, z: int) -> &'a Block {
        &self.blocks[x+1][y+1][z+1]
    }

    pub fn get_mut<'a>(&'a mut self, x: int, y: int, z: int) -> &'a mut Block {
        &mut self.blocks[x+1][y+1][z+1]
    }
}
<commit_msg>terrain: sample low resolution density data to create caves<commit_after>// Copyright 2014 Rich Lane.

// 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.

extern mod cgmath;
extern mod noise;

use std;

use cgmath::array::Array;
use cgmath::vector::Vector;
use cgmath::vector::Vec3;

use noise::Perlin;

use CHUNK_SIZE;

#[repr(u8)]
#[deriving(Eq)]
pub enum BlockType {
    BlockAir = 0,
    BlockGrass = 1,
    BlockStone = 2,
    BlockDirt = 3,
    BlockWater = 4,
}

pub struct Block {
    blocktype: BlockType,
}

impl Block {
    pub fn is_opaque(&self) -> bool {
        self.blocktype != BlockAir
    }
}

pub struct TerrainGenerator {
    perlin1 : Perlin,
    perlin2 : Perlin,
    perlin3 : Perlin,
    perlin4 : Perlin,
}

pub struct Terrain {
    priv blocks: [[[Block, ..CHUNK_SIZE+2], ..CHUNK_SIZE+2], ..CHUNK_SIZE+2],
}

impl TerrainGenerator {
    pub fn new(seed: u32) -> TerrainGenerator {
        TerrainGenerator {
            perlin1: Perlin::from_seed([seed as uint]),
            perlin2: Perlin::from_seed([seed as uint * 7]),
            perlin3: Perlin::from_seed([seed as uint * 13]),
            perlin4: Perlin::from_seed([seed as uint * 17]),
        }
    }

    pub fn gen(&self, p: Vec3<f64>) -> ~Terrain {
        let def_block = Block { blocktype: BlockAir };
        let mut t = ~Terrain {
            blocks: [[[def_block, ..CHUNK_SIZE+2], ..CHUNK_SIZE+2], ..CHUNK_SIZE+2],
        };

        static S : int = 4;

        let mut density = [[[0.0, ..(CHUNK_SIZE/S)+3], ..(CHUNK_SIZE/S)+3], ..(CHUNK_SIZE/S)+3];
        for density_x in std::iter::range(-1, CHUNK_SIZE/S+1) {
            for density_y in std::iter::range(-1, CHUNK_SIZE/S+1) {
                for density_z in std::iter::range(-1, CHUNK_SIZE/S+1) {
                    let v = Vec3::new(p.x + (density_x * S) as f64,
                                      p.y + (density_y * S) as f64,
                                      p.z + (density_z * S) as f64);
                    let warp_v = v.mul_v(&Vec3::new(0.02, 0.03, 0.02));
                    let warp = Vec3::new(
                        self.perlin2.gen(warp_v.as_slice()),
                        self.perlin3.gen(warp_v.as_slice()),
                        self.perlin4.gen(warp_v.as_slice())).mul_s(2.0);
                    let v2 = v.mul_v(&Vec3::new(0.012, 0.020, 0.025)).add_v(&warp);
                    density[density_x+1][density_y+1][density_z+1] =
                        self.perlin1.gen(v2.as_slice()) * 0.5 + 0.5;
                }
            }
        }

        let water_height = -12.0;
        let base_variance = 10.0;

        for block_x in std::iter::range(-1, CHUNK_SIZE+1) {
            for block_z in std::iter::range(-1, CHUNK_SIZE+1) {
                let noise1 = self.perlin1.gen([
                    (p.x + block_x as f64) * 0.07,
                    (p.z + block_z as f64) * 0.04
                ]);
                let noise2 = self.perlin2.gen([
                    (p.x + block_x as f64) * 0.05,
                    (p.z + block_z as f64) * 0.05
                ]);
                let noise3 = self.perlin3.gen([
                    (p.x + block_x as f64) * 0.005,
                    (p.z + block_z as f64) * 0.005
                ]);
                let noise4 = self.perlin4.gen([
                    (p.x + block_x as f64) * 0.001,
                    (p.z + block_z as f64) * 0.001
                ]);

                let height =
                    noise4 * 10.0 +
                    base_variance *
                        (noise3 + 1.0).powf(&2.5) *
                        noise1;

                let dirt_height = 4.0 + noise2 * 8.0;

                for block_y in range(-1, CHUNK_SIZE+1) {
                    let mut blocktype = BlockAir;
                    let v = p.add_v(&Vec3::new(block_x as f64, block_y as f64, block_z as f64));

                    if v.y < height {
                        if v.y > height - dirt_height {
                            if v.y > height - 2.0 {
                                blocktype = BlockGrass;
                            } else {
                                blocktype = BlockDirt;
                            }
                        } else {
                            blocktype = BlockStone;
                        }
                    }

                    if blocktype == BlockAir && v.y < water_height {
                        blocktype = BlockWater;
                    }

                    if blocktype != BlockAir && blocktype != BlockWater {
                        /* Trilinear interpolation of lower-resolution density */
                        let fx = (block_x as f64 / S as f64).fract();
                        let fy = (block_y as f64 / S as f64).fract();
                        let fz = (block_z as f64 / S as f64).fract();
                        let x = (block_x+S)/S;
                        let y = (block_y+S)/S;
                        let z = (block_z+S)/S;
                        let dxyz = density[x][y][z];
                        let dxyZ = density[x][y][z+1];
                        let dxYz = density[x][y+1][z];
                        let dxYZ = density[x][y+1][z+1];
                        let dXyz = density[x+1][y][z];
                        let dXyZ = density[x+1][y][z+1];
                        let dXYz = density[x+1][y+1][z];
                        let dXYZ = density[x+1][y+1][z+1];

                        let d = dxyz * (1.0-fx) * (1.0-fy) * (1.0-fz) +
                                dxyZ * (1.0-fx) * (1.0-fy) * fz +
                                dxYz * (1.0-fx) * fy * (1.0-fz) +
                                dxYZ * (1.0-fx) * fy * fz +
                                dXyz * fx * (1.0-fy) * (1.0-fz) +
                                dXyZ * fx * (1.0-fy) * fz +
                                dXYz * fx * fy * (1.0-fz) +
                                dXYZ * fx * fy * fz;

                        if d < 0.25 {
                            blocktype = BlockAir;
                        }
                    }

                    if blocktype != BlockAir {
                        let block = t.get_mut(block_x, block_y, block_z);
                        block.blocktype = blocktype;
                    }
                }
            }
        }

        return t;
    }
}

impl Terrain {
    pub fn get<'a>(&'a self, x: int, y: int, z: int) -> &'a Block {
        &self.blocks[x+1][y+1][z+1]
    }

    pub fn get_mut<'a>(&'a mut self, x: int, y: int, z: int) -> &'a mut Block {
        &mut self.blocks[x+1][y+1][z+1]
    }
}
<|endoftext|>


<commit_before>use events::{Event, EventHandler};
use formatter::formatter::Formatter;
use runner;
use std::io;

pub struct Simple<'a, Io: io::Write + 'a> {
    buf: &'a mut Io,
}

impl<'a, T: io::Write> Simple<'a, T> {
    fn new(buf: &mut T) -> Simple<T> {
        Simple { buf: buf }
    }

    fn write_summary(&mut self, result: runner::RunnerResult) -> Result<(), io::Error> {
        let (res, report) = match result {
            Ok(report) => ("ok", report),
            Err(report) => ("FAILED", report),
        };

        writeln!(self.buf,
                 "test result: {}. {} examples; {} passed; {} failed;",
                 res,
                 report.total_tests,
                 report.success_count,
                 report.error_count)
    }
}

impl<'a, T: io::Write> EventHandler for Simple<'a, T> {
    fn trigger(&mut self, event: &Event) {
        // FIXME: do something with the io::Error ?
        let _ = match *event {
            Event::StartRunner => writeln!(self.buf, "Running tests..."),
            Event::FinishedRunner(result) => self.write_summary(result),
            _ => Ok(()),
        };
    }
}
impl<'a, T: io::Write> Formatter for Simple<'a, T> {}

#[cfg(test)]
mod tests {
    pub use super::*;
    pub use formatter::formatter::Formatter;
    pub use events::{Event, EventHandler};
    pub use std::str;

    #[test]
    fn it_can_be_instanciated() {
        Simple::new(&mut vec![1u8]);
    }

    #[test]
    fn it_impl_formatter_trait() {
        let _: &Formatter = &Simple::new(&mut vec![1u8]) as &Formatter;
    }

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

        #[test]
        fn it_display_that_tests_started() {
            let mut v = vec![];
            {
                let mut s = Simple::new(&mut v);
                s.trigger(&Event::StartRunner);
            }

            assert_eq!("Running tests...\n", str::from_utf8(&v).unwrap());
        }
    }

    #[cfg(test)]
    mod event_finished_runner {
        pub use super::*;
        use runner::TestReport;

        fn make_report(succes: u32, errors: u32) -> Result<TestReport, TestReport> {
            let mut report = TestReport::default();
            report.success_count = succes;
            report.error_count = errors;
            report.total_tests = succes + errors;

            if errors != 0 {
                Err(report)
            } else {
                Ok(report)
            }
        }

        macro_rules! test_and_compare_output {
            ($(
                $test_name:ident : (success: $succ:expr, errors: $err:expr) => $msg:expr
            ),+) => {

                $(
                    #[test]
                    fn $test_name() {
                        let mut v = vec!();
                        {
                            let mut s = Simple::new(&mut v);
                            s.trigger(&Event::FinishedRunner(make_report($succ, $err)))
                        }

                        assert_eq!($msg, str::from_utf8(&v).unwrap())
                    }
                )+
            }
        }

        test_and_compare_output! {
            no_test_is_ok: (success: 0, errors: 0) =>
                "test result: ok. 0 examples; 0 passed; 0 failed;\n",
            one_test: (success: 1, errors: 0) =>
                "test result: ok. 1 examples; 1 passed; 0 failed;\n",
            multiple_ok: (success: 42, errors: 0) =>
                "test result: ok. 42 examples; 42 passed; 0 failed;\n",
            one_error: (success: 0, errors: 1) =>
              "test result: FAILED. 1 examples; 0 passed; 1 failed;\n",
            multiple_errors: (success: 0, errors: 37) =>
              "test result: FAILED. 37 examples; 0 passed; 37 failed;\n",
            one_of_each: (success: 1, errors: 1) =>
              "test result: FAILED. 2 examples; 1 passed; 1 failed;\n",
            multiple_of_each: (success: 12, errors: 21) =>
              "test result: FAILED. 33 examples; 12 passed; 21 failed;\n"
        }
    }
}
<commit_msg> add test progress<commit_after>use events::{Event, EventHandler};
use formatter::formatter::Formatter;
use runner;
use std::io;

pub struct Simple<'a, Io: io::Write + 'a> {
    buf: &'a mut Io,
}

impl<'a, T: io::Write> Simple<'a, T> {
    fn new(buf: &mut T) -> Simple<T> {
        Simple { buf: buf }
    }

    fn write_summary(&mut self, result: runner::RunnerResult) -> Result<(), io::Error> {
        let (res, report) = match result {
            Ok(report) => ("ok", report),
            Err(report) => ("FAILED", report),
        };

        writeln!(self.buf,
                 "test result: {}. {} examples; {} passed; {} failed;",
                 res,
                 report.total_tests,
                 report.success_count,
                 report.error_count)
    }
}

impl<'a, T: io::Write> EventHandler for Simple<'a, T> {
    fn trigger(&mut self, event: &Event) {
        // FIXME: do something with the io::Error ?
        let _ = match *event {
            Event::StartRunner => writeln!(self.buf, "Running tests..."),
            Event::EndTest(result) => {
                let chr = if result.is_ok() { "." } else { "F" };
                write!(self.buf, "{}", chr)
            },
            Event::FinishedRunner(result) => self.write_summary(result),
            _ => Ok(()),
        };
    }
}
impl<'a, T: io::Write> Formatter for Simple<'a, T> {}

#[cfg(test)]
mod tests {
    pub use super::*;
    pub use formatter::formatter::Formatter;
    pub use events::{Event, EventHandler};
    pub use std::str;

    #[test]
    fn it_can_be_instanciated() {
        Simple::new(&mut vec![1u8]);
    }

    #[test]
    fn it_impl_formatter_trait() {
        let _: &Formatter = &Simple::new(&mut vec![1u8]) as &Formatter;
    }

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

        #[test]
        fn it_display_that_tests_started() {
            let mut v = vec![];
            {
                let mut s = Simple::new(&mut v);
                s.trigger(&Event::StartRunner);
            }

            assert_eq!("Running tests...\n", str::from_utf8(&v).unwrap());
        }
    }

    #[cfg(test)]
    mod event_finished_runner {
        pub use super::*;
        use runner::TestReport;

        fn make_report(succes: u32, errors: u32) -> Result<TestReport, TestReport> {
            let mut report = TestReport::default();
            report.success_count = succes;
            report.error_count = errors;
            report.total_tests = succes + errors;

            if errors != 0 {
                Err(report)
            } else {
                Ok(report)
            }
        }

        macro_rules! test_and_compare_output {
            ($(
                $test_name:ident : (success: $succ:expr, errors: $err:expr) => $msg:expr
            ),+) => {

                $(
                    #[test]
                    fn $test_name() {
                        let mut v = vec!();
                        {
                            let mut s = Simple::new(&mut v);
                            s.trigger(&Event::FinishedRunner(make_report($succ, $err)))
                        }

                        assert_eq!($msg, str::from_utf8(&v).unwrap())
                    }
                )+
            }
        }

        test_and_compare_output! {
            no_test_is_ok: (success: 0, errors: 0) =>
                "test result: ok. 0 examples; 0 passed; 0 failed;\n",
            one_test: (success: 1, errors: 0) =>
                "test result: ok. 1 examples; 1 passed; 0 failed;\n",
            multiple_ok: (success: 42, errors: 0) =>
                "test result: ok. 42 examples; 42 passed; 0 failed;\n",
            one_error: (success: 0, errors: 1) =>
              "test result: FAILED. 1 examples; 0 passed; 1 failed;\n",
            multiple_errors: (success: 0, errors: 37) =>
              "test result: FAILED. 37 examples; 0 passed; 37 failed;\n",
            one_of_each: (success: 1, errors: 1) =>
              "test result: FAILED. 2 examples; 1 passed; 1 failed;\n",
            multiple_of_each: (success: 12, errors: 21) =>
              "test result: FAILED. 33 examples; 12 passed; 21 failed;\n"
        }
    }

    mod event_end_test {
        pub use super::*;

        #[test]
        fn it_displays_a_dot_when_success() {
            let mut v = vec![];
            {
                let mut s = Simple::new(&mut v);
                s.trigger(&Event::EndTest(Ok(())));
            }

            assert_eq!(".", str::from_utf8(&v).unwrap());
        }

        #[test]
        #[allow(non_snake_case)]
        fn it_displays_a_F_when_error() {
            let mut v = vec![];
            {
                let mut s = Simple::new(&mut v);
                s.trigger(&Event::EndTest(Err(())));
            }

            assert_eq!("F", str::from_utf8(&v).unwrap());
        }
    }
}
<|endoftext|>


<commit_before>// AsRef and AsMut allow for cheap reference-to-reference conversions.
// Read more about them at https://doc.rust-lang.org/std/convert/trait.AsRef.html
// and https://doc.rust-lang.org/std/convert/trait.AsMut.html, respectively.

// Obtain the number of bytes (not characters) in the given argument
// Add the AsRef trait appropriately as a trait bound
fn byte_counter<T>(arg: T) -> usize {
    arg.as_ref().as_bytes().len()
}

// I AM NOT DONE
// Obtain the number of characters (not bytes) in the given argument
// Add the AsRef trait appropriately as a trait bound
fn char_counter<T>(arg: T) -> usize {
    arg.as_ref().chars().count()
}

fn main() {
    let s = "Café au lait";
    println!("{}", char_counter(s));
    println!("{}", byte_counter(s));
}

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

    #[test]
    fn different_counts() {
        let s = "Café au lait";
        assert_ne!(char_counter(s), byte_counter(s));
    }

    #[test]
    fn same_counts() {
        let s = "Cafe au lait";
        assert_eq!(char_counter(s), byte_counter(s));
    }
}
<commit_msg>remove bottom comment instead of top<commit_after>// AsRef and AsMut allow for cheap reference-to-reference conversions.
// Read more about them at https://doc.rust-lang.org/std/convert/trait.AsRef.html
// and https://doc.rust-lang.org/std/convert/trait.AsMut.html, respectively.

// I AM NOT DONE
// Obtain the number of bytes (not characters) in the given argument
// Add the AsRef trait appropriately as a trait bound
fn byte_counter<T>(arg: T) -> usize {
    arg.as_ref().as_bytes().len()
}

// Obtain the number of characters (not bytes) in the given argument
// Add the AsRef trait appropriately as a trait bound
fn char_counter<T>(arg: T) -> usize {
    arg.as_ref().chars().count()
}

fn main() {
    let s = "Café au lait";
    println!("{}", char_counter(s));
    println!("{}", byte_counter(s));
}

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

    #[test]
    fn different_counts() {
        let s = "Café au lait";
        assert_ne!(char_counter(s), byte_counter(s));
    }

    #[test]
    fn same_counts() {
        let s = "Cafe au lait";
        assert_eq!(char_counter(s), byte_counter(s));
    }
}
<|endoftext|>


<commit_before>use std::io::Read;

use async_trait::async_trait;
use async_tungstenite::tungstenite::Message;
use flate2::read::ZlibDecoder;
use futures::stream::SplitSink;
use futures::{SinkExt, StreamExt, TryStreamExt};
use tokio::time::timeout;
use tracing::{instrument, warn};
use url::Url;

use crate::gateway::{GatewayError, WsStream};
use crate::internal::prelude::*;
use crate::json::{from_str, to_string};

#[async_trait]
pub trait ReceiverExt {
    async fn recv_json(&mut self) -> Result<Option<Value>>;
    async fn try_recv_json(&mut self) -> Result<Option<Value>>;
}

#[async_trait]
pub trait SenderExt {
    async fn send_json(&mut self, value: &Value) -> Result<()>;
}

#[async_trait]
impl ReceiverExt for WsStream {
    async fn recv_json(&mut self) -> Result<Option<Value>> {
        const TIMEOUT: tokio::time::Duration = tokio::time::Duration::from_millis(500);

        let ws_message = match timeout(TIMEOUT, self.next()).await {
            Ok(Some(Ok(v))) => Some(v),
            Ok(Some(Err(e))) => return Err(e.into()),
            Ok(None) | Err(_) => None,
        };

        convert_ws_message(ws_message)
    }

    async fn try_recv_json(&mut self) -> Result<Option<Value>> {
        convert_ws_message(self.try_next().await.ok().flatten())
    }
}

#[async_trait]
impl SenderExt for SplitSink<WsStream, Message> {
    async fn send_json(&mut self, value: &Value) -> Result<()> {
        Ok(to_string(value).map(Message::Text).map_err(Error::from).map(|m| self.send(m))?.await?)
    }
}

#[async_trait]
impl SenderExt for WsStream {
    async fn send_json(&mut self, value: &Value) -> Result<()> {
        Ok(to_string(value).map(Message::Text).map_err(Error::from).map(|m| self.send(m))?.await?)
    }
}

#[inline]
pub(crate) fn convert_ws_message(message: Option<Message>) -> Result<Option<Value>> {
    const DECOMPRESSION_MULTIPLIER: usize = 3;

    Ok(match message {
        Some(Message::Binary(bytes)) => {
            let mut decompressed = String::with_capacity(bytes.len() * DECOMPRESSION_MULTIPLIER);

            ZlibDecoder::new(&bytes[..]).read_to_string(&mut decompressed).map_err(|why| {
                warn!("Err decompressing bytes: {:?}; bytes: {:?}", why, bytes);

                why
            })?;

            from_str(decompressed.as_mut_str()).map(Some).map_err(|why| {
                warn!("Err deserializing bytes: {:?}; bytes: {:?}", why, bytes);

                why
            })?
        },
        Some(Message::Text(mut payload)) => from_str(&mut payload).map(Some).map_err(|why| {
            warn!("Err deserializing text: {:?}; text: {}", why, payload,);

            why
        })?,
        Some(Message::Close(Some(frame))) => {
            return Err(Error::Gateway(GatewayError::Closed(Some(frame))));
        },
        // Ping/Pong message behaviour is internally handled by tungstenite.
        _ => None,
    })
}

#[instrument]
pub(crate) async fn create_client(url: Url) -> Result<WsStream> {
    let config = async_tungstenite::tungstenite::protocol::WebSocketConfig {
        max_message_size: None,
        max_frame_size: None,
        max_send_queue: None,
        accept_unmasked_frames: false,
    };
    let (stream, _) =
        async_tungstenite::tokio::connect_async_with_config(url, Some(config)).await?;

    Ok(stream)
}
<commit_msg>Remove unused code related to the former voice functionality (#1883)<commit_after>use std::io::Read;

use async_trait::async_trait;
use async_tungstenite::tungstenite::Message;
use flate2::read::ZlibDecoder;
use futures::{SinkExt, StreamExt};
use tokio::time::timeout;
use tracing::{instrument, warn};
use url::Url;

use crate::gateway::{GatewayError, WsStream};
use crate::internal::prelude::*;
use crate::json::{from_str, to_string};

#[async_trait]
pub trait ReceiverExt {
    async fn recv_json(&mut self) -> Result<Option<Value>>;
}

#[async_trait]
pub trait SenderExt {
    async fn send_json(&mut self, value: &Value) -> Result<()>;
}

#[async_trait]
impl ReceiverExt for WsStream {
    async fn recv_json(&mut self) -> Result<Option<Value>> {
        const TIMEOUT: tokio::time::Duration = tokio::time::Duration::from_millis(500);

        let ws_message = match timeout(TIMEOUT, self.next()).await {
            Ok(Some(Ok(v))) => Some(v),
            Ok(Some(Err(e))) => return Err(e.into()),
            Ok(None) | Err(_) => None,
        };

        convert_ws_message(ws_message)
    }
}

#[async_trait]
impl SenderExt for WsStream {
    async fn send_json(&mut self, value: &Value) -> Result<()> {
        Ok(to_string(value).map(Message::Text).map_err(Error::from).map(|m| self.send(m))?.await?)
    }
}

#[inline]
pub(crate) fn convert_ws_message(message: Option<Message>) -> Result<Option<Value>> {
    const DECOMPRESSION_MULTIPLIER: usize = 3;

    Ok(match message {
        Some(Message::Binary(bytes)) => {
            let mut decompressed = String::with_capacity(bytes.len() * DECOMPRESSION_MULTIPLIER);

            ZlibDecoder::new(&bytes[..]).read_to_string(&mut decompressed).map_err(|why| {
                warn!("Err decompressing bytes: {:?}; bytes: {:?}", why, bytes);

                why
            })?;

            from_str(decompressed.as_mut_str()).map(Some).map_err(|why| {
                warn!("Err deserializing bytes: {:?}; bytes: {:?}", why, bytes);

                why
            })?
        },
        Some(Message::Text(mut payload)) => from_str(&mut payload).map(Some).map_err(|why| {
            warn!("Err deserializing text: {:?}; text: {}", why, payload,);

            why
        })?,
        Some(Message::Close(Some(frame))) => {
            return Err(Error::Gateway(GatewayError::Closed(Some(frame))));
        },
        // Ping/Pong message behaviour is internally handled by tungstenite.
        _ => None,
    })
}

#[instrument]
pub(crate) async fn create_client(url: Url) -> Result<WsStream> {
    let config = async_tungstenite::tungstenite::protocol::WebSocketConfig {
        max_message_size: None,
        max_frame_size: None,
        max_send_queue: None,
        accept_unmasked_frames: false,
    };
    let (stream, _) =
        async_tungstenite::tokio::connect_async_with_config(url, Some(config)).await?;

    Ok(stream)
}
<|endoftext|>


<commit_before>extern crate regex;

use self::regex::{Error as RegexError, Regex};

use constant::ME;
use error::{CliError, CronError, CronErrorKind};
use lib::io::*;
use std::collections::BTreeSet;
use std::env;
use std::fmt::Display;
use std::io::Write;
use std::path::Path;
use std::process::{self, Stdio};
use std::str;

#[derive(Debug)]
pub struct Cron {
    upper  : String,
    my_area: String,
    lower  : String,
}

impl Cron {
    fn base_mark<D: Display>(keyword: &str, exec: D) -> String {
        format!(
            r#"###################################
# "{}" uses the lines {}.
# Please don't touch them and me!
###################################
{}"#,
            ME,
            keyword,
            exec,
        )
    }
    fn start_mark() -> String {
        Self::base_mark("from this", Self::patrol())
    }
    fn end_mark() -> String {
        Self::base_mark("up to here", "")
    }

    fn patrol() -> String {
        format!("0 0 * * *\t{} patrol\n", ME)
    }

    fn escape_asterisk<S: AsRef<str>>(s: S) -> String {
        let re = match Regex::new(r"\*") {
            Ok(re) => re,
            Err(_) => unreachable!("Mistake regular expression!!"),
        };
        re.replace_all(s.as_ref(), "\\*")
    }

    pub fn read() -> Result<Self, CliError> {
        print_with_tag(Tag::Info, "Read cron");

        let result = process::Command::new("crontab")
            .arg("-l")
            .output();
        let output = try!(result);

        let contents = if output.status.success() {
            try!(str::from_utf8(&output.stdout).map_err(|_| CronError::new(CronErrorKind::InvalidCharacterCode)))
        } else {
            ""
        };

        let areas = format!(
            "^(?P<upper>(.|\n)*){}(?P<my_area>(.|\n)*){}(?P<lower>(.|\n)*)$",
            Self::escape_asterisk(Self::start_mark()),
            Self::end_mark(),
        );
        let re = match Regex::new(&areas) {
            Ok(re) => re,
            Err(_) => unreachable!("Mistake the regular expression!!"),
        };

        let (upper, my_area, lower) = match re.captures(contents) {
            Some(caps) => match (caps.name("upper"), caps.name("my_area"), caps.name("lower")) {
                (Some(u), Some(m), Some(l)) => (u, m, l),
                _                           => unreachable!("Mistake regular expression!!"),
            },
            None => (contents, "", ""),
        };

        Ok(Cron { upper: upper.to_string(), my_area: my_area.to_string(), lower: lower.to_string() })
    }

    pub fn update(mut self, pairs: &[(&str, &str); 2]) -> Result<Self, CliError> {
        let current_dir = try!(Self::current_dir_string());
        self.delete(&current_dir);

        let my_new_area = pairs
            .iter()
            .fold(String::new(), |area, &(time, command)| {
                let line = format!("{}\tcd {} && {} {}\n", time, current_dir, ME, command);
                area + &line
            });

        self.my_area = self.my_area + &my_new_area;
        Ok(self)
    }

    fn re_for_matching_line<S: AsRef<str>>(core: S) -> String {
        format!(r".*cd\s+{}\s+&&\s+{}.*\n", core.as_ref(), ME)
    }

    pub fn delete<S: AsRef<str>>(&mut self, dir: S) {
        let re = Self::re_for_matching_line(dir);
        let re = match Regex::new(re.as_ref()) {
            Ok(re) => re,
            Err(_) => unreachable!("Mistake regular expression!!"),
        };
        self.my_area = re.replace_all(&self.my_area, "");
    }

    pub fn discard(mut self) -> Result<Self, RegexError> {
        let re = Self::re_for_matching_line(r"(?P<path>[^\s]+)");
        let target_paths = try!(Regex::new(re.as_ref()))
            .captures_iter(&self.my_area)
            .map(|caps| match caps.name("path") {
                Some(p) => p.to_string(),
                None    => unreachable!("Mistake regular expression!!"),
            })
            .filter(|path| !Path::new(path).is_dir())
            .collect::<BTreeSet<String>>();
        if target_paths.len() == 0 {
            return Ok(self);
        }

        let re_core = target_paths
            .iter()
            .fold(String::new(), |core, path| core + "|" + path); // We want to use true "Iterator.reduce()".
        let re_core = re_core.trim_left_matches('|');
        let re = Self::re_for_matching_line(format!("({})", re_core));
        let re = try!(Regex::new(re.as_ref()));
        self.my_area = re.replace_all(&self.my_area, "");
        Ok(self)
    }

    pub fn set(self) -> Result<(), CliError> {
        print_with_tag(Tag::Info, "Set new cron");

        let result = process::Command::new("crontab")
            .stdin(Stdio::piped())
            .spawn();
        let mut child = try!(result);

        let contents = if self.my_area_is_empty() {
            self.upper + &self.lower
        } else {
            self.upper
                + &Self::start_mark()
                + &self.my_area
                + &Self::end_mark()
                + &self.lower
        };
        match &mut child.stdin {
            &mut Some(ref mut stdin) => try!(stdin.write_all(contents.as_bytes())),
            &mut None                => unreachable!("Please set Stdio::piped()!!"),
        };

        let output = try!(child.wait_with_output());
        if output.status.success() {
            Ok(())
        } else {
            Err(From::from(CronError::new(CronErrorKind::FailedToWrite)))
        }
    }

    pub fn current_dir_string() -> Result<String, CronError> {
        let current_dir = match env::current_dir() {
            Ok(d)  => d,
            Err(_) => unreachable!("There is a problem for current directory!!"),
        };
        current_dir
            .to_str()
            .ok_or(CronError::new(CronErrorKind::InvalidPath))
            .map(|s| s.to_string())
    }

    fn my_area_is_empty(&self) -> bool {
        let re = match Regex::new(r"^\s*$") {
            Ok(re) => re,
            Err(_) => unreachable!("Mistake the regular expression!!"),
        };
        re.is_match(self.my_area.as_ref())
    }
}

#[test]
fn my_area_is_empty_should_return_true() {
    let empties = [
        "",
        " ",
        "\t",
        "\r",
        "\n",
        " \t\r\n",
    ];

    for empty in &empties {
        let cron = Cron {
            upper: ""     .to_string(),
            my_area: empty.to_string(),
            lower: ""     .to_string(),
        };
        assert!(cron.my_area_is_empty());
    }
}
#[test]
fn my_area_is_empty_should_return_false() {
    let non_empties = [
        "a",
        "ab",
        " ab",
        "a b",
        "ab ",
        "\tab",
        "a\tb",
        "ab\t",
        "\rab",
        "a\rb",
        "ab\r",
        "\nab",
        "a\nb",
        "ab\n",
        " \t\r\nab",
        "a \t\r\nb",
        "ab \t\r\n",
    ];

    for non_empty in &non_empties {
        let cron = Cron {
            upper  : ""       .to_string(),
            my_area: non_empty.to_string(),
            lower  : ""       .to_string(),
        };
        assert!(!cron.my_area_is_empty());
    }
}

#[test]
fn delete_should_success() {
    fn wrap_by_extra_content<S: AsRef<str>>(target: S) -> String {
        let extra_content = "when cd path_to_extra && kic command\n";
        format!("{}{}{}", extra_content, target.as_ref(), extra_content)
    }

    let mut cron = Cron {
        upper  : "upper\n".to_string(),
        my_area: ""       .to_string(),
        lower  : "lower\n".to_string(),
    };

    let dir = "path_to_dir";

    let areas = vec![
        ("".to_string(), format!("cd {} && kic\n"             , dir)),
        ("".to_string(), format!("when cd {} && kic\n"        , dir)),
        ("".to_string(), format!("cd {} && kic command\n"     , dir)),
        ("".to_string(), format!("when cd {} && kic command\n", dir)),

        (wrap_by_extra_content(""), wrap_by_extra_content(format!("cd {} && kic\n"             , dir))),
        (wrap_by_extra_content(""), wrap_by_extra_content(format!("when cd {} && kic\n"        , dir))),
        (wrap_by_extra_content(""), wrap_by_extra_content(format!("cd {} && kic command\n"     , dir))),
        (wrap_by_extra_content(""), wrap_by_extra_content(format!("when cd {} && kic command\n", dir))),
    ];

    for (correct, area) in areas.into_iter() {
        cron.my_area = area;
        cron.delete(&dir);
        assert_eq!(correct, cron.my_area);
    }
}
<commit_msg>[Remedy] Change output message for developers<commit_after>extern crate regex;

use self::regex::{Error as RegexError, Regex};

use constant::ME;
use error::{CliError, CronError, CronErrorKind};
use lib::io::*;
use std::collections::BTreeSet;
use std::env;
use std::fmt::Display;
use std::io::Write;
use std::path::Path;
use std::process::{self, Stdio};
use std::str;

#[derive(Debug)]
pub struct Cron {
    upper  : String,
    my_area: String,
    lower  : String,
}

impl Cron {
    fn base_mark<D: Display>(keyword: &str, exec: D) -> String {
        format!(
            r#"###################################
# "{}" uses the lines {}.
# Please don't touch them and me!
###################################
{}"#,
            ME,
            keyword,
            exec,
        )
    }
    fn start_mark() -> String {
        Self::base_mark("from this", Self::patrol())
    }
    fn end_mark() -> String {
        Self::base_mark("up to here", "")
    }

    fn patrol() -> String {
        format!("0 0 * * *\t{} patrol\n", ME)
    }

    fn escape_asterisk<S: AsRef<str>>(s: S) -> String {
        let re = match Regex::new(r"\*") {
            Ok(re) => re,
            Err(_) => unreachable!("Mistake regular expression!!"),
        };
        re.replace_all(s.as_ref(), "\\*")
    }

    pub fn read() -> Result<Self, CliError> {
        print_with_tag(Tag::Info, "Read cron");

        let result = process::Command::new("crontab")
            .arg("-l")
            .output();
        let output = try!(result);

        let contents = if output.status.success() {
            try!(str::from_utf8(&output.stdout).map_err(|_| CronError::new(CronErrorKind::InvalidCharacterCode)))
        } else {
            ""
        };

        let areas = format!(
            "^(?P<upper>(.|\n)*){}(?P<my_area>(.|\n)*){}(?P<lower>(.|\n)*)$",
            Self::escape_asterisk(Self::start_mark()),
            Self::end_mark(),
        );
        let re = match Regex::new(&areas) {
            Ok(re) => re,
            Err(_) => unreachable!("Mistake the regular expression!!"),
        };

        let (upper, my_area, lower) = match re.captures(contents) {
            Some(caps) => match (caps.name("upper"), caps.name("my_area"), caps.name("lower")) {
                (Some(u), Some(m), Some(l)) => (u, m, l),
                _                           => unreachable!("Mistake regular expression!!"),
            },
            None => (contents, "", ""),
        };

        Ok(Cron { upper: upper.to_string(), my_area: my_area.to_string(), lower: lower.to_string() })
    }

    pub fn update(mut self, pairs: &[(&str, &str); 2]) -> Result<Self, CliError> {
        let current_dir = try!(Self::current_dir_string());
        self.delete(&current_dir);

        let my_new_area = pairs
            .iter()
            .fold(String::new(), |area, &(time, command)| {
                let line = format!("{}\tcd {} && {} {}\n", time, current_dir, ME, command);
                area + &line
            });

        self.my_area = self.my_area + &my_new_area;
        Ok(self)
    }

    fn re_for_matching_line<S: AsRef<str>>(core: S) -> String {
        format!(r".*cd\s+{}\s+&&\s+{}.*\n", core.as_ref(), ME)
    }

    pub fn delete<S: AsRef<str>>(&mut self, dir: S) {
        let re = Self::re_for_matching_line(dir);
        let re = match Regex::new(re.as_ref()) {
            Ok(re) => re,
            Err(_) => unreachable!("Wrong to use delete()!!"),
        };
        self.my_area = re.replace_all(&self.my_area, "");
    }

    pub fn discard(mut self) -> Result<Self, RegexError> {
        let re = Self::re_for_matching_line(r"(?P<path>[^\s]+)");
        let target_paths = try!(Regex::new(re.as_ref()))
            .captures_iter(&self.my_area)
            .map(|caps| match caps.name("path") {
                Some(p) => p.to_string(),
                None    => unreachable!("Mistake regular expression!!"),
            })
            .filter(|path| !Path::new(path).is_dir())
            .collect::<BTreeSet<String>>();
        if target_paths.len() == 0 {
            return Ok(self);
        }

        let re_core = target_paths
            .iter()
            .fold(String::new(), |core, path| core + "|" + path); // We want to use true "Iterator.reduce()".
        let re_core = re_core.trim_left_matches('|');
        let re = Self::re_for_matching_line(format!("({})", re_core));
        let re = try!(Regex::new(re.as_ref()));
        self.my_area = re.replace_all(&self.my_area, "");
        Ok(self)
    }

    pub fn set(self) -> Result<(), CliError> {
        print_with_tag(Tag::Info, "Set new cron");

        let result = process::Command::new("crontab")
            .stdin(Stdio::piped())
            .spawn();
        let mut child = try!(result);

        let contents = if self.my_area_is_empty() {
            self.upper + &self.lower
        } else {
            self.upper
                + &Self::start_mark()
                + &self.my_area
                + &Self::end_mark()
                + &self.lower
        };
        match &mut child.stdin {
            &mut Some(ref mut stdin) => try!(stdin.write_all(contents.as_bytes())),
            &mut None                => unreachable!("Please set Stdio::piped()!!"),
        };

        let output = try!(child.wait_with_output());
        if output.status.success() {
            Ok(())
        } else {
            Err(From::from(CronError::new(CronErrorKind::FailedToWrite)))
        }
    }

    pub fn current_dir_string() -> Result<String, CronError> {
        let current_dir = match env::current_dir() {
            Ok(d)  => d,
            Err(_) => unreachable!("There is a problem for current directory!!"),
        };
        current_dir
            .to_str()
            .ok_or(CronError::new(CronErrorKind::InvalidPath))
            .map(|s| s.to_string())
    }

    fn my_area_is_empty(&self) -> bool {
        let re = match Regex::new(r"^\s*$") {
            Ok(re) => re,
            Err(_) => unreachable!("Mistake the regular expression!!"),
        };
        re.is_match(self.my_area.as_ref())
    }
}

#[test]
fn my_area_is_empty_should_return_true() {
    let empties = [
        "",
        " ",
        "\t",
        "\r",
        "\n",
        " \t\r\n",
    ];

    for empty in &empties {
        let cron = Cron {
            upper: ""     .to_string(),
            my_area: empty.to_string(),
            lower: ""     .to_string(),
        };
        assert!(cron.my_area_is_empty());
    }
}
#[test]
fn my_area_is_empty_should_return_false() {
    let non_empties = [
        "a",
        "ab",
        " ab",
        "a b",
        "ab ",
        "\tab",
        "a\tb",
        "ab\t",
        "\rab",
        "a\rb",
        "ab\r",
        "\nab",
        "a\nb",
        "ab\n",
        " \t\r\nab",
        "a \t\r\nb",
        "ab \t\r\n",
    ];

    for non_empty in &non_empties {
        let cron = Cron {
            upper  : ""       .to_string(),
            my_area: non_empty.to_string(),
            lower  : ""       .to_string(),
        };
        assert!(!cron.my_area_is_empty());
    }
}

#[test]
fn delete_should_success() {
    fn wrap_by_extra_content<S: AsRef<str>>(target: S) -> String {
        let extra_content = "when cd path_to_extra && kic command\n";
        format!("{}{}{}", extra_content, target.as_ref(), extra_content)
    }

    let mut cron = Cron {
        upper  : "upper\n".to_string(),
        my_area: ""       .to_string(),
        lower  : "lower\n".to_string(),
    };

    let dir = "path_to_dir";

    let areas = vec![
        ("".to_string(), format!("cd {} && kic\n"             , dir)),
        ("".to_string(), format!("when cd {} && kic\n"        , dir)),
        ("".to_string(), format!("cd {} && kic command\n"     , dir)),
        ("".to_string(), format!("when cd {} && kic command\n", dir)),

        (wrap_by_extra_content(""), wrap_by_extra_content(format!("cd {} && kic\n"             , dir))),
        (wrap_by_extra_content(""), wrap_by_extra_content(format!("when cd {} && kic\n"        , dir))),
        (wrap_by_extra_content(""), wrap_by_extra_content(format!("cd {} && kic command\n"     , dir))),
        (wrap_by_extra_content(""), wrap_by_extra_content(format!("when cd {} && kic command\n", dir))),
    ];

    for (correct, area) in areas.into_iter() {
        cron.my_area = area;
        cron.delete(&dir);
        assert_eq!(correct, cron.my_area);
    }
}
<|endoftext|>