<commit_before>// Copyright 2018 The Exonum Team
//
// 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 futures::{Future, Sink, Stream};
use futures::{stream::Wait, sync::mpsc};
use tokio_core::reactor::Core;
use tokio_timer::{TimeoutStream, Timer};

use std::net::SocketAddr;
use std::thread;
use std::time::{self, Duration};

use crypto::{gen_keypair, PublicKey, Signature};
use messages::{Connect, Message, MessageWriter, RawMessage};
use events::{NetworkEvent, NetworkRequest};
use events::network::{NetworkConfiguration, NetworkPart};
use events::error::log_error;
use node::{EventsPoolCapacity, NodeChannel};
use blockchain::ConsensusConfig;
use helpers::user_agent;

#[derive(Debug)]
pub struct TestHandler {
    handle: Option<thread::JoinHandle<()>>,
    listen_address: SocketAddr,
    network_events_rx: Wait<TimeoutStream<mpsc::Receiver<NetworkEvent>>>,
    network_requests_tx: mpsc::Sender<NetworkRequest>,
}

impl TestHandler {
    pub fn new(
        listen_address: SocketAddr,
        network_requests_tx: mpsc::Sender<NetworkRequest>,
        network_events_rx: mpsc::Receiver<NetworkEvent>,
    ) -> TestHandler {
        let timer = Timer::default();
        let receiver = timer.timeout_stream(network_events_rx, Duration::from_secs(30));
        TestHandler {
            handle: None,
            listen_address,
            network_requests_tx,
            network_events_rx: receiver.wait(),
        }
    }

    pub fn wait_for_event(&mut self) -> Result<NetworkEvent, ()> {
        let event = self.network_events_rx.next().unwrap()?;
        Ok(event)
    }

    pub fn connect_with(&self, addr: SocketAddr) {
        let connect = connect_message(self.listen_address);
        self.network_requests_tx
            .clone()
            .send(NetworkRequest::SendMessage(addr, connect.raw().clone()))
            .wait()
            .unwrap();
    }

    pub fn disconnect_with(&self, addr: SocketAddr) {
        self.network_requests_tx
            .clone()
            .send(NetworkRequest::DisconnectWithPeer(addr))
            .wait()
            .unwrap();
    }

    pub fn send_to(&self, addr: SocketAddr, raw: RawMessage) {
        self.network_requests_tx
            .clone()
            .send(NetworkRequest::SendMessage(addr, raw))
            .wait()
            .unwrap();
    }

    pub fn wait_for_connect(&mut self) -> Connect {
        match self.wait_for_event() {
            Ok(NetworkEvent::PeerConnected(_addr, connect)) => connect,
            Ok(other) => panic!("Unexpected connect received, {:?}", other),
            Err(e) => panic!("An error during wait for connect occurred, {:?}", e),
        }
    }

    pub fn wait_for_disconnect(&mut self) -> SocketAddr {
        match self.wait_for_event() {
            Ok(NetworkEvent::PeerDisconnected(addr)) => addr,
            Ok(other) => panic!("Unexpected disconnect received, {:?}", other),
            Err(e) => panic!("An error during wait for disconnect occurred, {:?}", e),
        }
    }

    pub fn wait_for_message(&mut self) -> RawMessage {
        match self.wait_for_event() {
            Ok(NetworkEvent::MessageReceived(_addr, msg)) => msg,
            Ok(other) => panic!("Unexpected message received, {:?}", other),
            Err(e) => panic!("An error during wait for message occurred, {:?}", e),
        }
    }

    pub fn shutdown(&mut self) {
        self.network_requests_tx
            .clone()
            .send(NetworkRequest::Shutdown)
            .wait()
            .unwrap();
        self.handle.take().expect("shutdown twice").join().unwrap();
    }
}

impl Drop for TestHandler {
    fn drop(&mut self) {
        if !::std::thread::panicking() {
            self.shutdown();
        }
    }
}

#[derive(Debug)]
pub struct TestEvents {
    pub listen_address: SocketAddr,
    pub network_config: NetworkConfiguration,
    pub events_config: EventsPoolCapacity,
}

impl TestEvents {
    pub fn with_addr(listen_address: SocketAddr) -> TestEvents {
        TestEvents {
            listen_address,
            network_config: NetworkConfiguration::default(),
            events_config: EventsPoolCapacity::default(),
        }
    }

    pub fn spawn(self) -> TestHandler {
        let (mut handler_part, network_part) = self.into_reactor();
        let handle = thread::spawn(move || {
            let mut core = Core::new().unwrap();
            let fut = network_part.run(&core.handle());
            core.run(fut).map_err(log_error).unwrap();
        });
        handler_part.handle = Some(handle);
        handler_part
    }

    fn into_reactor(self) -> (TestHandler, NetworkPart) {
        let channel = NodeChannel::new(&self.events_config);
        let network_config = self.network_config;
        let (network_tx, network_rx) = channel.network_events;
        let network_requests_tx = channel.network_requests.0.clone();

        let network_part = NetworkPart {
            our_connect_message: connect_message(self.listen_address),
            listen_address: self.listen_address,
            network_config,
            max_message_len: ConsensusConfig::DEFAULT_MAX_MESSAGE_LEN,
            network_requests: channel.network_requests,
            network_tx: network_tx.clone(),
        };

        let handler_part = TestHandler::new(self.listen_address, network_requests_tx, network_rx);
        (handler_part, network_part)
    }
}

pub fn connect_message(addr: SocketAddr) -> Connect {
    let time = time::UNIX_EPOCH;
    Connect::new_with_signature(
        &PublicKey::zero(),
        addr,
        time.into(),
        &user_agent::get(),
        &Signature::zero(),
    )
}

pub fn raw_message(id: u16, len: usize) -> RawMessage {
    let writer = MessageWriter::new(::messages::PROTOCOL_MAJOR_VERSION, 0, id, len);
    RawMessage::new(writer.sign(&gen_keypair().1))
}

#[test]
fn test_network_handshake() {
    let first = "127.0.0.1:17230".parse().unwrap();
    let second = "127.0.0.1:17231".parse().unwrap();

    let e1 = TestEvents::with_addr(first);
    let e2 = TestEvents::with_addr(second);

    let c1 = connect_message(first);
    let c2 = connect_message(second);

    let mut e1 = e1.spawn();
    let mut e2 = e2.spawn();

    e1.connect_with(second);
    assert_eq!(e2.wait_for_connect(), c1);

    e2.connect_with(first);
    assert_eq!(e1.wait_for_connect(), c2);

    e1.disconnect_with(second);
    assert_eq!(e1.wait_for_disconnect(), second);

    e2.disconnect_with(first);
    assert_eq!(e2.wait_for_disconnect(), first);
}

#[test]
fn test_network_big_message() {
    let first = "127.0.0.1:17200".parse().unwrap();
    let second = "127.0.0.1:17201".parse().unwrap();

    let m1 = raw_message(15, 100000);
    let m2 = raw_message(16, 400);

    let e1 = TestEvents::with_addr(first);
    let e2 = TestEvents::with_addr(second);

    let mut e1 = e1.spawn();
    let mut e2 = e2.spawn();

    e1.connect_with(second);
    e2.wait_for_connect();

    e2.connect_with(first);
    e1.wait_for_connect();

    e1.send_to(second, m1.clone());
    assert_eq!(e2.wait_for_message(), m1);

    e1.send_to(second, m2.clone());
    assert_eq!(e2.wait_for_message(), m2);

    e1.send_to(second, m1.clone());
    assert_eq!(e2.wait_for_message(), m1);

    e2.send_to(first, m2.clone());
    assert_eq!(e1.wait_for_message(), m2);

    e2.send_to(first, m1.clone());
    assert_eq!(e1.wait_for_message(), m1);

    e2.send_to(first, m2.clone());
    assert_eq!(e1.wait_for_message(), m2);

    e1.disconnect_with(second);
    assert_eq!(e1.wait_for_disconnect(), second);

    e2.disconnect_with(first);
    assert_eq!(e2.wait_for_disconnect(), first);
}

#[test]
fn test_network_max_message_len() {
    let first = "127.0.0.1:17202".parse().unwrap();
    let second = "127.0.0.1:17303".parse().unwrap();

    let max_message_length = ConsensusConfig::DEFAULT_MAX_MESSAGE_LEN as usize;
    let max_payload_length =
        max_message_length - ::messages::HEADER_LENGTH - ::crypto::SIGNATURE_LENGTH;
    let acceptable_message = raw_message(15, max_payload_length);
    let too_big_message = raw_message(16, max_payload_length + 1000);

    let e1 = TestEvents::with_addr(first);
    let e2 = TestEvents::with_addr(second);

    let mut e1 = e1.spawn();
    let mut e2 = e2.spawn();

    e1.connect_with(second);
    e2.wait_for_connect();

    e2.connect_with(first);
    e1.wait_for_connect();

    e1.send_to(second, acceptable_message.clone());
    assert_eq!(e2.wait_for_message(), acceptable_message);

    e2.send_to(first, too_big_message.clone());
    assert!(e1.wait_for_event().is_err());
}

#[test]
fn test_network_reconnect() {
    let first = "127.0.0.1:19100".parse().unwrap();
    let second = "127.0.0.1:19101".parse().unwrap();

    let msg = raw_message(11, 1000);
    let c1 = connect_message(first);

    let mut t1 = TestEvents::with_addr(first).spawn();

    // First connect attempt.
    let mut t2 = TestEvents::with_addr(second).spawn();

    // Handle first attempt.
    t1.connect_with(second);
    assert_eq!(t2.wait_for_connect(), c1);

    t1.send_to(second, msg.clone());
    assert_eq!(t2.wait_for_message(), msg);

    drop(t2);
    assert_eq!(t1.wait_for_disconnect(), second);

    // Handle second attempt.
    let mut t2 = TestEvents::with_addr(second).spawn();

    t1.connect_with(second);
    assert_eq!(t2.wait_for_connect(), c1);

    t1.send_to(second, msg.clone());
    assert_eq!(t2.wait_for_message(), msg);

    t1.disconnect_with(second);
    assert_eq!(t1.wait_for_disconnect(), second);
}

#[test]
fn test_network_multiple_connect() {
    let main = "127.0.0.1:19600".parse().unwrap();

    let nodes = [
        "127.0.0.1:19601".parse().unwrap(),
        "127.0.0.1:19602".parse().unwrap(),
        "127.0.0.1:19603".parse().unwrap(),
    ];

    let mut node = TestEvents::with_addr(main).spawn();

    let connect_messages: Vec<_> = nodes.iter().cloned().map(connect_message).collect();
    let connectors: Vec<_> = nodes
        .iter()
        .map(|addr| TestEvents::with_addr(*addr).spawn())
        .collect();

    connectors[0].connect_with(main);
    assert_eq!(node.wait_for_connect(), connect_messages[0]);
    connectors[1].connect_with(main);
    assert_eq!(node.wait_for_connect(), connect_messages[1]);
    connectors[2].connect_with(main);
    assert_eq!(node.wait_for_connect(), connect_messages[2]);
}

#[test]
fn test_send_first_not_connect() {
    let main = "127.0.0.1:19500".parse().unwrap();
    let other = "127.0.0.1:19501".parse().unwrap();

    let mut node = TestEvents::with_addr(main).spawn();
    let other_node = TestEvents::with_addr(other).spawn();

    let message = raw_message(11, 1000);
    other_node.send_to(main, message.clone()); // should connect before send message

    assert_eq!(node.wait_for_connect(), connect_message(other));
    assert_eq!(node.wait_for_message(), message);
}
<commit_msg>Fix test_network_reconnect on windows. (#596) [ECR-446]<commit_after>// Copyright 2018 The Exonum Team
//
// 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 futures::{Future, Sink, Stream};
use futures::{stream::Wait, sync::mpsc};
use tokio_core::reactor::Core;
use tokio_timer::{TimeoutStream, Timer};

use std::net::SocketAddr;
use std::thread;
use std::time::{self, Duration};

use crypto::{gen_keypair, PublicKey, Signature};
use messages::{Connect, Message, MessageWriter, RawMessage};
use events::{NetworkEvent, NetworkRequest};
use events::network::{NetworkConfiguration, NetworkPart};
use events::error::log_error;
use node::{EventsPoolCapacity, NodeChannel};
use blockchain::ConsensusConfig;
use helpers::user_agent;

#[derive(Debug)]
pub struct TestHandler {
    handle: Option<thread::JoinHandle<()>>,
    listen_address: SocketAddr,
    network_events_rx: Wait<TimeoutStream<mpsc::Receiver<NetworkEvent>>>,
    network_requests_tx: mpsc::Sender<NetworkRequest>,
}

impl TestHandler {
    pub fn new(
        listen_address: SocketAddr,
        network_requests_tx: mpsc::Sender<NetworkRequest>,
        network_events_rx: mpsc::Receiver<NetworkEvent>,
    ) -> TestHandler {
        let timer = Timer::default();
        let receiver = timer.timeout_stream(network_events_rx, Duration::from_secs(30));
        TestHandler {
            handle: None,
            listen_address,
            network_requests_tx,
            network_events_rx: receiver.wait(),
        }
    }

    pub fn wait_for_event(&mut self) -> Result<NetworkEvent, ()> {
        let event = self.network_events_rx.next().unwrap()?;
        Ok(event)
    }

    pub fn connect_with(&self, addr: SocketAddr) {
        let connect = connect_message(self.listen_address);
        self.network_requests_tx
            .clone()
            .send(NetworkRequest::SendMessage(addr, connect.raw().clone()))
            .wait()
            .unwrap();
    }

    pub fn disconnect_with(&self, addr: SocketAddr) {
        self.network_requests_tx
            .clone()
            .send(NetworkRequest::DisconnectWithPeer(addr))
            .wait()
            .unwrap();
    }

    pub fn send_to(&self, addr: SocketAddr, raw: RawMessage) {
        self.network_requests_tx
            .clone()
            .send(NetworkRequest::SendMessage(addr, raw))
            .wait()
            .unwrap();
    }

    pub fn wait_for_connect(&mut self) -> Connect {
        match self.wait_for_event() {
            Ok(NetworkEvent::PeerConnected(_addr, connect)) => connect,
            Ok(other) => panic!("Unexpected connect received, {:?}", other),
            Err(e) => panic!("An error during wait for connect occurred, {:?}", e),
        }
    }

    pub fn wait_for_disconnect(&mut self) -> SocketAddr {
        match self.wait_for_event() {
            Ok(NetworkEvent::PeerDisconnected(addr)) => addr,
            Ok(other) => panic!("Unexpected disconnect received, {:?}", other),
            Err(e) => panic!("An error during wait for disconnect occurred, {:?}", e),
        }
    }

    pub fn wait_for_message(&mut self) -> RawMessage {
        match self.wait_for_event() {
            Ok(NetworkEvent::MessageReceived(_addr, msg)) => msg,
            Ok(other) => panic!("Unexpected message received, {:?}", other),
            Err(e) => panic!("An error during wait for message occurred, {:?}", e),
        }
    }

    pub fn shutdown(&mut self) {
        self.network_requests_tx
            .clone()
            .send(NetworkRequest::Shutdown)
            .wait()
            .unwrap();
        self.handle.take().expect("shutdown twice").join().unwrap();
    }
}

impl Drop for TestHandler {
    fn drop(&mut self) {
        if !::std::thread::panicking() {
            self.shutdown();
        }
    }
}

#[derive(Debug)]
pub struct TestEvents {
    pub listen_address: SocketAddr,
    pub network_config: NetworkConfiguration,
    pub events_config: EventsPoolCapacity,
}

impl TestEvents {
    pub fn with_addr(listen_address: SocketAddr) -> TestEvents {
        TestEvents {
            listen_address,
            network_config: NetworkConfiguration::default(),
            events_config: EventsPoolCapacity::default(),
        }
    }

    pub fn spawn(self) -> TestHandler {
        let (mut handler_part, network_part) = self.into_reactor();
        let handle = thread::spawn(move || {
            let mut core = Core::new().unwrap();
            let fut = network_part.run(&core.handle());
            core.run(fut).map_err(log_error).unwrap();
        });
        handler_part.handle = Some(handle);
        handler_part
    }

    fn into_reactor(self) -> (TestHandler, NetworkPart) {
        let channel = NodeChannel::new(&self.events_config);
        let network_config = self.network_config;
        let (network_tx, network_rx) = channel.network_events;
        let network_requests_tx = channel.network_requests.0.clone();

        let network_part = NetworkPart {
            our_connect_message: connect_message(self.listen_address),
            listen_address: self.listen_address,
            network_config,
            max_message_len: ConsensusConfig::DEFAULT_MAX_MESSAGE_LEN,
            network_requests: channel.network_requests,
            network_tx: network_tx.clone(),
        };

        let handler_part = TestHandler::new(self.listen_address, network_requests_tx, network_rx);
        (handler_part, network_part)
    }
}

pub fn connect_message(addr: SocketAddr) -> Connect {
    let time = time::UNIX_EPOCH;
    Connect::new_with_signature(
        &PublicKey::zero(),
        addr,
        time.into(),
        &user_agent::get(),
        &Signature::zero(),
    )
}

pub fn raw_message(id: u16, len: usize) -> RawMessage {
    let writer = MessageWriter::new(::messages::PROTOCOL_MAJOR_VERSION, 0, id, len);
    RawMessage::new(writer.sign(&gen_keypair().1))
}

#[test]
fn test_network_handshake() {
    let first = "127.0.0.1:17230".parse().unwrap();
    let second = "127.0.0.1:17231".parse().unwrap();

    let e1 = TestEvents::with_addr(first);
    let e2 = TestEvents::with_addr(second);

    let c1 = connect_message(first);
    let c2 = connect_message(second);

    let mut e1 = e1.spawn();
    let mut e2 = e2.spawn();

    e1.connect_with(second);
    assert_eq!(e2.wait_for_connect(), c1);

    e2.connect_with(first);
    assert_eq!(e1.wait_for_connect(), c2);

    e1.disconnect_with(second);
    assert_eq!(e1.wait_for_disconnect(), second);

    e2.disconnect_with(first);
    assert_eq!(e2.wait_for_disconnect(), first);
}

#[test]
fn test_network_big_message() {
    let first = "127.0.0.1:17200".parse().unwrap();
    let second = "127.0.0.1:17201".parse().unwrap();

    let m1 = raw_message(15, 100000);
    let m2 = raw_message(16, 400);

    let e1 = TestEvents::with_addr(first);
    let e2 = TestEvents::with_addr(second);

    let mut e1 = e1.spawn();
    let mut e2 = e2.spawn();

    e1.connect_with(second);
    e2.wait_for_connect();

    e2.connect_with(first);
    e1.wait_for_connect();

    e1.send_to(second, m1.clone());
    assert_eq!(e2.wait_for_message(), m1);

    e1.send_to(second, m2.clone());
    assert_eq!(e2.wait_for_message(), m2);

    e1.send_to(second, m1.clone());
    assert_eq!(e2.wait_for_message(), m1);

    e2.send_to(first, m2.clone());
    assert_eq!(e1.wait_for_message(), m2);

    e2.send_to(first, m1.clone());
    assert_eq!(e1.wait_for_message(), m1);

    e2.send_to(first, m2.clone());
    assert_eq!(e1.wait_for_message(), m2);

    e1.disconnect_with(second);
    assert_eq!(e1.wait_for_disconnect(), second);

    e2.disconnect_with(first);
    assert_eq!(e2.wait_for_disconnect(), first);
}

#[test]
fn test_network_max_message_len() {
    let first = "127.0.0.1:17202".parse().unwrap();
    let second = "127.0.0.1:17303".parse().unwrap();

    let max_message_length = ConsensusConfig::DEFAULT_MAX_MESSAGE_LEN as usize;
    let max_payload_length =
        max_message_length - ::messages::HEADER_LENGTH - ::crypto::SIGNATURE_LENGTH;
    let acceptable_message = raw_message(15, max_payload_length);
    let too_big_message = raw_message(16, max_payload_length + 1000);

    let e1 = TestEvents::with_addr(first);
    let e2 = TestEvents::with_addr(second);

    let mut e1 = e1.spawn();
    let mut e2 = e2.spawn();

    e1.connect_with(second);
    e2.wait_for_connect();

    e2.connect_with(first);
    e1.wait_for_connect();

    e1.send_to(second, acceptable_message.clone());
    assert_eq!(e2.wait_for_message(), acceptable_message);

    e2.send_to(first, too_big_message.clone());
    assert!(e1.wait_for_event().is_err());
}

#[test]
fn test_network_reconnect() {
    let first = "127.0.0.1:19100".parse().unwrap();
    let second = "127.0.0.1:19101".parse().unwrap();

    let msg = raw_message(11, 1000);
    let c1 = connect_message(first);

    let mut t1 = TestEvents::with_addr(first).spawn();

    // First connect attempt.
    let mut t2 = TestEvents::with_addr(second).spawn();

    // Handle first attempt.
    t1.connect_with(second);
    assert_eq!(t2.wait_for_connect(), c1);

    t1.send_to(second, msg.clone());
    assert_eq!(t2.wait_for_message(), msg);

    t1.disconnect_with(second);
    drop(t2);
    assert_eq!(t1.wait_for_disconnect(), second);

    // Handle second attempt.
    let mut t2 = TestEvents::with_addr(second).spawn();

    t1.connect_with(second);
    assert_eq!(t2.wait_for_connect(), c1);

    t1.send_to(second, msg.clone());
    assert_eq!(t2.wait_for_message(), msg);

    t1.disconnect_with(second);
    assert_eq!(t1.wait_for_disconnect(), second);
}

#[test]
fn test_network_multiple_connect() {
    let main = "127.0.0.1:19600".parse().unwrap();

    let nodes = [
        "127.0.0.1:19601".parse().unwrap(),
        "127.0.0.1:19602".parse().unwrap(),
        "127.0.0.1:19603".parse().unwrap(),
    ];

    let mut node = TestEvents::with_addr(main).spawn();

    let connect_messages: Vec<_> = nodes.iter().cloned().map(connect_message).collect();
    let connectors: Vec<_> = nodes
        .iter()
        .map(|addr| TestEvents::with_addr(*addr).spawn())
        .collect();

    connectors[0].connect_with(main);
    assert_eq!(node.wait_for_connect(), connect_messages[0]);
    connectors[1].connect_with(main);
    assert_eq!(node.wait_for_connect(), connect_messages[1]);
    connectors[2].connect_with(main);
    assert_eq!(node.wait_for_connect(), connect_messages[2]);
}

#[test]
fn test_send_first_not_connect() {
    let main = "127.0.0.1:19500".parse().unwrap();
    let other = "127.0.0.1:19501".parse().unwrap();

    let mut node = TestEvents::with_addr(main).spawn();
    let other_node = TestEvents::with_addr(other).spawn();

    let message = raw_message(11, 1000);
    other_node.send_to(main, message.clone()); // should connect before send message

    assert_eq!(node.wait_for_connect(), connect_message(other));
    assert_eq!(node.wait_for_message(), message);
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate serde_derive;
extern crate jsonrpc_core;
extern crate jsonrpc_minihttp_server;
extern crate fall_gen;
extern crate fall_tree;
extern crate elapsed;

use std::collections::HashSet;

use jsonrpc_core::{IoHandler, Params, to_value};
use jsonrpc_minihttp_server::{ServerBuilder};

use elapsed::measure_time;

use fall_tree::{Node, NodeType, walk_tree, AstNode  };
use fall_tree::visitor::{Visitor, NodeVisitor};
use fall_tree::search::{child_of_type};
use fall_gen::syntax::*;
use fall_gen::ast_ext::PartKind;

type Spans = Vec<(u32, u32, &'static str)>;

fn main() {
    let mut io = IoHandler::new();
    io.add_method("colors", |params: Params| {
        #[derive(Serialize, Default)]
        struct Response { spans: Spans }

        println!("colors");
        let (text, ): (String, ) = params.parse().unwrap();
        let spans = ::std::panic::catch_unwind(|| colorize(text)).unwrap_or_default();
        let r = to_value(Response { spans: spans }).unwrap();
        println!("OK\n");
        Ok(r)
    });
    io.add_method("tree", |params: Params| {
        #[derive(Serialize, Default)]
        struct Response { tree: String }

        println!("tree");
        let (text, ): (String, ) = params.parse().unwrap();
        let file = fall_gen::FallFile::parse(text);
        let r = to_value(Response { tree: file.tree_to_string() }).unwrap();
        println!("OK\n");
        Ok(r)
    });

    let server = ServerBuilder::new(io)
        .threads(3)
        .start_http(&"127.0.0.1:9292".parse().unwrap())
        .unwrap();

    println!("Starting server on 127.0.0.1:9292");
    server.wait().unwrap();
}

fn colorize(text: String) -> Spans {
    let file = fall_gen::FallFile::parse(text);
    let (elapsed, spans) = measure_time(|| {
        let mut spans = vec![];
        let token_names: HashSet<_> = file.ast().tokenizer_def().lex_rules().map(|r| r.node_type()).collect();
        Visitor(&mut spans)
            .visit_nodes(&[HASH_STRING, SIMPLE_STRING], |spans, node| {
                colorize_node(node, "string", spans)
            })
            .visit_nodes(&[KW_RULE, KW_VERBATIM, KW_NODES, KW_TOKENIZER], |spans, node| {
                colorize_node(node, "keyword", spans)
            })
            .visit::<NodesDef, _>(|spans, def| {
                walk_tree(def.node(), |n| if n.ty() == IDENT {
                    let color = if token_names.contains(n.text()) { "token" } else { "rule" };
                    colorize_node(n, color, spans);
                })
            })
            .visit::<LexRule, _>(|spans, rule| colorize_child(rule.node(), IDENT, "token", spans))
            .visit::<SynRule, _>(|spans, rule| colorize_child(rule.node(), IDENT, "rule", spans))
            .visit::<Part, _>(|spans, part| match part.kind() {
                PartKind::Token(_) => colorize_node(part.node(), "token", spans),
                PartKind::RuleReference { .. } => colorize_node(part.node(), "rule", spans),
                PartKind::Call { .. } => {
                    colorize_child(part.node(), IDENT, "builtin", spans);
                    colorize_child(part.node(), LANGLE, "builtin", spans);
                    colorize_child(part.node(), RANGLE, "builtin", spans);
                }
            })
            .walk_recursively_children_first(file.ast().node());
        spans
    });
    println!("Lexing   = {}", file.lexing_time());
    println!("Parsing  = {}", file.parsing_time());
    println!("Coloring = {}", elapsed);

    spans
}

fn colorize_node(node: Node, color: &'static str, spans: &mut Spans) {
    spans.push((node.range().start(), node.range().end(), color))
}

fn colorize_child(node: Node, child: NodeType, color: &'static str, spans: &mut Spans) {
    if let Some(child) = child_of_type(node, child) {
        colorize_node(child, color, spans);
    }
}
<commit_msg>Colors for ast<commit_after>#[macro_use]
extern crate serde_derive;
extern crate jsonrpc_core;
extern crate jsonrpc_minihttp_server;
extern crate fall_gen;
extern crate fall_tree;
extern crate elapsed;

use std::collections::HashSet;

use jsonrpc_core::{IoHandler, Params, to_value};
use jsonrpc_minihttp_server::{ServerBuilder};

use elapsed::measure_time;

use fall_tree::{Node, NodeType, walk_tree, AstNode  };
use fall_tree::visitor::{Visitor, NodeVisitor};
use fall_tree::search::{child_of_type};
use fall_gen::syntax::*;
use fall_gen::ast_ext::PartKind;

type Spans = Vec<(u32, u32, &'static str)>;

fn main() {
    let mut io = IoHandler::new();
    io.add_method("colors", |params: Params| {
        #[derive(Serialize, Default)]
        struct Response { spans: Spans }

        println!("colors");
        let (text, ): (String, ) = params.parse().unwrap();
        let spans = ::std::panic::catch_unwind(|| colorize(text)).unwrap_or_default();
        let r = to_value(Response { spans: spans }).unwrap();
        println!("OK\n");
        Ok(r)
    });
    io.add_method("tree", |params: Params| {
        #[derive(Serialize, Default)]
        struct Response { tree: String }

        println!("tree");
        let (text, ): (String, ) = params.parse().unwrap();
        let file = fall_gen::FallFile::parse(text);
        let r = to_value(Response { tree: file.tree_to_string() }).unwrap();
        println!("OK\n");
        Ok(r)
    });

    let server = ServerBuilder::new(io)
        .threads(3)
        .start_http(&"127.0.0.1:9292".parse().unwrap())
        .unwrap();

    println!("Starting server on 127.0.0.1:9292");
    server.wait().unwrap();
}

fn colorize(text: String) -> Spans {
    let file = fall_gen::FallFile::parse(text);
    let (elapsed, spans) = measure_time(|| {
        let mut spans = vec![];
        let token_names: HashSet<_> = file.ast().tokenizer_def().lex_rules().map(|r| r.node_type()).collect();
        Visitor(&mut spans)
            .visit_nodes(&[HASH_STRING, SIMPLE_STRING], |spans, node| {
                colorize_node(node, "string", spans)
            })
            .visit_nodes(&[KW_RULE, KW_VERBATIM, KW_NODES, KW_TOKENIZER, KW_AST], |spans, node| {
                colorize_node(node, "keyword", spans)
            })
            .visit::<NodesDef, _>(|spans, def| {
                walk_tree(def.node(), |n| if n.ty() == IDENT {
                    let color = if token_names.contains(n.text()) { "token" } else { "rule" };
                    colorize_node(n, color, spans);
                })
            })
            .visit::<LexRule, _>(|spans, rule| colorize_child(rule.node(), IDENT, "token", spans))
            .visit::<SynRule, _>(|spans, rule| colorize_child(rule.node(), IDENT, "rule", spans))
            .visit::<AstNodeDef, _>(|spans, rule| colorize_child(rule.node(), IDENT, "rule", spans))
            .visit::<Part, _>(|spans, part| match part.kind() {
                PartKind::Token(_) => colorize_node(part.node(), "token", spans),
                PartKind::RuleReference { .. } => colorize_node(part.node(), "rule", spans),
                PartKind::Call { .. } => {
                    colorize_child(part.node(), IDENT, "builtin", spans);
                    colorize_child(part.node(), LANGLE, "builtin", spans);
                    colorize_child(part.node(), RANGLE, "builtin", spans);
                }
            })
            .walk_recursively_children_first(file.ast().node());
        spans
    });
    println!("Lexing   = {}", file.lexing_time());
    println!("Parsing  = {}", file.parsing_time());
    println!("Coloring = {}", elapsed);

    spans
}

fn colorize_node(node: Node, color: &'static str, spans: &mut Spans) {
    spans.push((node.range().start(), node.range().end(), color))
}

fn colorize_child(node: Node, child: NodeType, color: &'static str, spans: &mut Spans) {
    if let Some(child) = child_of_type(node, child) {
        colorize_node(child, color, spans);
    }
}
<|endoftext|>


<commit_before>extern crate rayon;

use self::rayon::prelude::*;

use std::sync::{
    Arc,
    RwLock,
};
use super::attestation_validation::{
    AttestationValidationContext,
    AttestationValidationError,
};
use super::types::{
    AttestationRecord,
    AttesterMap,
    Block,
    ProposerMap,
};
use super::ssz_helpers::attestation_ssz_splitter::{
    split_one_attestation,
    split_all_attestations,
    AttestationSplitError,
};
use super::ssz_helpers::ssz_block::{
    SszBlock,
    SszBlockError,
};
use super::db::{
    ClientDB,
    DBError,
};
use super::db::stores::{
    BlockStore,
    PoWChainStore,
    ValidatorStore,
};
use super::ssz::{
    Decodable,
    DecodeError,
};
use super::types::Hash256;

#[derive(Debug, PartialEq)]
pub enum BlockStatus {
    NewBlock,
    KnownBlock,
}

#[derive(Debug, PartialEq)]
pub enum SszBlockValidationError {
    FutureSlot,
    SlotAlreadyFinalized,
    UnknownPoWChainRef,
    UnknownParentHash,
    BadAttestationSsz,
    AttestationValidationError(AttestationValidationError),
    AttestationSignatureFailed,
    ProposerAttestationHasObliqueHashes,
    NoProposerSignature,
    BadProposerMap,
    RwLockPoisoned,
    DBError(String),
}

/// The context against which a block should be validated.
pub struct BlockValidationContext<T>
    where T: ClientDB + Sized
{
    /// The slot as determined by the system time.
    pub present_slot: u64,
    /// The cycle_length as determined by the chain configuration.
    pub cycle_length: u8,
    /// The last justified slot as per the client's view of the canonical chain.
    pub last_justified_slot: u64,
    /// The last finalized slot as per the client's view of the canonical chain.
    pub last_finalized_slot: u64,
    /// A vec of the hashes of the blocks preceeding the present slot.
    pub parent_hashes: Arc<Vec<Hash256>>,
    /// A map of slots to a block proposer validation index.
    pub proposer_map: Arc<ProposerMap>,
    /// A map of (slot, shard_id) to the attestation set of validation indices.
    pub attester_map: Arc<AttesterMap>,
    /// The store containing block information.
    pub block_store: Arc<BlockStore<T>>,
    /// The store containing validator information.
    pub validator_store: Arc<ValidatorStore<T>>,
    /// The store containing information about the proof-of-work chain.
    pub pow_store: Arc<PoWChainStore<T>>,
}

impl<T> BlockValidationContext<T>
    where T: ClientDB
{
    /// Validate some SszBlock against a block validation context. An SszBlock varies from a Block in
    /// that is a read-only structure that reads directly from encoded SSZ.
    ///
    /// The reason to validate an SzzBlock is to avoid decoding it in its entirety if there is
    /// a suspicion that the block might be invalid. Such a suspicion should be applied to
    /// all blocks coming from the network.
    ///
    /// This function will determine if the block is new, already known or invalid (either
    /// intrinsically or due to some application error.)
    ///
    /// Note: this function does not implement randao_reveal checking as it is not in the
    /// specification.
    #[allow(dead_code)]
    pub fn validate_ssz_block(&self, b: &SszBlock)
        -> Result<(BlockStatus, Option<Block>), SszBlockValidationError>
        where T: ClientDB + Sized
    {

        /*
         * If this block is already known, return immediately and indicate the the block is
         * known. Don't attempt to deserialize the block.
         */
        let block_hash = &b.block_hash();
        if self.block_store.block_exists(&block_hash)? {
            return Ok((BlockStatus::KnownBlock, None));
        }

        /*
         * If the block slot corresponds to a slot in the future, return immediately with an error.
         *
         * It is up to the calling fn to determine what should be done with "future" blocks (e.g.,
         * cache or discard).
         */
        let block_slot = b.slot_number();
        if block_slot > self.present_slot {
            return Err(SszBlockValidationError::FutureSlot);
        }

        /*
         * If the block is unknown (assumed unknown because we checked the db earlier in this
         * function) and it comes from a slot that is already finalized, drop the block.
         *
         * If a slot is finalized, there's no point in considering any other blocks for that slot.
         */
        if block_slot <= self.last_finalized_slot {
            return Err(SszBlockValidationError::SlotAlreadyFinalized);
        }

        /*
         * If the PoW chain hash is not known to us, drop it.
         *
         * We only accept blocks that reference a known PoW hash.
         *
         * Note: it is not clear what a "known" PoW chain ref is. Likely it means the block hash is
         * "sufficienty deep in the canonical PoW chain". This should be clarified as the spec
         * crystallizes.
         */
        let pow_chain_ref = b.pow_chain_ref();
        if !self.pow_store.block_hash_exists(b.pow_chain_ref())? {
            return Err(SszBlockValidationError::UnknownPoWChainRef);
        }

        /*
         * Store a slice of the serialized attestations from the block SSZ.
         */
        let attestations_ssz = &b.attestations();

        /*
         * Get a slice of the first serialized attestation (the 0'th) and decode it into
         * a full AttestationRecord object.
         *
         * The first attestation must be validated separately as it must contain a signature of the
         * proposer of the previous block (this is checked later in this function).
         */
        let (first_attestation_ssz, next_index) = split_one_attestation(
            &attestations_ssz,
            0)?;
        let (first_attestation, _) = AttestationRecord::ssz_decode(
            &first_attestation_ssz, 0)?;

        /*
         * The first attestation may not have oblique hashes.
         *
         * The presence of oblique hashes in the first attestation would indicate that the proposer
         * of the previous block is attesting to some other block than the one they produced.
         */
        if first_attestation.oblique_parent_hashes.len() > 0 {
            return Err(SszBlockValidationError::ProposerAttestationHasObliqueHashes);
        }

        /*
         * Generate the context in which attestations will be validated.
         */
        let attestation_validation_context = Arc::new(AttestationValidationContext {
            block_slot,
            cycle_length: self.cycle_length,
            last_justified_slot: self.last_justified_slot,
            parent_hashes: self.parent_hashes.clone(),
            block_store: self.block_store.clone(),
            validator_store: self.validator_store.clone(),
            attester_map: self.attester_map.clone(),
        });

        /*
         * Validate this first attestation.
         */
        let attestation_voters = attestation_validation_context
            .validate_attestation(&first_attestation)?;

        /*
         * Read the parent hash from the block we are validating then attempt to load
         * the parent block ssz from the database. If that parent doesn't exist in
         * the database, reject the block.
         *
         * If the parent does exist in the database, read the slot of that parent. Then,
         * determine the proposer of that slot (the parent slot) by looking it up
         * in the proposer map.
         *
         * If that proposer (the proposer of the parent block) was not present in the first (0'th)
         * attestation of this block, reject the block.
         */
        let parent_hash = b.parent_hash();
        match self.block_store.get_serialized_block(&parent_hash)? {
            None => return Err(SszBlockValidationError::UnknownParentHash),
            Some(ssz) => {
                let parent_block = SszBlock::from_slice(&ssz[..])?;
                let proposer = self.proposer_map.get(&parent_block.slot_number())
                    .ok_or(SszBlockValidationError::BadProposerMap)?;
                if !attestation_voters.contains(&proposer) {
                    return Err(SszBlockValidationError::NoProposerSignature);
                }
            }
        }

        /*
         * Split the remaining attestations into a vector of slices, each containing
         * a single serialized attestation record.
         */
        let other_attestations = split_all_attestations(attestations_ssz,
                                                        next_index)?;

        /*
         * Verify each other AttestationRecord.
         *
         * This uses the `rayon` library to do "sometimes" parallelization. Put simply,
         * if there are some spare threads, the verification of attestation records will happen
         * concurrently.
         *
         * There is a thread-safe `failure` variable which is set whenever an attestation fails
         * validation. This is so all attestation validation is halted if a single bad attestation
         * is found.
         */
        let failure: RwLock<Option<SszBlockValidationError>> = RwLock::new(None);
        let mut deserialized_attestations: Vec<AttestationRecord> = other_attestations
            .par_iter()
            .filter_map(|attestation_ssz| {
                /*
                 * If some thread has set the `failure` variable to `Some(error)` the abandon
                 * attestation serialization and validation.
                 */
                if let Some(_) = *failure.read().unwrap() {
                    return None;
                }
                /*
                 * If there has not been a failure yet, attempt to serialize and validate the
                 * attestation.
                 */
                match AttestationRecord::ssz_decode(&attestation_ssz, 0) {
                    /*
                     * Deserialization failed, therefore the block is invalid.
                     */
                    Err(e) => {
                        let mut failure = failure.write().unwrap();
                        *failure = Some(SszBlockValidationError::from(e));
                        None
                    }
                    /*
                     * Deserialization succeeded and the attestation should be validated.
                     */
                    Ok((attestation, _)) => {
                        match attestation_validation_context.validate_attestation(&attestation) {
                            /*
                             * Attestation validation failed with some error.
                             */
                            Err(e) => {
                                let mut failure = failure.write().unwrap();
                                *failure = Some(SszBlockValidationError::from(e));
                                None
                            }
                            /*
                             * Attestation validation succeded.
                             */
                            Ok(_) => Some(attestation)
                        }
                    }
                }
            })
            .collect();

        match failure.into_inner() {
            Err(_) => return Err(SszBlockValidationError::RwLockPoisoned),
            Ok(failure) => {
                match failure {
                    Some(error) => return Err(error),
                    _ => ()
                }

            }
        }

        /*
         * Add the first attestation to the vec of deserialized attestations at
         * index 0.
         */
        deserialized_attestations.insert(0, first_attestation);

        /*
         * If we have reached this point, the block is a new valid block that is worthy of
         * processing.
         */
        let block = Block {
            parent_hash: Hash256::from(parent_hash),
            slot_number: block_slot,
            randao_reveal: Hash256::from(b.randao_reveal()),
            attestations: deserialized_attestations,
            pow_chain_ref: Hash256::from(pow_chain_ref),
            active_state_root: Hash256::from(b.act_state_root()),
            crystallized_state_root: Hash256::from(b.cry_state_root()),
        };
        Ok((BlockStatus::NewBlock, Some(block)))
    }
}

impl From<DBError> for SszBlockValidationError {
    fn from(e: DBError) -> Self {
        SszBlockValidationError::DBError(e.message)
    }
}

impl From<AttestationSplitError> for SszBlockValidationError {
    fn from(e: AttestationSplitError) -> Self {
        match e {
            AttestationSplitError::TooShort =>
                SszBlockValidationError::BadAttestationSsz
        }
    }
}

impl From<SszBlockError> for SszBlockValidationError {
    fn from(e: SszBlockError) -> Self {
        match e {
            SszBlockError::TooShort =>
                SszBlockValidationError::DBError("Bad parent block in db.".to_string()),
            SszBlockError::TooLong =>
                SszBlockValidationError::DBError("Bad parent block in db.".to_string()),
        }
    }
}

impl From<DecodeError> for SszBlockValidationError {
    fn from(e: DecodeError) -> Self {
        match e {
            DecodeError::TooShort =>
                SszBlockValidationError::BadAttestationSsz,
            DecodeError::TooLong =>
                SszBlockValidationError::BadAttestationSsz,
        }
    }
}

impl From<AttestationValidationError> for SszBlockValidationError {
    fn from(e: AttestationValidationError) -> Self {
        SszBlockValidationError::AttestationValidationError(e)
    }
}

/*
 * Tests for block validation are contained in the root directory "tests" directory (AKA
 * "integration tests directory").
 */
<commit_msg>Separate parent block checking and proposer checking<commit_after>extern crate rayon;

use self::rayon::prelude::*;

use std::sync::{
    Arc,
    RwLock,
};
use super::attestation_validation::{
    AttestationValidationContext,
    AttestationValidationError,
};
use super::types::{
    AttestationRecord,
    AttesterMap,
    Block,
    ProposerMap,
};
use super::ssz_helpers::attestation_ssz_splitter::{
    split_one_attestation,
    split_all_attestations,
    AttestationSplitError,
};
use super::ssz_helpers::ssz_block::{
    SszBlock,
    SszBlockError,
};
use super::db::{
    ClientDB,
    DBError,
};
use super::db::stores::{
    BlockStore,
    PoWChainStore,
    ValidatorStore,
};
use super::ssz::{
    Decodable,
    DecodeError,
};
use super::types::Hash256;

#[derive(Debug, PartialEq)]
pub enum BlockStatus {
    NewBlock,
    KnownBlock,
}

#[derive(Debug, PartialEq)]
pub enum SszBlockValidationError {
    FutureSlot,
    SlotAlreadyFinalized,
    UnknownPoWChainRef,
    UnknownParentHash,
    BadAttestationSsz,
    AttestationValidationError(AttestationValidationError),
    AttestationSignatureFailed,
    ProposerAttestationHasObliqueHashes,
    NoProposerSignature,
    BadProposerMap,
    RwLockPoisoned,
    DBError(String),
}

/// The context against which a block should be validated.
pub struct BlockValidationContext<T>
    where T: ClientDB + Sized
{
    /// The slot as determined by the system time.
    pub present_slot: u64,
    /// The cycle_length as determined by the chain configuration.
    pub cycle_length: u8,
    /// The last justified slot as per the client's view of the canonical chain.
    pub last_justified_slot: u64,
    /// The last finalized slot as per the client's view of the canonical chain.
    pub last_finalized_slot: u64,
    /// A vec of the hashes of the blocks preceeding the present slot.
    pub parent_hashes: Arc<Vec<Hash256>>,
    /// A map of slots to a block proposer validation index.
    pub proposer_map: Arc<ProposerMap>,
    /// A map of (slot, shard_id) to the attestation set of validation indices.
    pub attester_map: Arc<AttesterMap>,
    /// The store containing block information.
    pub block_store: Arc<BlockStore<T>>,
    /// The store containing validator information.
    pub validator_store: Arc<ValidatorStore<T>>,
    /// The store containing information about the proof-of-work chain.
    pub pow_store: Arc<PoWChainStore<T>>,
}

impl<T> BlockValidationContext<T>
    where T: ClientDB
{
    /// Validate some SszBlock against a block validation context. An SszBlock varies from a Block in
    /// that is a read-only structure that reads directly from encoded SSZ.
    ///
    /// The reason to validate an SzzBlock is to avoid decoding it in its entirety if there is
    /// a suspicion that the block might be invalid. Such a suspicion should be applied to
    /// all blocks coming from the network.
    ///
    /// This function will determine if the block is new, already known or invalid (either
    /// intrinsically or due to some application error.)
    ///
    /// Note: this function does not implement randao_reveal checking as it is not in the
    /// specification.
    #[allow(dead_code)]
    pub fn validate_ssz_block(&self, b: &SszBlock)
        -> Result<(BlockStatus, Option<Block>), SszBlockValidationError>
        where T: ClientDB + Sized
    {

        /*
         * If this block is already known, return immediately and indicate the the block is
         * known. Don't attempt to deserialize the block.
         */
        let block_hash = &b.block_hash();
        if self.block_store.block_exists(&block_hash)? {
            return Ok((BlockStatus::KnownBlock, None));
        }

        /*
         * If the block slot corresponds to a slot in the future, return immediately with an error.
         *
         * It is up to the calling fn to determine what should be done with "future" blocks (e.g.,
         * cache or discard).
         */
        let block_slot = b.slot_number();
        if block_slot > self.present_slot {
            return Err(SszBlockValidationError::FutureSlot);
        }

        /*
         * If the block is unknown (assumed unknown because we checked the db earlier in this
         * function) and it comes from a slot that is already finalized, drop the block.
         *
         * If a slot is finalized, there's no point in considering any other blocks for that slot.
         */
        if block_slot <= self.last_finalized_slot {
            return Err(SszBlockValidationError::SlotAlreadyFinalized);
        }

        /*
         * If the PoW chain hash is not known to us, drop it.
         *
         * We only accept blocks that reference a known PoW hash.
         *
         * Note: it is not clear what a "known" PoW chain ref is. Likely it means the block hash is
         * "sufficienty deep in the canonical PoW chain". This should be clarified as the spec
         * crystallizes.
         */
        let pow_chain_ref = b.pow_chain_ref();
        if !self.pow_store.block_hash_exists(b.pow_chain_ref())? {
            return Err(SszBlockValidationError::UnknownPoWChainRef);
        }

        /*
         * Store a slice of the serialized attestations from the block SSZ.
         */
        let attestations_ssz = &b.attestations();

        /*
         * Get a slice of the first serialized attestation (the 0'th) and decode it into
         * a full AttestationRecord object.
         *
         * The first attestation must be validated separately as it must contain a signature of the
         * proposer of the previous block (this is checked later in this function).
         */
        let (first_attestation_ssz, next_index) = split_one_attestation(
            &attestations_ssz,
            0)?;
        let (first_attestation, _) = AttestationRecord::ssz_decode(
            &first_attestation_ssz, 0)?;

        /*
         * The first attestation may not have oblique hashes.
         *
         * The presence of oblique hashes in the first attestation would indicate that the proposer
         * of the previous block is attesting to some other block than the one they produced.
         */
        if first_attestation.oblique_parent_hashes.len() > 0 {
            return Err(SszBlockValidationError::ProposerAttestationHasObliqueHashes);
        }

        /*
         * Read the parent hash from the block we are validating then attempt to load
         * that parent block ssz from the database.
         *
         * If that parent doesn't exist in the database or is invalid, reject the block.
         *
         * Also, read the slot from the parent block for later use.
         */
        let parent_hash = b.parent_hash();
        let parent_slot = match self.block_store.get_serialized_block(&parent_hash)? {
            None => return Err(SszBlockValidationError::UnknownParentHash),
            Some(ssz) => {
                let parent_block = SszBlock::from_slice(&ssz[..])?;
                parent_block.slot_number()
            }
        };

        /*
         * Generate the context in which attestations will be validated.
         */
        let attestation_validation_context = Arc::new(AttestationValidationContext {
            block_slot,
            cycle_length: self.cycle_length,
            last_justified_slot: self.last_justified_slot,
            parent_hashes: self.parent_hashes.clone(),
            block_store: self.block_store.clone(),
            validator_store: self.validator_store.clone(),
            attester_map: self.attester_map.clone(),
        });

        /*
         * Validate this first attestation.
         */
        let attestation_voters = attestation_validation_context
            .validate_attestation(&first_attestation)?;

        /*
         * Attempt to read load the parent block proposer from the proposer map. Return with an
         * error if it fails.
         *
         * If the signature of proposer for the parent slot was not present in the first (0'th)
         * attestation of this block, reject the block.
         */
        let parent_block_proposer = self.proposer_map.get(&parent_slot)
            .ok_or(SszBlockValidationError::BadProposerMap)?;
        if !attestation_voters.contains(&parent_block_proposer) {
            return Err(SszBlockValidationError::NoProposerSignature);
        }

        /*
         * Split the remaining attestations into a vector of slices, each containing
         * a single serialized attestation record.
         */
        let other_attestations = split_all_attestations(attestations_ssz,
                                                        next_index)?;

        /*
         * Verify each other AttestationRecord.
         *
         * This uses the `rayon` library to do "sometimes" parallelization. Put simply,
         * if there are some spare threads, the verification of attestation records will happen
         * concurrently.
         *
         * There is a thread-safe `failure` variable which is set whenever an attestation fails
         * validation. This is so all attestation validation is halted if a single bad attestation
         * is found.
         */
        let failure: RwLock<Option<SszBlockValidationError>> = RwLock::new(None);
        let mut deserialized_attestations: Vec<AttestationRecord> = other_attestations
            .par_iter()
            .filter_map(|attestation_ssz| {
                /*
                 * If some thread has set the `failure` variable to `Some(error)` the abandon
                 * attestation serialization and validation.
                 */
                if let Some(_) = *failure.read().unwrap() {
                    return None;
                }
                /*
                 * If there has not been a failure yet, attempt to serialize and validate the
                 * attestation.
                 */
                match AttestationRecord::ssz_decode(&attestation_ssz, 0) {
                    /*
                     * Deserialization failed, therefore the block is invalid.
                     */
                    Err(e) => {
                        let mut failure = failure.write().unwrap();
                        *failure = Some(SszBlockValidationError::from(e));
                        None
                    }
                    /*
                     * Deserialization succeeded and the attestation should be validated.
                     */
                    Ok((attestation, _)) => {
                        match attestation_validation_context.validate_attestation(&attestation) {
                            /*
                             * Attestation validation failed with some error.
                             */
                            Err(e) => {
                                let mut failure = failure.write().unwrap();
                                *failure = Some(SszBlockValidationError::from(e));
                                None
                            }
                            /*
                             * Attestation validation succeded.
                             */
                            Ok(_) => Some(attestation)
                        }
                    }
                }
            })
            .collect();

        match failure.into_inner() {
            Err(_) => return Err(SszBlockValidationError::RwLockPoisoned),
            Ok(failure) => {
                match failure {
                    Some(error) => return Err(error),
                    _ => ()
                }

            }
        }

        /*
         * Add the first attestation to the vec of deserialized attestations at
         * index 0.
         */
        deserialized_attestations.insert(0, first_attestation);

        /*
         * If we have reached this point, the block is a new valid block that is worthy of
         * processing.
         */
        let block = Block {
            parent_hash: Hash256::from(parent_hash),
            slot_number: block_slot,
            randao_reveal: Hash256::from(b.randao_reveal()),
            attestations: deserialized_attestations,
            pow_chain_ref: Hash256::from(pow_chain_ref),
            active_state_root: Hash256::from(b.act_state_root()),
            crystallized_state_root: Hash256::from(b.cry_state_root()),
        };
        Ok((BlockStatus::NewBlock, Some(block)))
    }
}

impl From<DBError> for SszBlockValidationError {
    fn from(e: DBError) -> Self {
        SszBlockValidationError::DBError(e.message)
    }
}

impl From<AttestationSplitError> for SszBlockValidationError {
    fn from(e: AttestationSplitError) -> Self {
        match e {
            AttestationSplitError::TooShort =>
                SszBlockValidationError::BadAttestationSsz
        }
    }
}

impl From<SszBlockError> for SszBlockValidationError {
    fn from(e: SszBlockError) -> Self {
        match e {
            SszBlockError::TooShort =>
                SszBlockValidationError::DBError("Bad parent block in db.".to_string()),
            SszBlockError::TooLong =>
                SszBlockValidationError::DBError("Bad parent block in db.".to_string()),
        }
    }
}

impl From<DecodeError> for SszBlockValidationError {
    fn from(e: DecodeError) -> Self {
        match e {
            DecodeError::TooShort =>
                SszBlockValidationError::BadAttestationSsz,
            DecodeError::TooLong =>
                SszBlockValidationError::BadAttestationSsz,
        }
    }
}

impl From<AttestationValidationError> for SszBlockValidationError {
    fn from(e: AttestationValidationError) -> Self {
        SszBlockValidationError::AttestationValidationError(e)
    }
}

/*
 * Tests for block validation are contained in the root directory "tests" directory (AKA
 * "integration tests directory").
 */
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::sync::Arc;
use descriptor::descriptor::DescriptorDesc;
use descriptor::descriptor::ShaderStages;
use descriptor::descriptor_set::DescriptorSetsCollection;
use descriptor::descriptor_set::UnsafeDescriptorSetLayout;
use descriptor::pipeline_layout::PipelineLayout;
use descriptor::pipeline_layout::PipelineLayoutSys;
use descriptor::pipeline_layout::PipelineLayoutCreationError;
use device::Device;

/// Trait for objects that describe the layout of the descriptors and push constants of a pipeline.
pub unsafe trait PipelineLayoutRef {
    /// Returns an opaque object that allows internal access to the pipeline layout.
    ///
    /// Can be obtained by calling `PipelineLayoutRef::sys()` on the pipeline layout.
    ///
    /// > **Note**: This is an internal function that you normally don't need to call.
    fn sys(&self) -> PipelineLayoutSys;

    /// Returns the description of the pipeline layout.
    ///
    /// Can be obtained by calling `PipelineLayoutRef::desc()` on the pipeline layout.
    fn desc(&self) -> &PipelineLayoutDesc;

    /// Returns the device that this pipeline layout belongs to.
    ///
    /// Can be obtained by calling `PipelineLayoutRef::device()` on the pipeline layout.
    fn device(&self) -> &Arc<Device>;
}

unsafe impl<T> PipelineLayoutRef for Arc<T> where T: PipelineLayoutRef {
    #[inline]
    fn sys(&self) -> PipelineLayoutSys {
        (**self).sys()
    }

    #[inline]
    fn desc(&self) -> &PipelineLayoutDesc {
        (**self).desc()
    }

    #[inline]
    fn device(&self) -> &Arc<Device> {
        (**self).device()
    }
}

unsafe impl<'a, T> PipelineLayoutRef for &'a T where T: 'a + PipelineLayoutRef {
    #[inline]
    fn sys(&self) -> PipelineLayoutSys {
        (**self).sys()
    }

    #[inline]
    fn desc(&self) -> &PipelineLayoutDesc {
        (**self).desc()
    }

    #[inline]
    fn device(&self) -> &Arc<Device> {
        (**self).device()
    }
}

/// Trait for objects that describe the layout of the descriptors and push constants of a pipeline.
pub unsafe trait PipelineLayoutDesc {
    /// Returns the number of sets in the layout. Includes possibly empty sets.
    ///
    /// In other words, this should be equal to the highest set number plus one.
    fn num_sets(&self) -> usize;

    /// Returns the number of descriptors in the set. Includes possibly empty descriptors.
    ///
    /// Returns `None` if the set is out of range.
    fn num_bindings_in_set(&self, set: usize) -> Option<usize>;

    /// Returns the descriptor for the given binding of the given set.
    ///
    /// Returns `None` if out of range.
    fn descriptor(&self, set: usize, binding: usize) -> Option<DescriptorDesc>;

    /// If the `PipelineLayoutDesc` implementation is able to provide an existing
    /// `UnsafeDescriptorSetLayout` for a given set, it can do so by returning it here.
    #[inline]
    fn provided_set_layout(&self, set: usize) -> Option<Arc<UnsafeDescriptorSetLayout>> {
        None
    }

    /// Returns the number of push constant ranges of the layout.
    fn num_push_constants_ranges(&self) -> usize;

    /// Returns a description of the given push constants range.
    ///
    /// Contrary to the descriptors, a push constants range can't be empty.
    ///
    /// Returns `None` if out of range.
    // TODO: better return value
    fn push_constants_range(&self, num: usize) -> Option<(usize, usize, ShaderStages)>;

    /// Turns the layout description into a `PipelineLayout` object that can be used by Vulkan.
    #[inline]
    fn build(self, device: &Arc<Device>)
             -> Result<PipelineLayout<Self>, PipelineLayoutCreationError>
        where Self: Sized
    {
        PipelineLayout::new(device, self)
    }
}

unsafe impl PipelineLayoutDesc for Box<PipelineLayoutDesc + Send + Sync> {
    #[inline]
    fn num_sets(&self) -> usize {
        (**self).num_sets()
    }

    #[inline]
    fn num_bindings_in_set(&self, set: usize) -> Option<usize> {
        (**self).num_bindings_in_set(set)
    }

    #[inline]
    fn descriptor(&self, set: usize, binding: usize) -> Option<DescriptorDesc> {
        (**self).descriptor(set, binding)
    }

    #[inline]
    fn num_push_constants_ranges(&self) -> usize {
        (**self).num_push_constants_ranges()
    }

    #[inline]
    fn push_constants_range(&self, num: usize) -> Option<(usize, usize, ShaderStages)> {
        (**self).push_constants_range(num)
    }
}

/// Traits that allow determining whether a pipeline layout is a superset of another one.
///
/// This trait is automatically implemented on all types that implement `PipelineLayoutRef`.
/// TODO: once specialization lands, we can add implementations that don't perform deep comparisons
pub unsafe trait PipelineLayoutSuperset<Other>: PipelineLayoutDesc
    where Other: PipelineLayoutDesc
{
    /// Returns true if `self` is a superset of `Other`.
    fn is_superset_of(&self, &Other) -> bool;
}

unsafe impl<T, U> PipelineLayoutSuperset<U> for T
    where T: PipelineLayoutDesc, U: PipelineLayoutDesc
{
    fn is_superset_of(&self, other: &U) -> bool {
        /*let mut other_descriptor_sets = other.descriptors_desc();

        for my_set in self.descriptors_desc() {
            let mut other_set = match other_descriptor_sets.next() {
                None => return false,
                Some(s) => s,
            };

            for my_desc in my_set {
                let other_desc = match other_set.next() {
                    None => return false,
                    Some(d) => d,
                };

                if !my_desc.is_superset_of(&other_desc) {
                    return false;
                }
            }
        }*/

        // FIXME:
        true
    }
}

/// Traits that allow determining whether
pub unsafe trait PipelineLayoutSetsCompatible<Other>: PipelineLayoutDesc
    where Other: DescriptorSetsCollection
{
    /// Returns true if `Other` can be used with a pipeline that uses `self` as layout.
    fn is_compatible(&self, &Other) -> bool;
}

unsafe impl<T, U> PipelineLayoutSetsCompatible<U> for T
    where T: PipelineLayoutDesc, U: DescriptorSetsCollection
{
    fn is_compatible(&self, sets: &U) -> bool {
        /*let mut other_descriptor_sets = DescriptorSetsCollection::description(sets);

        for my_set in self.descriptors_desc() {
            let mut other_set = match other_descriptor_sets.next() {
                None => return false,
                Some(s) => s,
            };

            for my_desc in my_set {
                let other_desc = match other_set.next() {
                    None => return false,
                    Some(d) => d,
                };

                if !my_desc.is_superset_of(&other_desc) {
                    return false;
                }
            }
        }*/

        // FIXME:
        true
    }
}

/// Traits that allow determining whether
// TODO: require a trait on Pc
pub unsafe trait PipelineLayoutPushConstantsCompatible<Pc>: PipelineLayoutRef {
    /// Returns true if `Pc` can be used with a pipeline that uses `self` as layout.
    fn is_compatible(&self, &Pc) -> bool;
}

unsafe impl<T, U> PipelineLayoutPushConstantsCompatible<U> for T where T: PipelineLayoutRef {
    fn is_compatible(&self, _: &U) -> bool {
        // FIXME:
        true
    }
}
<commit_msg>Fewer Sized requirements for pipeline layout traits<commit_after>// Copyright (c) 2016 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::sync::Arc;
use descriptor::descriptor::DescriptorDesc;
use descriptor::descriptor::ShaderStages;
use descriptor::descriptor_set::DescriptorSetsCollection;
use descriptor::descriptor_set::UnsafeDescriptorSetLayout;
use descriptor::pipeline_layout::PipelineLayout;
use descriptor::pipeline_layout::PipelineLayoutSys;
use descriptor::pipeline_layout::PipelineLayoutCreationError;
use device::Device;

/// Trait for objects that describe the layout of the descriptors and push constants of a pipeline.
pub unsafe trait PipelineLayoutRef {
    /// Returns an opaque object that allows internal access to the pipeline layout.
    ///
    /// Can be obtained by calling `PipelineLayoutRef::sys()` on the pipeline layout.
    ///
    /// > **Note**: This is an internal function that you normally don't need to call.
    fn sys(&self) -> PipelineLayoutSys;

    /// Returns the description of the pipeline layout.
    ///
    /// Can be obtained by calling `PipelineLayoutRef::desc()` on the pipeline layout.
    fn desc(&self) -> &PipelineLayoutDesc;

    /// Returns the device that this pipeline layout belongs to.
    ///
    /// Can be obtained by calling `PipelineLayoutRef::device()` on the pipeline layout.
    fn device(&self) -> &Arc<Device>;
}

unsafe impl<T: ?Sized> PipelineLayoutRef for Arc<T> where T: PipelineLayoutRef {
    #[inline]
    fn sys(&self) -> PipelineLayoutSys {
        (**self).sys()
    }

    #[inline]
    fn desc(&self) -> &PipelineLayoutDesc {
        (**self).desc()
    }

    #[inline]
    fn device(&self) -> &Arc<Device> {
        (**self).device()
    }
}

unsafe impl<'a, T: ?Sized> PipelineLayoutRef for &'a T where T: 'a + PipelineLayoutRef {
    #[inline]
    fn sys(&self) -> PipelineLayoutSys {
        (**self).sys()
    }

    #[inline]
    fn desc(&self) -> &PipelineLayoutDesc {
        (**self).desc()
    }

    #[inline]
    fn device(&self) -> &Arc<Device> {
        (**self).device()
    }
}

/// Trait for objects that describe the layout of the descriptors and push constants of a pipeline.
pub unsafe trait PipelineLayoutDesc {
    /// Returns the number of sets in the layout. Includes possibly empty sets.
    ///
    /// In other words, this should be equal to the highest set number plus one.
    fn num_sets(&self) -> usize;

    /// Returns the number of descriptors in the set. Includes possibly empty descriptors.
    ///
    /// Returns `None` if the set is out of range.
    fn num_bindings_in_set(&self, set: usize) -> Option<usize>;

    /// Returns the descriptor for the given binding of the given set.
    ///
    /// Returns `None` if out of range.
    fn descriptor(&self, set: usize, binding: usize) -> Option<DescriptorDesc>;

    /// If the `PipelineLayoutDesc` implementation is able to provide an existing
    /// `UnsafeDescriptorSetLayout` for a given set, it can do so by returning it here.
    #[inline]
    fn provided_set_layout(&self, set: usize) -> Option<Arc<UnsafeDescriptorSetLayout>> {
        None
    }

    /// Returns the number of push constant ranges of the layout.
    fn num_push_constants_ranges(&self) -> usize;

    /// Returns a description of the given push constants range.
    ///
    /// Contrary to the descriptors, a push constants range can't be empty.
    ///
    /// Returns `None` if out of range.
    // TODO: better return value
    fn push_constants_range(&self, num: usize) -> Option<(usize, usize, ShaderStages)>;

    /// Turns the layout description into a `PipelineLayout` object that can be used by Vulkan.
    #[inline]
    fn build(self, device: &Arc<Device>)
             -> Result<PipelineLayout<Self>, PipelineLayoutCreationError>
        where Self: Sized
    {
        PipelineLayout::new(device, self)
    }
}

unsafe impl PipelineLayoutDesc for Box<PipelineLayoutDesc + Send + Sync> {
    #[inline]
    fn num_sets(&self) -> usize {
        (**self).num_sets()
    }

    #[inline]
    fn num_bindings_in_set(&self, set: usize) -> Option<usize> {
        (**self).num_bindings_in_set(set)
    }

    #[inline]
    fn descriptor(&self, set: usize, binding: usize) -> Option<DescriptorDesc> {
        (**self).descriptor(set, binding)
    }

    #[inline]
    fn num_push_constants_ranges(&self) -> usize {
        (**self).num_push_constants_ranges()
    }

    #[inline]
    fn push_constants_range(&self, num: usize) -> Option<(usize, usize, ShaderStages)> {
        (**self).push_constants_range(num)
    }
}

/// Traits that allow determining whether a pipeline layout is a superset of another one.
///
/// This trait is automatically implemented on all types that implement `PipelineLayoutRef`.
/// TODO: once specialization lands, we can add implementations that don't perform deep comparisons
pub unsafe trait PipelineLayoutSuperset<Other: ?Sized>: PipelineLayoutDesc
    where Other: PipelineLayoutDesc
{
    /// Returns true if `self` is a superset of `Other`.
    fn is_superset_of(&self, &Other) -> bool;
}

unsafe impl<T: ?Sized, U: ?Sized> PipelineLayoutSuperset<U> for T
    where T: PipelineLayoutDesc, U: PipelineLayoutDesc
{
    fn is_superset_of(&self, other: &U) -> bool {
        /*let mut other_descriptor_sets = other.descriptors_desc();

        for my_set in self.descriptors_desc() {
            let mut other_set = match other_descriptor_sets.next() {
                None => return false,
                Some(s) => s,
            };

            for my_desc in my_set {
                let other_desc = match other_set.next() {
                    None => return false,
                    Some(d) => d,
                };

                if !my_desc.is_superset_of(&other_desc) {
                    return false;
                }
            }
        }*/

        // FIXME:
        true
    }
}

/// Traits that allow determining whether
pub unsafe trait PipelineLayoutSetsCompatible<Other: ?Sized>: PipelineLayoutDesc
    where Other: DescriptorSetsCollection
{
    /// Returns true if `Other` can be used with a pipeline that uses `self` as layout.
    fn is_compatible(&self, &Other) -> bool;
}

unsafe impl<T: ?Sized, U: ?Sized> PipelineLayoutSetsCompatible<U> for T
    where T: PipelineLayoutDesc, U: DescriptorSetsCollection
{
    fn is_compatible(&self, sets: &U) -> bool {
        /*let mut other_descriptor_sets = DescriptorSetsCollection::description(sets);

        for my_set in self.descriptors_desc() {
            let mut other_set = match other_descriptor_sets.next() {
                None => return false,
                Some(s) => s,
            };

            for my_desc in my_set {
                let other_desc = match other_set.next() {
                    None => return false,
                    Some(d) => d,
                };

                if !my_desc.is_superset_of(&other_desc) {
                    return false;
                }
            }
        }*/

        // FIXME:
        true
    }
}

/// Traits that allow determining whether
// TODO: require a trait on Pc
pub unsafe trait PipelineLayoutPushConstantsCompatible<Pc: ?Sized>: PipelineLayoutRef {
    /// Returns true if `Pc` can be used with a pipeline that uses `self` as layout.
    fn is_compatible(&self, &Pc) -> bool;
}

unsafe impl<T: ?Sized, U: ?Sized> PipelineLayoutPushConstantsCompatible<U> for T
    where T: PipelineLayoutRef
{
    fn is_compatible(&self, _: &U) -> bool {
        // FIXME:
        true
    }
}
<|endoftext|>


<commit_before>// Submitted by jess 3jane

extern crate rand;

fn shuffle(arr : &mut [i32]) {
    for i in 0..arr.len() {
        let r : usize = rand::random::<usize>() % arr.len();
        arr.swap(r,i);
    }
}

fn is_sorted(arr : &[i32]) -> bool {
    for i in 1..arr.len() {
        if arr[i-1] > arr[i] {
            return false;
        }
    }
    true
}

fn bogo_sort(arr : &mut [i32]) {
    while !is_sorted(arr) {
        shuffle(arr)
    }
}

fn main() {
    let mut v = vec!(1,2,3,4,5);
    shuffle(&mut v);
    println!("Original array: {:?}", v);
    bogo_sort(&mut v);
    println!("Sorted array: {:?}", v);
}
<commit_msg>Updated to use rand's inbuilt shuffle<commit_after>// Submitted by jess 3jane

extern crate rand;

use rand::{thread_rng, Rng};

fn is_sorted(arr : &[i32]) -> bool {
    for i in 1..arr.len() {
        if arr[i-1] > arr[i] {
            return false;
        }
    }
    true
}

fn bogo_sort(arr : &mut [i32]) {
    while !is_sorted(arr) {
        thread_rng().shuffle(arr);
    }
}

fn main() {
    let mut v = vec![1, 2, 3, 4, 5];
    thread_rng().shuffle(&mut v);
    println!("Original array: {:?}", v);
    bogo_sort(&mut v);
    println!("Sorted array: {:?}", v);
}
<|endoftext|>


<commit_before>pub use self::imp::read2;

#[cfg(unix)]
mod imp {
    use std::cmp;
    use std::io::prelude::*;
    use std::io;
    use std::mem;
    use std::os::unix::prelude::*;
    use std::process::{ChildStdout, ChildStderr};
    use libc;

    pub fn read2(mut out_pipe: ChildStdout,
                 mut err_pipe: ChildStderr,
                 data: &mut FnMut(bool, &mut Vec<u8>, bool)) -> io::Result<()> {
        unsafe {
            libc::fcntl(out_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK);
            libc::fcntl(err_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK);
        }

        let mut out_done = false;
        let mut err_done = false;
        let mut out = Vec::new();
        let mut err = Vec::new();

        let max = cmp::max(out_pipe.as_raw_fd(), err_pipe.as_raw_fd());
        loop {
            // wait for either pipe to become readable using `select`
            let r = unsafe {
                let mut read: libc::fd_set = mem::zeroed();
                if !out_done {
                    libc::FD_SET(out_pipe.as_raw_fd(), &mut read);
                }
                if !err_done {
                    libc::FD_SET(err_pipe.as_raw_fd(), &mut read);
                }
                libc::select(max + 1, &mut read, 0 as *mut _, 0 as *mut _,
                             0 as *mut _)
            };
            if r == -1 {
                let err = io::Error::last_os_error();
                if err.kind() == io::ErrorKind::Interrupted {
                    continue
                }
                return Err(err)
            }

            // Read as much as we can from each pipe, ignoring EWOULDBLOCK or
            // EAGAIN. If we hit EOF, then this will happen because the underlying
            // reader will return Ok(0), in which case we'll see `Ok` ourselves. In
            // this case we flip the other fd back into blocking mode and read
            // whatever's leftover on that file descriptor.
            let handle = |res: io::Result<_>| {
                match res {
                    Ok(_) => Ok(true),
                    Err(e) => {
                        if e.kind() == io::ErrorKind::WouldBlock {
                            Ok(false)
                        } else {
                            Err(e)
                        }
                    }
                }
            };
            if !out_done && handle(out_pipe.read_to_end(&mut out))? {
                out_done = true;
            }
            data(true, &mut out, out_done);
            if !err_done && handle(err_pipe.read_to_end(&mut err))? {
                err_done = true;
            }
            data(false, &mut err, err_done);

            if out_done && err_done {
                return Ok(())
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate miow;
    extern crate winapi;

    use std::io;
    use std::os::windows::prelude::*;
    use std::process::{ChildStdout, ChildStderr};
    use std::slice;

    use self::miow::iocp::{CompletionPort, CompletionStatus};
    use self::miow::pipe::NamedPipe;
    use self::miow::Overlapped;
    use self::winapi::ERROR_BROKEN_PIPE;

    struct Pipe<'a> {
        dst: &'a mut Vec<u8>,
        overlapped: Overlapped,
        pipe: NamedPipe,
        done: bool,
    }

    pub fn read2(out_pipe: ChildStdout,
                 err_pipe: ChildStderr,
                 data: &mut FnMut(bool, &mut Vec<u8>, bool)) -> io::Result<()> {
        let mut out = Vec::new();
        let mut err = Vec::new();

        let port = CompletionPort::new(1)?;
        port.add_handle(0, &out_pipe)?;
        port.add_handle(1, &err_pipe)?;

        unsafe {
            let mut out_pipe = Pipe::new(out_pipe, &mut out);
            let mut err_pipe = Pipe::new(err_pipe, &mut err);

            out_pipe.read()?;
            err_pipe.read()?;

            let mut status = [CompletionStatus::zero(), CompletionStatus::zero()];

            while !out_pipe.done || !err_pipe.done {
                for status in port.get_many(&mut status, None)? {
                    if status.token() == 0 {
                        out_pipe.complete(status);
                        data(true, out_pipe.dst, out_pipe.done);
                        out_pipe.read()?;
                    } else {
                        err_pipe.complete(status);
                        data(false, err_pipe.dst, err_pipe.done);
                        err_pipe.read()?;
                    }
                }
            }

            Ok(())
        }
    }

    impl<'a> Pipe<'a> {
        unsafe fn new<P: IntoRawHandle>(p: P, dst: &'a mut Vec<u8>) -> Pipe<'a> {
            Pipe {
                dst: dst,
                pipe: NamedPipe::from_raw_handle(p.into_raw_handle()),
                overlapped: Overlapped::zero(),
                done: false,
            }
        }

        unsafe fn read(&mut self) -> io::Result<()> {
            let dst = slice_to_end(self.dst);
            match self.pipe.read_overlapped(dst, self.overlapped.raw()) {
                Ok(_) => Ok(()),
                Err(e) => {
                    if e.raw_os_error() == Some(ERROR_BROKEN_PIPE as i32) {
                        self.done = true;
                        Ok(())
                    } else {
                        Err(e)
                    }
                }
            }
        }

        unsafe fn complete(&mut self, status: &CompletionStatus) {
            let prev = self.dst.len();
            self.dst.set_len(prev + status.bytes_transferred() as usize);
            if status.bytes_transferred() == 0 {
                self.done = true;
            }
        }
    }

    unsafe fn slice_to_end(v: &mut Vec<u8>) -> &mut [u8] {
        if v.capacity() == 0 {
            v.reserve(16);
        }
        if v.capacity() == v.len() {
            v.reserve(1);
        }
        slice::from_raw_parts_mut(v.as_mut_ptr().offset(v.len() as isize),
                                  v.capacity() - v.len())
    }
}
<commit_msg>Auto merge of #4477 - alexcrichton:fix-out-of-bounds, r=matklad<commit_after>pub use self::imp::read2;

#[cfg(unix)]
mod imp {
    use std::io::prelude::*;
    use std::io;
    use std::mem;
    use std::os::unix::prelude::*;
    use std::process::{ChildStdout, ChildStderr};
    use libc;

    pub fn read2(mut out_pipe: ChildStdout,
                 mut err_pipe: ChildStderr,
                 data: &mut FnMut(bool, &mut Vec<u8>, bool)) -> io::Result<()> {
        unsafe {
            libc::fcntl(out_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK);
            libc::fcntl(err_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK);
        }

        let mut out_done = false;
        let mut err_done = false;
        let mut out = Vec::new();
        let mut err = Vec::new();

        let mut fds: [libc::pollfd; 2] = unsafe { mem::zeroed() };
        fds[0].fd = out_pipe.as_raw_fd();
        fds[0].events = libc::POLLIN;
        fds[1].fd = err_pipe.as_raw_fd();
        fds[1].events = libc::POLLIN;
        loop {
            // wait for either pipe to become readable using `select`
            let r = unsafe { libc::poll(fds.as_mut_ptr(), 2, -1) };
            if r == -1 {
                let err = io::Error::last_os_error();
                if err.kind() == io::ErrorKind::Interrupted {
                    continue
                }
                return Err(err)
            }

            // Read as much as we can from each pipe, ignoring EWOULDBLOCK or
            // EAGAIN. If we hit EOF, then this will happen because the underlying
            // reader will return Ok(0), in which case we'll see `Ok` ourselves. In
            // this case we flip the other fd back into blocking mode and read
            // whatever's leftover on that file descriptor.
            let handle = |res: io::Result<_>| {
                match res {
                    Ok(_) => Ok(true),
                    Err(e) => {
                        if e.kind() == io::ErrorKind::WouldBlock {
                            Ok(false)
                        } else {
                            Err(e)
                        }
                    }
                }
            };
            if !out_done && fds[0].revents != 0 && handle(out_pipe.read_to_end(&mut out))? {
                out_done = true;
            }
            data(true, &mut out, out_done);
            if !err_done && fds[1].revents != 0 && handle(err_pipe.read_to_end(&mut err))? {
                err_done = true;
            }
            data(false, &mut err, err_done);

            if out_done && err_done {
                return Ok(())
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate miow;
    extern crate winapi;

    use std::io;
    use std::os::windows::prelude::*;
    use std::process::{ChildStdout, ChildStderr};
    use std::slice;

    use self::miow::iocp::{CompletionPort, CompletionStatus};
    use self::miow::pipe::NamedPipe;
    use self::miow::Overlapped;
    use self::winapi::ERROR_BROKEN_PIPE;

    struct Pipe<'a> {
        dst: &'a mut Vec<u8>,
        overlapped: Overlapped,
        pipe: NamedPipe,
        done: bool,
    }

    pub fn read2(out_pipe: ChildStdout,
                 err_pipe: ChildStderr,
                 data: &mut FnMut(bool, &mut Vec<u8>, bool)) -> io::Result<()> {
        let mut out = Vec::new();
        let mut err = Vec::new();

        let port = CompletionPort::new(1)?;
        port.add_handle(0, &out_pipe)?;
        port.add_handle(1, &err_pipe)?;

        unsafe {
            let mut out_pipe = Pipe::new(out_pipe, &mut out);
            let mut err_pipe = Pipe::new(err_pipe, &mut err);

            out_pipe.read()?;
            err_pipe.read()?;

            let mut status = [CompletionStatus::zero(), CompletionStatus::zero()];

            while !out_pipe.done || !err_pipe.done {
                for status in port.get_many(&mut status, None)? {
                    if status.token() == 0 {
                        out_pipe.complete(status);
                        data(true, out_pipe.dst, out_pipe.done);
                        out_pipe.read()?;
                    } else {
                        err_pipe.complete(status);
                        data(false, err_pipe.dst, err_pipe.done);
                        err_pipe.read()?;
                    }
                }
            }

            Ok(())
        }
    }

    impl<'a> Pipe<'a> {
        unsafe fn new<P: IntoRawHandle>(p: P, dst: &'a mut Vec<u8>) -> Pipe<'a> {
            Pipe {
                dst: dst,
                pipe: NamedPipe::from_raw_handle(p.into_raw_handle()),
                overlapped: Overlapped::zero(),
                done: false,
            }
        }

        unsafe fn read(&mut self) -> io::Result<()> {
            let dst = slice_to_end(self.dst);
            match self.pipe.read_overlapped(dst, self.overlapped.raw()) {
                Ok(_) => Ok(()),
                Err(e) => {
                    if e.raw_os_error() == Some(ERROR_BROKEN_PIPE as i32) {
                        self.done = true;
                        Ok(())
                    } else {
                        Err(e)
                    }
                }
            }
        }

        unsafe fn complete(&mut self, status: &CompletionStatus) {
            let prev = self.dst.len();
            self.dst.set_len(prev + status.bytes_transferred() as usize);
            if status.bytes_transferred() == 0 {
                self.done = true;
            }
        }
    }

    unsafe fn slice_to_end(v: &mut Vec<u8>) -> &mut [u8] {
        if v.capacity() == 0 {
            v.reserve(16);
        }
        if v.capacity() == v.len() {
            v.reserve(1);
        }
        slice::from_raw_parts_mut(v.as_mut_ptr().offset(v.len() as isize),
                                  v.capacity() - v.len())
    }
}
<|endoftext|>