<commit_before>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

use std::{str, ptr, mem};
use std::ffi::{CStr, CString};
use std::thread;
use std::net::TcpStream;
use std::sync::mpsc::{channel, Sender, Receiver};

use super::libc::{c_int, c_char, c_void};
use super::simple_stream::bstream::Bstream;

extern "C" {
    fn register_writer_tx(tx: *mut c_void);
    fn register_stop_tx(tx: *mut c_void);
}

// #[no_mangle]
// pub extern "C" fn some_new_fn() -> c_int {
//     println!("some_new_fn");
//     65 as c_int
// }

#[no_mangle]
pub extern "C" fn start(address: *const c_char,
    handler: extern fn(*const c_char, c_int),
    on_connect_handler: extern fn(),
    on_disconnect_handler: extern fn()) -> c_int {

    println!("Rust - start()");

    // println!("start");
    // 88 as c_int

    let mut r_address;
    unsafe {
        r_address = CStr::from_ptr(address);
    }
    let s_address = r_address.to_bytes();
    let host_address = match str::from_utf8(s_address) {
        Ok(safe_str) => safe_str,
        Err(_) => {
            println!("Invalid host address");
            return -1 as c_int;
        }
    };

    println!("Rust - address: {}", host_address);

    // Create and register a way to kill this client
    let (k_tx, kill_rx): (Sender<()>, Receiver<()>) = channel();
    let kill_tx = k_tx.clone();
    let mut k_tx_ptr = Box::new(k_tx);

    println!("calling register_stop_tx");

    let mut k_tx_ptr_clone = k_tx_ptr.clone();
    unsafe {
        let mut k_tx_as_void_ptr: *mut c_void = mem::transmute(k_tx_ptr_clone);
        register_stop_tx(&mut *k_tx_as_void_ptr);
    }
    //
    // // Writer thread's channel
    // let (w_tx, w_rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = channel();
    // let mut w_tx_ptr = Box::new(w_tx);
    // unsafe {
    //     register_writer_tx(&mut *w_tx_ptr);
    // }
    //
    // println!("Attempting connect to: {}", host_address);

    // let result = TcpStream::connect(host_address);
    // if result.is_err() {
    //     println!("Error connecting to {} - {}", host_address, result.unwrap_err());
    //     return -1 as c_int;
    // }
    // println!("Connected");
    // on_connect_handler();
    //
    // let stream = result.unwrap();
    // let client = Bstream::new(stream);
    //
    // let r_client = client.clone();
    // let r_kill_tx = kill_tx.clone();
    //
    // let w_client = client.clone();
    // let w_kill_tx = kill_tx.clone();
    //
    // // Start the reader thread
    // thread::Builder::new()
    //     .name("ReaderThread".to_string())
    //     .spawn(move||{
    //         reader_thread(r_client, handler, r_kill_tx)
    //     }).unwrap();
    //
    // // Start the writer thread
    // thread::Builder::new()
    //     .name("WriterThread".to_string())
    //     .spawn(move||{
    //         writer_thread(w_rx, w_client, w_kill_tx)
    //     }).unwrap();
    //
    // // Wait for the kill signal
    // match kill_rx.recv() {
    //     Ok(_) => { }
    //     Err(e) => {
    //         println!("Error on kill channel: {}", e);
    //         return -1 as c_int;
    //     }
    // };
    // on_disconnect_handler();

    // Exit out in standard C fashion
    0 as c_int
}

// /// Connects to the provided address, (eg "123.123.123.123:3000") and registers
// /// the on data received handler
// #[no_mangle]
// pub extern "C" fn connect(address: *const c_char,
//     handler: extern fn(*const c_char, c_int),
//     on_connect_handler: extern fn(),
//     on_disconnect_handler: extern fn()) -> c_int {
//
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//
//
//     78 as c_int
//
//
//     let mut r_address;
//     unsafe {
//         r_address = CStr::from_ptr(address);
//     }
//     let s_address = r_address.to_bytes();
//     let host_address = match str::from_utf8(s_address) {
//         Ok(safe_str) => safe_str,
//         Err(_) => {
//             println!("Invalid host address");
//             return -1 as c_int;
//         }
//     };
//
//     // Create and register a way to kill this client
//     let (k_tx, kill_rx): (Sender<()>, Receiver<()>) = channel();
//     let kill_tx = k_tx.clone();
//     let mut k_tx_ptr = Box::new(k_tx);
//     unsafe {
//         register_stop_tx(&mut *k_tx_ptr);
//     }
//
//     // Writer thread's channel
//     let (w_tx, w_rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = channel();
//     let mut w_tx_ptr = Box::new(w_tx);
//     unsafe {
//         register_writer_tx(&mut *w_tx_ptr);
//     }
//
//     println!("Attempting connect to: {}", host_address);
//
//     let result = TcpStream::connect(host_address);
//     if result.is_err() {
//         println!("Error connecting to {} - {}", host_address, result.unwrap_err());
//         return -1 as c_int;
//     }
//     println!("Connected");
//     on_connect_handler();
//
//     let stream = result.unwrap();
//     let client = Bstream::new(stream);
//
//     let r_client = client.clone();
//     let r_kill_tx = kill_tx.clone();
//
//     let w_client = client.clone();
//     let w_kill_tx = kill_tx.clone();
//
//     // Start the reader thread
//     thread::Builder::new()
//         .name("ReaderThread".to_string())
//         .spawn(move||{
//             reader_thread(r_client, handler, r_kill_tx)
//         }).unwrap();
//
//     // Start the writer thread
//     thread::Builder::new()
//         .name("WriterThread".to_string())
//         .spawn(move||{
//             writer_thread(w_rx, w_client, w_kill_tx)
//         }).unwrap();
//
//     // Wait for the kill signal
//     match kill_rx.recv() {
//         Ok(_) => { }
//         Err(e) => {
//             println!("Error on kill channel: {}", e);
//             return -1 as c_int;
//         }
//     };
//     on_disconnect_handler();
//
//     // Exit out in standard C fashion
//     0 as c_int
// }

/// Writes the complete contents of buffer to the server
/// Returns -1 on error
#[no_mangle]
pub extern "C" fn send_to_writer(w_tx: *mut Sender<Vec<u8>>,
                                 buffer: *const c_char,
                                 count: c_int,
                                 k_tx: *mut Sender<()>) -> c_int {
    if count < 1 {
        println!("Error - count must be greater than zero");
        return -1 as c_int;
    }

    let num_elts = count as usize;
    let mut n_buffer = Vec::<u8>::with_capacity(num_elts);
    for x in 0..num_elts as isize {
        unsafe {
            n_buffer.push(ptr::read(buffer.offset(x)) as u8);
        }
    }

    unsafe {
        match (*w_tx).send(n_buffer) {
            Ok(_) => { }
            Err(e) => {
                println!("Error sending buffer: {}", e);
                let _ = (*k_tx).send(());
                return -1 as c_int;
            }
        };
    }

    0 as c_int
}

/// Forever listens to incoming data and when a complete message is received,
/// the passed callback is hit
fn reader_thread(client: Bstream,
                 event_handler: extern fn(*const c_char, c_int),
                 kill_tx: Sender<()>) {

    let mut reader = client.clone();
    loop {
        match reader.read() {
            Ok(buffer) => {
                // Launch the handler in a new thread
                thread::Builder::new()
                    .name("Reader-Worker".to_string())
                    .spawn(move||{
                        let slice = &buffer[..];
                        let c_buffer = CString::new(slice).unwrap();
                        event_handler(c_buffer.as_ptr(), buffer.len() as c_int);
                    }).unwrap();
            }
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        };
    }
    println!("Reader thread finished");
    let _ = kill_tx.send(());
}

/// Forever listens to Receiver<Vec<u8>> waiting on messages to come in
/// Once available, blocks until the entire message has been written
fn writer_thread(rx: Receiver<Vec<u8>>, client: Bstream, kill_tx: Sender<()>) {
    let mut writer = client.clone();
    loop {
        match rx.recv() {
            Ok(ref mut buffer) => {
                match writer.write(buffer) {
                    Ok(_) => { }
                    Err(e) => {
                        println!("Error: {}", e);
                        break;
                    }
                };
            }
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        };
    }
    println!("Writer thread finished");
    let _ = kill_tx.send(());
}
<commit_msg>Debugging my life away<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

use std::{str, ptr, mem};
use std::ffi::{CStr, CString};
use std::thread;
use std::net::TcpStream;
use std::sync::mpsc::{channel, Sender, Receiver};

use super::libc::{c_int, c_char, c_void};
use super::simple_stream::bstream::Bstream;

extern "C" {
    fn register_writer_tx(tx: *mut c_void);
    fn register_stop_tx(tx: *mut c_void);
}

#[no_mangle]
pub extern "C" fn start(address: *const c_char,
    handler: extern fn(*const c_char, c_int),
    on_connect_handler: extern fn(),
    on_disconnect_handler: extern fn()) -> c_int {

    println!("Rust - start()");

    let mut r_address;
    unsafe {
        r_address = CStr::from_ptr(address);
    }
    let s_address = r_address.to_bytes();
    let host_address = match str::from_utf8(s_address) {
        Ok(safe_str) => safe_str,
        Err(_) => {
            println!("Invalid host address");
            return -1 as c_int;
        }
    };

    println!("Rust - address: {}", host_address);

    // Create and register a way to kill this client
    let (k_tx, kill_rx): (Sender<()>, Receiver<()>) = channel();
    let kill_tx = k_tx.clone();
    let mut k_tx_ptr = Box::new(k_tx);

    println!("calling register_stop_tx");

    let mut k_tx_ptr_clone = k_tx_ptr.clone();
    unsafe {
        let mut k_tx_as_void_ptr: *mut c_void = mem::transmute(k_tx_ptr_clone);
        //register_stop_tx(&mut *k_tx_as_void_ptr);
    }
    //
    // // Writer thread's channel
    // let (w_tx, w_rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = channel();
    // let mut w_tx_ptr = Box::new(w_tx);
    // unsafe {
    //     register_writer_tx(&mut *w_tx_ptr);
    // }
    //
    // println!("Attempting connect to: {}", host_address);

    // let result = TcpStream::connect(host_address);
    // if result.is_err() {
    //     println!("Error connecting to {} - {}", host_address, result.unwrap_err());
    //     return -1 as c_int;
    // }
    // println!("Connected");
    // on_connect_handler();
    //
    // let stream = result.unwrap();
    // let client = Bstream::new(stream);
    //
    // let r_client = client.clone();
    // let r_kill_tx = kill_tx.clone();
    //
    // let w_client = client.clone();
    // let w_kill_tx = kill_tx.clone();
    //
    // // Start the reader thread
    // thread::Builder::new()
    //     .name("ReaderThread".to_string())
    //     .spawn(move||{
    //         reader_thread(r_client, handler, r_kill_tx)
    //     }).unwrap();
    //
    // // Start the writer thread
    // thread::Builder::new()
    //     .name("WriterThread".to_string())
    //     .spawn(move||{
    //         writer_thread(w_rx, w_client, w_kill_tx)
    //     }).unwrap();
    //
    // // Wait for the kill signal
    // match kill_rx.recv() {
    //     Ok(_) => { }
    //     Err(e) => {
    //         println!("Error on kill channel: {}", e);
    //         return -1 as c_int;
    //     }
    // };
    // on_disconnect_handler();

    // Exit out in standard C fashion
    0 as c_int
}

// /// Connects to the provided address, (eg "123.123.123.123:3000") and registers
// /// the on data received handler
// #[no_mangle]
// pub extern "C" fn connect(address: *const c_char,
//     handler: extern fn(*const c_char, c_int),
//     on_connect_handler: extern fn(),
//     on_disconnect_handler: extern fn()) -> c_int {
//
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//
//
//     78 as c_int
//
//
//     let mut r_address;
//     unsafe {
//         r_address = CStr::from_ptr(address);
//     }
//     let s_address = r_address.to_bytes();
//     let host_address = match str::from_utf8(s_address) {
//         Ok(safe_str) => safe_str,
//         Err(_) => {
//             println!("Invalid host address");
//             return -1 as c_int;
//         }
//     };
//
//     // Create and register a way to kill this client
//     let (k_tx, kill_rx): (Sender<()>, Receiver<()>) = channel();
//     let kill_tx = k_tx.clone();
//     let mut k_tx_ptr = Box::new(k_tx);
//     unsafe {
//         register_stop_tx(&mut *k_tx_ptr);
//     }
//
//     // Writer thread's channel
//     let (w_tx, w_rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = channel();
//     let mut w_tx_ptr = Box::new(w_tx);
//     unsafe {
//         register_writer_tx(&mut *w_tx_ptr);
//     }
//
//     println!("Attempting connect to: {}", host_address);
//
//     let result = TcpStream::connect(host_address);
//     if result.is_err() {
//         println!("Error connecting to {} - {}", host_address, result.unwrap_err());
//         return -1 as c_int;
//     }
//     println!("Connected");
//     on_connect_handler();
//
//     let stream = result.unwrap();
//     let client = Bstream::new(stream);
//
//     let r_client = client.clone();
//     let r_kill_tx = kill_tx.clone();
//
//     let w_client = client.clone();
//     let w_kill_tx = kill_tx.clone();
//
//     // Start the reader thread
//     thread::Builder::new()
//         .name("ReaderThread".to_string())
//         .spawn(move||{
//             reader_thread(r_client, handler, r_kill_tx)
//         }).unwrap();
//
//     // Start the writer thread
//     thread::Builder::new()
//         .name("WriterThread".to_string())
//         .spawn(move||{
//             writer_thread(w_rx, w_client, w_kill_tx)
//         }).unwrap();
//
//     // Wait for the kill signal
//     match kill_rx.recv() {
//         Ok(_) => { }
//         Err(e) => {
//             println!("Error on kill channel: {}", e);
//             return -1 as c_int;
//         }
//     };
//     on_disconnect_handler();
//
//     // Exit out in standard C fashion
//     0 as c_int
// }

/// Writes the complete contents of buffer to the server
/// Returns -1 on error
#[no_mangle]
pub extern "C" fn send_to_writer(w_tx: *mut Sender<Vec<u8>>,
                                 buffer: *const c_char,
                                 count: c_int,
                                 k_tx: *mut Sender<()>) -> c_int {
    if count < 1 {
        println!("Error - count must be greater than zero");
        return -1 as c_int;
    }

    let num_elts = count as usize;
    let mut n_buffer = Vec::<u8>::with_capacity(num_elts);
    for x in 0..num_elts as isize {
        unsafe {
            n_buffer.push(ptr::read(buffer.offset(x)) as u8);
        }
    }

    unsafe {
        match (*w_tx).send(n_buffer) {
            Ok(_) => { }
            Err(e) => {
                println!("Error sending buffer: {}", e);
                let _ = (*k_tx).send(());
                return -1 as c_int;
            }
        };
    }

    0 as c_int
}

/// Forever listens to incoming data and when a complete message is received,
/// the passed callback is hit
fn reader_thread(client: Bstream,
                 event_handler: extern fn(*const c_char, c_int),
                 kill_tx: Sender<()>) {

    let mut reader = client.clone();
    loop {
        match reader.read() {
            Ok(buffer) => {
                // Launch the handler in a new thread
                thread::Builder::new()
                    .name("Reader-Worker".to_string())
                    .spawn(move||{
                        let slice = &buffer[..];
                        let c_buffer = CString::new(slice).unwrap();
                        event_handler(c_buffer.as_ptr(), buffer.len() as c_int);
                    }).unwrap();
            }
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        };
    }
    println!("Reader thread finished");
    let _ = kill_tx.send(());
}

/// Forever listens to Receiver<Vec<u8>> waiting on messages to come in
/// Once available, blocks until the entire message has been written
fn writer_thread(rx: Receiver<Vec<u8>>, client: Bstream, kill_tx: Sender<()>) {
    let mut writer = client.clone();
    loop {
        match rx.recv() {
            Ok(ref mut buffer) => {
                match writer.write(buffer) {
                    Ok(_) => { }
                    Err(e) => {
                        println!("Error: {}", e);
                        break;
                    }
                };
            }
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        };
    }
    println!("Writer thread finished");
    let _ = kill_tx.send(());
}
<|endoftext|>


<commit_before>use std::sync::{Mutex, Arc};
use std::net::{SocketAddr, ToSocketAddrs};
use std::collections::VecDeque;
use std::error::Error;
use std::mem;
use opengl_graphics::GlGraphics;
use opengl_graphics::glyph_cache::GlyphCache;
use piston::input::{Button, Key, MouseButton, RenderArgs, UpdateArgs};

use std::{thread, time};
use std::net::TcpStream;
use network::{Command, Message};

use bincode::{serialize_into, deserialize_from, Infinite};

use state::{UnitId, ClientId, WorldState, GameState, UNIT_SIZE};
use shapes::Shape;
use colors;
use colors::{BLACK, ORANGE};

pub mod menu;
pub mod error;

use self::menu::Menu;

pub struct NetworkClient {
    pub game_state: Arc<Mutex<Option<GameState>>>,
    server_addr: SocketAddr,
    stream: Option<TcpStream>,
    commands: Arc<Mutex<VecDeque<Command>>>,
}

impl NetworkClient {
    pub fn new<T: ToSocketAddrs>(server_addrs: T,
                                 game_state: Arc<Mutex<Option<GameState>>>,
                                 commands: Arc<Mutex<VecDeque<Command>>>) -> NetworkClient {
        let server_addr = server_addrs.to_socket_addrs().unwrap().next().unwrap();
        NetworkClient {
            game_state: game_state,
            server_addr: server_addr,
            stream: None,
            commands: commands,
        }
    }

    pub fn connect(&mut self) -> Result<(ClientId, WorldState), Box<Error>>  {
        let mut stream = TcpStream::connect(self.server_addr)?;
        serialize_into(&mut stream, &Message::ClientHello, Infinite)?;
        let server_hello = deserialize_from(&mut stream, Infinite);

        self.stream = Some(stream);
        if let Ok(Message::ServerHello(client_id, world_state)) = server_hello {
            Ok((client_id, world_state))
        } else {
            Err("Could not connect to server".into())
        }
    }

    pub fn update(&self) {
        let stream = self.stream.as_ref().expect("Stream not here :(");
        let mut command_stream = stream.try_clone().unwrap();
        let commands = self.commands.clone();

        // Command sender loop
        thread::spawn(move || {
            loop {
                let command = {
                    let mut commands = commands.lock().unwrap();
                    commands.pop_front()
                };
                command.map(|cmd| {
                    println!("Got command: {:?}", cmd);
                    //let cmd = Message::Command(Command::Move(0.into(), [100f64, 100f64]));
                    serialize_into(&mut command_stream, &Message::Command(cmd), Infinite)
                        .unwrap_or_else(|e|println!("Sending command failed: {}", e));
                });
                thread::sleep(time::Duration::from_millis(10));
            }
        });

        let mut game_state_stream = stream.try_clone().unwrap();
        let game_state = self.game_state.clone();
        thread::spawn(move || {
            loop {
                let game_state_server: Result<GameState,_> = deserialize_from(
                    &mut game_state_stream,
                    Infinite);
                match game_state_server {
                    Ok(game) => {
                        //println!("{:?}", game);
                        let mut game_state_lock = game_state.lock().unwrap();
                        *game_state_lock = Some(game);

                    }
                    Err(e) => {
                        println!("{:?}", e);
                        thread::sleep(time::Duration::from_millis(200));
                    }
                }
            }
        });
    }
}

#[derive(Clone, Debug)]
pub enum State {
    Menu,
    Error(error::Message),
    Running,
}

pub struct App {
    pub gl: GlGraphics, // OpenGL drawing backend.
    pub world_state: Option<WorldState>,
    pub game_state_server: Arc<Mutex<Option<GameState>>>,
    pub game_state: GameState,
    pub selected_units: Vec<UnitId>,
    pub commands: Arc<Mutex<VecDeque<Command>>>,
    pub cursor: [f64; 2],
    pub state: State,
    zoom: f64,
    scroll: [f64; 2],
    menu: Menu,
    client_id: Option<ClientId>,
}

impl App {
    pub fn new(gl: GlGraphics) -> App {
        App {
            gl: gl,
            world_state: None,
            game_state_server: Arc::new(Mutex::new(None)),
            game_state: GameState::new(),
            selected_units: vec![],
            commands: Arc::new(Mutex::new(VecDeque::new())),
            cursor: [0.0, 0.0],
            state: State::Menu,
            zoom: 1.0,
            scroll: [0.0, 0.0],
            menu: Menu::new(),
            client_id: None,
        }
    }

    pub fn start(&mut self) -> Result<(), Box<Error>> {
        let mut network_client = NetworkClient::new(
            ("127.0.0.1", 8080),
            self.game_state_server.clone(),
            self.commands.clone());
        let (client_id, world_state) = network_client.connect()?;
        self.client_id = Some(client_id);
        self.world_state = Some(world_state);
        network_client.update();
        Ok(())
    }

    pub fn select(&mut self, position: [f64;2]) {

        let player = {
            let index = self.client_id.unwrap_or(ClientId(0)).0 as usize;
            self.game_state.players.get(index).map(|v| v.clone())
        };

        self.selected_units.truncate(0);
        if let Some(player) = player {
            for unit in player.units.iter() {
                if unit.is_hit(UNIT_SIZE, position) {
                    self.selected_units.push(unit.id);
                }
            }
        }
    }

    fn render_game(&mut self, args: &RenderArgs, _: &mut GlyphCache) {
        use graphics::{polygon, line, clear, ellipse};
        use graphics::Transformed;
        use graphics::types::{Polygon, Line};

        const FRONT_THICKNESS: f64 = 5.0;

        let game_state = &self.game_state;
        let world = self.world_state.as_ref().unwrap();
        let (wx, wy) = (world.x, world.y);
        let zoom = self.zoom;
        let scroll = self.scroll;
        let selected_units = self.selected_units.clone();

        self.gl.draw(args.viewport(), |c, gl| {

            let transform = c.transform
                .scale(zoom, zoom)
                .trans(scroll[0], scroll[1]);

            // Clear the screen.
            clear(BLACK, gl);

            let world: [Line; 4] = [
                [0.0, 0.0, wx,  0.0],
                [wx,  0.0, wx,  wy],
                [wx,  wy,  0.0, wy],
                [0.0, wy,  0.0, 0.0],
            ];

            for l in world.iter() {
                line(ORANGE, 1.0, *l, transform, gl);
            }

            for i in 0..game_state.players.len() {
                let ref player = game_state.players[i];
                let color = &colors::PLAYERS[i % colors::PLAYERS.len()];
                for s in player.units.iter() {
                    // Create a triangle polygon. The initial orientation is facing east.
                    let triangle: Polygon = &s.get_shape(UNIT_SIZE);

                    // Create a border on the front of the polygon. This is a trapezoid.
                    // Because the angle of the trapezoid side is 22.5°, we know that `dx` is always `2 * dy`.
                    let front: Polygon = &[
                        [UNIT_SIZE, UNIT_SIZE],                                           // Top right
                        [UNIT_SIZE, 0.0],                                                 // Bottom right
                        [UNIT_SIZE - FRONT_THICKNESS, FRONT_THICKNESS / 2.0],             // Bottom left
                        [UNIT_SIZE - FRONT_THICKNESS, UNIT_SIZE - FRONT_THICKNESS / 2.0], // Top left
                    ];

                    // Rotate the front to match the unit
                    let transform_front = transform.trans(s.position[0], s.position[1])
                        .rot_rad(s.angle)
                        .trans(-0.5 * UNIT_SIZE, -0.5 * UNIT_SIZE);

                    // We don't need to apply any transformation to the units
                    let transform_triangle = transform;

                    // Draw the unit ORANGE if selected
                    let selected = selected_units.iter().any(|id| id == &s.id);
                    if selected {
                        polygon(color.primary, triangle, transform_triangle, gl);
                        polygon(color.secondary, front, transform_front, gl);
                    } else {
                        polygon(color.secondary, triangle, transform_triangle, gl);
                        polygon(color.primary, front, transform_front, gl);
                    }

                }

                for b in player.bullets.iter() {
                    let transform = transform.trans(b.position[0], b.position[1]);
                    ellipse(color.primary, [0.0, 0.0, 1.0, 1.0], transform, gl);
                }
            }
        });
    }

    pub fn render(&mut self, args: &RenderArgs, cache: &mut GlyphCache) {
        match self.state {
            State::Menu => self.menu.render(args, &mut self.gl, cache),
            State::Running => self.render_game(args, cache),
            State::Error(ref msg) => msg.render(args, &mut self.gl, cache),
        }
    }

    pub fn update(&mut self, args: &UpdateArgs) {
        // grab updated server state if it is available
        let game_state_option = {
            let mut game_state_lock = self.game_state_server.lock().unwrap();
            mem::replace(&mut *game_state_lock, None)
        };
        if let Some(game_state) = game_state_option {
            self.game_state = game_state;
        } else {
            self.game_state.update(args.dt*1000.0);
        }
    }

    pub fn on_button_press(&mut self, button: &Button) -> bool {
        match self.state {
            State::Menu => {
                match button {
                    &Button::Keyboard(Key::Up) => {
                        self.menu.previous();
                    }
                    &Button::Keyboard(Key::Down) => {
                        self.menu.next();
                    }
                    &Button::Keyboard(Key::Return) => {
                        match self.menu.get_selected_entry() {
                            menu::Entries::Start => {
                                match self.start() {
                                    Ok(_) => {
                                        self.state = State::Running;
                                    }
                                    Err(err) => {
                                        self.state = State::Error(error::Message::new(err.description().into()));
                                    }
                                }
                            }
                            menu::Entries::Exit => {
                                return true;
                            }
                        }
                    }
                    _ => { }
                }
            }
            State::Running => {
                match button {
                    &Button::Keyboard(Key::Up) => {
                        self.scroll[1] += 10.0;
                    }
                    &Button::Keyboard(Key::Down) => {
                        self.scroll[1] -= 10.0;
                    }
                    &Button::Keyboard(Key::Left) => {
                        self.scroll[0] += 10.0;
                    }
                    &Button::Keyboard(Key::Right) => {
                        self.scroll[0] -= 10.0;
                    }
                    &Button::Keyboard(_) => { }
                    &Button::Mouse(button) => {
                        self.on_mouse_click(&button);
                    }
                    &Button::Controller(_) => { }
                }
            }
            State::Error(_) => {
                match button {
                    &Button::Keyboard(_) => { self.state = State::Menu; }
                    _ => { }
                }
            }
        };
        false
    }

    pub fn on_mouse_click(&mut self, button: &MouseButton) {
        let cursor = [
            self.cursor[0] / self.zoom - self.scroll[0],
            self.cursor[1] / self.zoom - self.scroll[1],
        ];
        match *button {
            MouseButton::Left  => self.select(cursor),
            MouseButton::Right => self.move_selected(cursor),
            _ => println!("Pressed mouse button '{:?}'", button),
        }
    }

    pub fn on_mouse_move(&mut self, cursor: [f64; 2]) {
        self.cursor = cursor;
    }

    pub fn on_mouse_scroll(&mut self, scroll: [f64; 2]) {
        if scroll[1] > 0.0 {
            self.zoom *= 1.5 * scroll[1];
        } else {
            self.zoom /= 1.5 * -scroll[1];
        }
        println!("zoom: {}", self.zoom);
    }

    pub fn move_selected(&mut self, position: [f64;2]) {
        for u in self.selected_units.iter() {
            let mut commands = self.commands.lock().unwrap();
            commands.push_back(Command::Move(*u, position));
        }
    }
}
<commit_msg>client: Send Shoot command when pressing 'f'<commit_after>use std::sync::{Mutex, Arc};
use std::net::{SocketAddr, ToSocketAddrs};
use std::collections::VecDeque;
use std::error::Error;
use std::mem;
use opengl_graphics::GlGraphics;
use opengl_graphics::glyph_cache::GlyphCache;
use piston::input::{Button, Key, MouseButton, RenderArgs, UpdateArgs};

use std::{thread, time};
use std::net::TcpStream;
use network::{Command, Message};

use bincode::{serialize_into, deserialize_from, Infinite};

use state::{UnitId, ClientId, WorldState, GameState, UNIT_SIZE};
use shapes::Shape;
use colors;
use colors::{BLACK, ORANGE};

pub mod menu;
pub mod error;

use self::menu::Menu;

pub struct NetworkClient {
    pub game_state: Arc<Mutex<Option<GameState>>>,
    server_addr: SocketAddr,
    stream: Option<TcpStream>,
    commands: Arc<Mutex<VecDeque<Command>>>,
}

impl NetworkClient {
    pub fn new<T: ToSocketAddrs>(server_addrs: T,
                                 game_state: Arc<Mutex<Option<GameState>>>,
                                 commands: Arc<Mutex<VecDeque<Command>>>) -> NetworkClient {
        let server_addr = server_addrs.to_socket_addrs().unwrap().next().unwrap();
        NetworkClient {
            game_state: game_state,
            server_addr: server_addr,
            stream: None,
            commands: commands,
        }
    }

    pub fn connect(&mut self) -> Result<(ClientId, WorldState), Box<Error>>  {
        let mut stream = TcpStream::connect(self.server_addr)?;
        serialize_into(&mut stream, &Message::ClientHello, Infinite)?;
        let server_hello = deserialize_from(&mut stream, Infinite);

        self.stream = Some(stream);
        if let Ok(Message::ServerHello(client_id, world_state)) = server_hello {
            Ok((client_id, world_state))
        } else {
            Err("Could not connect to server".into())
        }
    }

    pub fn update(&self) {
        let stream = self.stream.as_ref().expect("Stream not here :(");
        let mut command_stream = stream.try_clone().unwrap();
        let commands = self.commands.clone();

        // Command sender loop
        thread::spawn(move || {
            loop {
                let command = {
                    let mut commands = commands.lock().unwrap();
                    commands.pop_front()
                };
                command.map(|cmd| {
                    println!("Got command: {:?}", cmd);
                    //let cmd = Message::Command(Command::Move(0.into(), [100f64, 100f64]));
                    serialize_into(&mut command_stream, &Message::Command(cmd), Infinite)
                        .unwrap_or_else(|e|println!("Sending command failed: {}", e));
                });
                thread::sleep(time::Duration::from_millis(10));
            }
        });

        let mut game_state_stream = stream.try_clone().unwrap();
        let game_state = self.game_state.clone();
        thread::spawn(move || {
            loop {
                let game_state_server: Result<GameState,_> = deserialize_from(
                    &mut game_state_stream,
                    Infinite);
                match game_state_server {
                    Ok(game) => {
                        //println!("{:?}", game);
                        let mut game_state_lock = game_state.lock().unwrap();
                        *game_state_lock = Some(game);

                    }
                    Err(e) => {
                        println!("{:?}", e);
                        thread::sleep(time::Duration::from_millis(200));
                    }
                }
            }
        });
    }
}

#[derive(Clone, Debug)]
pub enum State {
    Menu,
    Error(error::Message),
    Running,
}

pub struct App {
    pub gl: GlGraphics, // OpenGL drawing backend.
    pub world_state: Option<WorldState>,
    pub game_state_server: Arc<Mutex<Option<GameState>>>,
    pub game_state: GameState,
    pub selected_units: Vec<UnitId>,
    pub commands: Arc<Mutex<VecDeque<Command>>>,
    pub cursor: [f64; 2],
    pub state: State,
    zoom: f64,
    scroll: [f64; 2],
    menu: Menu,
    client_id: Option<ClientId>,
}

impl App {
    pub fn new(gl: GlGraphics) -> App {
        App {
            gl: gl,
            world_state: None,
            game_state_server: Arc::new(Mutex::new(None)),
            game_state: GameState::new(),
            selected_units: vec![],
            commands: Arc::new(Mutex::new(VecDeque::new())),
            cursor: [0.0, 0.0],
            state: State::Menu,
            zoom: 1.0,
            scroll: [0.0, 0.0],
            menu: Menu::new(),
            client_id: None,
        }
    }

    pub fn start(&mut self) -> Result<(), Box<Error>> {
        let mut network_client = NetworkClient::new(
            ("127.0.0.1", 8080),
            self.game_state_server.clone(),
            self.commands.clone());
        let (client_id, world_state) = network_client.connect()?;
        self.client_id = Some(client_id);
        self.world_state = Some(world_state);
        network_client.update();
        Ok(())
    }

    pub fn select(&mut self, position: [f64;2]) {

        let player = {
            let index = self.client_id.unwrap_or(ClientId(0)).0 as usize;
            self.game_state.players.get(index).map(|v| v.clone())
        };

        self.selected_units.truncate(0);
        if let Some(player) = player {
            for unit in player.units.iter() {
                if unit.is_hit(UNIT_SIZE, position) {
                    self.selected_units.push(unit.id);
                }
            }
        }
    }

    fn render_game(&mut self, args: &RenderArgs, _: &mut GlyphCache) {
        use graphics::{polygon, line, clear, ellipse};
        use graphics::Transformed;
        use graphics::types::{Polygon, Line};

        const FRONT_THICKNESS: f64 = 5.0;

        let game_state = &self.game_state;
        let world = self.world_state.as_ref().unwrap();
        let (wx, wy) = (world.x, world.y);
        let zoom = self.zoom;
        let scroll = self.scroll;
        let selected_units = self.selected_units.clone();

        self.gl.draw(args.viewport(), |c, gl| {

            let transform = c.transform
                .scale(zoom, zoom)
                .trans(scroll[0], scroll[1]);

            // Clear the screen.
            clear(BLACK, gl);

            let world: [Line; 4] = [
                [0.0, 0.0, wx,  0.0],
                [wx,  0.0, wx,  wy],
                [wx,  wy,  0.0, wy],
                [0.0, wy,  0.0, 0.0],
            ];

            for l in world.iter() {
                line(ORANGE, 1.0, *l, transform, gl);
            }

            for i in 0..game_state.players.len() {
                let ref player = game_state.players[i];
                let color = &colors::PLAYERS[i % colors::PLAYERS.len()];
                for s in player.units.iter() {
                    // Create a triangle polygon. The initial orientation is facing east.
                    let triangle: Polygon = &s.get_shape(UNIT_SIZE);

                    // Create a border on the front of the polygon. This is a trapezoid.
                    // Because the angle of the trapezoid side is 22.5°, we know that `dx` is always `2 * dy`.
                    let front: Polygon = &[
                        [UNIT_SIZE, UNIT_SIZE],                                           // Top right
                        [UNIT_SIZE, 0.0],                                                 // Bottom right
                        [UNIT_SIZE - FRONT_THICKNESS, FRONT_THICKNESS / 2.0],             // Bottom left
                        [UNIT_SIZE - FRONT_THICKNESS, UNIT_SIZE - FRONT_THICKNESS / 2.0], // Top left
                    ];

                    // Rotate the front to match the unit
                    let transform_front = transform.trans(s.position[0], s.position[1])
                        .rot_rad(s.angle)
                        .trans(-0.5 * UNIT_SIZE, -0.5 * UNIT_SIZE);

                    // We don't need to apply any transformation to the units
                    let transform_triangle = transform;

                    // Draw the unit ORANGE if selected
                    let selected = selected_units.iter().any(|id| id == &s.id);
                    if selected {
                        polygon(color.primary, triangle, transform_triangle, gl);
                        polygon(color.secondary, front, transform_front, gl);
                    } else {
                        polygon(color.secondary, triangle, transform_triangle, gl);
                        polygon(color.primary, front, transform_front, gl);
                    }

                }

                for b in player.bullets.iter() {
                    let transform = transform.trans(b.position[0], b.position[1]);
                    ellipse(color.primary, [0.0, 0.0, 1.0, 1.0], transform, gl);
                }
            }
        });
    }

    pub fn render(&mut self, args: &RenderArgs, cache: &mut GlyphCache) {
        match self.state {
            State::Menu => self.menu.render(args, &mut self.gl, cache),
            State::Running => self.render_game(args, cache),
            State::Error(ref msg) => msg.render(args, &mut self.gl, cache),
        }
    }

    pub fn update(&mut self, args: &UpdateArgs) {
        // grab updated server state if it is available
        let game_state_option = {
            let mut game_state_lock = self.game_state_server.lock().unwrap();
            mem::replace(&mut *game_state_lock, None)
        };
        if let Some(game_state) = game_state_option {
            self.game_state = game_state;
        } else {
            self.game_state.update(args.dt*1000.0);
        }
    }

    pub fn on_button_press(&mut self, button: &Button) -> bool {
        match self.state {
            State::Menu => {
                match button {
                    &Button::Keyboard(Key::Up) => {
                        self.menu.previous();
                    }
                    &Button::Keyboard(Key::Down) => {
                        self.menu.next();
                    }
                    &Button::Keyboard(Key::Return) => {
                        match self.menu.get_selected_entry() {
                            menu::Entries::Start => {
                                match self.start() {
                                    Ok(_) => {
                                        self.state = State::Running;
                                    }
                                    Err(err) => {
                                        self.state = State::Error(error::Message::new(err.description().into()));
                                    }
                                }
                            }
                            menu::Entries::Exit => {
                                return true;
                            }
                        }
                    }
                    _ => { }
                }
            }
            State::Running => {
                match button {
                    &Button::Keyboard(Key::Up) => {
                        self.scroll[1] += 10.0;
                    }
                    &Button::Keyboard(Key::Down) => {
                        self.scroll[1] -= 10.0;
                    }
                    &Button::Keyboard(Key::Left) => {
                        self.scroll[0] += 10.0;
                    }
                    &Button::Keyboard(Key::Right) => {
                        self.scroll[0] -= 10.0;
                    }
                    &Button::Keyboard(Key::F) => {
                        self.shoot_selected();
                    }
                    &Button::Keyboard(_) => { }
                    &Button::Mouse(button) => {
                        self.on_mouse_click(&button);
                    }
                    &Button::Controller(_) => { }
                }
            }
            State::Error(_) => {
                match button {
                    &Button::Keyboard(_) => { self.state = State::Menu; }
                    _ => { }
                }
            }
        };
        false
    }

    pub fn on_mouse_click(&mut self, button: &MouseButton) {
        let cursor = [
            self.cursor[0] / self.zoom - self.scroll[0],
            self.cursor[1] / self.zoom - self.scroll[1],
        ];
        match *button {
            MouseButton::Left  => self.select(cursor),
            MouseButton::Right => self.move_selected(cursor),
            _ => println!("Pressed mouse button '{:?}'", button),
        }
    }

    pub fn on_mouse_move(&mut self, cursor: [f64; 2]) {
        self.cursor = cursor;
    }

    pub fn on_mouse_scroll(&mut self, scroll: [f64; 2]) {
        if scroll[1] > 0.0 {
            self.zoom *= 1.5 * scroll[1];
        } else {
            self.zoom /= 1.5 * -scroll[1];
        }
        println!("zoom: {}", self.zoom);
    }

    pub fn move_selected(&mut self, position: [f64;2]) {
        for u in self.selected_units.iter() {
            let mut commands = self.commands.lock().unwrap();
            commands.push_back(Command::Move(*u, position));
        }
    }

    pub fn shoot_selected(&mut self) {
        for u in self.selected_units.iter() {
            let mut commands = self.commands.lock().unwrap();
            commands.push_back(Command::Shoot(*u));
        }
    }
}
<|endoftext|>


<commit_before>use hash_map::HashMap;
use core::hash;
use core::cmp;

pub type DispatchFn<T> = fn(&T) -> bool;

pub struct DispatchTable<T: cmp::Eq + hash::Hash> {
    table: HashMap<T, DispatchFn<T>>,
}

impl<T: cmp::Eq + hash::Hash> DispatchTable<T> {
    pub fn new() -> Self {
        DispatchTable { table: HashMap::new(16) }
    }

    pub fn dispatch(&mut self, event: &T) -> bool {
        match self.table.get(event) {
            Some(func) => func(event),
            None => false,
        }
    }

    pub fn register(&mut self, event: T, func: DispatchFn<T>) {
        self.table.insert(event, func);
    }

    pub fn unregister(&mut self, event: T) {
        self.table.remove(event);
    }
}

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

    #[derive(Hash, Eq, PartialEq, Debug)]
    enum Event {
        VMExit,
        PageFault,
    }

    fn on_vmexit(_: &Event) -> bool {
        true
    }

    #[test]
    fn test_dispatch_table_register() {
        let mut dt = DispatchTable::<Event>::new();
        dt.register(Event::VMExit, on_vmexit);
        assert!(dt.dispatch(&Event::VMExit));
        assert!(!dt.dispatch(&Event::PageFault));
    }

    #[test]
    fn test_dispatch_table_unregister() {
        let mut dt = DispatchTable::<Event>::new();
        dt.register(Event::VMExit, on_vmexit);
        assert!(dt.dispatch(&Event::VMExit));
        assert!(!dt.dispatch(&Event::PageFault));
        dt.unregister(Event::VMExit);
        assert!(!dt.dispatch(&Event::VMExit));
    }

}
<commit_msg>Dispatch table takes initial size<commit_after>use hash_map::HashMap;
use core::hash;
use core::cmp;

pub type DispatchFn<T> = fn(&T) -> bool;

pub struct DispatchTable<T: cmp::Eq + hash::Hash> {
    table: HashMap<T, DispatchFn<T>>,
}

impl<T: cmp::Eq + hash::Hash> DispatchTable<T> {
    pub fn new(size: usize) -> Self {
        DispatchTable { table: HashMap::new(size) }
    }

    pub fn dispatch(&mut self, event: &T) -> bool {
        match self.table.get(event) {
            Some(func) => func(event),
            None => false,
        }
    }

    pub fn register(&mut self, event: T, func: DispatchFn<T>) {
        self.table.insert(event, func);
    }

    pub fn unregister(&mut self, event: T) {
        self.table.remove(event);
    }
}

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

    #[derive(Hash, Eq, PartialEq, Debug)]
    enum Event {
        VMExit,
        PageFault,
    }

    fn on_vmexit(_: &Event) -> bool {
        true
    }

    #[test]
    fn test_dispatch_table_register() {
        let mut dt = DispatchTable::<Event>::new(16);
        dt.register(Event::VMExit, on_vmexit);
        assert!(dt.dispatch(&Event::VMExit));
        assert!(!dt.dispatch(&Event::PageFault));
    }

    #[test]
    fn test_dispatch_table_unregister() {
        let mut dt = DispatchTable::<Event>::new(16);
        dt.register(Event::VMExit, on_vmexit);
        assert!(dt.dispatch(&Event::VMExit));
        assert!(!dt.dispatch(&Event::PageFault));
        dt.unregister(Event::VMExit);
        assert!(!dt.dispatch(&Event::VMExit));
    }

}
<|endoftext|>


<commit_before>use super::super::commands::CommandResult;
use super::super::{LayoutTree, TreeError};
use super::super::core::Direction;
use super::super::core::container::{Container, ContainerType, Handle, Layout};

use petgraph::graph::NodeIndex;
use rustwlc::WlcView;
use uuid::Uuid;

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum FocusError {
    /// Reached a container where we can keep climbing the tree no longer.
    ///
    /// Usually this is a workspace, because it doesn't make sense to move a
    /// container out of a workspace
    ReachedLimit(NodeIndex),
    /// Tried to focus on a container that was not a view.
    NotAView(Uuid),
    /// Tried to focus on a container (first one),
    /// but that container was superseded by a fullscreen container (second one)
    BlockedByFullscreen(Uuid, Uuid)
}

impl LayoutTree {
    /// Focuses on the container by the uuid, if it points to a View.
    /// Otherwise, an error is returned.
    pub fn focus_on(&mut self, uuid: Uuid) -> CommandResult {
        let container = try!(self.lookup(uuid));
        match *container {
            Container::View { handle, .. } => {
                handle.focus();
                Ok(())
            },
            _ => Err(TreeError::Focus(FocusError::NotAView(uuid)))
        }
    }
    /// Focus on the container relative to the active container.
    ///
    /// If Horizontal, left and right will move within siblings.
    /// If Vertical, up and down will move within siblings.
    /// Other wise, it moves to the next sibling of the parent container.
    ///
    /// If the edge of the children is hit, it does not wrap around,
    /// but moves between ancestor siblings.
    pub fn move_focus(&mut self, direction: Direction) -> CommandResult {
        if let Some(prev_active_ix) = self.active_container {
            let new_active_ix = self.move_focus_recurse(prev_active_ix, direction)
                .unwrap_or(prev_active_ix);
            try!(self.set_active_node(new_active_ix));
            match self.tree[self.active_container.unwrap()] {
                Container::View { ref handle, .. } => handle.focus(),
                _ => warn!("move_focus returned a non-view, cannot focus")
            }
        } else {
            return Err(TreeError::NoActiveContainer)
        }
        self.validate();
        Ok(())
    }

    fn move_focus_recurse(&mut self, node_ix: NodeIndex, direction: Direction) -> Result<NodeIndex, TreeError> {
        match self.tree[node_ix].get_type() {
            ContainerType::View | ContainerType::Container => { /* continue */ },
            _ => return Err(TreeError::UuidWrongType(self.tree[node_ix].get_id(),
                                                     vec!(ContainerType::View, ContainerType::Container)))
        }
        let parent_ix = self.tree.parent_of(node_ix)
            .expect("Active ix had no parent");
        match self.tree[parent_ix] {
            Container::Container { layout, .. } => {
                match (layout, direction) {
                    (Layout::Horizontal, Direction::Left) |
                    (Layout::Horizontal, Direction::Right) |
                    (Layout::Vertical, Direction::Up) |
                    (Layout::Vertical, Direction::Down) => {
                        let siblings = self.tree.children_of(parent_ix);
                        let cur_index = siblings.iter().position(|node| {
                            *node == node_ix
                        }).expect("Could not find self in parent");
                        let maybe_new_index = match direction {
                            Direction::Right | Direction::Down => {
                                cur_index.checked_add(1)
                            }
                            Direction::Left  | Direction::Up => {
                                cur_index.checked_sub(1)
                            }
                        };
                        if maybe_new_index.is_some() &&
                            maybe_new_index.unwrap() < siblings.len() {
                                // There is a sibling to move to.
                                let new_index = maybe_new_index.unwrap();
                                let new_active_ix = siblings[new_index];
                                match self.tree[new_active_ix].get_type() {
                                    ContainerType::Container => {
                                        let path_ix = self.tree.follow_path(new_active_ix);
                                        // If the path wasn't complete, find the first view and focus on that
                                        let node_ix = try!(self.tree.descendant_of_type(path_ix, ContainerType::View)
                                                           .map_err(|err| TreeError::PetGraph(err)));
                                        let parent_ix = try!(self.tree.parent_of(node_ix)
                                                             .map_err(|err| TreeError::PetGraph(err)));
                                        match self.tree[node_ix].get_type() {
                                            ContainerType::View | ContainerType::Container => {},
                                            _ => panic!("Following path did not lead to a container or a view!")
                                        }
                                        trace!("Moving to different view {:?} in container {:?}",
                                                self.tree[node_ix], self.tree[parent_ix]);
                                        return Ok(node_ix);
                                    },
                                    ContainerType::View => {
                                        trace!("Moving to other view {:?}", self.tree[new_active_ix]);
                                        return Ok(new_active_ix)
                                    },
                                    _ => unreachable!()
                                };
                            }
                    },
                    _ => { /* We are moving out of siblings, recurse */ }
                }
            }
            Container::Workspace { .. } => {
                return Err(TreeError::Focus(FocusError::ReachedLimit(parent_ix)));
            }
            _ => unreachable!()
        }
        let parent_ix = self.tree.parent_of(node_ix)
            .expect("Node had no parent");
        return self.move_focus_recurse(parent_ix, direction);
    }

    /// Updates the current active container to be the next container or view
    /// to focus on after the previous view/container was moved/removed.
    ///
    /// A new view will tried to be set, starting with the children of the
    /// parent node. If a view cannot be found there, it starts climbing the
    /// tree until either a view is found or the workspace is (in which case
    /// it set the active container to the root container of the workspace)
    pub fn focus_on_next_container(&mut self, mut parent_ix: NodeIndex) {
        let last_ix = self.tree.active_path().last()
            .expect("Active path did not lead anywhere").0;
        match self.tree[last_ix] {
            Container::View { handle, .. } => {
                handle.focus();
                self.active_container = Some(last_ix);
                return
            },
            Container::Container { .. } => {
                parent_ix = last_ix;
            },
            _ => {}
        }
        while self.tree.node_type(parent_ix)
            .expect("Node not part of the tree") != ContainerType::Workspace {
                if let Ok(view_ix) = self.tree.descendant_of_type(parent_ix,
                                                                  ContainerType::View) {
                match self.tree[view_ix]
                                    .get_handle().expect("view had no handle") {
                    Handle::View(view) => view.focus(),
                    _ => panic!("View had an output handle")
                }
                trace!("Active container set to view at {:?}", view_ix);
                let id = self.tree[view_ix].get_id();
                self.set_active_container(id)
                    .expect("Could not set active container");
                return;
            }
            parent_ix = self.tree.ancestor_of_type(parent_ix,
                                                    ContainerType::Container)
                .unwrap_or_else(|_| {
                    self.tree.ancestor_of_type(parent_ix, ContainerType::Workspace)
                        .expect("Container was not part of a workspace")
                });
        }
        // If this is reached, parent is workspace
        let container_ix = self.tree.children_of(parent_ix)[0];
        let root_c_children = self.tree.grounded_children(container_ix);
        if root_c_children.len() > 0 {
            // Only searches first child of root container, can't be floating view.
            let new_active_ix = self.tree.descendant_of_type(root_c_children[0],
                                                                ContainerType::View)
                .unwrap_or(root_c_children[0]);
            let id = self.tree[new_active_ix].get_id();
            self.set_active_container(id)
                .expect("Could not set active container");
            match self.tree[new_active_ix] {
                Container::View { ref handle, .. } => {
                    info!("Focusing on {:?}", handle);
                    handle.focus();
                },
                Container::Container { .. } => {
                    info!("No view found, focusing on nothing in workspace {:?}", parent_ix);
                    WlcView::root().focus();
                }
                _ => unreachable!()
            };
            return;
        } else {
            let floating_children = self.tree.floating_children(container_ix);
            for child_ix in floating_children {
                if let Ok(view_ix) = self.tree.descendant_of_type(child_ix,
                                                                    ContainerType::View) {
                    match self.tree[view_ix] {
                        Container::View { handle, id, .. } => {
                            info!("Floating view found, focusing on {:#?}", handle);
                            handle.focus();
                            self.set_active_container(id)
                                .expect("Could not set active container");
                            return;
                        },
                        _ => unreachable!()
                    };
                }
            }
        }
        trace!("Active container set to container {:?}", container_ix);
        let id = self.tree[container_ix].get_id();
        self.set_active_container(id)
            .expect("Could not set active container");

        // Update focus to new container
        self.get_active_container().map(|con| match *con {
            Container::View { ref handle, .. } => handle.focus(),
            Container::Container { .. } => WlcView::root().focus(),
            _ => panic!("Active container not view or container!")
        });
    }

    /// If the currently focused view is floating, then the non-floating at the end of
    /// the path becomes the focused view. Otherwise, the first floating view becomes
    /// the focused view.
    ///
    /// If there is no currently focused view, does nothing.
    pub fn toggle_floating_focus(&mut self) -> CommandResult {
        let active_ix = try!(self.active_container.ok_or(TreeError::NoActiveContainer));
        if self.tree[active_ix].floating() {
            let root_ix = self.tree.root_ix();
            let new_ix = self.tree.follow_path(root_ix);
            match self.tree[new_ix].get_type() {
                ContainerType::View | ContainerType::Container  => {
                    try!(self.set_active_node(new_ix));
                    Ok(())
                },
                type_ => {
                    error!("Path lead to the wrong container, {:#?}\n{:#?}\n{:#?}",
                           active_ix, type_, self);
                    panic!("toggle_floating_focused: bad path");
                }
            }
        } else {
            // Current view is not floating, gotta focus on floating view
            let root_c_ix = self.root_container_ix()
                .expect("No root container ancestor of active container");
            let floating_children = self.tree.floating_children(root_c_ix);
            if floating_children.len() > 0 {
                try!(self.set_active_node(floating_children[0]));
            }
            Ok(())
        }
    }

    /// Normalizes the geometry of a view to be the same size as it's siblings,
    /// based on the parent container's layout, at the 0 point of the parent container.
    /// Note this does not auto-tile, only modifies this one view.
    ///
    /// Useful if a container's children want to be evenly distributed, or a new view
    /// is being added.
    pub fn normalize_view(&mut self, view: WlcView) {
        if let Some(view_ix) = self.tree.descendant_with_handle(self.tree.root_ix(), &view) {
            self.normalize_container(view_ix);
        }
    }
}
<commit_msg>Added fullscreen checks to focus actions<commit_after>use super::super::commands::CommandResult;
use super::super::{LayoutTree, TreeError};
use super::super::core::Direction;
use super::super::core::container::{Container, ContainerType, Handle, Layout};

use petgraph::graph::NodeIndex;
use rustwlc::WlcView;
use uuid::Uuid;

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum FocusError {
    /// Reached a container where we can keep climbing the tree no longer.
    ///
    /// Usually this is a workspace, because it doesn't make sense to move a
    /// container out of a workspace
    ReachedLimit(NodeIndex),
    /// Tried to focus on a container that was not a view.
    NotAView(Uuid),
    /// Tried to focus on a container (first one),
    /// but that container was superseded by a fullscreen container (second one)
    BlockedByFullscreen(Uuid, Uuid)
}

impl LayoutTree {
    /// Focuses on the container by the uuid, if it points to a View.
    /// Otherwise, an error is returned.
    pub fn focus_on(&mut self, uuid: Uuid) -> CommandResult {
        if let Some(fullscreen_id) = try!(self.in_fullscreen_workspace(uuid)) {
            return Err(TreeError::Focus(FocusError::BlockedByFullscreen(uuid, fullscreen_id)))
        }
        let container = try!(self.lookup(uuid));
        match *container {
            Container::View { handle, .. } => {
                handle.focus();
                Ok(())
            },
            _ => Err(TreeError::Focus(FocusError::NotAView(uuid)))
        }
    }
    /// Focus on the container relative to the active container.
    ///
    /// If Horizontal, left and right will move within siblings.
    /// If Vertical, up and down will move within siblings.
    /// Other wise, it moves to the next sibling of the parent container.
    ///
    /// If the edge of the children is hit, it does not wrap around,
    /// but moves between ancestor siblings.
    pub fn move_focus(&mut self, direction: Direction) -> CommandResult {
        if let Some(prev_active_ix) = self.active_container {
            let active_id = self.tree[prev_active_ix].get_id();
            if let Some(fullscreen_id) = try!(self.in_fullscreen_workspace(active_id)) {
                return Err(TreeError::Focus(
                    FocusError::BlockedByFullscreen(active_id, fullscreen_id)))
            }
            let new_active_ix = self.move_focus_recurse(prev_active_ix, direction)
                .unwrap_or(prev_active_ix);
            try!(self.set_active_node(new_active_ix));
            match self.tree[self.active_container.unwrap()] {
                Container::View { ref handle, .. } => handle.focus(),
                _ => warn!("move_focus returned a non-view, cannot focus")
            }
        } else {
            return Err(TreeError::NoActiveContainer)
        }
        self.validate();
        Ok(())
    }

    fn move_focus_recurse(&mut self, node_ix: NodeIndex, direction: Direction)
                          -> Result<NodeIndex, TreeError> {
        match self.tree[node_ix].get_type() {
            ContainerType::View | ContainerType::Container => { /* continue */ },
            _ => return Err(TreeError::UuidWrongType(self.tree[node_ix].get_id(),
                                                     vec!(ContainerType::View, ContainerType::Container)))
        }
        let parent_ix = self.tree.parent_of(node_ix)
            .expect("Active ix had no parent");
        match self.tree[parent_ix] {
            Container::Container { layout, .. } => {
                match (layout, direction) {
                    (Layout::Horizontal, Direction::Left) |
                    (Layout::Horizontal, Direction::Right) |
                    (Layout::Vertical, Direction::Up) |
                    (Layout::Vertical, Direction::Down) => {
                        let siblings = self.tree.children_of(parent_ix);
                        let cur_index = siblings.iter().position(|node| {
                            *node == node_ix
                        }).expect("Could not find self in parent");
                        let maybe_new_index = match direction {
                            Direction::Right | Direction::Down => {
                                cur_index.checked_add(1)
                            }
                            Direction::Left  | Direction::Up => {
                                cur_index.checked_sub(1)
                            }
                        };
                        if maybe_new_index.is_some() &&
                            maybe_new_index.unwrap() < siblings.len() {
                                // There is a sibling to move to.
                                let new_index = maybe_new_index.unwrap();
                                let new_active_ix = siblings[new_index];
                                match self.tree[new_active_ix].get_type() {
                                    ContainerType::Container => {
                                        let path_ix = self.tree.follow_path(new_active_ix);
                                        // If the path wasn't complete, find the first view and focus on that
                                        let node_ix = try!(self.tree.descendant_of_type(path_ix, ContainerType::View)
                                                           .map_err(|err| TreeError::PetGraph(err)));
                                        let parent_ix = try!(self.tree.parent_of(node_ix)
                                                             .map_err(|err| TreeError::PetGraph(err)));
                                        match self.tree[node_ix].get_type() {
                                            ContainerType::View | ContainerType::Container => {},
                                            _ => panic!("Following path did not lead to a container or a view!")
                                        }
                                        trace!("Moving to different view {:?} in container {:?}",
                                                self.tree[node_ix], self.tree[parent_ix]);
                                        return Ok(node_ix);
                                    },
                                    ContainerType::View => {
                                        trace!("Moving to other view {:?}", self.tree[new_active_ix]);
                                        return Ok(new_active_ix)
                                    },
                                    _ => unreachable!()
                                };
                            }
                    },
                    _ => { /* We are moving out of siblings, recurse */ }
                }
            }
            Container::Workspace { .. } => {
                return Err(TreeError::Focus(FocusError::ReachedLimit(parent_ix)));
            }
            _ => unreachable!()
        }
        let parent_ix = self.tree.parent_of(node_ix)
            .expect("Node had no parent");
        return self.move_focus_recurse(parent_ix, direction);
    }

    /// Updates the current active container to be the next container or view
    /// to focus on after the previous view/container was moved/removed.
    ///
    /// A new view will tried to be set, starting with the children of the
    /// parent node. If a view cannot be found there, it starts climbing the
    /// tree until either a view is found or the workspace is (in which case
    /// it set the active container to the root container of the workspace)
    ///
    /// If there is a fullscreen container in this workspace, that is focused on next,
    /// with the active path updated accordingly.
    pub fn focus_on_next_container(&mut self, mut parent_ix: NodeIndex) {
        let last_ix = self.tree.active_path().last()
            .expect("Active path did not lead anywhere").0;
        let id = self.tree[last_ix].get_id();
        // TODO error handling!!!
        match self.in_fullscreen_workspace(id).unwrap() {
            Some(fullscreen_id) => {
                self.set_active_container(fullscreen_id).unwrap();
                return;
            },
            _ => {}
        }
        // TODO Change this algorithm when we improve the pathing system
        match self.tree[last_ix] {
            Container::View { handle, .. } => {
                handle.focus();
                self.active_container = Some(last_ix);
                return
            },
            Container::Container { .. } => {
                parent_ix = last_ix;
            },
            _ => {}
        }
        while self.tree.node_type(parent_ix)
            .expect("Node not part of the tree") != ContainerType::Workspace {
                if let Ok(view_ix) = self.tree.descendant_of_type(parent_ix,
                                                                  ContainerType::View) {
                match self.tree[view_ix]
                                    .get_handle().expect("view had no handle") {
                    Handle::View(view) => view.focus(),
                    _ => panic!("View had an output handle")
                }
                trace!("Active container set to view at {:?}", view_ix);
                let id = self.tree[view_ix].get_id();
                self.set_active_container(id)
                    .expect("Could not set active container");
                return;
            }
            parent_ix = self.tree.ancestor_of_type(parent_ix,
                                                    ContainerType::Container)
                .unwrap_or_else(|_| {
                    self.tree.ancestor_of_type(parent_ix, ContainerType::Workspace)
                        .expect("Container was not part of a workspace")
                });
        }
        // If this is reached, parent is workspace
        let container_ix = self.tree.children_of(parent_ix)[0];
        let root_c_children = self.tree.grounded_children(container_ix);
        if root_c_children.len() > 0 {
            // Only searches first child of root container, can't be floating view.
            let new_active_ix = self.tree.descendant_of_type(root_c_children[0],
                                                                ContainerType::View)
                .unwrap_or(root_c_children[0]);
            let id = self.tree[new_active_ix].get_id();
            self.set_active_container(id)
                .expect("Could not set active container");
            match self.tree[new_active_ix] {
                Container::View { ref handle, .. } => {
                    info!("Focusing on {:?}", handle);
                    handle.focus();
                },
                Container::Container { .. } => {
                    info!("No view found, focusing on nothing in workspace {:?}", parent_ix);
                    WlcView::root().focus();
                }
                _ => unreachable!()
            };
            return;
        } else {
            let floating_children = self.tree.floating_children(container_ix);
            for child_ix in floating_children {
                if let Ok(view_ix) = self.tree.descendant_of_type(child_ix,
                                                                    ContainerType::View) {
                    match self.tree[view_ix] {
                        Container::View { handle, id, .. } => {
                            info!("Floating view found, focusing on {:#?}", handle);
                            handle.focus();
                            self.set_active_container(id)
                                .expect("Could not set active container");
                            return;
                        },
                        _ => unreachable!()
                    };
                }
            }
        }
        trace!("Active container set to container {:?}", container_ix);
        let id = self.tree[container_ix].get_id();
        self.set_active_container(id)
            .expect("Could not set active container");

        // Update focus to new container
        self.get_active_container().map(|con| match *con {
            Container::View { ref handle, .. } => handle.focus(),
            Container::Container { .. } => WlcView::root().focus(),
            _ => panic!("Active container not view or container!")
        });
    }

    /// If the currently focused view is floating, then the non-floating at the end of
    /// the path becomes the focused view. Otherwise, the first floating view becomes
    /// the focused view.
    ///
    /// If there is no currently focused view, does nothing.
    pub fn toggle_floating_focus(&mut self) -> CommandResult {
        let active_ix = try!(self.active_container.ok_or(TreeError::NoActiveContainer));
        let id; let floating;
        {
            let container = &self.tree[active_ix];
            id = container.get_id();
            floating = container.floating();
        }
        if let Some(fullscreen_id) = try!(self.in_fullscreen_workspace(id)) {
            return Err(TreeError::Focus(FocusError::BlockedByFullscreen(id, fullscreen_id)))
        }
        if floating {
            let root_ix = self.tree.root_ix();
            let new_ix = self.tree.follow_path(root_ix);
            match self.tree[new_ix].get_type() {
                ContainerType::View | ContainerType::Container  => {
                    try!(self.set_active_node(new_ix));
                    Ok(())
                },
                type_ => {
                    error!("Path lead to the wrong container, {:#?}\n{:#?}\n{:#?}",
                           active_ix, type_, self);
                    panic!("toggle_floating_focused: bad path");
                }
            }
        } else {
            // Current view is not floating, gotta focus on floating view
            let root_c_ix = self.root_container_ix()
                .expect("No root container ancestor of active container");
            let floating_children = self.tree.floating_children(root_c_ix);
            if floating_children.len() > 0 {
                try!(self.set_active_node(floating_children[0]));
            }
            Ok(())
        }
    }

    /// Normalizes the geometry of a view to be the same size as it's siblings,
    /// based on the parent container's layout, at the 0 point of the parent container.
    /// Note this does not auto-tile, only modifies this one view.
    ///
    /// Useful if a container's children want to be evenly distributed, or a new view
    /// is being added.
    pub fn normalize_view(&mut self, view: WlcView) {
        if let Some(view_ix) = self.tree.descendant_with_handle(self.tree.root_ix(), &view) {
            self.normalize_container(view_ix);
        }
    }
}
<|endoftext|>


<commit_before>use std::net::{
    IpAddr,
    Ipv4Addr,
    Ipv6Addr,
    SocketAddr,
};
use c_ares;
use futures;
use futures::Future;

use error::Error;
use host::HostResults;
use nameinfo::NameInfoResult;
use resolver::{
    Options,
    Resolver,
};

/// The type of future returned by methods on the `FutureResolver`.
pub struct CAresFuture<T> {
    inner: futures::sync::oneshot::Receiver<Result<T, c_ares::Error>>,
}

impl<T> CAresFuture<T> {
    fn new(p: futures::sync::oneshot::Receiver<Result<T, c_ares::Error>>)
        -> Self {
        CAresFuture {
            inner: p,
        }
    }
}

impl<T> Future for CAresFuture<T> {
    type Item = T;
    type Error = c_ares::Error;

    fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
        match self.inner.poll() {
            Ok(futures::Async::NotReady) => Ok(futures::Async::NotReady),
            Err(_) => Err(c_ares::Error::ECANCELLED),
            Ok(futures::Async::Ready(res)) => {
                match res {
                    Ok(r) => Ok(futures::Async::Ready(r)),
                    Err(e) => Err(e),
                }
            }
        }
    }
}

/// An asynchronous DNS resolver, which returns results as
/// `futures::Future`s.
pub struct FutureResolver {
    inner: Resolver,
}

// Most query implementations follow the same pattern: call through to the
// `Resolver`, arranging that the callback completes a future.
macro_rules! futurize {
    ($resolver:expr, $query:ident, $question:expr) => {
        {
            let (c, p) = futures::oneshot();
            $resolver.$query($question, move |result| {
                let _ = c.send(result);
            });
            CAresFuture::new(p)
        }
    }
}

impl FutureResolver {
    /// Create a new `FutureResolver`, using default `Options`.
    pub fn new() -> Result<FutureResolver, Error> {
        let options = Options::default();
        Self::with_options(options)
    }

    /// Create a new `FutureResolver`, with the given `Options`.
    pub fn with_options(options: Options) -> Result<FutureResolver, Error> {
        let inner = Resolver::with_options(options)?;
        let resolver = FutureResolver {
            inner: inner,
        };
        Ok(resolver)
    }

    /// Set the list of servers to contact, instead of the servers specified
    /// in resolv.conf or the local named.
    ///
    /// String format is `host[:port]`.  IPv6 addresses with ports require
    /// square brackets eg `[2001:4860:4860::8888]:53`.
    pub fn set_servers(
        &self,
        servers: &[&str]) -> Result<&Self, c_ares::Error> {
        self.inner.set_servers(servers)?;
        Ok(self)
    }

    /// Set the local IPv4 address from which to make queries.
    pub fn set_local_ipv4(&self, ipv4: &Ipv4Addr) -> &Self {
        self.inner.set_local_ipv4(ipv4);
        self
    }

    /// Set the local IPv6 address from which to make queries.
    pub fn set_local_ipv6(&self, ipv6: &Ipv6Addr) -> &Self {
        self.inner.set_local_ipv6(ipv6);
        self
    }

    /// Set the local device from which to make queries.
    pub fn set_local_device(&self, device: &str) -> &Self {
        self.inner.set_local_device(device);
        self
    }

    /// Look up the A records associated with `name`.
    pub fn query_a(&self, name: &str) -> CAresFuture<c_ares::AResults> {
        futurize!(self.inner, query_a, name)
    }

    /// Search for the A records associated with `name`.
    pub fn search_a(&self, name: &str) -> CAresFuture<c_ares::AResults> {
        futurize!(self.inner, search_a, name)
    }

    /// Look up the AAAA records associated with `name`.
    pub fn query_aaaa(&self, name: &str)  -> CAresFuture<c_ares::AAAAResults> {
        futurize!(self.inner, query_aaaa, name)
    }

    /// Search for the AAAA records associated with `name`.
    pub fn search_aaaa(&self, name: &str) -> CAresFuture<c_ares::AAAAResults> {
        futurize!(self.inner, search_aaaa, name)
    }

    /// Look up the CNAME records associated with `name`.
    pub fn query_cname(&self, name: &str)
        -> CAresFuture<c_ares::CNameResults> {
        futurize!(self.inner, query_cname, name)
    }

    /// Search for the CNAME records associated with `name`.
    pub fn search_cname(&self, name: &str)
        -> CAresFuture<c_ares::CNameResults> {
        futurize!(self.inner, search_cname, name)
    }

    /// Look up the MX records associated with `name`.
    pub fn query_mx(&self, name: &str) -> CAresFuture<c_ares::MXResults> {
        futurize!(self.inner, query_mx, name)
    }

    /// Search for the MX records associated with `name`.
    pub fn search_mx(&self, name: &str) -> CAresFuture<c_ares::MXResults> {
        futurize!(self.inner, search_mx, name)
    }

    /// Look up the NAPTR records associated with `name`.
    pub fn query_naptr(&self, name: &str)
        -> CAresFuture<c_ares::NAPTRResults> {
        futurize!(self.inner, query_naptr, name)
    }

    /// Search for the NAPTR records associated with `name`.
    pub fn search_naptr(&self, name: &str)
        -> CAresFuture<c_ares::NAPTRResults> {
        futurize!(self.inner, search_naptr, name)
    }

    /// Look up the NS records associated with `name`.
    pub fn query_ns(&self, name: &str) -> CAresFuture<c_ares::NSResults> {
        futurize!(self.inner, query_ns, name)
    }

    /// Search for the NS records associated with `name`.
    pub fn search_ns(&self, name: &str) -> CAresFuture<c_ares::NSResults> {
        futurize!(self.inner, search_ns, name)
    }

    /// Look up the PTR records associated with `name`.
    pub fn query_ptr(&self, name: &str) -> CAresFuture<c_ares::PTRResults> {
        futurize!(self.inner, query_ptr, name)
    }

    /// Search for the PTR records associated with `name`.
    pub fn search_ptr(&self, name: &str) -> CAresFuture<c_ares::PTRResults> {
        futurize!(self.inner, search_ptr, name)
    }

    /// Look up the SOA records associated with `name`.
    pub fn query_soa(&self, name: &str) -> CAresFuture<c_ares::SOAResult> {
        futurize!(self.inner, query_soa, name)
    }

    /// Search for the SOA records associated with `name`.
    pub fn search_soa(&self, name: &str) -> CAresFuture<c_ares::SOAResult> {
        futurize!(self.inner, search_soa, name)
    }

    /// Look up the SRV records associated with `name`.
    pub fn query_srv(&self, name: &str) -> CAresFuture<c_ares::SRVResults> {
        futurize!(self.inner, query_srv, name)
    }

    /// Search for the SRV records associated with `name`.
    pub fn search_srv(&self, name: &str) -> CAresFuture<c_ares::SRVResults> {
        futurize!(self.inner, search_srv, name)
    }

    /// Look up the TXT records associated with `name`.
    pub fn query_txt(&self, name: &str) -> CAresFuture<c_ares::TXTResults> {
        futurize!(self.inner, query_txt, name)
    }

    /// Search for the TXT records associated with `name`.
    pub fn search_txt(&self, name: &str) -> CAresFuture<c_ares::TXTResults> {
        futurize!(self.inner, search_txt, name)
    }

    /// Perform a host query by address.
    ///
    /// This method is one of the very few places where this library performs
    /// strictly more allocation than the underlying `c-ares` code.  If this is
    /// a problem for you, you should prefer to use the analogous method on the
    /// `Resolver`.
    pub fn get_host_by_address(&self, address: &IpAddr)
        -> CAresFuture<HostResults> {
        let (c, p) = futures::oneshot();
        self.inner.get_host_by_address(address, move |result| {
            let _ = c.send(result.map(|h| h.into()));
        });
        CAresFuture::new(p)
    }

    /// Perform a host query by name.
    ///
    /// This method is one of the very few places where this library performs
    /// strictly more allocation than the underlying `c-ares` code.  If this is
    /// a problem for you, you should prefer to use the analogous method on the
    /// `Resolver`.
    pub fn get_host_by_name(&self, name: &str, family: c_ares::AddressFamily)
        -> CAresFuture<HostResults> {
        let (c, p) = futures::oneshot();
        self.inner.get_host_by_name(name, family, move |result| {
            let _ = c.send(result.map(|h| h.into()));
        });
        CAresFuture::new(p)
    }

    /// Address-to-nodename translation in protocol-independent manner.
    ///
    /// This method is one of the very few places where this library performs
    /// strictly more allocation than the underlying `c-ares` code.  If this is
    /// a problem for you, you should prefer to use the analogous method on the
    /// `Resolver`.
    pub fn get_name_info<F>(
        &self,
        address: &SocketAddr,
        flags: c_ares::NIFlags)
        -> CAresFuture<NameInfoResult> {
        let (c, p) = futures::oneshot();
        self.inner.get_name_info(address, flags, move |result| {
            let _ = c.send(result.map(|n| n.into()));
        });
        CAresFuture::new(p)
    }

    /// Initiate a single-question DNS query for `name`.  The class and type of
    /// the query are per the provided parameters, taking values as defined in
    /// `arpa/nameser.h`.
    ///
    /// This method is one of the very few places where this library performs
    /// strictly more allocation than the underlying `c-ares` code.  If this is
    /// a problem for you, you should prefer to use the analogous method on the
    /// `Resolver`.
    ///
    /// This method is provided so that users can query DNS types for which
    /// `c-ares` does not provide a parser; or in case a third-party parser is
    /// preferred.  Usually, if a suitable `query_xxx()` is available, that
    /// should be used.
    pub fn query(&self, name: &str, dns_class: u16, query_type: u16)
        -> CAresFuture<Vec<u8>> {
        let (c, p) = futures::oneshot();
        self.inner.query(name, dns_class, query_type, move |result| {
            let _ = c.send(result.map(|bs| bs.to_owned()));
        });
        CAresFuture::new(p)
    }

    /// Initiate a series of single-question DNS queries for `name`.  The
    /// class and type of the query are per the provided parameters, taking
    /// values as defined in `arpa/nameser.h`.
    ///
    /// This method is one of the very few places where this library performs
    /// strictly more allocation than the underlying `c-ares` code.  If this is
    /// a problem for you, you should prefer to use the analogous method on the
    /// `Resolver`.
    ///
    /// This method is provided so that users can search DNS types for which
    /// `c-ares` does not provide a parser; or in case a third-party parser is
    /// preferred.  Usually, if a suitable `search_xxx()` is available, that
    /// should be used.
    pub fn search(&self, name: &str, dns_class: u16, query_type: u16)
        -> CAresFuture<Vec<u8>> {
        let (c, p) = futures::oneshot();
        self.inner.search(name, dns_class, query_type, move |result| {
            let _ = c.send(result.map(|bs| bs.to_owned()));
        });
        CAresFuture::new(p)
    }

    /// Cancel all requests made on this `FutureResolver`.
    pub fn cancel(&self) {
        self.inner.cancel()
    }
}
<commit_msg>cosmetic<commit_after>use std::net::{
    IpAddr,
    Ipv4Addr,
    Ipv6Addr,
    SocketAddr,
};
use c_ares;
use futures;
use futures::Future;

use error::Error;
use host::HostResults;
use nameinfo::NameInfoResult;
use resolver::{
    Options,
    Resolver,
};

/// The type of future returned by methods on the `FutureResolver`.
pub struct CAresFuture<T> {
    inner: futures::sync::oneshot::Receiver<c_ares::Result<T>>,
}

impl<T> CAresFuture<T> {
    fn new(promise: futures::sync::oneshot::Receiver<c_ares::Result<T>>)
        -> Self
    {
        CAresFuture {
            inner: promise,
        }
    }
}

impl<T> Future for CAresFuture<T> {
    type Item = T;
    type Error = c_ares::Error;

    fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
        match self.inner.poll() {
            Ok(futures::Async::NotReady) => Ok(futures::Async::NotReady),
            Err(_) => Err(c_ares::Error::ECANCELLED),
            Ok(futures::Async::Ready(res)) => {
                match res {
                    Ok(r) => Ok(futures::Async::Ready(r)),
                    Err(e) => Err(e),
                }
            }
        }
    }
}

/// An asynchronous DNS resolver, which returns results as
/// `futures::Future`s.
pub struct FutureResolver {
    inner: Resolver,
}

// Most query implementations follow the same pattern: call through to the
// `Resolver`, arranging that the callback completes a future.
macro_rules! futurize {
    ($resolver:expr, $query:ident, $question:expr) => {
        {
            let (c, p) = futures::oneshot();
            $resolver.$query($question, move |result| {
                let _ = c.send(result);
            });
            CAresFuture::new(p)
        }
    }
}

impl FutureResolver {
    /// Create a new `FutureResolver`, using default `Options`.
    pub fn new() -> Result<FutureResolver, Error> {
        let options = Options::default();
        Self::with_options(options)
    }

    /// Create a new `FutureResolver`, with the given `Options`.
    pub fn with_options(options: Options) -> Result<FutureResolver, Error> {
        let inner = Resolver::with_options(options)?;
        let resolver = FutureResolver {
            inner: inner,
        };
        Ok(resolver)
    }

    /// Set the list of servers to contact, instead of the servers specified
    /// in resolv.conf or the local named.
    ///
    /// String format is `host[:port]`.  IPv6 addresses with ports require
    /// square brackets eg `[2001:4860:4860::8888]:53`.
    pub fn set_servers(
        &self,
        servers: &[&str]) -> Result<&Self, c_ares::Error> {
        self.inner.set_servers(servers)?;
        Ok(self)
    }

    /// Set the local IPv4 address from which to make queries.
    pub fn set_local_ipv4(&self, ipv4: &Ipv4Addr) -> &Self {
        self.inner.set_local_ipv4(ipv4);
        self
    }

    /// Set the local IPv6 address from which to make queries.
    pub fn set_local_ipv6(&self, ipv6: &Ipv6Addr) -> &Self {
        self.inner.set_local_ipv6(ipv6);
        self
    }

    /// Set the local device from which to make queries.
    pub fn set_local_device(&self, device: &str) -> &Self {
        self.inner.set_local_device(device);
        self
    }

    /// Look up the A records associated with `name`.
    pub fn query_a(&self, name: &str) -> CAresFuture<c_ares::AResults> {
        futurize!(self.inner, query_a, name)
    }

    /// Search for the A records associated with `name`.
    pub fn search_a(&self, name: &str) -> CAresFuture<c_ares::AResults> {
        futurize!(self.inner, search_a, name)
    }

    /// Look up the AAAA records associated with `name`.
    pub fn query_aaaa(&self, name: &str)  -> CAresFuture<c_ares::AAAAResults> {
        futurize!(self.inner, query_aaaa, name)
    }

    /// Search for the AAAA records associated with `name`.
    pub fn search_aaaa(&self, name: &str) -> CAresFuture<c_ares::AAAAResults> {
        futurize!(self.inner, search_aaaa, name)
    }

    /// Look up the CNAME records associated with `name`.
    pub fn query_cname(&self, name: &str)
        -> CAresFuture<c_ares::CNameResults> {
        futurize!(self.inner, query_cname, name)
    }

    /// Search for the CNAME records associated with `name`.
    pub fn search_cname(&self, name: &str)
        -> CAresFuture<c_ares::CNameResults> {
        futurize!(self.inner, search_cname, name)
    }

    /// Look up the MX records associated with `name`.
    pub fn query_mx(&self, name: &str) -> CAresFuture<c_ares::MXResults> {
        futurize!(self.inner, query_mx, name)
    }

    /// Search for the MX records associated with `name`.
    pub fn search_mx(&self, name: &str) -> CAresFuture<c_ares::MXResults> {
        futurize!(self.inner, search_mx, name)
    }

    /// Look up the NAPTR records associated with `name`.
    pub fn query_naptr(&self, name: &str)
        -> CAresFuture<c_ares::NAPTRResults> {
        futurize!(self.inner, query_naptr, name)
    }

    /// Search for the NAPTR records associated with `name`.
    pub fn search_naptr(&self, name: &str)
        -> CAresFuture<c_ares::NAPTRResults> {
        futurize!(self.inner, search_naptr, name)
    }

    /// Look up the NS records associated with `name`.
    pub fn query_ns(&self, name: &str) -> CAresFuture<c_ares::NSResults> {
        futurize!(self.inner, query_ns, name)
    }

    /// Search for the NS records associated with `name`.
    pub fn search_ns(&self, name: &str) -> CAresFuture<c_ares::NSResults> {
        futurize!(self.inner, search_ns, name)
    }

    /// Look up the PTR records associated with `name`.
    pub fn query_ptr(&self, name: &str) -> CAresFuture<c_ares::PTRResults> {
        futurize!(self.inner, query_ptr, name)
    }

    /// Search for the PTR records associated with `name`.
    pub fn search_ptr(&self, name: &str) -> CAresFuture<c_ares::PTRResults> {
        futurize!(self.inner, search_ptr, name)
    }

    /// Look up the SOA records associated with `name`.
    pub fn query_soa(&self, name: &str) -> CAresFuture<c_ares::SOAResult> {
        futurize!(self.inner, query_soa, name)
    }

    /// Search for the SOA records associated with `name`.
    pub fn search_soa(&self, name: &str) -> CAresFuture<c_ares::SOAResult> {
        futurize!(self.inner, search_soa, name)
    }

    /// Look up the SRV records associated with `name`.
    pub fn query_srv(&self, name: &str) -> CAresFuture<c_ares::SRVResults> {
        futurize!(self.inner, query_srv, name)
    }

    /// Search for the SRV records associated with `name`.
    pub fn search_srv(&self, name: &str) -> CAresFuture<c_ares::SRVResults> {
        futurize!(self.inner, search_srv, name)
    }

    /// Look up the TXT records associated with `name`.
    pub fn query_txt(&self, name: &str) -> CAresFuture<c_ares::TXTResults> {
        futurize!(self.inner, query_txt, name)
    }

    /// Search for the TXT records associated with `name`.
    pub fn search_txt(&self, name: &str) -> CAresFuture<c_ares::TXTResults> {
        futurize!(self.inner, search_txt, name)
    }

    /// Perform a host query by address.
    ///
    /// This method is one of the very few places where this library performs
    /// strictly more allocation than the underlying `c-ares` code.  If this is
    /// a problem for you, you should prefer to use the analogous method on the
    /// `Resolver`.
    pub fn get_host_by_address(&self, address: &IpAddr)
        -> CAresFuture<HostResults>
    {
        let (c, p) = futures::oneshot();
        self.inner.get_host_by_address(address, move |result| {
            let _ = c.send(result.map(|h| h.into()));
        });
        CAresFuture::new(p)
    }

    /// Perform a host query by name.
    ///
    /// This method is one of the very few places where this library performs
    /// strictly more allocation than the underlying `c-ares` code.  If this is
    /// a problem for you, you should prefer to use the analogous method on the
    /// `Resolver`.
    pub fn get_host_by_name(&self, name: &str, family: c_ares::AddressFamily)
        -> CAresFuture<HostResults>
    {
        let (c, p) = futures::oneshot();
        self.inner.get_host_by_name(name, family, move |result| {
            let _ = c.send(result.map(|h| h.into()));
        });
        CAresFuture::new(p)
    }

    /// Address-to-nodename translation in protocol-independent manner.
    ///
    /// This method is one of the very few places where this library performs
    /// strictly more allocation than the underlying `c-ares` code.  If this is
    /// a problem for you, you should prefer to use the analogous method on the
    /// `Resolver`.
    pub fn get_name_info<F>(
        &self,
        address: &SocketAddr,
        flags: c_ares::NIFlags)
        -> CAresFuture<NameInfoResult>
    {
        let (c, p) = futures::oneshot();
        self.inner.get_name_info(address, flags, move |result| {
            let _ = c.send(result.map(|n| n.into()));
        });
        CAresFuture::new(p)
    }

    /// Initiate a single-question DNS query for `name`.  The class and type of
    /// the query are per the provided parameters, taking values as defined in
    /// `arpa/nameser.h`.
    ///
    /// This method is one of the very few places where this library performs
    /// strictly more allocation than the underlying `c-ares` code.  If this is
    /// a problem for you, you should prefer to use the analogous method on the
    /// `Resolver`.
    ///
    /// This method is provided so that users can query DNS types for which
    /// `c-ares` does not provide a parser; or in case a third-party parser is
    /// preferred.  Usually, if a suitable `query_xxx()` is available, that
    /// should be used.
    pub fn query(&self, name: &str, dns_class: u16, query_type: u16)
        -> CAresFuture<Vec<u8>>
    {
        let (c, p) = futures::oneshot();
        self.inner.query(name, dns_class, query_type, move |result| {
            let _ = c.send(result.map(|bs| bs.to_owned()));
        });
        CAresFuture::new(p)
    }

    /// Initiate a series of single-question DNS queries for `name`.  The
    /// class and type of the query are per the provided parameters, taking
    /// values as defined in `arpa/nameser.h`.
    ///
    /// This method is one of the very few places where this library performs
    /// strictly more allocation than the underlying `c-ares` code.  If this is
    /// a problem for you, you should prefer to use the analogous method on the
    /// `Resolver`.
    ///
    /// This method is provided so that users can search DNS types for which
    /// `c-ares` does not provide a parser; or in case a third-party parser is
    /// preferred.  Usually, if a suitable `search_xxx()` is available, that
    /// should be used.
    pub fn search(&self, name: &str, dns_class: u16, query_type: u16)
        -> CAresFuture<Vec<u8>>
    {
        let (c, p) = futures::oneshot();
        self.inner.search(name, dns_class, query_type, move |result| {
            let _ = c.send(result.map(|bs| bs.to_owned()));
        });
        CAresFuture::new(p)
    }

    /// Cancel all requests made on this `FutureResolver`.
    pub fn cancel(&self) {
        self.inner.cancel()
    }
}
<|endoftext|>