<commit_before>use std::io;
use std::net::SocketAddr;
use std::time::{SystemTime, Duration};
use std::thread;

use router::Router;
use mount::Mount;
use iron::{Chain, Iron};

use crypto::{PublicKey, SecretKey, Hash};
use events::{Events, Reactor, NetworkConfiguration, Event, EventsConfiguration, Channel,
             MioChannel, Network, EventLoop, Milliseconds, EventHandler, Result as EventsResult,
             Error as EventsError};
use blockchain::{Blockchain, Schema, GenesisConfig, Transaction, ApiContext};
use messages::{Connect, RawMessage};
use explorer::ExplorerApi;
use api::Api;

use self::timeout_adjuster::TimeoutAdjuster;

pub use self::state::{State, Round, Height, RequestData, ValidatorId, TxPool, ValidatorState};

mod basic;
mod consensus;
mod requests;

pub mod state; // TODO: temporary solution to get access to WAIT consts
pub mod timeout_adjuster;

#[derive(Debug)]
pub enum ExternalMessage {
    Transaction(Box<Transaction>),
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum NodeTimeout {
    Status(Height),
    Round(u64, u32),
    Request(RequestData, Option<PublicKey>),
    Propose(u64, u32),
    PeerExchange,
}

#[derive(Clone)]
pub struct TxSender<S>
    where S: Channel<ApplicationEvent = ExternalMessage, Timeout = NodeTimeout>
{
    inner: S,
}

pub struct NodeHandler<S>
    where S: Channel<ApplicationEvent = ExternalMessage, Timeout = NodeTimeout>
{
    pub state: State,
    pub channel: S,
    pub blockchain: Blockchain,
    // TODO: move this into peer exchange service
    pub peer_discovery: Vec<SocketAddr>,
    timeout_adjuster: Box<TimeoutAdjuster>
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ListenerConfig {
    pub public_key: PublicKey,
    pub secret_key: SecretKey,
    pub address: SocketAddr,
}

/// An api configuration options
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct NodeApiConfig {
    /// Enable api endpoints for the `blockchain_explorer` on public api address.
    pub enable_blockchain_explorer: bool,
    /// Listen address for public api endpoints.
    pub public_api_address: Option<SocketAddr>,
    /// Listen address for private api endpoints.
    pub private_api_address: Option<SocketAddr>,
}

impl Default for NodeApiConfig {
    fn default() -> NodeApiConfig {
        NodeApiConfig {
            enable_blockchain_explorer: true,
            public_api_address: None,
            private_api_address: None,
        }
    }
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct NodeConfig {
    pub genesis: GenesisConfig,
    pub listen_address: SocketAddr,
    pub network: NetworkConfiguration,
    pub peers: Vec<SocketAddr>,
    pub public_key: PublicKey,
    pub secret_key: SecretKey,
    pub api: NodeApiConfig,
}

#[derive(Debug, Clone)]
pub struct Configuration {
    pub listener: ListenerConfig,
    pub events: EventsConfiguration,
    pub network: NetworkConfiguration,
    pub peer_discovery: Vec<SocketAddr>,
}

pub type NodeChannel = MioChannel<ExternalMessage, NodeTimeout>;

pub struct Node {
    reactor: Events<NodeHandler<NodeChannel>>,
    api_options: NodeApiConfig,
}

impl<S> NodeHandler<S>
    where S: Channel<ApplicationEvent = ExternalMessage, Timeout = NodeTimeout>
{
    pub fn new(blockchain: Blockchain, sender: S, config: Configuration) -> Self {
        // FIXME: remove unwraps here, use FATAL log level instead
        let (last_hash, last_height) = {
            let block = blockchain.last_block().unwrap();
            (block.hash(), block.height() + 1)
        };

        let stored = Schema::new(&blockchain.view())
            .actual_configuration()
            .unwrap();
        info!("Create node with config={:#?}", stored);

        let validator_id = stored
            .validators
            .iter()
            .position(|pk| pk == &config.listener.public_key)
            .map(|id| id as ValidatorId);
        info!("Validator={:#?}", validator_id);
        let connect = Connect::new(&config.listener.public_key,
                                   sender.address(),
                                   sender.get_time(),
                                   &config.listener.secret_key);

        let mut state = State::new(validator_id,
                                   config.listener.public_key,
                                   config.listener.secret_key,
                                   stored,
                                   connect,
                                   last_hash,
                                   last_height,
                                   sender.get_time());

        let mut timeout_adjuster = Box::new(timeout_adjuster::Constant::default());
        let timeout = timeout_adjuster.adjust_timeout(&state, blockchain.view());
        state.set_propose_timeout(timeout);

        NodeHandler {
            state: state,
            channel: sender,
            blockchain: blockchain,
            peer_discovery: config.peer_discovery,
            timeout_adjuster: timeout_adjuster,
        }
    }

    pub fn set_timeout_adjuster(&mut self, adjuster: Box<timeout_adjuster::TimeoutAdjuster>) {
        self.timeout_adjuster = adjuster;
    }

    pub fn propose_timeout(&self) -> Milliseconds {
        self.state().consensus_config().propose_timeout
    }

    pub fn round_timeout(&self) -> Milliseconds {
        self.state().consensus_config().round_timeout
    }

    pub fn status_timeout(&self) -> Milliseconds {
        self.state().consensus_config().status_timeout
    }

    pub fn peers_timeout(&self) -> Milliseconds {
        self.state().consensus_config().peers_timeout
    }

    pub fn txs_block_limit(&self) -> u32 {
        self.state().consensus_config().txs_block_limit
    }

    pub fn state(&self) -> &State {
        &self.state
    }

    pub fn initialize(&mut self) {
        info!("Start listening address={}", self.channel.address());
        for address in &self.peer_discovery.clone() {
            if address == &self.channel.address() {
                continue;
            }
            self.connect(address);
            info!("Try to connect with peer {}", address);
        }

        let round = 1;
        self.state.jump_round(round);
        info!("Jump to round {}", round);

        self.add_round_timeout();
        self.add_status_timeout();
        self.add_peer_exchange_timeout();
    }

    pub fn send_to_validator(&mut self, id: u32, message: &RawMessage) {
        // TODO: check validator id
        let public_key = self.state.validators()[id as usize];
        self.send_to_peer(public_key, message);
    }

    pub fn send_to_peer(&mut self, public_key: PublicKey, message: &RawMessage) {
        if let Some(conn) = self.state.peers().get(&public_key) {
            trace!("Send to addr: {}", conn.addr());
            self.channel.send_to(&conn.addr(), message.clone());
        } else {
            warn!("Hasn't connection with peer {:?}", public_key);
        }
    }

    pub fn send_to_addr(&mut self, address: &SocketAddr, message: &RawMessage) {
        trace!("Send to addr: {}", address);
        self.channel.send_to(address, message.clone());
    }

    // TODO: use Into<RawMessage>
    pub fn broadcast(&mut self, message: &RawMessage) {
        for conn in self.state.peers().values() {
            trace!("Send to addr: {}", conn.addr());
            self.channel.send_to(&conn.addr(), message.clone());
        }
    }

    pub fn connect(&mut self, address: &SocketAddr) {
        self.channel.connect(address);
    }

    pub fn request(&mut self, data: RequestData, peer: PublicKey) {
        let is_new = self.state.request(data.clone(), peer);
        if is_new {
            self.add_request_timeout(data, None);
        }
    }

    pub fn add_round_timeout(&mut self) {
        let time = self.round_start_time(self.state.round() + 1);
        trace!("ADD ROUND TIMEOUT, time={:?}, height={}, round={}",
               time,
               self.state.height(),
               self.state.round());
        let timeout = NodeTimeout::Round(self.state.height(), self.state.round());
        self.channel.add_timeout(timeout, time);
    }

    pub fn add_propose_timeout(&mut self) {
        let adjusted_propose_timeout = self.state.propose_timeout();
        let time = self.round_start_time(self.state.round()) +
                   Duration::from_millis(adjusted_propose_timeout);

        trace!("ADD PROPOSE TIMEOUT, time={:?}, height={}, round={}",
               time,
               self.state.height(),
               self.state.round());
        let timeout = NodeTimeout::Propose(self.state.height(), self.state.round());
        self.channel.add_timeout(timeout, time);
    }

    pub fn add_status_timeout(&mut self) {
        let time = self.channel.get_time() + Duration::from_millis(self.status_timeout());
        self.channel
            .add_timeout(NodeTimeout::Status(self.state.height()), time);
    }

    pub fn add_request_timeout(&mut self, data: RequestData, peer: Option<PublicKey>) {
        trace!("ADD REQUEST TIMEOUT");
        let time = self.channel.get_time() + data.timeout();
        self.channel
            .add_timeout(NodeTimeout::Request(data, peer), time);
    }

    pub fn add_peer_exchange_timeout(&mut self) {
        let time = self.channel.get_time() + Duration::from_millis(self.peers_timeout());
        self.channel.add_timeout(NodeTimeout::PeerExchange, time);
    }

    pub fn last_block_hash(&self) -> Hash {
        self.blockchain.last_block().unwrap().hash()
    }

    pub fn round_start_time(&self, round: Round) -> SystemTime {
        let ms = (round - 1) as u64 * self.round_timeout();
        self.state.height_start_time() + Duration::from_millis(ms)
    }
}

impl<S> EventHandler for NodeHandler<S>
    where S: Channel<ApplicationEvent = ExternalMessage, Timeout = NodeTimeout>
{
    type Timeout = NodeTimeout;
    type ApplicationEvent = ExternalMessage;

    fn handle_event(&mut self, event: Event) {
        match event {
            Event::Connected(addr) => self.handle_connected(&addr),
            Event::Disconnected(addr) => self.handle_disconnected(&addr),
            Event::Incoming(raw) => self.handle_message(raw),
            Event::Error(_) => {}
        }
    }

    fn handle_application_event(&mut self, event: Self::ApplicationEvent) {
        match event {
            ExternalMessage::Transaction(tx) => {
                self.handle_incoming_tx(tx);
            }
        }
    }

    fn handle_timeout(&mut self, timeout: Self::Timeout) {
        match timeout {
            NodeTimeout::Round(height, round) => self.handle_round_timeout(height, round),
            NodeTimeout::Request(data, peer) => self.handle_request_timeout(data, peer),
            NodeTimeout::Status(height) => self.handle_status_timeout(height),
            NodeTimeout::PeerExchange => self.handle_peer_exchange_timeout(),
            NodeTimeout::Propose(height, round) => self.handle_propose_timeout(height, round),
        }
    }
}

pub trait TransactionSend: Send + Sync {
    fn send<T: Transaction>(&self, tx: T) -> EventsResult<()>;
}

impl<S> TxSender<S>
    where S: Channel<ApplicationEvent = ExternalMessage, Timeout = NodeTimeout>
{
    pub fn new(inner: S) -> TxSender<S> {
        TxSender { inner: inner }
    }
}

impl<S> TransactionSend for TxSender<S>
    where S: Channel<ApplicationEvent = ExternalMessage, Timeout = NodeTimeout>
{
    fn send<T: Transaction>(&self, tx: T) -> EventsResult<()> {
        // TODO remove double data convertation
        if !tx.verify() {
            return Err(EventsError::new("Unable to verify transaction"));
        }
        let msg = ExternalMessage::Transaction(Box::new(tx));
        self.inner.post_event(msg)
    }
}

impl Node {
    /// Creates node for the given blockchain and node configuration
    pub fn new(blockchain: Blockchain, node_cfg: NodeConfig) -> Node {
        blockchain
            .create_genesis_block(node_cfg.genesis.clone())
            .unwrap();

        let config = Configuration {
            listener: ListenerConfig {
                public_key: node_cfg.public_key,
                secret_key: node_cfg.secret_key,
                address: node_cfg.listen_address,
            },
            network: node_cfg.network,
            events: EventsConfiguration::default(),
            peer_discovery: node_cfg.peers,
        };
        let network = Network::with_config(node_cfg.listen_address, config.network);
        let event_loop = EventLoop::configured(config.events.clone()).unwrap();
        let channel = NodeChannel::new(node_cfg.listen_address, event_loop.channel());
        let worker = NodeHandler::new(blockchain, channel, config);
        Node {
            reactor: Events::with_event_loop(network, worker, event_loop),
            api_options: node_cfg.api,
        }
    }

    /// Launches only consensus messages handler.
    /// This may be used if you want to customize api with the `ApiContext`.
    pub fn run_handler(&mut self) -> io::Result<()> {
        self.reactor.bind()?;
        self.reactor.handler_mut().initialize();
        self.reactor.run()
    }

    /// A generic implementation that launches `Node` and optionally creates threads
    /// for public and private api handlers.
    /// Explorer api prefix is `/api/explorer`
    /// Public api prefix is `/api/services/{service_name}`
    /// Private api prefix is `/api/services/{service_name}`
    pub fn run(&mut self) -> io::Result<()> {
        let blockchain = self.handler().blockchain.clone();

        let private_config_api_thread = match self.api_options.private_api_address {
            Some(listen_address) => {
                let api_context = ApiContext::new(self);
                let mut mount = Mount::new();
                mount.mount("services", api_context.mount_private_api());

                let thread = thread::spawn(move || {
                                               info!("Private exonum api started on {}",
                                                     listen_address);
                                               let chain = Chain::new(mount);
                                               Iron::new(chain).http(listen_address).unwrap();
                                           });
                Some(thread)
            }
            None => None,
        };
        let public_config_api_thread = match self.api_options.public_api_address {
            Some(listen_address) => {
                let api_context = ApiContext::new(self);
                let mut mount = Mount::new();
                mount.mount("api/services", api_context.mount_public_api());

                if self.api_options.enable_blockchain_explorer {
                    let mut router = Router::new();
                    let explorer_api = ExplorerApi::new(blockchain);
                    explorer_api.wire(&mut router);
                    mount.mount("api/explorer", router);
                }

                let thread = thread::spawn(move || {
                                               info!("Public exonum api started on {}",
                                                     listen_address);

                                               let chain = Chain::new(mount);
                                               Iron::new(chain).http(listen_address).unwrap();
                                           });
                Some(thread)
            }
            None => None,
        };

        self.run_handler()?;

        if let Some(private_config_api_thread) = private_config_api_thread {
            private_config_api_thread.join().unwrap();
        }
        if let Some(public_config_api_thread) = public_config_api_thread {
            public_config_api_thread.join().unwrap();
        }

        Ok(())
    }

    pub fn state(&self) -> &State {
        self.reactor.handler().state()
    }

    pub fn handler(&self) -> &NodeHandler<NodeChannel> {
        self.reactor.handler()
    }

    pub fn channel(&self) -> TxSender<NodeChannel> {
        TxSender::new(self.reactor.handler().channel.clone())
    }
}
<commit_msg>make public/private endpoints' roots look uniform<commit_after>use std::io;
use std::net::SocketAddr;
use std::time::{SystemTime, Duration};
use std::thread;

use router::Router;
use mount::Mount;
use iron::{Chain, Iron};

use crypto::{PublicKey, SecretKey, Hash};
use events::{Events, Reactor, NetworkConfiguration, Event, EventsConfiguration, Channel,
             MioChannel, Network, EventLoop, Milliseconds, EventHandler, Result as EventsResult,
             Error as EventsError};
use blockchain::{Blockchain, Schema, GenesisConfig, Transaction, ApiContext};
use messages::{Connect, RawMessage};
use explorer::ExplorerApi;
use api::Api;

use self::timeout_adjuster::TimeoutAdjuster;

pub use self::state::{State, Round, Height, RequestData, ValidatorId, TxPool, ValidatorState};

mod basic;
mod consensus;
mod requests;

pub mod state; // TODO: temporary solution to get access to WAIT consts
pub mod timeout_adjuster;

#[derive(Debug)]
pub enum ExternalMessage {
    Transaction(Box<Transaction>),
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum NodeTimeout {
    Status(Height),
    Round(u64, u32),
    Request(RequestData, Option<PublicKey>),
    Propose(u64, u32),
    PeerExchange,
}

#[derive(Clone)]
pub struct TxSender<S>
    where S: Channel<ApplicationEvent = ExternalMessage, Timeout = NodeTimeout>
{
    inner: S,
}

pub struct NodeHandler<S>
    where S: Channel<ApplicationEvent = ExternalMessage, Timeout = NodeTimeout>
{
    pub state: State,
    pub channel: S,
    pub blockchain: Blockchain,
    // TODO: move this into peer exchange service
    pub peer_discovery: Vec<SocketAddr>,
    timeout_adjuster: Box<TimeoutAdjuster>
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ListenerConfig {
    pub public_key: PublicKey,
    pub secret_key: SecretKey,
    pub address: SocketAddr,
}

/// An api configuration options
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct NodeApiConfig {
    /// Enable api endpoints for the `blockchain_explorer` on public api address.
    pub enable_blockchain_explorer: bool,
    /// Listen address for public api endpoints.
    pub public_api_address: Option<SocketAddr>,
    /// Listen address for private api endpoints.
    pub private_api_address: Option<SocketAddr>,
}

impl Default for NodeApiConfig {
    fn default() -> NodeApiConfig {
        NodeApiConfig {
            enable_blockchain_explorer: true,
            public_api_address: None,
            private_api_address: None,
        }
    }
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct NodeConfig {
    pub genesis: GenesisConfig,
    pub listen_address: SocketAddr,
    pub network: NetworkConfiguration,
    pub peers: Vec<SocketAddr>,
    pub public_key: PublicKey,
    pub secret_key: SecretKey,
    pub api: NodeApiConfig,
}

#[derive(Debug, Clone)]
pub struct Configuration {
    pub listener: ListenerConfig,
    pub events: EventsConfiguration,
    pub network: NetworkConfiguration,
    pub peer_discovery: Vec<SocketAddr>,
}

pub type NodeChannel = MioChannel<ExternalMessage, NodeTimeout>;

pub struct Node {
    reactor: Events<NodeHandler<NodeChannel>>,
    api_options: NodeApiConfig,
}

impl<S> NodeHandler<S>
    where S: Channel<ApplicationEvent = ExternalMessage, Timeout = NodeTimeout>
{
    pub fn new(blockchain: Blockchain, sender: S, config: Configuration) -> Self {
        // FIXME: remove unwraps here, use FATAL log level instead
        let (last_hash, last_height) = {
            let block = blockchain.last_block().unwrap();
            (block.hash(), block.height() + 1)
        };

        let stored = Schema::new(&blockchain.view())
            .actual_configuration()
            .unwrap();
        info!("Create node with config={:#?}", stored);

        let validator_id = stored
            .validators
            .iter()
            .position(|pk| pk == &config.listener.public_key)
            .map(|id| id as ValidatorId);
        info!("Validator={:#?}", validator_id);
        let connect = Connect::new(&config.listener.public_key,
                                   sender.address(),
                                   sender.get_time(),
                                   &config.listener.secret_key);

        let mut state = State::new(validator_id,
                                   config.listener.public_key,
                                   config.listener.secret_key,
                                   stored,
                                   connect,
                                   last_hash,
                                   last_height,
                                   sender.get_time());

        let mut timeout_adjuster = Box::new(timeout_adjuster::Constant::default());
        let timeout = timeout_adjuster.adjust_timeout(&state, blockchain.view());
        state.set_propose_timeout(timeout);

        NodeHandler {
            state: state,
            channel: sender,
            blockchain: blockchain,
            peer_discovery: config.peer_discovery,
            timeout_adjuster: timeout_adjuster,
        }
    }

    pub fn set_timeout_adjuster(&mut self, adjuster: Box<timeout_adjuster::TimeoutAdjuster>) {
        self.timeout_adjuster = adjuster;
    }

    pub fn propose_timeout(&self) -> Milliseconds {
        self.state().consensus_config().propose_timeout
    }

    pub fn round_timeout(&self) -> Milliseconds {
        self.state().consensus_config().round_timeout
    }

    pub fn status_timeout(&self) -> Milliseconds {
        self.state().consensus_config().status_timeout
    }

    pub fn peers_timeout(&self) -> Milliseconds {
        self.state().consensus_config().peers_timeout
    }

    pub fn txs_block_limit(&self) -> u32 {
        self.state().consensus_config().txs_block_limit
    }

    pub fn state(&self) -> &State {
        &self.state
    }

    pub fn initialize(&mut self) {
        info!("Start listening address={}", self.channel.address());
        for address in &self.peer_discovery.clone() {
            if address == &self.channel.address() {
                continue;
            }
            self.connect(address);
            info!("Try to connect with peer {}", address);
        }

        let round = 1;
        self.state.jump_round(round);
        info!("Jump to round {}", round);

        self.add_round_timeout();
        self.add_status_timeout();
        self.add_peer_exchange_timeout();
    }

    pub fn send_to_validator(&mut self, id: u32, message: &RawMessage) {
        // TODO: check validator id
        let public_key = self.state.validators()[id as usize];
        self.send_to_peer(public_key, message);
    }

    pub fn send_to_peer(&mut self, public_key: PublicKey, message: &RawMessage) {
        if let Some(conn) = self.state.peers().get(&public_key) {
            trace!("Send to addr: {}", conn.addr());
            self.channel.send_to(&conn.addr(), message.clone());
        } else {
            warn!("Hasn't connection with peer {:?}", public_key);
        }
    }

    pub fn send_to_addr(&mut self, address: &SocketAddr, message: &RawMessage) {
        trace!("Send to addr: {}", address);
        self.channel.send_to(address, message.clone());
    }

    // TODO: use Into<RawMessage>
    pub fn broadcast(&mut self, message: &RawMessage) {
        for conn in self.state.peers().values() {
            trace!("Send to addr: {}", conn.addr());
            self.channel.send_to(&conn.addr(), message.clone());
        }
    }

    pub fn connect(&mut self, address: &SocketAddr) {
        self.channel.connect(address);
    }

    pub fn request(&mut self, data: RequestData, peer: PublicKey) {
        let is_new = self.state.request(data.clone(), peer);
        if is_new {
            self.add_request_timeout(data, None);
        }
    }

    pub fn add_round_timeout(&mut self) {
        let time = self.round_start_time(self.state.round() + 1);
        trace!("ADD ROUND TIMEOUT, time={:?}, height={}, round={}",
               time,
               self.state.height(),
               self.state.round());
        let timeout = NodeTimeout::Round(self.state.height(), self.state.round());
        self.channel.add_timeout(timeout, time);
    }

    pub fn add_propose_timeout(&mut self) {
        let adjusted_propose_timeout = self.state.propose_timeout();
        let time = self.round_start_time(self.state.round()) +
                   Duration::from_millis(adjusted_propose_timeout);

        trace!("ADD PROPOSE TIMEOUT, time={:?}, height={}, round={}",
               time,
               self.state.height(),
               self.state.round());
        let timeout = NodeTimeout::Propose(self.state.height(), self.state.round());
        self.channel.add_timeout(timeout, time);
    }

    pub fn add_status_timeout(&mut self) {
        let time = self.channel.get_time() + Duration::from_millis(self.status_timeout());
        self.channel
            .add_timeout(NodeTimeout::Status(self.state.height()), time);
    }

    pub fn add_request_timeout(&mut self, data: RequestData, peer: Option<PublicKey>) {
        trace!("ADD REQUEST TIMEOUT");
        let time = self.channel.get_time() + data.timeout();
        self.channel
            .add_timeout(NodeTimeout::Request(data, peer), time);
    }

    pub fn add_peer_exchange_timeout(&mut self) {
        let time = self.channel.get_time() + Duration::from_millis(self.peers_timeout());
        self.channel.add_timeout(NodeTimeout::PeerExchange, time);
    }

    pub fn last_block_hash(&self) -> Hash {
        self.blockchain.last_block().unwrap().hash()
    }

    pub fn round_start_time(&self, round: Round) -> SystemTime {
        let ms = (round - 1) as u64 * self.round_timeout();
        self.state.height_start_time() + Duration::from_millis(ms)
    }
}

impl<S> EventHandler for NodeHandler<S>
    where S: Channel<ApplicationEvent = ExternalMessage, Timeout = NodeTimeout>
{
    type Timeout = NodeTimeout;
    type ApplicationEvent = ExternalMessage;

    fn handle_event(&mut self, event: Event) {
        match event {
            Event::Connected(addr) => self.handle_connected(&addr),
            Event::Disconnected(addr) => self.handle_disconnected(&addr),
            Event::Incoming(raw) => self.handle_message(raw),
            Event::Error(_) => {}
        }
    }

    fn handle_application_event(&mut self, event: Self::ApplicationEvent) {
        match event {
            ExternalMessage::Transaction(tx) => {
                self.handle_incoming_tx(tx);
            }
        }
    }

    fn handle_timeout(&mut self, timeout: Self::Timeout) {
        match timeout {
            NodeTimeout::Round(height, round) => self.handle_round_timeout(height, round),
            NodeTimeout::Request(data, peer) => self.handle_request_timeout(data, peer),
            NodeTimeout::Status(height) => self.handle_status_timeout(height),
            NodeTimeout::PeerExchange => self.handle_peer_exchange_timeout(),
            NodeTimeout::Propose(height, round) => self.handle_propose_timeout(height, round),
        }
    }
}

pub trait TransactionSend: Send + Sync {
    fn send<T: Transaction>(&self, tx: T) -> EventsResult<()>;
}

impl<S> TxSender<S>
    where S: Channel<ApplicationEvent = ExternalMessage, Timeout = NodeTimeout>
{
    pub fn new(inner: S) -> TxSender<S> {
        TxSender { inner: inner }
    }
}

impl<S> TransactionSend for TxSender<S>
    where S: Channel<ApplicationEvent = ExternalMessage, Timeout = NodeTimeout>
{
    fn send<T: Transaction>(&self, tx: T) -> EventsResult<()> {
        // TODO remove double data convertation
        if !tx.verify() {
            return Err(EventsError::new("Unable to verify transaction"));
        }
        let msg = ExternalMessage::Transaction(Box::new(tx));
        self.inner.post_event(msg)
    }
}

impl Node {
    /// Creates node for the given blockchain and node configuration
    pub fn new(blockchain: Blockchain, node_cfg: NodeConfig) -> Node {
        blockchain
            .create_genesis_block(node_cfg.genesis.clone())
            .unwrap();

        let config = Configuration {
            listener: ListenerConfig {
                public_key: node_cfg.public_key,
                secret_key: node_cfg.secret_key,
                address: node_cfg.listen_address,
            },
            network: node_cfg.network,
            events: EventsConfiguration::default(),
            peer_discovery: node_cfg.peers,
        };
        let network = Network::with_config(node_cfg.listen_address, config.network);
        let event_loop = EventLoop::configured(config.events.clone()).unwrap();
        let channel = NodeChannel::new(node_cfg.listen_address, event_loop.channel());
        let worker = NodeHandler::new(blockchain, channel, config);
        Node {
            reactor: Events::with_event_loop(network, worker, event_loop),
            api_options: node_cfg.api,
        }
    }

    /// Launches only consensus messages handler.
    /// This may be used if you want to customize api with the `ApiContext`.
    pub fn run_handler(&mut self) -> io::Result<()> {
        self.reactor.bind()?;
        self.reactor.handler_mut().initialize();
        self.reactor.run()
    }

    /// A generic implementation that launches `Node` and optionally creates threads
    /// for public and private api handlers.
    /// Explorer api prefix is `/api/explorer`
    /// Public api prefix is `/api/services/{service_name}`
    /// Private api prefix is `/api/services/{service_name}`
    pub fn run(&mut self) -> io::Result<()> {
        let blockchain = self.handler().blockchain.clone();

        let private_config_api_thread = match self.api_options.private_api_address {
            Some(listen_address) => {
                let api_context = ApiContext::new(self);
                let mut mount = Mount::new();
                mount.mount("api/services", api_context.mount_private_api());

                let thread = thread::spawn(move || {
                                               info!("Private exonum api started on {}",
                                                     listen_address);
                                               let chain = Chain::new(mount);
                                               Iron::new(chain).http(listen_address).unwrap();
                                           });
                Some(thread)
            }
            None => None,
        };
        let public_config_api_thread = match self.api_options.public_api_address {
            Some(listen_address) => {
                let api_context = ApiContext::new(self);
                let mut mount = Mount::new();
                mount.mount("api/services", api_context.mount_public_api());

                if self.api_options.enable_blockchain_explorer {
                    let mut router = Router::new();
                    let explorer_api = ExplorerApi::new(blockchain);
                    explorer_api.wire(&mut router);
                    mount.mount("api/explorer", router);
                }

                let thread = thread::spawn(move || {
                                               info!("Public exonum api started on {}",
                                                     listen_address);

                                               let chain = Chain::new(mount);
                                               Iron::new(chain).http(listen_address).unwrap();
                                           });
                Some(thread)
            }
            None => None,
        };

        self.run_handler()?;

        if let Some(private_config_api_thread) = private_config_api_thread {
            private_config_api_thread.join().unwrap();
        }
        if let Some(public_config_api_thread) = public_config_api_thread {
            public_config_api_thread.join().unwrap();
        }

        Ok(())
    }

    pub fn state(&self) -> &State {
        self.reactor.handler().state()
    }

    pub fn handler(&self) -> &NodeHandler<NodeChannel> {
        self.reactor.handler()
    }

    pub fn channel(&self) -> TxSender<NodeChannel> {
        TxSender::new(self.reactor.handler().channel.clone())
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Timing functions.

use heartbeats;
use ipc_channel::ipc::{self, IpcReceiver};
use profile_traits::time::{ProfilerCategory, ProfilerChan, ProfilerMsg, TimerMetadata};
use std::borrow::ToOwned;
use std::cmp::Ordering;
use std::collections::BTreeMap;
use std::f64;
use std::thread::sleep_ms;
use std_time::precise_time_ns;
use util::task::spawn_named;

pub trait Formattable {
    fn format(&self) -> String;
}

impl Formattable for Option<TimerMetadata> {
    fn format(&self) -> String {
        match self {
            // TODO(cgaebel): Center-align in the format strings as soon as rustc supports it.
            &Some(ref meta) => {
                let url = &*meta.url;
                let url = if url.len() > 30 {
                    &url[..30]
                } else {
                    url
                };
                let incremental = if meta.incremental { "    yes" } else { "    no " };
                let iframe = if meta.iframe { "  yes" } else { "  no " };
                format!(" {:14} {:9} {:30}", incremental, iframe, url)
            },
            &None =>
                format!(" {:14} {:9} {:30}", "    N/A", "  N/A", "             N/A")
        }
    }
}

impl Formattable for ProfilerCategory {
    // some categories are subcategories of LayoutPerformCategory
    // and should be printed to indicate this
    fn format(&self) -> String {
        let padding = match *self {
            ProfilerCategory::LayoutStyleRecalc |
            ProfilerCategory::LayoutRestyleDamagePropagation |
            ProfilerCategory::LayoutNonIncrementalReset |
            ProfilerCategory::LayoutGeneratedContent |
            ProfilerCategory::LayoutMain |
            ProfilerCategory::LayoutDispListBuild |
            ProfilerCategory::LayoutShaping |
            ProfilerCategory::LayoutDamagePropagate |
            ProfilerCategory::PaintingPerTile |
            ProfilerCategory::PaintingPrepBuff => "+ ",
            ProfilerCategory::LayoutParallelWarmup |
            ProfilerCategory::LayoutSelectorMatch |
            ProfilerCategory::LayoutTreeBuilder => "| + ",
            _ => ""
        };
        let name = match *self {
            ProfilerCategory::Compositing => "Compositing",
            ProfilerCategory::LayoutPerform => "Layout",
            ProfilerCategory::LayoutStyleRecalc => "Style Recalc",
            ProfilerCategory::LayoutRestyleDamagePropagation => "Restyle Damage Propagation",
            ProfilerCategory::LayoutNonIncrementalReset => "Non-incremental reset (temporary)",
            ProfilerCategory::LayoutSelectorMatch => "Selector Matching",
            ProfilerCategory::LayoutTreeBuilder => "Tree Building",
            ProfilerCategory::LayoutDamagePropagate => "Damage Propagation",
            ProfilerCategory::LayoutGeneratedContent => "Generated Content Resolution",
            ProfilerCategory::LayoutMain => "Primary Layout Pass",
            ProfilerCategory::LayoutParallelWarmup => "Parallel Warmup",
            ProfilerCategory::LayoutShaping => "Shaping",
            ProfilerCategory::LayoutDispListBuild => "Display List Construction",
            ProfilerCategory::PaintingPerTile => "Painting Per Tile",
            ProfilerCategory::PaintingPrepBuff => "Buffer Prep",
            ProfilerCategory::Painting => "Painting",
            ProfilerCategory::ImageDecoding => "Image Decoding",
        };
        format!("{}{}", padding, name)
    }
}

type ProfilerBuckets = BTreeMap<(ProfilerCategory, Option<TimerMetadata>), Vec<f64>>;

// back end of the profiler that handles data aggregation and performance metrics
pub struct Profiler {
    pub port: IpcReceiver<ProfilerMsg>,
    buckets: ProfilerBuckets,
    pub last_msg: Option<ProfilerMsg>,
}

impl Profiler {
    pub fn create(period: Option<f64>) -> ProfilerChan {
        let (chan, port) = ipc::channel().unwrap();
        match period {
            Some(period) => {
                let period = (period * 1000.) as u32;
                let chan = chan.clone();
                spawn_named("Time profiler timer".to_owned(), move || {
                    loop {
                        sleep_ms(period);
                        if chan.send(ProfilerMsg::Print).is_err() {
                            break;
                        }
                    }
                });
                // Spawn the time profiler.
                spawn_named("Time profiler".to_owned(), move || {
                    let mut profiler = Profiler::new(port);
                    profiler.start();
                });
            }
            None => {
                // No-op to handle messages when the time profiler is inactive.
                spawn_named("Time profiler".to_owned(), move || {
                    loop {
                        match port.recv() {
                            Err(_) | Ok(ProfilerMsg::Exit) => break,
                            _ => {}
                        }
                    }
                });
            }
        }
        heartbeats::init();

        ProfilerChan(chan)
    }

    pub fn new(port: IpcReceiver<ProfilerMsg>) -> Profiler {
        Profiler {
            port: port,
            buckets: BTreeMap::new(),
            last_msg: None,
        }
    }

    pub fn start(&mut self) {
        loop {
            let msg = self.port.recv();
            match msg {
               Ok(msg) => {
                   if !self.handle_msg(msg) {
                       break
                   }
               }
               _ => break
            }
        }
    }

    fn find_or_insert(&mut self, k: (ProfilerCategory, Option<TimerMetadata>), t: f64) {
        match self.buckets.get_mut(&k) {
            None => {},
            Some(v) => { v.push(t); return; },
        }

        self.buckets.insert(k, vec!(t));
    }

    fn handle_msg(&mut self, msg: ProfilerMsg) -> bool {
        match msg.clone() {
            ProfilerMsg::Time(k, t) => {
                heartbeats::maybe_heartbeat(&k.0, t.0, t.1, 0, 0);
                let ms = (t.1 - t.0) as f64 / 1000000f64;
                self.find_or_insert(k, ms);
            },
            ProfilerMsg::Print => match self.last_msg {
                // only print if more data has arrived since the last printout
                Some(ProfilerMsg::Time(..)) => self.print_buckets(),
                _ => ()
            },
            ProfilerMsg::Exit => {
                heartbeats::cleanup();
                return false;
            },
        };
        self.last_msg = Some(msg);
        true
    }

    fn print_buckets(&mut self) {
        println!("{:35} {:14} {:9} {:30} {:15} {:15} {:-15} {:-15} {:-15}",
                 "_category_", "_incremental?_", "_iframe?_",
                 "            _url_", "    _mean (ms)_", "  _median (ms)_",
                 "     _min (ms)_", "     _max (ms)_", "      _events_");
        for (&(ref category, ref meta), ref mut data) in &mut self.buckets {
            data.sort_by(|a, b| {
                if a < b {
                    Ordering::Less
                } else {
                    Ordering::Greater
                }
            });
            let data_len = data.len();
            if data_len > 0 {
                let (mean, median, min, max) =
                    (data.iter().map(|&x|x).sum::<f64>() / (data_len as f64),
                     data[data_len / 2],
                     data.iter().fold(f64::INFINITY, |a, &b| a.min(b)),
                     data.iter().fold(-f64::INFINITY, |a, &b| a.max(b)));
                println!("{:-35}{} {:15.4} {:15.4} {:15.4} {:15.4} {:15}",
                         category.format(), meta.format(), mean, median, min, max, data_len);
            }
        }
        println!("");
    }
}

pub fn time<T, F>(msg: &str, callback: F) -> T
    where F: Fn() -> T
{
    let start_time = precise_time_ns();
    let val = callback();
    let end_time = precise_time_ns();
    let ms = (end_time - start_time) as f64 / 1000000f64;
    if ms >= 5f64 {
        debug!("{} took {} ms", msg, ms);
    }
    return val;
}
<commit_msg>Issue #7501 emove unused time function in time module of profile<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Timing functions.

use heartbeats;
use ipc_channel::ipc::{self, IpcReceiver};
use profile_traits::time::{ProfilerCategory, ProfilerChan, ProfilerMsg, TimerMetadata};
use std::borrow::ToOwned;
use std::cmp::Ordering;
use std::collections::BTreeMap;
use std::f64;
use std::thread::sleep_ms;
use std_time::precise_time_ns;
use util::task::spawn_named;

pub trait Formattable {
    fn format(&self) -> String;
}

impl Formattable for Option<TimerMetadata> {
    fn format(&self) -> String {
        match self {
            // TODO(cgaebel): Center-align in the format strings as soon as rustc supports it.
            &Some(ref meta) => {
                let url = &*meta.url;
                let url = if url.len() > 30 {
                    &url[..30]
                } else {
                    url
                };
                let incremental = if meta.incremental { "    yes" } else { "    no " };
                let iframe = if meta.iframe { "  yes" } else { "  no " };
                format!(" {:14} {:9} {:30}", incremental, iframe, url)
            },
            &None =>
                format!(" {:14} {:9} {:30}", "    N/A", "  N/A", "             N/A")
        }
    }
}

impl Formattable for ProfilerCategory {
    // some categories are subcategories of LayoutPerformCategory
    // and should be printed to indicate this
    fn format(&self) -> String {
        let padding = match *self {
            ProfilerCategory::LayoutStyleRecalc |
            ProfilerCategory::LayoutRestyleDamagePropagation |
            ProfilerCategory::LayoutNonIncrementalReset |
            ProfilerCategory::LayoutGeneratedContent |
            ProfilerCategory::LayoutMain |
            ProfilerCategory::LayoutDispListBuild |
            ProfilerCategory::LayoutShaping |
            ProfilerCategory::LayoutDamagePropagate |
            ProfilerCategory::PaintingPerTile |
            ProfilerCategory::PaintingPrepBuff => "+ ",
            ProfilerCategory::LayoutParallelWarmup |
            ProfilerCategory::LayoutSelectorMatch |
            ProfilerCategory::LayoutTreeBuilder => "| + ",
            _ => ""
        };
        let name = match *self {
            ProfilerCategory::Compositing => "Compositing",
            ProfilerCategory::LayoutPerform => "Layout",
            ProfilerCategory::LayoutStyleRecalc => "Style Recalc",
            ProfilerCategory::LayoutRestyleDamagePropagation => "Restyle Damage Propagation",
            ProfilerCategory::LayoutNonIncrementalReset => "Non-incremental reset (temporary)",
            ProfilerCategory::LayoutSelectorMatch => "Selector Matching",
            ProfilerCategory::LayoutTreeBuilder => "Tree Building",
            ProfilerCategory::LayoutDamagePropagate => "Damage Propagation",
            ProfilerCategory::LayoutGeneratedContent => "Generated Content Resolution",
            ProfilerCategory::LayoutMain => "Primary Layout Pass",
            ProfilerCategory::LayoutParallelWarmup => "Parallel Warmup",
            ProfilerCategory::LayoutShaping => "Shaping",
            ProfilerCategory::LayoutDispListBuild => "Display List Construction",
            ProfilerCategory::PaintingPerTile => "Painting Per Tile",
            ProfilerCategory::PaintingPrepBuff => "Buffer Prep",
            ProfilerCategory::Painting => "Painting",
            ProfilerCategory::ImageDecoding => "Image Decoding",
        };
        format!("{}{}", padding, name)
    }
}

type ProfilerBuckets = BTreeMap<(ProfilerCategory, Option<TimerMetadata>), Vec<f64>>;

// back end of the profiler that handles data aggregation and performance metrics
pub struct Profiler {
    pub port: IpcReceiver<ProfilerMsg>,
    buckets: ProfilerBuckets,
    pub last_msg: Option<ProfilerMsg>,
}

impl Profiler {
    pub fn create(period: Option<f64>) -> ProfilerChan {
        let (chan, port) = ipc::channel().unwrap();
        match period {
            Some(period) => {
                let period = (period * 1000.) as u32;
                let chan = chan.clone();
                spawn_named("Time profiler timer".to_owned(), move || {
                    loop {
                        sleep_ms(period);
                        if chan.send(ProfilerMsg::Print).is_err() {
                            break;
                        }
                    }
                });
                // Spawn the time profiler.
                spawn_named("Time profiler".to_owned(), move || {
                    let mut profiler = Profiler::new(port);
                    profiler.start();
                });
            }
            None => {
                // No-op to handle messages when the time profiler is inactive.
                spawn_named("Time profiler".to_owned(), move || {
                    loop {
                        match port.recv() {
                            Err(_) | Ok(ProfilerMsg::Exit) => break,
                            _ => {}
                        }
                    }
                });
            }
        }
        heartbeats::init();

        ProfilerChan(chan)
    }

    pub fn new(port: IpcReceiver<ProfilerMsg>) -> Profiler {
        Profiler {
            port: port,
            buckets: BTreeMap::new(),
            last_msg: None,
        }
    }

    pub fn start(&mut self) {
        loop {
            let msg = self.port.recv();
            match msg {
               Ok(msg) => {
                   if !self.handle_msg(msg) {
                       break
                   }
               }
               _ => break
            }
        }
    }

    fn find_or_insert(&mut self, k: (ProfilerCategory, Option<TimerMetadata>), t: f64) {
        match self.buckets.get_mut(&k) {
            None => {},
            Some(v) => { v.push(t); return; },
        }

        self.buckets.insert(k, vec!(t));
    }

    fn handle_msg(&mut self, msg: ProfilerMsg) -> bool {
        match msg.clone() {
            ProfilerMsg::Time(k, t) => {
                heartbeats::maybe_heartbeat(&k.0, t.0, t.1, 0, 0);
                let ms = (t.1 - t.0) as f64 / 1000000f64;
                self.find_or_insert(k, ms);
            },
            ProfilerMsg::Print => match self.last_msg {
                // only print if more data has arrived since the last printout
                Some(ProfilerMsg::Time(..)) => self.print_buckets(),
                _ => ()
            },
            ProfilerMsg::Exit => {
                heartbeats::cleanup();
                return false;
            },
        };
        self.last_msg = Some(msg);
        true
    }

    fn print_buckets(&mut self) {
        println!("{:35} {:14} {:9} {:30} {:15} {:15} {:-15} {:-15} {:-15}",
                 "_category_", "_incremental?_", "_iframe?_",
                 "            _url_", "    _mean (ms)_", "  _median (ms)_",
                 "     _min (ms)_", "     _max (ms)_", "      _events_");
        for (&(ref category, ref meta), ref mut data) in &mut self.buckets {
            data.sort_by(|a, b| {
                if a < b {
                    Ordering::Less
                } else {
                    Ordering::Greater
                }
            });
            let data_len = data.len();
            if data_len > 0 {
                let (mean, median, min, max) =
                    (data.iter().map(|&x|x).sum::<f64>() / (data_len as f64),
                     data[data_len / 2],
                     data.iter().fold(f64::INFINITY, |a, &b| a.min(b)),
                     data.iter().fold(-f64::INFINITY, |a, &b| a.max(b)));
                println!("{:-35}{} {:15.4} {:15.4} {:15.4} {:15.4} {:15}",
                         category.format(), meta.format(), mean, median, min, max, data_len);
            }
        }
        println!("");
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2017 Colin Walters <walters@verbum.org>
 * Based on original bupsplit.c:
 * Copyright 2011 Avery Pennarun. All rights reserved.
 *
 * (This license applies to bupsplit.c and bupsplit.h only.)
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *    1. Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *    2. Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in
 *       the documentation and/or other materials provided with the
 *       distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY AVERY PENNARUN ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

extern crate libc;

use std::slice;

// According to librsync/rollsum.h:
// "We should make this something other than zero to improve the
// checksum algorithm: tridge suggests a prime number."
// apenwarr: I unscientifically tried 0 and 7919, and they both ended up
// slightly worse than the librsync value of 31 for my arbitrary test data.
const ROLLSUM_CHAR_OFFSET: u32 = 31;

// Previously in the header file
const BUP_BLOBBITS: u32= 13;
const BUP_BLOBSIZE: u32 = (1<<BUP_BLOBBITS);
const BUP_WINDOWBITS: u32 = 7;
const BUP_WINDOWSIZE: u32 = (1<<(BUP_WINDOWBITS-1));

struct Rollsum {
    s1: u32,
    s2: u32,
    window: [u8; BUP_WINDOWSIZE as usize],
    wofs: i32,
}

impl Rollsum {
    pub fn new() -> Rollsum {
        Rollsum { s1: BUP_WINDOWSIZE * ROLLSUM_CHAR_OFFSET,
                  s2: BUP_WINDOWSIZE * (BUP_WINDOWSIZE-1) * ROLLSUM_CHAR_OFFSET,
                  window: [0; 64],
                  wofs: 0
        }
    }

    // These formulas are based on rollsum.h in the librsync project.
    pub fn add(&mut self, drop: u8, add: u8) -> () {
        let drop_expanded = drop as u32;
        let add_expanded = add as u32;
        self.s1 = self.s1.wrapping_add(add_expanded.wrapping_sub(drop_expanded));
        self.s2 = self.s2.wrapping_add(self.s1.wrapping_sub(BUP_WINDOWSIZE * (drop_expanded + ROLLSUM_CHAR_OFFSET)));
    }

    pub fn roll(&mut self, ch: u8) -> () {
        let wofs = self.wofs as usize;
        let dval = self.window[wofs];
        self.add(dval, ch);
        self.window[wofs] = ch;
        self.wofs = (self.wofs + 1) % (BUP_WINDOWSIZE as i32);
    }

    pub fn digest(&self) -> u32 {
        (self.s1 << 16) | (self.s2 & 0xFFFF)
    }
}

#[no_mangle]
pub extern fn bupsplit_sum(buf: *const u8, ofs: libc::size_t, len: libc::size_t) -> u32 {
    let sbuf = unsafe {
        assert!(!buf.is_null());
        slice::from_raw_parts(buf.offset(ofs as isize), (len - ofs) as usize)
    };

    let mut r = Rollsum::new();
    for x in sbuf {
        r.roll(*x);
    }
    r.digest()
}

#[no_mangle]
pub extern fn bupsplit_find_ofs(buf: *const u8, len: libc::size_t,
                                bits: *mut libc::c_int) -> libc::c_int
{
    let sbuf = unsafe {
        assert!(!buf.is_null());
        slice::from_raw_parts(buf, len as usize)
    };

    let mut r = Rollsum::new();
    for x in sbuf {
        r.roll(*x);
	      if (r.s2 & (BUP_BLOBSIZE-1)) == ((u32::max_value()) & (BUP_BLOBSIZE-1)) {
	          if !bits.is_null() {
                let mut sum = r.digest() >> BUP_BLOBBITS;
                let mut rbits : libc::c_int = BUP_BLOBBITS as i32;
                while sum & 1 != 0 {
                    sum = sum >> 1;
                    rbits = rbits + 1;
                }
                unsafe {
                    *bits = rbits;
                }
            }
            return len as i32
        }
    }
    0
}
<commit_msg>rust/bupsplit: minor idiomatic fixes<commit_after>/*
 * Copyright 2017 Colin Walters <walters@verbum.org>
 * Based on original bupsplit.c:
 * Copyright 2011 Avery Pennarun. All rights reserved.
 *
 * (This license applies to bupsplit.c and bupsplit.h only.)
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *    1. Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *    2. Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in
 *       the documentation and/or other materials provided with the
 *       distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY AVERY PENNARUN ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

extern crate libc;

use std::slice;

// According to librsync/rollsum.h:
// "We should make this something other than zero to improve the
// checksum algorithm: tridge suggests a prime number."
// apenwarr: I unscientifically tried 0 and 7919, and they both ended up
// slightly worse than the librsync value of 31 for my arbitrary test data.
const ROLLSUM_CHAR_OFFSET: u32 = 31;

// Previously in the header file
const BUP_BLOBBITS: u32 = 13;
const BUP_BLOBSIZE: u32 = (1<<BUP_BLOBBITS);
const BUP_WINDOWBITS: u32 = 7;
const BUP_WINDOWSIZE: u32 = (1<<(BUP_WINDOWBITS-1));

struct Rollsum {
    s1: u32,
    s2: u32,
    window: [u8; BUP_WINDOWSIZE as usize],
    wofs: i32,
}

impl Rollsum {
    pub fn new() -> Rollsum {
        Rollsum { s1: BUP_WINDOWSIZE * ROLLSUM_CHAR_OFFSET,
                  s2: BUP_WINDOWSIZE * (BUP_WINDOWSIZE-1) * ROLLSUM_CHAR_OFFSET,
                  window: [0; 64],
                  wofs: 0
        }
    }

    // These formulas are based on rollsum.h in the librsync project.
    pub fn add(&mut self, drop: u8, add: u8) -> () {
        let drop_expanded = u32::from(drop);
        let add_expanded = u32::from(add);
        self.s1 = self.s1.wrapping_add(add_expanded.wrapping_sub(drop_expanded));
        self.s2 = self.s2.wrapping_add(self.s1.wrapping_sub(BUP_WINDOWSIZE * (drop_expanded + ROLLSUM_CHAR_OFFSET)));
    }

    pub fn roll(&mut self, ch: u8) -> () {
        let wofs = self.wofs as usize;
        let dval = self.window[wofs];
        self.add(dval, ch);
        self.window[wofs] = ch;
        self.wofs = (self.wofs + 1) % (BUP_WINDOWSIZE as i32);
    }

    pub fn digest(&self) -> u32 {
        (self.s1 << 16) | (self.s2 & 0xFFFF)
    }
}

#[no_mangle]
pub extern fn bupsplit_sum(buf: *const u8, ofs: libc::size_t, len: libc::size_t) -> u32 {
    let sbuf = unsafe {
        assert!(!buf.is_null());
        slice::from_raw_parts(buf.offset(ofs as isize), (len - ofs) as usize)
    };

    let mut r = Rollsum::new();
    for x in sbuf {
        r.roll(*x);
    }
    r.digest()
}

#[no_mangle]
pub extern fn bupsplit_find_ofs(buf: *const u8, len: libc::size_t,
                                bits: *mut libc::c_int) -> libc::c_int
{
    if buf.is_null() {
        return 0;
    }

    let sbuf = unsafe { slice::from_raw_parts(buf, len as usize) };
    let mut r = Rollsum::new();
    for x in sbuf {
        r.roll(*x);
	      if (r.s2 & (BUP_BLOBSIZE-1)) == ((u32::max_value()) & (BUP_BLOBSIZE-1)) {
	          if !bits.is_null() {
                let mut sum = r.digest() >> BUP_BLOBBITS;
                let mut rbits : libc::c_int = BUP_BLOBBITS as i32;
                while sum & 1 != 0 {
                    sum >>= 1;
                    rbits += 1;
                }
                unsafe {
                    *bits = rbits;
                }
            }
            return len as i32
        }
    }
    0
}
<|endoftext|>


<commit_before><commit_msg>rlpx: poll new peers before checking newly connected and disconnected<commit_after><|endoftext|>


<commit_before>//! Parsing OpentType tables.

#![deny(rustdoc::broken_intra_doc_links)]
#![cfg_attr(not(feature = "std"), no_std)]

#[cfg(any(feature = "std", test))]
#[macro_use]
extern crate std;

#[cfg(all(not(feature = "std"), not(test)))]
#[macro_use]
extern crate core as std;

pub mod array;
mod font_data;
pub mod layout;
mod offset;
mod read;
mod table_provider;
mod table_ref;
pub mod tables;
#[cfg(feature = "traversal")]
pub mod traversal;

#[cfg(any(test, feature = "test_data"))]
pub mod codegen_test;
#[cfg(any(test, feature = "test_data"))]
#[path = "tests/test_data.rs"]
pub mod test_data;
#[cfg(any(test, feature = "test_data"))]
#[path = "tests/test_helpers.rs"]
pub mod test_helpers;

pub use font_data::FontData;
pub use offset::{Offset, ResolveNullableOffset, ResolveOffset};
pub use read::{ComputeSize, FontRead, FontReadWithArgs, ReadArgs, ReadError, VarSize};
pub use table_provider::TableProvider;
pub use table_ref::TableRef;

/// All the types that may be referenced in auto-generated code.
#[doc(hidden)]
pub(crate) mod codegen_prelude {
    pub use crate::array::{ComputedArray, VarLenArray};
    pub use crate::font_data::{Cursor, FontData};
    pub use crate::offset::{Offset, ResolveNullableOffset, ResolveOffset};
    pub use crate::read::{
        ComputeSize, FontRead, FontReadWithArgs, Format, ReadArgs, ReadError, VarSize,
    };
    pub use crate::table_ref::TableRef;
    pub use font_types::*;
    pub use std::ops::Range;

    #[cfg(feature = "traversal")]
    pub use crate::traversal::{self, Field, FieldType, RecordResolver, SomeRecord, SomeTable};

    // used in generated traversal code to get type names of offset fields, which
    // may include generics
    #[cfg(feature = "traversal")]
    pub(crate) fn better_type_name<T>() -> &'static str {
        let raw_name = std::any::type_name::<T>();
        let last = raw_name.rsplit("::").next().unwrap_or(raw_name);
        // this happens if we end up getting a type name like TableRef<'a, module::SomeMarker>
        last.trim_end_matches("Marker>")
    }

    /// used in generated code
    pub fn minus_one(val: impl Into<usize>) -> usize {
        val.into().saturating_sub(1)
    }
}

include!("../generated/font.rs");

#[derive(Clone)]
/// Reference to the content of a font or font collection file.
pub enum FileRef<'a> {
    /// A single font.
    Font(FontRef<'a>),
    /// A collection of fonts.
    Collection(CollectionRef<'a>),
}

impl<'a> FileRef<'a> {
    /// Creates a new reference to a file representing a font or font collection.
    pub fn new(data: FontData<'a>) -> Result<Self, ReadError> {
        Ok(if let Ok(collection) = CollectionRef::new(data) {
            Self::Collection(collection)
        } else {
            Self::Font(FontRef::new(data)?)
        })
    }

    /// Returns an iterator over the fonts contained in the file.
    pub fn fonts(&self) -> impl Iterator<Item = Result<FontRef<'a>, ReadError>> + 'a + Clone {
        let (iter_one, iter_two) = match self {
            Self::Font(font) => (Some(Ok(font.clone())), None),
            Self::Collection(collection) => (None, Some(collection.iter())),
        };
        iter_two.into_iter().flatten().chain(iter_one)
    }
}

/// Reference to the content of a font collection file.
#[derive(Clone)]
pub struct CollectionRef<'a> {
    data: FontData<'a>,
    header: TTCHeader<'a>,
}

impl<'a> CollectionRef<'a> {
    /// Creates a new reference to a font collection.
    pub fn new(data: FontData<'a>) -> Result<Self, ReadError> {
        let header = TTCHeader::read(data)?;
        if header.ttc_tag() != TTC_HEADER_TAG {
            Err(ReadError::InvalidTtc(header.ttc_tag()))
        } else {
            Ok(Self { data, header })
        }
    }

    /// Returns the number of fonts in the collection.
    pub fn len(&self) -> u32 {
        self.header.num_fonts()
    }

    /// Returns true if the collection is empty.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns the font in the collection at the specified index.
    pub fn get(&self, index: u32) -> Result<FontRef<'a>, ReadError> {
        let offset = self
            .header
            .table_directory_offsets()
            .get(index as usize)
            .ok_or(ReadError::InvalidCollectionIndex(index))?
            .get() as usize;
        let table_dir_data = self.data.slice(offset..).ok_or(ReadError::OutOfBounds)?;
        FontRef::with_table_directory(self.data, TableDirectory::read(table_dir_data)?)
    }

    /// Returns an iterator over the fonts in the collection.
    pub fn iter(&self) -> impl Iterator<Item = Result<FontRef<'a>, ReadError>> + 'a + Clone {
        let copy = self.clone();
        (0..self.len()).map(move |ix| copy.get(ix))
    }
}

#[derive(Clone)]
/// A temporary type for accessing tables
pub struct FontRef<'a> {
    data: FontData<'a>,
    pub table_directory: TableDirectory<'a>,
}

impl<'a> FontRef<'a> {
    /// Creates a new reference to a font.
    pub fn new(data: FontData<'a>) -> Result<Self, ReadError> {
        Self::with_table_directory(data, TableDirectory::read(data)?)
    }

    /// Returns the data for the table with the specified tag, if present.
    pub fn table_data(&self, tag: Tag) -> Option<FontData<'a>> {
        self.table_directory
            .table_records()
            .binary_search_by(|rec| rec.tag.get().cmp(&tag))
            .ok()
            .and_then(|idx| self.table_directory.table_records().get(idx))
            .and_then(|record| {
                let start = record.offset().non_null()?;
                let len = record.length() as usize;
                self.data.slice(start..start + len)
            })
    }

    fn with_table_directory(
        data: FontData<'a>,
        table_directory: TableDirectory<'a>,
    ) -> Result<Self, ReadError> {
        if [TT_SFNT_VERSION, CFF_SFTN_VERSION].contains(&table_directory.sfnt_version()) {
            Ok(FontRef {
                data,
                table_directory,
            })
        } else {
            Err(ReadError::InvalidSfnt(table_directory.sfnt_version()))
        }
    }
}

impl<'a> TableProvider<'a> for FontRef<'a> {
    fn data_for_tag(&self, tag: Tag) -> Option<FontData<'a>> {
        self.table_data(tag)
    }
}
<commit_msg>re-export font-types in read-fonts<commit_after>//! Parsing OpentType tables.

#![deny(rustdoc::broken_intra_doc_links)]
#![cfg_attr(not(feature = "std"), no_std)]

#[cfg(any(feature = "std", test))]
#[macro_use]
extern crate std;

#[cfg(all(not(feature = "std"), not(test)))]
#[macro_use]
extern crate core as std;

pub mod array;
mod font_data;
pub mod layout;
mod offset;
mod read;
mod table_provider;
mod table_ref;
pub mod tables;
#[cfg(feature = "traversal")]
pub mod traversal;

#[cfg(any(test, feature = "test_data"))]
pub mod codegen_test;
#[cfg(any(test, feature = "test_data"))]
#[path = "tests/test_data.rs"]
pub mod test_data;
#[cfg(any(test, feature = "test_data"))]
#[path = "tests/test_helpers.rs"]
pub mod test_helpers;

pub use font_data::FontData;
pub use offset::{Offset, ResolveNullableOffset, ResolveOffset};
pub use read::{ComputeSize, FontRead, FontReadWithArgs, ReadArgs, ReadError, VarSize};
pub use table_provider::TableProvider;
pub use table_ref::TableRef;

/// Public re-export of the font-types crate.
pub use font_types as types;

/// All the types that may be referenced in auto-generated code.
#[doc(hidden)]
pub(crate) mod codegen_prelude {
    pub use crate::array::{ComputedArray, VarLenArray};
    pub use crate::font_data::{Cursor, FontData};
    pub use crate::offset::{Offset, ResolveNullableOffset, ResolveOffset};
    pub use crate::read::{
        ComputeSize, FontRead, FontReadWithArgs, Format, ReadArgs, ReadError, VarSize,
    };
    pub use crate::table_ref::TableRef;
    pub use font_types::*;
    pub use std::ops::Range;

    #[cfg(feature = "traversal")]
    pub use crate::traversal::{self, Field, FieldType, RecordResolver, SomeRecord, SomeTable};

    // used in generated traversal code to get type names of offset fields, which
    // may include generics
    #[cfg(feature = "traversal")]
    pub(crate) fn better_type_name<T>() -> &'static str {
        let raw_name = std::any::type_name::<T>();
        let last = raw_name.rsplit("::").next().unwrap_or(raw_name);
        // this happens if we end up getting a type name like TableRef<'a, module::SomeMarker>
        last.trim_end_matches("Marker>")
    }

    /// used in generated code
    pub fn minus_one(val: impl Into<usize>) -> usize {
        val.into().saturating_sub(1)
    }
}

include!("../generated/font.rs");

#[derive(Clone)]
/// Reference to the content of a font or font collection file.
pub enum FileRef<'a> {
    /// A single font.
    Font(FontRef<'a>),
    /// A collection of fonts.
    Collection(CollectionRef<'a>),
}

impl<'a> FileRef<'a> {
    /// Creates a new reference to a file representing a font or font collection.
    pub fn new(data: FontData<'a>) -> Result<Self, ReadError> {
        Ok(if let Ok(collection) = CollectionRef::new(data) {
            Self::Collection(collection)
        } else {
            Self::Font(FontRef::new(data)?)
        })
    }

    /// Returns an iterator over the fonts contained in the file.
    pub fn fonts(&self) -> impl Iterator<Item = Result<FontRef<'a>, ReadError>> + 'a + Clone {
        let (iter_one, iter_two) = match self {
            Self::Font(font) => (Some(Ok(font.clone())), None),
            Self::Collection(collection) => (None, Some(collection.iter())),
        };
        iter_two.into_iter().flatten().chain(iter_one)
    }
}

/// Reference to the content of a font collection file.
#[derive(Clone)]
pub struct CollectionRef<'a> {
    data: FontData<'a>,
    header: TTCHeader<'a>,
}

impl<'a> CollectionRef<'a> {
    /// Creates a new reference to a font collection.
    pub fn new(data: FontData<'a>) -> Result<Self, ReadError> {
        let header = TTCHeader::read(data)?;
        if header.ttc_tag() != TTC_HEADER_TAG {
            Err(ReadError::InvalidTtc(header.ttc_tag()))
        } else {
            Ok(Self { data, header })
        }
    }

    /// Returns the number of fonts in the collection.
    pub fn len(&self) -> u32 {
        self.header.num_fonts()
    }

    /// Returns true if the collection is empty.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns the font in the collection at the specified index.
    pub fn get(&self, index: u32) -> Result<FontRef<'a>, ReadError> {
        let offset = self
            .header
            .table_directory_offsets()
            .get(index as usize)
            .ok_or(ReadError::InvalidCollectionIndex(index))?
            .get() as usize;
        let table_dir_data = self.data.slice(offset..).ok_or(ReadError::OutOfBounds)?;
        FontRef::with_table_directory(self.data, TableDirectory::read(table_dir_data)?)
    }

    /// Returns an iterator over the fonts in the collection.
    pub fn iter(&self) -> impl Iterator<Item = Result<FontRef<'a>, ReadError>> + 'a + Clone {
        let copy = self.clone();
        (0..self.len()).map(move |ix| copy.get(ix))
    }
}

#[derive(Clone)]
/// A temporary type for accessing tables
pub struct FontRef<'a> {
    data: FontData<'a>,
    pub table_directory: TableDirectory<'a>,
}

impl<'a> FontRef<'a> {
    /// Creates a new reference to a font.
    pub fn new(data: FontData<'a>) -> Result<Self, ReadError> {
        Self::with_table_directory(data, TableDirectory::read(data)?)
    }

    /// Returns the data for the table with the specified tag, if present.
    pub fn table_data(&self, tag: Tag) -> Option<FontData<'a>> {
        self.table_directory
            .table_records()
            .binary_search_by(|rec| rec.tag.get().cmp(&tag))
            .ok()
            .and_then(|idx| self.table_directory.table_records().get(idx))
            .and_then(|record| {
                let start = record.offset().non_null()?;
                let len = record.length() as usize;
                self.data.slice(start..start + len)
            })
    }

    fn with_table_directory(
        data: FontData<'a>,
        table_directory: TableDirectory<'a>,
    ) -> Result<Self, ReadError> {
        if [TT_SFNT_VERSION, CFF_SFTN_VERSION].contains(&table_directory.sfnt_version()) {
            Ok(FontRef {
                data,
                table_directory,
            })
        } else {
            Err(ReadError::InvalidSfnt(table_directory.sfnt_version()))
        }
    }
}

impl<'a> TableProvider<'a> for FontRef<'a> {
    fn data_for_tag(&self, tag: Tag) -> Option<FontData<'a>> {
        self.table_data(tag)
    }
}
<|endoftext|>


<commit_before>/// An interpreter for the rust-installer [1] installation format.
///
/// https://github.com/rust-lang/rust-installer

pub use self::transaction::*;
pub use self::components::*;
pub use self::package::*;

// Transactional file system tools
mod transaction;
// The representation of a package, its components, and installation
//
// FIXME: Because of rust-lang/rust#18241 this must be pub to pub reexport
// the inner Package trait.
pub mod package;
// The representation of *installed* components, and uninstallation
mod components;

<commit_msg>Auto merge of #1116 - mattico:remove-pub-fixme, r=Diggsey<commit_after>/// An interpreter for the rust-installer [1] installation format.
///
/// https://github.com/rust-lang/rust-installer

pub use self::transaction::*;
pub use self::components::*;
pub use self::package::*;

// Transactional file system tools
mod transaction;
// The representation of a package, its components, and installation
mod package;
// The representation of *installed* components, and uninstallation
mod components;

<|endoftext|>


<commit_before>extern crate tetrahedrane;

use tetrahedrane::vid::*;
use tetrahedrane::start;
use tetrahedrane::shaders;

fn main() {
    let mut window = start::Window::new(640, 480, "Hello World!", 1 as usize);

    let mut shaders: Vec<Shader> = Vec::new();

    let mut triangle = Triangle::new(DepthPoint::new(0.0, -0.5, 3.0),
                                 DepthPoint::new(0.5, 0.5, 3.0),
                                 DepthPoint::new(-0.5, 0.5, 3.0),
                                 0.0, 0.0, 0.0,
                                 Color::new(200, 200, 200));

    shaders.push(shaders::filled_triangle_color(1));

    triangle.shader_ids[0] = 1;

    loop {
        window.window.set(Color::new(20, 40, 60).orb_color());
        window.window.set(Color::new(20, 40, 60).orb_color());

        triangle.coord_rotate_x_y(0.0, 0.0, 0.01);
        triangle.coord_rotate_x_z(0.0, 3.0, 0.02);
        triangle.coord_rotate_y_z(0.0, 3.0, 0.03);

        window.render(triangle, &shaders);

        window.window.sync();

        std::thread::sleep(std::time::Duration::from_millis(33));
    }
}<commit_msg>Some change I forgot<commit_after>extern crate tetrahedrane;

use tetrahedrane::vid::*;
use tetrahedrane::start;
use tetrahedrane::shaders;

fn main() {
    // Make a new window
    let mut window = start::Window::new(640, 480, "Hello World!", 1 as usize);

    let mut shaders: Vec<Shader> = Vec::new();

    // Create a triangle
    let mut triangle = Triangle::new(DepthPoint::new(0.0, -0.5, 3.0),
                                 DepthPoint::new(0.5, 0.5, 3.0),
                                 DepthPoint::new(-0.5, 0.5, 3.0),
                                 0.0, 0.0, 0.0,
                                 Color::new(200, 200, 200));

    // Add a shader
    shaders.push(shaders::filled_triangle_color(1));

    // Apply shader to the triangle
    triangle.shader_ids[0] = 1;

    loop {
        window.window.set(Color::new(20, 40, 60).orb_color());
        window.window.set(Color::new(20, 40, 60).orb_color());

        triangle.coord_rotate_x_y(0.0, 0.0, 0.01);
        triangle.coord_rotate_x_z(0.0, 3.0, 0.02);
        triangle.coord_rotate_y_z(0.0, 3.0, 0.05);

        // Render the triangle with shaders.
        window.render(triangle, &shaders);

        window.window.sync();

        std::thread::sleep(std::time::Duration::from_millis(16));
    }
}<|endoftext|>


<commit_before>// Copyright 2014 The Gfx-rs Developers.
//
// 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.

#![feature(phase)]
#![crate_name = "glutin"]

//! Demonstrates how to initialize gfx-rs using the gl-init-rs library.

extern crate gfx;
#[phase(plugin)]
extern crate gfx_macros;
extern crate glutin;
extern crate native;

use gfx::{Device, DeviceHelper};

// We need to run on the main thread for GLFW, so ensure we are using the `native` runtime. This is
// technically not needed, since this is the default, but it's not guaranteed.
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
     native::start(argc, argv, main)
}

fn main() {
    let window = glutin::Window::new().unwrap();
    window.set_title("glutin initialization example");
    unsafe { window.make_current() };
    let (w, h) = window.get_inner_size().unwrap();

    let mut device = gfx::GlDevice::new(|s| window.get_proc_address(s));
    let mut renderer = device.create_renderer();

    renderer.clear(
        gfx::ClearData {
            color: [0.3, 0.3, 0.3, 1.0],
            depth: 1.0,
            stencil: 0,
        },
        gfx::COLOR,
        &gfx::Frame::new(w as u16, h as u16)
    );

    'main: loop {
        // quit when Esc is pressed.
        for event in window.poll_events() {
            match event {
                glutin::KeyboardInput(_, _, Some(glutin::Escape), _) => break 'main,
                glutin::Closed => break 'main,
                _ => {},
            }
        }
        device.submit(renderer.as_buffer());
        window.swap_buffers();
    }
}
<commit_msg>Update glutin example.<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// 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.

#![feature(phase)]
#![crate_name = "glutin"]

//! Demonstrates how to initialize gfx-rs using the gl-init-rs library.

extern crate gfx;
#[phase(plugin)]
extern crate gfx_macros;
extern crate glutin;
extern crate native;

use gfx::{Device, DeviceHelper};

// We need to run on the main thread for GLFW, so ensure we are using the `native` runtime. This is
// technically not needed, since this is the default, but it's not guaranteed.
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
     native::start(argc, argv, main)
}

fn main() {
    let window = glutin::Window::new().unwrap();
    window.set_title("glutin initialization example");
    unsafe { window.make_current() };
    let (w, h) = window.get_inner_size().unwrap();

    let mut device = gfx::GlDevice::new(|s| window.get_proc_address(s));
    let mut renderer = device.create_renderer();

    renderer.clear(
        gfx::ClearData {
            color: [0.3, 0.3, 0.3, 1.0],
            depth: 1.0,
            stencil: 0,
        },
        gfx::COLOR,
        &gfx::Frame::new(w as u16, h as u16)
    );

    'main: loop {
        // quit when Esc is pressed.
        for event in window.poll_events() {
            match event {
                glutin::KeyboardInput(_, _, Some(glutin::Escape)) => break 'main,
                glutin::Closed => break 'main,
                _ => {},
            }
        }
        device.submit(renderer.as_buffer());
        window.swap_buffers();
    }
}
<|endoftext|>


<commit_before>//   Copyright 2014 Colin Sherratt
//
//   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.

#![crate_name = "noclip"]
#![feature(macro_rules)]
#![feature(globs)]

extern crate glfw;
extern crate gl;
extern crate "snowmew-core" as snowmew;
extern crate "snowmew-render-mux" as render;
extern crate "snowmew-loader" as loader;
extern crate "snowmew-position" as position;
extern crate "snowmew-graphics" as graphics;
extern crate cgmath;
extern crate native;
extern crate "snowmew-render-data" as render_data;

use std::from_str::FromStr;

use cgmath::*;

use snowmew::input;
use snowmew::input_integrator::{input_integrator, InputIntegratorState};
use snowmew::game::Game;
use snowmew::camera::Camera;
use position::Positions;
use graphics::{Graphics};
use graphics::light;

use render_data::Renderable;
use render::RenderFactory;
use loader::Obj;
use snowmew::common::Common;

use gamedata::GameData;

mod gamedata;

#[start]
fn start(argc: int, argv: *const *const u8) -> int {
    native::start(argc, argv, main)
}

fn main() {
    let sc = snowmew::SnowmewConfig::new();

    let args = std::os::args();
    if args.len() == 1 {
        println!("Please supply a path to an obj to load");
        return;
    }
    let path = Path::new(args[1].as_slice());
    let scale: f32 = if args.len() >= 3 {
        match FromStr::from_str(args[2].as_slice()) {
            Some(v) => v,
            None => 1.0
        }
    } else {
        1.0
    };

    let mut db = GameData::new();
    let loader = Obj::load(&path).expect("Failed to load OBJ");
    let import = db.new_object(None, "import");
    loader.import(import, &mut db);
    let scene = db.new_scene("scene");
    let geo_dir = db.find("import/objects").expect("geometry not found from import");
    for (name, id) in db.clone().walk_dir(geo_dir) {
        match db.get_draw(id) {
            Some(d) => {
                let obj = db.new_object(Some(scene), name);
                db.set_draw(obj, d.geometry, d.material);
                db.set_scale(obj, scale);
            }
            None => ()
        }
    }

    let camera_loc = db.new_object(None, "camera");
    db.set_to_identity(camera_loc);

    let pos = if args.len() >= 6 {
        let x = FromStr::from_str(args[3].as_slice());
        let y = FromStr::from_str(args[4].as_slice());
        let z = FromStr::from_str(args[5].as_slice());
        match (x, y, z) {
            (Some(x), Some(y), Some(z)) => {
                Point3::new(x, y, z)
            }
            _ => Point3::new(0f32, 0., 0.)
        }
    } else {
        Point3::new(0f32, 0f32, 0f32)
    };

    let head_trans = Decomposed{scale: 1f32,
                                rot:   Quaternion::identity(),
                                disp:  pos.to_vec()};
    db.update_location(camera_loc, head_trans);

    let sun = light::Directional::new(Vector3::new(0.05f32, 1., 0.05),
                                      Vector3::new(1f32, 1., 1.), 1.);
    db.set_scene(scene);
    db.set_camera(camera_loc);
    db.new_light(scene, "sun", light::DirectionalLight(sun));

    let (game, gd) = input_integrator(Noclip, db);
    sc.start(box RenderFactory::new(), game, gd);
}

struct Noclip;

impl Game<GameData, InputIntegratorState> for Noclip {
    fn step(&mut self, state: InputIntegratorState, gd: GameData) -> GameData {
        let mut next = gd.clone();

        let camera_key = gd.camera().expect("no camera set");
        let camera = Camera::new(next.position(camera_key));
        let (mut rx, ry, mut rz) = next.get_rotation(camera_key).expect("no rot").to_euler();

        let (x, y) = state.mouse_delta();
        rx = rx.add_a(rad((-x / 120.) as f32));
        rz = rz.add_a(rad((-y / 120.) as f32));

        let max_rot: f32 = Float::frac_pi_2();
        if rz.s > max_rot {
            rz.s = max_rot;
        } else if rz.s < -max_rot {
            rz.s = -max_rot;
        }

        let input_vec = Vector3::new(
            if state.button_down(input::KeyboardA) {0.05f32} else {0f32} +
            if state.button_down(input::KeyboardD) {-0.05f32} else {0f32},
            0f32,
            if state.button_down(input::KeyboardW) {0.05f32} else {0f32} +
            if state.button_down(input::KeyboardS) {-0.05f32} else {0f32}
        ).mul_s(-1f32);

        let head_trans = Decomposed{scale: 1f32,
                                    rot:   Rotation3::from_euler(rx, ry, rz),
                                    disp:  camera.move_with_vector(&input_vec).to_vec()};
        next.update_location(camera_key, head_trans);

        next
    }
}<commit_msg>added noclip to debugger<commit_after>//   Copyright 2014 Colin Sherratt
//
//   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.

#![crate_name = "noclip"]
#![feature(macro_rules)]
#![feature(globs)]

extern crate glfw;
extern crate gl;
extern crate "snowmew-core" as snowmew;
extern crate "snowmew-render-mux" as render;
extern crate "snowmew-loader" as loader;
extern crate "snowmew-position" as position;
extern crate "snowmew-graphics" as graphics;
extern crate cgmath;
extern crate native;
extern crate "snowmew-render-data" as render_data;

use std::from_str::FromStr;

use cgmath::*;

use snowmew::input;
use snowmew::debugger::debugger;
use snowmew::input_integrator::{input_integrator, InputIntegratorState};
use snowmew::game::Game;
use snowmew::camera::Camera;
use position::Positions;
use graphics::{Graphics};
use graphics::light;

use render_data::Renderable;
use render::RenderFactory;
use loader::Obj;
use snowmew::common::Common;

use gamedata::GameData;

mod gamedata;

#[start]
fn start(argc: int, argv: *const *const u8) -> int {
    native::start(argc, argv, main)
}

fn main() {
    let sc = snowmew::SnowmewConfig::new();

    let args = std::os::args();
    if args.len() == 1 {
        println!("Please supply a path to an obj to load");
        return;
    }
    let path = Path::new(args[1].as_slice());
    let scale: f32 = if args.len() >= 3 {
        match FromStr::from_str(args[2].as_slice()) {
            Some(v) => v,
            None => 1.0
        }
    } else {
        1.0
    };

    let mut db = GameData::new();
    let loader = Obj::load(&path).expect("Failed to load OBJ");
    let import = db.new_object(None, "import");
    loader.import(import, &mut db);
    let scene = db.new_scene("scene");
    let geo_dir = db.find("import/objects").expect("geometry not found from import");
    for (name, id) in db.clone().walk_dir(geo_dir) {
        match db.get_draw(id) {
            Some(d) => {
                let obj = db.new_object(Some(scene), name);
                db.set_draw(obj, d.geometry, d.material);
                db.set_scale(obj, scale);
            }
            None => ()
        }
    }

    let camera_loc = db.new_object(None, "camera");
    db.set_to_identity(camera_loc);

    let pos = if args.len() >= 6 {
        let x = FromStr::from_str(args[3].as_slice());
        let y = FromStr::from_str(args[4].as_slice());
        let z = FromStr::from_str(args[5].as_slice());
        match (x, y, z) {
            (Some(x), Some(y), Some(z)) => {
                Point3::new(x, y, z)
            }
            _ => Point3::new(0f32, 0., 0.)
        }
    } else {
        Point3::new(0f32, 0f32, 0f32)
    };

    let head_trans = Decomposed{scale: 1f32,
                                rot:   Quaternion::identity(),
                                disp:  pos.to_vec()};
    db.update_location(camera_loc, head_trans);

    let sun = light::Directional::new(Vector3::new(0.05f32, 1., 0.05),
                                      Vector3::new(1f32, 1., 1.), 1.);
    db.set_scene(scene);
    db.set_camera(camera_loc);
    db.new_light(scene, "sun", light::DirectionalLight(sun));

    let (game, gd) = input_integrator(Noclip, db);
    let (game, gd) = debugger(game, gd);
    sc.start(box RenderFactory::new(), game, gd);
}

struct Noclip;

impl Game<GameData, InputIntegratorState> for Noclip {
    fn step(&mut self, state: InputIntegratorState, gd: GameData) -> GameData {
        let mut next = gd.clone();

        let camera_key = gd.camera().expect("no camera set");
        let camera = Camera::new(next.position(camera_key));
        let (mut rx, ry, mut rz) = next.get_rotation(camera_key).expect("no rot").to_euler();

        let (x, y) = state.mouse_delta();
        rx = rx.add_a(rad((-x / 120.) as f32));
        rz = rz.add_a(rad((-y / 120.) as f32));

        let max_rot: f32 = Float::frac_pi_2();
        if rz.s > max_rot {
            rz.s = max_rot;
        } else if rz.s < -max_rot {
            rz.s = -max_rot;
        }

        let input_vec = Vector3::new(
            if state.button_down(input::KeyboardA) {0.05f32} else {0f32} +
            if state.button_down(input::KeyboardD) {-0.05f32} else {0f32},
            0f32,
            if state.button_down(input::KeyboardW) {0.05f32} else {0f32} +
            if state.button_down(input::KeyboardS) {-0.05f32} else {0f32}
        ).mul_s(-1f32);

        let head_trans = Decomposed{scale: 1f32,
                                    rot:   Rotation3::from_euler(rx, ry, rz),
                                    disp:  camera.move_with_vector(&input_vec).to_vec()};
        next.update_location(camera_key, head_trans);

        next
    }
}<|endoftext|>