<commit_before>use term_painter::ToStyle;
use term_painter::Color::*;

pub mod types;
pub mod helper;

// Game logic (board, initialization, valid move, set, play or finished)

/// Visualization of the boards.
fn print_boards(board1: &Vec<types::SubField>, board2: &Vec<types::SubField>) {
    println!("{}{}", "------------------ O W N   B O A R D ------------------",
        "-------------------------- O P P O N E N T ---------------");

    let mut cnt = 9;

    for i in 0..10 {
        print!("\n{0:<width$}", cnt, width=3);
        for j in 0..10 {
            if board1[j + i * 10] == types::SubField::Hit {
                print!(" {} ", Red.paint(board1[j + i * 10]));
            } else {
                print!(" {} ", board1[j + i * 10]);
            }
        }
        print!("        ");
        print!("{}  ", cnt);
        for j in 0..10 {
            if board2[j + i * 10] == types::SubField::Hit {
                print!(" {} ", Green.paint(board2[j + i * 10]));
            } else {
                print!(" {} ", board2[j + i * 10]);
            }
        }
        println!("");
        cnt -= 1;
    }
    println!("");
    println!("{}{}", "     A    B    C    D    E    F    G    H    I    J",
        "               A    B    C    D    E    F    G    H    I    J");
    println!("");
    println!("{}{}", "----------------------------------------------------",
        "-------------------------------------------------------------");
}

/// The actual placement of the ships.
fn place(player: &mut types::Player, ship: &types::ShipType) -> Result<(), String> {

    /* Vector to collect the indices for the possible ship position. */
    let mut indices = Vec::new();

    let mut input = get_input();
    loop {
        match player.own_board[input] {
            types::SubField::Water => { indices.push(input); break; },
            _ => {
                println!("Invalid input, again please.");
                input = get_input();
            },
        }
    }

    println!(
    "Enter 'h' for a horizontal (rightwards) orientation of the ship,
    'v' for a vertical (upwards) one."
    );

    let mut ori = helper::read_string();
    loop {
        match ori.as_str() {
            "h" | "v" => break,
            _ => {
                println!("Invalid input, again please.");
                ori = helper::read_string();
            }
        }
    }

    if ori == "v" {
        for i in 0..ship.size - 1 {
            /* input < 10 --> no field above */
            println!("{}", input);
            if player.own_board[input] != types::SubField::Water
                || (input < 10 && i != ship.size - 1) {
                    return Err("Invalid position for this ship, please choose another coordinate."
                        .to_string())
            }
            indices.push(input - 10);
        }
    } else {
        for i in 0..ship.size - 1 {
            /* unit position == 9 --> no field to the right */
            if player.own_board[input] != types::SubField::Water
                || ((input % 10) == 9 && i != ship.size - 1) {
                    return Err("Invalid position for this ship, please choose another coordinate."
                        .to_string())
            }
            indices.push(input + 1);
        }
    }

    /* Places the ships on the board. */
    for i in indices.iter() {
        player.own_board[*i] = types::SubField::Ship;
    }

    Ok(())
}

/// Handles the initial ship placement for each player.
fn place_ships(mut player1: &mut types::Player, mut player2: &mut types::Player) {

    /* A vector of all the ships each player needs to place.
       The default version: #  Class of ship Size
                            4   Submarine     2
                            3   Destroyer     3
                            2   Cruiser       4
                            1   Battleship    5
    */
    let s1 = types::ShipType{ name: "Submarine".to_string(), size: 2, amount: 4 };
    let s2 = types::ShipType{ name: "Destroyer".to_string(), size: 3, amount: 3 };
    let s3 = types::ShipType{ name: "Cruiser".to_string(), size: 4, amount: 2 };
    let s4 = types::ShipType{ name: "Battleship".to_string(), size: 5, amount: 1 };
    let ships = vec![s1, s2, s3, s4];

    print_boards(&player1.own_board, &player1.op_board);

    /* Asks player1 to place the ships. */
    for i in ships.iter() {
        for _ in 0..i.amount {
            loop {
                println!("{}, please enter the first coordinate for your {:?} ({} fields).",
                    player1.name, i.name, i.size);
                match place(&mut player1, i) {
                    Ok(_) => { break; },
                    Err(e) => { println!("{}", e); },
                }
            }
            player1.capacity += i.size;
            print_boards(&player1.own_board, &player1.op_board);
        }
    }

    /* Asks player2 to place the ships. */
    for i in ships.iter() {
        for _ in 0..i.amount {
            loop {
                println!("{}, please enter the first coordinate for your {:?} ({} fields).",
                    player2.name, i.name, i.size);
                match place(&mut player2, i) {
                    Ok(_) => { break; },
                    Err(e) => { println!("{}", e); },
                }
            }
            player2.capacity += i.size;
            print_boards(&player2.own_board, &player2.op_board);
        }
    }
}

/// Reads the coordinates of a field from the user
/// and returns the corresponding index.
fn get_input() -> usize {

    /* 100 --> invalid */
    let mut input = 100;

    while input == 100 {
        input = match helper::read_string().as_ref() {
            "A0" => 90, "A1" => 80,"A2" => 70, "A3" => 60, "A4" => 50,
            "A5" => 40, "A6" => 30, "A7" => 20, "A8" => 10, "A9" => 0,
            "B0" => 91, "B1" => 81, "B2" => 71, "B3" => 61, "B4" => 51,
            "B5" => 41, "B6" => 31, "B7" => 21, "B8" => 11, "B9" => 1,
            "C0" => 92, "C1" => 82, "C2" => 72, "C3" => 62, "C4" => 52,
            "C5" => 42, "C6" => 32, "C7" => 22, "C8" => 12, "C9" => 2,
            "D0" => 93, "D1" => 83, "D2" => 73, "D3" => 63, "D4" => 53,
            "D5" => 43, "D6" => 33, "D7" => 23, "D8" => 13, "D9" => 3,
            "E0" => 94, "E1" => 84, "E2" => 74, "E3" => 64, "E4" => 54,
            "E5" => 44, "E6" => 34, "E7" => 24, "E8" => 14, "E9" => 4,
            "F0" => 95, "F1" => 85, "F2" => 75, "F3" => 65, "F4" => 55,
            "F5" => 45, "F6" => 35, "F7" => 25, "F8" => 15, "F9" => 5,
            "G0" => 96, "G1" => 86, "G2" => 76, "G3" => 66, "G4" => 56,
            "G5" => 46, "G6" => 36, "G7" => 26, "G8" => 16, "G9" => 6,
            "H0" => 97, "H1" => 87, "H2" => 77, "H3" => 67, "H4" => 57,
            "H5" => 47, "H6" => 37, "H7" => 27, "H8" => 17, "H9" => 7,
            "I0" => 98, "I1" => 88, "I2" => 78, "I3" => 68, "I4" => 58,
            "I5" => 48, "I6" => 38, "I7" => 28, "I8" => 18, "I9" => 8,
            "J0" => 99, "J1" => 89, "J2" => 79, "J3" => 69, "J4" => 59,
            "J5" => 49, "J6" => 39, "J7" => 29, "J8" => 19, "J9" => 9,
            _ => 100,
        };

        if input == 100 {
            println!("Invalid field, try again.")
        }
    }
    input
}

/// Determines the type of the SubField that got hit
/// by the current move and sets it accordingly.
fn match_move(first: &mut types::Player, second: &mut types::Player, idx: usize) {

    match second.own_board[idx] {
        types::SubField::Water => {
            println!("Miss - try again.");
            first.op_board[idx] = types::SubField::WaterHit;
        }
        types::SubField::Ship => {
            println!("Hit!");
            first.op_board[idx] = types::SubField::Hit;
            second.own_board[idx] = types::SubField::Hit;
            second.capacity -= 1;
        },
        types::SubField::Hit => { println!("Already hit."); }
        types::SubField::WaterHit => { println!("Miss - try again."); }
    }
}

/// Lets the players perform their moves.
fn make_move(mut first: &mut types::Player, mut second: &mut types::Player) {
    println!("Enter coordinates, {}:", first.name);
    let input = get_input();
    match_move(&mut first, &mut second, input);
}

/// Returns whether all the player's ships got destroyed.
pub fn game_over(player: &types::Player) -> bool {
    player.capacity <= 0
}

/// Initializes the players and the boards and provides the
/// game loop which lets the players perform their moves alternately.
pub fn start_round() {

    /* Creates the initial (empty) boards (10 x 10) for player1. */
    let mut player1 = types::Player {
        own_board: vec![types::SubField::Water; 100],
        op_board: vec![types::SubField::Water; 100],
        capacity: 0,
        name: "Player1".to_string(),
    };
    /* Creates the initial (empty) boards (10 x 10) for player2. */
    let mut player2 = types::Player {
        own_board: vec![types::SubField::Water; 100],
        op_board: vec![types::SubField::Water; 100],
        capacity: 0,
        name: "Player2".to_string(),
    };

    /* Initializes the boards with the player's ships. */
    place_ships(&mut player1, &mut player2);

    loop {
        print_boards(&player1.own_board, &player1.op_board);
        make_move(&mut player1, &mut player2);
        if game_over(&player2) {
            println!("G A M E   O V E R");
            println!("Congratulations, Player1");
            break;
        }

        print_boards(&player2.own_board, &player2.op_board);
        make_move(&mut player2, &mut player1);
        if game_over(&player1) {
            println!("G A M E   O V E R");
            println!("Congratulations, Player2");
            break;
        }
    }
}
<commit_msg>fixed placement bug<commit_after>use term_painter::ToStyle;
use term_painter::Color::*;

pub mod types;
pub mod helper;

// Game logic (board, initialization, valid move, set, play or finished)

/// Visualization of the boards.
fn print_boards(board1: &Vec<types::SubField>, board2: &Vec<types::SubField>) {
    println!("{}{}", "------------------ O W N   B O A R D ------------------",
        "-------------------------- O P P O N E N T ---------------");

    let mut cnt = 9;

    for i in 0..10 {
        print!("\n{0:<width$}", cnt, width=3);
        for j in 0..10 {
            if board1[j + i * 10] == types::SubField::Hit {
                print!(" {} ", Red.paint(board1[j + i * 10]));
            } else {
                print!(" {} ", board1[j + i * 10]);
            }
        }
        print!("        ");
        print!("{}  ", cnt);
        for j in 0..10 {
            if board2[j + i * 10] == types::SubField::Hit {
                print!(" {} ", Green.paint(board2[j + i * 10]));
            } else {
                print!(" {} ", board2[j + i * 10]);
            }
        }
        println!("");
        cnt -= 1;
    }
    println!("");
    println!("{}{}", "     A    B    C    D    E    F    G    H    I    J",
        "               A    B    C    D    E    F    G    H    I    J");
    println!("");
    println!("{}{}", "----------------------------------------------------",
        "-------------------------------------------------------------");
}

/// The actual placement of the ships.
fn place(player: &mut types::Player, ship: &types::ShipType) -> Result<(), String> {

    /* Vector to collect the indices for the possible ship position. */
    let mut indices = Vec::new();

    let mut input = get_input();
    loop {
        match player.own_board[input] {
            types::SubField::Water => { indices.push(input); break; },
            _ => {
                println!("Invalid input, again please.");
                input = get_input();
            },
        }
    }

    println!(
    "Enter 'h' for a horizontal (rightwards) orientation of the ship,
    'v' for a vertical (upwards) one."
    );

    let mut ori = helper::read_string();
    loop {
        match ori.as_str() {
            "h" | "v" => break,
            _ => {
                println!("Invalid input, again please.");
                ori = helper::read_string();
            }
        }
    }

    if ori == "v" {
        for i in 0..ship.size - 1 {
            /* input < 10 --> no field above */
            if player.own_board[input] != types::SubField::Water
                || input < 10 && i != ship.size - 1 {
                    return Err("Invalid position for this ship, please choose another coordinate."
                        .to_string())
            }
            input -= 10;
            indices.push(input);
        }
    } else {
        for i in 0..ship.size - 1 {
            /* unit position == 9 --> no field to the right */
            if player.own_board[input] != types::SubField::Water
                || (input % 10) == 9 && i != ship.size - 1 {
                    return Err("Invalid position for this ship, please choose another coordinate."
                        .to_string())
            }
            input += 1;
            indices.push(input);
        }
    }

    /* Places the ships on the board. */
    for i in indices.iter() {
        player.own_board[*i] = types::SubField::Ship;
    }

    Ok(())
}

/// Handles the initial ship placement for each player.
fn place_ships(mut player1: &mut types::Player, mut player2: &mut types::Player) {

    /* A vector of all the ships each player needs to place.
       The default version: #  Class of ship Size
                            4   Submarine     2
                            3   Destroyer     3
                            2   Cruiser       4
                            1   Battleship    5
    */
    let s1 = types::ShipType{ name: "Submarine".to_string(), size: 2, amount: 4 };
    let s2 = types::ShipType{ name: "Destroyer".to_string(), size: 3, amount: 3 };
    let s3 = types::ShipType{ name: "Cruiser".to_string(), size: 4, amount: 2 };
    let s4 = types::ShipType{ name: "Battleship".to_string(), size: 5, amount: 1 };
    let ships = vec![s1, s2, s3, s4];

    print_boards(&player1.own_board, &player1.op_board);

    /* Asks player1 to place the ships. */
    for i in ships.iter() {
        for _ in 0..i.amount {
            loop {
                println!("{}, please enter the first coordinate for your {:?} ({} fields).",
                    player1.name, i.name, i.size);
                match place(&mut player1, i) {
                    Ok(_) => { break; },
                    Err(e) => { println!("{}", e); },
                }
            }
            player1.capacity += i.size;
            print_boards(&player1.own_board, &player1.op_board);
        }
    }

    /* Asks player2 to place the ships. */
    for i in ships.iter() {
        for _ in 0..i.amount {
            loop {
                println!("{}, please enter the first coordinate for your {:?} ({} fields).",
                    player2.name, i.name, i.size);
                match place(&mut player2, i) {
                    Ok(_) => { break; },
                    Err(e) => { println!("{}", e); },
                }
            }
            player2.capacity += i.size;
            print_boards(&player2.own_board, &player2.op_board);
        }
    }
}

/// Reads the coordinates of a field from the user
/// and returns the corresponding index.
fn get_input() -> usize {

    /* 100 --> invalid */
    let mut input = 100;

    while input == 100 {
        input = match helper::read_string().as_ref() {
            "A0" => 90, "A1" => 80,"A2" => 70, "A3" => 60, "A4" => 50,
            "A5" => 40, "A6" => 30, "A7" => 20, "A8" => 10, "A9" => 0,
            "B0" => 91, "B1" => 81, "B2" => 71, "B3" => 61, "B4" => 51,
            "B5" => 41, "B6" => 31, "B7" => 21, "B8" => 11, "B9" => 1,
            "C0" => 92, "C1" => 82, "C2" => 72, "C3" => 62, "C4" => 52,
            "C5" => 42, "C6" => 32, "C7" => 22, "C8" => 12, "C9" => 2,
            "D0" => 93, "D1" => 83, "D2" => 73, "D3" => 63, "D4" => 53,
            "D5" => 43, "D6" => 33, "D7" => 23, "D8" => 13, "D9" => 3,
            "E0" => 94, "E1" => 84, "E2" => 74, "E3" => 64, "E4" => 54,
            "E5" => 44, "E6" => 34, "E7" => 24, "E8" => 14, "E9" => 4,
            "F0" => 95, "F1" => 85, "F2" => 75, "F3" => 65, "F4" => 55,
            "F5" => 45, "F6" => 35, "F7" => 25, "F8" => 15, "F9" => 5,
            "G0" => 96, "G1" => 86, "G2" => 76, "G3" => 66, "G4" => 56,
            "G5" => 46, "G6" => 36, "G7" => 26, "G8" => 16, "G9" => 6,
            "H0" => 97, "H1" => 87, "H2" => 77, "H3" => 67, "H4" => 57,
            "H5" => 47, "H6" => 37, "H7" => 27, "H8" => 17, "H9" => 7,
            "I0" => 98, "I1" => 88, "I2" => 78, "I3" => 68, "I4" => 58,
            "I5" => 48, "I6" => 38, "I7" => 28, "I8" => 18, "I9" => 8,
            "J0" => 99, "J1" => 89, "J2" => 79, "J3" => 69, "J4" => 59,
            "J5" => 49, "J6" => 39, "J7" => 29, "J8" => 19, "J9" => 9,
            _ => 100,
        };

        if input == 100 {
            println!("Invalid field, try again.")
        }
    }
    input
}

/// Determines the type of the SubField that got hit
/// by the current move and sets it accordingly.
fn match_move(first: &mut types::Player, second: &mut types::Player, idx: usize) {

    match second.own_board[idx] {
        types::SubField::Water => {
            println!("Miss - try again.");
            first.op_board[idx] = types::SubField::WaterHit;
        }
        types::SubField::Ship => {
            println!("Hit!");
            first.op_board[idx] = types::SubField::Hit;
            second.own_board[idx] = types::SubField::Hit;
            second.capacity -= 1;
        },
        types::SubField::Hit => { println!("Already hit."); }
        types::SubField::WaterHit => { println!("Miss - try again."); }
    }
}

/// Lets the players perform their moves.
fn make_move(mut first: &mut types::Player, mut second: &mut types::Player) {
    println!("Enter coordinates, {}:", first.name);
    let input = get_input();
    match_move(&mut first, &mut second, input);
}

/// Returns whether all the player's ships got destroyed.
pub fn game_over(player: &types::Player) -> bool {
    player.capacity <= 0
}

/// Initializes the players and the boards and provides the
/// game loop which lets the players perform their moves alternately.
pub fn start_round() {

    /* Creates the initial (empty) boards (10 x 10) for player1. */
    let mut player1 = types::Player {
        own_board: vec![types::SubField::Water; 100],
        op_board: vec![types::SubField::Water; 100],
        capacity: 0,
        name: "Player1".to_string(),
    };
    /* Creates the initial (empty) boards (10 x 10) for player2. */
    let mut player2 = types::Player {
        own_board: vec![types::SubField::Water; 100],
        op_board: vec![types::SubField::Water; 100],
        capacity: 0,
        name: "Player2".to_string(),
    };

    /* Initializes the boards with the player's ships. */
    place_ships(&mut player1, &mut player2);

    loop {
        print_boards(&player1.own_board, &player1.op_board);
        make_move(&mut player1, &mut player2);
        if game_over(&player2) {
            println!("G A M E   O V E R");
            println!("Congratulations, Player1");
            break;
        }

        print_boards(&player2.own_board, &player2.op_board);
        make_move(&mut player2, &mut player1);
        if game_over(&player1) {
            println!("G A M E   O V E R");
            println!("Congratulations, Player2");
            break;
        }
    }
}
<|endoftext|>


<commit_before>use std;
use std::error::Error;
use std::fmt;
use std::ops::{Add, Sub};

#[derive(Debug, PartialEq)]
pub enum MsfParseError {
    ParseIntError(std::num::ParseIntError),
    OutOfRangeError,
    InvalidMsfError
}

impl Error for MsfParseError {
    fn description(&self) -> &str {
        "Could not parse MSF Timestamp"
    }

    fn cause(&self) -> Option<&Error> {
        use MsfParseError::*;
        match *self {
            ParseIntError(ref inner_err) => Some(inner_err),
            _ => None
        }
    }
}

impl fmt::Display for MsfParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
    }
}

impl From<std::num::ParseIntError> for MsfParseError {
    fn from(err: std::num::ParseIntError) -> MsfParseError {
        MsfParseError::ParseIntError(err)
    }
}

// MsfIndex(minutes, seconds, frame), not BCD encoded
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
pub struct MsfIndex(u8, u8, u8);

impl MsfIndex {
    pub fn new(m: u8, s: u8, f: u8) -> Result<MsfIndex, MsfParseError> {
        if m > 99 || s > 59 || f > 74 {
            Err(MsfParseError::OutOfRangeError)
        } else {
            Ok(MsfIndex(m,s,f))
        }
    }

    pub fn from_bcd_values(m_bcd: u8, s_bcd: u8, f_bcd: u8) -> Result<MsfIndex, MsfParseError> {
        if (m_bcd & 0xf0) > 0x90 || (m_bcd & 0x0f) > 0x09 ||
           (s_bcd & 0xf0) > 0x90 || (s_bcd & 0x0f) > 0x09 ||
           (f_bcd & 0xf0) > 0x90 || (f_bcd & 0x0f) > 0x09 {
            Err(MsfParseError::OutOfRangeError)
        } else {
            let m = (m_bcd >> 4) * 10 + (m_bcd & 0x0f);
            let s = (s_bcd >> 4) * 10 + (s_bcd & 0x0f);
            let f = (f_bcd >> 4) * 10 + (f_bcd & 0x0f);
            debug!("from_bcd_values: Converted (0x{:x}, 0x{:x}, 0x{:x}) to ({}, {}, {})",
                   m_bcd, s_bcd, f_bcd, m, s, f);
            MsfIndex::new(m,s,f)
        }
    }

    pub fn try_from_str(s: &str) -> Result<MsfIndex, MsfParseError> {
        let s = s.trim();
        let colon_matches = s.split(":").collect::<Vec<&str>>();
        debug!("{:?}", colon_matches);
        if colon_matches.len() == 3 {
            let (m, s, f) = (
                colon_matches[0].parse()?,
                colon_matches[1].parse()?,
                colon_matches[2].parse()?
            );
            MsfIndex::new(m, s, f)
        } else {
            Err(MsfParseError::InvalidMsfError)
        }
    }

    pub fn to_offset(&self) -> usize {
        let MsfIndex(m,s,f) = (*self - MsfIndex::new(0, 2, 0).unwrap()).unwrap();
        (m as usize * 60 * 75 + s as usize * 75 + f as usize) * 2352
    }

    pub fn next(&self) -> Result<MsfIndex, MsfOverflow> {
        *self + MsfIndex::new(0, 0, 1).unwrap()
    }

    pub fn to_bcd_values(&self) -> (u8, u8, u8) {
        let MsfIndex(m,s,f) = *self;
        let m_bcd = ((m / 10) << 4) | m & 0x0f;
        let s_bcd = ((s / 10) << 4) | s & 0x0f;
        let f_bcd = ((f / 10) << 4) | f & 0x0f;
        (m_bcd, s_bcd, f_bcd)
    }
}

impl fmt::Display for MsfIndex {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({}, {}, {})", self.0, self.1, self.2)
    }
}

#[derive(Debug)]
pub enum MsfOperation {
    Add,
    Sub
}

impl fmt::Display for MsfOperation {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::MsfOperation::*;
        match *self {
            Add => write!(f, "+"),
            Sub => write!(f, "-")
        }
    }
}

#[derive(Debug)]
pub struct MsfOverflow(MsfOperation, MsfIndex, MsfIndex);

impl Error for MsfOverflow {
    fn description(&self) -> &str {
        "Addition of two MsfIndex values overflowed"
    }

    fn cause(&self) -> Option<&Error> {
        None
    }
}

impl fmt::Display for MsfOverflow {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "The following operation on these two MsfIndex values overflowed: {} {} {}",
               self.1, self.0, self.2)
    }
}

impl Add for MsfIndex {
    type Output = Result<MsfIndex, MsfOverflow>;

    fn add(self, other: MsfIndex) -> Result<MsfIndex, MsfOverflow> {
        let mut new_msf_tuple = (self.0 + other.0,
                                 self.1 + other.1,
                                 self.2 + other.2);

        // 75 frames -> 1 second
        while new_msf_tuple.2 >= 75 {
            new_msf_tuple.2 -= 75;
            new_msf_tuple.1 += 1;
        }

        // 60 seconds -> 1 minute
        while new_msf_tuple.1 >= 60 {
            new_msf_tuple.1 -= 60;
            new_msf_tuple.0 += 1;
        }

        match MsfIndex::new(new_msf_tuple.0, new_msf_tuple.1, new_msf_tuple.2)
        {
            Ok(result) => Ok(result),
            Err(_) => Err(MsfOverflow(MsfOperation::Add, self, other))
        }
    }
}

impl Sub for MsfIndex {
    type Output = Result<MsfIndex, MsfOverflow>;

    fn sub(self, other: MsfIndex) -> Result<MsfIndex, MsfOverflow> {
        if other > self {
            return Err(MsfOverflow(MsfOperation::Sub, self, other));
        }

        let mut tmp: (i16, i16, i16) = (
            self.0 as i16 - other.0 as i16,
            self.1 as i16 - other.1 as i16,
            self.2 as i16 - other.2 as i16);

        if tmp.2 < 0 {
            tmp.1 -= 1;
            tmp.2 += 75;
        }

        if tmp.1 < 0 {
            tmp.0 -= 1;
            tmp.1 += 60;
        }

        assert!(tmp.0 >= 0, "{} - {}", self, other);

        match MsfIndex::new(tmp.0 as u8, tmp.1 as u8, tmp.2 as u8)
        {
            Ok(result) => Ok(result),
            Err(_) => Err(MsfOverflow(MsfOperation::Sub, self, other))
        }
    }
}

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

    #[test]
    fn msf_index_range() {
        assert_eq!(MsfIndex::new(0, 0, 0).unwrap(), MsfIndex(0, 0, 0));
        assert_eq!(MsfIndex::new(13, 37, 42).unwrap(), MsfIndex(13, 37, 42));
        assert_eq!(MsfIndex::new(99, 59, 74).unwrap(), MsfIndex(99, 59, 74));

        assert_eq!(MsfIndex::new(99, 59, 75), Err(MsfParseError::OutOfRangeError));
        assert_eq!(MsfIndex::new(99, 60, 74), Err(MsfParseError::OutOfRangeError));
        assert_eq!(MsfIndex::new(100, 59, 74), Err(MsfParseError::OutOfRangeError));
    }

    #[test]
    fn msf_add() {
        let msf_0 = MsfIndex::new(0, 0, 0).unwrap();
        let msf_0_0_1 = MsfIndex::new(0, 0, 1).unwrap();
        let msf_13_37_42 = MsfIndex::new(13, 37, 42).unwrap();
        let msf_max_f = MsfIndex::new(0, 0, 74).unwrap();
        let msf_max_sf = MsfIndex::new(0, 59, 74).unwrap();
        let msf_max_msf = MsfIndex::new(99, 59, 74).unwrap();

        assert_eq!((msf_0 + msf_0_0_1).unwrap(), msf_0_0_1);
        assert_eq!((msf_13_37_42 + msf_0_0_1).unwrap(), MsfIndex(13, 37, 43));
        assert_eq!((msf_max_f + msf_0_0_1).unwrap(), MsfIndex(0, 1, 0));
        assert_eq!((msf_max_sf + msf_0_0_1).unwrap(), MsfIndex(1, 0, 0));
        assert!((msf_max_msf + msf_0_0_1).is_err());
    }
}<commit_msg>fix MsfIndex::to_bcd_values<commit_after>use std;
use std::error::Error;
use std::fmt;
use std::ops::{Add, Sub};

#[derive(Debug, PartialEq)]
pub enum MsfParseError {
    ParseIntError(std::num::ParseIntError),
    OutOfRangeError,
    InvalidMsfError
}

impl Error for MsfParseError {
    fn description(&self) -> &str {
        "Could not parse MSF Timestamp"
    }

    fn cause(&self) -> Option<&Error> {
        use MsfParseError::*;
        match *self {
            ParseIntError(ref inner_err) => Some(inner_err),
            _ => None
        }
    }
}

impl fmt::Display for MsfParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
    }
}

impl From<std::num::ParseIntError> for MsfParseError {
    fn from(err: std::num::ParseIntError) -> MsfParseError {
        MsfParseError::ParseIntError(err)
    }
}

// MsfIndex(minutes, seconds, frame), not BCD encoded
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
pub struct MsfIndex(u8, u8, u8);

impl MsfIndex {
    pub fn new(m: u8, s: u8, f: u8) -> Result<MsfIndex, MsfParseError> {
        if m > 99 || s > 59 || f > 74 {
            Err(MsfParseError::OutOfRangeError)
        } else {
            Ok(MsfIndex(m,s,f))
        }
    }

    pub fn from_bcd_values(m_bcd: u8, s_bcd: u8, f_bcd: u8) -> Result<MsfIndex, MsfParseError> {
        if (m_bcd & 0xf0) > 0x90 || (m_bcd & 0x0f) > 0x09 ||
           (s_bcd & 0xf0) > 0x90 || (s_bcd & 0x0f) > 0x09 ||
           (f_bcd & 0xf0) > 0x90 || (f_bcd & 0x0f) > 0x09 {
            Err(MsfParseError::OutOfRangeError)
        } else {
            let m = (m_bcd >> 4) * 10 + (m_bcd & 0x0f);
            let s = (s_bcd >> 4) * 10 + (s_bcd & 0x0f);
            let f = (f_bcd >> 4) * 10 + (f_bcd & 0x0f);
            debug!("from_bcd_values: Converted (0x{:x}, 0x{:x}, 0x{:x}) to ({}, {}, {})",
                   m_bcd, s_bcd, f_bcd, m, s, f);
            MsfIndex::new(m,s,f)
        }
    }

    pub fn try_from_str(s: &str) -> Result<MsfIndex, MsfParseError> {
        let s = s.trim();
        let colon_matches = s.split(":").collect::<Vec<&str>>();
        debug!("{:?}", colon_matches);
        if colon_matches.len() == 3 {
            let (m, s, f) = (
                colon_matches[0].parse()?,
                colon_matches[1].parse()?,
                colon_matches[2].parse()?
            );
            MsfIndex::new(m, s, f)
        } else {
            Err(MsfParseError::InvalidMsfError)
        }
    }

    pub fn to_offset(&self) -> usize {
        let MsfIndex(m,s,f) = (*self - MsfIndex::new(0, 2, 0).unwrap()).unwrap();
        (m as usize * 60 * 75 + s as usize * 75 + f as usize) * 2352
    }

    pub fn next(&self) -> Result<MsfIndex, MsfOverflow> {
        *self + MsfIndex::new(0, 0, 1).unwrap()
    }

    pub fn to_bcd_values(&self) -> (u8, u8, u8) {
        let MsfIndex(m,s,f) = *self;
        let m_bcd = ((m / 10) << 4) + (m % 10);
        let s_bcd = ((s / 10) << 4) + (s % 10);
        let f_bcd = ((f / 10) << 4) + (s % 10);
        (m_bcd, s_bcd, f_bcd)
    }
}

impl fmt::Display for MsfIndex {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({}, {}, {})", self.0, self.1, self.2)
    }
}

#[derive(Debug)]
pub enum MsfOperation {
    Add,
    Sub
}

impl fmt::Display for MsfOperation {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::MsfOperation::*;
        match *self {
            Add => write!(f, "+"),
            Sub => write!(f, "-")
        }
    }
}

#[derive(Debug)]
pub struct MsfOverflow(MsfOperation, MsfIndex, MsfIndex);

impl Error for MsfOverflow {
    fn description(&self) -> &str {
        "Addition of two MsfIndex values overflowed"
    }

    fn cause(&self) -> Option<&Error> {
        None
    }
}

impl fmt::Display for MsfOverflow {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "The following operation on these two MsfIndex values overflowed: {} {} {}",
               self.1, self.0, self.2)
    }
}

impl Add for MsfIndex {
    type Output = Result<MsfIndex, MsfOverflow>;

    fn add(self, other: MsfIndex) -> Result<MsfIndex, MsfOverflow> {
        let mut new_msf_tuple = (self.0 + other.0,
                                 self.1 + other.1,
                                 self.2 + other.2);

        // 75 frames -> 1 second
        while new_msf_tuple.2 >= 75 {
            new_msf_tuple.2 -= 75;
            new_msf_tuple.1 += 1;
        }

        // 60 seconds -> 1 minute
        while new_msf_tuple.1 >= 60 {
            new_msf_tuple.1 -= 60;
            new_msf_tuple.0 += 1;
        }

        match MsfIndex::new(new_msf_tuple.0, new_msf_tuple.1, new_msf_tuple.2)
        {
            Ok(result) => Ok(result),
            Err(_) => Err(MsfOverflow(MsfOperation::Add, self, other))
        }
    }
}

impl Sub for MsfIndex {
    type Output = Result<MsfIndex, MsfOverflow>;

    fn sub(self, other: MsfIndex) -> Result<MsfIndex, MsfOverflow> {
        if other > self {
            return Err(MsfOverflow(MsfOperation::Sub, self, other));
        }

        let mut tmp: (i16, i16, i16) = (
            self.0 as i16 - other.0 as i16,
            self.1 as i16 - other.1 as i16,
            self.2 as i16 - other.2 as i16);

        if tmp.2 < 0 {
            tmp.1 -= 1;
            tmp.2 += 75;
        }

        if tmp.1 < 0 {
            tmp.0 -= 1;
            tmp.1 += 60;
        }

        assert!(tmp.0 >= 0, "{} - {}", self, other);

        match MsfIndex::new(tmp.0 as u8, tmp.1 as u8, tmp.2 as u8)
        {
            Ok(result) => Ok(result),
            Err(_) => Err(MsfOverflow(MsfOperation::Sub, self, other))
        }
    }
}

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

    #[test]
    fn msf_index_range() {
        assert_eq!(MsfIndex::new(0, 0, 0).unwrap(), MsfIndex(0, 0, 0));
        assert_eq!(MsfIndex::new(13, 37, 42).unwrap(), MsfIndex(13, 37, 42));
        assert_eq!(MsfIndex::new(99, 59, 74).unwrap(), MsfIndex(99, 59, 74));

        assert_eq!(MsfIndex::new(99, 59, 75), Err(MsfParseError::OutOfRangeError));
        assert_eq!(MsfIndex::new(99, 60, 74), Err(MsfParseError::OutOfRangeError));
        assert_eq!(MsfIndex::new(100, 59, 74), Err(MsfParseError::OutOfRangeError));
    }

    #[test]
    fn msf_add() {
        let msf_0 = MsfIndex::new(0, 0, 0).unwrap();
        let msf_0_0_1 = MsfIndex::new(0, 0, 1).unwrap();
        let msf_13_37_42 = MsfIndex::new(13, 37, 42).unwrap();
        let msf_max_f = MsfIndex::new(0, 0, 74).unwrap();
        let msf_max_sf = MsfIndex::new(0, 59, 74).unwrap();
        let msf_max_msf = MsfIndex::new(99, 59, 74).unwrap();

        assert_eq!((msf_0 + msf_0_0_1).unwrap(), msf_0_0_1);
        assert_eq!((msf_13_37_42 + msf_0_0_1).unwrap(), MsfIndex(13, 37, 43));
        assert_eq!((msf_max_f + msf_0_0_1).unwrap(), MsfIndex(0, 1, 0));
        assert_eq!((msf_max_sf + msf_0_0_1).unwrap(), MsfIndex(1, 0, 0));
        assert!((msf_max_msf + msf_0_0_1).is_err());
    }
}<|endoftext|>


<commit_before>extern "C" {
    fn getpid() -> i32;
}

fn main() {
    let pid = unsafe { getpid() };
    println!("Hello from {}", pid);

    let snake = Snake {
        cells: vec![Cell { x: 2, y: 0 }, Cell { x: 1, y: 0 }, Cell { x: 0, y: 0 }],
        direction: Direction::Right,
    };

    assert_eq!(
        snake.slide(),
        Snake {
            cells: vec![Cell { x: 3, y: 0 }, Cell { x: 2, y: 0 }, Cell { x: 1, y: 0 }],
            direction: Direction::Right,
        }
    )
}

#[derive(Debug, PartialEq, Clone)]
struct Snake {
    cells: Vec<Cell>,
    direction: Direction,
}

impl Snake {
    fn slide(&self) -> Snake {
        let mut new_cells = self.cells.clone();
        new_cells.pop();
        let mut vec: Vec<Cell> = vec![self.cells.first().unwrap().move_in(&self.direction)];
        vec.append(&mut new_cells);

        let mut new_snake = self.clone();
        new_snake.cells = vec;
        new_snake
    }
}

#[derive(Debug, PartialEq, Clone)]
struct Cell {
    x: i32,
    y: i32,
}

impl Cell {
    fn move_in(&self, direction: &Direction) -> Cell {
        let dx = match direction {
            Direction::Up => 0,
            Direction::Down => 0,
            Direction::Left => -1,
            Direction::Right => 1,
        };
        let dy = match direction {
            Direction::Up => -1,
            Direction::Down => 1,
            Direction::Left => 0,
            Direction::Right => 0,
        };
        return Cell { x: self.x + dx, y: self.y + dy };
    }
}

#[derive(Debug, PartialEq, Clone)]
enum Direction {
    Up,
    Down,
    Left,
    Right,
}
<commit_msg>snake tests<commit_after>extern "C" {
    fn getpid() -> i32;
}

fn main() {
    let pid = unsafe { getpid() };
    println!("Hello from {}", pid);
}

#[derive(Debug, PartialEq, Clone)]
struct Snake {
    cells: Vec<Cell>,
    direction: Direction,
}

impl Snake {
    fn slide(&self) -> Snake {
        let mut vec: Vec<Cell> = vec![self.cells.first().unwrap().move_in(&self.direction)];

        let mut new_cells = self.cells.clone();
        new_cells.pop();
        vec.append(&mut new_cells);

        Snake { cells: vec, direction: self.direction }
    }
}

#[derive(Debug, PartialEq, Clone)]
struct Cell {
    x: i32,
    y: i32,
}

impl Cell {
    fn move_in(&self, direction: &Direction) -> Cell {
        let dx = match direction {
            Direction::Up => 0,
            Direction::Down => 0,
            Direction::Left => -1,
            Direction::Right => 1,
        };
        let dy = match direction {
            Direction::Up => -1,
            Direction::Down => 1,
            Direction::Left => 0,
            Direction::Right => 0,
        };
        return Cell { x: self.x + dx, y: self.y + dy };
    }
}

#[derive(Debug, PartialEq, Clone, Copy)]
enum Direction {
    Up,
    Down,
    Left,
    Right,
}

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

    #[test]
    fn it_works() {
        let snake = Snake {
            cells: vec![Cell { x: 2, y: 0 }, Cell { x: 1, y: 0 }, Cell { x: 0, y: 0 }],
            direction: Direction::Right,
        };

        assert_eq!(
            snake.slide(),
            Snake {
                cells: vec![Cell { x: 3, y: 0 }, Cell { x: 2, y: 0 }, Cell { x: 1, y: 0 }],
                direction: Direction::Right,
            }
        )
    }
}<|endoftext|>


<commit_before>#![feature(phase, macro_rules)]
#[phase(link, plugin)] extern crate log;
extern crate forth;

use forth::error::Error::StackUnderflow;
use forth::stack::Stack;
use forth::state::State;
use forth::word::Word;
use forth::word::WordKind::Builtin;
use std::io::stdin;

macro_rules! builtin {
    ($state:ident : $command:expr $function:expr) => {
        $state.add_word(Word {
            command: $command.to_string(),
            kind: Builtin($function),
        });
    }
}

fn main() {
    let mut state = State::new();
    builtin!(state : "+" box |&: s: &mut Stack| {
        let x = try!(s.pop().ok_or(StackUnderflow));
        let y = try!(s.pop().ok_or(StackUnderflow));
        s.push(y + x);
        Ok(())
    });
    builtin!(state : "-" box |&: s: &mut Stack| {
        let x = try!(s.pop().ok_or(StackUnderflow));
        let y = try!(s.pop().ok_or(StackUnderflow));
        s.push(y - x);
        Ok(())
    });
    builtin!(state : "." box |&: s: &mut Stack| {
        let x = try!(s.pop().ok_or(StackUnderflow));
        println!("{}", x);
        Ok(())
    });
    builtin!(state : "DUP" box |&: s: &mut Stack| {
        let x = try!(s.peek().ok_or(StackUnderflow));
        s.push(x);
        Ok(())
    });
    for line in stdin().lock().lines() {
        match line {
            Ok(l) => match state.parse_line(l.as_slice()) {
                Ok(()) => (),
                Err(e) => error!("{}", e),
            },
            Err(e) => error!("{}", e),
        }
    }
}
<commit_msg>Add "ok" message after successful line<commit_after>#![feature(phase, macro_rules)]
#[phase(link, plugin)] extern crate log;
extern crate forth;

use forth::error::Error::StackUnderflow;
use forth::stack::Stack;
use forth::state::State;
use forth::word::Word;
use forth::word::WordKind::Builtin;
use std::io::{stdin, stderr};

macro_rules! builtin {
    ($state:ident : $command:expr $function:expr) => {
        $state.add_word(Word {
            command: $command.to_string(),
            kind: Builtin($function),
        });
    }
}

fn main() {
    let mut stderr = stderr();
    let mut state = State::new();
    builtin!(state : "+" box |&: s: &mut Stack| {
        let x = try!(s.pop().ok_or(StackUnderflow));
        let y = try!(s.pop().ok_or(StackUnderflow));
        s.push(y + x);
        Ok(())
    });
    builtin!(state : "-" box |&: s: &mut Stack| {
        let x = try!(s.pop().ok_or(StackUnderflow));
        let y = try!(s.pop().ok_or(StackUnderflow));
        s.push(y - x);
        Ok(())
    });
    builtin!(state : "." box |&: s: &mut Stack| {
        let x = try!(s.pop().ok_or(StackUnderflow));
        println!("{}", x);
        Ok(())
    });
    builtin!(state : "DUP" box |&: s: &mut Stack| {
        let x = try!(s.peek().ok_or(StackUnderflow));
        s.push(x);
        Ok(())
    });
    for line in stdin().lock().lines() {
        match line {
            Ok(l) => match state.parse_line(l.as_slice()) {
                Ok(()) => match writeln!(&mut stderr, "ok") {
                    Ok(()) => (),
                    Err(e) => error!("{}", e),
                },
                Err(e) => error!("{}", e),
            },
            Err(e) => error!("{}", e),
        }
    }
}
<|endoftext|>


<commit_before>extern crate log;
#[macro_use]
extern crate wlroots;

use std::{thread, process::Command};

use log::LevelFilter;
use wlroots::{area::{Area, Origin, Size},
              compositor,
              cursor::{self, Cursor, xcursor},
              input::{self, keyboard, pointer},
              output::{self, layout::Layout},
              render::{matrix, Renderer},
              seat::{self, Seat},
              shell::xdg_shell_v6,
              surface,
              utils::{Handleable, log::Logger, current_time}};
use wlroots::wlroots_sys::wlr_key_state::WLR_KEY_PRESSED;
use wlroots::xkbcommon::xkb::keysyms::{KEY_Escape, KEY_F1};
use wlroots::wlroots_dehandle;

struct State {
    xcursor_manager: xcursor::Manager,
    keyboard: Option<keyboard::Handle>,
    layout: output::layout::Handle,
    cursor: cursor::Handle,
    shells: Vec<xdg_shell_v6::Handle>,
    seat_handle: Option<seat::Handle>
}

impl State {
    fn new(xcursor_manager: xcursor::Manager,
           layout: output::layout::Handle,
           cursor: cursor::Handle)
           -> Self {
        State { xcursor_manager,
                layout,
                cursor,
                keyboard: None,
                seat_handle: None,
                shells: vec![] }
    }
}

struct SeatHandlerEx;

struct CursorEx;

impl cursor::Handler for CursorEx {}

impl seat::Handler for SeatHandlerEx {}

struct XdgV6ShellHandlerEx;
struct OutputLayoutEx;

impl output::layout::Handler for OutputLayoutEx {}

impl xdg_shell_v6::Handler for XdgV6ShellHandlerEx {
    fn destroyed(&mut self, compositor: compositor::Handle, shell: xdg_shell_v6::Handle) {
        with_handles!([(compositor: {compositor})] => {
            let state: &mut State = compositor.downcast();
            let weak = shell;
            if let Some(index) = state.shells.iter().position(|s| *s == weak) {
                state.shells.remove(index);
            }
        }).unwrap();
    }
}

struct SurfaceEx;

impl surface::Handler for SurfaceEx {
    fn on_commit(&mut self, _: compositor::Handle, surface: surface::Handle) {
        wlr_log!(WLR_DEBUG, "Commiting for surface {:?}", surface);
    }
}

#[wlroots_dehandle(compositor, shell, layout, output)]
fn new_surface(compositor: compositor::Handle,
               shell: xdg_shell_v6::Handle)
               -> (Option<Box<xdg_shell_v6::Handler>>, Option<Box<surface::Handler>>) {
    {
        use compositor as compositor;
        use shell as shell;
        shell.ping();
        let state: &mut State = compositor.downcast();
        state.shells.push(shell.weak_reference());
        let layout_handle = &state.layout;
        use layout_handle as layout;
        for (output, _) in layout.outputs() {
            use output as output;
            output.schedule_frame()
        }
    }
    (Some(Box::new(XdgV6ShellHandlerEx)), Some(Box::new(SurfaceEx)))
}

struct ExOutput;

struct ExPointer;

struct ExKeyboardHandler;

#[wlroots_dehandle(compositor, output, layout, cursor)]
fn output_added<'output>(compositor: compositor::Handle,
                         builder: output::Builder<'output>)
                         -> Option<output::BuilderResult<'output>> {
    let result = builder.build_best_mode(ExOutput);
    {
        let output_handle = &result.output;
        use compositor as compositor;
        use output_handle as output;
        let state: &mut State = compositor.data.downcast_mut().unwrap();
        let xcursor_manager = &mut state.xcursor_manager;
        // TODO use output config if present instead of auto
        let layout = &mut state.layout;
        let cursor = &mut state.cursor;
        use layout as layout;
        use cursor as cursor;
        layout.add_auto(output);
        cursor.attach_output_layout(layout);
        xcursor_manager.load(output.scale());
        xcursor_manager.set_cursor_image("left_ptr".to_string(), cursor);
        let (x, y) = cursor.coords();
        // https://en.wikipedia.org/wiki/Mouse_warping
        cursor.warp(None, x, y);
    }
    Some(result)
}

impl keyboard::Handler for ExKeyboardHandler {
    #[wlroots_dehandle(compositor, seat)]
    fn on_key(&mut self,
              compositor_handle: compositor::Handle,
              _: keyboard::Handle,
              key_event: &keyboard::event::Key) {
        for key in key_event.pressed_keys() {
            if key == KEY_Escape {
                compositor::terminate();
            } else if key_event.key_state() == WLR_KEY_PRESSED {
                if key == KEY_F1 {
                    thread::spawn(move || {
                        Command::new("weston-terminal").output().unwrap();
                    });
                    return
                }
            }
        };
        use compositor_handle as compositor;
        let state: &mut State = compositor.downcast();
        let seat_handle = state.seat_handle.clone().unwrap();
        use seat_handle as seat;
        seat.keyboard_notify_key(key_event.time_msec(),
                                    key_event.keycode(),
                                    key_event.key_state() as u32);
    }
}

impl pointer::Handler for ExPointer {
    #[wlroots_dehandle(compositor, cursor)]
    fn on_motion_absolute(&mut self,
                          compositor: compositor::Handle,
                          _: pointer::Handle,
                          event: &pointer::event::AbsoluteMotion) {
        use compositor as compositor;
        let state: &mut State = compositor.downcast();
        let (x, y) = event.pos();
        let cursor_handle = &state.cursor;
        use cursor_handle as cursor;
        cursor.warp_absolute(event.device(), x, y)
    }

    #[wlroots_dehandle(compositor, cursor)]
    fn on_motion(&mut self,
                 compositor: compositor::Handle,
                 _: pointer::Handle,
                 event: &pointer::event::Motion) {
        use compositor as compositor;
        let state: &mut State = compositor.downcast();
        let (delta_x, delta_y) = event.delta();
        let cursor_handle = &state.cursor;
        use cursor_handle as cursor;
        cursor.move_to(event.device(), delta_x, delta_y)
    }

    #[wlroots_dehandle(compositor, shell, seat, keyboard, surface)]
    fn on_button(&mut self,
                 compositor: compositor::Handle, _:
                 pointer::Handle,
                 _: &pointer::event::Button) {
        use compositor as compositor;
        let state: &mut State = compositor.downcast();
        let seat = state.seat_handle.clone().unwrap();
        let keyboard = state.keyboard.clone().unwrap();
        let shell_handle = &state.shells[0];
        use shell_handle as shell;
        match shell.state() {
            Some(&mut xdg_shell_v6::ShellState::TopLevel(ref mut toplevel)) => {
                toplevel.set_activated(true);
            }
            _ => {}
        };
        let surface = shell.surface();
        use seat as seat;
        use keyboard as keyboard;
        use surface as surface;
        seat.set_keyboard(keyboard.input_device());
        seat.keyboard_notify_enter(surface,
                                   &mut keyboard.keycodes(),
                                   &mut keyboard.get_modifier_masks())
    }
}

impl output::Handler for ExOutput {
    #[wlroots_dehandle(compositor, output)]
    fn on_frame(&mut self, compositor: compositor::Handle, output: output::Handle) {
        use compositor as compositor;
        use output as output;
        let state: &mut State = compositor.data.downcast_mut().unwrap();
        let renderer = compositor.renderer
            .as_mut()
            .expect("Compositor was not loaded with a renderer");
        let mut render_context = renderer.render(output, None);
        render_context.clear([0.25, 0.25, 0.25, 1.0]);
        render_shells(state, &mut render_context)
    }
}

fn pointer_added(_: compositor::Handle,
                 _: pointer::Handle)
                 -> Option<Box<pointer::Handler>> {
    Some(Box::new(ExPointer))
}

#[wlroots_dehandle(compositor, keyboard, seat)]
fn keyboard_added(compositor: compositor::Handle,
                  keyboard: keyboard::Handle)
                  -> Option<Box<keyboard::Handler>> {
    {
        use compositor as compositor;
        use keyboard as keyboard;
        let state: &mut State = compositor.downcast();
        state.keyboard = Some(keyboard.weak_reference());
        let seat_handle = state.seat_handle.as_ref().unwrap();
        use seat_handle as seat;
        seat.set_keyboard(keyboard.input_device());
    }
    Some(Box::new(ExKeyboardHandler))
}

fn main() {
    Logger::init(LevelFilter::Debug, None);
    let cursor = Cursor::create(Box::new(CursorEx));
    let mut xcursor_manager =
        xcursor::Manager::create("default".to_string(), 24).expect("Could not create xcursor \
                                                                    manager");
    xcursor_manager.load(1.0);
    cursor.run(|c| xcursor_manager.set_cursor_image("left_ptr".to_string(), c))
        .unwrap();
    let layout = Layout::create(Box::new(OutputLayoutEx));

    let output_builder = output::manager::Builder::default().output_added(output_added);
    let input_builder = input::manager::Builder::default()
        .keyboard_added(keyboard_added)
        .pointer_added(pointer_added);
    let xdg_shell_v6_builder = xdg_shell_v6::manager::Builder::default()
        .surface_added(new_surface);
    let mut compositor =
        compositor::Builder::new().gles2(true)
        .wl_shm(true)
        .input_manager(input_builder)
        .output_manager(output_builder)
        .xdg_shell_v6_manager(xdg_shell_v6_builder)
        .build_auto(State::new(xcursor_manager, layout, cursor));

    {
        let seat_handle =
            Seat::create(&mut compositor, "seat0".into(), Box::new(SeatHandlerEx));
        seat_handle.run(|seat| {
                            seat.set_capabilities(seat::Capability::all());
                        })
                   .unwrap();
        let state: &mut State = compositor.downcast();
        state.seat_handle = Some(seat_handle);
    }
    compositor.run();
}

/// Render the shells in the current compositor state on the given output.
#[wlroots_dehandle(shell, surface, layout)]
fn render_shells(state: &mut State, renderer: &mut Renderer) {
    let shells = state.shells.clone();
    let layout_handle = &state.layout;
    for mut shell in shells {
        use shell as shell;
        let surface_handle = shell.surface();
        use surface_handle as surface;
        use layout_handle as layout;
        let (width, height) = surface.current_state().size();
        let (render_width, render_height) =
            (width * renderer.output.scale() as i32,
             height * renderer.output.scale() as i32);
        let (lx, ly) = (0.0, 0.0);
        let render_box = Area::new(Origin::new(lx as i32, ly as i32),
                                   Size::new(render_width,
                                             render_height));
        if layout.intersects(renderer.output, render_box) {
            let transform = renderer.output.get_transform().invert();
            let matrix = matrix::project_box(render_box,
                                             transform,
                                             0.0,
                                             renderer.output
                                             .transform_matrix());
            if let Some(texture) = surface.texture().as_ref() {
                renderer.render_texture_with_matrix(texture, matrix);
            }
            surface.send_frame_done(current_time());
        }
    }
}
<commit_msg>Updated xdg shell test to wlroots_dehandle 2.0<commit_after>extern crate log;
#[macro_use]
extern crate wlroots;

use std::{thread, process::Command};

use log::LevelFilter;
use wlroots::{area::{Area, Origin, Size},
              compositor,
              cursor::{self, Cursor, xcursor},
              input::{self, keyboard, pointer},
              output::{self, layout::Layout},
              render::{matrix, Renderer},
              seat::{self, Seat},
              shell::xdg_shell_v6,
              surface,
              utils::{Handleable, log::Logger, current_time}};
use wlroots::wlroots_sys::wlr_key_state::WLR_KEY_PRESSED;
use wlroots::xkbcommon::xkb::keysyms::{KEY_Escape, KEY_F1};
use wlroots::wlroots_dehandle;

struct State {
    xcursor_manager: xcursor::Manager,
    keyboard: Option<keyboard::Handle>,
    layout: output::layout::Handle,
    cursor: cursor::Handle,
    shells: Vec<xdg_shell_v6::Handle>,
    seat_handle: Option<seat::Handle>
}

impl State {
    fn new(xcursor_manager: xcursor::Manager,
           layout: output::layout::Handle,
           cursor: cursor::Handle)
           -> Self {
        State { xcursor_manager,
                layout,
                cursor,
                keyboard: None,
                seat_handle: None,
                shells: vec![] }
    }
}

struct SeatHandlerEx;

struct CursorEx;

impl cursor::Handler for CursorEx {}

impl seat::Handler for SeatHandlerEx {}

struct XdgV6ShellHandlerEx;
struct OutputLayoutEx;

impl output::layout::Handler for OutputLayoutEx {}

impl xdg_shell_v6::Handler for XdgV6ShellHandlerEx {
    fn destroyed(&mut self, compositor: compositor::Handle, shell: xdg_shell_v6::Handle) {
        with_handles!([(compositor: {compositor})] => {
            let state: &mut State = compositor.downcast();
            let weak = shell;
            if let Some(index) = state.shells.iter().position(|s| *s == weak) {
                state.shells.remove(index);
            }
        }).unwrap();
    }
}

struct SurfaceEx;

impl surface::Handler for SurfaceEx {
    fn on_commit(&mut self, _: compositor::Handle, surface: surface::Handle) {
        wlr_log!(WLR_DEBUG, "Commiting for surface {:?}", surface);
    }
}

#[wlroots_dehandle]
fn new_surface(compositor: compositor::Handle,
               shell: xdg_shell_v6::Handle)
               -> (Option<Box<xdg_shell_v6::Handler>>, Option<Box<surface::Handler>>) {
    {
        #[dehandle] let compositor = compositor;
        #[dehandle] let shell = shell;
        shell.ping();
        let state: &mut State = compositor.downcast();
        state.shells.push(shell.weak_reference());
        #[dehandle] let layout = &state.layout;
        for (output, _) in layout.outputs() {
            #[dehandle] let output = output;
            output.schedule_frame()
        }
    }
    (Some(Box::new(XdgV6ShellHandlerEx)), Some(Box::new(SurfaceEx)))
}

struct ExOutput;

struct ExPointer;

struct ExKeyboardHandler;

#[wlroots_dehandle]
fn output_added<'output>(compositor: compositor::Handle,
                         builder: output::Builder<'output>)
                         -> Option<output::BuilderResult<'output>> {
    let result = builder.build_best_mode(ExOutput);
    {
        #[dehandle] let compositor = compositor;
        #[dehandle] let output = &result.output;
        let state: &mut State = compositor.data.downcast_mut().unwrap();
        // TODO use output config if present instead of auto
        #[dehandle] let layout = state.layout.clone();
        #[dehandle] let cursor = state.cursor.clone();
        layout.add_auto(output);
        cursor.attach_output_layout(layout);
        state.xcursor_manager.load(output.scale());
        state.xcursor_manager.set_cursor_image("left_ptr".to_string(), cursor);
        let (x, y) = cursor.coords();
        // https://en.wikipedia.org/wiki/Mouse_warping
        cursor.warp(None, x, y);
    }
    Some(result)
}

impl keyboard::Handler for ExKeyboardHandler {
    #[wlroots_dehandle]
    fn on_key(&mut self,
              compositor_handle: compositor::Handle,
              _: keyboard::Handle,
              key_event: &keyboard::event::Key) {
        for key in key_event.pressed_keys() {
            if key == KEY_Escape {
                compositor::terminate();
            } else if key_event.key_state() == WLR_KEY_PRESSED {
                if key == KEY_F1 {
                    thread::spawn(move || {
                        Command::new("weston-terminal").output().unwrap();
                    });
                    return
                }
            }
        };
        #[dehandle] let compositor = compositor_handle;
        let state: &mut State = compositor.downcast();
        #[dehandle] let seat = state.seat_handle.clone().unwrap();
        seat.keyboard_notify_key(key_event.time_msec(),
                                 key_event.keycode(),
                                 key_event.key_state() as u32);
    }
}

impl pointer::Handler for ExPointer {
    #[wlroots_dehandle]
    fn on_motion_absolute(&mut self,
                          compositor: compositor::Handle,
                          _: pointer::Handle,
                          event: &pointer::event::AbsoluteMotion) {
        #[dehandle] let compositor = compositor;
        let state: &mut State = compositor.downcast();
        let (x, y) = event.pos();
        #[dehandle] let cursor = &state.cursor;
        cursor.warp_absolute(event.device(), x, y)
    }

    #[wlroots_dehandle]
    fn on_motion(&mut self,
                 compositor: compositor::Handle,
                 _: pointer::Handle,
                 event: &pointer::event::Motion) {
        #[dehandle] let compositor = compositor;
        let state: &mut State = compositor.downcast();
        let (delta_x, delta_y) = event.delta();
        #[dehandle] let cursor = &state.cursor;
        cursor.move_to(event.device(), delta_x, delta_y)
    }

    #[wlroots_dehandle]
    fn on_button(&mut self,
                 compositor: compositor::Handle, _:
                 pointer::Handle,
                 _: &pointer::event::Button) {
        #[dehandle] let compositor = compositor;
        let state: &mut State = compositor.downcast();
        let seat = state.seat_handle.clone().unwrap();
        let keyboard = state.keyboard.clone().unwrap();
        let shell_handle = &state.shells[0];
        #[dehandle] let shell = &state.shells[0];
        match shell.state() {
            Some(&mut xdg_shell_v6::ShellState::TopLevel(ref mut toplevel)) => {
                toplevel.set_activated(true);
            }
            _ => {}
        };
        #[dehandle] let seat = state.seat_handle.clone().unwrap();
        #[dehandle] let keyboard = state.keyboard.clone().unwrap();
        #[dehandle] let surface = shell.surface();
        seat.set_keyboard(keyboard.input_device());
        seat.keyboard_notify_enter(surface,
                                   &mut keyboard.keycodes(),
                                   &mut keyboard.get_modifier_masks())
    }
}

impl output::Handler for ExOutput {
    #[wlroots_dehandle]
    fn on_frame(&mut self, compositor: compositor::Handle, output: output::Handle) {
        #[dehandle] let compositor = compositor;
        #[dehandle] let output = output;
        let state: &mut State = compositor.data.downcast_mut().unwrap();
        let renderer = compositor.renderer
            .as_mut()
            .expect("Compositor was not loaded with a renderer");
        let mut render_context = renderer.render(output, None);
        render_context.clear([0.25, 0.25, 0.25, 1.0]);
        render_shells(state, &mut render_context)
    }
}

fn pointer_added(_: compositor::Handle,
                 _: pointer::Handle)
                 -> Option<Box<pointer::Handler>> {
    Some(Box::new(ExPointer))
}

#[wlroots_dehandle]
fn keyboard_added(compositor: compositor::Handle,
                  keyboard: keyboard::Handle)
                  -> Option<Box<keyboard::Handler>> {
    {
        #[dehandle] let compositor = compositor;
        #[dehandle] let keyboard = keyboard;
        let state: &mut State = compositor.downcast();
        state.keyboard = Some(keyboard.weak_reference());
        #[dehandle] let seat = state.seat_handle.as_ref().unwrap();
        seat.set_keyboard(keyboard.input_device());
    }
    Some(Box::new(ExKeyboardHandler))
}

fn main() {
    Logger::init(LevelFilter::Debug, None);
    let cursor = Cursor::create(Box::new(CursorEx));
    let mut xcursor_manager =
        xcursor::Manager::create("default".to_string(), 24).expect("Could not create xcursor \
                                                                    manager");
    xcursor_manager.load(1.0);
    cursor.run(|c| xcursor_manager.set_cursor_image("left_ptr".to_string(), c))
        .unwrap();
    let layout = Layout::create(Box::new(OutputLayoutEx));

    let output_builder = output::manager::Builder::default().output_added(output_added);
    let input_builder = input::manager::Builder::default()
        .keyboard_added(keyboard_added)
        .pointer_added(pointer_added);
    let xdg_shell_v6_builder = xdg_shell_v6::manager::Builder::default()
        .surface_added(new_surface);
    let mut compositor =
        compositor::Builder::new().gles2(true)
        .wl_shm(true)
        .input_manager(input_builder)
        .output_manager(output_builder)
        .xdg_shell_v6_manager(xdg_shell_v6_builder)
        .build_auto(State::new(xcursor_manager, layout, cursor));

    {
        let seat_handle =
            Seat::create(&mut compositor, "seat0".into(), Box::new(SeatHandlerEx));
        seat_handle.run(|seat| {
            seat.set_capabilities(seat::Capability::all());
        })
            .unwrap();
        let state: &mut State = compositor.downcast();
        state.seat_handle = Some(seat_handle);
    }
    compositor.run();
}

/// Render the shells in the current compositor state on the given output.
#[wlroots_dehandle]
fn render_shells(state: &mut State, renderer: &mut Renderer) {
    let shells = state.shells.clone();
    for mut shell in shells {
        #[dehandle] let shell = shell;
        #[dehandle] let surface = shell.surface();
        #[dehandle] let layout = &state.layout;
        let (width, height) = surface.current_state().size();
        let (render_width, render_height) =
            (width * renderer.output.scale() as i32,
             height * renderer.output.scale() as i32);
        let (lx, ly) = (0.0, 0.0);
        let render_box = Area::new(Origin::new(lx as i32, ly as i32),
                                   Size::new(render_width,
                                             render_height));
        if layout.intersects(renderer.output, render_box) {
            let transform = renderer.output.get_transform().invert();
            let matrix = matrix::project_box(render_box,
                                             transform,
                                             0.0,
                                             renderer.output
                                             .transform_matrix());
            if let Some(texture) = surface.texture().as_ref() {
                renderer.render_texture_with_matrix(texture, matrix);
            }
            surface.send_frame_done(current_time());
        }
    }
}
<|endoftext|>


<commit_before>use super::controls;

use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
use std::sync::mpsc::{SendError, Sender};

static GLOBAL_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct CallbackId(usize);

impl CallbackId {
    pub fn next() -> CallbackId {
        CallbackId(atomic_next())
    }
}

fn atomic_next() -> usize {
    GLOBAL_COUNT.fetch_add(1, Ordering::SeqCst)
}

pub trait Callback {
    fn name(&self) -> &'static str;
    fn id(&self) -> CallbackId;
}

#[derive(Debug, Clone)]
pub struct AsyncFeeder<T: Callback> {
    sender: Sender<T>,
}
impl<T: Callback> AsyncFeeder<T> {
    pub fn feed(&mut self, data: T) -> Result<(), SendError<T>> {
        self.sender.send(data)
    }
}
impl<T: Callback> From<Sender<T>> for AsyncFeeder<T> {
    fn from(s: Sender<T>) -> Self {
        AsyncFeeder { sender: s }
    }
}

#[macro_export]
macro_rules! callback {
	($id: ident, $($typ:tt)+) => {
		pub struct $id(CallbackId, Box<dyn $($typ)+>);

		impl Callback for $id {
			fn name(&self) -> &'static str {
				stringify!($id)
			}
			fn id(&self) -> CallbackId {
				self.0
			}
		}

		impl <T> From<T> for $id where T: $($typ)+ + Sized + 'static {
			fn from(t: T) -> $id {
				$id(CallbackId::next(), Box::new(t))
			}
		}
		impl AsRef<dyn $($typ)+> for $id {
			fn as_ref(&self) -> &(dyn $($typ)+  + 'static) {
				self.1.as_ref()
			}
		}
		impl AsMut<dyn $($typ)+> for $id {
			fn as_mut(&mut self) -> &mut (dyn $($typ)+ + 'static) {
				self.1.as_mut()
			}
		}
		impl From<$id> for (CallbackId, Box<dyn $($typ)+>) {
		    fn from(a: $id) -> Self {
		        (a.0, a.1)
		    }
		}
		impl From<(CallbackId, Box<dyn $($typ)+>)> for $id {
		    fn from(a: (CallbackId, Box<dyn $($typ)+>)) -> Self {
		        $id(a.0, a.1)
		    }
		}
	}
}

callback!(Resize, FnMut(&mut dyn controls::Member, u16, u16));
callback!(Click, FnMut(&mut dyn controls::Clickable));
callback!(Frame, FnMut(&mut dyn controls::Window) -> bool);
callback!(Action, FnMut(&mut dyn controls::Member) -> bool);

<commit_msg>Forgotten atomic updated<commit_after>use super::controls;

use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::mpsc::{SendError, Sender};

static GLOBAL_COUNT: AtomicUsize = AtomicUsize::new(0);

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct CallbackId(usize);

impl CallbackId {
    pub fn next() -> CallbackId {
        CallbackId(atomic_next())
    }
}

fn atomic_next() -> usize {
    GLOBAL_COUNT.fetch_add(1, Ordering::SeqCst)
}

pub trait Callback {
    fn name(&self) -> &'static str;
    fn id(&self) -> CallbackId;
}

#[derive(Debug, Clone)]
pub struct AsyncFeeder<T: Callback> {
    sender: Sender<T>,
}
impl<T: Callback> AsyncFeeder<T> {
    pub fn feed(&mut self, data: T) -> Result<(), SendError<T>> {
        self.sender.send(data)
    }
}
impl<T: Callback> From<Sender<T>> for AsyncFeeder<T> {
    fn from(s: Sender<T>) -> Self {
        AsyncFeeder { sender: s }
    }
}

#[macro_export]
macro_rules! callback {
	($id: ident, $($typ:tt)+) => {
		pub struct $id(CallbackId, Box<dyn $($typ)+>);

		impl Callback for $id {
			fn name(&self) -> &'static str {
				stringify!($id)
			}
			fn id(&self) -> CallbackId {
				self.0
			}
		}

		impl <T> From<T> for $id where T: $($typ)+ + Sized + 'static {
			fn from(t: T) -> $id {
				$id(CallbackId::next(), Box::new(t))
			}
		}
		impl AsRef<dyn $($typ)+> for $id {
			fn as_ref(&self) -> &(dyn $($typ)+  + 'static) {
				self.1.as_ref()
			}
		}
		impl AsMut<dyn $($typ)+> for $id {
			fn as_mut(&mut self) -> &mut (dyn $($typ)+ + 'static) {
				self.1.as_mut()
			}
		}
		impl From<$id> for (CallbackId, Box<dyn $($typ)+>) {
		    fn from(a: $id) -> Self {
		        (a.0, a.1)
		    }
		}
		impl From<(CallbackId, Box<dyn $($typ)+>)> for $id {
		    fn from(a: (CallbackId, Box<dyn $($typ)+>)) -> Self {
		        $id(a.0, a.1)
		    }
		}
	}
}

callback!(Resize, FnMut(&mut dyn controls::Member, u16, u16));
callback!(Click, FnMut(&mut dyn controls::Clickable));
callback!(Frame, FnMut(&mut dyn controls::Window) -> bool);
callback!(Action, FnMut(&mut dyn controls::Member) -> bool);

<|endoftext|>


<commit_before>//! # Type-based Serialization and Deserialization
//!
//! Serde provides a mechanism for low boilerplate serialization & deserialization of values to and
//! from MessagePack via the serialization API. To be able to serialize a piece of data, it must
//! implement the `serde::Serialize` trait. To be able to deserialize a piece of data, it must
//! implement the `serde::Deserialize` trait. Serde provides provides an annotation to
//! automatically generate the code for these traits: `#[derive(Serialize, Deserialize)]`.
//!
//! # Examples
//!
//! Let's try to encode and decode some built-in types.
//!
//! ```rust
//! extern crate serde;
//! extern crate rmp_serde as rmps;
//!
//! use serde::{Deserialize, Serialize};
//! use rmps::{Deserializer, Serializer};
//!
//! fn main() {
//!     let mut buf = Vec::new();
//!     let val = (42u8, "the Answer");
//!     val.serialize(&mut Serializer::new(&mut buf)).unwrap();
//!
//!     assert_eq!(vec![0x92, 0x2a, 0xaa, 0x74, 0x68, 0x65, 0x20, 0x41, 0x6e, 0x73, 0x77, 0x65, 0x72], buf);
//!
//!     let mut de = Deserializer::new(&buf[..]);
//!     assert_eq!((42, "the Answer".to_owned()), Deserialize::deserialize(&mut de).unwrap());
//! }
//! ```
//!
//! No one gonna hurt if we add some reflection magic.
//!
//! ```ignore
//! extern crate serde;
//! #[macro_use]
//! extern crate serde_derive;
//! extern crate rmp_serde as rmps;
//!
//! use std::collections::HashMap;
//! use serde::{Deserialize, Serialize};
//! use rmps::{Deserializer, Serializer};
//!
//! #[derive(Debug, PartialEq, Deserialize, Serialize)]
//! struct Human {
//!     age: u32,
//!     name: String,
//! }
//!
//! fn main() {
//!     let mut buf = Vec::new();
//!     let val = Human {
//!         age: 42,
//!         name: "John".into(),
//!     };
//!
//!     val.serialize(&mut Serializer::new(&mut buf)).unwrap();
//! }
//! ```

extern crate rmp;
extern crate byteorder;
#[macro_use]
extern crate serde;

use std::fmt::{self, Display, Formatter};
use std::mem;
use std::str::{self, Utf8Error};

use serde::Serialize;
use serde::de::{self, Deserialize};

pub use decode::{Deserializer, from_slice, from_read};
pub use encode::{Serializer, to_vec, to_vec_named};

pub mod decode;
pub mod encode;

/// Helper that allows both to encode and decode strings no matter whether they contain valid or
/// invalid UTF-8.
///
/// Regardless of validity the UTF-8 content this type will always be serialized as a string.
#[derive(Clone, Debug, PartialEq)]
pub struct Raw {
    s: Result<String, (Vec<u8>, Utf8Error)>,
}

impl Raw {
    /// Constructs a new `Raw` from the UTF-8 string.
    pub fn new(v: String) -> Self {
        Self { s: Ok(v) }
    }

    /// Converts a vector of bytes to a `Raw`.
    pub fn from_utf8(v: Vec<u8>) -> Self {
        match String::from_utf8(v) {
            Ok(v) => Raw::new(v),
            Err(err) => {
                let e = err.utf8_error();
                Self {
                    s: Err((err.into_bytes(), e))
                }
            }
        }
    }

    /// Returns `true` if the raw is valid UTF-8.
    pub fn is_str(&self) -> bool {
        self.s.is_ok()
    }

    /// Returns `true` if the raw contains invalid UTF-8 sequence.
    pub fn is_err(&self) -> bool {
        self.s.is_err()
    }

    /// Returns the string reference if the raw is valid UTF-8, or else `None`.
    pub fn as_str(&self) -> Option<&str> {
        match self.s {
            Ok(ref s) => Some(s.as_str()),
            Err(..) => None,
        }
    }

    /// Returns the underlying `Utf8Error` if the raw contains invalid UTF-8 sequence, or
    /// else `None`.
    pub fn as_err(&self) -> Option<&Utf8Error> {
        match self.s {
            Ok(..) => None,
            Err((_, ref err)) => Some(&err),
        }
    }

    /// Returns a byte slice of this raw's contents.
    pub fn as_bytes(&self) -> &[u8] {
        match self.s {
            Ok(ref s) => s.as_bytes(),
            Err(ref err) => &err.0[..],
        }
    }

    /// Consumes this object, yielding the string if the raw is valid UTF-8, or else `None`.
    pub fn into_str(self) -> Option<String> {
        self.s.ok()
    }

    /// Converts a `Raw` into a byte vector.
    pub fn into_bytes(self) -> Vec<u8> {
        match self.s {
            Ok(s) => s.into_bytes(),
            Err(err) => err.0,
        }
    }
}

impl Serialize for Raw {
    fn serialize<S>(&self, se: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer
    {
        let s = match self.s {
            Ok(ref s) => s.as_str(),
            Err((ref b, ..)) => unsafe { mem::transmute(&b[..]) },
        };

        se.serialize_str(s)
    }
}

struct RawVisitor;

impl<'de> de::Visitor<'de> for RawVisitor {
    type Value = Raw;

    fn expecting(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        "string or bytes".fmt(fmt)
    }

    #[inline]
    fn visit_string<E>(self, v: String) -> Result<Self::Value, E> {
        Ok(Raw { s: Ok(v) })
    }

    #[inline]
    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
        where E: de::Error
    {
        Ok(Raw { s: Ok(v.into()) })
    }

    #[inline]
    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
        where E: de::Error
    {
        let s = match str::from_utf8(v) {
            Ok(s) => Ok(s.into()),
            Err(err) => Err((v.into(), err)),
        };

        Ok(Raw { s: s })
    }

    #[inline]
    fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
        where E: de::Error
    {
        let s = match String::from_utf8(v) {
            Ok(s) => Ok(s),
            Err(err) => {
                let e = err.utf8_error();
                Err((err.into_bytes(), e))
            }
        };

        Ok(Raw { s: s })
    }
}

impl<'de> Deserialize<'de> for Raw {
    #[inline]
    fn deserialize<D>(de: D) -> Result<Self, D::Error>
        where D: de::Deserializer<'de>
    {
        de.deserialize_any(RawVisitor)
    }
}

/// Helper that allows to decode strings no matter whether they contain valid or invalid UTF-8.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct RawRef<'a> {
    s: Result<&'a str, (&'a [u8], Utf8Error)>,
}

impl<'a> RawRef<'a> {
    /// Constructs a new `RawRef` from the UTF-8 string.
    pub fn new(v: &'a str) -> Self {
        Self { s: Ok(v) }
    }

    /// Converts a vector of bytes to a `RawRef`.
    pub fn from_utf8(v: &'a[u8]) -> Self {
        match str::from_utf8(v) {
            Ok(v) => RawRef::new(v),
            Err(err) => {
                Self {
                    s: Err((v, err))
                }
            }
        }
    }

    /// Returns `true` if the raw is valid UTF-8.
    pub fn is_str(&self) -> bool {
        self.s.is_ok()
    }

    /// Returns `true` if the raw contains invalid UTF-8 sequence.
    pub fn is_err(&self) -> bool {
        self.s.is_err()
    }

    /// Returns the string reference if the raw is valid UTF-8, or else `None`.
    pub fn as_str(&self) -> Option<&str> {
        match self.s {
            Ok(ref s) => Some(s),
            Err(..) => None,
        }
    }

    /// Returns the underlying `Utf8Error` if the raw contains invalid UTF-8 sequence, or
    /// else `None`.
    pub fn as_err(&self) -> Option<&Utf8Error> {
        match self.s {
            Ok(..) => None,
            Err((_, ref err)) => Some(&err),
        }
    }

    /// Returns a byte slice of this raw's contents.
    pub fn as_bytes(&self) -> &[u8] {
        match self.s {
            Ok(ref s) => s.as_bytes(),
            Err(ref err) => &err.0[..],
        }
    }
}

impl<'a> Serialize for RawRef<'a> {
    fn serialize<S>(&self, se: S) -> Result<S::Ok, S::Error>
        where
            S: serde::Serializer
    {
        let s = match self.s {
            Ok(ref s) => s,
            Err((ref b, ..)) => unsafe { mem::transmute(b) },
        };

        se.serialize_str(s)
    }
}

struct RawRefVisitor;

impl<'de> de::Visitor<'de> for RawRefVisitor {
    type Value = RawRef<'de>;

    fn expecting(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        "string or bytes".fmt(fmt)
    }

    #[inline]
    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
        where E: de::Error
    {
        Ok(RawRef { s: Ok(v) })
    }

    #[inline]
    fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
        where E: de::Error
    {
        let s = match str::from_utf8(v) {
            Ok(s) => Ok(s),
            Err(err) => Err((v, err)),
        };

        Ok(RawRef { s: s })
    }
}

impl<'de> Deserialize<'de> for RawRef<'de> {
    #[inline]
    fn deserialize<D>(de: D) -> Result<Self, D::Error>
        where D: de::Deserializer<'de>
    {
        de.deserialize_any(RawRefVisitor)
    }
}
<commit_msg>chore: style and docs<commit_after>//! # Type-based Serialization and Deserialization
//!
//! Serde provides a mechanism for low boilerplate serialization & deserialization of values to and
//! from MessagePack via the serialization API. To be able to serialize a piece of data, it must
//! implement the `serde::Serialize` trait. To be able to deserialize a piece of data, it must
//! implement the `serde::Deserialize` trait. Serde provides provides an annotation to
//! automatically generate the code for these traits: `#[derive(Serialize, Deserialize)]`.
//!
//! # Examples
//!
//! Let's try to encode and decode some built-in types.
//!
//! ```rust
//! extern crate serde;
//! extern crate rmp_serde as rmps;
//!
//! use serde::{Deserialize, Serialize};
//! use rmps::{Deserializer, Serializer};
//!
//! fn main() {
//!     let mut buf = Vec::new();
//!     let val = (42u8, "the Answer");
//!     val.serialize(&mut Serializer::new(&mut buf)).unwrap();
//!
//!     assert_eq!(vec![0x92, 0x2a, 0xaa, 0x74, 0x68, 0x65, 0x20, 0x41, 0x6e, 0x73, 0x77, 0x65, 0x72], buf);
//!
//!     let mut de = Deserializer::new(&buf[..]);
//!     assert_eq!((42, "the Answer".to_owned()), Deserialize::deserialize(&mut de).unwrap());
//! }
//! ```
//!
//! No one gonna hurt if we add some reflection magic.
//!
//! ```ignore
//! extern crate serde;
//! #[macro_use]
//! extern crate serde_derive;
//! extern crate rmp_serde as rmps;
//!
//! use std::collections::HashMap;
//! use serde::{Deserialize, Serialize};
//! use rmps::{Deserializer, Serializer};
//!
//! #[derive(Debug, PartialEq, Deserialize, Serialize)]
//! struct Human {
//!     age: u32,
//!     name: String,
//! }
//!
//! fn main() {
//!     let mut buf = Vec::new();
//!     let val = Human {
//!         age: 42,
//!         name: "John".into(),
//!     };
//!
//!     val.serialize(&mut Serializer::new(&mut buf)).unwrap();
//! }
//! ```

extern crate rmp;
extern crate byteorder;
#[macro_use]
extern crate serde;

use std::fmt::{self, Display, Formatter};
use std::mem;
use std::str::{self, Utf8Error};

use serde::Serialize;
use serde::de::{self, Deserialize};

pub use decode::{Deserializer, from_slice, from_read};
pub use encode::{Serializer, to_vec, to_vec_named};

pub mod decode;
pub mod encode;

/// Helper that allows both to encode and decode strings no matter whether they contain valid or
/// invalid UTF-8.
///
/// Regardless of validity the UTF-8 content this type will always be serialized as a string.
#[derive(Clone, Debug, PartialEq)]
pub struct Raw {
    s: Result<String, (Vec<u8>, Utf8Error)>,
}

impl Raw {
    /// Constructs a new `Raw` from the UTF-8 string.
    pub fn new(v: String) -> Self {
        Self { s: Ok(v) }
    }

    /// Converts a vector of bytes to a `Raw`.
    pub fn from_utf8(v: Vec<u8>) -> Self {
        match String::from_utf8(v) {
            Ok(v) => Raw::new(v),
            Err(err) => {
                let e = err.utf8_error();
                Self {
                    s: Err((err.into_bytes(), e))
                }
            }
        }
    }

    /// Returns `true` if the raw is valid UTF-8.
    pub fn is_str(&self) -> bool {
        self.s.is_ok()
    }

    /// Returns `true` if the raw contains invalid UTF-8 sequence.
    pub fn is_err(&self) -> bool {
        self.s.is_err()
    }

    /// Returns the string reference if the raw is valid UTF-8, or else `None`.
    pub fn as_str(&self) -> Option<&str> {
        match self.s {
            Ok(ref s) => Some(s.as_str()),
            Err(..) => None,
        }
    }

    /// Returns the underlying `Utf8Error` if the raw contains invalid UTF-8 sequence, or
    /// else `None`.
    pub fn as_err(&self) -> Option<&Utf8Error> {
        match self.s {
            Ok(..) => None,
            Err((_, ref err)) => Some(&err),
        }
    }

    /// Returns a byte slice of this raw's contents.
    pub fn as_bytes(&self) -> &[u8] {
        match self.s {
            Ok(ref s) => s.as_bytes(),
            Err(ref err) => &err.0[..],
        }
    }

    /// Consumes this object, yielding the string if the raw is valid UTF-8, or else `None`.
    pub fn into_str(self) -> Option<String> {
        self.s.ok()
    }

    /// Converts a `Raw` into a byte vector.
    pub fn into_bytes(self) -> Vec<u8> {
        match self.s {
            Ok(s) => s.into_bytes(),
            Err(err) => err.0,
        }
    }
}

impl Serialize for Raw {
    fn serialize<S>(&self, se: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer
    {
        let s = match self.s {
            Ok(ref s) => s.as_str(),
            Err((ref b, ..)) => unsafe { mem::transmute(&b[..]) },
        };

        se.serialize_str(s)
    }
}

struct RawVisitor;

impl<'de> de::Visitor<'de> for RawVisitor {
    type Value = Raw;

    fn expecting(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        "string or bytes".fmt(fmt)
    }

    #[inline]
    fn visit_string<E>(self, v: String) -> Result<Self::Value, E> {
        Ok(Raw { s: Ok(v) })
    }

    #[inline]
    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
        where E: de::Error
    {
        Ok(Raw { s: Ok(v.into()) })
    }

    #[inline]
    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
        where E: de::Error
    {
        let s = match str::from_utf8(v) {
            Ok(s) => Ok(s.into()),
            Err(err) => Err((v.into(), err)),
        };

        Ok(Raw { s: s })
    }

    #[inline]
    fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
        where E: de::Error
    {
        let s = match String::from_utf8(v) {
            Ok(s) => Ok(s),
            Err(err) => {
                let e = err.utf8_error();
                Err((err.into_bytes(), e))
            }
        };

        Ok(Raw { s: s })
    }
}

impl<'de> Deserialize<'de> for Raw {
    #[inline]
    fn deserialize<D>(de: D) -> Result<Self, D::Error>
        where D: de::Deserializer<'de>
    {
        de.deserialize_any(RawVisitor)
    }
}

/// Helper that allows both to encode and decode strings no matter whether they contain valid or
/// invalid UTF-8.
///
/// Regardless of validity the UTF-8 content this type will always be serialized as a string.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct RawRef<'a> {
    s: Result<&'a str, (&'a [u8], Utf8Error)>,
}

impl<'a> RawRef<'a> {
    /// Constructs a new `RawRef` from the UTF-8 string.
    pub fn new(v: &'a str) -> Self {
        Self { s: Ok(v) }
    }

    /// Converts a vector of bytes to a `RawRef`.
    pub fn from_utf8(v: &'a [u8]) -> Self {
        match str::from_utf8(v) {
            Ok(v) => RawRef::new(v),
            Err(err) => {
                Self {
                    s: Err((v, err))
                }
            }
        }
    }

    /// Returns `true` if the raw is valid UTF-8.
    pub fn is_str(&self) -> bool {
        self.s.is_ok()
    }

    /// Returns `true` if the raw contains invalid UTF-8 sequence.
    pub fn is_err(&self) -> bool {
        self.s.is_err()
    }

    /// Returns the string reference if the raw is valid UTF-8, or else `None`.
    pub fn as_str(&self) -> Option<&str> {
        match self.s {
            Ok(ref s) => Some(s),
            Err(..) => None,
        }
    }

    /// Returns the underlying `Utf8Error` if the raw contains invalid UTF-8 sequence, or
    /// else `None`.
    pub fn as_err(&self) -> Option<&Utf8Error> {
        match self.s {
            Ok(..) => None,
            Err((_, ref err)) => Some(&err),
        }
    }

    /// Returns a byte slice of this raw's contents.
    pub fn as_bytes(&self) -> &[u8] {
        match self.s {
            Ok(ref s) => s.as_bytes(),
            Err(ref err) => &err.0[..],
        }
    }
}

impl<'a> Serialize for RawRef<'a> {
    fn serialize<S>(&self, se: S) -> Result<S::Ok, S::Error>
        where
            S: serde::Serializer
    {
        let s = match self.s {
            Ok(ref s) => s,
            Err((ref b, ..)) => unsafe { mem::transmute(b) },
        };

        se.serialize_str(s)
    }
}

struct RawRefVisitor;

impl<'de> de::Visitor<'de> for RawRefVisitor {
    type Value = RawRef<'de>;

    fn expecting(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        "string or bytes".fmt(fmt)
    }

    #[inline]
    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
        where E: de::Error
    {
        Ok(RawRef { s: Ok(v) })
    }

    #[inline]
    fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
        where E: de::Error
    {
        let s = match str::from_utf8(v) {
            Ok(s) => Ok(s),
            Err(err) => Err((v, err)),
        };

        Ok(RawRef { s: s })
    }
}

impl<'de> Deserialize<'de> for RawRef<'de> {
    #[inline]
    fn deserialize<D>(de: D) -> Result<Self, D::Error>
        where D: de::Deserializer<'de>
    {
        de.deserialize_any(RawRefVisitor)
    }
}
<|endoftext|>