<commit_before>extern crate clerk;
extern crate itertools;

use std::cell::RefCell;
use std::collections::VecDeque;

use clerk::{DefaultLines, Delay, Display, DisplayControlBuilder, EntryModeBuilder,
            FunctionSetBuilder, SeekFrom, ShiftTo, Send, Receive, Init, WriteMode, ReadMode};

struct ConnectionMock {
    init_calls: RefCell<u8>,
    send_bytes: RefCell<Vec<WriteMode>>,
    receivable_bytes: RefCell<VecDeque<u8>>,
}

impl Default for ConnectionMock {
    fn default() -> Self {
        ConnectionMock {
            init_calls: RefCell::new(0),
            send_bytes: RefCell::new(vec![]),
            receivable_bytes: RefCell::new(VecDeque::new()),
        }
    }
}

impl ConnectionMock {
    fn set_read_value(&self, value: u8) {
        self.receivable_bytes.borrow_mut().push_back(value)
    }
}

impl Init for ConnectionMock {
    fn init(&self) {
        let mut init_calls = self.init_calls.borrow_mut();

        *init_calls += 1;
    }
}

impl Send for ConnectionMock {
    fn send(&self, mode: WriteMode) {
        let mut send_bytes = self.send_bytes.borrow_mut();

        send_bytes.push(mode);
    }
}

impl Receive for ConnectionMock {
    fn receive(&self, _: ReadMode) -> u8 {
        self.receivable_bytes.borrow_mut().pop_front().unwrap()
    }
}

pub struct CustomDelayMock;

impl Delay for CustomDelayMock {
    fn delay_ns(_: u16) {
        // mhh
    }
}

fn setup_display() -> Display<ConnectionMock, DefaultLines> {
    Display::new(ConnectionMock::default())
}

#[test]
fn init() {
    let lcd = setup_display();

    lcd.init(&FunctionSetBuilder::default());

    let connection = lcd.get_connection();

    let init_calls = connection.init_calls.borrow_mut();
    assert_eq!(*init_calls, 1);

    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0x33));
    assert_eq!(send_bytes[1], WriteMode::Command(0x32));
    assert_eq!(send_bytes[2], WriteMode::Command(0x20));
    assert_eq!(send_bytes[3], WriteMode::Command(0x01));
}

#[test]
fn set_entry_mode() {
    let lcd = setup_display();

    lcd.set_entry_mode(&EntryModeBuilder::default());

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b0000_0110));
}

#[test]
fn test_set_display_control() {
    let lcd = setup_display();

    lcd.set_display_control(&DisplayControlBuilder::default());

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b0000_1100));
}

#[test]
fn test_shift_cursor_left() {
    let mut lcd = setup_display();

    lcd.shift_cursor(ShiftTo::Left(1));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b0001_0000));
}

#[test]
fn test_shift_cursor_left_with_zero_offset() {
    let mut lcd = setup_display();

    lcd.shift_cursor(ShiftTo::Left(0));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes.len(), 0);
}

#[test]
fn test_shift_cursor_right() {
    let mut lcd = setup_display();

    lcd.shift_cursor(ShiftTo::Right(1));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b0001_0100));
}

#[test]
fn test_shift_cursor_right_multiple() {
    let mut lcd = setup_display();

    lcd.shift_cursor(ShiftTo::Right(2));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b0001_0100));
    assert_eq!(send_bytes[1], WriteMode::Command(0b0001_0100));
}

#[test]
fn test_shift_cursor_right_with_zero_offset() {
    let mut lcd = setup_display();

    lcd.shift_cursor(ShiftTo::Right(0));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes.len(), 0);
}

#[test]
fn test_shift_left() {
    let lcd = setup_display();

    lcd.shift(ShiftTo::Left(1));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b0001_1000));
}

#[test]
fn test_shift_right() {
    let lcd = setup_display();

    lcd.shift(ShiftTo::Right(1));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b0001_1100));
}

#[test]
fn test_clear() {
    let lcd = setup_display();

    lcd.clear();

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0x01));
}

#[test]
fn test_seek_from_home() {
    let mut lcd = setup_display();

    lcd.seek(SeekFrom::Home(3));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b1000_0011));
}

#[test]
fn test_seek_from_current() {
    let mut lcd = setup_display();

    lcd.seek(SeekFrom::Home(2));
    lcd.seek(SeekFrom::Current(1));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b1000_0010));
    assert_eq!(send_bytes[1], WriteMode::Command(0b1000_0011));
}

#[test]
fn test_seek_from_line() {
    let mut lcd = setup_display();

    lcd.seek(SeekFrom::Line {
        line: DefaultLines::Two,
        bytes: 3,
    });

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b1100_0011));
}

#[test]
fn test_seek_cgram_from_home() {
    let mut lcd = setup_display();

    lcd.seek_cgram(SeekFrom::Home(3));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b0100_0011));
}

#[test]
fn test_seek_cgram_from_current() {
    let mut lcd = setup_display();

    lcd.seek_cgram(SeekFrom::Home(2));
    lcd.seek_cgram(SeekFrom::Current(1));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b0100_0010));
    assert_eq!(send_bytes[1], WriteMode::Command(0b0100_0011));
}

#[test]
#[ignore]
// TODO: needs clarification: line does not make sense here,  For 5×8 dots, eight character
// patterns can be written, and for 5×10 dots, four character patterns can be written
fn test_seek_cgram_from_line() {
    let mut lcd = setup_display();

    lcd.seek_cgram(SeekFrom::Home(2));
    lcd.seek_cgram(SeekFrom::Current(1));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b0100_0010));
    assert_eq!(send_bytes[1], WriteMode::Command(0b0100_0011));
}

#[test]
fn test_write() {
    let mut lcd = setup_display();

    lcd.write(123);

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Data(123));
}

#[test]
fn test_write_updates_address_counter() {
    let mut lcd = setup_display();

    lcd.seek(SeekFrom::Home(0));
    lcd.write(12);
    lcd.write(34);
    lcd.seek(SeekFrom::Current(0));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[3], WriteMode::Command(0b1000_0010));
}

#[test]
fn test_write_message() {
    let mut lcd = setup_display();

    lcd.write_message("Hi");

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Data(b'H'));
    assert_eq!(send_bytes[1], WriteMode::Data(b'i'));
}

#[test]
fn test_write_message_increments_address_counter() {
    let mut lcd = setup_display();

    lcd.write_message("Hi");
    lcd.seek(SeekFrom::Current(0));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[2], WriteMode::Command(0b1000_0010));
}

#[test]
fn test_read() {
    let expected = 42;

    let connection = ConnectionMock::default();
    connection.set_read_value(expected);

    let mut lcd: Display<ConnectionMock, DefaultLines> = Display::new(connection);
    let input = lcd.read_byte();
    assert_eq!(input, expected);
}

#[test]
fn test_read_increments_address_counter() {
    let connection = ConnectionMock::default();

    connection.set_read_value(4);
    connection.set_read_value(2);

    let mut lcd: Display<ConnectionMock, DefaultLines> = Display::new(connection);

    lcd.read_byte();
    lcd.seek(SeekFrom::Current(0));

    lcd.read_byte();
    lcd.seek(SeekFrom::Current(0));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b1000_0001));
    assert_eq!(send_bytes[1], WriteMode::Command(0b1000_0010));
}
<commit_msg>Remove unused crate itertools<commit_after>extern crate clerk;

use std::cell::RefCell;
use std::collections::VecDeque;

use clerk::{DefaultLines, Delay, Display, DisplayControlBuilder, EntryModeBuilder,
            FunctionSetBuilder, SeekFrom, ShiftTo, Send, Receive, Init, WriteMode, ReadMode};

struct ConnectionMock {
    init_calls: RefCell<u8>,
    send_bytes: RefCell<Vec<WriteMode>>,
    receivable_bytes: RefCell<VecDeque<u8>>,
}

impl Default for ConnectionMock {
    fn default() -> Self {
        ConnectionMock {
            init_calls: RefCell::new(0),
            send_bytes: RefCell::new(vec![]),
            receivable_bytes: RefCell::new(VecDeque::new()),
        }
    }
}

impl ConnectionMock {
    fn set_read_value(&self, value: u8) {
        self.receivable_bytes.borrow_mut().push_back(value)
    }
}

impl Init for ConnectionMock {
    fn init(&self) {
        let mut init_calls = self.init_calls.borrow_mut();

        *init_calls += 1;
    }
}

impl Send for ConnectionMock {
    fn send(&self, mode: WriteMode) {
        let mut send_bytes = self.send_bytes.borrow_mut();

        send_bytes.push(mode);
    }
}

impl Receive for ConnectionMock {
    fn receive(&self, _: ReadMode) -> u8 {
        self.receivable_bytes.borrow_mut().pop_front().unwrap()
    }
}

pub struct CustomDelayMock;

impl Delay for CustomDelayMock {
    fn delay_ns(_: u16) {
        // mhh
    }
}

fn setup_display() -> Display<ConnectionMock, DefaultLines> {
    Display::new(ConnectionMock::default())
}

#[test]
fn init() {
    let lcd = setup_display();

    lcd.init(&FunctionSetBuilder::default());

    let connection = lcd.get_connection();

    let init_calls = connection.init_calls.borrow_mut();
    assert_eq!(*init_calls, 1);

    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0x33));
    assert_eq!(send_bytes[1], WriteMode::Command(0x32));
    assert_eq!(send_bytes[2], WriteMode::Command(0x20));
    assert_eq!(send_bytes[3], WriteMode::Command(0x01));
}

#[test]
fn set_entry_mode() {
    let lcd = setup_display();

    lcd.set_entry_mode(&EntryModeBuilder::default());

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b0000_0110));
}

#[test]
fn test_set_display_control() {
    let lcd = setup_display();

    lcd.set_display_control(&DisplayControlBuilder::default());

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b0000_1100));
}

#[test]
fn test_shift_cursor_left() {
    let mut lcd = setup_display();

    lcd.shift_cursor(ShiftTo::Left(1));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b0001_0000));
}

#[test]
fn test_shift_cursor_left_with_zero_offset() {
    let mut lcd = setup_display();

    lcd.shift_cursor(ShiftTo::Left(0));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes.len(), 0);
}

#[test]
fn test_shift_cursor_right() {
    let mut lcd = setup_display();

    lcd.shift_cursor(ShiftTo::Right(1));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b0001_0100));
}

#[test]
fn test_shift_cursor_right_multiple() {
    let mut lcd = setup_display();

    lcd.shift_cursor(ShiftTo::Right(2));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b0001_0100));
    assert_eq!(send_bytes[1], WriteMode::Command(0b0001_0100));
}

#[test]
fn test_shift_cursor_right_with_zero_offset() {
    let mut lcd = setup_display();

    lcd.shift_cursor(ShiftTo::Right(0));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes.len(), 0);
}

#[test]
fn test_shift_left() {
    let lcd = setup_display();

    lcd.shift(ShiftTo::Left(1));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b0001_1000));
}

#[test]
fn test_shift_right() {
    let lcd = setup_display();

    lcd.shift(ShiftTo::Right(1));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b0001_1100));
}

#[test]
fn test_clear() {
    let lcd = setup_display();

    lcd.clear();

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0x01));
}

#[test]
fn test_seek_from_home() {
    let mut lcd = setup_display();

    lcd.seek(SeekFrom::Home(3));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b1000_0011));
}

#[test]
fn test_seek_from_current() {
    let mut lcd = setup_display();

    lcd.seek(SeekFrom::Home(2));
    lcd.seek(SeekFrom::Current(1));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b1000_0010));
    assert_eq!(send_bytes[1], WriteMode::Command(0b1000_0011));
}

#[test]
fn test_seek_from_line() {
    let mut lcd = setup_display();

    lcd.seek(SeekFrom::Line {
        line: DefaultLines::Two,
        bytes: 3,
    });

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b1100_0011));
}

#[test]
fn test_seek_cgram_from_home() {
    let mut lcd = setup_display();

    lcd.seek_cgram(SeekFrom::Home(3));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b0100_0011));
}

#[test]
fn test_seek_cgram_from_current() {
    let mut lcd = setup_display();

    lcd.seek_cgram(SeekFrom::Home(2));
    lcd.seek_cgram(SeekFrom::Current(1));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b0100_0010));
    assert_eq!(send_bytes[1], WriteMode::Command(0b0100_0011));
}

#[test]
#[ignore]
// TODO: needs clarification: line does not make sense here,  For 5×8 dots, eight character
// patterns can be written, and for 5×10 dots, four character patterns can be written
fn test_seek_cgram_from_line() {
    let mut lcd = setup_display();

    lcd.seek_cgram(SeekFrom::Home(2));
    lcd.seek_cgram(SeekFrom::Current(1));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b0100_0010));
    assert_eq!(send_bytes[1], WriteMode::Command(0b0100_0011));
}

#[test]
fn test_write() {
    let mut lcd = setup_display();

    lcd.write(123);

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Data(123));
}

#[test]
fn test_write_updates_address_counter() {
    let mut lcd = setup_display();

    lcd.seek(SeekFrom::Home(0));
    lcd.write(12);
    lcd.write(34);
    lcd.seek(SeekFrom::Current(0));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[3], WriteMode::Command(0b1000_0010));
}

#[test]
fn test_write_message() {
    let mut lcd = setup_display();

    lcd.write_message("Hi");

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Data(b'H'));
    assert_eq!(send_bytes[1], WriteMode::Data(b'i'));
}

#[test]
fn test_write_message_increments_address_counter() {
    let mut lcd = setup_display();

    lcd.write_message("Hi");
    lcd.seek(SeekFrom::Current(0));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[2], WriteMode::Command(0b1000_0010));
}

#[test]
fn test_read() {
    let expected = 42;

    let connection = ConnectionMock::default();
    connection.set_read_value(expected);

    let mut lcd: Display<ConnectionMock, DefaultLines> = Display::new(connection);
    let input = lcd.read_byte();
    assert_eq!(input, expected);
}

#[test]
fn test_read_increments_address_counter() {
    let connection = ConnectionMock::default();

    connection.set_read_value(4);
    connection.set_read_value(2);

    let mut lcd: Display<ConnectionMock, DefaultLines> = Display::new(connection);

    lcd.read_byte();
    lcd.seek(SeekFrom::Current(0));

    lcd.read_byte();
    lcd.seek(SeekFrom::Current(0));

    let connection = lcd.get_connection();
    let send_bytes = connection.send_bytes.borrow_mut();
    assert_eq!(send_bytes[0], WriteMode::Command(0b1000_0001));
    assert_eq!(send_bytes[1], WriteMode::Command(0b1000_0010));
}
<|endoftext|>


<commit_before>use numpy::{array, dot, einsum, inner, pyarray, PyArray0, PyArray1, PyArray2};
use pyo3::Python;

#[test]
fn test_dot() {
    Python::with_gil(|py| {
        let a = pyarray![py, [1, 0], [0, 1]];
        let b = pyarray![py, [4, 1], [2, 2]];
        let c: &PyArray2<_> = dot(a, b).unwrap();
        assert_eq!(c.readonly().as_array(), array![[4, 1], [2, 2]]);

        let a = pyarray![py, 1, 2, 3];
        let err = dot::<_, _, _, &PyArray2<_>>(a, b).unwrap_err();
        assert!(err.to_string().contains("not aligned"), "{}", err);
    });
}

#[test]
fn test_inner() {
    Python::with_gil(|py| {
        let a = pyarray![py, 1, 2, 3];
        let b = pyarray![py, 0, 1, 0];
        let c: &PyArray0<_> = inner(a, b).unwrap();
        assert_eq!(c.readonly().as_array(), ndarray::arr0(2));

        let a = pyarray![py, [1, 0], [0, 1]];
        let b = pyarray![py, [4, 1], [2, 2]];
        let c: &PyArray2<_> = inner(a, b).unwrap();
        assert_eq!(c.readonly().as_array(), array![[4, 2], [1, 2]]);

        let a = pyarray![py, 1, 2, 3];
        let err = inner::<_, _, _, &PyArray2<_>>(a, b).unwrap_err();
        assert!(err.to_string().contains("not aligned"), "{}", err);
    });
}

#[test]
fn test_einsum() {
    Python::with_gil(|py| {
        let a = PyArray1::<i32>::arange(py, 0, 25, 1)
            .reshape([5, 5])
            .unwrap();
        let b = pyarray![py, 0, 1, 2, 3, 4];
        let c = pyarray![py, [0, 1, 2], [3, 4, 5]];

        assert_eq!(
            einsum!("ii", a).unwrap().readonly().as_array(),
            ndarray::arr0(60)
        );
        assert_eq!(
            einsum!("ii->i", a).unwrap().readonly().as_array(),
            array![0, 6, 12, 18, 24],
        );
        assert_eq!(
            einsum!("ij->i", a).unwrap().readonly().as_array(),
            array![10, 35, 60, 85, 110],
        );
        assert_eq!(
            einsum!("ji", c).unwrap().readonly().as_array(),
            array![[0, 3], [1, 4], [2, 5]],
        );
        assert_eq!(
            einsum!("ij,j", a, b).unwrap().readonly().as_array(),
            array![30, 80, 130, 180, 230],
        );
    });
}
<commit_msg>Extend integration tests to include the scalar cases for dot and inner.<commit_after>use numpy::{array, dot, einsum, inner, pyarray, PyArray0, PyArray1, PyArray2};
use pyo3::Python;

#[test]
fn test_dot() {
    Python::with_gil(|py| {
        let a = pyarray![py, [1, 0], [0, 1]];
        let b = pyarray![py, [4, 1], [2, 2]];
        let c: &PyArray2<_> = dot(a, b).unwrap();
        assert_eq!(c.readonly().as_array(), array![[4, 1], [2, 2]]);

        let a = pyarray![py, 1, 2, 3];
        let err = dot::<_, _, _, &PyArray2<_>>(a, b).unwrap_err();
        assert!(err.to_string().contains("not aligned"), "{}", err);

        let a = pyarray![py, 1, 2, 3];
        let b = pyarray![py, 0, 1, 0];
        let c: &PyArray0<_> = dot(a, b).unwrap();
        assert_eq!(c.item(), 2);
        let c: i32 = dot(a, b).unwrap();
        assert_eq!(c, 2);

        let a = pyarray![py, 1.0, 2.0, 3.0];
        let b = pyarray![py, 0.0, 0.0, 0.0];
        let c: f64 = dot(a, b).unwrap();
        assert_eq!(c, 0.0);
    });
}

#[test]
fn test_inner() {
    Python::with_gil(|py| {
        let a = pyarray![py, 1, 2, 3];
        let b = pyarray![py, 0, 1, 0];
        let c: &PyArray0<_> = inner(a, b).unwrap();
        assert_eq!(c.item(), 2);
        let c: i32 = inner(a, b).unwrap();
        assert_eq!(c, 2);

        let a = pyarray![py, 1.0, 2.0, 3.0];
        let b = pyarray![py, 0.0, 0.0, 0.0];
        let c: f64 = inner(a, b).unwrap();
        assert_eq!(c, 0.0);

        let a = pyarray![py, [1, 0], [0, 1]];
        let b = pyarray![py, [4, 1], [2, 2]];
        let c: &PyArray2<_> = inner(a, b).unwrap();
        assert_eq!(c.readonly().as_array(), array![[4, 2], [1, 2]]);

        let a = pyarray![py, 1, 2, 3];
        let err = inner::<_, _, _, &PyArray2<_>>(a, b).unwrap_err();
        assert!(err.to_string().contains("not aligned"), "{}", err);
    });
}

#[test]
fn test_einsum() {
    Python::with_gil(|py| {
        let a = PyArray1::<i32>::arange(py, 0, 25, 1)
            .reshape([5, 5])
            .unwrap();
        let b = pyarray![py, 0, 1, 2, 3, 4];
        let c = pyarray![py, [0, 1, 2], [3, 4, 5]];

        assert_eq!(einsum!("ii", a).unwrap().item(), 60);
        assert_eq!(
            einsum!("ii->i", a).unwrap().readonly().as_array(),
            array![0, 6, 12, 18, 24],
        );
        assert_eq!(
            einsum!("ij->i", a).unwrap().readonly().as_array(),
            array![10, 35, 60, 85, 110],
        );
        assert_eq!(
            einsum!("ji", c).unwrap().readonly().as_array(),
            array![[0, 3], [1, 4], [2, 5]],
        );
        assert_eq!(
            einsum!("ij,j", a, b).unwrap().readonly().as_array(),
            array![30, 80, 130, 180, 230],
        );
    });
}
<|endoftext|>


<commit_before>//! Requires the "cache", "methods", and "voice" features be enabled in your
//! Cargo.toml, like so:
//!
//! ```toml
//! [dependencies.serenity]
//! git = "https://github.com/zeyla/serenity.git"
//! features = ["cache", "framework", "voice"]
//! ```

#[macro_use]
extern crate serenity;

use serenity::client::{CACHE, Client};
use serenity::ext::voice;
use serenity::model::{ChannelId, Message, Mentionable};
use serenity::Result as SerenityResult;
use std::env;

fn main() {
    // Configure the client with your Discord bot token in the environment.
    let token = env::var("DISCORD_TOKEN")
        .expect("Expected a token in the environment");
    let mut client = Client::login(&token);

    client.with_framework(|f| f
        .configure(|c| c
            .prefix("~")
            .on_mention(true))
        .on("deafen", deafen)
        .on("join", join)
        .on("leave", leave)
        .on("mute", mute)
        .on("play", play)
        .on("ping", ping)
        .on("undeafen", undeafen)
        .on("unmute", unmute));

    client.on_ready(|_context, ready| {
        println!("{} is connected!", ready.user.name);
    });

    let _ = client.start().map_err(|why| println!("Client ended: {:?}", why));
}

command!(deafen(ctx, msg) {
    let guild_id = match CACHE.read().unwrap().get_guild_channel(msg.channel_id) {
        Some(channel) => channel.read().unwrap().guild_id,
        None => {
            check_msg(msg.channel_id.say("Groups and DMs not supported"));

            return Ok(());
        },
    };

    let mut shard = ctx.shard.lock().unwrap();

    let handler = match shard.manager.get(guild_id) {
        Some(handler) => handler,
        None => {
            check_msg(msg.reply("Not in a voice channel"));

            return Ok(());
        },
    };

    if handler.self_deaf {
        check_msg(msg.channel_id.say("Already deafened"));
    } else {
        handler.deafen(true);

        check_msg(msg.channel_id.say("Deafened"));
    }
});

command!(join(ctx, msg, args) {
    let connect_to = match args.get(0) {
        Some(arg) => match arg.parse::<u64>() {
            Ok(id) => ChannelId(id),
            Err(_why) => {
                check_msg(msg.reply("Invalid voice channel ID given"));

                return Ok(());
            },
        },
        None => {
            check_msg(msg.reply("Requires a voice channel ID be given"));

            return Ok(());
        },
    };

    let guild_id = match CACHE.read().unwrap().get_guild_channel(msg.channel_id) {
        Some(channel) => channel.read().unwrap().guild_id,
        None => {
            check_msg(msg.channel_id.say("Groups and DMs not supported"));

            return Ok(());
        },
    };

    let mut shard = ctx.shard.lock().unwrap();
    shard.manager.join(Some(guild_id), connect_to);

    check_msg(msg.channel_id.say(&format!("Joined {}", connect_to.mention())));
});

command!(leave(ctx, msg) {
    let guild_id = match CACHE.read().unwrap().get_guild_channel(msg.channel_id) {
        Some(channel) => channel.read().unwrap().guild_id,
        None => {
            check_msg(msg.channel_id.say("Groups and DMs not supported"));

            return Ok(());
        },
    };

    let mut shard = ctx.shard.lock().unwrap();
    let has_handler = shard.manager.get(guild_id).is_some();

    if has_handler {
        shard.manager.remove(guild_id);

        check_msg(msg.channel_id.say("Left voice channel"));
    } else {
        check_msg(msg.reply("Not in a voice channel"));
    }
});

command!(mute(ctx, msg) {
    let guild_id = match CACHE.read().unwrap().get_guild_channel(msg.channel_id) {
        Some(channel) => channel.read().unwrap().guild_id,
        None => {
            check_msg(msg.channel_id.say("Groups and DMs not supported"));

            return Ok(());
        },
    };

    let mut shard = ctx.shard.lock().unwrap();

    let handler = match shard.manager.get(guild_id) {
        Some(handler) => handler,
        None => {
            check_msg(msg.reply("Not in a voice channel"));

            return Ok(());
        },
    };

    if handler.self_mute {
        check_msg(msg.channel_id.say("Already muted"));
    } else {
        handler.mute(true);

        check_msg(msg.channel_id.say("Now muted"));
    }
});

command!(ping(_context, msg) {
    check_msg(msg.channel_id.say("Pong!"));
});

command!(play(ctx, msg, args) {
    let url = match args.get(0) {
        Some(url) => url,
        None => {
            check_msg(msg.channel_id.say("Must provide a URL to a video or audio"));

            return Ok(());
        },
    };

    if !url.starts_with("http") {
        check_msg(msg.channel_id.say("Must provide a valid URL"));

        return Ok(());
    }

    let guild_id = match CACHE.read().unwrap().get_guild_channel(msg.channel_id) {
        Some(channel) => channel.read().unwrap().guild_id,
        None => {
            check_msg(msg.channel_id.say("Error finding channel info"));

            return Ok(());
        },
    };

    if let Some(handler) = ctx.shard.lock().unwrap().manager.get(guild_id) {
        let source = match voice::ytdl(url) {
            Ok(source) => source,
            Err(why) => {
                println!("Err starting source: {:?}", why);

                check_msg(msg.channel_id.say("Error sourcing ffmpeg"));

                return Ok(());
            },
        };

        handler.play(source);

        check_msg(msg.channel_id.say("Playing song"));
    } else {
        check_msg(msg.channel_id.say("Not in a voice channel to play in"));
    }
});

command!(undeafen(ctx, msg) {
    let guild_id = match CACHE.read().unwrap().get_guild_channel(msg.channel_id) {
        Some(channel) => channel.read().unwrap().guild_id,
        None => {
            check_msg(msg.channel_id.say("Error finding channel info"));

            return Ok(());
        },
    };

    if let Some(handler) = ctx.shard.lock().unwrap().manager.get(guild_id) {
        handler.deafen(false);

        check_msg(msg.channel_id.say("Undeafened"));
    } else {
        check_msg(msg.channel_id.say("Not in a voice channel to undeafen in"));
    }
});

command!(unmute(ctx, msg) {
    let guild_id = match CACHE.read().unwrap().get_guild_channel(msg.channel_id) {
        Some(channel) => channel.read().unwrap().guild_id,
        None => {
            check_msg(msg.channel_id.say("Error finding channel info"));

            return Ok(());
        },
    };

    if let Some(handler) = ctx.shard.lock().unwrap().manager.get(guild_id) {
        handler.mute(false);

        check_msg(msg.channel_id.say("Unmuted"));
    } else {
        check_msg(msg.channel_id.say("Not in a voice channel to undeafen in"));
    }
});

/// Checks that a message successfully sent; if not, then logs why to stdout.
fn check_msg(result: SerenityResult<Message>) {
    if let Err(why) = result {
        println!("Error sending message: {:?}", why);
    }
}
<commit_msg>Fix call to VoiceManager.join in example 06<commit_after>//! Requires the "cache", "methods", and "voice" features be enabled in your
//! Cargo.toml, like so:
//!
//! ```toml
//! [dependencies.serenity]
//! git = "https://github.com/zeyla/serenity.git"
//! features = ["cache", "framework", "voice"]
//! ```

#[macro_use]
extern crate serenity;

use serenity::client::{CACHE, Client};
use serenity::ext::voice;
use serenity::model::{ChannelId, Message, Mentionable};
use serenity::Result as SerenityResult;
use std::env;

fn main() {
    // Configure the client with your Discord bot token in the environment.
    let token = env::var("DISCORD_TOKEN")
        .expect("Expected a token in the environment");
    let mut client = Client::login(&token);

    client.with_framework(|f| f
        .configure(|c| c
            .prefix("~")
            .on_mention(true))
        .on("deafen", deafen)
        .on("join", join)
        .on("leave", leave)
        .on("mute", mute)
        .on("play", play)
        .on("ping", ping)
        .on("undeafen", undeafen)
        .on("unmute", unmute));

    client.on_ready(|_context, ready| {
        println!("{} is connected!", ready.user.name);
    });

    let _ = client.start().map_err(|why| println!("Client ended: {:?}", why));
}

command!(deafen(ctx, msg) {
    let guild_id = match CACHE.read().unwrap().get_guild_channel(msg.channel_id) {
        Some(channel) => channel.read().unwrap().guild_id,
        None => {
            check_msg(msg.channel_id.say("Groups and DMs not supported"));

            return Ok(());
        },
    };

    let mut shard = ctx.shard.lock().unwrap();

    let handler = match shard.manager.get(guild_id) {
        Some(handler) => handler,
        None => {
            check_msg(msg.reply("Not in a voice channel"));

            return Ok(());
        },
    };

    if handler.self_deaf {
        check_msg(msg.channel_id.say("Already deafened"));
    } else {
        handler.deafen(true);

        check_msg(msg.channel_id.say("Deafened"));
    }
});

command!(join(ctx, msg, args) {
    let connect_to = match args.get(0) {
        Some(arg) => match arg.parse::<u64>() {
            Ok(id) => ChannelId(id),
            Err(_why) => {
                check_msg(msg.reply("Invalid voice channel ID given"));

                return Ok(());
            },
        },
        None => {
            check_msg(msg.reply("Requires a voice channel ID be given"));

            return Ok(());
        },
    };

    let guild_id = match CACHE.read().unwrap().get_guild_channel(msg.channel_id) {
        Some(channel) => channel.read().unwrap().guild_id,
        None => {
            check_msg(msg.channel_id.say("Groups and DMs not supported"));

            return Ok(());
        },
    };

    let mut shard = ctx.shard.lock().unwrap();
    shard.manager.join(guild_id, connect_to);

    check_msg(msg.channel_id.say(&format!("Joined {}", connect_to.mention())));
});

command!(leave(ctx, msg) {
    let guild_id = match CACHE.read().unwrap().get_guild_channel(msg.channel_id) {
        Some(channel) => channel.read().unwrap().guild_id,
        None => {
            check_msg(msg.channel_id.say("Groups and DMs not supported"));

            return Ok(());
        },
    };

    let mut shard = ctx.shard.lock().unwrap();
    let has_handler = shard.manager.get(guild_id).is_some();

    if has_handler {
        shard.manager.remove(guild_id);

        check_msg(msg.channel_id.say("Left voice channel"));
    } else {
        check_msg(msg.reply("Not in a voice channel"));
    }
});

command!(mute(ctx, msg) {
    let guild_id = match CACHE.read().unwrap().get_guild_channel(msg.channel_id) {
        Some(channel) => channel.read().unwrap().guild_id,
        None => {
            check_msg(msg.channel_id.say("Groups and DMs not supported"));

            return Ok(());
        },
    };

    let mut shard = ctx.shard.lock().unwrap();

    let handler = match shard.manager.get(guild_id) {
        Some(handler) => handler,
        None => {
            check_msg(msg.reply("Not in a voice channel"));

            return Ok(());
        },
    };

    if handler.self_mute {
        check_msg(msg.channel_id.say("Already muted"));
    } else {
        handler.mute(true);

        check_msg(msg.channel_id.say("Now muted"));
    }
});

command!(ping(_context, msg) {
    check_msg(msg.channel_id.say("Pong!"));
});

command!(play(ctx, msg, args) {
    let url = match args.get(0) {
        Some(url) => url,
        None => {
            check_msg(msg.channel_id.say("Must provide a URL to a video or audio"));

            return Ok(());
        },
    };

    if !url.starts_with("http") {
        check_msg(msg.channel_id.say("Must provide a valid URL"));

        return Ok(());
    }

    let guild_id = match CACHE.read().unwrap().get_guild_channel(msg.channel_id) {
        Some(channel) => channel.read().unwrap().guild_id,
        None => {
            check_msg(msg.channel_id.say("Error finding channel info"));

            return Ok(());
        },
    };

    if let Some(handler) = ctx.shard.lock().unwrap().manager.get(guild_id) {
        let source = match voice::ytdl(url) {
            Ok(source) => source,
            Err(why) => {
                println!("Err starting source: {:?}", why);

                check_msg(msg.channel_id.say("Error sourcing ffmpeg"));

                return Ok(());
            },
        };

        handler.play(source);

        check_msg(msg.channel_id.say("Playing song"));
    } else {
        check_msg(msg.channel_id.say("Not in a voice channel to play in"));
    }
});

command!(undeafen(ctx, msg) {
    let guild_id = match CACHE.read().unwrap().get_guild_channel(msg.channel_id) {
        Some(channel) => channel.read().unwrap().guild_id,
        None => {
            check_msg(msg.channel_id.say("Error finding channel info"));

            return Ok(());
        },
    };

    if let Some(handler) = ctx.shard.lock().unwrap().manager.get(guild_id) {
        handler.deafen(false);

        check_msg(msg.channel_id.say("Undeafened"));
    } else {
        check_msg(msg.channel_id.say("Not in a voice channel to undeafen in"));
    }
});

command!(unmute(ctx, msg) {
    let guild_id = match CACHE.read().unwrap().get_guild_channel(msg.channel_id) {
        Some(channel) => channel.read().unwrap().guild_id,
        None => {
            check_msg(msg.channel_id.say("Error finding channel info"));

            return Ok(());
        },
    };

    if let Some(handler) = ctx.shard.lock().unwrap().manager.get(guild_id) {
        handler.mute(false);

        check_msg(msg.channel_id.say("Unmuted"));
    } else {
        check_msg(msg.channel_id.say("Not in a voice channel to undeafen in"));
    }
});

/// Checks that a message successfully sent; if not, then logs why to stdout.
fn check_msg(result: SerenityResult<Message>) {
    if let Err(why) = result {
        println!("Error sending message: {:?}", why);
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use capnp::capability::{Server};
use capnp::Error;
use capnp::primitive_list;

use capnp_rpc::rpc::{LocalClient};

use calculator_capnp::calculator;
use gj::Promise;

struct ValueImpl {
    value: f64
}

impl ValueImpl {
    fn new(value: f64) -> ValueImpl {
        ValueImpl { value: value }
    }
}

impl calculator::value::Server for ValueImpl {
    fn read(&mut self,
            _params: calculator::value::ReadParams,
            mut results: calculator::value::ReadResults)
            -> Promise<calculator::value::ReadResults, Error>
    {
        results.get().set_value(self.value);
        Promise::ok(results)
    }
}

fn evaluate_impl(
    expression: calculator::expression::Reader,
    params: Option<primitive_list::Reader<f64>>) -> Promise<f64, Error> {

    match pry!(expression.which()) {
        calculator::expression::Literal(v) => {
            Promise::ok(v)
        },
        calculator::expression::PreviousResult(p) => {
            pry!(p).read_request().send().promise.map(|v| {
                Ok(try!(v.get()).get_value())
            })
        }
        calculator::expression::Parameter(p) => {
            match params {
                Some(params) if p < params.len() => {
                    Promise::ok(params.get(p))
                }
                _ => {
                    Promise::err(Error::failed(format!("bad parameter: {}", p)))
                }
            }
        }
        calculator::expression::Call(call) => {
            let func = call.get_function();
            let params = call.get_params();
            unimplemented!()
        }
    }
}

struct FunctionImpl {
    param_count: u32,
    body: ::capnp::message::Builder<::capnp::message::HeapAllocator>,
}

impl FunctionImpl {
    fn new(param_count: u32, body: calculator::expression::Reader) -> FunctionImpl {
        let mut result = FunctionImpl {
            param_count: param_count,
            body: ::capnp::message::Builder::new_default()
        };
        result.body.set_root(body).unwrap();
        result
    }
}

impl calculator::function::Server for FunctionImpl {
    fn call(&mut self,
            params: calculator::function::CallParams,
            mut results: calculator::function::CallResults)
        -> Promise<calculator::function::CallResults, Error>
    {
        let params = pry!(params.get().get_params());
        if params.len() != self.param_count {
            Promise::err(Error::failed(
                format!("Expect {} parameters but got {}.", self.param_count, params.len())))
        } else {
            evaluate_impl(
                pry!(self.body.get_root::<calculator::expression::Builder>()).as_reader(),
                Some(params)).map(move |v| {
                    results.get().set_value(v);
                    Ok(results)
                })
        }
    }
}

#[derive(Clone, Copy)]
pub struct OperatorImpl {
    op: calculator::Operator,
}

impl calculator::function::Server for OperatorImpl {
    fn call(&mut self,
            params: calculator::function::CallParams,
            mut results: calculator::function::CallResults)
            -> Promise<calculator::function::CallResults, Error>
    {
        let params = pry!(params.get().get_params());
        if params.len() != 2 {
            Promise::err(Error::failed("Wrong number of paramters.".to_string()))
        } else {
            let v = match self.op {
                calculator::Operator::Add =>       params.get(0) + params.get(1),
                calculator::Operator::Subtract =>  params.get(0) - params.get(1),
                calculator::Operator::Multiply =>  params.get(0) * params.get(1),
                calculator::Operator::Divide =>    params.get(0) / params.get(1),
            };
            results.get().set_value(v);
            Promise::ok(results)
        }
    }
}

struct CalculatorImpl;

impl calculator::Server for CalculatorImpl {
    fn evaluate(&mut self,
                params: calculator::EvaluateParams,
                mut results: calculator::EvaluateResults)
                -> Promise<calculator::EvaluateResults, Error>
    {
        evaluate_impl(pry!(params.get().get_expression()), None).map(move |v| {
            results.get().set_value(
                calculator::value::ToClient::new(ValueImpl::new(v)).from_server::<LocalClient>());
            Ok(results)
        })
    }
    fn def_function(&mut self,
                    params: calculator::DefFunctionParams,
                    mut results: calculator::DefFunctionResults)
                    -> Promise<calculator::DefFunctionResults, Error>
    {
        results.get().set_func(
            calculator::function::ToClient::new(
                FunctionImpl::new(params.get().get_param_count() as u32, pry!(params.get().get_body())))
                .from_server::<LocalClient>());
        Promise::ok(results)
    }
    fn get_operator(&mut self,
                    params: calculator::GetOperatorParams,
                    mut results: calculator::GetOperatorResults)
                    -> Promise<calculator::GetOperatorResults, Error>
    {
        let op = pry!(params.get().get_op());
        results.get().set_func(
            calculator::function::ToClient::new(OperatorImpl {op : op}).from_server::<LocalClient>());
        Promise::ok(results)
    }
}

pub fn main() {
    let args : Vec<String> = ::std::env::args().collect();
    if args.len() != 3 {
        println!("usage: {} server ADDRESS[:PORT]", args[0]);
        return;
    }

    //let rpc_server = EzRpcServer::new(&*args[2]).unwrap();

    // There's got to be a better way to do this.
    //let calculator = Box::new(calculator::ServerDispatch { server : Box::new(CalculatorImpl)});

    //let _ = rpc_server.serve(calculator);
}
<commit_msg>Finish evaluate_impl().<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use capnp::capability::{Server};
use capnp::Error;
use capnp::primitive_list;

use capnp_rpc::rpc::{LocalClient};

use calculator_capnp::calculator;
use gj::Promise;

struct ValueImpl {
    value: f64
}

impl ValueImpl {
    fn new(value: f64) -> ValueImpl {
        ValueImpl { value: value }
    }
}

impl calculator::value::Server for ValueImpl {
    fn read(&mut self,
            _params: calculator::value::ReadParams,
            mut results: calculator::value::ReadResults)
            -> Promise<calculator::value::ReadResults, Error>
    {
        results.get().set_value(self.value);
        Promise::ok(results)
    }
}

fn evaluate_impl(expression: calculator::expression::Reader,
                 params: Option<primitive_list::Reader<f64>>)
                 -> Promise<f64, Error>
{
    match pry!(expression.which()) {
        calculator::expression::Literal(v) => {
            Promise::ok(v)
        },
        calculator::expression::PreviousResult(p) => {
            pry!(p).read_request().send().promise.map(|v| {
                Ok(try!(v.get()).get_value())
            })
        }
        calculator::expression::Parameter(p) => {
            match params {
                Some(params) if p < params.len() => {
                    Promise::ok(params.get(p))
                }
                _ => {
                    Promise::err(Error::failed(format!("bad parameter: {}", p)))
                }
            }
        }
        calculator::expression::Call(call) => {
            let func = pry!(call.get_function());
            let mut param_promises = Vec::new();
            for param in pry!(call.get_params()).iter() {
                param_promises.push(evaluate_impl(param, params));
            }
            Promise::all(param_promises.into_iter()).then(move |param_values| {
                let mut request = func.call_request();
                {
                    let mut params = request.init().init_params(param_values.len() as u32);
                    for ii in 0..param_values.len() {
                        params.set(ii as u32, param_values[ii]);
                    }
                }
                request.send().promise.map(|result| {
                    Ok(try!(result.get()).get_value())
                })
            })
        }
    }
}

struct FunctionImpl {
    param_count: u32,
    body: ::capnp::message::Builder<::capnp::message::HeapAllocator>,
}

impl FunctionImpl {
    fn new(param_count: u32, body: calculator::expression::Reader) -> FunctionImpl {
        let mut result = FunctionImpl {
            param_count: param_count,
            body: ::capnp::message::Builder::new_default()
        };
        result.body.set_root(body).unwrap();
        result
    }
}

impl calculator::function::Server for FunctionImpl {
    fn call(&mut self,
            params: calculator::function::CallParams,
            mut results: calculator::function::CallResults)
        -> Promise<calculator::function::CallResults, Error>
    {
        let params = pry!(params.get().get_params());
        if params.len() != self.param_count {
            Promise::err(Error::failed(
                format!("Expect {} parameters but got {}.", self.param_count, params.len())))
        } else {
            evaluate_impl(
                pry!(self.body.get_root::<calculator::expression::Builder>()).as_reader(),
                Some(params)).map(move |v| {
                    results.get().set_value(v);
                    Ok(results)
                })
        }
    }
}

#[derive(Clone, Copy)]
pub struct OperatorImpl {
    op: calculator::Operator,
}

impl calculator::function::Server for OperatorImpl {
    fn call(&mut self,
            params: calculator::function::CallParams,
            mut results: calculator::function::CallResults)
            -> Promise<calculator::function::CallResults, Error>
    {
        let params = pry!(params.get().get_params());
        if params.len() != 2 {
            Promise::err(Error::failed("Wrong number of paramters.".to_string()))
        } else {
            let v = match self.op {
                calculator::Operator::Add =>       params.get(0) + params.get(1),
                calculator::Operator::Subtract =>  params.get(0) - params.get(1),
                calculator::Operator::Multiply =>  params.get(0) * params.get(1),
                calculator::Operator::Divide =>    params.get(0) / params.get(1),
            };
            results.get().set_value(v);
            Promise::ok(results)
        }
    }
}

struct CalculatorImpl;

impl calculator::Server for CalculatorImpl {
    fn evaluate(&mut self,
                params: calculator::EvaluateParams,
                mut results: calculator::EvaluateResults)
                -> Promise<calculator::EvaluateResults, Error>
    {
        evaluate_impl(pry!(params.get().get_expression()), None).map(move |v| {
            results.get().set_value(
                calculator::value::ToClient::new(ValueImpl::new(v)).from_server::<LocalClient>());
            Ok(results)
        })
    }
    fn def_function(&mut self,
                    params: calculator::DefFunctionParams,
                    mut results: calculator::DefFunctionResults)
                    -> Promise<calculator::DefFunctionResults, Error>
    {
        results.get().set_func(
            calculator::function::ToClient::new(
                FunctionImpl::new(params.get().get_param_count() as u32, pry!(params.get().get_body())))
                .from_server::<LocalClient>());
        Promise::ok(results)
    }
    fn get_operator(&mut self,
                    params: calculator::GetOperatorParams,
                    mut results: calculator::GetOperatorResults)
                    -> Promise<calculator::GetOperatorResults, Error>
    {
        let op = pry!(params.get().get_op());
        results.get().set_func(
            calculator::function::ToClient::new(OperatorImpl {op : op}).from_server::<LocalClient>());
        Promise::ok(results)
    }
}

pub fn main() {
    let args : Vec<String> = ::std::env::args().collect();
    if args.len() != 3 {
        println!("usage: {} server ADDRESS[:PORT]", args[0]);
        return;
    }

    //let rpc_server = EzRpcServer::new(&*args[2]).unwrap();

    // There's got to be a better way to do this.
    //let calculator = Box::new(calculator::ServerDispatch { server : Box::new(CalculatorImpl)});

    //let _ = rpc_server.serve(calculator);
}
<|endoftext|>


<commit_before>use std::borrow::Borrow;
use std::env;
use std::ffi::OsStr;
use std::path::{Path, PathBuf};
use std::process::{self, Command};

fn run_command_or_fail<P, S>(dir: &str, cmd: P, args: &[S])
where
    P: AsRef<Path>,
    S: Borrow<str> + AsRef<OsStr>,
{
    let cmd = cmd.as_ref();
    let cmd = if cmd.components().count() > 1 && cmd.is_relative() {
        // If `cmd` is a relative path (and not a bare command that should be
        // looked up in PATH), absolutize it relative to `dir`, as otherwise the
        // behavior of std::process::Command is undefined.
        // https://github.com/rust-lang/rust/issues/37868
        PathBuf::from(dir)
            .join(cmd)
            .canonicalize()
            .expect("canonicalization failed")
    } else {
        PathBuf::from(cmd)
    };
    eprintln!(
        "Running command: \"{} {}\" in dir: {}",
        cmd.display(),
        args.join(" "),
        dir
    );
    let ret = Command::new(cmd).current_dir(dir).args(args).status();
    match ret.map(|status| (status.success(), status.code())) {
        Ok((true, _)) => (),
        Ok((false, Some(c))) => panic!("Command failed with error code {}", c),
        Ok((false, None)) => panic!("Command got killed"),
        Err(e) => panic!("Command failed with error: {}", e),
    }
}

fn main() {
    if env::var("CARGO_FEATURE_DYNAMIC_LINKING").is_ok() {
        eprintln!("librdkafka will be linked dynamically");

        let librdkafka_version = match env!("CARGO_PKG_VERSION")
            .split('+')
            .collect::<Vec<_>>()
            .as_slice()
        {
            [_rdsys_version, librdkafka_version] => *librdkafka_version,
            _ => panic!("Version format is not valid"),
        };

        let pkg_probe = pkg_config::Config::new()
            .cargo_metadata(true)
            .atleast_version(librdkafka_version)
            .probe("rdkafka");

        match pkg_probe {
            Ok(library) => {
                eprintln!("librdkafka found on the system:");
                eprintln!("  Name: {:?}", library.libs);
                eprintln!("  Path: {:?}", library.link_paths);
                eprintln!("  Version: {}", library.version);
            }
            Err(err) => {
                eprintln!(
                    "librdkafka {} cannot be found on the system: {}",
                    librdkafka_version, err
                );
                eprintln!("Dynamic linking failed. Exiting.");
                process::exit(1);
            }
        }
    } else {
        if !Path::new("librdkafka/LICENSE").exists() {
            eprintln!("Setting up submodules");
            run_command_or_fail("../", "git", &["submodule", "update", "--init"]);
        }
        eprintln!("Building and linking librdkafka statically");
        build_librdkafka();
    }
}

#[cfg(not(feature = "cmake-build"))]
fn build_librdkafka() {
    let mut configure_flags: Vec<String> = Vec::new();

    let mut cflags = Vec::new();
    if let Ok(var) = env::var("CFLAGS") {
        cflags.push(var);
    }

    let mut ldflags = Vec::new();
    if let Ok(var) = env::var("LDFLAGS") {
        ldflags.push(var);
    }

    if env::var("CARGO_FEATURE_SSL").is_ok() {
        configure_flags.push("--enable-ssl".into());
        if let Ok(openssl_root) = env::var("DEP_OPENSSL_ROOT") {
            cflags.push(format!("-I{}/include", openssl_root));
            ldflags.push(format!("-L{}/lib", openssl_root));
        }
    } else {
        configure_flags.push("--disable-ssl".into());
    }

    if env::var("CARGO_FEATURE_GSSAPI").is_ok() {
        configure_flags.push("--enable-gssapi".into());
        if let Ok(sasl2_root) = env::var("DEP_SASL2_ROOT") {
            cflags.push(format!("-I{}/include", sasl2_root));
            ldflags.push(format!("-L{}/build", sasl2_root));
        }
    } else {
        configure_flags.push("--disable-gssapi".into());
    }

    if env::var("CARGO_FEATURE_LIBZ").is_ok() {
        // There is no --enable-zlib option, but it is enabled by default.
        if let Ok(z_root) = env::var("DEP_Z_ROOT") {
            cflags.push(format!("-I{}/include", z_root));
            ldflags.push(format!("-L{}/build", z_root));
        }
    } else {
        configure_flags.push("--disable-zlib".into());
    }

    if env::var("CARGO_FEATURE_ZSTD").is_ok() {
        configure_flags.push("--enable-zstd".into());
        if let Ok(zstd_root) = env::var("DEP_ZSTD_ROOT") {
            cflags.push(format!("-I{}/include", zstd_root));
            ldflags.push(format!("-L{}", zstd_root));
        }
    } else {
        configure_flags.push("--disable-zstd".into());
    }

    if env::var("CARGO_FEATURE_EXTERNAL_LZ4").is_ok() {
        configure_flags.push("--enable-lz4-ext".into());
        if let Ok(lz4_root) = env::var("DEP_LZ4_ROOT") {
            cflags.push(format!("-I{}/include", lz4_root));
            ldflags.push(format!("-L{}", lz4_root));
        }
    } else {
        configure_flags.push("--disable-lz4-ext".into());
    }

    env::set_var("CFLAGS", cflags.join(" "));
    env::set_var("LDFLAGS", ldflags.join(" "));

    let out_dir = env::var("OUT_DIR").expect("OUT_DIR missing");

    if !Path::new(&out_dir).join("LICENSE").exists() {
        // We're not allowed to build in-tree directly, as ~/.cargo/registry is
        // globally shared. mklove doesn't support out-of-tree builds [0], so we
        // work around the issue by creating a clone of librdkafka inside of
        // OUT_DIR, and build inside of *that* tree.
        //
        // https://github.com/edenhill/mklove/issues/17
        println!("Cloning librdkafka");
        run_command_or_fail(".", "cp", &["-a", "librdkafka/.", &out_dir]);
    }

    println!("Configuring librdkafka");
    run_command_or_fail(&out_dir, "./configure", configure_flags.as_slice());

    println!("Compiling librdkafka");
    env::set_var(
        "MAKEFLAGS",
        env::var_os("CARGO_MAKEFLAGS").expect("CARGO_MAKEFLAGS env var missing"),
    );
    run_command_or_fail(
        &out_dir,
        if cfg!(target_os = "freebsd") {
            "gmake"
        } else {
            "make"
        },
        &["libs"],
    );

    println!("cargo:rustc-link-search=native={}/src", out_dir);
    println!("cargo:rustc-link-lib=static=rdkafka");
    println!("cargo:root={}", out_dir);
}

#[cfg(feature = "cmake-build")]
fn build_librdkafka() {
    let mut config = cmake::Config::new("librdkafka");

    config
        .define("RDKAFKA_BUILD_STATIC", "1")
        .define("RDKAFKA_BUILD_TESTS", "0")
        .define("RDKAFKA_BUILD_EXAMPLES", "0")
        // CMAKE_INSTALL_LIBDIR is inferred as "lib64" on some platforms, but we
        // want a stable location that we can add to the linker search path.
        // Since we're not actually installing to /usr or /usr/local, there's no
        // harm to always using "lib" here.
        .define("CMAKE_INSTALL_LIBDIR", "lib");

    if env::var("CARGO_FEATURE_LIBZ").is_ok() {
        config.define("WITH_ZLIB", "1");
        config.register_dep("z");
        if let Ok(z_root) = env::var("DEP_Z_ROOT") {
            env::set_var("CMAKE_LIBRARY_PATH", format!("{}/build", z_root));
        }
    } else {
        config.define("WITH_ZLIB", "0");
    }

    if env::var("CARGO_FEATURE_SSL").is_ok() {
        config.define("WITH_SSL", "1");
        config.define("WITH_SASL_SCRAM", "1");
        config.define("WITH_SASL_OAUTHBEARER", "1");
        config.register_dep("openssl");
    } else {
        config.define("WITH_SSL", "0");
    }

    if env::var("CARGO_FEATURE_GSSAPI").is_ok() {
        config.define("WITH_SASL", "1");
        config.register_dep("sasl2");
        if let Ok(sasl2_root) = env::var("DEP_SASL2_ROOT") {
            config.cflag(format!("-I{}/include", sasl2_root));
            config.cxxflag(format!("-I{}/include", sasl2_root));
        }
    } else {
        config.define("WITH_SASL", "0");
    }

    if env::var("CARGO_FEATURE_ZSTD").is_ok() {
        config.define("WITH_ZSTD", "1");
        config.register_dep("zstd");
    } else {
        config.define("WITH_ZSTD", "0");
    }

    if env::var("CARGO_FEATURE_EXTERNAL_LZ4").is_ok() {
        config.define("ENABLE_LZ4_EXT", "1");
        config.register_dep("lz4");
    } else {
        config.define("ENABLE_LZ4_EXT", "0");
    }

    if let Ok(system_name) = env::var("CMAKE_SYSTEM_NAME") {
        config.define("CMAKE_SYSTEM_NAME", system_name);
    }

    println!("Configuring and compiling librdkafka");
    let dst = config.build();

    println!("cargo:rustc-link-search=native={}/lib", dst.display());
    println!("cargo:rustc-link-lib=static=rdkafka");
}
<commit_msg>rdkafka-sys: make CARGO_MAKEFLAGS optional<commit_after>use std::borrow::Borrow;
use std::env;
use std::ffi::OsStr;
use std::path::{Path, PathBuf};
use std::process::{self, Command};

fn run_command_or_fail<P, S>(dir: &str, cmd: P, args: &[S])
where
    P: AsRef<Path>,
    S: Borrow<str> + AsRef<OsStr>,
{
    let cmd = cmd.as_ref();
    let cmd = if cmd.components().count() > 1 && cmd.is_relative() {
        // If `cmd` is a relative path (and not a bare command that should be
        // looked up in PATH), absolutize it relative to `dir`, as otherwise the
        // behavior of std::process::Command is undefined.
        // https://github.com/rust-lang/rust/issues/37868
        PathBuf::from(dir)
            .join(cmd)
            .canonicalize()
            .expect("canonicalization failed")
    } else {
        PathBuf::from(cmd)
    };
    eprintln!(
        "Running command: \"{} {}\" in dir: {}",
        cmd.display(),
        args.join(" "),
        dir
    );
    let ret = Command::new(cmd).current_dir(dir).args(args).status();
    match ret.map(|status| (status.success(), status.code())) {
        Ok((true, _)) => (),
        Ok((false, Some(c))) => panic!("Command failed with error code {}", c),
        Ok((false, None)) => panic!("Command got killed"),
        Err(e) => panic!("Command failed with error: {}", e),
    }
}

fn main() {
    if env::var("CARGO_FEATURE_DYNAMIC_LINKING").is_ok() {
        eprintln!("librdkafka will be linked dynamically");

        let librdkafka_version = match env!("CARGO_PKG_VERSION")
            .split('+')
            .collect::<Vec<_>>()
            .as_slice()
        {
            [_rdsys_version, librdkafka_version] => *librdkafka_version,
            _ => panic!("Version format is not valid"),
        };

        let pkg_probe = pkg_config::Config::new()
            .cargo_metadata(true)
            .atleast_version(librdkafka_version)
            .probe("rdkafka");

        match pkg_probe {
            Ok(library) => {
                eprintln!("librdkafka found on the system:");
                eprintln!("  Name: {:?}", library.libs);
                eprintln!("  Path: {:?}", library.link_paths);
                eprintln!("  Version: {}", library.version);
            }
            Err(err) => {
                eprintln!(
                    "librdkafka {} cannot be found on the system: {}",
                    librdkafka_version, err
                );
                eprintln!("Dynamic linking failed. Exiting.");
                process::exit(1);
            }
        }
    } else {
        if !Path::new("librdkafka/LICENSE").exists() {
            eprintln!("Setting up submodules");
            run_command_or_fail("../", "git", &["submodule", "update", "--init"]);
        }
        eprintln!("Building and linking librdkafka statically");
        build_librdkafka();
    }
}

#[cfg(not(feature = "cmake-build"))]
fn build_librdkafka() {
    let mut configure_flags: Vec<String> = Vec::new();

    let mut cflags = Vec::new();
    if let Ok(var) = env::var("CFLAGS") {
        cflags.push(var);
    }

    let mut ldflags = Vec::new();
    if let Ok(var) = env::var("LDFLAGS") {
        ldflags.push(var);
    }

    if env::var("CARGO_FEATURE_SSL").is_ok() {
        configure_flags.push("--enable-ssl".into());
        if let Ok(openssl_root) = env::var("DEP_OPENSSL_ROOT") {
            cflags.push(format!("-I{}/include", openssl_root));
            ldflags.push(format!("-L{}/lib", openssl_root));
        }
    } else {
        configure_flags.push("--disable-ssl".into());
    }

    if env::var("CARGO_FEATURE_GSSAPI").is_ok() {
        configure_flags.push("--enable-gssapi".into());
        if let Ok(sasl2_root) = env::var("DEP_SASL2_ROOT") {
            cflags.push(format!("-I{}/include", sasl2_root));
            ldflags.push(format!("-L{}/build", sasl2_root));
        }
    } else {
        configure_flags.push("--disable-gssapi".into());
    }

    if env::var("CARGO_FEATURE_LIBZ").is_ok() {
        // There is no --enable-zlib option, but it is enabled by default.
        if let Ok(z_root) = env::var("DEP_Z_ROOT") {
            cflags.push(format!("-I{}/include", z_root));
            ldflags.push(format!("-L{}/build", z_root));
        }
    } else {
        configure_flags.push("--disable-zlib".into());
    }

    if env::var("CARGO_FEATURE_ZSTD").is_ok() {
        configure_flags.push("--enable-zstd".into());
        if let Ok(zstd_root) = env::var("DEP_ZSTD_ROOT") {
            cflags.push(format!("-I{}/include", zstd_root));
            ldflags.push(format!("-L{}", zstd_root));
        }
    } else {
        configure_flags.push("--disable-zstd".into());
    }

    if env::var("CARGO_FEATURE_EXTERNAL_LZ4").is_ok() {
        configure_flags.push("--enable-lz4-ext".into());
        if let Ok(lz4_root) = env::var("DEP_LZ4_ROOT") {
            cflags.push(format!("-I{}/include", lz4_root));
            ldflags.push(format!("-L{}", lz4_root));
        }
    } else {
        configure_flags.push("--disable-lz4-ext".into());
    }

    env::set_var("CFLAGS", cflags.join(" "));
    env::set_var("LDFLAGS", ldflags.join(" "));

    let out_dir = env::var("OUT_DIR").expect("OUT_DIR missing");

    if !Path::new(&out_dir).join("LICENSE").exists() {
        // We're not allowed to build in-tree directly, as ~/.cargo/registry is
        // globally shared. mklove doesn't support out-of-tree builds [0], so we
        // work around the issue by creating a clone of librdkafka inside of
        // OUT_DIR, and build inside of *that* tree.
        //
        // https://github.com/edenhill/mklove/issues/17
        println!("Cloning librdkafka");
        run_command_or_fail(".", "cp", &["-a", "librdkafka/.", &out_dir]);
    }

    println!("Configuring librdkafka");
    run_command_or_fail(&out_dir, "./configure", configure_flags.as_slice());

    println!("Compiling librdkafka");
    if let Some(makeflags) = env::var_os("CARGO_MAKEFLAGS") {
        env::set_var("MAKEFLAGS", makeflags);
    }
    run_command_or_fail(
        &out_dir,
        if cfg!(target_os = "freebsd") {
            "gmake"
        } else {
            "make"
        },
        &["libs"],
    );

    println!("cargo:rustc-link-search=native={}/src", out_dir);
    println!("cargo:rustc-link-lib=static=rdkafka");
    println!("cargo:root={}", out_dir);
}

#[cfg(feature = "cmake-build")]
fn build_librdkafka() {
    let mut config = cmake::Config::new("librdkafka");

    config
        .define("RDKAFKA_BUILD_STATIC", "1")
        .define("RDKAFKA_BUILD_TESTS", "0")
        .define("RDKAFKA_BUILD_EXAMPLES", "0")
        // CMAKE_INSTALL_LIBDIR is inferred as "lib64" on some platforms, but we
        // want a stable location that we can add to the linker search path.
        // Since we're not actually installing to /usr or /usr/local, there's no
        // harm to always using "lib" here.
        .define("CMAKE_INSTALL_LIBDIR", "lib");

    if env::var("CARGO_FEATURE_LIBZ").is_ok() {
        config.define("WITH_ZLIB", "1");
        config.register_dep("z");
        if let Ok(z_root) = env::var("DEP_Z_ROOT") {
            env::set_var("CMAKE_LIBRARY_PATH", format!("{}/build", z_root));
        }
    } else {
        config.define("WITH_ZLIB", "0");
    }

    if env::var("CARGO_FEATURE_SSL").is_ok() {
        config.define("WITH_SSL", "1");
        config.define("WITH_SASL_SCRAM", "1");
        config.define("WITH_SASL_OAUTHBEARER", "1");
        config.register_dep("openssl");
    } else {
        config.define("WITH_SSL", "0");
    }

    if env::var("CARGO_FEATURE_GSSAPI").is_ok() {
        config.define("WITH_SASL", "1");
        config.register_dep("sasl2");
        if let Ok(sasl2_root) = env::var("DEP_SASL2_ROOT") {
            config.cflag(format!("-I{}/include", sasl2_root));
            config.cxxflag(format!("-I{}/include", sasl2_root));
        }
    } else {
        config.define("WITH_SASL", "0");
    }

    if env::var("CARGO_FEATURE_ZSTD").is_ok() {
        config.define("WITH_ZSTD", "1");
        config.register_dep("zstd");
    } else {
        config.define("WITH_ZSTD", "0");
    }

    if env::var("CARGO_FEATURE_EXTERNAL_LZ4").is_ok() {
        config.define("ENABLE_LZ4_EXT", "1");
        config.register_dep("lz4");
    } else {
        config.define("ENABLE_LZ4_EXT", "0");
    }

    if let Ok(system_name) = env::var("CMAKE_SYSTEM_NAME") {
        config.define("CMAKE_SYSTEM_NAME", system_name);
    }

    println!("Configuring and compiling librdkafka");
    let dst = config.build();

    println!("cargo:rustc-link-search=native={}/lib", dst.display());
    println!("cargo:rustc-link-lib=static=rdkafka");
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::io::{self, Write};
use std::mem;
use process::{Process, Context};
use instruction::parameter::Register;
use instruction::Instruction;
use instruction::Error as InstrError;
use champion::Champion;
use arena::{Arena, ArenaIndex};
use core::{MEM_SIZE, CYCLE_TO_DIE, CYCLE_DELTA, NBR_LIVE, MAX_CHECKS};

pub struct Machine {
    pub arena: Arena,
    champions: BTreeMap<i32, Champion>,
    processes: Vec<Process>,
    last_living_champion: Option<i32>,

    number_of_lives: usize,
    cycles_to_die: usize,
    cycles: usize,
    cycle_checks: usize,
}

impl Machine {
    pub fn new(champions: BTreeMap<i32, Champion>) -> Self {
        let mut arena = Arena::new();
        let mut arena_index = ArenaIndex::zero();
        let mut processes = Vec::with_capacity(champions.len());
        let step = MEM_SIZE.checked_div(champions.len()).unwrap_or(0);

        for (id, &Champion{ ref program, .. }) in &champions {
            {
                let mut writer = arena.write_to(arena_index);
                io::copy(&mut program.as_slice(), &mut writer).unwrap();
            }

            let mut context = Context::new(arena_index);
            let reg = Register::new(1).unwrap();
            context.registers[reg] = *id;

            let process = Process::new(context, &arena);
            trace!("push process {:?}", process);
            processes.push(process);

            arena_index = arena_index.advance_by(step);
        }

        Machine {
            arena: arena,
            champions: champions,
            processes: processes,
            last_living_champion: None,
            number_of_lives: 0,
            cycles_to_die: CYCLE_TO_DIE,
            cycles: 0,
            cycle_checks: 0,
        }
    }

    pub fn live_champion(&mut self, champion_id: i32) {
        if self.champions.get(&champion_id).is_some() {
            self.last_living_champion = Some(champion_id);
            self.number_of_lives += 1;
        }
    }

    pub fn last_living_champion(&self) -> Option<(i32, &Champion)> {
        self.last_living_champion
            .and_then(|id| self.champions.get(&id)
            .map(|champ| (id, champ)))
    }

    pub fn new_process(&mut self, context: Context) {
        let process = Process::new(context, &self.arena);
        trace!("push process {:?}", process);
        self.processes.push(process)
    }

    pub fn cycle_execute<'a, W: Write>(&'a mut self, output: &'a mut W) -> CycleExecute<'a, W> {
        CycleExecute { machine: self, output }
    }
}

pub struct CycleExecute<'a, W: 'a + Write> {
    machine: &'a mut Machine,
    output: &'a mut W,
}

#[derive(Debug, Clone, Copy, Default)]
pub struct CycleInfo {
    pub remaining_processes: usize,
    pub cycles_to_die: usize,
    pub last_living_champion: Option<i32>,
}

impl<'a, W: 'a + Write> Iterator for CycleExecute<'a, W> {
    type Item = io::Result<CycleInfo>;

    fn next(&mut self) -> Option<Self::Item> {
        let mut processes = Vec::new();
        mem::swap(&mut processes, &mut self.machine.processes);

        let mut cycle_info = CycleInfo::default();

        self.machine.cycles += 1;
        if self.machine.cycles >= self.machine.cycles_to_die {
            self.machine.cycle_checks += 1;
            processes.retain(|p| p.context.cycle_since_last_live < self.machine.cycles_to_die);
            if self.machine.number_of_lives >= NBR_LIVE || self.machine.cycle_checks >= MAX_CHECKS {
                self.machine.cycles_to_die = self.machine.cycles_to_die.saturating_sub(CYCLE_DELTA);
                self.machine.cycle_checks = 0;
            }
            self.machine.cycles = 0;
            self.machine.number_of_lives = 0;
        }

        cycle_info.cycles_to_die = self.machine.cycles_to_die - self.machine.cycles;

        for process in processes.iter_mut().rev() {
            let ctx = &mut process.context;
            process.remaining_cycles -= 1;
            ctx.cycle_since_last_live += 1;

            if process.remaining_cycles == 0 {
                let instr = &mut process.instruction;
                match *instr {
                    Some(instr) => if let Err(e) = instr.execute(&mut self.machine, ctx, &mut self.output) {
                        return Some(Err(e))
                    },
                    None => Instruction::execute_noop(ctx)
                }
                trace!("execute {:?}", instr);

                let reader = self.machine.arena.read_from(ctx.pc);
                *instr = match Instruction::read_from(reader) {
                    Ok(instr) => Some(instr),
                    Err(InstrError::Io(e)) => return Some(Err(e)),
                    Err(_) => None,
                };
                process.remaining_cycles = instr.map(|instr| instr.cycle_cost()).unwrap_or(1);
            }
        }
        self.machine.processes.append(&mut processes);
        cycle_info.remaining_processes = self.machine.processes.len();
        cycle_info.last_living_champion = self.machine.last_living_champion;

        if !self.machine.processes.is_empty() {
            Some(Ok(cycle_info))
        } else { None }
    }
}
<commit_msg>feat: Add a champion live counter to CycleInfo<commit_after>use std::collections::{BTreeMap, HashMap};
use std::io::{self, Write};
use std::mem;
use process::{Process, Context};
use instruction::parameter::{Direct, Register};
use instruction::Instruction;
use instruction::Error as InstrError;
use champion::Champion;
use arena::{Arena, ArenaIndex};
use core::{MEM_SIZE, CYCLE_TO_DIE, CYCLE_DELTA, NBR_LIVE, MAX_CHECKS};

pub struct Machine {
    pub arena: Arena,
    champions: BTreeMap<i32, Champion>,
    processes: Vec<Process>,
    last_living_champion: Option<i32>,

    number_of_lives: usize,
    cycles_to_die: usize,
    cycles: usize,
    cycle_checks: usize,
}

impl Machine {
    pub fn new(champions: BTreeMap<i32, Champion>) -> Self {
        let mut arena = Arena::new();
        let mut arena_index = ArenaIndex::zero();
        let mut processes = Vec::with_capacity(champions.len());
        let step = MEM_SIZE.checked_div(champions.len()).unwrap_or(0);

        for (id, &Champion{ ref program, .. }) in &champions {
            {
                let mut writer = arena.write_to(arena_index);
                io::copy(&mut program.as_slice(), &mut writer).unwrap();
            }

            let mut context = Context::new(arena_index);
            let reg = Register::new(1).unwrap();
            context.registers[reg] = *id;

            let process = Process::new(context, &arena);
            trace!("push process {:?}", process);
            processes.push(process);

            arena_index = arena_index.advance_by(step);
        }

        Machine {
            arena: arena,
            champions: champions,
            processes: processes,
            last_living_champion: None,
            number_of_lives: 0,
            cycles_to_die: CYCLE_TO_DIE,
            cycles: 0,
            cycle_checks: 0,
        }
    }

    pub fn live_champion(&mut self, champion_id: i32) {
        if self.champions.get(&champion_id).is_some() {
            self.last_living_champion = Some(champion_id);
            self.number_of_lives += 1;
        }
    }

    pub fn last_living_champion(&self) -> Option<(i32, &Champion)> {
        self.last_living_champion
            .and_then(|id| self.champions.get(&id)
            .map(|champ| (id, champ)))
    }

    pub fn new_process(&mut self, context: Context) {
        let process = Process::new(context, &self.arena);
        trace!("push process {:?}", process);
        self.processes.push(process)
    }

    pub fn cycle_execute<'a, W: Write>(&'a mut self, output: &'a mut W) -> CycleExecute<'a, W> {
        CycleExecute { machine: self, output }
    }
}

pub struct CycleExecute<'a, W: 'a + Write> {
    machine: &'a mut Machine,
    output: &'a mut W,
}

#[derive(Debug, Clone, Default)]
pub struct CycleInfo {
    pub remaining_processes: usize,
    pub cycles_to_die: usize,
    pub lives_counter: HashMap<i32, usize>,
    pub last_living_champion: Option<i32>,
}

impl<'a, W: 'a + Write> Iterator for CycleExecute<'a, W> {
    type Item = io::Result<CycleInfo>;

    fn next(&mut self) -> Option<Self::Item> {
        let mut processes = Vec::new();
        mem::swap(&mut processes, &mut self.machine.processes);

        let mut cycle_info = CycleInfo {
            lives_counter: HashMap::with_capacity(self.machine.champions.len()),
            ..Default::default()
        };

        self.machine.cycles += 1;
        if self.machine.cycles >= self.machine.cycles_to_die {
            self.machine.cycle_checks += 1;
            processes.retain(|p| p.context.cycle_since_last_live < self.machine.cycles_to_die);
            if self.machine.number_of_lives >= NBR_LIVE || self.machine.cycle_checks >= MAX_CHECKS {
                self.machine.cycles_to_die = self.machine.cycles_to_die.saturating_sub(CYCLE_DELTA);
                self.machine.cycle_checks = 0;
            }
            self.machine.cycles = 0;
            self.machine.number_of_lives = 0;
        }

        cycle_info.cycles_to_die = self.machine.cycles_to_die - self.machine.cycles;

        for process in processes.iter_mut().rev() {
            let ctx = &mut process.context;
            process.remaining_cycles -= 1;
            ctx.cycle_since_last_live += 1;

            if process.remaining_cycles == 0 {
                let instr = &mut process.instruction;
                match *instr {
                    Some(instr) => if let Err(e) = instr.execute(&mut self.machine, ctx, &mut self.output) {
                        return Some(Err(e))
                    },
                    None => Instruction::execute_noop(ctx)
                }
                trace!("execute {:?}", instr);

                if let Some(Instruction::Live(Direct(champion_id))) = *instr {
                    if self.machine.champions.contains_key(&champion_id) {
                        let counter = cycle_info.lives_counter.entry(champion_id).or_insert(0);
                        *counter += 1;
                    }
                }

                let reader = self.machine.arena.read_from(ctx.pc);
                *instr = match Instruction::read_from(reader) {
                    Ok(instr) => Some(instr),
                    Err(InstrError::Io(e)) => return Some(Err(e)),
                    Err(_) => None,
                };
                process.remaining_cycles = instr.map(|instr| instr.cycle_cost()).unwrap_or(1);
            }
        }
        self.machine.processes.append(&mut processes);
        cycle_info.remaining_processes = self.machine.processes.len();
        cycle_info.last_living_champion = self.machine.last_living_champion;

        if !self.machine.processes.is_empty() {
            Some(Ok(cycle_info))
        } else { None }
    }
}
<|endoftext|>


<commit_before>extern crate cairo;

use std::fmt;
use std::str::FromStr;

use parsers;

/* Keep this in sync with rsvg-private.h:RsvgViewBox */
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct RsvgViewBox {
    pub rect:   cairo::Rectangle,
    pub active: bool
}

impl RsvgViewBox {
    pub fn new_inactive () -> RsvgViewBox {
        RsvgViewBox {
            rect: cairo::Rectangle { x: 0.0,
                                     y: 0.0,
                                     width: 0.0,
                                     height: 0.0 },
            active: false
        }
    }
}

impl Default for RsvgViewBox {
    fn default () -> RsvgViewBox {
        RsvgViewBox::new_inactive ()
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ParseViewBoxError {
    NegativeWidthOrHeight, // In "x y w h", w and h must be nonnegative
    Error                  // General parsing error
}

impl fmt::Display for ParseViewBoxError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ParseViewBoxError::NegativeWidthOrHeight => {
                "width and height must not be negative".fmt (f)
            },

            ParseViewBoxError::Error => {
                "string does not match 'x [,] y [,] w [,] h'".fmt (f)
            }
        }
    }
}

impl FromStr for RsvgViewBox {
    type Err = ParseViewBoxError;

    fn from_str (s: &str) -> Result<RsvgViewBox, ParseViewBoxError> {
        let result = parsers::view_box (s.as_bytes ()).to_full_result ();

        match result {
            Ok ((x, y, w, h)) => {
                if w >= 0.0 && h >= 0.0 {
                    Ok (RsvgViewBox { rect: cairo::Rectangle { x: x,
                                                               y: y,
                                                               width: w,
                                                               height: h },
                                      active: true })
                } else {
                    Err (ParseViewBoxError::NegativeWidthOrHeight)
                }
            },

            Err (_) => {
                Err (ParseViewBoxError::Error)
            }
        }
    }
}

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

    #[test]
    fn parses_valid_viewboxes () {
        assert_eq! (RsvgViewBox::from_str ("1 2 3 4"),
                    Ok (RsvgViewBox { rect: cairo::Rectangle { x: 1.0,
                                                               y: 2.0,
                                                               width: 3.0,
                                                               height: 4.0 },
                                      active: true }));

        assert_eq! (RsvgViewBox::from_str ("-1.5 -2.5e1,34,56e2"),
                    Ok (RsvgViewBox { rect: cairo::Rectangle { x: -1.5,
                                                               y: -25.0,
                                                               width: 34.0,
                                                               height: 5600.0 },
                                      active: true }));
    }

    #[test]
    fn parsing_invalid_viewboxes_yields_error () {
        assert_eq! (RsvgViewBox::from_str (""),
                    Err (ParseViewBoxError::Error));

        assert_eq! (RsvgViewBox::from_str ("1,2,-3,-4"),
                    Err (ParseViewBoxError::NegativeWidthOrHeight));

        assert_eq! (RsvgViewBox::from_str ("qwerasdfzxcv"),
                    Err (ParseViewBoxError::Error));

        assert_eq! (RsvgViewBox::from_str ("1 2 3 4 5"),
                    Err (ParseViewBoxError::Error));
    }
}
<commit_msg>viewbox.rs: Trim whitespace before parsing the viewBox string<commit_after>extern crate cairo;

use std::fmt;
use std::str::FromStr;

use parsers;

/* Keep this in sync with rsvg-private.h:RsvgViewBox */
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct RsvgViewBox {
    pub rect:   cairo::Rectangle,
    pub active: bool
}

impl RsvgViewBox {
    pub fn new_inactive () -> RsvgViewBox {
        RsvgViewBox {
            rect: cairo::Rectangle { x: 0.0,
                                     y: 0.0,
                                     width: 0.0,
                                     height: 0.0 },
            active: false
        }
    }
}

impl Default for RsvgViewBox {
    fn default () -> RsvgViewBox {
        RsvgViewBox::new_inactive ()
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ParseViewBoxError {
    NegativeWidthOrHeight, // In "x y w h", w and h must be nonnegative
    Error                  // General parsing error
}

impl fmt::Display for ParseViewBoxError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ParseViewBoxError::NegativeWidthOrHeight => {
                "width and height must not be negative".fmt (f)
            },

            ParseViewBoxError::Error => {
                "string does not match 'x [,] y [,] w [,] h'".fmt (f)
            }
        }
    }
}

impl FromStr for RsvgViewBox {
    type Err = ParseViewBoxError;

    fn from_str (s: &str) -> Result<RsvgViewBox, ParseViewBoxError> {
        let result = parsers::view_box (s.trim ().as_bytes ()).to_full_result ();

        match result {
            Ok ((x, y, w, h)) => {
                if w >= 0.0 && h >= 0.0 {
                    Ok (RsvgViewBox { rect: cairo::Rectangle { x: x,
                                                               y: y,
                                                               width: w,
                                                               height: h },
                                      active: true })
                } else {
                    Err (ParseViewBoxError::NegativeWidthOrHeight)
                }
            },

            Err (_) => {
                Err (ParseViewBoxError::Error)
            }
        }
    }
}

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

    #[test]
    fn parses_valid_viewboxes () {
        assert_eq! (RsvgViewBox::from_str ("  1 2 3 4"),
                    Ok (RsvgViewBox { rect: cairo::Rectangle { x: 1.0,
                                                               y: 2.0,
                                                               width: 3.0,
                                                               height: 4.0 },
                                      active: true }));

        assert_eq! (RsvgViewBox::from_str (" -1.5 -2.5e1,34,56e2  "),
                    Ok (RsvgViewBox { rect: cairo::Rectangle { x: -1.5,
                                                               y: -25.0,
                                                               width: 34.0,
                                                               height: 5600.0 },
                                      active: true }));
    }

    #[test]
    fn parsing_invalid_viewboxes_yields_error () {
        assert_eq! (RsvgViewBox::from_str (""),
                    Err (ParseViewBoxError::Error));

        assert_eq! (RsvgViewBox::from_str (" 1,2,-3,-4 "),
                    Err (ParseViewBoxError::NegativeWidthOrHeight));

        assert_eq! (RsvgViewBox::from_str ("qwerasdfzxcv"),
                    Err (ParseViewBoxError::Error));

        assert_eq! (RsvgViewBox::from_str (" 1 2 3 4   5"),
                    Err (ParseViewBoxError::Error));
    }
}
<|endoftext|>