<commit_before>/// Is used to control the visibility of a widget
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Visibility {
    /// The widget is visible.
    Visible,

    /// The widget will not be displayed, isn't taken into account in the
    /// layout pipeline, thus doesn't consume memory in the render buffer.
    Hidden,

    /// The widget isn't displayed but `is` rendered and thus consume
    /// memory in the layout.
    Collapsed,
}

impl Default for Visibility {
    fn default() -> Visibility {
        Visibility::Visible
    }
}

// --- Conversions ---

impl From<&str> for Visibility {
    fn from(t: &str) -> Self {
        match t {
            "Hidden" | "hidden" => Visibility::Hidden,
            "Collapsed" | "collapsed" => Visibility::Collapsed,
            _ => Visibility::Visible,
        }
    }
}

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

    #[test]
    fn test_into() {
        let visibility: Visibility = "Hidden".into();
        assert_eq!(visibility, Visibility::Hidden);

        let visibility: Visibility = "hidden".into();
        assert_eq!(visibility, Visibility::Hidden);

        let visibility: Visibility = "Collapsed".into();
        assert_eq!(visibility, Visibility::Collapsed);

        let visibility: Visibility = "collapsed".into();
        assert_eq!(visibility, Visibility::Collapsed);

        let visibility: Visibility = "Visible".into();
        assert_eq!(visibility, Visibility::Visible);

        let visibility: Visibility = "visible".into();
        assert_eq!(visibility, Visibility::Visible);

        let visibility: Visibility = "other".into();
        assert_eq!(visibility, Visibility::Visible);
    }
}
<commit_msg>utils: update visibility documentation string<commit_after>/// Is used to control the visibility of a widget
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Visibility {
    /// The widget is visible.
    Visible,

    /// The widget will not be displayed, isn't taken into account in the
    /// layout pipeline. It **does** consume memory in the render buffer.
    Hidden,

    /// The widget isn't displayed but `is` rendered. Thus it **dos
    /// not** consume space in the layout.
    Collapsed,
}

impl Default for Visibility {
    fn default() -> Visibility {
	Visibility::Visible
    }
}

// --- Conversions ---

impl From<&str> for Visibility {
    fn from(t: &str) -> Self {
	match t {
	    "Hidden" | "hidden" => Visibility::Hidden,
	    "Collapsed" | "collapsed" => Visibility::Collapsed,
	    _ => Visibility::Visible,
	}
    }
}

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

    #[test]
    fn test_into() {
	let visibility: Visibility = "Hidden".into();
	assert_eq!(visibility, Visibility::Hidden);

	let visibility: Visibility = "hidden".into();
	assert_eq!(visibility, Visibility::Hidden);

	let visibility: Visibility = "Collapsed".into();
	assert_eq!(visibility, Visibility::Collapsed);

	let visibility: Visibility = "collapsed".into();
	assert_eq!(visibility, Visibility::Collapsed);

	let visibility: Visibility = "Visible".into();
	assert_eq!(visibility, Visibility::Visible);

	let visibility: Visibility = "visible".into();
	assert_eq!(visibility, Visibility::Visible);

	let visibility: Visibility = "other".into();
	assert_eq!(visibility, Visibility::Visible);
    }
}
<|endoftext|>


<commit_before>extern crate react;

use react::*;

#[test]
fn input_cells_have_a_value() {
    let mut reactor = Reactor::new();
    let input = reactor.create_input(10);
    assert_eq!(reactor.value(input), Some(10));
}

#[test]
#[ignore]
fn an_input_cells_value_can_be_set() {
    let mut reactor = Reactor::new();
    let input = reactor.create_input(4);
    assert!(reactor.set_value(input, 20).is_ok());
    assert_eq!(reactor.value(input), Some(20));
}

#[test]
#[ignore]
fn error_setting_a_nonexistent_input_cell() {
    let mut dummy_reactor = Reactor::new();
    let input = dummy_reactor.create_input(1);
    assert!(Reactor::new().set_value(input, 0).is_err());
}

#[test]
#[ignore]
fn compute_cells_calculate_initial_value() {
    let mut reactor = Reactor::new();
    let input = reactor.create_input(1);
    let output = reactor.create_compute(&vec![input], |v| v[0] + 1).unwrap();
    assert_eq!(reactor.value(output), Some(2));
}

#[test]
#[ignore]
fn compute_cells_take_inputs_in_the_right_order() {
    let mut reactor = Reactor::new();
    let one = reactor.create_input(1);
    let two = reactor.create_input(2);
    let output = reactor.create_compute(&vec![one, two], |v| v[0] + v[1] * 10).unwrap();
    assert_eq!(reactor.value(output), Some(21));
}

#[test]
#[ignore]
fn error_creating_compute_cell_if_input_doesnt_exist() {
    let mut dummy_reactor = Reactor::new();
    let input = dummy_reactor.create_input(1);
    assert!(Reactor::new().create_compute(&vec![input], |_| 0).is_err());
}

#[test]
#[ignore]
fn do_not_break_cell_if_creating_compute_cell_with_valid_and_invalid_input() {
    let mut dummy_reactor = Reactor::new();
    let _ = dummy_reactor.create_input(1);
    let dummy_cell = dummy_reactor.create_input(2);
    let mut reactor = Reactor::new();
    let input = reactor.create_input(1);
    assert!(reactor.create_compute(&vec![input, dummy_cell], |_| 0).is_err());
    assert!(reactor.set_value(input, 5).is_ok());
    assert_eq!(reactor.value(input), Some(5));
}

#[test]
#[ignore]
fn compute_cells_update_value_when_dependencies_are_changed() {
    let mut reactor = Reactor::new();
    let input = reactor.create_input(1);
    let output = reactor.create_compute(&vec![input], |v| v[0] + 1).unwrap();
    assert_eq!(reactor.value(output), Some(2));
    assert!(reactor.set_value(input, 3).is_ok());
    assert_eq!(reactor.value(output), Some(4));
}

#[test]
#[ignore]
fn compute_cells_can_depend_on_other_compute_cells() {
    let mut reactor = Reactor::new();
    let input = reactor.create_input(1);
    let times_two = reactor.create_compute(&vec![input], |v| v[0] * 2).unwrap();
    let times_thirty = reactor.create_compute(&vec![input], |v| v[0] * 30).unwrap();
    let output = reactor.create_compute(&vec![times_two, times_thirty], |v| v[0] + v[1]).unwrap();
    assert_eq!(reactor.value(output), Some(32));
    assert!(reactor.set_value(input, 3).is_ok());
    assert_eq!(reactor.value(output), Some(96));
}

#[test]
#[ignore]
fn error_setting_a_compute_cell() {
    let mut reactor = Reactor::new();
    let input = reactor.create_input(1);
    let output = reactor.create_compute(&vec![input], |_| 0).unwrap();
    assert!(reactor.set_value(output, 3).is_err());
}

#[test]
#[ignore]
fn compute_cells_fire_callbacks() {
    // This is a bit awkward, but the closure mutably borrows `values`.
    // So we have to end its borrow by taking reactor out of scope.
    let mut values = Vec::new();
    {
        let mut reactor = Reactor::new();
        let input = reactor.create_input(1);
        let output = reactor.create_compute(&vec![input], |v| v[0] + 1).unwrap();
        assert!(reactor.add_callback(output, |v| values.push(v)).is_ok());
        assert!(reactor.set_value(input, 3).is_ok());
    }
    assert_eq!(values, vec![4]);
}

#[test]
#[ignore]
fn error_adding_callback_to_nonexistent_cell() {
    let mut dummy_reactor = Reactor::new();
    let input = dummy_reactor.create_input(1);
    let output = dummy_reactor.create_compute(&vec![input], |_| 0).unwrap();
    assert!(Reactor::new().add_callback(output, |_: usize| println!("hi")).is_err());
}

#[test]
#[ignore]
fn callbacks_only_fire_on_change() {
    let mut values = Vec::new();
    {
        let mut reactor = Reactor::new();
        let input = reactor.create_input(1);
        let output = reactor.create_compute(&vec![input], |v| if v[0] < 3 { 111 } else { 222 }).unwrap();
        assert!(reactor.add_callback(output, |v| values.push(v)).is_ok());
        assert!(reactor.set_value(input, 2).is_ok());
        assert!(reactor.set_value(input, 4).is_ok());
    }
    assert_eq!(values, vec![222]);
}

#[test]
#[ignore]
fn callbacks_can_be_added_and_removed() {
    let mut values1 = Vec::new();
    let mut values2 = Vec::new();
    let mut values3 = Vec::new();
    {
        let mut reactor = Reactor::new();
        let input = reactor.create_input(11);
        let output = reactor.create_compute(&vec![input], |v| v[0] + 1).unwrap();
        let callback = reactor.add_callback(output, |v| values1.push(v)).unwrap();
        assert!(reactor.add_callback(output, |v| values2.push(v)).is_ok());
        assert!(reactor.set_value(input, 31).is_ok());
        assert!(reactor.remove_callback(output, callback).is_ok());
        assert!(reactor.add_callback(output, |v| values3.push(v)).is_ok());
        assert!(reactor.set_value(input, 41).is_ok());
    }
    assert_eq!(values1, vec![32]);
    assert_eq!(values2, vec![32, 42]);
    assert_eq!(values3, vec![42]);
}

#[test]
#[ignore]
fn removing_a_callback_multiple_times_doesnt_interfere_with_other_callbacks() {
    let mut values1 = Vec::new();
    let mut values2 = Vec::new();
    {
        let mut reactor = Reactor::new();
        let input = reactor.create_input(1);
        let output = reactor.create_compute(&vec![input], |v| v[0] + 1).unwrap();
        let callback = reactor.add_callback(output, |v| values1.push(v)).unwrap();
        assert!(reactor.add_callback(output, |v| values2.push(v)).is_ok());
        // We want the first remove to be Ok, but we don't care about the others.
        assert!(reactor.remove_callback(output, callback).is_ok());
        for _ in 1..5 {
            assert!(reactor.remove_callback(output, callback).is_err());
        }
        assert!(reactor.set_value(input, 2).is_ok());
    }
    assert_eq!(values1, Vec::new());
    assert_eq!(values2, vec![3]);
}

#[test]
#[ignore]
fn callbacks_should_only_be_called_once_even_if_multiple_dependencies_change() {
    let mut values = Vec::new();
    {
        let mut reactor = Reactor::new();
        let input = reactor.create_input(1);
        let plus_one = reactor.create_compute(&vec![input], |v| v[0] + 1).unwrap();
        let minus_one1 = reactor.create_compute(&vec![input], |v| v[0] - 1).unwrap();
        let minus_one2 = reactor.create_compute(&vec![minus_one1], |v| v[0] - 1).unwrap();
        let output = reactor.create_compute(&vec![plus_one, minus_one2], |v| v[0] * v[1]).unwrap();
        assert!(reactor.add_callback(output, |v| values.push(v)).is_ok());
        assert!(reactor.set_value(input, 4).is_ok());
    }
    assert_eq!(values, vec![10]);
}

#[test]
#[ignore]
fn callbacks_should_not_be_called_if_dependencies_change_but_output_value_doesnt_change() {
    let mut values = Vec::new();
    {
        let mut reactor = Reactor::new();
        let input = reactor.create_input(1);
        let plus_one = reactor.create_compute(&vec![input], |v| v[0] + 1).unwrap();
        let minus_one = reactor.create_compute(&vec![input], |v| v[0] - 1).unwrap();
        let always_two = reactor.create_compute(&vec![plus_one, minus_one], |v| v[0] - v[1]).unwrap();
        assert!(reactor.add_callback(always_two, |v| values.push(v)).is_ok());
        for i in 2..5 {
            assert!(reactor.set_value(input, i).is_ok());
        }
    }
    assert_eq!(values, Vec::new());
}

#[test]
#[ignore]
fn test_adder_with_boolean_values() {
    // This is a digital logic circuit called an adder:
    // https://en.wikipedia.org/wiki/Adder_(electronics)
    let mut reactor = Reactor::new();
    let a = reactor.create_input(false);
    let b = reactor.create_input(false);
    let carry_in = reactor.create_input(false);

    let a_xor_b = reactor.create_compute(&vec![a, b], |v| v[0] ^ v[1]).unwrap();
    let sum = reactor.create_compute(&vec![a_xor_b, carry_in], |v| v[0] ^ v[1]).unwrap();

    let a_xor_b_and_cin = reactor.create_compute(&vec![a_xor_b, carry_in], |v| v[0] && v[1]).unwrap();
    let a_and_b = reactor.create_compute(&vec![a, b], |v| v[0] && v[1]).unwrap();
    let carry_out = reactor.create_compute(&vec![a_xor_b_and_cin, a_and_b], |v| v[0] || v[1]).unwrap();

    let tests = vec![
        (false, false, false, false, false),
        (false, false, true, false, true),
        (false, true, false, false, true),
        (false, true, true, true, false),
        (true, false, false, false, true),
        (true, false, true, true, false),
        (true, true, false, true, false),
        (true, true, true, true, true),
    ];

    for (aval, bval, cinval, expected_cout, expected_sum) in tests {
        assert!(reactor.set_value(a, aval).is_ok());
        assert!(reactor.set_value(b, bval).is_ok());
        assert!(reactor.set_value(carry_in, cinval).is_ok());

        assert_eq!(reactor.value(sum), Some(expected_sum));
        assert_eq!(reactor.value(carry_out), Some(expected_cout));
    }
}
<commit_msg>react: Use `&[...]` instead of `&vec![...]`<commit_after>extern crate react;

use react::*;

#[test]
fn input_cells_have_a_value() {
    let mut reactor = Reactor::new();
    let input = reactor.create_input(10);
    assert_eq!(reactor.value(input), Some(10));
}

#[test]
#[ignore]
fn an_input_cells_value_can_be_set() {
    let mut reactor = Reactor::new();
    let input = reactor.create_input(4);
    assert!(reactor.set_value(input, 20).is_ok());
    assert_eq!(reactor.value(input), Some(20));
}

#[test]
#[ignore]
fn error_setting_a_nonexistent_input_cell() {
    let mut dummy_reactor = Reactor::new();
    let input = dummy_reactor.create_input(1);
    assert!(Reactor::new().set_value(input, 0).is_err());
}

#[test]
#[ignore]
fn compute_cells_calculate_initial_value() {
    let mut reactor = Reactor::new();
    let input = reactor.create_input(1);
    let output = reactor.create_compute(&[input], |v| v[0] + 1).unwrap();
    assert_eq!(reactor.value(output), Some(2));
}

#[test]
#[ignore]
fn compute_cells_take_inputs_in_the_right_order() {
    let mut reactor = Reactor::new();
    let one = reactor.create_input(1);
    let two = reactor.create_input(2);
    let output = reactor.create_compute(&[one, two], |v| v[0] + v[1] * 10).unwrap();
    assert_eq!(reactor.value(output), Some(21));
}

#[test]
#[ignore]
fn error_creating_compute_cell_if_input_doesnt_exist() {
    let mut dummy_reactor = Reactor::new();
    let input = dummy_reactor.create_input(1);
    assert!(Reactor::new().create_compute(&[input], |_| 0).is_err());
}

#[test]
#[ignore]
fn do_not_break_cell_if_creating_compute_cell_with_valid_and_invalid_input() {
    let mut dummy_reactor = Reactor::new();
    let _ = dummy_reactor.create_input(1);
    let dummy_cell = dummy_reactor.create_input(2);
    let mut reactor = Reactor::new();
    let input = reactor.create_input(1);
    assert!(reactor.create_compute(&[input, dummy_cell], |_| 0).is_err());
    assert!(reactor.set_value(input, 5).is_ok());
    assert_eq!(reactor.value(input), Some(5));
}

#[test]
#[ignore]
fn compute_cells_update_value_when_dependencies_are_changed() {
    let mut reactor = Reactor::new();
    let input = reactor.create_input(1);
    let output = reactor.create_compute(&[input], |v| v[0] + 1).unwrap();
    assert_eq!(reactor.value(output), Some(2));
    assert!(reactor.set_value(input, 3).is_ok());
    assert_eq!(reactor.value(output), Some(4));
}

#[test]
#[ignore]
fn compute_cells_can_depend_on_other_compute_cells() {
    let mut reactor = Reactor::new();
    let input = reactor.create_input(1);
    let times_two = reactor.create_compute(&[input], |v| v[0] * 2).unwrap();
    let times_thirty = reactor.create_compute(&[input], |v| v[0] * 30).unwrap();
    let output = reactor.create_compute(&[times_two, times_thirty], |v| v[0] + v[1]).unwrap();
    assert_eq!(reactor.value(output), Some(32));
    assert!(reactor.set_value(input, 3).is_ok());
    assert_eq!(reactor.value(output), Some(96));
}

#[test]
#[ignore]
fn error_setting_a_compute_cell() {
    let mut reactor = Reactor::new();
    let input = reactor.create_input(1);
    let output = reactor.create_compute(&[input], |_| 0).unwrap();
    assert!(reactor.set_value(output, 3).is_err());
}

#[test]
#[ignore]
fn compute_cells_fire_callbacks() {
    // This is a bit awkward, but the closure mutably borrows `values`.
    // So we have to end its borrow by taking reactor out of scope.
    let mut values = Vec::new();
    {
        let mut reactor = Reactor::new();
        let input = reactor.create_input(1);
        let output = reactor.create_compute(&[input], |v| v[0] + 1).unwrap();
        assert!(reactor.add_callback(output, |v| values.push(v)).is_ok());
        assert!(reactor.set_value(input, 3).is_ok());
    }
    assert_eq!(values, vec![4]);
}

#[test]
#[ignore]
fn error_adding_callback_to_nonexistent_cell() {
    let mut dummy_reactor = Reactor::new();
    let input = dummy_reactor.create_input(1);
    let output = dummy_reactor.create_compute(&[input], |_| 0).unwrap();
    assert!(Reactor::new().add_callback(output, |_: usize| println!("hi")).is_err());
}

#[test]
#[ignore]
fn callbacks_only_fire_on_change() {
    let mut values = Vec::new();
    {
        let mut reactor = Reactor::new();
        let input = reactor.create_input(1);
        let output = reactor.create_compute(&[input], |v| if v[0] < 3 { 111 } else { 222 }).unwrap();
        assert!(reactor.add_callback(output, |v| values.push(v)).is_ok());
        assert!(reactor.set_value(input, 2).is_ok());
        assert!(reactor.set_value(input, 4).is_ok());
    }
    assert_eq!(values, vec![222]);
}

#[test]
#[ignore]
fn callbacks_can_be_added_and_removed() {
    let mut values1 = Vec::new();
    let mut values2 = Vec::new();
    let mut values3 = Vec::new();
    {
        let mut reactor = Reactor::new();
        let input = reactor.create_input(11);
        let output = reactor.create_compute(&[input], |v| v[0] + 1).unwrap();
        let callback = reactor.add_callback(output, |v| values1.push(v)).unwrap();
        assert!(reactor.add_callback(output, |v| values2.push(v)).is_ok());
        assert!(reactor.set_value(input, 31).is_ok());
        assert!(reactor.remove_callback(output, callback).is_ok());
        assert!(reactor.add_callback(output, |v| values3.push(v)).is_ok());
        assert!(reactor.set_value(input, 41).is_ok());
    }
    assert_eq!(values1, vec![32]);
    assert_eq!(values2, vec![32, 42]);
    assert_eq!(values3, vec![42]);
}

#[test]
#[ignore]
fn removing_a_callback_multiple_times_doesnt_interfere_with_other_callbacks() {
    let mut values1 = Vec::new();
    let mut values2 = Vec::new();
    {
        let mut reactor = Reactor::new();
        let input = reactor.create_input(1);
        let output = reactor.create_compute(&[input], |v| v[0] + 1).unwrap();
        let callback = reactor.add_callback(output, |v| values1.push(v)).unwrap();
        assert!(reactor.add_callback(output, |v| values2.push(v)).is_ok());
        // We want the first remove to be Ok, but we don't care about the others.
        assert!(reactor.remove_callback(output, callback).is_ok());
        for _ in 1..5 {
            assert!(reactor.remove_callback(output, callback).is_err());
        }
        assert!(reactor.set_value(input, 2).is_ok());
    }
    assert_eq!(values1, Vec::new());
    assert_eq!(values2, vec![3]);
}

#[test]
#[ignore]
fn callbacks_should_only_be_called_once_even_if_multiple_dependencies_change() {
    let mut values = Vec::new();
    {
        let mut reactor = Reactor::new();
        let input = reactor.create_input(1);
        let plus_one = reactor.create_compute(&[input], |v| v[0] + 1).unwrap();
        let minus_one1 = reactor.create_compute(&[input], |v| v[0] - 1).unwrap();
        let minus_one2 = reactor.create_compute(&[minus_one1], |v| v[0] - 1).unwrap();
        let output = reactor.create_compute(&[plus_one, minus_one2], |v| v[0] * v[1]).unwrap();
        assert!(reactor.add_callback(output, |v| values.push(v)).is_ok());
        assert!(reactor.set_value(input, 4).is_ok());
    }
    assert_eq!(values, vec![10]);
}

#[test]
#[ignore]
fn callbacks_should_not_be_called_if_dependencies_change_but_output_value_doesnt_change() {
    let mut values = Vec::new();
    {
        let mut reactor = Reactor::new();
        let input = reactor.create_input(1);
        let plus_one = reactor.create_compute(&[input], |v| v[0] + 1).unwrap();
        let minus_one = reactor.create_compute(&[input], |v| v[0] - 1).unwrap();
        let always_two = reactor.create_compute(&[plus_one, minus_one], |v| v[0] - v[1]).unwrap();
        assert!(reactor.add_callback(always_two, |v| values.push(v)).is_ok());
        for i in 2..5 {
            assert!(reactor.set_value(input, i).is_ok());
        }
    }
    assert_eq!(values, Vec::new());
}

#[test]
#[ignore]
fn test_adder_with_boolean_values() {
    // This is a digital logic circuit called an adder:
    // https://en.wikipedia.org/wiki/Adder_(electronics)
    let mut reactor = Reactor::new();
    let a = reactor.create_input(false);
    let b = reactor.create_input(false);
    let carry_in = reactor.create_input(false);

    let a_xor_b = reactor.create_compute(&[a, b], |v| v[0] ^ v[1]).unwrap();
    let sum = reactor.create_compute(&[a_xor_b, carry_in], |v| v[0] ^ v[1]).unwrap();

    let a_xor_b_and_cin = reactor.create_compute(&[a_xor_b, carry_in], |v| v[0] && v[1]).unwrap();
    let a_and_b = reactor.create_compute(&[a, b], |v| v[0] && v[1]).unwrap();
    let carry_out = reactor.create_compute(&[a_xor_b_and_cin, a_and_b], |v| v[0] || v[1]).unwrap();

    let tests = vec![
        (false, false, false, false, false),
        (false, false, true, false, true),
        (false, true, false, false, true),
        (false, true, true, true, false),
        (true, false, false, false, true),
        (true, false, true, true, false),
        (true, true, false, true, false),
        (true, true, true, true, true),
    ];

    for (aval, bval, cinval, expected_cout, expected_sum) in tests {
        assert!(reactor.set_value(a, aval).is_ok());
        assert!(reactor.set_value(b, bval).is_ok());
        assert!(reactor.set_value(carry_in, cinval).is_ok());

        assert_eq!(reactor.value(sum), Some(expected_sum));
        assert_eq!(reactor.value(carry_out), Some(expected_cout));
    }
}
<|endoftext|>


<commit_before>// 将闭包作为参数并调用它的函数。
fn apply<F>(f: F) where
    // 闭包没有输入值和返回值。
    F: FnOnce() {
    // ^ 试一试：将 `FnOnce` 换成 `Fn` 或 `FnMut`。

    f()
}

// 使用闭包并返回一个 `i32` 整型的函数。
fn apply_to_3<F>(f: F) -> i32 where
// 闭包处理一个 `i32` 整型并返回一个 `i32` 整型。
    F: Fn(i32) -> i32 {

    f(3)
}

fn main() {
    use std::mem;

    let greeting = "hello";
    // 不可复制的类型。
    let mut farewell = "goodbye".to_owned();

    // 捕获 2 个变量：通过引用方式的 `greeting` 和
    // 通过值方式的 `farewell`。
    let diary = || {
        // `greeting` 使用引用方式：需要 `Fn`。
        println!("I said {}.", greeting);

        // 改变迫使 `farewell` 变成了通过可变引用来捕获。
        // （原文：Mutation forces `farewell` to be
        // captured by mutable reference.）
        // 现在需要 `FnMut`。
        farewell.push_str("!!!");
        println!("Then I screamed {}.", farewell);
        println!("Now I can sleep. zzzzz");

        // 手动调用 drop 将 `farewell` 强制转成通过值来捕获。
        // （原文：Manually calling drop forces `farewell` to
        // be captured by value. Now requires `FnOnce`.）
        // 现在需要 `FnOnce`。
        mem::drop(farewell);
    };

    // 调用处理闭包的函数（原文：Call the function
    // which applies the closure）。
    apply(diary);

    let double = |x| 2 * x;

    println!("3 doubled: {}", apply_to_3(double));
}
<commit_msg>Implicit return<commit_after>// 将闭包作为参数并调用它的函数。
fn apply<F>(f: F) where
    // 闭包没有输入值和返回值。
    F: FnOnce() {
    // ^ 试一试：将 `FnOnce` 换成 `Fn` 或 `FnMut`。

    f();
}

// 使用闭包并返回一个 `i32` 整型的函数。
fn apply_to_3<F>(f: F) -> i32 where
// 闭包处理一个 `i32` 整型并返回一个 `i32` 整型。
    F: Fn(i32) -> i32 {

    f(3)
}

fn main() {
    use std::mem;

    let greeting = "hello";
    // 不可复制的类型。
    let mut farewell = "goodbye".to_owned();

    // 捕获 2 个变量：通过引用方式的 `greeting` 和
    // 通过值方式的 `farewell`。
    let diary = || {
        // `greeting` 使用引用方式：需要 `Fn`。
        println!("I said {}.", greeting);

        // 改变迫使 `farewell` 变成了通过可变引用来捕获。
        // （原文：Mutation forces `farewell` to be
        // captured by mutable reference.）
        // 现在需要 `FnMut`。
        farewell.push_str("!!!");
        println!("Then I screamed {}.", farewell);
        println!("Now I can sleep. zzzzz");

        // 手动调用 drop 将 `farewell` 强制转成通过值来捕获。
        // （原文：Manually calling drop forces `farewell` to
        // be captured by value. Now requires `FnOnce`.）
        // 现在需要 `FnOnce`。
        mem::drop(farewell);
    };

    // 调用处理闭包的函数（原文：Call the function
    // which applies the closure）。
    apply(diary);

    let double = |x| 2 * x;

    println!("3 doubled: {}", apply_to_3(double));
}
<|endoftext|>


<commit_before>use std::io;
use std::path::PathBuf;

/// Returns the .runfiles directory for the currently executing binary.
pub fn get_runfiles_dir() -> io::Result<PathBuf> {
    let mut path = std::env::current_exe()?;

    let mut name = path.file_name().unwrap().to_owned();
    name.push(".runfiles");

    path.pop();
    path.push(name);

    Ok(path)
}

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

    use std::io;
    use std::io::prelude::*;
    use std::fs::File;

    #[test]
    fn test_can_read_data_from_runfiles() {
        let runfiles = get_runfiles_dir().unwrap();

        let mut f = File::open(runfiles.join("examples/hello_runfiles/data/sample.txt")).unwrap();
        let mut buffer = String::new();

        f.read_to_string(&mut buffer).unwrap();

        assert_eq!("Example Text!", buffer);
    }
}
<commit_msg>Fix runfiles test: Macos runfiles are quite different (#66)<commit_after>use std::io;
use std::path::PathBuf;

/// Returns the .runfiles directory for the currently executing binary.
pub fn get_runfiles_dir() -> io::Result<PathBuf> {
    let mut path = std::env::current_exe()?;

    if cfg!(target_os = "macos") {
      path.pop();
    } else {
      let mut name = path.file_name().unwrap().to_owned();
      name.push(".runfiles");
      path.pop();
      path.push(name);
    }

    Ok(path)
}

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

    use std::io;
    use std::io::prelude::*;
    use std::fs::File;

    #[test]
    fn test_can_read_data_from_runfiles() {
        let runfiles = get_runfiles_dir().unwrap();

        let mut f = if cfg!(target_os = "macos") {
          File::open(runfiles.join("data/sample.txt")).unwrap()
        } else {
          File::open(runfiles.join("examples/hello_runfiles/data/sample.txt")).unwrap()
        };
        let mut buffer = String::new();

        f.read_to_string(&mut buffer).unwrap();

        assert_eq!("Example Text!", buffer);
    }
}
<|endoftext|>


<commit_before>use bytes::BytesMut;
use serde_1::{Deserialize, Serialize};
use serde_json_1::Value;
use std::error::Error;
use std::fmt::Debug;
use std::io::Read;

use crate::{FromSql, IsNull, ToSql, Type};

/// A wrapper type to allow arbitrary `Serialize`/`Deserialize` types to convert to Postgres JSON values.
#[derive(Debug)]
pub struct Json<T>(pub T);

impl<'a, T> FromSql<'a> for Json<T>
where
    T: Deserialize<'a>,
{
    fn from_sql(ty: &Type, mut raw: &'a [u8]) -> Result<Json<T>, Box<dyn Error + Sync + Send>> {
        if *ty == Type::JSONB {
            let mut b = [0; 1];
            raw.read_exact(&mut b)?;
            // We only support version 1 of the jsonb binary format
            if b[0] != 1 {
                return Err("unsupported JSONB encoding version".into());
            }
        }
        serde_json_1::de::from_slice(raw)
            .map(Json)
            .map_err(Into::into)
    }

    accepts!(JSON, JSONB);
}

impl<T> ToSql for Json<T>
where
    T: Serialize + Debug,
{
    fn to_sql(
        &self,
        ty: &Type,
        out: &mut BytesMut,
    ) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
        if *ty == Type::JSONB {
            out.push(1);
        }
        serde_json_1::ser::to_writer(out, &self.0)?;
        Ok(IsNull::No)
    }

    accepts!(JSON, JSONB);
    to_sql_checked!();
}

impl<'a> FromSql<'a> for Value {
    fn from_sql(ty: &Type, raw: &[u8]) -> Result<Value, Box<dyn Error + Sync + Send>> {
        Json::<Value>::from_sql(ty, raw).map(|json| json.0)
    }

    accepts!(JSON, JSONB);
}

impl ToSql for Value {
    fn to_sql(
        &self,
        ty: &Type,
        out: &mut BytesMut,
    ) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
        Json(self).to_sql(ty, out)
    }

    accepts!(JSON, JSONB);
    to_sql_checked!();
}
<commit_msg>Fix build for real<commit_after>use bytes::{BufMut, BytesMut};
use serde_1::{Deserialize, Serialize};
use serde_json_1::Value;
use std::error::Error;
use std::fmt::Debug;
use std::io::Read;

use crate::{FromSql, IsNull, ToSql, Type};

// https://github.com/tokio-rs/bytes/issues/170
struct B<'a>(&'a mut BytesMut);

impl<'a> BufMut for B<'a> {
    #[inline]
    fn remaining_mut(&self) -> usize {
        usize::max_value() - self.0.len()
    }

    #[inline]
    unsafe fn advance_mut(&mut self, cnt: usize) {
        self.0.advance_mut(cnt);
    }

    #[inline]
    unsafe fn bytes_mut(&mut self) -> &mut [u8] {
        if !self.0.has_remaining_mut() {
            self.0.reserve(64);
        }

        self.0.bytes_mut()
    }
}

/// A wrapper type to allow arbitrary `Serialize`/`Deserialize` types to convert to Postgres JSON values.
#[derive(Debug)]
pub struct Json<T>(pub T);

impl<'a, T> FromSql<'a> for Json<T>
where
    T: Deserialize<'a>,
{
    fn from_sql(ty: &Type, mut raw: &'a [u8]) -> Result<Json<T>, Box<dyn Error + Sync + Send>> {
        if *ty == Type::JSONB {
            let mut b = [0; 1];
            raw.read_exact(&mut b)?;
            // We only support version 1 of the jsonb binary format
            if b[0] != 1 {
                return Err("unsupported JSONB encoding version".into());
            }
        }
        serde_json_1::de::from_slice(raw)
            .map(Json)
            .map_err(Into::into)
    }

    accepts!(JSON, JSONB);
}

impl<T> ToSql for Json<T>
where
    T: Serialize + Debug,
{
    fn to_sql(
        &self,
        ty: &Type,
        out: &mut BytesMut,
    ) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
        if *ty == Type::JSONB {
            B(out).put_u8(1);
        }
        serde_json_1::ser::to_writer(B(out).writer(), &self.0)?;
        Ok(IsNull::No)
    }

    accepts!(JSON, JSONB);
    to_sql_checked!();
}

impl<'a> FromSql<'a> for Value {
    fn from_sql(ty: &Type, raw: &[u8]) -> Result<Value, Box<dyn Error + Sync + Send>> {
        Json::<Value>::from_sql(ty, raw).map(|json| json.0)
    }

    accepts!(JSON, JSONB);
}

impl ToSql for Value {
    fn to_sql(
        &self,
        ty: &Type,
        out: &mut BytesMut,
    ) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
        Json(self).to_sql(ty, out)
    }

    accepts!(JSON, JSONB);
    to_sql_checked!();
}
<|endoftext|>


<commit_before>extern crate rand;

use std::io;
use std::process;
use std::cmp::Ordering;
use rand::Rng;

#[derive(Debug)]
pub struct Guess {
    value: u32,
}

impl Guess {
    pub fn new(value: u32) -> Guess {
        if value < 1 || value > 100 {
            panic!("Guess value must be between 1 and 100, got {}.", value);
        }
        Guess { value }
    }

    // Getter
    pub fn value(&self) -> u32 {
        self.value
    }

    pub fn comparison(&self, secret_number: &u32) -> i32 {
        match self.value.cmp(secret_number) {
            Ordering::Less => {
                println!("Too small!");
                return -1;
            },
            Ordering::Greater => {
                println!("Too big!");
                return 1;
            },
            Ordering::Equal => {
                println!("You win!");
                return 0;
            }
        }
    }
}

fn sample(guess: &str) -> String {
    return guess.to_string();
}

fn main() {
    let secret_number = rand::thread_rng().gen_range(1, 101);

    println!("The secret number is: {}", secret_number);

    loop {
        println!("Input your guess.");

        let mut guess = String::new();

        io::stdin()
            .read_line(&mut guess)
            .expect("Failed to read line");

        guess = sample(&guess);

        // Allow potentially negative numbers
        let guess: Guess = match guess.trim().parse() {
            Ok(num) => Guess::new(num),
            Err(_) => continue,
        };

        println!("You guessed: {:?}", guess);

        let result = guess.comparison(&secret_number);
        if result == 0 { process::exit(1); }
    }
}

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

    #[test]
    fn test_sample() {
        let actual_guess: &str = "1";
        let expected_response: String = "1".to_string();
        assert_eq!(sample(&actual_guess), expected_response);
    }

    #[test]
    fn test_guess() {
        let actual_guess_number: u32 = 99;
        let actual_guess_instance: Guess = Guess::new(actual_guess_number);
        let expected_guess_instance_value: u32 = actual_guess_instance.value();
        assert_eq!(99, expected_guess_instance_value);
    }

    #[test]
    fn test_comparison() {
        let actual_guess_number: u32 = 50;
        let actual_guess_instance: Guess = Guess::new(actual_guess_number);
        let actual_secret_number: u32 = 50;
        let actual_comparison_result: i32 = actual_guess_instance.comparison(&actual_secret_number);
        let expected_comparison_result: i32 = 0;
        assert_eq!(actual_comparison_result, expected_comparison_result);
    }
}<commit_msg>fix: Fix so Custom Type for Validation called for negative guess value and panics<commit_after>extern crate rand;

use std::io;
use std::process;
use std::cmp::Ordering;
use rand::Rng;

#[derive(Debug)]
pub struct Guess {
    value: i32,
}

impl Guess {
    pub fn new(value: i32) -> Guess {
        if value < 1 || value > 100 {
            panic!("Guess value must be between 1 and 100, got {}.", value);
        }
        Guess { value }
    }

    // Getter
    pub fn value(&self) -> i32 {
        self.value
    }

    pub fn comparison(&self, secret_number: &i32) -> i32 {
        match self.value.cmp(secret_number) {
            Ordering::Less => {
                println!("Too small!");
                return -1;
            },
            Ordering::Greater => {
                println!("Too big!");
                return 1;
            },
            Ordering::Equal => {
                println!("You win!");
                return 0;
            }
        }
    }
}

fn sample(guess: &str) -> String {
    return guess.to_string();
}

fn main() {
    let secret_number = rand::thread_rng().gen_range(1, 101);

    println!("The secret number is: {}", secret_number);

    loop {
        println!("Input your guess.");

        let mut guess = String::new();

        io::stdin()
            .read_line(&mut guess)
            .expect("Failed to read line");

        guess = sample(&guess);

        // Allow potentially negative numbers
        let guess: Guess = match guess.trim().parse() {
            Ok(num) => Guess::new(num),
            Err(_) => continue,
        };

        println!("You guessed: {:?}", guess);

        let result = guess.comparison(&secret_number);
        if result == 0 { process::exit(1); }
    }
}

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

    #[test]
    fn test_sample() {
        let actual_guess: &str = "1";
        let expected_response: String = "1".to_string();
        assert_eq!(sample(&actual_guess), expected_response);
    }

    #[test]
    fn test_guess() {
        let actual_guess_number: i32 = 99;
        let actual_guess_instance: Guess = Guess::new(actual_guess_number);
        let expected_guess_instance_value: i32 = actual_guess_instance.value();
        assert_eq!(99, expected_guess_instance_value);
    }

    #[test]
    fn test_comparison() {
        let actual_guess_number: i32 = 50;
        let actual_guess_instance: Guess = Guess::new(actual_guess_number);
        let actual_secret_number: i32 = 50;
        let actual_comparison_result: i32 = actual_guess_instance.comparison(&actual_secret_number);
        let expected_comparison_result: i32 = 0;
        assert_eq!(actual_comparison_result, expected_comparison_result);
    }
}<|endoftext|>


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

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

/// Program to display a 3x3 cube solution.
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
   /// Solve the planes problem.
   #[arg(short, long)]
   planes: bool,
}

fn main() {
    env_logger::init();
    let args = Args::parse();

    let mut window = Window::new("Kiss3d: cube");
    window.set_light(Light::StickToCamera);

    let mut cubes = Vec::new();
    let rot1 = UnitQuaternion::from_axis_angle(&Vector3::x_axis(), -0.5);
    for i in 0..27 {
        let c = window.add_cube(0.08, 0.08, 0.08);
        cubes.push(c);

        cubes[i].append_rotation(&rot1);

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

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

    let rot = UnitQuaternion::from_axis_angle(&Vector3::y_axis(), 0.014);
    while window.render() {
        for i in 0..27 {
            cubes[i].append_rotation(&rot);
        }
    }
}<commit_msg>Add minotaur.<commit_after>extern crate clap;
extern crate kiss3d;
extern crate nalgebra as na;

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

/// Program to display a 3x3 cube solution.
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
   /// Solve the minotaur problem.
   #[arg(short, long)]
   minotaur: bool,

   /// Solve the planes problem.
   #[arg(short, long)]
   planes: bool,
}

fn main() {
    env_logger::init();
    let args = Args::parse();

    let mut window = Window::new("Kiss3d: cube");
    window.set_light(Light::StickToCamera);

    let mut cubes = Vec::new();
    //let rot1 = UnitQuaternion::from_axis_angle(&Vector3::x_axis(), -0.5);
    for i in 0..27 {
        let c = window.add_cube(0.08, 0.08, 0.08);
        cubes.push(c);

        //cubes[i].append_rotation(&rot1);

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

    if args.minotaur {
        cubes[0].set_color(1.0, 0.0, 0.0);
        cubes[1].set_color(1.0, 0.0, 0.0);
        cubes[2].set_color(1.0, 0.0, 0.0);

        cubes[3].set_color(1.0, 0.0, 0.0);
        cubes[4].set_color(0.0, 1.0, 0.0);
        cubes[5].set_color(0.0, 0.0, 1.0);

        cubes[6].set_color(0.0, 1.0, 0.0);
        cubes[7].set_color(0.0, 1.0, 0.0);
        cubes[8].set_color(0.0, 0.0, 1.0);

        cubes[9].set_color(1.0, 1.0, 0.0);
        cubes[10].set_color(1.0, 0.0, 0.0);
        cubes[11].set_color(0.0, 1.0, 1.0);

        cubes[12].set_color(1.0, 1.0, 0.0);
        cubes[13].set_color(1.0, 1.0, 0.0);
        cubes[14].set_color(0.0, 1.0, 1.0);

        cubes[15].set_color(0.0, 1.0, 0.0);
        cubes[16].set_color(0.0, 0.0, 1.0);
        cubes[17].set_color(0.0, 0.0, 1.0);

        cubes[18].set_color(1.0, 0.0, 1.0);
        cubes[19].set_color(1.0, 0.0, 1.0);
        cubes[20].set_color(1.0, 0.0, 1.0);

        cubes[21].set_color(1.0, 1.0, 0.0);
        cubes[22].set_color(1.0, 0.0, 1.0);
        cubes[23].set_color(0.0, 1.0, 1.0);

        cubes[24].set_color(1.0, 1.0, 0.0);
        cubes[25].set_color(0.0, 1.0, 1.0);
        cubes[26].set_color(0.0, 1.0, 1.0);
    }

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

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


<commit_before>#![feature(rust_2018_preview)]
#![warn(rust_2018_idioms)]

use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::HashMap;
use std::env;
use std::time::Duration;

use ggez::conf;
use ggez::event;
use ggez::graphics;
use ggez::graphics::spritebatch::SpriteBatch;
use ggez::graphics::Color;
use ggez::timer;
use ggez::{Context, GameResult};
use image::{ImageBuffer, RgbaImage};
use specs::world::Builder;
use specs::{Join, RunNow, World};
use warmy::{LogicalKey, Store, StoreOpt};

use openmoonstone::animation::{Image, Sprite};
use openmoonstone::combat::components::{Draw, Position};
use openmoonstone::combat::systems::{Movement, Renderer};
use openmoonstone::objects::{Rect, TextureAtlas};
use openmoonstone::piv::{Colour, PivImage};

struct MainState {
    palette: Vec<Colour>,
    image: graphics::Image,
    batch: graphics::spritebatch::SpriteBatch,
    rects: Vec<Rect>,
    encounter: World,
    systems: Systems,
    store: Store<Context>,
    images: HashMap<String, graphics::Image>,
}

struct Systems {
    movement: Movement,
    //renderer: Renderer,
}

impl MainState {
    fn new_batch(
        atlas: &warmy::res::Res<TextureAtlas>,
        ctx: &mut Context,
        palette: &Vec<Colour>,
    ) -> SpriteBatch {
        let atlas_dimension = atlas.borrow().image.width as u32;
        // todo: do not do this every draw frame
        let image = graphics::Image::from_rgba8(
            ctx,
            atlas_dimension as u16,
            atlas_dimension as u16,
            &atlas.borrow().image.to_rgba8(palette),
        ).unwrap();
        SpriteBatch::new(image)
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, ctx: &mut Context) -> GameResult<()> {
        const DESIRED_FPS: u32 = 1000 / (1193182 / 21845 * 2);
        while timer::check_update_time(ctx, DESIRED_FPS) {
            self.systems.movement.run_now(&self.encounter.res)
            // println!("Delta frame time: {:?} ", timer::get_delta(ctx));
            // println!("Average FPS: {}", timer::get_fps(ctx));
        }
        timer::sleep(Duration::from_millis(109));
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
        graphics::set_background_color(ctx, Color::from((0, 0, 0, 255)));
        graphics::clear(ctx);

        let dest_point = graphics::Point2::new(0.0, 0.0);
        graphics::draw_ex(
            ctx,
            &self.image,
            graphics::DrawParam {
                dest: dest_point,
                scale: graphics::Point2::new(3.0, 3.0),
                ..Default::default()
            },
        )?;
        //self.systems.renderer.run_now(&self.encounter.res, ctx: Context);
        let mut batches: HashMap<String, graphics::spritebatch::SpriteBatch> = HashMap::new();
        let mut batch_order: Vec<String> = vec![];
        let position_storage = self.encounter.read_storage::<Position>();
        let draw_storage = self.encounter.read_storage::<Draw>();
        for (position, draw) in (&position_storage, &draw_storage).join() {
            for image in &draw.frame.images {
                let atlas = self
                    .store
                    .get::<_, TextureAtlas>(&LogicalKey::new(image.sheet.as_str()), ctx)
                    .unwrap();
                let mut batch = match batches.entry(image.sheet.clone()) {
                    Occupied(entry) => entry.into_mut(),
                    Vacant(entry) => {
                        batch_order.push(image.sheet.clone());
                        let atlas_dimension = atlas.borrow().image.width as u32;
                        let image = match(self.images.entry(image.sheet.clone())) {
                            Occupied(i) => i.into_mut(),
                            Vacant(i) => {
                                i.insert(graphics::Image::from_rgba8(
                                    ctx,
                                    atlas_dimension as u16,
                                    atlas_dimension as u16,
                                    &atlas.borrow().image.to_rgba8(&self.palette),
                                ).unwrap())
                            }
                        };
                        entry.insert(SpriteBatch::new(image.clone()))
                    }
                };

                let rect = atlas.borrow().rects[image.image];
                let texture_size = atlas.borrow().image.width as f32;
                batch.add(graphics::DrawParam {
                    src: graphics::Rect {
                        x: rect.x as f32 / texture_size,
                        y: rect.y as f32 / texture_size,
                        w: rect.w as f32 / texture_size,
                        h: rect.h as f32 / texture_size,
                    },
                    dest: graphics::Point2::new(
                        (position.x as i32 + image.x) as f32,
                        (position.y as i32 + image.y) as f32,
                    ),
                    //scale: graphics::Point2::new(3.0, 3.0),
                    ..Default::default()
                });
            }
        }
        for batch_name in batch_order {
            let mut batch = batches.get_mut(&batch_name).unwrap();
            graphics::draw_ex(
                ctx,
                batch,
                graphics::DrawParam {
                    dest: dest_point,
                    scale: graphics::Point2::new(3.0, 3.0),
                    ..Default::default()
                },
            )?;
            batch.clear();
        }

        //let banner = &self.rects[73];
        //self.batch.add(graphics::DrawParam {
        //    src: graphics::Rect {
        //        x: banner.x as f32 / 512.0,
        //        y: banner.y as f32 / 512.0,
        //        w: banner.w as f32 / 512.0,
        //        h: banner.h as f32 / 512.0,
        //    },
        //    dest: graphics::Point2::new(5.0, 20.0),
        //    //scale: graphics::Point2::new(3.0, 3.0),
        //    ..Default::default()
        //});

        //let copyright = &self.rects[74];
        //self.batch.add(graphics::DrawParam {
        //    src: graphics::Rect {
        //        x: copyright.x as f32 / 512.0,
        //        y: copyright.y as f32 / 512.0,
        //        w: copyright.w as f32 / 512.0,
        //        h: copyright.h as f32 / 512.0,
        //    },
        //    dest: graphics::Point2::new(22.0, 181.0),
        //    //scale: graphics::Point2::new(3.0, 3.0),
        //    ..Default::default()
        //});

        //let rights = &self.rects[75];
        //self.batch.add(graphics::DrawParam {
        //    src: graphics::Rect {
        //        x: rights.x as f32 / 512.0,
        //        y: rights.y as f32 / 512.0,
        //        w: rights.w as f32 / 512.0,
        //        h: rights.h as f32 / 512.0,
        //    },
        //    dest: graphics::Point2::new(110.0, 190.0),
        //    //scale: graphics::Point2::new(3.0, 3.0),
        //    ..Default::default()
        //});
        //graphics::draw_ex(
        //    ctx,
        //    &self.batch,
        //    graphics::DrawParam {
        //        dest: dest_point,
        //        scale: graphics::Point2::new(3.0, 3.0),
        //        ..Default::default()
        //    },
        //)?;
        //self.batch.clear();
        graphics::present(ctx);

        timer::yield_now();
        Ok(())
    }
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let filename = &args[1];
    let ob = &args[2];

    let c = conf::Conf::new();
    let ctx = &mut Context::load_from_conf("openmoonstone", "joetsoi", c).unwrap();
    graphics::set_default_filter(ctx, graphics::FilterMode::Nearest);

    let mut store: Store<Context> = Store::new(StoreOpt::default()).expect("store creation");
    let piv = store
        .get::<_, PivImage>(&LogicalKey::new(filename), ctx)
        .unwrap();

    let atlas = store
        .get::<_, TextureAtlas>(&LogicalKey::new(ob), ctx)
        .unwrap();

    let sprite = store
        .get::<_, Sprite>(&LogicalKey::new("/knight.yaml"), ctx)
        .unwrap();

    let atlas_dimension = atlas.borrow().image.width as u32;
    // let mut a: RgbaImage = ImageBuffer::from_raw(
    //     atlas_dimension,
    //     atlas_dimension,
    //     atlas.borrow().image.to_rgba8(&*piv.borrow().palette),
    // ).unwrap();
    // a.save("test.png");

    let background = graphics::Image::from_rgba8(ctx, 320, 200, &*piv.borrow().to_rgba8()).unwrap();
    let image = graphics::Image::from_rgba8(
        ctx,
        atlas_dimension as u16,
        atlas_dimension as u16,
        &atlas.borrow().image.to_rgba8(&*piv.borrow().palette),
    ).unwrap();
    //let test = image.clone();
    let batch = graphics::spritebatch::SpriteBatch::new(image);

    // let im1 = &ob.images[0];
    // let test = Image::from_rgba8(
    //     ctx,
    //     im1.width as u16,
    //     im1.height as u16,
    //     &im1.to_rgba8(&piv.palette),
    // ).unwrap();

    let mut encounter = World::new();
    encounter.register::<Position>();
    encounter.register::<Draw>();
    let knight = encounter
        .create_entity()
        .with(Position { x: 0, y: 200 })
        .with(Draw {
            frame: sprite.borrow().animations["idle"][0].clone(),
        })
        .build();
    let movement = Movement;
    //let renderer = Renderer { ctx: ctx };
    let systems = Systems {
        movement: movement,
        //renderer: renderer,
    };

    let mut state = MainState {
        palette: piv.borrow().palette.to_vec(),
        image: background,
        batch: batch,
        rects: atlas.borrow().rects.clone(),
        encounter: encounter,
        systems: systems,
        store: store,
        images: HashMap::new(),
    };

    event::run(ctx, &mut state).unwrap();
}
<commit_msg>Rust: keep batches in world state.<commit_after>#![feature(rust_2018_preview)]
#![warn(rust_2018_idioms)]

use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::HashMap;
use std::env;
use std::time::Duration;

use ggez::conf;
use ggez::event;
use ggez::graphics;
use ggez::graphics::spritebatch::SpriteBatch;
use ggez::graphics::Color;
use ggez::timer;
use ggez::{Context, GameResult};
use image::{ImageBuffer, RgbaImage};
use specs::world::Builder;
use specs::{Join, RunNow, World};
use warmy::{LogicalKey, Store, StoreOpt};

use openmoonstone::animation::{Image, Sprite};
use openmoonstone::combat::components::{Draw, Position};
use openmoonstone::combat::systems::{Movement, Renderer};
use openmoonstone::objects::{Rect, TextureAtlas};
use openmoonstone::piv::{Colour, PivImage};

struct MainState {
    palette: Vec<Colour>,
    image: graphics::Image,
    batch: graphics::spritebatch::SpriteBatch,
    rects: Vec<Rect>,
    encounter: World,
    systems: Systems,
    store: Store<Context>,

    images: HashMap<String, graphics::Image>,
    batches: HashMap<String, graphics::spritebatch::SpriteBatch>,
    batch_order: Vec<String>,
}

struct Systems {
    movement: Movement,
    //renderer: Renderer,
}

impl event::EventHandler for MainState {
    fn update(&mut self, ctx: &mut Context) -> GameResult<()> {
        const DESIRED_FPS: u32 = 1000 / (1193182 / 21845 * 2);
        while timer::check_update_time(ctx, DESIRED_FPS) {
            self.systems.movement.run_now(&self.encounter.res)
            // println!("Delta frame time: {:?} ", timer::get_delta(ctx));
            // println!("Average FPS: {}", timer::get_fps(ctx));
        }
        timer::sleep(Duration::from_millis(109));
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
        graphics::set_background_color(ctx, Color::from((0, 0, 0, 255)));
        graphics::clear(ctx);

        let dest_point = graphics::Point2::new(0.0, 0.0);
        graphics::draw_ex(
            ctx,
            &self.image,
            graphics::DrawParam {
                dest: dest_point,
                scale: graphics::Point2::new(3.0, 3.0),
                ..Default::default()
            },
        )?;
        //self.systems.renderer.run_now(&self.encounter.res, ctx: Context);
        //let mut batches: HashMap<String, graphics::spritebatch::SpriteBatch> = HashMap::new();
        //let mut batch_order: Vec<String> = vec![];
        let position_storage = self.encounter.read_storage::<Position>();
        let draw_storage = self.encounter.read_storage::<Draw>();
        for (position, draw) in (&position_storage, &draw_storage).join() {
            for image in &draw.frame.images {
                let atlas = self
                    .store
                    .get::<_, TextureAtlas>(&LogicalKey::new(image.sheet.as_str()), ctx)
                    .unwrap();
                let mut batch = match self.batches.entry(image.sheet.clone()) {
                    Occupied(entry) => entry.into_mut(),
                    Vacant(entry) => {
                        self.batch_order.push(image.sheet.clone());
                        let atlas_dimension = atlas.borrow().image.width as u32;
                        let image = match (self.images.entry(image.sheet.clone())) {
                            Occupied(i) => i.into_mut(),
                            Vacant(i) => i.insert(
                                graphics::Image::from_rgba8(
                                    ctx,
                                    atlas_dimension as u16,
                                    atlas_dimension as u16,
                                    &atlas.borrow().image.to_rgba8(&self.palette),
                                ).unwrap(),
                            ),
                        };
                        entry.insert(SpriteBatch::new(image.clone()))
                    }
                };

                let rect = atlas.borrow().rects[image.image];
                let texture_size = atlas.borrow().image.width as f32;
                batch.add(graphics::DrawParam {
                    src: graphics::Rect {
                        x: rect.x as f32 / texture_size,
                        y: rect.y as f32 / texture_size,
                        w: rect.w as f32 / texture_size,
                        h: rect.h as f32 / texture_size,
                    },
                    dest: graphics::Point2::new(
                        (position.x as i32 + image.x) as f32,
                        (position.y as i32 + image.y) as f32,
                    ),
                    //scale: graphics::Point2::new(3.0, 3.0),
                    ..Default::default()
                });
            }
        }
        for batch_name in &self.batch_order {
            let mut batch = self.batches.get_mut(batch_name).unwrap();
            graphics::draw_ex(
                ctx,
                batch,
                graphics::DrawParam {
                    dest: dest_point,
                    scale: graphics::Point2::new(3.0, 3.0),
                    ..Default::default()
                },
            )?;
            batch.clear();
        }

        //let banner = &self.rects[73];
        //self.batch.add(graphics::DrawParam {
        //    src: graphics::Rect {
        //        x: banner.x as f32 / 512.0,
        //        y: banner.y as f32 / 512.0,
        //        w: banner.w as f32 / 512.0,
        //        h: banner.h as f32 / 512.0,
        //    },
        //    dest: graphics::Point2::new(5.0, 20.0),
        //    //scale: graphics::Point2::new(3.0, 3.0),
        //    ..Default::default()
        //});

        //let copyright = &self.rects[74];
        //self.batch.add(graphics::DrawParam {
        //    src: graphics::Rect {
        //        x: copyright.x as f32 / 512.0,
        //        y: copyright.y as f32 / 512.0,
        //        w: copyright.w as f32 / 512.0,
        //        h: copyright.h as f32 / 512.0,
        //    },
        //    dest: graphics::Point2::new(22.0, 181.0),
        //    //scale: graphics::Point2::new(3.0, 3.0),
        //    ..Default::default()
        //});

        //let rights = &self.rects[75];
        //self.batch.add(graphics::DrawParam {
        //    src: graphics::Rect {
        //        x: rights.x as f32 / 512.0,
        //        y: rights.y as f32 / 512.0,
        //        w: rights.w as f32 / 512.0,
        //        h: rights.h as f32 / 512.0,
        //    },
        //    dest: graphics::Point2::new(110.0, 190.0),
        //    //scale: graphics::Point2::new(3.0, 3.0),
        //    ..Default::default()
        //});
        //graphics::draw_ex(
        //    ctx,
        //    &self.batch,
        //    graphics::DrawParam {
        //        dest: dest_point,
        //        scale: graphics::Point2::new(3.0, 3.0),
        //        ..Default::default()
        //    },
        //)?;
        //self.batch.clear();
        graphics::present(ctx);

        timer::yield_now();
        Ok(())
    }
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let filename = &args[1];
    let ob = &args[2];

    let c = conf::Conf::new();
    let ctx = &mut Context::load_from_conf("openmoonstone", "joetsoi", c).unwrap();
    graphics::set_default_filter(ctx, graphics::FilterMode::Nearest);

    let mut store: Store<Context> = Store::new(StoreOpt::default()).expect("store creation");
    let piv = store
        .get::<_, PivImage>(&LogicalKey::new(filename), ctx)
        .unwrap();

    let atlas = store
        .get::<_, TextureAtlas>(&LogicalKey::new(ob), ctx)
        .unwrap();

    let sprite = store
        .get::<_, Sprite>(&LogicalKey::new("/knight.yaml"), ctx)
        .unwrap();

    let atlas_dimension = atlas.borrow().image.width as u32;
    // let mut a: RgbaImage = ImageBuffer::from_raw(
    //     atlas_dimension,
    //     atlas_dimension,
    //     atlas.borrow().image.to_rgba8(&*piv.borrow().palette),
    // ).unwrap();
    // a.save("test.png");

    let background = graphics::Image::from_rgba8(ctx, 320, 200, &*piv.borrow().to_rgba8()).unwrap();
    let image = graphics::Image::from_rgba8(
        ctx,
        atlas_dimension as u16,
        atlas_dimension as u16,
        &atlas.borrow().image.to_rgba8(&*piv.borrow().palette),
    ).unwrap();
    //let test = image.clone();
    let batch = graphics::spritebatch::SpriteBatch::new(image);

    // let im1 = &ob.images[0];
    // let test = Image::from_rgba8(
    //     ctx,
    //     im1.width as u16,
    //     im1.height as u16,
    //     &im1.to_rgba8(&piv.palette),
    // ).unwrap();

    let mut encounter = World::new();
    encounter.register::<Position>();
    encounter.register::<Draw>();
    let knight = encounter
        .create_entity()
        .with(Position { x: 0, y: 200 })
        .with(Draw {
            frame: sprite.borrow().animations["idle"][0].clone(),
        })
        .build();
    let movement = Movement;
    //let renderer = Renderer { ctx: ctx };
    let systems = Systems {
        movement: movement,
        //renderer: renderer,
    };

    let mut state = MainState {
        palette: piv.borrow().palette.to_vec(),
        image: background,
        batch: batch,
        rects: atlas.borrow().rects.clone(),
        encounter: encounter,
        systems: systems,
        store: store,
        images: HashMap::new(),
        batches: HashMap::new(),
        batch_order: vec![],
    };

    event::run(ctx, &mut state).unwrap();
}
<|endoftext|>


<commit_before>use std::process::Command;
// files in tests/ directory are integration tests
#[test]
// add test to verify we cannot generate a password < 30 characters
fn validate_password_length() {
    let output = Command::new("cargo")
        .args(&["run", "--release", "--quiet", "0"])
        .output()
        .expect("could not run cargo");
    let output = String::from_utf8_lossy(&output.stderr);
    assert_eq!("Please provide a password length greater than or equal to 30", output.trim());
}
<commit_msg>fix rustfmt error<commit_after>use std::process::Command;
// files in tests/ directory are integration tests
#[test]
// add test to verify we cannot generate a password < 30 characters
fn validate_password_length() {
    let output = Command::new("cargo")
        .args(&["run", "--release", "--quiet", "0"])
        .output()
        .expect("could not run cargo");
    let output = String::from_utf8_lossy(&output.stderr);
    assert_eq!(
        "Please provide a password length greater than or equal to 30",
        output.trim()
    );
}
<|endoftext|>


<commit_before>//
// rslex - a lexer generator for rust
//
// parser.rs
// Input file parsing
//
// Andrei de A. Formiga, 2013-08-04
//

extern mod std;

// --- utility functions -------------------------------------------

#[inline]
fn is_eof(c: char) -> bool {
    c == (-1 as char)
}

// --- the lookahead buffer ----------------------------------------
struct LookaheadBuffer {
    c: char,
    valid: bool,
    reader: @Reader
}

impl LookaheadBuffer {
    fn new(r: @Reader) -> LookaheadBuffer {
        LookaheadBuffer { c: ' ', valid: false, reader: r}
    }

    // FIX: should be read_char but doesn't work due to method resolution bug in rustc
    fn next_char(&mut self) -> char {
        if self.valid {
            self.valid = false;
            self.c
        }
        else {
            self.reader.read_char()
        }
    }

    fn return_char(&mut self, c: char) {
        // assumes at most one char of lookahead
        assert!(self.valid == false);
        self.c = c;
        self.valid = true;
    }
}

#[cfg(test)]
mod buffer_tests {
    use super::*;
    use std::io::with_str_reader;

    #[test]
    fn no_buffer_use() {
        let mut buffer = with_str_reader("abcdef", LookaheadBuffer::new);
        assert!(!buffer.valid);
        assert!(buffer.next_char() == 'a');
        assert!(buffer.next_char() == 'b');
        assert!(buffer.next_char() == 'c');
        assert!(!buffer.valid);
    }

    #[test]
    fn buffer_use() {
        let mut buffer = with_str_reader("abcdef", LookaheadBuffer::new);
        assert!(!buffer.valid);
        assert!(buffer.next_char() == 'a');
        buffer.return_char('a');
        assert!(buffer.valid);
        assert!(buffer.next_char() == 'a');
        assert!(!buffer.valid);
        assert!(buffer.next_char() == 'b');
        assert!(buffer.next_char() == 'c');
    }

    #[test]
    fn return_other_char() {
        let mut buffer = with_str_reader("abcdef", LookaheadBuffer::new);
        assert!(!buffer.valid);
        assert!(buffer.next_char() == 'a');
        buffer.return_char('x');
        assert!(buffer.valid);
        assert!(buffer.next_char() == 'x');
        assert!(!buffer.valid);
        assert!(buffer.next_char() == 'b');
        assert!(buffer.next_char() == 'c');
        assert!(!buffer.valid);
        buffer.return_char('c');
        assert!(buffer.valid);
        assert!(buffer.next_char() == 'c');
        assert!(!buffer.valid);
        assert!(buffer.next_char() == 'd');
        assert!(buffer.next_char() == 'e');
    }

    #[test]
    #[should_fail]
    fn return_other_char_expect_same() {
        let mut buffer = with_str_reader("abcdef", LookaheadBuffer::new);
        assert!(!buffer.valid);
        assert!(buffer.next_char() == 'a');
        buffer.return_char('x');
        assert!(buffer.valid);
        assert!(buffer.next_char() == 'a');
    }

    #[test]
    fn read_until_eof() {
        let mut buffer = with_str_reader("abc", LookaheadBuffer::new);
        assert!(buffer.next_char() == 'a');
        assert!(buffer.next_char() == 'b');
        assert!(buffer.next_char() == 'c');
        assert!(buffer.next_char() == -1 as char);
    }

    #[test]
    fn return_char_eof() {
        let mut buffer = with_str_reader("abc", LookaheadBuffer::new);
        assert!(buffer.next_char() == 'a');
        assert!(buffer.next_char() == 'b');
        assert!(buffer.next_char() == 'c');
        assert!(buffer.next_char() == -1 as char);
        buffer.return_char(-1 as char);
        assert!(buffer.valid);
        assert!(buffer.next_char() == -1 as char);
    }
}

fn skip_whitespace(buffer: &mut LookaheadBuffer) {
    let mut c = buffer.next_char();
    while (!is_eof(c) && std::char::is_whitespace(c)) {
        c = buffer.next_char();
    }
    buffer.return_char(c);
}

#[test]
fn test_skip_ws() {
    let mut buffer = std::io::with_str_reader("   abc   ", LookaheadBuffer::new);
    skip_whitespace(&mut buffer);
    assert!(buffer.next_char() == 'a');
    skip_whitespace(&mut buffer);
    assert!(buffer.next_char() == 'b');
    skip_whitespace(&mut buffer);
    assert!(buffer.next_char() == 'c');
    skip_whitespace(&mut buffer);
    assert!(is_eof(buffer.next_char()));
}

// token types
enum Token { LBrace, RBrace, Equals, Comma, Semicolon,
             LParen, RParen, Star, Plus, Bar,
             DefsId, RulesId, CodeId, Id(~str), RegExp, Eof }

enum Block { Rules, Defs, Code }

// fn match_next_token() -> bool {
// }

fn get_next_token(buffer: &mut LookaheadBuffer) -> ~Token {
    let mut c = buffer.next_char();
    let mut done = false;
    let mut res = ~Eof;
    while !done {
        skip_whitespace(buffer);
        if is_eof(c) {
            done = true;
        }
        else {
            match c {
                '{' => { res = ~LBrace; done = true; },
                _   => { done = true; }   // FIX
            }
        }
    }
    res
}

fn read_string(buffer: &mut LookaheadBuffer, first: char) -> ~str {
    let mut res : ~str = ~"";
    let mut c = buffer.next_char();
    res.push_char(first);
    while !is_eof(c) && !std::char::is_whitespace(c) {
        res.push_char(c);
        c = buffer.next_char();
    }
    buffer.return_char(c);
    res
}

#[test]
fn test_read_string() {
    let mut buffer = std::io::with_str_reader("hombas   ", LookaheadBuffer::new);
    assert!(std::str::eq(&read_string(&mut buffer, 's'), &~"shombas"));

    let mut buffer2 = std::io::with_str_reader(" or die ", LookaheadBuffer::new);
    assert!(std::str::eq(&read_string(&mut buffer2, 'b'), &~"b"));
}

fn parse_toplevel_block(buffer: &mut LookaheadBuffer) {
}

// fn parse_regexp() {
// }

pub fn parse_lexer_spec(reader: @Reader) {
    let mut buffer = LookaheadBuffer::new(reader);
    parse_toplevel_block(&mut buffer);
}

<commit_msg>More parsing functions<commit_after>//
// rslex - a lexer generator for rust
//
// parser.rs
// Input file parsing
//
// Andrei de A. Formiga, 2013-08-04
//

extern mod std;

// --- utility functions -------------------------------------------

#[inline]
fn is_eof(c: char) -> bool {
    c == (-1 as char)
}

// --- the lookahead buffer ----------------------------------------
struct LookaheadBuffer {
    c: char,
    valid: bool,
    reader: @Reader
}

impl LookaheadBuffer {
    fn new(r: @Reader) -> LookaheadBuffer {
        LookaheadBuffer { c: ' ', valid: false, reader: r}
    }

    // FIX: should be read_char but doesn't work due to method resolution bug in rustc
    fn next_char(&mut self) -> char {
        if self.valid {
            self.valid = false;
            self.c
        }
        else {
            self.reader.read_char()
        }
    }

    fn return_char(&mut self, c: char) {
        // assumes at most one char of lookahead
        assert!(self.valid == false);
        self.c = c;
        self.valid = true;
    }
}

#[cfg(test)]
mod buffer_tests {
    use super::*;
    use std::io::with_str_reader;

    #[test]
    fn no_buffer_use() {
        let mut buffer = with_str_reader("abcdef", LookaheadBuffer::new);
        assert!(!buffer.valid);
        assert!(buffer.next_char() == 'a');
        assert!(buffer.next_char() == 'b');
        assert!(buffer.next_char() == 'c');
        assert!(!buffer.valid);
    }

    #[test]
    fn buffer_use() {
        let mut buffer = with_str_reader("abcdef", LookaheadBuffer::new);
        assert!(!buffer.valid);
        assert!(buffer.next_char() == 'a');
        buffer.return_char('a');
        assert!(buffer.valid);
        assert!(buffer.next_char() == 'a');
        assert!(!buffer.valid);
        assert!(buffer.next_char() == 'b');
        assert!(buffer.next_char() == 'c');
    }

    #[test]
    fn return_other_char() {
        let mut buffer = with_str_reader("abcdef", LookaheadBuffer::new);
        assert!(!buffer.valid);
        assert!(buffer.next_char() == 'a');
        buffer.return_char('x');
        assert!(buffer.valid);
        assert!(buffer.next_char() == 'x');
        assert!(!buffer.valid);
        assert!(buffer.next_char() == 'b');
        assert!(buffer.next_char() == 'c');
        assert!(!buffer.valid);
        buffer.return_char('c');
        assert!(buffer.valid);
        assert!(buffer.next_char() == 'c');
        assert!(!buffer.valid);
        assert!(buffer.next_char() == 'd');
        assert!(buffer.next_char() == 'e');
    }

    #[test]
    #[should_fail]
    fn return_other_char_expect_same() {
        let mut buffer = with_str_reader("abcdef", LookaheadBuffer::new);
        assert!(!buffer.valid);
        assert!(buffer.next_char() == 'a');
        buffer.return_char('x');
        assert!(buffer.valid);
        assert!(buffer.next_char() == 'a');
    }

    #[test]
    fn read_until_eof() {
        let mut buffer = with_str_reader("abc", LookaheadBuffer::new);
        assert!(buffer.next_char() == 'a');
        assert!(buffer.next_char() == 'b');
        assert!(buffer.next_char() == 'c');
        assert!(buffer.next_char() == -1 as char);
    }

    #[test]
    fn return_char_eof() {
        let mut buffer = with_str_reader("abc", LookaheadBuffer::new);
        assert!(buffer.next_char() == 'a');
        assert!(buffer.next_char() == 'b');
        assert!(buffer.next_char() == 'c');
        assert!(buffer.next_char() == -1 as char);
        buffer.return_char(-1 as char);
        assert!(buffer.valid);
        assert!(buffer.next_char() == -1 as char);
    }
}

fn skip_whitespace(buffer: &mut LookaheadBuffer) {
    let mut c = buffer.next_char();
    while (!is_eof(c) && std::char::is_whitespace(c)) {
        c = buffer.next_char();
    }
    buffer.return_char(c);
}

#[test]
fn test_skip_ws() {
    let mut buffer = std::io::with_str_reader("   abc   ", LookaheadBuffer::new);
    skip_whitespace(&mut buffer);
    assert!(buffer.next_char() == 'a');
    skip_whitespace(&mut buffer);
    assert!(buffer.next_char() == 'b');
    skip_whitespace(&mut buffer);
    assert!(buffer.next_char() == 'c');
    skip_whitespace(&mut buffer);
    assert!(is_eof(buffer.next_char()));
}

// token types
enum Token { LBrace, RBrace, Equals, Comma, Semicolon,
             LParen, RParen, Star, Plus, Bar,
             DefsId, RulesId, CodeId, Id(~str), RegExp, Eof }

enum Block { Rules, Defs, Code }

// fn match_next_token() -> bool {
// }

fn get_next_token(buffer: &mut LookaheadBuffer) -> ~Token {
    let mut c = buffer.next_char();
    let mut done = false;
    let mut res = ~Eof;
    while !done {
        skip_whitespace(buffer);
        if is_eof(c) {
            done = true;
        }
        else {
            match c {
                '{' => { res = ~LBrace; done = true; },
                _   => { done = true; }   // FIX
            }
        }
    }
    res
}

fn read_string(buffer: &mut LookaheadBuffer) -> ~str {
    let mut res : ~str = ~"";
    let mut c = buffer.next_char();
    while !is_eof(c) && !std::char::is_whitespace(c) {
        res.push_char(c);
        c = buffer.next_char();
    }
    buffer.return_char(c);
    res
}

fn read_string_after_first(buffer: &mut LookaheadBuffer, first: char) -> ~str {
    let mut res : ~str = ~"";
    let mut c = buffer.next_char();
    res.push_char(first);
    while !is_eof(c) && !std::char::is_whitespace(c) {
        res.push_char(c);
        c = buffer.next_char();
    }
    buffer.return_char(c);
    res
}

#[test]
fn test_read_string() {
    let mut b1 = std::io::with_str_reader("aussonderungsaxiom   ", LookaheadBuffer::new);
    assert!(std::str::eq(&read_string(&mut b1), &~"aussonderungsaxiom"));

    let mut b2 = std::io::with_str_reader("", LookaheadBuffer::new);
    assert!(std::str::eq(&read_string(&mut b2), &~""));

    let mut buffer = std::io::with_str_reader("hombas   ", LookaheadBuffer::new);
    assert!(std::str::eq(&read_string_after_first(&mut buffer, 's'), &~"shombas"));

    let mut buffer2 = std::io::with_str_reader(" or die ", LookaheadBuffer::new);
    assert!(std::str::eq(&read_string_after_first(&mut buffer2, 'b'), &~"b"));
}

fn parse_toplevel_block(buffer: &mut LookaheadBuffer) {
    skip_whitespace(buffer);
    // TODO: check for EOF
    match read_string(buffer) {
        ~"rules" => println("Rules"),
        ~"defs" => println("defs"),
        ~"code" => println("code"),
        _ => println("Quo vadis?") // TODO: error
    }
}

fn match_next_string(buffer: &mut LookaheadBuffer, s: &~str) -> bool {
    std::str::eq(&read_string(buffer), s)
}

// fn parse_defs(buffer: &mut LookaheadBuffer) {
//     println("Wut?")
// }

// fn parse_def(buffer: &mut LookaheadBuffer) {
// }

#[test]
fn test_parse_toplevel() {
    let mut b1 = std::io::with_str_reader("   rules { }   ", LookaheadBuffer::new);
    parse_toplevel_block(&mut b1);

    let mut b2 = std::io::with_str_reader("shwemba { }   ", LookaheadBuffer::new);
    parse_toplevel_block(&mut b2);

    let mut b3 = std::io::with_str_reader("defs { ausmaus }   ", LookaheadBuffer::new);
    parse_toplevel_block(&mut b3);
}

// fn parse_regexp() {
// }

pub fn parse_lexer_spec(reader: @Reader) {
    let mut buffer = LookaheadBuffer::new(reader);
    parse_toplevel_block(&mut buffer);
}

<|endoftext|>


<commit_before>use oppai_common::common::is_last_move_stupid;
use oppai_common::trajectory::{build_trajectories, build_trajectories_from, Trajectory};
use oppai_field::field::wave_diag;
use oppai_field::field::{Field, NonZeroPos, Pos};
use oppai_field::player::Player;
use std::iter;
use std::sync::atomic::{AtomicBool, Ordering};

fn mark_group(field: &Field, start_pos: Pos, player: Player, empty_board: &mut Vec<u32>) -> Vec<Pos> {
  let mut marks = Vec::new();
  wave_diag(field.width(), start_pos, |pos| {
    if empty_board[pos] != 0 {
      return false;
    }
    let cell = field.cell(pos);
    if cell.is_players_point(player) {
      empty_board[pos] = 1;
      marks.push(pos);
      true
    } else {
      false
    }
  });
  marks
}

fn collect_near_moves(field: &Field, player: Player, empty_board: &mut Vec<u32>) -> Vec<Pos> {
  let mut moves = Vec::new();
  for &pos in field
    .points_seq()
    .iter()
    .filter(|&&pos| field.cell(pos).is_players_point(player))
  {
    for &near_pos in field.directions(pos).iter() {
      if empty_board[near_pos] == 0 && field.is_putting_allowed(near_pos) {
        moves.push(near_pos);
        empty_board[near_pos] = 1;
      }
    }
  }
  for &pos in &moves {
    empty_board[pos] = 0;
  }
  moves
}

fn is_trajectoty_alive(field: &mut Field, trajectory: &Trajectory, player: Player, empty_board: &mut Vec<u32>) -> bool {
  if trajectory.points().iter().any(|&pos| !field.is_putting_allowed(pos)) {
    return false;
  }

  for &pos in trajectory.points() {
    field.put_point(pos, player);
  }

  let result = field.get_delta_score(player) > 0 || {
    let enemy = player.next();
    let moves = collect_near_moves(field, enemy, empty_board);
    moves.into_iter().any(|pos| {
      field.put_point(pos, player);
      let result = field.get_delta_score(player) > 0
        && trajectory
          .points()
          .iter()
          .all(|&trajectory_pos| field.cell(trajectory_pos).is_bound());
      field.undo();
      result && {
        let enemies_around = field
          .directions(pos)
          .iter()
          .filter(|&&pos| field.cell(pos).is_players_point(enemy))
          .count();
        enemies_around < 3
          || enemies_around == 3
            && field
              .directions(pos)
              .iter()
              .all(|&near_pos| !field.cell(near_pos).is_putting_allowed())
      }
    })
  };

  for _ in 0..trajectory.len() {
    field.undo();
  }

  result
}

fn is_trajectoty_viable(
  field: &mut Field,
  trajectory: &Trajectory,
  player: Player,
  empty_board: &mut Vec<u32>,
) -> bool {
  let moves = collect_near_moves(field, player, empty_board);
  let enemy = player.next();
  moves.into_iter().all(|enemy_pos| {
    field.put_point(enemy_pos, enemy);

    if field.get_delta_score(enemy) == 0 {
      field.undo();
      return true;
    }

    let result = is_trajectoty_alive(field, trajectory, player, empty_board);

    field.undo();

    result
  })
}

fn ladders_rec(
  field: &mut Field,
  player: Player,
  trajectory: &Trajectory,
  mut alpha: i32,
  empty_board: &mut Vec<u32>,
  should_stop: &AtomicBool,
  depth: u32,
) -> (Option<NonZeroPos>, i32, u32) {
  match *trajectory.points().as_slice() {
    [pos] => {
      field.put_point(pos, player);
      let cur_score = field.score(player);
      field.undo();
      (NonZeroPos::new(pos), cur_score, depth)
    }
    [pos1, pos2] => {
      let mut best_move = None;
      let mut capture_depth = 0;

      for &(our_pos, enemy_pos) in &[(pos1, pos2), (pos2, pos1)] {
        if trajectory.score() <= alpha {
          break;
        }

        if field.cell(our_pos).is_players_empty_base(player.next()) {
          continue;
        }

        if !field.put_point(our_pos, player) {
          panic!(
            "Failed to put a point to ({}, {}) on the field:\n{}",
            field.to_x(our_pos),
            field.to_y(our_pos),
            field,
          );
        }

        if is_last_move_stupid(field, our_pos, player) {
          field.undo();
          continue;
        }

        if field.get_delta_score(player) > 0 {
          let cur_score = field.score(player);
          field.undo();
          if cur_score > alpha {
            alpha = cur_score;
            best_move = NonZeroPos::new(our_pos);
            capture_depth = depth;
          }
          continue;
        }

        if !field.put_point(enemy_pos, player.next()) {
          panic!(
            "Failed to put a point to ({}, {}) on the field:\n{}",
            field.to_x(our_pos),
            field.to_y(our_pos),
            field,
          );
        }

        let trajectories = build_trajectories_from(field, our_pos, player, 2, empty_board, should_stop);

        if should_stop.load(Ordering::Relaxed) {
          break;
        }

        let marks = mark_group(field, our_pos, player, empty_board);

        for trajectory in trajectories {
          if trajectory.score() <= alpha {
            continue;
          }

          let (_, cur_score, cur_capture_depth) =
            ladders_rec(field, player, &trajectory, alpha, empty_board, should_stop, depth + 1);
          let cur_score = cur_score.min(trajectory.score());

          if cur_score > alpha && is_trajectoty_viable(field, &trajectory, player, empty_board) {
            alpha = cur_score;
            best_move = NonZeroPos::new(our_pos);
            capture_depth = cur_capture_depth;
          }
        }

        for pos in marks {
          empty_board[pos] = 0;
        }

        field.undo();
        field.undo();
      }

      (best_move, alpha, capture_depth)
    }
    _ => unreachable!("Trajectory with {} points", trajectory.len()),
  }
}

pub fn ladders(field: &mut Field, player: Player, should_stop: &AtomicBool) -> (Option<NonZeroPos>, i32, u32) {
  let mut empty_board = iter::repeat(0u32).take(field.length()).collect();

  let trajectories = build_trajectories(field, player, 2, &mut empty_board, &should_stop);

  info!("Solving ladders for {} trajectories.", trajectories.len());

  let mut alpha = field.score(player);
  let mut capture_depth = 0;
  let mut best_move = None;

  for trajectory in trajectories {
    if should_stop.load(Ordering::Relaxed) {
      break;
    }

    if trajectory.score() <= alpha {
      continue;
    }

    let marks = if let [pos1, _] = *trajectory.points().as_slice() {
      if let Some(&pos) = field
        .directions_diag(pos1)
        .iter()
        .find(|&&pos| field.cell(pos).is_players_point(player))
      {
        // mark one of near groups to not search trajectories from it
        mark_group(field, pos, player, &mut empty_board)
      } else {
        Vec::new()
      }
    } else {
      Vec::new()
    };

    let (cur_pos, cur_score, cur_capture_depth) =
      ladders_rec(field, player, &trajectory, alpha, &mut empty_board, should_stop, 0);
    let cur_score = cur_score.min(trajectory.score());
    if cur_score > alpha && is_trajectoty_viable(field, &trajectory, player, &mut empty_board) {
      alpha = cur_score;
      capture_depth = cur_capture_depth;
      best_move = cur_pos;
    }

    for pos in marks {
      empty_board[pos] = 0;
    }
  }

  (best_move, alpha, capture_depth)
}
<commit_msg>Beta pruning for trajectories.<commit_after>use oppai_common::common::is_last_move_stupid;
use oppai_common::trajectory::{build_trajectories, build_trajectories_from, Trajectory};
use oppai_field::field::wave_diag;
use oppai_field::field::{Field, NonZeroPos, Pos};
use oppai_field::player::Player;
use std::iter;
use std::sync::atomic::{AtomicBool, Ordering};

fn mark_group(field: &Field, start_pos: Pos, player: Player, empty_board: &mut Vec<u32>) -> Vec<Pos> {
  let mut marks = Vec::new();
  wave_diag(field.width(), start_pos, |pos| {
    if empty_board[pos] != 0 {
      return false;
    }
    let cell = field.cell(pos);
    if cell.is_players_point(player) {
      empty_board[pos] = 1;
      marks.push(pos);
      true
    } else {
      false
    }
  });
  marks
}

fn collect_near_moves(field: &Field, player: Player, empty_board: &mut Vec<u32>) -> Vec<Pos> {
  let mut moves = Vec::new();
  for &pos in field
    .points_seq()
    .iter()
    .filter(|&&pos| field.cell(pos).is_players_point(player))
  {
    for &near_pos in field.directions(pos).iter() {
      if empty_board[near_pos] == 0 && field.is_putting_allowed(near_pos) {
        moves.push(near_pos);
        empty_board[near_pos] = 1;
      }
    }
  }
  for &pos in &moves {
    empty_board[pos] = 0;
  }
  moves
}

fn is_trajectoty_alive(field: &mut Field, trajectory: &Trajectory, player: Player, empty_board: &mut Vec<u32>) -> bool {
  if trajectory.points().iter().any(|&pos| !field.is_putting_allowed(pos)) {
    return false;
  }

  for &pos in trajectory.points() {
    field.put_point(pos, player);
  }

  let result = field.get_delta_score(player) > 0 || {
    let enemy = player.next();
    let moves = collect_near_moves(field, enemy, empty_board);
    moves.into_iter().any(|pos| {
      field.put_point(pos, player);
      let result = field.get_delta_score(player) > 0
        && trajectory
          .points()
          .iter()
          .all(|&trajectory_pos| field.cell(trajectory_pos).is_bound());
      field.undo();
      result && {
        let enemies_around = field
          .directions(pos)
          .iter()
          .filter(|&&pos| field.cell(pos).is_players_point(enemy))
          .count();
        enemies_around < 3
          || enemies_around == 3
            && field
              .directions(pos)
              .iter()
              .all(|&near_pos| !field.cell(near_pos).is_putting_allowed())
      }
    })
  };

  for _ in 0..trajectory.len() {
    field.undo();
  }

  result
}

fn is_trajectoty_viable(
  field: &mut Field,
  trajectory: &Trajectory,
  player: Player,
  empty_board: &mut Vec<u32>,
) -> bool {
  let moves = collect_near_moves(field, player, empty_board);
  let enemy = player.next();
  moves.into_iter().all(|enemy_pos| {
    field.put_point(enemy_pos, enemy);

    if field.get_delta_score(enemy) == 0 {
      field.undo();
      return true;
    }

    let result = is_trajectoty_alive(field, trajectory, player, empty_board);

    field.undo();

    result
  })
}

fn ladders_rec(
  field: &mut Field,
  player: Player,
  trajectory: &Trajectory,
  mut alpha: i32,
  beta: i32,
  empty_board: &mut Vec<u32>,
  should_stop: &AtomicBool,
  depth: u32,
) -> (Option<NonZeroPos>, i32, u32) {
  match *trajectory.points().as_slice() {
    [pos] => {
      field.put_point(pos, player);
      let cur_score = field.score(player);
      field.undo();
      (NonZeroPos::new(pos), cur_score, depth)
    }
    [pos1, pos2] => {
      let mut best_move = None;
      let mut capture_depth = 0;

      for &(our_pos, enemy_pos) in &[(pos1, pos2), (pos2, pos1)] {
        if trajectory.score() <= alpha || alpha >= beta {
          break;
        }

        if field.cell(our_pos).is_players_empty_base(player.next()) {
          continue;
        }

        if !field.put_point(our_pos, player) {
          panic!(
            "Failed to put a point to ({}, {}) on the field:\n{}",
            field.to_x(our_pos),
            field.to_y(our_pos),
            field,
          );
        }

        if is_last_move_stupid(field, our_pos, player) {
          field.undo();
          continue;
        }

        if field.get_delta_score(player) > 0 {
          let cur_score = field.score(player);
          field.undo();
          if cur_score > alpha {
            alpha = cur_score;
            best_move = NonZeroPos::new(our_pos);
            capture_depth = depth;
          }
          continue;
        }

        if !field.put_point(enemy_pos, player.next()) {
          panic!(
            "Failed to put a point to ({}, {}) on the field:\n{}",
            field.to_x(our_pos),
            field.to_y(our_pos),
            field,
          );
        }

        let trajectories = build_trajectories_from(field, our_pos, player, 2, empty_board, should_stop);

        if should_stop.load(Ordering::Relaxed) {
          break;
        }

        let marks = mark_group(field, our_pos, player, empty_board);

        for trajectory in trajectories {
          if alpha >= beta {
            break;
          }

          if trajectory.score() <= alpha {
            continue;
          }

          let (_, cur_score, cur_capture_depth) = ladders_rec(
            field,
            player,
            &trajectory,
            alpha,
            beta.min(trajectory.score()),
            empty_board,
            should_stop,
            depth + 1,
          );
          let cur_score = cur_score.min(trajectory.score());

          if cur_score > alpha && is_trajectoty_viable(field, &trajectory, player, empty_board) {
            alpha = cur_score;
            best_move = NonZeroPos::new(our_pos);
            capture_depth = cur_capture_depth;
          }
        }

        for pos in marks {
          empty_board[pos] = 0;
        }

        field.undo();
        field.undo();
      }

      (best_move, alpha, capture_depth)
    }
    _ => unreachable!("Trajectory with {} points", trajectory.len()),
  }
}

pub fn ladders(field: &mut Field, player: Player, should_stop: &AtomicBool) -> (Option<NonZeroPos>, i32, u32) {
  let mut empty_board = iter::repeat(0u32).take(field.length()).collect();

  let trajectories = build_trajectories(field, player, 2, &mut empty_board, &should_stop);

  info!("Solving ladders for {} trajectories.", trajectories.len());

  let mut alpha = field.score(player);
  let mut capture_depth = 0;
  let mut best_move = None;

  for trajectory in trajectories {
    if should_stop.load(Ordering::Relaxed) {
      break;
    }

    if trajectory.score() <= alpha {
      continue;
    }

    let marks = if let [pos1, _] = *trajectory.points().as_slice() {
      if let Some(&pos) = field
        .directions_diag(pos1)
        .iter()
        .find(|&&pos| field.cell(pos).is_players_point(player))
      {
        // mark one of near groups to not search trajectories from it
        mark_group(field, pos, player, &mut empty_board)
      } else {
        Vec::new()
      }
    } else {
      Vec::new()
    };

    let (cur_pos, cur_score, cur_capture_depth) = ladders_rec(
      field,
      player,
      &trajectory,
      alpha,
      trajectory.score(),
      &mut empty_board,
      should_stop,
      0,
    );
    let cur_score = cur_score.min(trajectory.score());
    if cur_score > alpha && is_trajectoty_viable(field, &trajectory, player, &mut empty_board) {
      alpha = cur_score;
      capture_depth = cur_capture_depth;
      best_move = cur_pos;
    }

    for pos in marks {
      empty_board[pos] = 0;
    }
  }

  (best_move, alpha, capture_depth)
}
<|endoftext|>