<commit_before>extern crate xml;

use server_handler::XmppServerHandler;
use std::io::net::tcp::TcpStream;
use std::io::BufferedStream;

use read_str::ReadString;

use xmpp_socket::Tcp;
use ns;

/// Represent a server side XMPP stream
pub struct XmppServerStream {
    parser: xml::Parser,
    builder: xml::ElementBuilder,
    handler: XmppServerHandler,
}

impl XmppServerStream {

    pub fn new(
        stream: TcpStream
    ) -> XmppServerStream {
        XmppServerStream {
            parser: xml::Parser::new(),
            builder: xml::ElementBuilder::new(),
            handler: XmppServerHandler {
                socket: Tcp(BufferedStream::new(stream))
            }
        }
    }

    pub fn handle(&mut self) {

        loop {
            let string = {
                let socket = &mut self.handler.socket;
                match socket.read_str() {
                    Ok(string) => string,
                    Err(e) => {
                        println!("{}", e);
                        return;
                    }
                }
            };
            println!("raw string {}", string);
            self.parser.feed_str(string.as_slice());

            let builder = &mut self.builder;
            let handler = &mut self.handler;

            for event in self.parser { match event {
                Ok(xml::StartTag(xml::StartTag {
                    name: ref name,
                    ns: Some(ref ns),
                    prefix: ref prefix, ..
                })) if name.as_slice() == "stream" && ns.as_slice() == ns::STREAMS => {
                    println!("In: Stream start");
                    match *prefix {
                        Some(ref prefix) => {
                            *builder = xml::ElementBuilder::new();
                            builder.set_default_ns(ns::JABBER_CLIENT);
                            builder.define_prefix(prefix.as_slice(), ns::STREAMS);
                            handler.start_stream("localhost".as_slice());
                            handler.advertize_security_features();
                        },
                        None => ()
                    }
                },
                Ok(xml::EndTag(xml::EndTag {
                    name: ref name,
                    ns: Some(ref ns), ..
                })) if name.as_slice() == "stream" && ns.as_slice() == ns::STREAMS => {
                    println!("In: Stream end");
                    handler.close_stream();
                    return;
                }
               Ok(event) => {
                    match builder.push_event(event) {
                        Ok(Some(ref e)) => {
                            println!("In: {}", e)
                        }
                        Ok(None) => (),
                        Err(e) => println!("{}", e),
                    }
                },
                Err(e) => println!(
                    "Line: {} Column: {} Msg: {}",
                    e.line,
                    e.col, e.msg),
            };}
        }
    }

}
<commit_msg>added some comments in XmppServerStream<commit_after>extern crate xml;

use server_handler::XmppServerHandler;
use std::io::net::tcp::TcpStream;
use std::io::BufferedStream;

use read_str::ReadString;

use xmpp_socket::Tcp;
use ns;

/// Represent a server side XMPP stream
pub struct XmppServerStream {
    parser: xml::Parser,
    builder: xml::ElementBuilder,
    handler: XmppServerHandler,
}

impl XmppServerStream {

    pub fn new(
        stream: TcpStream
    ) -> XmppServerStream {
        XmppServerStream {
            parser: xml::Parser::new(),
            builder: xml::ElementBuilder::new(),
            handler: XmppServerHandler {
                socket: Tcp(BufferedStream::new(stream))
            }
        }
    }

    pub fn handle(&mut self) {

        loop {
            let string = {
                let socket = &mut self.handler.socket;
                match socket.read_str() {
                    Ok(string) => string,
                    Err(e) => {
                        println!("{}", e);
                        return;
                    }
                }
            };
            println!("raw string {}", string);
            self.parser.feed_str(string.as_slice());

            let builder = &mut self.builder;
            let handler = &mut self.handler;

            for event in self.parser { match event {

                // handle <stream:stream> from client
                Ok(xml::StartTag(xml::StartTag {
                    name: ref name,
                    ns: Some(ref ns),
                    prefix: ref prefix, ..
                })) if name.as_slice() == "stream" && ns.as_slice() == ns::STREAMS => {

                    println!("In: Stream start");
                    match *prefix {
                        Some(ref prefix) => {
                            *builder = xml::ElementBuilder::new();
                            builder.set_default_ns(ns::JABBER_CLIENT);
                            builder.define_prefix(prefix.as_slice(), ns::STREAMS);
                            handler.start_stream("localhost".as_slice());
                            handler.advertize_security_features();
                        },
                        None => ()
                    }
                },

                // handle </stream:stream> from client
                Ok(xml::EndTag(xml::EndTag {
                    name: ref name,
                    ns: Some(ref ns), ..
                })) if name.as_slice() == "stream" && ns.as_slice() == ns::STREAMS => {
                    println!("In: Stream end");
                    handler.close_stream();
                    return;
                }

               Ok(event) => {
                    match builder.push_event(event) {
                        Ok(Some(ref e)) => {
                            println!("In: {}", e)
                        }
                        Ok(None) => (),
                        Err(e) => println!("{}", e),
                    }
                },
                Err(e) => println!(
                    "Line: {} Column: {} Msg: {}",
                    e.line,
                    e.col, e.msg),
            };}
        }
    }

}
<|endoftext|>


<commit_before>use crate::msg::diagnostic_msgs::{DiagnosticArray, DiagnosticStatus};
use crate::msg::std_msgs::Header;
use crate::{Level, Status, Task};
use rosrust::{error::Result, Publisher};

pub struct Updater {
    publisher: Publisher<DiagnosticArray>,
    tasks: Vec<Box<dyn Task>>,
    hardware_id: String,
}

impl Updater {
    pub fn new() -> Result<Self> {
        let publisher = rosrust::publish("/diagnostics", 10)?;
        Ok(Self {
            publisher,
            tasks: vec![],
            hardware_id: String::new(),
        })
    }

    pub fn add_task(&mut self, task: impl Task + 'static) {
        self.tasks.push(Box::new(task))
    }

    pub fn update_with_extra<'a>(&'a self, extra_tasks: &[&'a dyn Task]) -> Result<()> {
        self.publish(self.perform_checks(extra_tasks))
    }

    pub fn update(&self) -> Result<()> {
        self.update_with_extra(&vec![])
    }

    pub fn perform_checks<'a>(&self, extra_tasks: &[&'a dyn Task]) -> Vec<DiagnosticStatus> {
        Iterator::chain(
            self.tasks.iter().map(|v| &(**v)),
            extra_tasks.into_iter().map(|v| *v),
        )
        .map(|task| {
            let mut status = Status {
                name: task.name().into(),
                hardware_id: self.hardware_id.clone(),
                level: Level::Error,
                message: "No message was set".into(),
                values: vec![],
            };
            task.run(&mut status);
            status.into()
        })
        .collect()
    }

    pub fn publish(&self, status: Vec<DiagnosticStatus>) -> Result<()> {
        let message = DiagnosticArray {
            header: Header::default(),
            status,
        };
        self.publisher.send(message)
    }
}
<commit_msg>Extract single diagnostic check handler<commit_after>use crate::msg::diagnostic_msgs::{DiagnosticArray, DiagnosticStatus};
use crate::msg::std_msgs::Header;
use crate::{Level, Status, Task};
use rosrust::{error::Result, Publisher};

pub struct Updater {
    publisher: Publisher<DiagnosticArray>,
    tasks: Vec<Box<dyn Task>>,
    hardware_id: String,
}

impl Updater {
    pub fn new() -> Result<Self> {
        let publisher = rosrust::publish("/diagnostics", 10)?;
        Ok(Self {
            publisher,
            tasks: vec![],
            hardware_id: String::new(),
        })
    }

    pub fn add_task(&mut self, task: impl Task + 'static) {
        self.tasks.push(Box::new(task))
    }

    pub fn update_with_extra<'a>(&'a self, extra_tasks: &[&'a dyn Task]) -> Result<()> {
        self.publish(self.perform_checks(extra_tasks))
    }

    pub fn update(&self) -> Result<()> {
        self.update_with_extra(&vec![])
    }

    pub fn perform_checks<'a>(&self, extra_tasks: &[&'a dyn Task]) -> Vec<DiagnosticStatus> {
        Iterator::chain(
            self.tasks.iter().map(|v| &(**v)),
            extra_tasks.into_iter().map(|v| *v),
        )
        .map(|task| self.perform_passed_check(task))
        .collect()
    }

    pub fn perform_passed_check(&self, task: &dyn Task) -> DiagnosticStatus {
        let mut status = Status {
            name: task.name().into(),
            hardware_id: self.hardware_id.clone(),
            level: Level::Error,
            message: "No message was set".into(),
            values: vec![],
        };
        task.run(&mut status);
        status.into()
    }

    pub fn publish(&self, status: Vec<DiagnosticStatus>) -> Result<()> {
        let message = DiagnosticArray {
            header: Header::default(),
            status,
        };
        self.publisher.send(message)
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Delix Project Authors. See the AUTHORS file at the top level directory.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

use std::fmt;
use std::io::{Cursor, Read, Write};
use std::net::{SocketAddr, TcpStream};
use std::sync::{Arc, Mutex, mpsc};
use std::thread::{JoinHandle, spawn};

use protobuf::Message as Message_imported_for_functions;
use protobuf::error::ProtobufError;
use protobuf::{parse_from_reader, parse_from_bytes};
use message::{Container, Kind, Introduction, Peers, Peer};
use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt};

use node::ID;

pub struct Connection {
    stream: TcpStream,
    thread: Option<JoinHandle<()>>,

    peer_node_id_receiver: mpsc::Receiver<ID>,
    peer_node_id: Option<ID>,

    peer_public_address_receiver: mpsc::Receiver<SocketAddr>,
    peer_public_address: Option<SocketAddr>,

    on_peers: Arc<Mutex<Option<Box<Fn(Vec<(ID, SocketAddr)>) + Send>>>>,
}

impl Connection {
    pub fn new(s: TcpStream, node_id: ID, public_address: SocketAddr) -> Connection {
        let mut stream = s.try_clone().unwrap();

        let on_peers: Arc<Mutex<Option<Box<Fn(Vec<(ID, SocketAddr)>) + Send>>>> =
            Arc::new(Mutex::new(None));
        let on_peers_mutex = on_peers.clone();

        let (peer_node_id_sender, peer_node_id_receiver) = mpsc::channel();
        let (peer_public_address_sender, peer_public_address_receiver) = mpsc::channel();
        let thread = spawn(move || {
            write_introduction(&mut stream, node_id, public_address).unwrap();
            // println!("send introduction {}", node_id);

            let mut introduction = read_introduction(&mut stream).unwrap();
            let peer_node_id = ID::new(introduction.take_id()).unwrap();
            let peer_public_address = introduction.take_public_address()
                                                  .parse::<SocketAddr>()
                                                  .unwrap();
            // println!("got introduction {} {}", peer_node_id, peer_public_address);

            peer_node_id_sender.send(peer_node_id).unwrap();
            peer_public_address_sender.send(peer_public_address).unwrap();

            loop {
                let mut container = read_container(&mut stream).unwrap();
                match container.get_kind() {
                    Kind::PeersMessage => {
                        let mut peers_packet = read_peers(&mut container).unwrap();
                        let mut peers = Vec::new();
                        for peer_packet in peers_packet.mut_peers().iter_mut() {
                            let peer_node_id = ID::new(peer_packet.take_id()).unwrap();
                            let peer_public_address = peer_packet.take_public_address()
                                                                 .parse::<SocketAddr>()
                                                                 .unwrap();

                            peers.push((peer_node_id, peer_public_address));
                        }

                        if let Some(ref f) = *on_peers_mutex.lock().unwrap() {
                            f(peers);
                        }
                    }
                    _ => {
                        println!("{}: got unexpected container {:?}", node_id, container);
                    }
                }
            }
        });

        Connection {
            stream: s,
            thread: Some(thread),
            peer_node_id_receiver: peer_node_id_receiver,
            peer_node_id: None,
            peer_public_address_receiver: peer_public_address_receiver,
            peer_public_address: None,
            on_peers: on_peers,
        }
    }

    pub fn peer_node_id(&mut self) -> ID {
        if let Some(node_id) = self.peer_node_id {
            return node_id;
        }

        let peer_node_id = self.peer_node_id_receiver.recv().unwrap();
        self.peer_node_id = Some(peer_node_id);
        peer_node_id
    }

    pub fn peer_public_address(&mut self) -> SocketAddr {
        if let Some(public_address) = self.peer_public_address {
            return public_address;
        }

        let peer_public_address = self.peer_public_address_receiver.recv().unwrap();
        self.peer_public_address = Some(peer_public_address);
        peer_public_address
    }

    pub fn peer_addr(&self) -> SocketAddr {
        self.stream.peer_addr().unwrap()
    }

    pub fn local_addr(&self) -> SocketAddr {
        self.stream.local_addr().unwrap()
    }

    pub fn send_peers(&mut self, peers: &[(ID, SocketAddr)]) {
        // WORKAROUND: process peer node id first before sending peers. This ensures, that
        // that the introduction sequence has been finished.
        self.peer_node_id();

        write_peers(&mut self.stream, peers).unwrap();
    }

    pub fn set_on_peers(&mut self, f: Box<Fn(Vec<(ID, SocketAddr)>) + Send>) {
        *self.on_peers.lock().unwrap() = Some(f);
    }
}

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

impl Drop for Connection {
    fn drop(&mut self) {
        self.thread.take().unwrap().join().unwrap();
    }
}

fn write_introduction(w: &mut Write,
                      node_id: ID,
                      public_address: SocketAddr)
                      -> Result<(), ProtobufError> {
    let mut buffer = Vec::new();
    let mut introduction = Introduction::new();
    introduction.set_id(node_id.to_vec());
    introduction.set_public_address(format!("{}", public_address));
    try!(introduction.write_to_vec(&mut buffer));
    write_container(w, Kind::IntroductionMessage, buffer)
}

fn write_peers(w: &mut Write, peers: &[(ID, SocketAddr)]) -> Result<(), ProtobufError> {
    let mut buffer = Vec::new();
    let mut peers_packet = Peers::new();
    for peer in peers {
        let (peer_node_id, peer_public_address) = *peer;
        let mut peer_packet = Peer::new();
        peer_packet.set_id(peer_node_id.to_vec());
        peer_packet.set_public_address(format!("{}", peer_public_address));
        peers_packet.mut_peers().push(peer_packet);
    }
    try!(peers_packet.write_to_vec(&mut buffer));
    write_container(w, Kind::PeersMessage, buffer)
}

fn write_container(w: &mut Write, kind: Kind, data: Vec<u8>) -> Result<(), ProtobufError> {
    let mut container = Container::new();
    container.set_kind(kind);
    container.set_payload(data);

    let container_bytes = try!(container.write_to_bytes());
    let container_size = container_bytes.len() as u64;

    w.write_u64::<BigEndian>(container_size).unwrap();
    w.write(&container_bytes).unwrap();
    w.flush().unwrap();

    Ok(())
}

fn read_introduction(r: &mut Read) -> Result<Introduction, ProtobufError> {
    let mut container = try!(read_container(r));
    let mut payload_cursor = Cursor::new(container.take_payload());
    parse_from_reader::<Introduction>(&mut payload_cursor)
}

fn read_peers(container: &mut Container) -> Result<Peers, ProtobufError> {
    parse_from_reader::<Peers>(&mut Cursor::new(container.take_payload()))
}

fn read_container(r: &mut Read) -> Result<Container, ProtobufError> {
    let container_size = r.read_u64::<BigEndian>().unwrap() as usize;

    let mut buffer = Vec::with_capacity(container_size);
    unsafe {
        buffer.set_len(container_size);
    }
    r.read(&mut buffer).unwrap();

    parse_from_bytes::<Container>(&buffer)
}
<commit_msg>small fix<commit_after>// Copyright 2015 The Delix Project Authors. See the AUTHORS file at the top level directory.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

use std::fmt;
use std::io::{Cursor, Read, Write};
use std::net::{SocketAddr, TcpStream};
use std::sync::{Arc, Mutex, mpsc};
use std::thread::{JoinHandle, spawn};

use protobuf::Message as Message_imported_for_functions;
use protobuf::error::ProtobufError;
use protobuf::{parse_from_reader, parse_from_bytes};
use message::{Container, Kind, Introduction, Peers, Peer};
use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt};

use node::ID;

pub struct Connection {
    stream: TcpStream,
    thread: Option<JoinHandle<()>>,

    peer_node_id_receiver: mpsc::Receiver<ID>,
    peer_node_id: Option<ID>,

    peer_public_address_receiver: mpsc::Receiver<SocketAddr>,
    peer_public_address: Option<SocketAddr>,

    on_peers: Arc<Mutex<Option<Box<Fn(Vec<(ID, SocketAddr)>) + Send>>>>,
}

impl Connection {
    pub fn new(s: TcpStream, node_id: ID, public_address: SocketAddr) -> Connection {
        let mut stream = s.try_clone().unwrap();

        let on_peers: Arc<Mutex<Option<Box<Fn(Vec<(ID, SocketAddr)>) + Send>>>> =
            Arc::new(Mutex::new(None));
        let on_peers_mutex = on_peers.clone();

        let (peer_node_id_sender, peer_node_id_receiver) = mpsc::channel();
        let (peer_public_address_sender, peer_public_address_receiver) = mpsc::channel();
        let thread = spawn(move || {
            write_introduction(&mut stream, node_id, public_address).unwrap();
            // println!("send introduction {}", node_id);

            let mut introduction = read_introduction(&mut stream).unwrap();
            let peer_node_id = ID::new(introduction.take_id()).unwrap();
            let peer_public_address = introduction.take_public_address()
                                                  .parse::<SocketAddr>()
                                                  .unwrap();
            // println!("got introduction {} {}", peer_node_id, peer_public_address);

            peer_node_id_sender.send(peer_node_id).unwrap();
            peer_public_address_sender.send(peer_public_address).unwrap();

            loop {
                let mut container = read_container(&mut stream).unwrap();
                match container.get_kind() {
                    Kind::PeersMessage => {
                        let mut peers_packet = read_peers(&mut container).unwrap();
                        let mut peers = Vec::new();
                        for peer_packet in peers_packet.mut_peers().iter_mut() {
                            let peer_node_id = ID::new(peer_packet.take_id()).unwrap();
                            let peer_public_address = peer_packet.take_public_address()
                                                                 .parse::<SocketAddr>()
                                                                 .unwrap();

                            peers.push((peer_node_id, peer_public_address));
                        }

                        if let Some(ref f) = *on_peers_mutex.lock().unwrap() {
                            f(peers);
                        }
                    }
                    _ => {
                        println!("{}: got unexpected container {:?}", node_id, container);
                    }
                }
            }
        });

        Connection {
            stream: s,
            thread: Some(thread),
            peer_node_id_receiver: peer_node_id_receiver,
            peer_node_id: None,
            peer_public_address_receiver: peer_public_address_receiver,
            peer_public_address: None,
            on_peers: on_peers,
        }
    }

    pub fn peer_node_id(&mut self) -> ID {
        if let Some(node_id) = self.peer_node_id {
            return node_id;
        }

        let peer_node_id = self.peer_node_id_receiver.recv().unwrap();
        self.peer_node_id = Some(peer_node_id);
        peer_node_id
    }

    pub fn peer_public_address(&mut self) -> SocketAddr {
        if let Some(public_address) = self.peer_public_address {
            return public_address;
        }

        let peer_public_address = self.peer_public_address_receiver.recv().unwrap();
        self.peer_public_address = Some(peer_public_address);
        peer_public_address
    }

    pub fn peer_addr(&self) -> SocketAddr {
        self.stream.peer_addr().unwrap()
    }

    pub fn local_addr(&self) -> SocketAddr {
        self.stream.local_addr().unwrap()
    }

    pub fn send_peers(&mut self, peers: &[(ID, SocketAddr)]) {
        // Process peer node id first before sending peers. This ensures, that
        // that the introduction sequence has been finished.
        self.peer_node_id();

        write_peers(&mut self.stream, peers).unwrap();
    }

    pub fn set_on_peers(&mut self, f: Box<Fn(Vec<(ID, SocketAddr)>) + Send>) {
        *self.on_peers.lock().unwrap() = Some(f);
    }
}

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

impl Drop for Connection {
    fn drop(&mut self) {
        self.thread.take().unwrap().join().unwrap();
    }
}

fn write_introduction(w: &mut Write,
                      node_id: ID,
                      public_address: SocketAddr)
                      -> Result<(), ProtobufError> {
    let mut buffer = Vec::new();
    let mut introduction = Introduction::new();
    introduction.set_id(node_id.to_vec());
    introduction.set_public_address(format!("{}", public_address));
    try!(introduction.write_to_vec(&mut buffer));
    write_container(w, Kind::IntroductionMessage, buffer)
}

fn write_peers(w: &mut Write, peers: &[(ID, SocketAddr)]) -> Result<(), ProtobufError> {
    let mut buffer = Vec::new();
    let mut peers_packet = Peers::new();
    for peer in peers {
        let (peer_node_id, peer_public_address) = *peer;
        let mut peer_packet = Peer::new();
        peer_packet.set_id(peer_node_id.to_vec());
        peer_packet.set_public_address(format!("{}", peer_public_address));
        peers_packet.mut_peers().push(peer_packet);
    }
    try!(peers_packet.write_to_vec(&mut buffer));
    write_container(w, Kind::PeersMessage, buffer)
}

fn write_container(w: &mut Write, kind: Kind, data: Vec<u8>) -> Result<(), ProtobufError> {
    let mut container = Container::new();
    container.set_kind(kind);
    container.set_payload(data);

    let container_bytes = try!(container.write_to_bytes());
    let container_size = container_bytes.len() as u64;

    w.write_u64::<BigEndian>(container_size).unwrap();
    w.write(&container_bytes).unwrap();
    w.flush().unwrap();

    Ok(())
}

fn read_introduction(r: &mut Read) -> Result<Introduction, ProtobufError> {
    let mut container = try!(read_container(r));
    let mut payload_cursor = Cursor::new(container.take_payload());
    parse_from_reader::<Introduction>(&mut payload_cursor)
}

fn read_peers(container: &mut Container) -> Result<Peers, ProtobufError> {
    parse_from_reader::<Peers>(&mut Cursor::new(container.take_payload()))
}

fn read_container(r: &mut Read) -> Result<Container, ProtobufError> {
    let container_size = r.read_u64::<BigEndian>().unwrap() as usize;

    let mut buffer = Vec::with_capacity(container_size);
    unsafe {
        buffer.set_len(container_size);
    }
    r.read(&mut buffer).unwrap();

    parse_from_bytes::<Container>(&buffer)
}
<|endoftext|>


<commit_before>extern crate libc;

use libc::c_int;

#[repr(C)]
#[derive(Clone, Copy)]
pub struct RawEvent {
    pub etype: u8,
    pub emod: u8,
    pub key: u16,
    pub ch: u32,
    pub w: i32,
    pub h: i32,
    pub x: i32,
    pub y: i32,
}

extern "C" {
    pub fn tb_init() -> c_int;
    pub fn tb_shutdown();

    pub fn tb_width() -> c_int;
    pub fn tb_height() -> c_int;

    pub fn tb_clear();
    pub fn tb_present();

    pub fn tb_set_cursor(cx: c_int, cy: c_int);
    pub fn tb_change_cell(x: c_int, y: c_int, ch: u32, fg: u16, bg: u16);

    pub fn tb_select_input_mode(mode: c_int) -> c_int;
    pub fn tb_set_clear_attributes(fg: u16, bg: u16);

    pub fn tb_peek_event(ev: *const ::RawEvent, timeout: c_int) -> c_int;
    pub fn tb_poll_event(ev: *const ::RawEvent) -> c_int;
}
<commit_msg>Added everything else from 'termbox.h'.<commit_after>extern crate libc;

use libc::{
    c_char,
    c_int,
};

#[repr(C)]
#[derive(Clone, Copy)]
pub struct RawCell {
    pub ch: u32,
    pub fg: u16,
    pub bg: u16,
}

#[repr(C)]
#[derive(Clone, Copy)]
pub struct RawEvent {
    pub etype: u8,
    pub emod: u8,
    pub key: u16,
    pub ch: u32,
    pub w: i32,
    pub h: i32,
    pub x: i32,
    pub y: i32,
}

extern "C" {
    pub fn tb_init() -> c_int;
    pub fn tb_shutdown();
    pub fn tb_width() -> c_int;
    pub fn tb_height() -> c_int;
    pub fn tb_clear();
    pub fn tb_set_clear_attributes(fg: u16, bg: u16);
    pub fn tb_present();
    pub fn tb_set_cursor(cx: c_int, cy: c_int);
    pub fn tb_put_cell(x: c_int, y: c_int, cell: *const RawCell);
    pub fn tb_change_cell(x: c_int, y: c_int, ch: u32, fg: u16, bg: u16);
    pub fn tb_blit(x: c_int, y: c_int, w: c_int, h: c_int, cells: *const RawCell);
    pub fn tb_cell_buffer() -> *mut RawCell;
    pub fn tb_select_input_mode(mode: c_int) -> c_int;
    pub fn tb_select_output_mode(mode: c_int) -> c_int;
    pub fn tb_peek_event(ev: *const ::RawEvent, timeout: c_int) -> c_int;
    pub fn tb_poll_event(ev: *const ::RawEvent) -> c_int;
    pub fn tb_utf8_char_length(c: c_char) -> c_int;
    pub fn tb_utf8_char_to_unicode(out: *mut u32, c: *const c_char) -> c_int;
    pub fn tb_utf8_unicode_to_char(out: *mut c_char, c: u32) -> c_int;
}

pub const TB_KEY_F1: u16 = 0xffff - 0;
pub const TB_KEY_F2: u16 = 0xffff - 1;
pub const TB_KEY_F3: u16 = 0xffff - 2;
pub const TB_KEY_F4: u16 = 0xffff - 3;
pub const TB_KEY_F5: u16 = 0xffff - 4;
pub const TB_KEY_F6: u16 = 0xffff - 5;
pub const TB_KEY_F7: u16 = 0xffff - 6;
pub const TB_KEY_F8: u16 = 0xffff - 7;
pub const TB_KEY_F9: u16 = 0xffff - 8;
pub const TB_KEY_F10: u16 = 0xffff - 9;
pub const TB_KEY_F11: u16 = 0xffff - 10;
pub const TB_KEY_F12: u16 = 0xffff - 11;
pub const TB_KEY_INSERT: u16 = 0xffff - 12;
pub const TB_KEY_DELETE: u16 = 0xffff - 13;
pub const TB_KEY_HOME: u16 = 0xffff - 14;
pub const TB_KEY_END: u16 = 0xffff - 15;
pub const TB_KEY_PGUP: u16 = 0xffff - 16;
pub const TB_KEY_PGDN: u16 = 0xffff - 17;
pub const TB_KEY_ARROW_UP: u16 = 0xffff - 18;
pub const TB_KEY_ARROW_DOWN: u16 = 0xffff - 19;
pub const TB_KEY_ARROW_LEFT: u16 = 0xffff - 20;
pub const TB_KEY_ARROW_RIGHT: u16 = 0xffff - 21;
pub const TB_KEY_MOUSE_LEFT: u16 = 0xffff - 22;
pub const TB_KEY_MOUSE_RIGHT: u16 = 0xffff - 23;
pub const TB_KEY_MOUSE_MIDDLE: u16 = 0xffff - 24;
pub const TB_KEY_MOUSE_RELEASE: u16 = 0xffff - 25;
pub const TB_KEY_MOUSE_WHEEL_UP: u16 = 0xffff - 26;
pub const TB_KEY_MOUSE_WHEEL_DOWN: u16 = 0xffff - 27;

pub const TB_KEY_CTRL_TILDE: u16 = 0x00;
pub const TB_KEY_CTRL_2: u16 = 0x00;
pub const TB_KEY_CTRL_A: u16 = 0x01;
pub const TB_KEY_CTRL_B: u16 = 0x02;
pub const TB_KEY_CTRL_C: u16 = 0x03;
pub const TB_KEY_CTRL_D: u16 = 0x04;
pub const TB_KEY_CTRL_E: u16 = 0x05;
pub const TB_KEY_CTRL_F: u16 = 0x06;
pub const TB_KEY_CTRL_G: u16 = 0x07;
pub const TB_KEY_BACKSPACE: u16 = 0x08;
pub const TB_KEY_CTRL_H: u16 = 0x08;
pub const TB_KEY_TAB: u16 = 0x09;
pub const TB_KEY_CTRL_I: u16 = 0x09;
pub const TB_KEY_CTRL_J: u16 = 0x0a;
pub const TB_KEY_CTRL_K: u16 = 0x0b;
pub const TB_KEY_CTRL_L: u16 = 0x0c;
pub const TB_KEY_ENTER: u16 = 0x0d;
pub const TB_KEY_CTRL_M: u16 = 0x0d;
pub const TB_KEY_CTRL_N: u16 = 0x0e;
pub const TB_KEY_CTRL_O: u16 = 0x0f;
pub const TB_KEY_CTRL_P: u16 = 0x10;
pub const TB_KEY_CTRL_Q: u16 = 0x11;
pub const TB_KEY_CTRL_R: u16 = 0x12;
pub const TB_KEY_CTRL_S: u16 = 0x13;
pub const TB_KEY_CTRL_T: u16 = 0x14;
pub const TB_KEY_CTRL_U: u16 = 0x15;
pub const TB_KEY_CTRL_V: u16 = 0x16;
pub const TB_KEY_CTRL_W: u16 = 0x17;
pub const TB_KEY_CTRL_X: u16 = 0x18;
pub const TB_KEY_CTRL_Y: u16 = 0x19;
pub const TB_KEY_CTRL_Z: u16 = 0x1a;
pub const TB_KEY_ESC: u16 = 0x1b;
pub const TB_KEY_CTRL_LSQ_BRACKET: u16 = 0x1b;
pub const TB_KEY_CTRL_3: u16 = 0x1b;
pub const TB_KEY_CTRL_4: u16 = 0x1c;
pub const TB_KEY_CTRL_BACKSLASH: u16 = 0x1c;
pub const TB_KEY_CTRL_5: u16 = 0x1d;
pub const TB_KEY_CTRL_RSQ_BRACKET: u16 = 0x1d;
pub const TB_KEY_CTRL_6: u16 = 0x1e;
pub const TB_KEY_CTRL_7: u16 = 0x1f;
pub const TB_KEY_CTRL_SLASH: u16 = 0x1f;
pub const TB_KEY_CTRL_UNDERSCORE: u16 = 0x1f;
pub const TB_KEY_SPACE: u16 = 0x20;
pub const TB_KEY_BACKSPACE2: u16 = 0x7f;
pub const TB_KEY_CTRL_8: u16 = 0x7f;

pub const TB_MOD_ALT: u8 = 0x01;

pub const TB_DEFAULT: u16 = 0x00;
pub const TB_BLACK: u16 = 0x01;
pub const TB_RED: u16 = 0x02;
pub const TB_GREEN: u16 = 0x03;
pub const TB_YELLOW: u16 = 0x04;
pub const TB_BLUE: u16 = 0x05;
pub const TB_MAGENTA: u16 = 0x06;
pub const TB_CYAN: u16 = 0x07;
pub const TB_WHITE: u16 = 0x08;

pub const TB_BOLD: u16 = 0x0100;
pub const TB_UNDERLINE: u16 = 0x0200;
pub const TB_REVERSE: u16 = 0x0400;

pub const TB_EVENT_KEY: u8 = 1;
pub const TB_EVENT_RESIZE: u8 = 2;
pub const TB_EVENT_MOUSE: u8 = 3;

pub const TB_EUNSUPPORTED_TERMINAL: c_int = -1;
pub const TB_EFAILED_TO_OPEN_TTY: c_int = -2;
pub const TB_EPIPE_TRAP_ERROR: c_int = -3;

pub const TB_HIDE_CURSOR: c_int = -1;

pub const TB_INPUT_CURRENT: c_int = 0;
pub const TB_INPUT_ESC: c_int = 1;
pub const TB_INPUT_ALT: c_int = 2;
pub const TB_INPUT_MOUSE: c_int = 4;

pub const TB_OUTPUT_CURRENT: c_int = 0;
pub const TB_OUTPUT_NORMAL: c_int = 1;
pub const TB_OUTPUT_256: c_int = 2;
pub const TB_OUTPUT_216: c_int = 3;
pub const TB_OUTPUT_GRAYSCALE: c_int = 4;

pub const TB_EOF: c_int = -1;
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[crate_id = "github.com/mozilla-servo/sharegl#0.1"];
#[crate_type = "lib"];
#[crate_type = "dylib"];
#[crate_type = "rlib"];

#[feature(phase)];
#[phase(syntax, link)] extern crate log;

extern crate std;
extern crate sync;
extern crate geom;

#[cfg(target_os="macos")]
extern crate core_foundation;
#[cfg(target_os="macos")]
extern crate io_surface;
#[cfg(target_os="macos")]
extern crate opengles;

pub mod base;
pub mod context;

#[cfg(target_os="macos")]
#[path="platform/macos.rs"]
pub mod platform;

#[cfg(target_os="linux")]
#[path="platform/linux.rs"]
pub mod platform;

#[cfg(target_os="windows")]
#[cfg(target_os="android")]
#[path="platform/dummy.rs"]
pub mod platform;
<commit_msg>Update to current rust: use the new attributes syntax.<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![crate_id = "github.com/mozilla-servo/sharegl#0.1"]
#![crate_type = "lib"]
#![crate_type = "dylib"]
#![crate_type = "rlib"]

#![feature(phase)]

extern crate geom;
#[phase(syntax, link)]
extern crate log;
extern crate std;
extern crate sync;

#[cfg(target_os="macos")]
extern crate core_foundation;
#[cfg(target_os="macos")]
extern crate io_surface;
#[cfg(target_os="macos")]
extern crate opengles;

pub mod base;
pub mod context;

#[cfg(target_os="macos")]
#[path="platform/macos.rs"]
pub mod platform;

#[cfg(target_os="linux")]
#[path="platform/linux.rs"]
pub mod platform;

#[cfg(target_os="windows")]
#[cfg(target_os="android")]
#[path="platform/dummy.rs"]
pub mod platform;
<|endoftext|>


<commit_before>use board::sjadam_board::SjadamBoard;
use search_algorithms::board::{GameResult, EvalBoard};
use uci::UciBoard;

use std::collections::hash_map::DefaultHasher;
use std::hash::Hash;
use std::hash::Hasher;

#[test]
fn hash_stays_equal() {
    let mut board = SjadamBoard::start_board();

    let mut hasher = DefaultHasher::new();
    board.hash(&mut hasher);
    let start_hash = hasher.finish();

    for mv in board.all_legal_moves() {
        let undo_move = board.do_move(mv);
        board.undo_move(undo_move);

        hasher = DefaultHasher::new();
        board.hash(&mut hasher);
        let new_hash = hasher.finish();

        assert_eq!(start_hash, new_hash);

    }
}

#[test]
fn repetitions_do_not_preserve_hash() {
    let mut board = SjadamBoard::start_board();

    let mut hasher = DefaultHasher::new();
    board.hash(&mut hasher);
    let start_hash = hasher.finish();

    for mv_str in ["c1c3", "c8c6", "c3c1", "c6c8"].iter() {
        let mv = board.from_alg(mv_str).unwrap();
        board.do_move(mv);
    }

    hasher = DefaultHasher::new();
    board.hash(&mut hasher);
    let new_hash = hasher.finish();

    assert_ne!(start_hash, new_hash);
}

#[test]
fn repetitions_are_drawn() {
    let mut board = SjadamBoard::start_board();

    for mv_str in ["c1c3", "c8c6", "c3c1", "c6c8"].iter() {
        let mv = board.from_alg(mv_str).unwrap();
        board.do_move(mv);
    }

    assert_eq!(board.game_result(), None, "Wrong game result for board:\n{:?}", board);

    for mv_str in ["c1c3", "c8c6", "c3c1", "c6c8"].iter() {
        let mv = board.from_alg(mv_str).unwrap();
        board.do_move(mv);
    }

    assert_eq!(board.game_result(), Some(GameResult::Draw), "Wrong game result for board:\n{:?}", board);
}<commit_msg>improve sjadam repetition detection test<commit_after>use board::sjadam_board::SjadamBoard;
use search_algorithms::board::{GameResult, EvalBoard};
use uci::UciBoard;

use std::collections::hash_map::DefaultHasher;
use std::hash::Hash;
use std::hash::Hasher;

#[test]
fn hash_stays_equal() {
    let mut board = SjadamBoard::start_board();

    let mut hasher = DefaultHasher::new();
    board.hash(&mut hasher);
    let start_hash = hasher.finish();

    for mv in board.all_legal_moves() {
        let undo_move = board.do_move(mv);
        board.undo_move(undo_move);

        hasher = DefaultHasher::new();
        board.hash(&mut hasher);
        let new_hash = hasher.finish();

        assert_eq!(start_hash, new_hash);

    }
}

#[test]
fn repetitions_do_not_preserve_hash() {
    let mut board = SjadamBoard::start_board();

    let mut hasher = DefaultHasher::new();
    board.hash(&mut hasher);
    let start_hash = hasher.finish();

    for mv_str in ["c1c3", "c8c6", "c3c1", "c6c8"].iter() {
        let mv = board.from_alg(mv_str).unwrap();
        board.do_move(mv);
    }

    hasher = DefaultHasher::new();
    board.hash(&mut hasher);
    let new_hash = hasher.finish();

    assert_ne!(start_hash, new_hash);
}

#[test]
fn repetitions_are_drawn() {
    let mut board = SjadamBoard::start_board();

    for mv_str in ["c1c3", "c8c6", "c3c1", "c6c8", "c1c3", "c8c6", "c3c1", "c6c8"].iter() {
        assert_eq!(board.game_result(), None, "Wrong game result for board:\n{:?}", board);
        let mv = board.from_alg(mv_str).unwrap();
        board.do_move(mv);
    }

    assert_eq!(board.game_result(), Some(GameResult::Draw), "Wrong game result for board:\n{:?}", board);

    let mv = board.from_alg("g1e3").unwrap();
    board.do_move(mv);

    assert_eq!(board.game_result(), None, "Wrong game result for board:\n{:?}", board);
}<|endoftext|>


<commit_before>#![doc(html_root_url = "https://docs.rs/tokio-threadpool/0.1.11")]
#![deny(warnings, missing_docs, missing_debug_implementations)]

//! A work-stealing based thread pool for executing futures.
//!
//! The Tokio thread pool supports scheduling futures and processing them on
//! multiple CPU cores. It is optimized for the primary Tokio use case of many
//! independent tasks with limited computation and with most tasks waiting on
//! I/O. Usually, users will not create a `ThreadPool` instance directly, but
//! will use one via a [`runtime`].
//!
//! The `TheadPool` structure manages two sets of threads:
//!
//! * Worker threads.
//! * Backup threads.
//!
//! Worker threads are used to schedule futures using a work-stealing strategy.
//! Backup threads, on the other hand, are intended only to support the
//! `blocking` API. Threads will transition between the two sets.
//!
//! The advantage of the work-stealing strategy is minimal cross-thread
//! coordination. The thread pool attempts to make as much progress as possible
//! without communicating across threads.
//!
//! ## Worker overview
//!
//! Each worker has two queues: a deque and a mpsc channel. The deque is the
//! primary queue for tasks that are scheduled to run on the worker thread. Tasks
//! can only be pushed onto the deque by the worker, but other workers may
//! "steal" from that deque. The mpsc channel is used to submit futures while
//! external to the pool.
//!
//! As long as the thread pool has not been shutdown, a worker will run in a
//! loop. Each loop, it consumes all tasks on its mpsc channel and pushes it onto
//! the deque. It then pops tasks off of the deque and executes them.
//!
//! If a worker has no work, i.e., both queues are empty. It attempts to steal.
//! To do this, it randomly scans other workers' deques and tries to pop a task.
//! If it finds no work to steal, the thread goes to sleep.
//!
//! When the worker detects that the pool has been shut down, it exits the loop,
//! cleans up its state, and shuts the thread down.
//!
//! ## Thread pool initialization
//!
//! Note, users normally will use the threadpool created by a [`runtime`].
//!
//! By default, no threads are spawned on creation. Instead, when new futures are
//! spawned, the pool first checks if there are enough active worker threads. If
//! not, a new worker thread is spawned.
//!
//! ## Spawning futures
//!
//! The spawning behavior depends on whether a future was spawned from within a
//! worker or thread or if it was spawned from an external handle.
//!
//! When spawning a future while external to the thread pool, the current
//! strategy is to randomly pick a worker to submit the task to. The task is then
//! pushed onto that worker's mpsc channel.
//!
//! When spawning a future while on a worker thread, the task is pushed onto the
//! back of the current worker's deque.
//!
//! ## Blocking annotation strategy
//!
//! The [`blocking`] function is used to annotate a section of code that
//! performs a blocking operation, either by issuing a blocking syscall or
//! performing any long running CPU-bound computation.
//!
//! The strategy for handling blocking closures is to hand off the worker to a
//! new thread. This implies handing off the `deque` and `mpsc`. Once this is
//! done, the new thread continues to process the work queue and the original
//! thread is able to block. Once it finishes processing the blocking future, the
//! thread has no additional work and is inserted into the backup pool. This
//! makes it available to other workers that encounter a [`blocking`] call.
//!
//! [`blocking`]: fn.blocking.html
//! [`runtime`]: https://docs.rs/tokio/0.1/tokio/runtime/

extern crate tokio_executor;

extern crate crossbeam_deque;
extern crate crossbeam_queue;
extern crate crossbeam_utils;
#[macro_use]
extern crate futures;
extern crate num_cpus;
extern crate rand;
extern crate slab;

#[macro_use]
extern crate log;

// ## Crate layout
//
// The primary type, `Pool`, holds the majority of a thread pool's state,
// including the state for each worker. Each worker's state is maintained in an
// instance of `worker::Entry`.
//
// `Worker` contains the logic that runs on each worker thread. It holds an
// `Arc` to `Pool` and is able to access its state from `Pool`.
//
// `Task` is a harness around an individual future. It manages polling and
// scheduling that future.
//
// ## Sleeping workers
//
// Sleeping workers are tracked using a [Treiber stack]. This results in the
// thread that most recently went to sleep getting woken up first. When the pool
// is not under load, this helps threads shutdown faster.
//
// Sleeping is done by using `tokio_executor::Park` implementations. This allows
// the user of the thread pool to customize the work that is performed to sleep.
// This is how injecting timers and other functionality into the thread pool is
// done.
//
// ## Notifying workers
//
// When there is work to be done, workers must be notified. However, notifying a
// worker requires cross thread coordination. Ideally, a worker would only be
// notified when it is sleeping, but there is no way to know if a worker is
// sleeping without cross thread communication.
//
// The two cases when a worker might need to be notified are:
//
// 1. A task is externally submitted to a worker via the mpsc channel.
// 2. A worker has a back log of work and needs other workers to steal from it.
//
// In the first case, the worker will always be notified. However, it could be
// possible to avoid the notification if the mpsc channel has two or greater
// number of tasks *after* the task is submitted. In this case, we are able to
// assume that the worker has previously been notified.
//
// The second case is trickier. Currently, whenever a worker spawns a new future
// (pushing it onto its deque) and when it pops a future from its mpsc, it tries
// to notify a sleeping worker to wake up and start stealing. This is a lot of
// notification and it **might** be possible to reduce it.
//
// Also, whenever a worker is woken up via a signal and it does find work, it,
// in turn, will try to wake up a new worker.
//
// [Treiber stack]: https://en.wikipedia.org/wiki/Treiber_Stack

pub mod park;

mod blocking;
mod builder;
mod callback;
mod config;
mod notifier;
mod pool;
mod sender;
mod shutdown;
mod task;
mod thread_pool;
mod worker;

pub use blocking::{blocking, BlockingError};
pub use builder::Builder;
pub use sender::Sender;
pub use shutdown::Shutdown;
pub use thread_pool::{ThreadPool, SpawnHandle};
pub use worker::{Worker, WorkerId};
<commit_msg>threadpool: fix typo in documentation (#915)<commit_after>#![doc(html_root_url = "https://docs.rs/tokio-threadpool/0.1.11")]
#![deny(warnings, missing_docs, missing_debug_implementations)]

//! A work-stealing based thread pool for executing futures.
//!
//! The Tokio thread pool supports scheduling futures and processing them on
//! multiple CPU cores. It is optimized for the primary Tokio use case of many
//! independent tasks with limited computation and with most tasks waiting on
//! I/O. Usually, users will not create a `ThreadPool` instance directly, but
//! will use one via a [`runtime`].
//!
//! The `ThreadPool` structure manages two sets of threads:
//!
//! * Worker threads.
//! * Backup threads.
//!
//! Worker threads are used to schedule futures using a work-stealing strategy.
//! Backup threads, on the other hand, are intended only to support the
//! `blocking` API. Threads will transition between the two sets.
//!
//! The advantage of the work-stealing strategy is minimal cross-thread
//! coordination. The thread pool attempts to make as much progress as possible
//! without communicating across threads.
//!
//! ## Worker overview
//!
//! Each worker has two queues: a deque and a mpsc channel. The deque is the
//! primary queue for tasks that are scheduled to run on the worker thread. Tasks
//! can only be pushed onto the deque by the worker, but other workers may
//! "steal" from that deque. The mpsc channel is used to submit futures while
//! external to the pool.
//!
//! As long as the thread pool has not been shutdown, a worker will run in a
//! loop. Each loop, it consumes all tasks on its mpsc channel and pushes it onto
//! the deque. It then pops tasks off of the deque and executes them.
//!
//! If a worker has no work, i.e., both queues are empty. It attempts to steal.
//! To do this, it randomly scans other workers' deques and tries to pop a task.
//! If it finds no work to steal, the thread goes to sleep.
//!
//! When the worker detects that the pool has been shut down, it exits the loop,
//! cleans up its state, and shuts the thread down.
//!
//! ## Thread pool initialization
//!
//! Note, users normally will use the threadpool created by a [`runtime`].
//!
//! By default, no threads are spawned on creation. Instead, when new futures are
//! spawned, the pool first checks if there are enough active worker threads. If
//! not, a new worker thread is spawned.
//!
//! ## Spawning futures
//!
//! The spawning behavior depends on whether a future was spawned from within a
//! worker or thread or if it was spawned from an external handle.
//!
//! When spawning a future while external to the thread pool, the current
//! strategy is to randomly pick a worker to submit the task to. The task is then
//! pushed onto that worker's mpsc channel.
//!
//! When spawning a future while on a worker thread, the task is pushed onto the
//! back of the current worker's deque.
//!
//! ## Blocking annotation strategy
//!
//! The [`blocking`] function is used to annotate a section of code that
//! performs a blocking operation, either by issuing a blocking syscall or
//! performing any long running CPU-bound computation.
//!
//! The strategy for handling blocking closures is to hand off the worker to a
//! new thread. This implies handing off the `deque` and `mpsc`. Once this is
//! done, the new thread continues to process the work queue and the original
//! thread is able to block. Once it finishes processing the blocking future, the
//! thread has no additional work and is inserted into the backup pool. This
//! makes it available to other workers that encounter a [`blocking`] call.
//!
//! [`blocking`]: fn.blocking.html
//! [`runtime`]: https://docs.rs/tokio/0.1/tokio/runtime/

extern crate tokio_executor;

extern crate crossbeam_deque;
extern crate crossbeam_queue;
extern crate crossbeam_utils;
#[macro_use]
extern crate futures;
extern crate num_cpus;
extern crate rand;
extern crate slab;

#[macro_use]
extern crate log;

// ## Crate layout
//
// The primary type, `Pool`, holds the majority of a thread pool's state,
// including the state for each worker. Each worker's state is maintained in an
// instance of `worker::Entry`.
//
// `Worker` contains the logic that runs on each worker thread. It holds an
// `Arc` to `Pool` and is able to access its state from `Pool`.
//
// `Task` is a harness around an individual future. It manages polling and
// scheduling that future.
//
// ## Sleeping workers
//
// Sleeping workers are tracked using a [Treiber stack]. This results in the
// thread that most recently went to sleep getting woken up first. When the pool
// is not under load, this helps threads shutdown faster.
//
// Sleeping is done by using `tokio_executor::Park` implementations. This allows
// the user of the thread pool to customize the work that is performed to sleep.
// This is how injecting timers and other functionality into the thread pool is
// done.
//
// ## Notifying workers
//
// When there is work to be done, workers must be notified. However, notifying a
// worker requires cross thread coordination. Ideally, a worker would only be
// notified when it is sleeping, but there is no way to know if a worker is
// sleeping without cross thread communication.
//
// The two cases when a worker might need to be notified are:
//
// 1. A task is externally submitted to a worker via the mpsc channel.
// 2. A worker has a back log of work and needs other workers to steal from it.
//
// In the first case, the worker will always be notified. However, it could be
// possible to avoid the notification if the mpsc channel has two or greater
// number of tasks *after* the task is submitted. In this case, we are able to
// assume that the worker has previously been notified.
//
// The second case is trickier. Currently, whenever a worker spawns a new future
// (pushing it onto its deque) and when it pops a future from its mpsc, it tries
// to notify a sleeping worker to wake up and start stealing. This is a lot of
// notification and it **might** be possible to reduce it.
//
// Also, whenever a worker is woken up via a signal and it does find work, it,
// in turn, will try to wake up a new worker.
//
// [Treiber stack]: https://en.wikipedia.org/wiki/Treiber_Stack

pub mod park;

mod blocking;
mod builder;
mod callback;
mod config;
mod notifier;
mod pool;
mod sender;
mod shutdown;
mod task;
mod thread_pool;
mod worker;

pub use blocking::{blocking, BlockingError};
pub use builder::Builder;
pub use sender::Sender;
pub use shutdown::Shutdown;
pub use thread_pool::{ThreadPool, SpawnHandle};
pub use worker::{Worker, WorkerId};
<|endoftext|>


<commit_before>//! In rust-analyzer, syntax trees are transient objects.
//!
//! That means that we create trees when we need them, and tear them down to
//! save memory. In this architecture, hanging on to a particular syntax node
//! for a long time is ill-advisable, as that keeps the whole tree resident.
//!
//! Instead, we provide a [`SyntaxNodePtr`] type, which stores information about
//! *location* of a particular syntax node in a tree. Its a small type which can
//! be cheaply stored, and which can be resolved to a real [`SyntaxNode`] when
//! necessary.

use std::{
    hash::{Hash, Hasher},
    iter::successors,
    marker::PhantomData,
};

use crate::{AstNode, SyntaxKind, SyntaxNode, TextRange};

/// A pointer to a syntax node inside a file. It can be used to remember a
/// specific node across reparses of the same file.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SyntaxNodePtr {
    // Don't expose this field further. At some point, we might want to replace
    // range with node id.
    pub(crate) range: TextRange,
    kind: SyntaxKind,
}

impl SyntaxNodePtr {
    pub fn new(node: &SyntaxNode) -> SyntaxNodePtr {
        SyntaxNodePtr { range: node.text_range(), kind: node.kind() }
    }

    pub fn to_node(&self, root: &SyntaxNode) -> SyntaxNode {
        assert!(root.parent().is_none());
        successors(Some(root.clone()), |node| {
            node.children().find(|it| it.text_range().contains_range(self.range))
        })
        .find(|it| it.text_range() == self.range && it.kind() == self.kind)
        .unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self))
    }

    pub fn cast<N: AstNode>(self) -> Option<AstPtr<N>> {
        if !N::can_cast(self.kind) {
            return None;
        }
        Some(AstPtr { raw: self, _ty: PhantomData })
    }
}

/// Like `SyntaxNodePtr`, but remembers the type of node
#[derive(Debug)]
pub struct AstPtr<N: AstNode> {
    raw: SyntaxNodePtr,
    _ty: PhantomData<fn() -> N>,
}

impl<N: AstNode> Clone for AstPtr<N> {
    fn clone(&self) -> AstPtr<N> {
        AstPtr { raw: self.raw.clone(), _ty: PhantomData }
    }
}

impl<N: AstNode> Eq for AstPtr<N> {}

impl<N: AstNode> PartialEq for AstPtr<N> {
    fn eq(&self, other: &AstPtr<N>) -> bool {
        self.raw == other.raw
    }
}

impl<N: AstNode> Hash for AstPtr<N> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.raw.hash(state)
    }
}

impl<N: AstNode> AstPtr<N> {
    pub fn new(node: &N) -> AstPtr<N> {
        AstPtr { raw: SyntaxNodePtr::new(node.syntax()), _ty: PhantomData }
    }

    pub fn to_node(&self, root: &SyntaxNode) -> N {
        let syntax_node = self.raw.to_node(root);
        N::cast(syntax_node).unwrap()
    }

    pub fn syntax_node_ptr(&self) -> SyntaxNodePtr {
        self.raw.clone()
    }

    pub fn cast<U: AstNode>(self) -> Option<AstPtr<U>> {
        if !U::can_cast(self.raw.kind) {
            return None;
        }
        Some(AstPtr { raw: self.raw, _ty: PhantomData })
    }
}

impl<N: AstNode> From<AstPtr<N>> for SyntaxNodePtr {
    fn from(ptr: AstPtr<N>) -> SyntaxNodePtr {
        ptr.raw
    }
}

#[test]
fn test_local_syntax_ptr() {
    use crate::{ast, AstNode, SourceFile};

    let file = SourceFile::parse("struct Foo { f: u32, }").ok().unwrap();
    let field = file.syntax().descendants().find_map(ast::RecordField::cast).unwrap();
    let ptr = SyntaxNodePtr::new(field.syntax());
    let field_syntax = ptr.to_node(file.syntax());
    assert_eq!(field.syntax(), &field_syntax);
}
<commit_msg>feature: massively improve performance for large files<commit_after>//! In rust-analyzer, syntax trees are transient objects.
//!
//! That means that we create trees when we need them, and tear them down to
//! save memory. In this architecture, hanging on to a particular syntax node
//! for a long time is ill-advisable, as that keeps the whole tree resident.
//!
//! Instead, we provide a [`SyntaxNodePtr`] type, which stores information about
//! *location* of a particular syntax node in a tree. Its a small type which can
//! be cheaply stored, and which can be resolved to a real [`SyntaxNode`] when
//! necessary.

use std::{
    hash::{Hash, Hasher},
    iter::successors,
    marker::PhantomData,
};

use crate::{AstNode, SyntaxKind, SyntaxNode, TextRange};

/// A pointer to a syntax node inside a file. It can be used to remember a
/// specific node across reparses of the same file.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SyntaxNodePtr {
    // Don't expose this field further. At some point, we might want to replace
    // range with node id.
    pub(crate) range: TextRange,
    kind: SyntaxKind,
}

impl SyntaxNodePtr {
    pub fn new(node: &SyntaxNode) -> SyntaxNodePtr {
        SyntaxNodePtr { range: node.text_range(), kind: node.kind() }
    }

    pub fn to_node(&self, root: &SyntaxNode) -> SyntaxNode {
        assert!(root.parent().is_none());
        successors(Some(root.clone()), |node| {
            node.child_or_token_at_range(self.range).and_then(|it| it.into_node())
        })
        .find(|it| it.text_range() == self.range && it.kind() == self.kind)
        .unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self))
    }

    pub fn cast<N: AstNode>(self) -> Option<AstPtr<N>> {
        if !N::can_cast(self.kind) {
            return None;
        }
        Some(AstPtr { raw: self, _ty: PhantomData })
    }
}

/// Like `SyntaxNodePtr`, but remembers the type of node
#[derive(Debug)]
pub struct AstPtr<N: AstNode> {
    raw: SyntaxNodePtr,
    _ty: PhantomData<fn() -> N>,
}

impl<N: AstNode> Clone for AstPtr<N> {
    fn clone(&self) -> AstPtr<N> {
        AstPtr { raw: self.raw.clone(), _ty: PhantomData }
    }
}

impl<N: AstNode> Eq for AstPtr<N> {}

impl<N: AstNode> PartialEq for AstPtr<N> {
    fn eq(&self, other: &AstPtr<N>) -> bool {
        self.raw == other.raw
    }
}

impl<N: AstNode> Hash for AstPtr<N> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.raw.hash(state)
    }
}

impl<N: AstNode> AstPtr<N> {
    pub fn new(node: &N) -> AstPtr<N> {
        AstPtr { raw: SyntaxNodePtr::new(node.syntax()), _ty: PhantomData }
    }

    pub fn to_node(&self, root: &SyntaxNode) -> N {
        let syntax_node = self.raw.to_node(root);
        N::cast(syntax_node).unwrap()
    }

    pub fn syntax_node_ptr(&self) -> SyntaxNodePtr {
        self.raw.clone()
    }

    pub fn cast<U: AstNode>(self) -> Option<AstPtr<U>> {
        if !U::can_cast(self.raw.kind) {
            return None;
        }
        Some(AstPtr { raw: self.raw, _ty: PhantomData })
    }
}

impl<N: AstNode> From<AstPtr<N>> for SyntaxNodePtr {
    fn from(ptr: AstPtr<N>) -> SyntaxNodePtr {
        ptr.raw
    }
}

#[test]
fn test_local_syntax_ptr() {
    use crate::{ast, AstNode, SourceFile};

    let file = SourceFile::parse("struct Foo { f: u32, }").ok().unwrap();
    let field = file.syntax().descendants().find_map(ast::RecordField::cast).unwrap();
    let ptr = SyntaxNodePtr::new(field.syntax());
    let field_syntax = ptr.to_node(file.syntax());
    assert_eq!(field.syntax(), &field_syntax);
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use crate::error::Result;
use crate::error_reporting::LSPErrorReporter;
use crate::lsp::{
    set_ready_status, show_info_message, Connection, DidChangeTextDocument, DidCloseTextDocument,
    DidOpenTextDocument, Exit, InitializeParams, LSPBridgeMessage, Message, Notification, Request,
    ServerCapabilities, ServerNotification, ServerRequest, ServerRequestId, ServerResponse,
    Shutdown, TextDocumentSyncCapability, TextDocumentSyncKind,
};
use common::{ConsoleLogger, PerfLogger};
use log::info;
use relay_compiler::compiler::Compiler;
use relay_compiler::config::Config;
use std::sync::Arc;
use tokio::sync::{mpsc, Notify};

use crate::text_documents::extract_graphql_sources;

/// Initializes an LSP connection, handling the `initialize` message and `initialized` notification
/// handshake.
pub fn initialize(connection: &Connection) -> Result<InitializeParams> {
    let mut server_capabilities = ServerCapabilities::default();
    // Enable text document syncing so we can know when files are opened/changed/saved/closed
    server_capabilities.text_document_sync =
        Some(TextDocumentSyncCapability::Kind(TextDocumentSyncKind::Full));

    /* TODO: Re-enable auto-complete
    server_capabilities.completion_provider = Some(CompletionOptions {
        resolve_provider: Some(true),
        trigger_characters: None,
        work_done_progress_options: WorkDoneProgressOptions {
            work_done_progress: None,
        },
    });
    */

    let server_capabilities = serde_json::to_value(&server_capabilities)?;
    let params = connection.initialize(server_capabilities)?;
    let params: InitializeParams = serde_json::from_value(params)?;
    Ok(params)
}

/// Run the main server loop
pub async fn run<TPerfLogger>(
    connection: Connection,
    mut config: Config,
    _params: InitializeParams,
    _perf_logger: Arc<TPerfLogger>,
) -> Result<()>
where
    TPerfLogger: PerfLogger + 'static,
{
    show_info_message("Relay Language Server Started", &connection)?;
    info!("Running language server");
    let receiver = connection.receiver.clone();
    let sender = connection.sender.clone();

    // A `Notify` instance used to signal that the compiler should be initialized.
    let compiler_notify = Arc::new(Notify::new());
    let compiler_notify_clone = compiler_notify.clone();
    let mut has_notified = false;
    let mut on_opened_document = move |text: &String| {
        if !has_notified {
            if extract_graphql_sources(text).is_some() {
                has_notified = true;
                compiler_notify_clone.notify();
            }
        }
    };

    // A channel to communicate between the LSP message loop and the compiler loop
    let (mut lsp_tx, _lsp_rx) = mpsc::channel::<LSPBridgeMessage>(100);

    tokio::spawn(async move {
        for msg in receiver {
            info!("Received LSP message\n{:?}", msg);
            match msg {
                Message::Request(req) => {
                    /* TODO: Re-enable auto-complete
                    // Auto-complete request
                    if req.method == Completion::METHOD {
                        let (request_id, params) = extract_request_params::<Completion>(req);
                        lsp_tx
                            .send(LSPBridgeMessage::CompletionRequest { request_id, params })
                            .await
                            .ok();
                    }
                    */
                    if req.method == Shutdown::METHOD {
                        let (request_id, _) = extract_request_params::<Shutdown>(req);
                        let response = ServerResponse {
                            id: request_id,
                            error: None,
                            result: None,
                        };
                        sender.send(Message::Response(response)).ok();
                        // TODO: We should exit when receiving Exit notification according to the protocol,
                        // but the notification is never received.
                        std::process::exit(0);
                    }
                }
                Message::Notification(notif) => {
                    match &notif.method {
                        method if method == DidOpenTextDocument::METHOD => {
                            let params = extract_notif_params::<DidOpenTextDocument>(notif);
                            on_opened_document(&params.text_document.text);
                            lsp_tx
                                .send(LSPBridgeMessage::DidOpenTextDocument(params))
                                .await
                                .ok();
                        }
                        method if method == DidChangeTextDocument::METHOD => {
                            let params = extract_notif_params::<DidChangeTextDocument>(notif);
                            lsp_tx
                                .send(LSPBridgeMessage::DidChangeTextDocument(params))
                                .await
                                .ok();
                        }
                        method if method == DidCloseTextDocument::METHOD => {
                            let params = extract_notif_params::<DidCloseTextDocument>(notif);
                            lsp_tx
                                .send(LSPBridgeMessage::DidCloseTextDocument(params))
                                .await
                                .ok();
                        }
                        method if method == Exit::METHOD => {
                            std::process::exit(0);
                        }
                        _ => {
                            // Notifications we don't care about
                        }
                    }
                }
                Message::Response(_) => {
                    // Ignore responses for now
                }
            }
        }
    });

    info!("Waiting for compiler to initialize...");
    compiler_notify.notified().await;
    info!("Compiler has initialized");
    set_ready_status(&connection.sender);

    config.error_reporter = Box::new(LSPErrorReporter::new(
        config.root_dir.clone(),
        connection.sender.clone(),
    ));
    let compiler = Compiler::new(config, Arc::new(ConsoleLogger));
    compiler.watch().await.unwrap();
    Ok(())
}

fn extract_notif_params<N>(notif: ServerNotification) -> N::Params
where
    N: Notification,
{
    notif.extract(N::METHOD).unwrap()
}

fn extract_request_params<R>(req: ServerRequest) -> (ServerRequestId, R::Params)
where
    R: Request,
{
    req.extract(R::METHOD).unwrap()
}
<commit_msg>- log LSP messages and compiler performance<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use crate::error::Result;
use crate::error_reporting::LSPErrorReporter;
use crate::lsp::{
    set_ready_status, show_info_message, Connection, DidChangeTextDocument, DidCloseTextDocument,
    DidOpenTextDocument, Exit, InitializeParams, LSPBridgeMessage, Message, Notification, Request,
    ServerCapabilities, ServerNotification, ServerRequest, ServerRequestId, ServerResponse,
    Shutdown, TextDocumentSyncCapability, TextDocumentSyncKind,
};
use common::{PerfLogEvent, PerfLogger};
use log::info;
use relay_compiler::compiler::Compiler;
use relay_compiler::config::Config;
use std::sync::Arc;
use tokio::sync::{mpsc, Notify};

use crate::text_documents::extract_graphql_sources;

/// Initializes an LSP connection, handling the `initialize` message and `initialized` notification
/// handshake.
pub fn initialize(connection: &Connection) -> Result<InitializeParams> {
    let mut server_capabilities = ServerCapabilities::default();
    // Enable text document syncing so we can know when files are opened/changed/saved/closed
    server_capabilities.text_document_sync =
        Some(TextDocumentSyncCapability::Kind(TextDocumentSyncKind::Full));

    /* TODO: Re-enable auto-complete
    server_capabilities.completion_provider = Some(CompletionOptions {
        resolve_provider: Some(true),
        trigger_characters: None,
        work_done_progress_options: WorkDoneProgressOptions {
            work_done_progress: None,
        },
    });
    */

    let server_capabilities = serde_json::to_value(&server_capabilities)?;
    let params = connection.initialize(server_capabilities)?;
    let params: InitializeParams = serde_json::from_value(params)?;
    Ok(params)
}

/// Run the main server loop
pub async fn run<TPerfLogger>(
    connection: Connection,
    mut config: Config,
    _params: InitializeParams,
    perf_logger: Arc<TPerfLogger>,
) -> Result<()>
where
    TPerfLogger: PerfLogger + 'static,
{
    show_info_message("Relay Language Server Started", &connection)?;
    info!("Running language server");
    let receiver = connection.receiver.clone();
    let sender = connection.sender.clone();

    // A `Notify` instance used to signal that the compiler should be initialized.
    let compiler_notify = Arc::new(Notify::new());
    let compiler_notify_clone = compiler_notify.clone();
    let mut has_notified = false;
    let mut on_opened_document = move |text: &String| {
        if !has_notified {
            if extract_graphql_sources(text).is_some() {
                has_notified = true;
                compiler_notify_clone.notify();
            }
        }
    };

    // A channel to communicate between the LSP message loop and the compiler loop
    let (mut lsp_tx, _lsp_rx) = mpsc::channel::<LSPBridgeMessage>(100);
    let logger_for_process = Arc::clone(&perf_logger);

    tokio::spawn(async move {
        for msg in receiver {
            let perf_logger_msg_event = logger_for_process.create_event("lsp_message");
            info!("Received LSP message\n{:?}", msg);
            match msg {
                Message::Request(req) => {
                    /* TODO: Re-enable auto-complete
                    // Auto-complete request
                    if req.method == Completion::METHOD {
                        let (request_id, params) = extract_request_params::<Completion>(req);
                        lsp_tx
                            .send(LSPBridgeMessage::CompletionRequest { request_id, params })
                            .await
                            .ok();
                    }
                    */
                    if req.method == Shutdown::METHOD {
                        perf_logger_msg_event.string("method", req.method.clone());
                        logger_for_process.complete_event(perf_logger_msg_event);
                        logger_for_process.flush();
                        let (request_id, _) = extract_request_params::<Shutdown>(req);
                        let response = ServerResponse {
                            id: request_id,
                            error: None,
                            result: None,
                        };
                        sender.send(Message::Response(response)).ok();
                        // TODO: We should exit when receiving Exit notification according to the protocol,
                        // but the notification is never received.
                        std::process::exit(0);
                    }
                }
                Message::Notification(notif) => {
                    let mut should_flush_perf_log_event = true;
                    perf_logger_msg_event.string("method", notif.method.clone());
                    let lsp_message_processing_time =
                        perf_logger_msg_event.start("lsp_message_processing_time");

                    match &notif.method {
                        method if method == DidOpenTextDocument::METHOD => {
                            let params = extract_notif_params::<DidOpenTextDocument>(notif);
                            on_opened_document(&params.text_document.text);
                            lsp_tx
                                .send(LSPBridgeMessage::DidOpenTextDocument(params))
                                .await
                                .ok();
                        }
                        method if method == DidChangeTextDocument::METHOD => {
                            let params = extract_notif_params::<DidChangeTextDocument>(notif);
                            lsp_tx
                                .send(LSPBridgeMessage::DidChangeTextDocument(params))
                                .await
                                .ok();
                        }
                        method if method == DidCloseTextDocument::METHOD => {
                            let params = extract_notif_params::<DidCloseTextDocument>(notif);
                            lsp_tx
                                .send(LSPBridgeMessage::DidCloseTextDocument(params))
                                .await
                                .ok();
                        }
                        method if method == Exit::METHOD => {
                            perf_logger_msg_event.stop(lsp_message_processing_time);
                            logger_for_process.complete_event(perf_logger_msg_event);
                            logger_for_process.flush();
                            std::process::exit(0);
                        }
                        _ => {
                            should_flush_perf_log_event = false;
                            // Notifications we don't care about
                        }
                    }
                    if should_flush_perf_log_event {
                        perf_logger_msg_event.stop(lsp_message_processing_time);
                        logger_for_process.complete_event(perf_logger_msg_event);
                        logger_for_process.flush();
                    }
                }
                Message::Response(_) => {
                    // Ignore responses for now
                }
            }
        }
    });

    info!("Waiting for compiler to initialize...");
    compiler_notify.notified().await;
    info!("Compiler has initialized");
    set_ready_status(&connection.sender);

    config.error_reporter = Box::new(LSPErrorReporter::new(
        config.root_dir.clone(),
        connection.sender.clone(),
    ));
    let compiler = Compiler::new(config, Arc::clone(&perf_logger));
    compiler.watch().await.unwrap();
    Ok(())
}

fn extract_notif_params<N>(notif: ServerNotification) -> N::Params
where
    N: Notification,
{
    notif.extract(N::METHOD).unwrap()
}

fn extract_request_params<R>(req: ServerRequest) -> (ServerRequestId, R::Params)
where
    R: Request,
{
    req.extract(R::METHOD).unwrap()
}
<|endoftext|>


<commit_before><commit_msg>Add player name validation<commit_after><|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A type representing either success or failure

#[allow(missing_doc)];

use clone::Clone;
use cmp::Eq;
use either;
use iterator::Iterator;
use option::{None, Option, Some};
use vec;
use vec::{OwnedVector, ImmutableVector};
use container::Container;
use to_str::ToStr;
use str::StrSlice;

/// `Result` is a type that represents either success (`Ok`) or failure (`Err`).
///
/// In order to provide informative error messages, `E` is reqired to implement `ToStr`.
/// It is further recommended for `E` to be a descriptive error type, eg a `enum` for
/// all possible errors cases.
#[deriving(Clone, Eq)]
pub enum Result<T, E> {
    /// Contains the successful result value
    Ok(T),
    /// Contains the error value
    Err(E)
}

impl<T, E: ToStr> Result<T, E> {
    /// Convert to the `either` type
    ///
    /// `Ok` result variants are converted to `either::Right` variants, `Err`
    /// result variants are converted to `either::Left`.
    #[inline]
    pub fn to_either(self)-> either::Either<E, T>{
        match self {
            Ok(t) => either::Right(t),
            Err(e) => either::Left(e),
        }
    }

    /// Get a reference to the value out of a successful result
    ///
    /// # Failure
    ///
    /// If the result is an error
    #[inline]
    pub fn get_ref<'a>(&'a self) -> &'a T {
        match *self {
            Ok(ref t) => t,
            Err(ref e) => fail!("called `Result::get_ref()` on `Err` value: %s", e.to_str()),
        }
    }

    /// Returns true if the result is `Ok`
    #[inline]
    pub fn is_ok(&self) -> bool {
        match *self {
            Ok(_) => true,
            Err(_) => false
        }
    }

    /// Returns true if the result is `Err`
    #[inline]
    pub fn is_err(&self) -> bool {
        !self.is_ok()
    }

    /// Call a method based on a previous result
    ///
    /// If `self` is `Ok` then the value is extracted and passed to `op`
    /// whereupon `op`s result is returned. if `self` is `Err` then it is
    /// immediately returned. This function can be used to compose the results
    /// of two functions.
    ///
    /// Example:
    ///
    ///     do read_file(file).iter |buf| {
    ///         print_buf(buf)
    ///     }
    #[inline]
    pub fn iter(&self, f: &fn(&T)) {
        match *self {
            Ok(ref t) => f(t),
            Err(_) => (),
        }
    }

    /// Call a method based on a previous result
    ///
    /// If `self` is `Err` then the value is extracted and passed to `op`
    /// whereupon `op`s result is returned. if `self` is `Ok` then it is
    /// immediately returned.  This function can be used to pass through a
    /// successful result while handling an error.
    #[inline]
    pub fn iter_err(&self, f: &fn(&E)) {
        match *self {
            Ok(_) => (),
            Err(ref e) => f(e),
        }
    }

    /// Unwraps a result, yielding the content of an `Ok`.
    /// Fails if the value is a `Err` with an error message derived
    /// from `E`'s `ToStr` implementation.
    #[inline]
    pub fn unwrap(self) -> T {
        match self {
            Ok(t) => t,
            Err(e) => fail!("called `Result::unwrap()` on `Err` value: %s", e.to_str()),
        }
    }

    /// Unwraps a result, yielding the content of an `Err`.
    /// Fails if the value is a `Ok`.
    #[inline]
    pub fn unwrap_err(self) -> E {
        self.expect_err("called `Result::unwrap_err()` on `Ok` value")
    }

    /// Unwraps a result, yielding the content of an `Ok`.
    /// Fails if the value is a `Err` with a custom failure message.
    #[inline]
    pub fn expect(self, reason: &str) -> T {
        match self {
            Ok(t) => t,
            Err(_) => fail!(reason.to_owned()),
        }
    }

    /// Unwraps a result, yielding the content of an `Err`
    /// Fails if the value is a `Ok` with a custom failure message.
    #[inline]
    pub fn expect_err(self, reason: &str) -> E {
        match self {
            Err(e) => e,
            Ok(_) => fail!(reason.to_owned()),
        }
    }

    /// Call a method based on a previous result
    ///
    /// If `self` is `Ok` then the value is extracted and passed to `op`
    /// whereupon `op`s result is returned. if `self` is `Err` then it is
    /// immediately returned. This function can be used to compose the results
    /// of two functions.
    ///
    /// Example:
    ///
    ///     let res = do read_file(file) |buf| {
    ///         Ok(parse_bytes(buf))
    ///     };
    #[inline]
    pub fn chain<U>(self, op: &fn(T) -> Result<U, E>) -> Result<U, E> {
        match self {
            Ok(t) => op(t),
            Err(e) => Err(e),
        }
    }

    /// Call a function based on a previous result
    ///
    /// If `self` is `Err` then the value is extracted and passed to `op`
    /// whereupon `op`s result is returned. if `self` is `Ok` then it is
    /// immediately returned.  This function can be used to pass through a
    /// successful result while handling an error.
    #[inline]
    pub fn chain_err<F>(self, op: &fn(E) -> Result<T, F>) -> Result<T, F> {
        match self {
            Ok(t) => Ok(t),
            Err(e) => op(e),
        }
    }
}

impl<T: Clone, E: ToStr> Result<T, E> {
    /// Call a method based on a previous result
    ///
    /// If `self` is `Err` then the value is extracted and passed to `op`
    /// whereupon `op`s result is wrapped in an `Err` and returned. if `self` is
    /// `Ok` then it is immediately returned.  This function can be used to pass
    /// through a successful result while handling an error.
    #[inline]
    pub fn map_err<F: Clone>(&self, op: &fn(&E) -> F) -> Result<T,F> {
        match *self {
            Ok(ref t) => Ok(t.clone()),
            Err(ref e) => Err(op(e))
        }
    }
}

impl<T, E: Clone + ToStr> Result<T, E> {
    /// Call a method based on a previous result
    ///
    /// If `self` is `Ok` then the value is extracted and passed to `op`
    /// whereupon `op`s result is wrapped in `Ok` and returned. if `self` is
    /// `Err` then it is immediately returned.  This function can be used to
    /// compose the results of two functions.
    ///
    /// Example:
    ///
    ///     let res = do read_file(file).map |buf| {
    ///         parse_bytes(buf)
    ///     };
    #[inline]
    pub fn map<U: Clone>(&self, op: &fn(&T) -> U) -> Result<U,E> {
        match *self {
            Ok(ref t) => Ok(op(t)),
            Err(ref e) => Err(e.clone())
        }
    }
}

#[inline]
#[allow(missing_doc)]
pub fn map_opt<T, U: ToStr, V>(o_t: &Option<T>,
                               op: &fn(&T) -> Result<V,U>) -> Result<Option<V>,U> {
    match *o_t {
        None => Ok(None),
        Some(ref t) => match op(t) {
            Ok(v) => Ok(Some(v)),
            Err(e) => Err(e)
        }
    }
}

// FIXME: #8228 Replaceable by an external iterator?
/// Maps each element in the vector `ts` using the operation `op`.  Should an
/// error occur, no further mappings are performed and the error is returned.
/// Should no error occur, a vector containing the result of each map is
/// returned.
///
/// Here is an example which increments every integer in a vector,
/// checking for overflow:
///
///     fn inc_conditionally(x: uint) -> result<uint,str> {
///         if x == uint::max_value { return Err("overflow"); }
///         else { return Ok(x+1u); }
///     }
///     map(~[1u, 2u, 3u], inc_conditionally).chain {|incd|
///         assert!(incd == ~[2u, 3u, 4u]);
///     }
#[inline]
pub fn map_vec<T,U,V>(ts: &[T], op: &fn(&T) -> Result<V,U>)
                      -> Result<~[V],U> {
    let mut vs: ~[V] = vec::with_capacity(ts.len());
    for t in ts.iter() {
        match op(t) {
          Ok(v) => vs.push(v),
          Err(u) => return Err(u)
        }
    }
    return Ok(vs);
}

// FIXME: #8228 Replaceable by an external iterator?
/// Same as map, but it operates over two parallel vectors.
///
/// A precondition is used here to ensure that the vectors are the same
/// length.  While we do not often use preconditions in the standard
/// library, a precondition is used here because result::t is generally
/// used in 'careful' code contexts where it is both appropriate and easy
/// to accommodate an error like the vectors being of different lengths.
#[inline]
pub fn map_vec2<S, T, U: ToStr, V>(ss: &[S], ts: &[T],
                                   op: &fn(&S,&T) -> Result<V,U>) -> Result<~[V],U> {
    assert!(vec::same_length(ss, ts));
    let n = ts.len();
    let mut vs = vec::with_capacity(n);
    let mut i = 0u;
    while i < n {
        match op(&ss[i],&ts[i]) {
          Ok(v) => vs.push(v),
          Err(u) => return Err(u)
        }
        i += 1u;
    }
    return Ok(vs);
}

// FIXME: #8228 Replaceable by an external iterator?
/// Applies op to the pairwise elements from `ss` and `ts`, aborting on
/// error.  This could be implemented using `map_zip()` but it is more efficient
/// on its own as no result vector is built.
#[inline]
pub fn iter_vec2<S, T, U: ToStr>(ss: &[S], ts: &[T],
                                 op: &fn(&S,&T) -> Result<(),U>) -> Result<(),U> {
    assert!(vec::same_length(ss, ts));
    let n = ts.len();
    let mut i = 0u;
    while i < n {
        match op(&ss[i],&ts[i]) {
          Ok(()) => (),
          Err(u) => return Err(u)
        }
        i += 1u;
    }
    return Ok(());
}

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

    pub fn op1() -> Result<int, ~str> { Ok(666) }

    pub fn op2(i: int) -> Result<uint, ~str> {
        Ok(i as uint + 1u)
    }

    pub fn op3() -> Result<int, ~str> { Err(~"sadface") }

    #[test]
    pub fn chain_success() {
        assert_eq!(op1().chain(op2).unwrap(), 667u);
    }

    #[test]
    pub fn chain_failure() {
        assert_eq!(op3().chain( op2).unwrap_err(), ~"sadface");
    }

    #[test]
    pub fn test_impl_iter() {
        let mut valid = false;
        Ok::<~str, ~str>(~"a").iter(|_x| valid = true);
        assert!(valid);

        Err::<~str, ~str>(~"b").iter(|_x| valid = false);
        assert!(valid);
    }

    #[test]
    pub fn test_impl_iter_err() {
        let mut valid = true;
        Ok::<~str, ~str>(~"a").iter_err(|_x| valid = false);
        assert!(valid);

        valid = false;
        Err::<~str, ~str>(~"b").iter_err(|_x| valid = true);
        assert!(valid);
    }

    #[test]
    pub fn test_impl_map() {
        assert_eq!(Ok::<~str, ~str>(~"a").map(|_x| ~"b"), Ok(~"b"));
        assert_eq!(Err::<~str, ~str>(~"a").map(|_x| ~"b"), Err(~"a"));
    }

    #[test]
    pub fn test_impl_map_err() {
        assert_eq!(Ok::<~str, ~str>(~"a").map_err(|_x| ~"b"), Ok(~"a"));
        assert_eq!(Err::<~str, ~str>(~"a").map_err(|_x| ~"b"), Err(~"b"));
    }

    #[test]
    pub fn test_get_ref_method() {
        let foo: Result<int, ()> = Ok(100);
        assert_eq!(*foo.get_ref(), 100);
    }

    #[test]
    pub fn test_to_either() {
        let r: Result<int, ()> = Ok(100);
        let err: Result<(), int> = Err(404);

        assert_eq!(r.to_either(), either::Right(100));
        assert_eq!(err.to_either(), either::Left(404));
    }
}
<commit_msg>std: Convert Result to use external iterators<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A type representing either success or failure

#[allow(missing_doc)];

use clone::Clone;
use cmp::Eq;
use either;
use iterator::Iterator;
use option::{None, Option, Some, OptionIterator};
use vec;
use vec::{OwnedVector, ImmutableVector};
use container::Container;
use to_str::ToStr;
use str::StrSlice;

/// `Result` is a type that represents either success (`Ok`) or failure (`Err`).
///
/// In order to provide informative error messages, `E` is reqired to implement `ToStr`.
/// It is further recommended for `E` to be a descriptive error type, eg a `enum` for
/// all possible errors cases.
#[deriving(Clone, Eq)]
pub enum Result<T, E> {
    /// Contains the successful result value
    Ok(T),
    /// Contains the error value
    Err(E)
}

impl<T, E: ToStr> Result<T, E> {
    /// Convert to the `either` type
    ///
    /// `Ok` result variants are converted to `either::Right` variants, `Err`
    /// result variants are converted to `either::Left`.
    #[inline]
    pub fn to_either(self)-> either::Either<E, T>{
        match self {
            Ok(t) => either::Right(t),
            Err(e) => either::Left(e),
        }
    }

    /// Get a reference to the value out of a successful result
    ///
    /// # Failure
    ///
    /// If the result is an error
    #[inline]
    pub fn get_ref<'a>(&'a self) -> &'a T {
        match *self {
            Ok(ref t) => t,
            Err(ref e) => fail!("called `Result::get_ref()` on `Err` value: %s", e.to_str()),
        }
    }

    /// Returns true if the result is `Ok`
    #[inline]
    pub fn is_ok(&self) -> bool {
        match *self {
            Ok(_) => true,
            Err(_) => false
        }
    }

    /// Returns true if the result is `Err`
    #[inline]
    pub fn is_err(&self) -> bool {
        !self.is_ok()
    }

    /// Call a method based on a previous result
    ///
    /// If `self` is `Ok` then the value is extracted and passed to `op`
    /// whereupon `op`s result is returned. if `self` is `Err` then it is
    /// immediately returned. This function can be used to compose the results
    /// of two functions.
    ///
    /// Example:
    ///
    ///     for buf in read_file(file) {
    ///         print_buf(buf)
    ///     }
    #[inline]
    pub fn iter<'r>(&'r self) -> OptionIterator<&'r T> {
        match *self {
            Ok(ref t) => Some(t),
            Err(*) => None,
        }.consume_iter()
    }

    /// Call a method based on a previous result
    ///
    /// If `self` is `Err` then the value is extracted and passed to `op`
    /// whereupon `op`s result is returned. if `self` is `Ok` then it is
    /// immediately returned.  This function can be used to pass through a
    /// successful result while handling an error.
    #[inline]
    pub fn iter_err<'r>(&'r self) -> OptionIterator<&'r E> {
        match *self {
            Ok(*) => None,
            Err(ref t) => Some(t),
        }.consume_iter()
    }

    /// Unwraps a result, yielding the content of an `Ok`.
    /// Fails if the value is a `Err` with an error message derived
    /// from `E`'s `ToStr` implementation.
    #[inline]
    pub fn unwrap(self) -> T {
        match self {
            Ok(t) => t,
            Err(e) => fail!("called `Result::unwrap()` on `Err` value: %s", e.to_str()),
        }
    }

    /// Unwraps a result, yielding the content of an `Err`.
    /// Fails if the value is a `Ok`.
    #[inline]
    pub fn unwrap_err(self) -> E {
        self.expect_err("called `Result::unwrap_err()` on `Ok` value")
    }

    /// Unwraps a result, yielding the content of an `Ok`.
    /// Fails if the value is a `Err` with a custom failure message.
    #[inline]
    pub fn expect(self, reason: &str) -> T {
        match self {
            Ok(t) => t,
            Err(_) => fail!(reason.to_owned()),
        }
    }

    /// Unwraps a result, yielding the content of an `Err`
    /// Fails if the value is a `Ok` with a custom failure message.
    #[inline]
    pub fn expect_err(self, reason: &str) -> E {
        match self {
            Err(e) => e,
            Ok(_) => fail!(reason.to_owned()),
        }
    }

    /// Call a method based on a previous result
    ///
    /// If `self` is `Ok` then the value is extracted and passed to `op`
    /// whereupon `op`s result is returned. if `self` is `Err` then it is
    /// immediately returned. This function can be used to compose the results
    /// of two functions.
    ///
    /// Example:
    ///
    ///     let res = do read_file(file) |buf| {
    ///         Ok(parse_bytes(buf))
    ///     };
    #[inline]
    pub fn chain<U>(self, op: &fn(T) -> Result<U, E>) -> Result<U, E> {
        match self {
            Ok(t) => op(t),
            Err(e) => Err(e),
        }
    }

    /// Call a function based on a previous result
    ///
    /// If `self` is `Err` then the value is extracted and passed to `op`
    /// whereupon `op`s result is returned. if `self` is `Ok` then it is
    /// immediately returned.  This function can be used to pass through a
    /// successful result while handling an error.
    #[inline]
    pub fn chain_err<F>(self, op: &fn(E) -> Result<T, F>) -> Result<T, F> {
        match self {
            Ok(t) => Ok(t),
            Err(e) => op(e),
        }
    }
}

impl<T: Clone, E: ToStr> Result<T, E> {
    /// Call a method based on a previous result
    ///
    /// If `self` is `Err` then the value is extracted and passed to `op`
    /// whereupon `op`s result is wrapped in an `Err` and returned. if `self` is
    /// `Ok` then it is immediately returned.  This function can be used to pass
    /// through a successful result while handling an error.
    #[inline]
    pub fn map_err<F: Clone>(&self, op: &fn(&E) -> F) -> Result<T,F> {
        match *self {
            Ok(ref t) => Ok(t.clone()),
            Err(ref e) => Err(op(e))
        }
    }
}

impl<T, E: Clone + ToStr> Result<T, E> {
    /// Call a method based on a previous result
    ///
    /// If `self` is `Ok` then the value is extracted and passed to `op`
    /// whereupon `op`s result is wrapped in `Ok` and returned. if `self` is
    /// `Err` then it is immediately returned.  This function can be used to
    /// compose the results of two functions.
    ///
    /// Example:
    ///
    ///     let res = do read_file(file).map |buf| {
    ///         parse_bytes(buf)
    ///     };
    #[inline]
    pub fn map<U: Clone>(&self, op: &fn(&T) -> U) -> Result<U,E> {
        match *self {
            Ok(ref t) => Ok(op(t)),
            Err(ref e) => Err(e.clone())
        }
    }
}

#[inline]
#[allow(missing_doc)]
pub fn map_opt<T, U: ToStr, V>(o_t: &Option<T>,
                               op: &fn(&T) -> Result<V,U>) -> Result<Option<V>,U> {
    match *o_t {
        None => Ok(None),
        Some(ref t) => match op(t) {
            Ok(v) => Ok(Some(v)),
            Err(e) => Err(e)
        }
    }
}

// FIXME: #8228 Replaceable by an external iterator?
/// Maps each element in the vector `ts` using the operation `op`.  Should an
/// error occur, no further mappings are performed and the error is returned.
/// Should no error occur, a vector containing the result of each map is
/// returned.
///
/// Here is an example which increments every integer in a vector,
/// checking for overflow:
///
///     fn inc_conditionally(x: uint) -> result<uint,str> {
///         if x == uint::max_value { return Err("overflow"); }
///         else { return Ok(x+1u); }
///     }
///     map(~[1u, 2u, 3u], inc_conditionally).chain {|incd|
///         assert!(incd == ~[2u, 3u, 4u]);
///     }
#[inline]
pub fn map_vec<T,U,V>(ts: &[T], op: &fn(&T) -> Result<V,U>)
                      -> Result<~[V],U> {
    let mut vs: ~[V] = vec::with_capacity(ts.len());
    for t in ts.iter() {
        match op(t) {
          Ok(v) => vs.push(v),
          Err(u) => return Err(u)
        }
    }
    return Ok(vs);
}

// FIXME: #8228 Replaceable by an external iterator?
/// Same as map, but it operates over two parallel vectors.
///
/// A precondition is used here to ensure that the vectors are the same
/// length.  While we do not often use preconditions in the standard
/// library, a precondition is used here because result::t is generally
/// used in 'careful' code contexts where it is both appropriate and easy
/// to accommodate an error like the vectors being of different lengths.
#[inline]
pub fn map_vec2<S, T, U: ToStr, V>(ss: &[S], ts: &[T],
                                   op: &fn(&S,&T) -> Result<V,U>) -> Result<~[V],U> {
    assert!(vec::same_length(ss, ts));
    let n = ts.len();
    let mut vs = vec::with_capacity(n);
    let mut i = 0u;
    while i < n {
        match op(&ss[i],&ts[i]) {
          Ok(v) => vs.push(v),
          Err(u) => return Err(u)
        }
        i += 1u;
    }
    return Ok(vs);
}

// FIXME: #8228 Replaceable by an external iterator?
/// Applies op to the pairwise elements from `ss` and `ts`, aborting on
/// error.  This could be implemented using `map_zip()` but it is more efficient
/// on its own as no result vector is built.
#[inline]
pub fn iter_vec2<S, T, U: ToStr>(ss: &[S], ts: &[T],
                                 op: &fn(&S,&T) -> Result<(),U>) -> Result<(),U> {
    assert!(vec::same_length(ss, ts));
    let n = ts.len();
    let mut i = 0u;
    while i < n {
        match op(&ss[i],&ts[i]) {
          Ok(()) => (),
          Err(u) => return Err(u)
        }
        i += 1u;
    }
    return Ok(());
}

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

    pub fn op1() -> Result<int, ~str> { Ok(666) }

    pub fn op2(i: int) -> Result<uint, ~str> {
        Ok(i as uint + 1u)
    }

    pub fn op3() -> Result<int, ~str> { Err(~"sadface") }

    #[test]
    pub fn chain_success() {
        assert_eq!(op1().chain(op2).unwrap(), 667u);
    }

    #[test]
    pub fn chain_failure() {
        assert_eq!(op3().chain( op2).unwrap_err(), ~"sadface");
    }

    #[test]
    pub fn test_impl_iter() {
        let mut valid = false;
        let okval = Ok::<~str, ~str>(~"a");
        do okval.iter().next().map |_| { valid = true; };
        assert!(valid);

        let errval = Err::<~str, ~str>(~"b");
        do errval.iter().next().map |_| { valid = false; };
        assert!(valid);
    }

    #[test]
    pub fn test_impl_iter_err() {
        let mut valid = true;
        let okval = Ok::<~str, ~str>(~"a");
        do okval.iter_err().next().map |_| { valid = false };
        assert!(valid);

        valid = false;
        let errval = Err::<~str, ~str>(~"b");
        do errval.iter_err().next().map |_| { valid = true };
        assert!(valid);
    }

    #[test]
    pub fn test_impl_map() {
        assert_eq!(Ok::<~str, ~str>(~"a").map(|_x| ~"b"), Ok(~"b"));
        assert_eq!(Err::<~str, ~str>(~"a").map(|_x| ~"b"), Err(~"a"));
    }

    #[test]
    pub fn test_impl_map_err() {
        assert_eq!(Ok::<~str, ~str>(~"a").map_err(|_x| ~"b"), Ok(~"a"));
        assert_eq!(Err::<~str, ~str>(~"a").map_err(|_x| ~"b"), Err(~"b"));
    }

    #[test]
    pub fn test_get_ref_method() {
        let foo: Result<int, ()> = Ok(100);
        assert_eq!(*foo.get_ref(), 100);
    }

    #[test]
    pub fn test_to_either() {
        let r: Result<int, ()> = Ok(100);
        let err: Result<(), int> = Err(404);

        assert_eq!(r.to_either(), either::Right(100));
        assert_eq!(err.to_either(), either::Left(404));
    }
}
<|endoftext|>