<commit_before>extern crate tak;

use tak::Game;
use tak::Player;

fn play_no_win(moves: Vec<&str>, game: &mut Game) -> () {
    let mut turn = 0;
    for str in moves {
        println!("{}", str);
        if turn >= 2 {
            let player = if turn % 2 == 0 {
                Player::One
            } else {
                Player::Two
            };
            assert_eq!(game.play(str, player, Some(player)).unwrap(), None);
        } else {
            let player = if turn % 2 == 0 {
                Player::One
            } else {
                Player::Two
            };
            assert_eq!(game.play(str, player, Some(player.other())).unwrap(), None);
        }
        turn += 1;
    }
}

#[test]
fn basic_placement() {
    let mut game = Game::new(5);
    play_no_win(vec!["Fa2", "d1", "Sa1", "Cd3"], &mut game);
    assert_eq!(game.to_string(),
               "_______________\n\
                |  |  |  |  |  \n\
                |  |  |  |  |  \n\
                |  |  |  |C2|  \n\
                |F2|  |  |  |  \n\
                |S1|  |  |F1|  \n\
                P1: 2/20 Flatstones\n\
                P1: 0/1 Capstones\n\
                P2: 1/20 Flatstones\n\
                P2: 1/1 Capstones\n");
}

#[test]
fn basic_movement() {
    let mut game = Game::new(4);
    play_no_win(vec!["a2", "a1", "a1+", "b1", "2a2>11"], &mut game);
    assert_eq!(game.to_string(),
               "____________\n\
                |  |  |  |  \n\
                |  |  |  |  \n\
                |  |F2|F1|  \n\
                |  |F2|  |  \n\
                P1: 1/15 Flatstones\n\
                P1: 0/0 Capstones\n\
                P2: 2/15 Flatstones\n\
                P2: 0/0 Capstones\n");
}

#[test]
fn break_parser() {
    let mut game = Game::new(4);
    match game.play("0a1", Player::One, None) {
        Ok(_) => panic!(""),
        Err(_) => return,
    }
}

#[test]
fn must_own_pile_to_move() {
    let mut game = Game::new(5);
    play_no_win(vec!["a1", "a2", "a2-"], &mut game);
    match game.play("1a1>1", Player::Two, None) {
        Ok(_) => panic!(""),
        Err(_) => return,
    }
}

#[test]
fn invalid_movement_onto_standing() {
    let mut game = Game::new(5);
    play_no_win(vec!["a2", "a4", "Sa1"], &mut game);
    match game.play("a2-", Player::Two, None) {
        Ok(_) => panic!(""),
        Err(_) => return,
    }
}

#[test]
fn starting_order() {
    match Game::new(4).play("a2", Player::One, Some(Player::One)) {
        Ok(_) => panic!(""),
        Err(_) => return,
    }
}

#[test]
fn starting_stone() {
    match Game::new(4).play("Sa2", Player::One, Some(Player::Two)) {
        Ok(_) => panic!(""),
        Err(_) => return,
    }
}

#[test]
fn move_offstage() {
    let mut game = Game::new(5);
    play_no_win(vec!["a1", "a2"], &mut game);
    match game.play("a2<", Player::One, None) {
        Ok(_) => panic!(""),
        Err(_) => return,
    }
}

#[test]
fn under_carry_limit() {
    let mut game = Game::new(5);
    play_no_win(vec!["a1", "a2", "a2-", "b1", "a2", "b1<", "a2-",
                     "b1", "a2", "b1<", "a2-", "b1", "5a1>5"],
                &mut game);
}

#[test]
fn carry_limit() {
    let mut game = Game::new(5);
    play_no_win(vec!["a1", "a2", "a2-", "b1", "a2", "b1<", "a2-",
                     "b1", "a2", "b1<", "a2-", "b1"], &mut game);
    match game.play("6a1>6", Player::One, None) {
        Ok(_) => panic!(""),
        Err(_) => return,
    }
}

#[test]
fn movement_amount() {
    let mut game = Game::new(5);
    play_no_win(vec!["a1", "a2", "a2-", "b1", "a2", "b1<", "a2-",
                     "b1"], &mut game);
    match game.play("4a1>022", Player::One, None) {
        Ok(_) => panic!(""),
        Err(_) => return,
    }
}

#[test]
fn invalid_movement_onto_capstone() {
    let mut game = Game::new(5);
    play_no_win(vec!["a2", "c3", "Ca1"], &mut game);
    match game.play("a2-", Player::Two, None) {
        Ok(_) => panic!(""),
        Err(_) => return,
    }
}

#[test]
fn squash() {
    let mut game = Game::new(5);
    play_no_win(vec!["b2", "b1", "Sa1", "Ca2", "b3", "a2-"],
                &mut game);
    assert_eq!(game.to_string(),
               "_________________________\n\
                |    |    |    |    |    \n\
                |    |    |    |    |    \n\
                |    |F1  |    |    |    \n\
                |    |F2  |    |    |    \n\
                |F1C2|F1  |    |    |    \n\
                P1: 3/20 Flatstones\n\
                P1: 0/1 Capstones\n\
                P2: 1/20 Flatstones\n\
                P2: 1/1 Capstones\n");
}

#[test]
fn win_across() {
    let mut game = Game::new(4);
    let m = vec!["b1", "a1", "a2", "b2", "a3", "b3"];
    play_no_win(m, &mut game);
    assert_eq!(game.play("a4", Player::One, Some(Player::One)).unwrap(), Some(Player::One));
}

#[test]
fn almost() {
    play_no_win(vec!["a2", "a1", "b1", "b2", "c1"],
                &mut Game::new(4));
}

#[test]
fn almost2() {
    play_no_win(vec!["a2", "b1", "c1", "b2", "d1"],
                &mut Game::new(4));
}

#[test]
fn win_up() {
    let mut game = Game::new(4);
    let m = vec!["a2", "a1", "b1", "b2", "c1", "c2"];
    play_no_win(m, &mut game);
    assert_eq!(game.play("d1", Player::One, Some(Player::One)).unwrap(), Some(Player::One));
}

#[test]
fn cant_win_with_standing() {
    let mut game = Game::new(4);
    let m = vec!["a2", "a1", "b1", "b2", "c1", "c2"];
    play_no_win(m, &mut game);
    assert_eq!(game.play("Sd1", Player::One, Some(Player::One)).unwrap(), None);
}

#[test]
fn all_pieces() {
    let mut game = Game::new(4);
    let m = vec!["a2", "a1", "a3", "a4", "b2", "b1", "b4", "b3", "c1", "c2",
                 "c3", "c4", "d2", "d1", "d4", "d1<", "d1", "b1<", "b1", "a2>",
                 "a2", "c2>", "c2", "b3<", "b3", "a4>", "a4", "c4<"];
    play_no_win(m, &mut game);
    assert_eq!(game.play("c4", Player::One, Some(Player::One)).unwrap(), Some(Player::One));
}

#[test]
fn all_pieces_with_cap() {
    let mut game = Game::new(5);
    let m = vec!["e1", "a1", "Ca2", "e1+", "a3", "e2-", "a4", "e1+", "b1", "e2-",
                 "b2", "e1+", "b3", "e2-", "b4", "e1+", "c1", "e2-", "c2", "e1+",
                 "c3", "e2-", "c4", "e1+", "d1", "e2-", "d2", "e1+", "d3", "e2-",
                 "d4", "e1+", "d4<", "e2<", "d3<", "2d2-2", "d4", "3d1<3", "d3",
                 "c1+", "d2", "2c2<2", "d1", "e1"];
    play_no_win(m, &mut game);
    assert_eq!(game.play("e5", Player::One, Some(Player::One)).unwrap(), Some(Player::One));
}

#[test]
fn full_board() {
    let mut game = Game::new(4);
    let m = vec!["a2", "a1", "a3", "a4", "b2", "b1", "b4", "b3", "c1", "c2",
                 "c3", "c4", "d2", "d1", "d4"];
    play_no_win(m, &mut game);
    assert_eq!(game.play("d3", Player::Two, Some(Player::Two)).unwrap(), Some(Player::Two));
}

#[test]
fn cannot_play_too_many_capstones() {
    let mut game = Game::new(5);
    let m = vec!["e1", "a1", "Cc3", "c2"];
    play_no_win(m, &mut game);
    match game.play("Cc4", Player::One, Some(Player::One)) {
        Ok(_) => panic!(""),
        Err(_) => return,
    }
}

#[test]
fn cannot_play_too_many_flats() {
    let mut game = Game::new(5);
    let m = vec!["e1", "a1", "a2", "e1+", "a3", "e2-", "a4", "e1+", "b1", "e2-",
                 "b2", "e1+", "b3", "e2-", "b4", "e1+", "c1", "e2-", "c2", "e1+",
                 "c3", "e2-", "c4", "e1+", "d1", "e2-", "d2", "e1+", "d3", "e2-",
                 "d4", "e1+", "d4<", "e2<", "d3<", "2d2-2", "d4", "3d1<3", "d3",
                 "c1+", "d2", "2c2<2", "d1", "e1"];
    play_no_win(m, &mut game);
    match game.play("e5", Player::One, Some(Player::One)) {
        Ok(_) => panic!(""),
        Err(_) => return,
    }
}

#[test]
fn convoluted_road_win() {
    let mut game = Game::new(6);
    let m = vec!["a2", "a1", "b1", "b2", "c1", "c2", "d1", "e1", "d2", "e2",
                 "d3", "e3", "c3", "e4", "b3", "d4", "b4", "c4", "b5", "a3",
                 "c5", "a4", "d5", "a5", "e5", "a6"];
    play_no_win(m, &mut game);
    assert_eq!(game.play("f5", Player::One, Some(Player::One)).unwrap(), Some(Player::One));
}

#[test]
fn example1() {
    let mut game = Game::new(5);
    let m = vec!["a1", "e1", "c3", "a3", "e3", "a4", "a2", "a5", "b4", "d3",
                 "e2", "e4", "d2", "b2", "b4<", "a3+", "a3", "3a4-12", "a4", "b3",
                 "b4", "b3+", "a4+", "a4", "b3", "2b4-2", "d4", "b5", "2a5-11",
                 "3b3<3", "a5"];
    play_no_win(m, &mut game);
    assert_eq!(game.play("a4+", Player::Two, None).unwrap(), Some(Player::Two));
}
<commit_msg>Modification of tests for increased flatstones<commit_after>extern crate tak;

use tak::Game;
use tak::Player;

fn play_no_win(moves: Vec<&str>, game: &mut Game) -> () {
    let mut turn = 0;
    for str in moves {
        println!("{}", str);
        if turn >= 2 {
            let player = if turn % 2 == 0 {
                Player::One
            } else {
                Player::Two
            };
            assert_eq!(game.play(str, player, Some(player)).unwrap(), None);
        } else {
            let player = if turn % 2 == 0 {
                Player::One
            } else {
                Player::Two
            };
            assert_eq!(game.play(str, player, Some(player.other())).unwrap(), None);
        }
        turn += 1;
    }
}

#[test]
fn basic_placement() {
    let mut game = Game::new(5);
    play_no_win(vec!["Fa2", "d1", "Sa1", "Cd3"], &mut game);
    assert_eq!(game.to_string(),
               "_______________\n\
                |  |  |  |  |  \n\
                |  |  |  |  |  \n\
                |  |  |  |C2|  \n\
                |F2|  |  |  |  \n\
                |S1|  |  |F1|  \n\
                P1: 2/21 Flatstones\n\
                P1: 0/1 Capstones\n\
                P2: 1/21 Flatstones\n\
                P2: 1/1 Capstones\n");
}

#[test]
fn basic_movement() {
    let mut game = Game::new(4);
    play_no_win(vec!["a2", "a1", "a1+", "b1", "2a2>11"], &mut game);
    assert_eq!(game.to_string(),
               "____________\n\
                |  |  |  |  \n\
                |  |  |  |  \n\
                |  |F2|F1|  \n\
                |  |F2|  |  \n\
                P1: 1/15 Flatstones\n\
                P1: 0/0 Capstones\n\
                P2: 2/15 Flatstones\n\
                P2: 0/0 Capstones\n");
}

#[test]
fn break_parser() {
    let mut game = Game::new(4);
    match game.play("0a1", Player::One, None) {
        Ok(_) => panic!(""),
        Err(_) => return,
    }
}

#[test]
fn must_own_pile_to_move() {
    let mut game = Game::new(5);
    play_no_win(vec!["a1", "a2", "a2-"], &mut game);
    match game.play("1a1>1", Player::Two, None) {
        Ok(_) => panic!(""),
        Err(_) => return,
    }
}

#[test]
fn invalid_movement_onto_standing() {
    let mut game = Game::new(5);
    play_no_win(vec!["a2", "a4", "Sa1"], &mut game);
    match game.play("a2-", Player::Two, None) {
        Ok(_) => panic!(""),
        Err(_) => return,
    }
}

#[test]
fn starting_order() {
    match Game::new(4).play("a2", Player::One, Some(Player::One)) {
        Ok(_) => panic!(""),
        Err(_) => return,
    }
}

#[test]
fn starting_stone() {
    match Game::new(4).play("Sa2", Player::One, Some(Player::Two)) {
        Ok(_) => panic!(""),
        Err(_) => return,
    }
}

#[test]
fn move_offstage() {
    let mut game = Game::new(5);
    play_no_win(vec!["a1", "a2"], &mut game);
    match game.play("a2<", Player::One, None) {
        Ok(_) => panic!(""),
        Err(_) => return,
    }
}

#[test]
fn under_carry_limit() {
    let mut game = Game::new(5);
    play_no_win(vec!["a1", "a2", "a2-", "b1", "a2", "b1<", "a2-",
                     "b1", "a2", "b1<", "a2-", "b1", "5a1>5"],
                &mut game);
}

#[test]
fn carry_limit() {
    let mut game = Game::new(5);
    play_no_win(vec!["a1", "a2", "a2-", "b1", "a2", "b1<", "a2-",
                     "b1", "a2", "b1<", "a2-", "b1"], &mut game);
    match game.play("6a1>6", Player::One, None) {
        Ok(_) => panic!(""),
        Err(_) => return,
    }
}

#[test]
fn movement_amount() {
    let mut game = Game::new(5);
    play_no_win(vec!["a1", "a2", "a2-", "b1", "a2", "b1<", "a2-",
                     "b1"], &mut game);
    match game.play("4a1>022", Player::One, None) {
        Ok(_) => panic!(""),
        Err(_) => return,
    }
}

#[test]
fn invalid_movement_onto_capstone() {
    let mut game = Game::new(5);
    play_no_win(vec!["a2", "c3", "Ca1"], &mut game);
    match game.play("a2-", Player::Two, None) {
        Ok(_) => panic!(""),
        Err(_) => return,
    }
}

#[test]
fn squash() {
    let mut game = Game::new(5);
    play_no_win(vec!["b2", "b1", "Sa1", "Ca2", "b3", "a2-"],
                &mut game);
    assert_eq!(game.to_string(),
               "_________________________\n\
                |    |    |    |    |    \n\
                |    |    |    |    |    \n\
                |    |F1  |    |    |    \n\
                |    |F2  |    |    |    \n\
                |F1C2|F1  |    |    |    \n\
                P1: 3/21 Flatstones\n\
                P1: 0/1 Capstones\n\
                P2: 1/21 Flatstones\n\
                P2: 1/1 Capstones\n");
}

#[test]
fn win_across() {
    let mut game = Game::new(4);
    let m = vec!["b1", "a1", "a2", "b2", "a3", "b3"];
    play_no_win(m, &mut game);
    assert_eq!(game.play("a4", Player::One, Some(Player::One)).unwrap(), Some(Player::One));
}

#[test]
fn almost() {
    play_no_win(vec!["a2", "a1", "b1", "b2", "c1"],
                &mut Game::new(4));
}

#[test]
fn almost2() {
    play_no_win(vec!["a2", "b1", "c1", "b2", "d1"],
                &mut Game::new(4));
}

#[test]
fn win_up() {
    let mut game = Game::new(4);
    let m = vec!["a2", "a1", "b1", "b2", "c1", "c2"];
    play_no_win(m, &mut game);
    assert_eq!(game.play("d1", Player::One, Some(Player::One)).unwrap(), Some(Player::One));
}

#[test]
fn cant_win_with_standing() {
    let mut game = Game::new(4);
    let m = vec!["a2", "a1", "b1", "b2", "c1", "c2"];
    play_no_win(m, &mut game);
    assert_eq!(game.play("Sd1", Player::One, Some(Player::One)).unwrap(), None);
}

#[test]
fn all_pieces() {
    let mut game = Game::new(4);
    let m = vec!["a2", "a1", "a3", "a4", "b2", "b1", "b4", "b3", "c1", "c2",
                 "c3", "c4", "d2", "d1", "d4", "d1<", "d1", "b1<", "b1", "a2>",
                 "a2", "c2>", "c2", "b3<", "b3", "a4>", "a4", "c4<"];
    play_no_win(m, &mut game);
    assert_eq!(game.play("c4", Player::One, Some(Player::One)).unwrap(), Some(Player::One));
}

#[test]
fn all_pieces_with_cap() {
    let mut game = Game::new(5);
    let m = vec!["e1", "a1", "Ca2", "e1+", "a3", "e2-", "a4", "e1+", "b1", "e2-",
                 "b2", "e1+", "b3", "e2-", "b4", "e1+", "c1", "e2-", "c2", "e1+",
                 "c3", "e2-", "c4", "e1+", "d1", "e2-", "d2", "e1+", "d3", "e2-",
                 "d4", "e1+", "d4<", "e2<", "d3<", "2d2-2", "d4", "3d1<3", "d3",
                 "c1+", "d2", "2c2<2", "d1", "e1"];
    play_no_win(m, &mut game);
    assert_eq!(game.play("e5", Player::One, Some(Player::One)).unwrap(), Some(Player::One));
}

#[test]
fn full_board() {
    let mut game = Game::new(4);
    let m = vec!["a2", "a1", "a3", "a4", "b2", "b1", "b4", "b3", "c1", "c2",
                 "c3", "c4", "d2", "d1", "d4"];
    play_no_win(m, &mut game);
    assert_eq!(game.play("d3", Player::Two, Some(Player::Two)).unwrap(), Some(Player::Two));
}

#[test]
fn cannot_play_too_many_capstones() {
    let mut game = Game::new(5);
    let m = vec!["e1", "a1", "Cc3", "c2"];
    play_no_win(m, &mut game);
    match game.play("Cc4", Player::One, Some(Player::One)) {
        Ok(_) => panic!(""),
        Err(_) => return,
    }
}

#[test]
fn cannot_play_too_many_flats() {
    let mut game = Game::new(5);
    let m = vec!["e1", "a1", "a2", "e1+", "a3", "e2-", "a4", "e1+", "b1", "e2-",
                 "b2", "e1+", "b3", "e2-", "b4", "e1+", "c1", "e2-", "c2", "e1+",
                 "c3", "e2-", "c4", "e1+", "d1", "e2-", "d2", "e1+", "d3", "e2-",
                 "d4", "e1+", "d4<", "e2<", "d3<", "2d2-2", "d4", "3d1<3", "d3",
                 "c1+", "d2", "2c2<2", "d1", "e1", "c2", "e3"];
    play_no_win(m, &mut game);
    match game.play("e5", Player::One, Some(Player::One)) {
        Ok(_) => panic!(""),
        Err(_) => return,
    }
}

#[test]
fn convoluted_road_win() {
    let mut game = Game::new(6);
    let m = vec!["a2", "a1", "b1", "b2", "c1", "c2", "d1", "e1", "d2", "e2",
                 "d3", "e3", "c3", "e4", "b3", "d4", "b4", "c4", "b5", "a3",
                 "c5", "a4", "d5", "a5", "e5", "a6"];
    play_no_win(m, &mut game);
    assert_eq!(game.play("f5", Player::One, Some(Player::One)).unwrap(), Some(Player::One));
}

#[test]
fn example1() {
    let mut game = Game::new(5);
    let m = vec!["a1", "e1", "c3", "a3", "e3", "a4", "a2", "a5", "b4", "d3",
                 "e2", "e4", "d2", "b2", "b4<", "a3+", "a3", "3a4-12", "a4", "b3",
                 "b4", "b3+", "a4+", "a4", "b3", "2b4-2", "d4", "b5", "2a5-11",
                 "3b3<3", "a5"];
    play_no_win(m, &mut game);
    assert_eq!(game.play("a4+", Player::Two, None).unwrap(), Some(Player::Two));
}
<|endoftext|>


<commit_before>use libc;
use std::mem;

#[repr(C)]
pub struct lzma_stream {
	pub next_in: *const u8,
    pub avail_in: usize,
    pub total_in: u64,

    pub next_out: *mut u8,
    pub avail_out: usize,
    pub total_out: u64,

    pub allocator: *const lzma_allocator,

    pub internal: *mut libc::c_void,   /* Actually lzma_internal, but lzma_internal is opaque */

    pub reserved_ptr1: *mut libc::c_void,
    pub reserved_ptr2: *mut libc::c_void,
    pub reserved_ptr3: *mut libc::c_void,
    pub reserved_ptr4: *mut libc::c_void,
    pub reserved_int1: *mut u64,
    pub reserved_int2: *mut u64,
    pub reserved_int3: *mut usize,
    pub reserved_int4: *mut usize,
    pub reserved_enum1: u32,  // TODO: in base.h this is lzma_reserved_enum, which seems to compile to 4-bytes
    pub reserved_enum2: u32,  // TODO: in base.h this is lzma_reserved_enum, which seems to compile to 4-bytes
}

impl lzma_stream {
	// base.h defines LZMA_STREAM_INIT; we declare new instead.
	pub fn new() -> lzma_stream {
		unsafe {
			mem::zeroed()
		}
	}
}

#[repr(C)]
pub struct lzma_allocator {
    pub alloc: *mut extern fn(opaque: *mut libc::c_void, nmemb: usize, size: usize),
    pub free: extern fn(opaque: *mut libc::c_void, ptr: *mut libc::c_void),
    pub opaque: *mut libc::c_void,
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
#[must_use]
pub enum lzma_ret {
    LZMA_OK                  = 0,
    LZMA_STREAM_END          = 1,
    LZMA_NO_CHECK            = 2,
    LZMA_UNSUPPORTED_CHECK   = 3,
    LZMA_GET_CHECK           = 4,
    LZMA_MEM_ERROR           = 5,
    LZMA_MEMLIMIT_ERROR      = 6,
    LZMA_FORMAT_ERROR        = 7,
    LZMA_OPTIONS_ERROR       = 8,
    LZMA_DATA_ERROR          = 9,
    LZMA_BUF_ERROR           = 10,
    LZMA_PROG_ERROR          = 11,
}

#[repr(C)]
#[derive(Clone, Copy)]
pub enum lzma_action {
	LZMA_RUN           = 0,
	LZMA_SYNC_FLUSH    = 1,
	LZMA_FULL_FLUSH    = 2,
	LZMA_FULL_BARRIER  = 4,
	LZMA_FINISH        = 3,
}

#[repr(C)]
#[derive(Clone, Copy)]
pub enum lzma_check {
	LZMA_CHECK_NONE     = 0,
    LZMA_CHECK_CRC32    = 1,
    LZMA_CHECK_CRC64    = 4,
    LZMA_CHECK_SHA256   = 10,
}

pub const LZMA_CONCATENATED: u32            = 0x08;
pub const LZMA_TELL_NO_CHECK: u32           = 0x01;
pub const LZMA_TELL_UNSUPPORTED_CHECK: u32  = 0x02;
pub const LZMA_TELL_ANY_CHECK: u32          = 0x04;

extern {
	pub fn lzma_easy_encoder(stream: *mut lzma_stream, preset: u32, check: lzma_check) -> lzma_ret;
	pub fn lzma_code(stream: *mut lzma_stream, action: lzma_action) -> lzma_ret;
	pub fn lzma_end(stream: *mut lzma_stream);
	pub fn lzma_stream_decoder(stream: *mut lzma_stream, memlimit: u64, flags: u32) -> lzma_ret;
}
<commit_msg>Formatting cleanup.<commit_after>use libc;
use std::mem;

#[repr(C)]
pub struct lzma_stream {
	pub next_in: *const u8,
	pub avail_in: usize,
	pub total_in: u64,

	pub next_out: *mut u8,
	pub avail_out: usize,
	pub total_out: u64,

	pub allocator: *const lzma_allocator,

	pub internal: *mut libc::c_void,   /* Actually lzma_internal, but lzma_internal is opaque */

	pub reserved_ptr1: *mut libc::c_void,
	pub reserved_ptr2: *mut libc::c_void,
	pub reserved_ptr3: *mut libc::c_void,
	pub reserved_ptr4: *mut libc::c_void,
	pub reserved_int1: *mut u64,
	pub reserved_int2: *mut u64,
	pub reserved_int3: *mut usize,
	pub reserved_int4: *mut usize,
	pub reserved_enum1: u32,  // TODO: in base.h this is lzma_reserved_enum, which seems to compile to 4-bytes
	pub reserved_enum2: u32,  // TODO: in base.h this is lzma_reserved_enum, which seems to compile to 4-bytes
}

impl lzma_stream {
	// base.h defines LZMA_STREAM_INIT; we declare new instead.
	pub fn new() -> lzma_stream {
		unsafe {
			mem::zeroed()
		}
	}
}

#[repr(C)]
pub struct lzma_allocator {
	pub alloc: *mut extern fn(opaque: *mut libc::c_void, nmemb: usize, size: usize),
	pub free: extern fn(opaque: *mut libc::c_void, ptr: *mut libc::c_void),
	pub opaque: *mut libc::c_void,
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
#[must_use]
pub enum lzma_ret {
	LZMA_OK                  = 0,
	LZMA_STREAM_END          = 1,
	LZMA_NO_CHECK            = 2,
	LZMA_UNSUPPORTED_CHECK   = 3,
	LZMA_GET_CHECK           = 4,
	LZMA_MEM_ERROR           = 5,
	LZMA_MEMLIMIT_ERROR      = 6,
	LZMA_FORMAT_ERROR        = 7,
	LZMA_OPTIONS_ERROR       = 8,
	LZMA_DATA_ERROR          = 9,
	LZMA_BUF_ERROR           = 10,
	LZMA_PROG_ERROR          = 11,
}

#[repr(C)]
#[derive(Clone, Copy)]
pub enum lzma_action {
	LZMA_RUN           = 0,
	LZMA_SYNC_FLUSH    = 1,
	LZMA_FULL_FLUSH    = 2,
	LZMA_FULL_BARRIER  = 4,
	LZMA_FINISH        = 3,
}

#[repr(C)]
#[derive(Clone, Copy)]
pub enum lzma_check {
	LZMA_CHECK_NONE     = 0,
	LZMA_CHECK_CRC32    = 1,
	LZMA_CHECK_CRC64    = 4,
	LZMA_CHECK_SHA256   = 10,
}

pub const LZMA_CONCATENATED: u32            = 0x08;
pub const LZMA_TELL_NO_CHECK: u32           = 0x01;
pub const LZMA_TELL_UNSUPPORTED_CHECK: u32  = 0x02;
pub const LZMA_TELL_ANY_CHECK: u32          = 0x04;

extern {
	pub fn lzma_easy_encoder(stream: *mut lzma_stream, preset: u32, check: lzma_check) -> lzma_ret;
	pub fn lzma_code(stream: *mut lzma_stream, action: lzma_action) -> lzma_ret;
	pub fn lzma_end(stream: *mut lzma_stream);
	pub fn lzma_stream_decoder(stream: *mut lzma_stream, memlimit: u64, flags: u32) -> lzma_ret;
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::rc::Rc;
use std::cell::RefCell;

type WordCell = Rc<RefCell<Word>>;
type AuthorCell = Rc<RefCell<Author>>;
type SourceCell = Rc<RefCell<Source>>;
type MessageCell = Rc<RefCell<Message>>;
type CategoryCell = Rc<RefCell<Category>>;
type ConversationCell = Rc<RefCell<Conversation>>;

fn wrap<T>(t: T) -> Rc<RefCell<T>> {
    Rc::new(RefCell::new(t))
}

const RATIO_CONTAINED_BEFORE_COMBINATION: f64 = 0.8;

struct Lexicon {
    words: BTreeMap<&'static str, WordCell>,
    authors: BTreeMap<&'static str, AuthorCell>,
    sources: BTreeMap<&'static str, SourceCell>,
    conversations: Vec<ConversationCell>,

    active_conversations: BTreeMap<*const Source, ConversationCell>,
}

impl Lexicon {
    fn tell(source: SourceCell, author: &str, message: &str) -> Option<String> {
        None
    }
}

struct Conversation {
    source: SourceCell,
    messages: Vec<MessageCell>,
}

struct Author {
    name: String,
}

struct Source {
    name: String,
    messages: u64,
}

struct MessageWord {
    word: WordCell,
    category: CategoryCell,
}

struct Message {
    author: AuthorCell,
    conversation: ConversationCell,
    index: usize,
    words: Vec<MessageWord>,
}

struct WordInstance {
    word: WordCell,
    message: MessageCell,
    index: usize,
}

struct Category {
    supercategory: Option<CategoryCell>,
    instances: Vec<WordInstance>,
    subcategories: Vec<CategoryCell>,
}

struct Word {
    name: String,
    instances: Vec<WordInstance>,
}
<commit_msg>add author detection<commit_after>use std::collections::BTreeMap;
use std::collections::btree_map::Entry;
use std::rc::Rc;
use std::cell::RefCell;

type WordCell = Rc<RefCell<Word>>;
type AuthorCell = Rc<RefCell<Author>>;
type SourceCell = Rc<RefCell<Source>>;
type MessageCell = Rc<RefCell<Message>>;
type CategoryCell = Rc<RefCell<Category>>;
type ConversationCell = Rc<RefCell<Conversation>>;

fn wrap<T>(t: T) -> Rc<RefCell<T>> {
    Rc::new(RefCell::new(t))
}

const RATIO_CONTAINED_BEFORE_COMBINATION: f64 = 0.8;

struct Lexicon {
    words: BTreeMap<String, WordCell>,
    authors: BTreeMap<String, AuthorCell>,
    sources: BTreeMap<String, SourceCell>,
    conversations: Vec<ConversationCell>,

    active_conversations: BTreeMap<*const Source, ConversationCell>,
}

impl Lexicon {
    fn tell(&mut self, source: SourceCell, author: String, message: String) -> Option<String> {
        let author = match self.authors.entry(author.clone()) {
            Entry::Vacant(v) => {
                let a = wrap(Author{
                    name: author.clone(),
                });
                v.insert(a.clone());
                a
            },
            Entry::Occupied(o) => o.get().clone(),
        };
        None
    }
}

struct Conversation {
    source: SourceCell,
    messages: Vec<MessageCell>,
}

struct Author {
    name: String,
}

struct Source {
    name: String,
    messages: u64,
}

struct MessageWord {
    word: WordCell,
    category: CategoryCell,
}

struct Message {
    author: AuthorCell,
    conversation: ConversationCell,
    index: usize,
    words: Vec<MessageWord>,
}

struct WordInstance {
    word: WordCell,
    message: MessageCell,
    index: usize,
}

struct Category {
    supercategory: Option<CategoryCell>,
    instances: Vec<WordInstance>,
    subcategories: Vec<CategoryCell>,
}

struct Word {
    name: String,
    instances: Vec<WordInstance>,
}
<|endoftext|>


<commit_before>//! # TreeView Sample
//!
//! This sample demonstrates how to create a TreeView with either a ListStore or TreeStore.

extern crate glib;
extern crate gtk;
extern crate gdk_pixbuf;

use gtk::prelude::*;
use gdk_pixbuf::Pixbuf;

fn append_text_column(tree: &gtk::TreeView) {
    let column = gtk::TreeViewColumn::new();
    let cell = gtk::CellRendererText::new();

    column.pack_start(&cell, true);
    column.add_attribute(&cell, "text", 0);
    tree.append_column(&column);
}

fn main() {
    if gtk::init().is_err() {
        println!("Failed to initialize GTK.");
        return;
    }

    let window = gtk::Window::new(gtk::WindowType::Toplevel);

    window.set_title("TreeView Sample");
    window.set_position(gtk::WindowPosition::Center);

    window.connect_delete_event(|_, _| {
        gtk::main_quit();
        Inhibit(false)
    });

    // left pane

    let left_tree = gtk::TreeView::new();
    let left_store = gtk::TreeStore::new(&[String::static_type()]);

    left_tree.set_model(Some(&left_store));
    left_tree.set_headers_visible(false);
    append_text_column(&left_tree);

    for i in 0..10 {
        // insert_with_values takes two slices: column indices and ToValue
        // trait objects. ToValue is implemented for strings, numeric types,
        // bool and Object descendants
        let iter = left_store.insert_with_values(None, None, &[0], &[&format!("Hello {}", i)]);

        for _ in 0..i {
            left_store.insert_with_values(Some(&iter), None, &[0], &[&"I'm a child node"]);
        }
    }

    // right pane
    let right_tree = gtk::TreeView::new();
    let right_column_types = [Pixbuf::static_type(), String::static_type()];
    let right_store = gtk::TreeStore::new(&right_column_types);
    let renderer = gtk::CellRendererPixbuf::new();
    let col = gtk::TreeViewColumn::new();

    col.set_title("Picture");
    col.pack_start(&renderer, false);

    col.add_attribute(&renderer, "pixbuf", 0);

    let renderer2 = gtk::CellRendererText::new();
    col.pack_start(&renderer2, true);
    col.add_attribute(&renderer2, "text", 1);
    let image = Pixbuf::new_from_file("./resources/eye.png").or_else(|err| {
        let mut msg = err.to_string();
        if err.kind() == Some(glib::FileError::Noent) {
            msg.push_str(&format!("\nRelaunch this example from the same level \
                                  as the `resources` folder"));
        }
        let window = window.clone();

        gtk::idle_add(move || {
            let dialog = gtk::MessageDialog::new(Some(&window), gtk::DIALOG_MODAL,
                gtk::MessageType::Error, gtk::ButtonsType::Ok, &msg);
            dialog.run();
            dialog.destroy();
            Continue(false)
        });

        Err(())
    }).ok();

    right_tree.append_column(&col);
    right_tree.set_model(Some(&right_store));
    right_tree.set_headers_visible(true);

    for _ in 0..10 {
        right_store.insert_with_values(None, None, &[0, 1],
                                       &[&image, &"I'm a child node with an image"]);
    }

    // selection and path manipulation

    let left_selection = left_tree.get_selection();
    let right_tree1 = right_tree.clone();
    left_selection.connect_changed(move |tree_selection| {
        let (left_model, iter) = tree_selection.get_selected().unwrap();
        let mut path = left_model.get_path(&iter);
        // get the top-level element path
        while path.get_depth() > 1 {
            path.up();
        }
        right_tree1.get_selection().select_path(&path);
    });

    // display the panes

    let split_pane = gtk::Box::new(gtk::Orientation::Horizontal, 10);

    split_pane.set_size_request(-1, -1);
    split_pane.add(&left_tree);
    split_pane.add(&right_tree);

    window.add(&split_pane);
    window.show_all();
    gtk::main();
}
<commit_msg>Import types and constant<commit_after>//! # TreeView Sample
//!
//! This sample demonstrates how to create a TreeView with either a ListStore or TreeStore.

extern crate glib;
extern crate gtk;
extern crate gdk_pixbuf;

use gtk::prelude::*;
use gtk::{
    ButtonsType, CellRendererPixbuf, CellRendererText, MessageDialog, MessageType, Orientation,
    TreeStore, TreeView, TreeViewColumn, Window, WindowPosition, WindowType, DIALOG_MODAL
};
use gdk_pixbuf::Pixbuf;

fn append_text_column(tree: &TreeView) {
    let column = TreeViewColumn::new();
    let cell = CellRendererText::new();

    column.pack_start(&cell, true);
    column.add_attribute(&cell, "text", 0);
    tree.append_column(&column);
}

fn main() {
    if gtk::init().is_err() {
        println!("Failed to initialize GTK.");
        return;
    }

    let window = Window::new(WindowType::Toplevel);

    window.set_title("TreeView Sample");
    window.set_position(WindowPosition::Center);

    window.connect_delete_event(|_, _| {
        gtk::main_quit();
        Inhibit(false)
    });

    // left pane

    let left_tree = TreeView::new();
    let left_store = TreeStore::new(&[String::static_type()]);

    left_tree.set_model(Some(&left_store));
    left_tree.set_headers_visible(false);
    append_text_column(&left_tree);

    for i in 0..10 {
        // insert_with_values takes two slices: column indices and ToValue
        // trait objects. ToValue is implemented for strings, numeric types,
        // bool and Object descendants
        let iter = left_store.insert_with_values(None, None, &[0], &[&format!("Hello {}", i)]);

        for _ in 0..i {
            left_store.insert_with_values(Some(&iter), None, &[0], &[&"I'm a child node"]);
        }
    }

    // right pane
    let right_tree = TreeView::new();
    let right_column_types = [Pixbuf::static_type(), String::static_type()];
    let right_store = TreeStore::new(&right_column_types);
    let renderer = CellRendererPixbuf::new();
    let col = TreeViewColumn::new();

    col.set_title("Picture");
    col.pack_start(&renderer, false);

    col.add_attribute(&renderer, "pixbuf", 0);

    let renderer2 = CellRendererText::new();
    col.pack_start(&renderer2, true);
    col.add_attribute(&renderer2, "text", 1);
    let image = Pixbuf::new_from_file("./resources/eye.png").or_else(|err| {
        let mut msg = err.to_string();
        if err.kind() == Some(glib::FileError::Noent) {
            msg.push_str(&format!("\nRelaunch this example from the same level \
                                  as the `resources` folder"));
        }
        let window = window.clone();

        gtk::idle_add(move || {
            let dialog = MessageDialog::new(Some(&window), DIALOG_MODAL,
                MessageType::Error, ButtonsType::Ok, &msg);
            dialog.run();
            dialog.destroy();
            Continue(false)
        });

        Err(())
    }).ok();

    right_tree.append_column(&col);
    right_tree.set_model(Some(&right_store));
    right_tree.set_headers_visible(true);

    for _ in 0..10 {
        right_store.insert_with_values(None, None, &[0, 1],
                                       &[&image, &"I'm a child node with an image"]);
    }

    // selection and path manipulation

    let left_selection = left_tree.get_selection();
    let right_tree1 = right_tree.clone();
    left_selection.connect_changed(move |tree_selection| {
        let (left_model, iter) = tree_selection.get_selected().unwrap();
        let mut path = left_model.get_path(&iter);
        // get the top-level element path
        while path.get_depth() > 1 {
            path.up();
        }
        right_tree1.get_selection().select_path(&path);
    });

    // display the panes

    let split_pane = gtk::Box::new(Orientation::Horizontal, 10);

    split_pane.set_size_request(-1, -1);
    split_pane.add(&left_tree);
    split_pane.add(&right_tree);

    window.add(&split_pane);
    window.show_all();
    gtk::main();
}
<|endoftext|>


<commit_before>//! A short tutorial on how to use vikos
//!
//! # Tutorial
//! Look, a bunch of data! Let us do something with it.
//!
//! ```
//! let history = [
//!    (2.0, 1.0), (3.0, 3.0), (3.5, 4.0),
//!    (5.0, 7.0), (5.5, 8.0), (7.0, 11.0),
//!    (16.0, 29.0)
//! ];
//! ```
//! The first elements of each tuple represent our feature vector,
//! the second elements represents the truth. We want to
//! use a [Training] to find the coefficients of a [Model]
//! which minimizes a `Cost` function. Let us start with
//! finding the mean value of the truth.
//!
//! ## Estimating mean
//!
//! ```
//! use vikos::{model, cost, teacher, learn_history, Model};
//! //mean is 9, but of course we do not know that yet
//! let history = [
//!    (2.0, 1.0), (3.0, 3.0), (3.5, 4.0),
//!    (5.0, 7.0), (5.5, 8.0), (7.0, 11.0),
//!    (16.0, 29.0)
//! ];
//!
//! // The mean is just a simple number ...
//! let mut model = model::Constant::new(0.0);
//! // ... which minimizes the square error
//! let cost = cost::LeastSquares {};
//! // Use stochastic gradient descent with an annealed learning rate
//! let teacher = teacher::GradientDescentAl { l0: 0.3, t: 4.0 };
//! // Train 100 (admittedly repetitive) events
//! learn_history(&teacher,
//!               &cost,
//!               &mut model,
//!               history.iter().cycle().take(100).cloned());
//! // We need an input vector for predictions, the 42 will not influence the mean
//! println!("{}", model.predict(&42.0));
//! // Since we know the model's type is `Constant`, we could just access the members
//! println!("{}", model.c);
//! ```
//! As far as the mean is concerned, the first element of each tuple, i.e., the feature, is just
//! ignored. The code would also compile if the first
//! element would be an empty tuple or any other type for
//! that matter.
//!
//! ## Estimating median
//!
//! If we want to estimate the median instead, we only need to change
//! our cost function:
//!
//! ```
//! use vikos::{model, cost, teacher, learn_history, Model};
//! let history = [
//!    (2.0, 1.0), (3.0, 3.0), (3.5, 4.0),
//!    (5.0, 7.0), (5.5, 8.0), (7.0, 11.0),
//!    (16.0, 29.0)
//! ];
//! // median is 7, but we don't know that yet of course
//!
//! // The median is just a simple number ...
//! let mut model = model::Constant::new(0.0);
//! // ... which minimizes the absolute error
//! let cost = cost::LeastAbsoluteDeviation {};
//! let teacher = teacher::GradientDescentAl { l0: 1.0, t: 9.0 };
//! learn_history(&teacher,
//!               &cost,
//!               &mut model,
//!               history.iter().cycle().take(100).cloned());
//! ```
//! Most notably we changed the cost function to train for the median. We also had to
//! increase our learning rate to be able to converge to `7` more quickly. Maybe we
//! should try a slightly more sophisticated `Training` algorithm.
//!
//! ## Estimating median again
//!
//! ```
//! use vikos::{model, cost, teacher, learn_history, Model};
//! // median is 7, but of course we do not know that yet
//! let history = [
//!    (2.0, 1.0), (3.0, 3.0), (3.5, 4.0),
//!    (5.0, 7.0), (5.5, 8.0), (7.0, 11.0),
//!    (16.0, 29.0)
//! ];
//!
//! // The median is just a simple number ...
//! let mut model = model::Constant::new(0.0);
//! // ... which minimizes the absolute error
//! let cost = cost::LeastAbsoluteDeviation {};
//! // Use stochasic gradient descent with an annealed learning rate and momentum
//! let teacher = teacher::Momentum {
//!     l0: 1.0,
//!     t: 3.0,
//!     inertia: 0.9,
//! };
//! learn_history(&teacher,
//!               &cost,
//!               &mut model,
//!               history.iter().cycle().take(100).cloned());
//! println!("{}", model.predict(&42.0));
//! ```
//! The momentum term allowed us to drop our learning rate way quicker and to retrieve a
//! more precise result in the same number of iterations. The algorithms and their
//! parameters are not the point however---the important thing is we could switch them
//! quite easily and independently of both cost function and model. Speaking of which:
//! it is time to fit a straight line through our data points.
//!
//! ## Line of best fit
//!
//! ```
//! use vikos::{model, cost, teacher, learn_history, Model};
//! // Best described by 2 * m - 3
//! let history = [
//!    (2.0, 1.0), (3.0, 3.0), (3.5, 4.0),
//!    (5.0, 7.0), (5.5, 8.0), (7.0, 11.0),
//!    (16.0, 29.0)
//! ];
//!
//! let mut model = model::Linear { m: 0.0, c: 0.0 };
//! let cost = cost::LeastSquares {};
//! let teacher = teacher::Momentum {
//!     l0: 0.0001,
//!     t: 1000.0,
//!     inertia: 0.99,
//! };
//! learn_history(&teacher,
//!               &cost,
//!               &mut model,
//!               history.iter().cycle().take(500).cloned());
//! for &(input, truth) in history.iter() {
//!     println!("Input: {}, Truth: {}, Prediction: {}",
//!              input,
//!              truth,
//!              model.predict(&input));
//! }
//! println!("slope: {}, intercept: {}", model.m, model.c);
//! ```
<commit_msg>Clarifications / extensions to the tutorial<commit_after>//! A short tutorial on how to use vikos to solve the problem of supervised
//! machine learning: We want to predict values for a quantity (the target), and
//! we have some data that we can base our inference on (features). We have a
//! data set (a history), that consists of features and corresponding, *true* target values, so
//! that we have a base to learn about how the target relates to the feature data.
//!
//! # Tutorial
//! Look, a bunch of data! Let us do something with it.
//!
//! ```
//! let history = [
//!    (2.0, 1.0), (3.0, 3.0), (3.5, 4.0),
//!    (5.0, 7.0), (5.5, 8.0), (7.0, 11.0),
//!    (16.0, 29.0)
//! ];
//! ```
//! The first elements of each tuple represent our *feature* vector,
//! the second elements represents the true (observed) *target* value
//! (aka *the truth*). We want to use a [Training](../trait.Training.html) to
//! find the coefficients of a  [Model](../trait.Model.html)
//! which minimizes a [Cost](../trait.Cost.html) function. Let us start with
//! finding the mean value of the truth.
//!
//! ## Estimating the mean target value
//!
//! ```
//! use vikos::{model, cost, teacher, learn_history, Model};
//! // mean is 9, but of course we do not know that yet
//! let history = [
//!    (2.0, 1.0), (3.0, 3.0), (3.5, 4.0),
//!    (5.0, 7.0), (5.5, 8.0), (7.0, 11.0),
//!    (16.0, 29.0)
//! ];
//!
//! // The mean is just a simple number ...
//! let mut model = model::Constant::new(0.0);
//! // ... which minimizes the square error
//! let cost = cost::LeastSquares {};
//! // Use stochastic gradient descent with an annealed learning rate
//! let teacher = teacher::GradientDescentAl { l0: 0.3, t: 4.0 };
//! // Train 100 (admittedly repetitive) events
//! learn_history(&teacher,
//!               &cost,
//!               &mut model,
//!               history.iter().cycle().take(100).cloned());
//! // We need an input vector for predictions, the 42 will not influence the mean
//! println!("{}", model.predict(&42.0));
//! // Since we know the model's type is `Constant`, we could just access the members
//! println!("{}", model.c);
//! ```
//! As far as the mean is concerned, the first element of each tuple, i.e.,
//! the feature, is just ignored (because we use the
//! [Constant](../model/struct.Constant.html) model).  The code would also
//! compile if the first element would be an empty tuple or any other type for
//! that matter.
//!
//! ## Estimating the median target value
//!
//! If we want to estimate the median instead, we only need to change
//! our cost function, to that of an absolute error:
//!
//! ```
//! use vikos::{model, cost, teacher, learn_history, Model};
//! let history = [
//!    (2.0, 1.0), (3.0, 3.0), (3.5, 4.0),
//!    (5.0, 7.0), (5.5, 8.0), (7.0, 11.0),
//!    (16.0, 29.0)
//! ];
//! // median is 7, but we don't know that yet of course
//!
//! // The median is just a simple number ...
//! let mut model = model::Constant::new(0.0);
//! // ... which minimizes the absolute error
//! let cost = cost::LeastAbsoluteDeviation {};
//! let teacher = teacher::GradientDescentAl { l0: 1.0, t: 9.0 };
//! learn_history(&teacher,
//!               &cost,
//!               &mut model,
//!               history.iter().cycle().take(100).cloned());
//! ```
//! Most notably we changed the cost function to train for the median. We also had to
//! increase our learning rate to be able to converge to `7` more quickly. Maybe we
//! should try a slightly more sophisticated `Training` algorithm.
//!
//! ## Estimating median again
//!
//! ```
//! use vikos::{model, cost, teacher, learn_history, Model};
//! // median is 7, but of course we do not know that yet
//! let history = [
//!    (2.0, 1.0), (3.0, 3.0), (3.5, 4.0),
//!    (5.0, 7.0), (5.5, 8.0), (7.0, 11.0),
//!    (16.0, 29.0)
//! ];
//!
//! // The median is just a simple number ...
//! let mut model = model::Constant::new(0.0);
//! // ... which minimizes the absolute error
//! let cost = cost::LeastAbsoluteDeviation {};
//! // Use stochasic gradient descent with an annealed learning rate and momentum
//! let teacher = teacher::Momentum {
//!     l0: 1.0,
//!     t: 3.0,
//!     inertia: 0.9,
//! };
//! learn_history(&teacher,
//!               &cost,
//!               &mut model,
//!               history.iter().cycle().take(100).cloned());
//! println!("{}", model.predict(&42.0));
//! ```
//! The momentum term allowed us to drop our learning rate way quicker and to retrieve a
//! more precise result in the same number of iterations. The algorithms and their
//! parameters are not the point however — the important thing is we could switch them
//! quite easily and independently of both cost function and model. Speaking of which:
//! it is time to fit a straight line through our data points.
//!
//! ## Line of best fit
//! We now use a linear model
//!
//! ```
//! use vikos::{model, cost, teacher, learn_history, Model};
//! // Best described by 2 * m - 3
//! let history = [
//!    (2.0, 1.0), (3.0, 3.0), (3.5, 4.0),
//!    (5.0, 7.0), (5.5, 8.0), (7.0, 11.0),
//!    (16.0, 29.0)
//! ];
//!
//! let mut model = model::Linear { m: 0.0, c: 0.0 };
//! let cost = cost::LeastSquares {};
//! let teacher = teacher::Momentum {
//!     l0: 0.0001,
//!     t: 1000.0,
//!     inertia: 0.99,
//! };
//! learn_history(&teacher,
//!               &cost,
//!               &mut model,
//!               history.iter().cycle().take(500).cloned());
//! for &(input, truth) in history.iter() {
//!     println!("Input: {}, Truth: {}, Prediction: {}",
//!              input,
//!              truth,
//!              model.predict(&input));
//! }
//! println!("slope: {}, intercept: {}", model.m, model.c);
//! ```
//! # Summary
//!
//! Using Vikos, we can build a machine-learning model by composing
//! implementations of three aspects:
//!
//!  * the [Model](../trait.Model.html) describes how features and target
//!    relate to each other (and what kind of estimated parameters/coefficients
//!    mediate among the target and the feature space), the model is  fitted by
//!  * the training algorithm, modelled with the
//!    [Teacher](../trait.Teacher.html) and the [Training](../trait.Training.html)
//!    traits, that contains the optimization algorithm minimizing the
//!  * the [Cost](../trait.Cost.html) "function" describes the function that
//!    should be minimized by the algorithm.
<|endoftext|>


<commit_before>use libc;
use {Errno, Result};
use std::mem;

#[derive(Clone, Copy)]
pub struct UContext {
    context: libc::ucontext_t,
}

impl UContext {
    pub fn get() -> Result<UContext> {
        let mut context: libc::ucontext_t = unsafe { mem::uninitialized() };
        let res = unsafe {
            libc::getcontext(&mut context as *mut libc::ucontext_t)
        };
        Errno::result(res).map(|_| UContext { context: context })
    }

    pub fn set(&self) -> Result<()> {
        let res = unsafe {
            libc::setcontext(&self.context as *const libc::ucontext_t)
        };
        Errno::result(res).map(drop)
    }
}
<commit_msg>Exclude UContext::get(),set() on musl, not available from libc.<commit_after>use libc;
#[cfg(not(target_env = "musl"))]
use {Errno, Result};
#[cfg(not(target_env = "musl"))]
use std::mem;

#[derive(Clone, Copy)]
pub struct UContext {
    context: libc::ucontext_t,
}

impl UContext {
    #[cfg(not(target_env = "musl"))]
    pub fn get() -> Result<UContext> {
        let mut context: libc::ucontext_t = unsafe { mem::uninitialized() };
        let res = unsafe {
            libc::getcontext(&mut context as *mut libc::ucontext_t)
        };
        Errno::result(res).map(|_| UContext { context: context })
    }

    #[cfg(not(target_env = "musl"))]
    pub fn set(&self) -> Result<()> {
        let res = unsafe {
            libc::setcontext(&self.context as *const libc::ucontext_t)
        };
        Errno::result(res).map(drop)
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017-2018 Ryan Huang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

mod board;
mod board_parts;
mod sys;
mod vec2;

use imgui::{ImGuiCond, ImStr, ImVec2, StyleVar, Ui};

use self::board::board;
pub use self::sys::run;
use self::vec2::Vec2;
use model::{Color, ColorMap, Model, Player};
use update::Event;

pub fn draw(ui: &Ui, size: (f32, f32), model: &Model) -> Option<Event> {
    let mut event = None;

    ui.main_menu_bar(|| {
        ui.menu(im_str!("Game")).build(|| {
            ui.menu_item(im_str!("New game")).enabled(false).build();

            use self::Player::*;
            if ui.menu_item(im_str!("Human vs. Human")).build() {
                insert_if_empty(&mut event, Event::NewGame(ColorMap::new(Human, Human)));
            }
            if ui.menu_item(im_str!("Human vs. Computer")).build() {
                insert_if_empty(&mut event, Event::NewGame(ColorMap::new(Human, Computer)));
            }
            if ui.menu_item(im_str!("Computer vs. Human")).build() {
                insert_if_empty(&mut event, Event::NewGame(ColorMap::new(Computer, Human)));
            }
            if ui.menu_item(im_str!("Computer vs. Computer")).build() {
                insert_if_empty(
                    &mut event,
                    Event::NewGame(ColorMap::new(Computer, Computer)),
                );
            }
            ui.separator();
            if ui.menu_item(im_str!("Quit")).build() {
                insert_if_empty(&mut event, Event::Quit);
            }
        });

        let mut depth = i32::from(model.ai_search_depth);
        ui.menu(im_str!("Computer")).build(|| {
            ui.slider_int(im_str!("Search depth"), &mut depth, 1, 7)
                .build();
            if ui.is_item_hovered() {
                ui.tooltip_text("How many moves ahead the computer will search.\nFewer moves is faster and easier, while more moves is slower and more difficult.");
            }
        });
        if depth as u8 != model.ai_search_depth {
            insert_if_empty(&mut event, Event::SetAIDepth(depth as u8));
        }
    });

    ui.with_style_var(StyleVar::WindowRounding(0.0), || {
        draw_window(ui, size, model, &mut event);
    });

    event
}

fn draw_window(ui: &Ui, size: (f32, f32), model: &Model, event: &mut Option<Event>) {
    ui.window(im_str!("Coerceo"))
        .size(size, ImGuiCond::Always)
        .position((0.0, 19.0), ImGuiCond::Once)
        .title_bar(false)
        .resizable(false)
        .movable(false)
        .build(|| {
            ui.text("Welcome to Coerceo!");
            ui.text(format!(
                "{:?} vs. {:?}",
                model.players.white, model.players.black
            ));

            if let Some(click) = board(ui, model, Vec2::new(size.0 - 16.0, size.1 - 170.0)) {
                insert_if_empty(event, click);
            }

            let display_vitals = || {
                ui.text(format!(
                    "{:?} has {} piece(s) left and {} captured hex(es).",
                    Color::White,
                    model.board.pieces(Color::White),
                    model.board.hexes(Color::White),
                ));
                ui.text(format!(
                    "{:?} has {} piece(s) left and {} captured hex(es).",
                    Color::Black,
                    model.board.pieces(Color::Black),
                    model.board.hexes(Color::Black),
                ));
            };

            let button_size = Vec2::new(120.0, 20.0);
            use model::Outcome::*;
            match model.outcome {
                Win(color) => {
                    ui.text(format!("{:?} wins!", color));
                    display_vitals();
                    if model.can_undo() && ui.button(im_str!("Undo"), button_size) {
                        insert_if_empty(event, Event::Undo);
                    }
                }
                InProgress => {
                    ui.text(format!(
                        "It's {:?}'s turn. ({})",
                        model.board.turn,
                        match model.current_player() {
                            Player::Computer => "Computer",
                            Player::Human => "Human",
                        }
                    ));
                    display_vitals();

                    horz_button_layout(
                        ui,
                        vec![
                            (model.can_undo(), im_str!("Undo"), Event::Undo),
                            (model.can_redo(), im_str!("Redo"), Event::Redo),
                        ],
                        &button_size,
                        event,
                    );
                    let is_human_player = model.current_player() == Player::Human;
                    horz_button_layout(
                        ui,
                        vec![
                            (is_human_player, im_str!("Resign"), Event::Resign),
                            (
                                model.board.can_exchange() && is_human_player,
                                if model.exchanging {
                                    im_str!("Stop Exchanging")
                                } else {
                                    im_str!("Exchange")
                                },
                                Event::Exchange,
                            ),
                        ],
                        &button_size,
                        event,
                    );
                }
                // Draw cases
                _ => {
                    let message = match model.outcome {
                        DrawStalemate => "It's a draw by stalemate!",
                        DrawThreefoldRepetition => "It's a draw by threefold repetition!",
                        DrawInsufficientMaterial => "It's a draw by insufficient material!",
                        _ => unreachable!(),
                    };
                    ui.text(message);
                    display_vitals();
                    if model.can_undo() && ui.button(im_str!("Undo"), button_size) {
                        insert_if_empty(event, Event::Undo);
                    }
                }
            }
        });
}

fn horz_button_layout(
    ui: &Ui,
    buttons: Vec<(bool, &ImStr, Event)>,
    size: &Vec2,
    event: &mut Option<Event>,
) {
    if !buttons.iter().any(|&(show, _, _)| show) {
        return;
    }

    let size: ImVec2 = (*size).into();

    for (show, label, action) in buttons {
        if show {
            if ui.button(label, size) {
                insert_if_empty(event, action);
            }
        } else {
            ui.dummy(size);
        }
        ui.same_line(0.0);
    }
    ui.new_line();
}

fn insert_if_empty<T>(a: &mut Option<T>, b: T) {
    if a.is_none() {
        *a = Some(b);
    }
}
<commit_msg>Improve status messages<commit_after>/*
 * Copyright (C) 2017-2018 Ryan Huang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

mod board;
mod board_parts;
mod sys;
mod vec2;

use imgui::{ImGuiCond, ImStr, ImVec2, StyleVar, Ui};

use self::board::board;
pub use self::sys::run;
use self::vec2::Vec2;
use model::{Color, ColorMap, Model, Player};
use update::Event;

pub fn draw(ui: &Ui, size: (f32, f32), model: &Model) -> Option<Event> {
    let mut event = None;

    ui.main_menu_bar(|| {
        ui.menu(im_str!("Game")).build(|| {
            ui.menu_item(im_str!("New game")).enabled(false).build();

            use self::Player::*;
            if ui.menu_item(im_str!("Human vs. Human")).build() {
                insert_if_empty(&mut event, Event::NewGame(ColorMap::new(Human, Human)));
            }
            if ui.menu_item(im_str!("Human vs. Computer")).build() {
                insert_if_empty(&mut event, Event::NewGame(ColorMap::new(Human, Computer)));
            }
            if ui.menu_item(im_str!("Computer vs. Human")).build() {
                insert_if_empty(&mut event, Event::NewGame(ColorMap::new(Computer, Human)));
            }
            if ui.menu_item(im_str!("Computer vs. Computer")).build() {
                insert_if_empty(
                    &mut event,
                    Event::NewGame(ColorMap::new(Computer, Computer)),
                );
            }
            ui.separator();
            if ui.menu_item(im_str!("Quit")).build() {
                insert_if_empty(&mut event, Event::Quit);
            }
        });

        let mut depth = i32::from(model.ai_search_depth);
        ui.menu(im_str!("Computer")).build(|| {
            ui.slider_int(im_str!("Search depth"), &mut depth, 1, 7)
                .build();
            if ui.is_item_hovered() {
                ui.tooltip_text("How many moves ahead the computer will search.\nFewer moves is faster and easier, while more moves is slower and more difficult.");
            }
        });
        if depth as u8 != model.ai_search_depth {
            insert_if_empty(&mut event, Event::SetAIDepth(depth as u8));
        }
    });

    ui.with_style_var(StyleVar::WindowRounding(0.0), || {
        draw_window(ui, size, model, &mut event);
    });

    event
}

fn draw_window(ui: &Ui, size: (f32, f32), model: &Model, event: &mut Option<Event>) {
    ui.window(im_str!("Coerceo"))
        .size(size, ImGuiCond::Always)
        .position((0.0, 19.0), ImGuiCond::Once)
        .title_bar(false)
        .resizable(false)
        .movable(false)
        .build(|| {
            ui.text("Welcome to Coerceo!");
            ui.text(format!(
                "{:?} vs. {:?}",
                model.players.white, model.players.black
            ));

            if let Some(click) = board(ui, model, Vec2::new(size.0 - 16.0, size.1 - 170.0)) {
                insert_if_empty(event, click);
            }

            let format_piece_count = |count| match count {
                1 => String::from("1 piece"),
                _ => format!("{} pieces", count),
            };

            let format_hex_count = |count| match count {
                1 => String::from("1 captured hex"),
                _ => format!("{} captured hexes", count),
            };

            let display_vitals = || {
                ui.text(format!(
                    "{:?} has {} and {}.",
                    Color::White,
                    format_piece_count(model.board.pieces(Color::White)),
                    format_hex_count(model.board.hexes(Color::White)),
                ));
                ui.text(format!(
                    "{:?} has {} and {}.",
                    Color::Black,
                    format_piece_count(model.board.pieces(Color::Black)),
                    format_hex_count(model.board.hexes(Color::Black)),
                ));
            };

            let button_size = Vec2::new(120.0, 20.0);
            use model::Outcome::*;
            match model.outcome {
                Win(color) => {
                    ui.text(format!("{:?} wins!", color));
                    display_vitals();
                    if model.can_undo() && ui.button(im_str!("Undo"), button_size) {
                        insert_if_empty(event, Event::Undo);
                    }
                }
                InProgress => {
                    if model.players.white == model.players.black {
                        ui.text(format!("It's {:?}'s turn.", model.board.turn,));
                    } else {
                        ui.text(match model.current_player() {
                            Player::Computer => "Waiting for the computer...",
                            Player::Human => "It's your turn.",
                        });
                    }

                    display_vitals();

                    horz_button_layout(
                        ui,
                        vec![
                            (model.can_undo(), im_str!("Undo"), Event::Undo),
                            (model.can_redo(), im_str!("Redo"), Event::Redo),
                        ],
                        &button_size,
                        event,
                    );
                    let is_human_player = model.current_player() == Player::Human;
                    horz_button_layout(
                        ui,
                        vec![
                            (is_human_player, im_str!("Resign"), Event::Resign),
                            (
                                model.board.can_exchange() && is_human_player,
                                if model.exchanging {
                                    im_str!("Stop Exchanging")
                                } else {
                                    im_str!("Exchange")
                                },
                                Event::Exchange,
                            ),
                        ],
                        &button_size,
                        event,
                    );
                }
                // Draw cases
                _ => {
                    let message = match model.outcome {
                        DrawStalemate => "It's a draw by stalemate!",
                        DrawThreefoldRepetition => "It's a draw by threefold repetition!",
                        DrawInsufficientMaterial => "It's a draw by insufficient material!",
                        _ => unreachable!(),
                    };
                    ui.text(message);
                    display_vitals();
                    if model.can_undo() && ui.button(im_str!("Undo"), button_size) {
                        insert_if_empty(event, Event::Undo);
                    }
                }
            }
        });
}

fn horz_button_layout(
    ui: &Ui,
    buttons: Vec<(bool, &ImStr, Event)>,
    size: &Vec2,
    event: &mut Option<Event>,
) {
    if !buttons.iter().any(|&(show, _, _)| show) {
        return;
    }

    let size: ImVec2 = (*size).into();

    for (show, label, action) in buttons {
        if show {
            if ui.button(label, size) {
                insert_if_empty(event, action);
            }
        } else {
            ui.dummy(size);
        }
        ui.same_line(0.0);
    }
    ui.new_line();
}

fn insert_if_empty<T>(a: &mut Option<T>, b: T) {
    if a.is_none() {
        *a = Some(b);
    }
}
<|endoftext|>


<commit_before>use crate::timing;
use chrono::ParseError as ChronoError;
use quick_xml::events::{attributes, BytesStart, Event};
use quick_xml::{Error as XmlError, Reader, Writer};
use std::borrow::Cow;
use std::io::{self, BufRead};
use std::num::{ParseFloatError, ParseIntError};
use std::ops::Deref;
use std::{str, string};

quick_error! {
    /// The Error type for XML-based splits files that couldn't be parsed.
    #[derive(Debug)]
    pub enum Error {
        /// Failed to parse the XML.
        Xml(err: XmlError) {
            from()
        }
        /// Failed to read from the source.
        Io(err: io::Error) {
            from()
        }
        /// Failed to parse a boolean.
        Bool {}
        /// Didn't expect the end of the file.
        UnexpectedEndOfFile {}
        /// Didn't expect an inner element.
        UnexpectedElement {}
        /// A required attribute has not been found on an element.
        AttributeNotFound {}
        /// A required element has not been found.
        ElementNotFound {}
        /// The length of a buffer was too large.
        LengthOutOfBounds {}
        /// Failed to decode a string slice as UTF-8.
        Utf8Str(err: str::Utf8Error) {
            from()
        }
        /// Failed to decode a string as UTF-8.
        Utf8String(err: string::FromUtf8Error) {
            from()
        }
        /// Failed to parse an integer.
        Int(err: ParseIntError) {
            from()
        }
        /// Failed to parse a floating point number.
        Float(err: ParseFloatError) {
            from()
        }
        /// Failed to parse a time.
        Time(err: timing::ParseError) {
            from()
        }
        /// Failed to parse a date.
        Date(err: ChronoError) {
            from()
        }
    }
}

/// The Result type for Parsers that parse XML-based splits files.
// pub type Result<T> = StdResult<T, Error>;

pub struct Tag<'a>(BytesStart<'a>, *mut Vec<u8>);

impl<'a> Deref for Tag<'a> {
    type Target = BytesStart<'a>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<'a> Tag<'a> {
    pub unsafe fn new(tag: BytesStart<'a>, buf: *mut Vec<u8>) -> Self {
        Tag(tag, buf)
    }

    pub fn into_buf(self) -> &'a mut Vec<u8> {
        unsafe { &mut *self.1 }
    }
}

pub struct AttributeValue<'a>(&'a attributes::Attribute<'a>);

impl<'a> AttributeValue<'a> {
    pub fn get<E>(self) -> Result<Cow<'a, str>, E>
    where
        E: From<Error> + From<string::FromUtf8Error> + From<str::Utf8Error>,
    {
        decode_cow_text(self.0.unescaped_value().map_err(Error::Xml)?)
    }

    pub fn get_raw(&self) -> &'a [u8] {
        &self.0.value
    }
}

fn decode_cow_text<E>(cow: Cow<'_, [u8]>) -> Result<Cow<'_, str>, E>
where
    E: From<string::FromUtf8Error> + From<str::Utf8Error>,
{
    Ok(match cow {
        Cow::Borrowed(b) => Cow::Borrowed(str::from_utf8(b)?),
        Cow::Owned(o) => Cow::Owned(String::from_utf8(o)?),
    })
}

pub fn text_parsed<R, F, T, E>(reader: &mut Reader<R>, buf: &mut Vec<u8>, f: F) -> Result<(), E>
where
    R: BufRead,
    F: FnOnce(T),
    T: str::FromStr,
    E: From<Error> + From<string::FromUtf8Error> + From<str::Utf8Error> + From<T::Err>,
{
    text_err(reader, buf, |t| {
        f(t.parse()?);
        Ok(())
    })
}

pub fn text<R, F, E>(reader: &mut Reader<R>, buf: &mut Vec<u8>, f: F) -> Result<(), E>
where
    R: BufRead,
    F: FnOnce(Cow<'_, str>),
    E: From<Error> + From<string::FromUtf8Error> + From<str::Utf8Error>,
{
    text_err(reader, buf, |t| {
        f(t);
        Ok(())
    })
}

pub fn text_err<R, F, E>(reader: &mut Reader<R>, buf: &mut Vec<u8>, f: F) -> Result<(), E>
where
    R: BufRead,
    F: FnOnce(Cow<'_, str>) -> Result<(), E>,
    E: From<Error> + From<string::FromUtf8Error> + From<str::Utf8Error>,
{
    text_as_bytes_err(reader, buf, |b| f(decode_cow_text::<E>(b)?))
}

pub fn text_as_escaped_bytes_err<R, F, T, E>(
    reader: &mut Reader<R>,
    buf: &mut Vec<u8>,
    f: F,
) -> Result<T, E>
where
    R: BufRead,
    F: FnOnce(&[u8]) -> Result<T, E>,
    E: From<Error>,
{
    loop {
        buf.clear();
        match reader.read_event(buf).map_err(Error::Xml)? {
            Event::Start(_) => return Err(Error::UnexpectedElement).map_err(Into::into),
            Event::End(_) => {
                return f(&[]);
            }
            Event::Text(text) | Event::CData(text) => {
                let val = f(&text)?;
                end_tag_immediately(reader, buf)?;
                return Ok(val);
            }
            Event::Eof => return Err(Error::UnexpectedEndOfFile).map_err(Into::into),
            _ => {}
        }
    }
}

pub fn text_as_bytes_err<R, F, T, E>(
    reader: &mut Reader<R>,
    buf: &mut Vec<u8>,
    f: F,
) -> Result<T, E>
where
    R: BufRead,
    F: FnOnce(Cow<'_, [u8]>) -> Result<T, E>,
    E: From<Error>,
{
    loop {
        buf.clear();
        match reader.read_event(buf).map_err(Error::Xml)? {
            Event::Start(_) => return Err(Error::UnexpectedElement).map_err(Into::into),
            Event::End(_) => {
                return f(Cow::Borrowed(&[]));
            }
            Event::Text(text) | Event::CData(text) => {
                let text = text.unescaped().map_err(Into::into)?;
                let val = f(text)?;
                end_tag_immediately(reader, buf)?;
                return Ok(val);
            }
            Event::Eof => return Err(Error::UnexpectedEndOfFile).map_err(Into::into),
            _ => {}
        }
    }
}

fn end_tag_immediately<R, E>(reader: &mut Reader<R>, buf: &mut Vec<u8>) -> Result<(), E>
where
    R: BufRead,
    E: From<Error>,
{
    loop {
        buf.clear();
        match reader.read_event(buf).map_err(Error::Xml)? {
            Event::Start(_) => return Err(Error::UnexpectedElement).map_err(Into::into),
            Event::End(_) => return Ok(()),
            Event::Eof => return Err(Error::UnexpectedEndOfFile).map_err(Into::into),
            _ => {}
        }
    }
}

pub fn reencode_children<R>(
    reader: &mut Reader<R>,
    buf: &mut Vec<u8>,
    target_buf: &mut Vec<u8>,
) -> Result<(), Error>
where
    R: BufRead,
{
    reader.expand_empty_elements(false);
    let mut writer = Writer::new(target_buf);
    let mut depth = 0;
    loop {
        buf.clear();
        match reader.read_event(buf)? {
            Event::Start(start) => {
                depth += 1;
                writer.write_event(Event::Start(start))?;
            }
            Event::End(end) => {
                if depth == 0 {
                    reader.expand_empty_elements(true);
                    return Ok(());
                }
                depth -= 1;
                writer.write_event(Event::End(end))?;
            }
            event @ Event::Text(_)
            | event @ Event::Comment(_)
            | event @ Event::CData(_)
            | event @ Event::PI(_)
            | event @ Event::Empty(_) => {
                writer.write_event(event)?;
            }
            Event::Decl(_) => {
                // Shouldn't really be a child anyway.
            }
            Event::DocType(_) => {
                // A DOCTYPE is not allowed in content.
            }
            Event::Eof => return Err(Error::UnexpectedEndOfFile),
        }
    }
}

pub fn end_tag<R, E>(reader: &mut Reader<R>, buf: &mut Vec<u8>) -> Result<(), E>
where
    R: BufRead,
    E: From<Error>,
{
    let mut depth = 0;
    loop {
        buf.clear();
        match reader.read_event(buf).map_err(Error::Xml)? {
            Event::Start(_) => {
                depth += 1;
            }
            Event::End(_) => {
                if depth == 0 {
                    return Ok(());
                }
                depth -= 1;
            }
            Event::Eof => return Err(Error::UnexpectedEndOfFile).map_err(Into::into),
            _ => {}
        }
    }
}

pub fn single_child<R, F, T, E>(
    reader: &mut Reader<R>,
    buf: &mut Vec<u8>,
    tag: &[u8],
    mut f: F,
) -> Result<T, E>
where
    R: BufRead,
    F: FnMut(&mut Reader<R>, Tag<'_>) -> Result<T, E>,
    E: From<Error>,
{
    let mut val = None;
    parse_children::<_, _, E>(reader, buf, |reader, t| {
        if t.name() == tag && val.is_none() {
            val = Some(f(reader, t)?);
            Ok(())
        } else {
            end_tag(reader, t.into_buf())
        }
    })?;
    val.ok_or(Error::ElementNotFound).map_err(Into::into)
}

pub fn parse_children<R, F, E>(reader: &mut Reader<R>, buf: &mut Vec<u8>, mut f: F) -> Result<(), E>
where
    R: BufRead,
    F: FnMut(&mut Reader<R>, Tag<'_>) -> Result<(), E>,
    E: From<Error>,
{
    unsafe {
        let ptr_buf: *mut Vec<u8> = buf;
        loop {
            buf.clear();
            match reader.read_event(buf).map_err(Error::Xml)? {
                Event::Start(start) => {
                    let tag = Tag::new(start, ptr_buf);
                    f(reader, tag)?;
                }
                Event::End(_) => return Ok(()),
                Event::Eof => return Err(Error::UnexpectedEndOfFile).map_err(Into::into),
                _ => {}
            }
        }
    }
}

pub fn parse_base<R, F, E>(
    reader: &mut Reader<R>,
    buf: &mut Vec<u8>,
    tag: &[u8],
    mut f: F,
) -> Result<(), E>
where
    R: BufRead,
    F: FnMut(&mut Reader<R>, Tag<'_>) -> Result<(), E>,
    E: From<Error>,
{
    unsafe {
        let ptr_buf: *mut Vec<u8> = buf;
        loop {
            buf.clear();
            match reader.read_event(buf).map_err(Error::Xml)? {
                Event::Start(start) => {
                    if start.name() == tag {
                        let tag = Tag::new(start, ptr_buf);
                        return f(reader, tag);
                    } else {
                        return Err(Error::ElementNotFound).map_err(Into::into);
                    }
                }
                Event::Eof => return Err(Error::UnexpectedEndOfFile).map_err(Into::into),
                _ => {}
            }
        }
    }
}

pub fn parse_attributes<F, E>(tag: &BytesStart<'_>, mut f: F) -> Result<(), E>
where
    F: FnMut(&[u8], AttributeValue<'_>) -> Result<bool, E>,
    E: From<Error>,
{
    for attribute in tag.attributes() {
        let attribute = attribute.map_err(Error::Xml)?;
        let key = attribute.key;
        if !f(key, AttributeValue(&attribute))? {
            return Ok(());
        }
    }
    Ok(())
}

pub fn optional_attribute_err<F, E>(tag: &BytesStart<'_>, key: &[u8], mut f: F) -> Result<(), E>
where
    F: FnMut(Cow<'_, str>) -> Result<(), E>,
    E: From<Error>,
{
    parse_attributes(tag, |k, v| {
        if k == key {
            f(v.get()?)?;
            Ok(false)
        } else {
            Ok(true)
        }
    })
}

pub fn attribute_err<F, E>(tag: &BytesStart<'_>, key: &[u8], mut f: F) -> Result<(), E>
where
    F: FnMut(Cow<'_, str>) -> Result<(), E>,
    E: From<Error>,
{
    let mut called = false;
    parse_attributes::<_, E>(tag, |k, v| {
        if k == key {
            f(v.get()?)?;
            called = true;
            Ok(false)
        } else {
            Ok(true)
        }
    })?;
    if called {
        Ok(())
    } else {
        Err(Error::AttributeNotFound).map_err(Into::into)
    }
}

pub fn attribute<F, E>(tag: &BytesStart<'_>, key: &[u8], mut f: F) -> Result<(), E>
where
    F: FnMut(Cow<'_, str>),
    E: From<Error>,
{
    attribute_err(tag, key, |t| {
        f(t);
        Ok(())
    })
}
<commit_msg>Improve XML Parsing Performance<commit_after>use crate::timing;
use chrono::ParseError as ChronoError;
use quick_xml::events::{attributes, BytesStart, Event};
use quick_xml::{Error as XmlError, Reader, Writer};
use std::borrow::Cow;
use std::io::{self, BufRead};
use std::num::{ParseFloatError, ParseIntError};
use std::ops::Deref;
use std::{str, string};

quick_error! {
    /// The Error type for XML-based splits files that couldn't be parsed.
    #[derive(Debug)]
    pub enum Error {
        /// Failed to parse the XML.
        Xml(err: XmlError) {
            from()
        }
        /// Failed to read from the source.
        Io(err: io::Error) {
            from()
        }
        /// Failed to parse a boolean.
        Bool {}
        /// Didn't expect the end of the file.
        UnexpectedEndOfFile {}
        /// Didn't expect an inner element.
        UnexpectedElement {}
        /// A required attribute has not been found on an element.
        AttributeNotFound {}
        /// A required element has not been found.
        ElementNotFound {}
        /// The length of a buffer was too large.
        LengthOutOfBounds {}
        /// Failed to decode a string slice as UTF-8.
        Utf8Str(err: str::Utf8Error) {
            from()
        }
        /// Failed to decode a string as UTF-8.
        Utf8String(err: string::FromUtf8Error) {
            from()
        }
        /// Failed to parse an integer.
        Int(err: ParseIntError) {
            from()
        }
        /// Failed to parse a floating point number.
        Float(err: ParseFloatError) {
            from()
        }
        /// Failed to parse a time.
        Time(err: timing::ParseError) {
            from()
        }
        /// Failed to parse a date.
        Date(err: ChronoError) {
            from()
        }
    }
}

/// The Result type for Parsers that parse XML-based splits files.
// pub type Result<T> = StdResult<T, Error>;

pub struct Tag<'a>(BytesStart<'a>, *mut Vec<u8>);

impl<'a> Deref for Tag<'a> {
    type Target = BytesStart<'a>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<'a> Tag<'a> {
    pub unsafe fn new(tag: BytesStart<'a>, buf: *mut Vec<u8>) -> Self {
        Tag(tag, buf)
    }

    pub fn into_buf(self) -> &'a mut Vec<u8> {
        unsafe { &mut *self.1 }
    }
}

pub struct AttributeValue<'a>(&'a attributes::Attribute<'a>);

impl<'a> AttributeValue<'a> {
    pub fn get<E>(self) -> Result<Cow<'a, str>, E>
    where
        E: From<Error> + From<string::FromUtf8Error> + From<str::Utf8Error>,
    {
        decode_cow_text(self.0.unescaped_value().map_err(Error::Xml)?)
    }

    pub fn get_raw(&self) -> &'a [u8] {
        &self.0.value
    }
}

fn decode_cow_text<E>(cow: Cow<'_, [u8]>) -> Result<Cow<'_, str>, E>
where
    E: From<string::FromUtf8Error> + From<str::Utf8Error>,
{
    Ok(match cow {
        Cow::Borrowed(b) => Cow::Borrowed(str::from_utf8(b)?),
        Cow::Owned(o) => Cow::Owned(String::from_utf8(o)?),
    })
}

pub fn text_parsed<R, F, T, E>(reader: &mut Reader<R>, buf: &mut Vec<u8>, f: F) -> Result<(), E>
where
    R: BufRead,
    F: FnOnce(T),
    T: str::FromStr,
    E: From<Error> + From<string::FromUtf8Error> + From<str::Utf8Error> + From<T::Err>,
{
    text_err(reader, buf, |t| {
        f(t.parse()?);
        Ok(())
    })
}

pub fn text<R, F, E>(reader: &mut Reader<R>, buf: &mut Vec<u8>, f: F) -> Result<(), E>
where
    R: BufRead,
    F: FnOnce(Cow<'_, str>),
    E: From<Error> + From<string::FromUtf8Error> + From<str::Utf8Error>,
{
    text_err(reader, buf, |t| {
        f(t);
        Ok(())
    })
}

pub fn text_err<R, F, E>(reader: &mut Reader<R>, buf: &mut Vec<u8>, f: F) -> Result<(), E>
where
    R: BufRead,
    F: FnOnce(Cow<'_, str>) -> Result<(), E>,
    E: From<Error> + From<string::FromUtf8Error> + From<str::Utf8Error>,
{
    text_as_bytes_err(reader, buf, |b| f(decode_cow_text::<E>(b)?))
}

pub fn text_as_escaped_bytes_err<R, F, T, E>(
    reader: &mut Reader<R>,
    buf: &mut Vec<u8>,
    f: F,
) -> Result<T, E>
where
    R: BufRead,
    F: FnOnce(&[u8]) -> Result<T, E>,
    E: From<Error>,
{
    loop {
        buf.clear();
        match reader.read_event(buf).map_err(Error::Xml)? {
            Event::Start(_) => return Err(Error::UnexpectedElement).map_err(Into::into),
            Event::End(_) => {
                return f(&[]);
            }
            Event::Text(text) | Event::CData(text) => {
                let val = f(&text)?;
                end_tag_immediately(reader, buf)?;
                return Ok(val);
            }
            Event::Eof => return Err(Error::UnexpectedEndOfFile).map_err(Into::into),
            _ => {}
        }
    }
}

pub fn text_as_bytes_err<R, F, T, E>(
    reader: &mut Reader<R>,
    buf: &mut Vec<u8>,
    f: F,
) -> Result<T, E>
where
    R: BufRead,
    F: FnOnce(Cow<'_, [u8]>) -> Result<T, E>,
    E: From<Error>,
{
    loop {
        buf.clear();
        match reader.read_event(buf).map_err(Error::Xml)? {
            Event::Start(_) => return Err(Error::UnexpectedElement).map_err(Into::into),
            Event::End(_) => {
                return f(Cow::Borrowed(&[]));
            }
            Event::Text(text) | Event::CData(text) => {
                let text = text.unescaped().map_err(Into::into)?;
                let val = f(text)?;
                end_tag_immediately(reader, buf)?;
                return Ok(val);
            }
            Event::Eof => return Err(Error::UnexpectedEndOfFile).map_err(Into::into),
            _ => {}
        }
    }
}

fn end_tag_immediately<R, E>(reader: &mut Reader<R>, buf: &mut Vec<u8>) -> Result<(), E>
where
    R: BufRead,
    E: From<Error>,
{
    loop {
        buf.clear();
        match reader.read_event(buf).map_err(Error::Xml)? {
            Event::Start(_) => return Err(Error::UnexpectedElement).map_err(Into::into),
            Event::End(_) => return Ok(()),
            Event::Eof => return Err(Error::UnexpectedEndOfFile).map_err(Into::into),
            _ => {}
        }
    }
}

pub fn reencode_children<R>(
    reader: &mut Reader<R>,
    buf: &mut Vec<u8>,
    target_buf: &mut Vec<u8>,
) -> Result<(), Error>
where
    R: BufRead,
{
    reader.expand_empty_elements(false);
    let mut writer = Writer::new(target_buf);
    let mut depth = 0;
    loop {
        buf.clear();
        match reader.read_event(buf)? {
            Event::Start(start) => {
                depth += 1;
                writer.write_event(Event::Start(start))?;
            }
            Event::End(end) => {
                if depth == 0 {
                    reader.expand_empty_elements(true);
                    return Ok(());
                }
                depth -= 1;
                writer.write_event(Event::End(end))?;
            }
            event @ Event::Text(_)
            | event @ Event::Comment(_)
            | event @ Event::CData(_)
            | event @ Event::PI(_)
            | event @ Event::Empty(_) => {
                writer.write_event(event)?;
            }
            Event::Decl(_) => {
                // Shouldn't really be a child anyway.
            }
            Event::DocType(_) => {
                // A DOCTYPE is not allowed in content.
            }
            Event::Eof => return Err(Error::UnexpectedEndOfFile),
        }
    }
}

pub fn end_tag<R, E>(reader: &mut Reader<R>, buf: &mut Vec<u8>) -> Result<(), E>
where
    R: BufRead,
    E: From<Error>,
{
    let mut depth = 0;
    loop {
        buf.clear();
        match reader.read_event(buf).map_err(Error::Xml)? {
            Event::Start(_) => {
                depth += 1;
            }
            Event::End(_) => {
                if depth == 0 {
                    return Ok(());
                }
                depth -= 1;
            }
            Event::Eof => return Err(Error::UnexpectedEndOfFile).map_err(Into::into),
            _ => {}
        }
    }
}

pub fn single_child<R, F, T, E>(
    reader: &mut Reader<R>,
    buf: &mut Vec<u8>,
    tag: &[u8],
    mut f: F,
) -> Result<T, E>
where
    R: BufRead,
    F: FnMut(&mut Reader<R>, Tag<'_>) -> Result<T, E>,
    E: From<Error>,
{
    let mut val = None;
    parse_children::<_, _, E>(reader, buf, |reader, t| {
        if t.name() == tag && val.is_none() {
            val = Some(f(reader, t)?);
            Ok(())
        } else {
            end_tag(reader, t.into_buf())
        }
    })?;
    val.ok_or(Error::ElementNotFound).map_err(Into::into)
}

pub fn parse_children<R, F, E>(reader: &mut Reader<R>, buf: &mut Vec<u8>, mut f: F) -> Result<(), E>
where
    R: BufRead,
    F: FnMut(&mut Reader<R>, Tag<'_>) -> Result<(), E>,
    E: From<Error>,
{
    unsafe {
        let ptr_buf: *mut Vec<u8> = buf;
        loop {
            buf.clear();
            match reader.read_event(buf).map_err(Error::Xml)? {
                Event::Start(start) => {
                    let tag = Tag::new(start, ptr_buf);
                    f(reader, tag)?;
                }
                Event::End(_) => return Ok(()),
                Event::Eof => return Err(Error::UnexpectedEndOfFile).map_err(Into::into),
                _ => {}
            }
        }
    }
}

pub fn parse_base<R, F, E>(
    reader: &mut Reader<R>,
    buf: &mut Vec<u8>,
    tag: &[u8],
    mut f: F,
) -> Result<(), E>
where
    R: BufRead,
    F: FnMut(&mut Reader<R>, Tag<'_>) -> Result<(), E>,
    E: From<Error>,
{
    unsafe {
        let ptr_buf: *mut Vec<u8> = buf;
        loop {
            buf.clear();
            match reader.read_event(buf).map_err(Error::Xml)? {
                Event::Start(start) => {
                    if start.name() == tag {
                        let tag = Tag::new(start, ptr_buf);
                        return f(reader, tag);
                    } else {
                        return Err(Error::ElementNotFound).map_err(Into::into);
                    }
                }
                Event::Eof => return Err(Error::UnexpectedEndOfFile).map_err(Into::into),
                _ => {}
            }
        }
    }
}

pub fn parse_attributes<F, E>(tag: &BytesStart<'_>, mut f: F) -> Result<(), E>
where
    F: FnMut(&[u8], AttributeValue<'_>) -> Result<bool, E>,
    E: From<Error>,
{
    for attribute in tag.attributes().with_checks(false) {
        let attribute = attribute.map_err(Error::Xml)?;
        let key = attribute.key;
        if !f(key, AttributeValue(&attribute))? {
            return Ok(());
        }
    }
    Ok(())
}

pub fn optional_attribute_err<F, E>(tag: &BytesStart<'_>, key: &[u8], mut f: F) -> Result<(), E>
where
    F: FnMut(Cow<'_, str>) -> Result<(), E>,
    E: From<Error>,
{
    parse_attributes(tag, |k, v| {
        if k == key {
            f(v.get()?)?;
            Ok(false)
        } else {
            Ok(true)
        }
    })
}

pub fn attribute_err<F, E>(tag: &BytesStart<'_>, key: &[u8], mut f: F) -> Result<(), E>
where
    F: FnMut(Cow<'_, str>) -> Result<(), E>,
    E: From<Error>,
{
    let mut called = false;
    parse_attributes::<_, E>(tag, |k, v| {
        if k == key {
            f(v.get()?)?;
            called = true;
            Ok(false)
        } else {
            Ok(true)
        }
    })?;
    if called {
        Ok(())
    } else {
        Err(Error::AttributeNotFound).map_err(Into::into)
    }
}

pub fn attribute<F, E>(tag: &BytesStart<'_>, key: &[u8], mut f: F) -> Result<(), E>
where
    F: FnMut(Cow<'_, str>),
    E: From<Error>,
{
    attribute_err(tag, key, |t| {
        f(t);
        Ok(())
    })
}
<|endoftext|>


<commit_before>use itertools::Itertools;

fn day10(input: &str) -> (usize, usize) {
    let mut i = 1;
    let mut next = String::from(input);
    let mut part1 = 0;
    let mut part2 = 0;
    loop {
        let mut buf = String::new();
        for (number, list) in next.chars().group_by(|&x| x) {
            buf.push_str(&list.len().to_string());
            buf.push(number);
        }
        next = buf;
        if i == 40 {
            part1 = next.len();
        }
        if i == 50 {
            part2 = next.len();
        }
        i += 1;
        if i == 51 {
            break;
        }
    }
    return (part1, part2);
}

pub fn main() {
    let (part1, part2) = day10("3113322113");
    println!("Part 1: {}\nPart 2: {}", part1, part2);
}

#[test]
fn test() {
    let (part1, part2) = day10("3113322113");
    assert_eq!(part1, 329356);
    assert_eq!(part2, 4666278);
}
<commit_msg>optimize rust day10 a little further to avoid allocations<commit_after>use itertools::Itertools;

fn day10(input: &str) -> (usize, usize) {
    let mut i = 1;
    let mut next = String::from(input);
    let mut part1 = 0;
    let mut part2 = 0;
    loop {
        // worst case size is double the digits
        let mut buf = String::with_capacity(next.len() * 2);
        for (number, list) in next.chars().group_by(|&x| x) {
            buf.push_str(&list.len().to_string());
            buf.push(number);
        }
        next = buf;
        if i == 40 {
            part1 = next.len();
        }
        if i == 50 {
            part2 = next.len();
        }
        i += 1;
        if i == 51 {
            break;
        }
    }
    return (part1, part2);
}

pub fn main() {
    let (part1, part2) = day10("3113322113");
    println!("Part 1: {}\nPart 2: {}", part1, part2);
}

#[test]
fn test() {
    let (part1, part2) = day10("3113322113");
    assert_eq!(part1, 329356);
    assert_eq!(part2, 4666278);
}
<|endoftext|>


<commit_before>use std::fmt;
use std::error;

use parsers::ParseError;

#[derive(Debug, Clone, PartialEq)]
pub enum AttributeError {
    // parse error
    Parse (ParseError),

    // invalid value
    Value (String)
}

#[derive(Debug, Clone, PartialEq)]
pub struct NodeError {
    attr_name: &'static str,
    err:       AttributeError
}

impl NodeError {
    pub fn parse_error (attr_name: &'static str, error: ParseError) -> NodeError {
        NodeError {
            attr_name: attr_name,
            err: AttributeError::Parse (error)
        }
    }

    pub fn value_error (attr_name: &'static str, description: String) -> NodeError {
        NodeError {
            attr_name: attr_name,
            err: AttributeError::Value (description)
        }
    }
}

impl error::Error for NodeError {
    fn description (&self) -> &str {
        match self.err {
            AttributeError::Parse (ref n) => &"parse error",
            AttributeError::Value (_) => &"invalid attribute value"
        }
    }
}

impl fmt::Display for NodeError {
    fn fmt (&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.err {
            AttributeError::Parse (ref n) => write! (f,
                                                     "error parsing value for attribute \"{}\": {}",
                                                     self.attr_name,
                                                     n.display),

            AttributeError::Value (ref s) => write! (f,
                                                     "invalid value for attribute \"{}\": {}",
                                                     self.attr_name,
                                                     s)
        }
    }
}

impl From<ParseError> for AttributeError {
    fn from (pe: ParseError) -> AttributeError {
        AttributeError::Parse (pe)
    }
}

pub fn is_parse_error<T> (r: &Result<T, AttributeError>) -> bool {
    match *r {
        Err (AttributeError::Parse (_)) => true,
        _ => false
    }
}

pub fn is_value_error<T> (r: &Result<T, AttributeError>) -> bool {
    match *r {
        Err (AttributeError::Value (_)) => true,
        _ => false
    }
}
<commit_msg>error.rs: Remove unused argument<commit_after>use std::fmt;
use std::error;

use parsers::ParseError;

#[derive(Debug, Clone, PartialEq)]
pub enum AttributeError {
    // parse error
    Parse (ParseError),

    // invalid value
    Value (String)
}

#[derive(Debug, Clone, PartialEq)]
pub struct NodeError {
    attr_name: &'static str,
    err:       AttributeError
}

impl NodeError {
    pub fn parse_error (attr_name: &'static str, error: ParseError) -> NodeError {
        NodeError {
            attr_name: attr_name,
            err: AttributeError::Parse (error)
        }
    }

    pub fn value_error (attr_name: &'static str, description: String) -> NodeError {
        NodeError {
            attr_name: attr_name,
            err: AttributeError::Value (description)
        }
    }
}

impl error::Error for NodeError {
    fn description (&self) -> &str {
        match self.err {
            AttributeError::Parse (_) => &"parse error",
            AttributeError::Value (_) => &"invalid attribute value"
        }
    }
}

impl fmt::Display for NodeError {
    fn fmt (&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.err {
            AttributeError::Parse (ref n) => write! (f,
                                                     "error parsing value for attribute \"{}\": {}",
                                                     self.attr_name,
                                                     n.display),

            AttributeError::Value (ref s) => write! (f,
                                                     "invalid value for attribute \"{}\": {}",
                                                     self.attr_name,
                                                     s)
        }
    }
}

impl From<ParseError> for AttributeError {
    fn from (pe: ParseError) -> AttributeError {
        AttributeError::Parse (pe)
    }
}

pub fn is_parse_error<T> (r: &Result<T, AttributeError>) -> bool {
    match *r {
        Err (AttributeError::Parse (_)) => true,
        _ => false
    }
}

pub fn is_value_error<T> (r: &Result<T, AttributeError>) -> bool {
    match *r {
        Err (AttributeError::Value (_)) => true,
        _ => false
    }
}
<|endoftext|>