<commit_before>//! This is the actual "grammar" of the Rust language.
//!
//! Each function in this module and its children corresponds
//! to a production of the formal grammar. Submodules roughly
//! correspond to different *areas* of the grammar. By convention,
//! each submodule starts with `use super::*` import and exports
//! "public" productions via `pub(super)`.
//!
//! See docs for `Parser` to learn about API, available to the grammar,
//! and see docs for `Event` to learn how this actually manages to
//! produce parse trees.
//!
//! Code in this module also contains inline tests, which start with
//! `// test name-of-the-test` comment and look like this:
//!
//! ```
//! // test function_with_zero_parameters
//! // fn foo() {}
//! ```
//!
//! After adding a new inline-test, run `cargo collect-tests` to extract
//! it as a standalone text-fixture into `tests/data/parser/inline`, and
//! run `cargo test` once to create the "gold" value.
//!
//! Coding convention: rules like `where_clause` always produce either a
//! node or an error, rules like `opt_where_clause` may produce nothing.
//! Non-opt rules typically start with `assert!(p.at(FIRST_TOKEN))`, the
//! caller is responsible for branching on the first token.
mod attributes;
mod expressions;
mod items;
mod params;
mod paths;
mod patterns;
mod type_args;
mod type_params;
mod types;

use crate::{
    parser::{CompletedMarker, Marker, Parser},
    SyntaxKind::{self, *},
    TokenSet,
};

pub(crate) fn root(p: &mut Parser) {
    let m = p.start();
    p.eat(SHEBANG);
    items::mod_contents(p, false);
    m.complete(p, SOURCE_FILE);
}

/// Various pieces of syntax that can be parsed by macros by example
pub(crate) mod fragments {
    use super::*;

    pub(crate) use super::{
        expressions::block_expr, paths::type_path as path, patterns::pattern, types::type_,
    };

    pub(crate) fn expr(p: &mut Parser) {
        let _ = expressions::expr(p);
    }

    pub(crate) fn stmt(p: &mut Parser) {
        expressions::stmt(p, expressions::StmtWithSemi::No)
    }

    pub(crate) fn opt_visibility(p: &mut Parser) {
        let _ = super::opt_visibility(p);
    }

    // Parse a meta item , which excluded [], e.g : #[ MetaItem ]
    pub(crate) fn meta_item(p: &mut Parser) {
        fn is_delimiter(p: &mut Parser) -> bool {
            match p.current() {
                T!['{'] | T!['('] | T!['['] => true,
                _ => false,
            }
        }

        if is_delimiter(p) {
            items::token_tree(p);
            return;
        }

        let m = p.start();
        while !p.at(EOF) {
            if is_delimiter(p) {
                items::token_tree(p);
                break;
            } else {
                // https://doc.rust-lang.org/reference/attributes.html
                // https://doc.rust-lang.org/reference/paths.html#simple-paths
                // The start of an meta must be a simple path
                match p.current() {
                    IDENT | T![::] | T![super] | T![self] | T![crate] => p.bump_any(),
                    T![=] => {
                        p.bump_any();
                        match p.current() {
                            c if c.is_literal() => p.bump_any(),
                            T![true] | T![false] => p.bump_any(),
                            _ => {}
                        }
                        break;
                    }
                    _ => break,
                }
            }
        }

        m.complete(p, TOKEN_TREE);
    }

    pub(crate) fn item(p: &mut Parser) {
        items::item_or_macro(p, true, items::ItemFlavor::Mod)
    }

    pub(crate) fn macro_items(p: &mut Parser) {
        let m = p.start();
        items::mod_contents(p, false);
        m.complete(p, MACRO_ITEMS);
    }

    pub(crate) fn macro_stmts(p: &mut Parser) {
        let m = p.start();

        while !p.at(EOF) {
            if p.at(T![;]) {
                p.bump(T![;]);
                continue;
            }

            expressions::stmt(p, expressions::StmtWithSemi::Optional);
        }

        m.complete(p, MACRO_STMTS);
    }
}

pub(crate) fn reparser(
    node: SyntaxKind,
    first_child: Option<SyntaxKind>,
    parent: Option<SyntaxKind>,
) -> Option<fn(&mut Parser)> {
    let res = match node {
        BLOCK_EXPR => expressions::block_expr,
        RECORD_FIELD_DEF_LIST => items::record_field_def_list,
        RECORD_FIELD_LIST => items::record_field_list,
        ENUM_VARIANT_LIST => items::enum_variant_list,
        MATCH_ARM_LIST => items::match_arm_list,
        USE_TREE_LIST => items::use_tree_list,
        EXTERN_ITEM_LIST => items::extern_item_list,
        TOKEN_TREE if first_child? == T!['{'] => items::token_tree,
        ITEM_LIST => match parent? {
            IMPL_DEF => items::impl_item_list,
            TRAIT_DEF => items::trait_item_list,
            MODULE => items::mod_item_list,
            _ => return None,
        },
        _ => return None,
    };
    Some(res)
}

#[derive(Clone, Copy, PartialEq, Eq)]
enum BlockLike {
    Block,
    NotBlock,
}

impl BlockLike {
    fn is_block(self) -> bool {
        self == BlockLike::Block
    }
}

fn opt_visibility(p: &mut Parser) -> bool {
    match p.current() {
        T![pub] => {
            let m = p.start();
            p.bump(T![pub]);
            if p.at(T!['(']) {
                match p.nth(1) {
                    // test crate_visibility
                    // pub(crate) struct S;
                    // pub(self) struct S;
                    // pub(self) struct S;
                    // pub(self) struct S;
                    T![crate] | T![self] | T![super] => {
                        p.bump_any();
                        p.bump_any();
                        p.expect(T![')']);
                    }
                    T![in] => {
                        p.bump_any();
                        p.bump_any();
                        paths::use_path(p);
                        p.expect(T![')']);
                    }
                    _ => (),
                }
            }
            m.complete(p, VISIBILITY);
        }
        // test crate_keyword_vis
        // crate fn main() { }
        // struct S { crate field: u32 }
        // struct T(crate u32);
        //
        // test crate_keyword_path
        // fn foo() { crate::foo(); }
        T![crate] if !p.nth_at(1, T![::]) => {
            let m = p.start();
            p.bump(T![crate]);
            m.complete(p, VISIBILITY);
        }
        _ => return false,
    }
    true
}

fn opt_alias(p: &mut Parser) {
    if p.at(T![as]) {
        let m = p.start();
        p.bump(T![as]);
        if !p.eat(T![_]) {
            name(p);
        }
        m.complete(p, ALIAS);
    }
}

fn abi(p: &mut Parser) {
    assert!(p.at(T![extern]));
    let abi = p.start();
    p.bump(T![extern]);
    match p.current() {
        STRING | RAW_STRING => p.bump_any(),
        _ => (),
    }
    abi.complete(p, ABI);
}

fn opt_fn_ret_type(p: &mut Parser) -> bool {
    if p.at(T![->]) {
        let m = p.start();
        p.bump(T![->]);
        types::type_no_bounds(p);
        m.complete(p, RET_TYPE);
        true
    } else {
        false
    }
}

fn name_r(p: &mut Parser, recovery: TokenSet) {
    if p.at(IDENT) {
        let m = p.start();
        p.bump(IDENT);
        m.complete(p, NAME);
    } else {
        p.err_recover("expected a name", recovery);
    }
}

fn name(p: &mut Parser) {
    name_r(p, TokenSet::EMPTY)
}

fn name_ref(p: &mut Parser) {
    if p.at(IDENT) {
        let m = p.start();
        p.bump(IDENT);
        m.complete(p, NAME_REF);
    } else if p.at(T![self]) {
        let m = p.start();
        p.bump(T![self]);
        m.complete(p, T![self]);
    } else {
        p.err_and_bump("expected identifier");
    }
}

fn name_ref_or_index(p: &mut Parser) {
    assert!(p.at(IDENT) || p.at(INT_NUMBER));
    let m = p.start();
    p.bump_any();
    m.complete(p, NAME_REF);
}

fn error_block(p: &mut Parser, message: &str) {
    assert!(p.at(T!['{']));
    let m = p.start();
    p.error(message);
    p.bump(T!['{']);
    expressions::expr_block_contents(p);
    p.eat(T!['}']);
    m.complete(p, ERROR);
}
<commit_msg>Update a comment for the new source organization<commit_after>//! This is the actual "grammar" of the Rust language.
//!
//! Each function in this module and its children corresponds
//! to a production of the formal grammar. Submodules roughly
//! correspond to different *areas* of the grammar. By convention,
//! each submodule starts with `use super::*` import and exports
//! "public" productions via `pub(super)`.
//!
//! See docs for `Parser` to learn about API, available to the grammar,
//! and see docs for `Event` to learn how this actually manages to
//! produce parse trees.
//!
//! Code in this module also contains inline tests, which start with
//! `// test name-of-the-test` comment and look like this:
//!
//! ```
//! // test function_with_zero_parameters
//! // fn foo() {}
//! ```
//!
//! After adding a new inline-test, run `cargo xtask codegen` to
//! extract it as a standalone text-fixture into
//! `crates/ra_syntax/test_data/parser/`, and run `cargo test` once to
//! create the "gold" value.
//!
//! Coding convention: rules like `where_clause` always produce either a
//! node or an error, rules like `opt_where_clause` may produce nothing.
//! Non-opt rules typically start with `assert!(p.at(FIRST_TOKEN))`, the
//! caller is responsible for branching on the first token.
mod attributes;
mod expressions;
mod items;
mod params;
mod paths;
mod patterns;
mod type_args;
mod type_params;
mod types;

use crate::{
    parser::{CompletedMarker, Marker, Parser},
    SyntaxKind::{self, *},
    TokenSet,
};

pub(crate) fn root(p: &mut Parser) {
    let m = p.start();
    p.eat(SHEBANG);
    items::mod_contents(p, false);
    m.complete(p, SOURCE_FILE);
}

/// Various pieces of syntax that can be parsed by macros by example
pub(crate) mod fragments {
    use super::*;

    pub(crate) use super::{
        expressions::block_expr, paths::type_path as path, patterns::pattern, types::type_,
    };

    pub(crate) fn expr(p: &mut Parser) {
        let _ = expressions::expr(p);
    }

    pub(crate) fn stmt(p: &mut Parser) {
        expressions::stmt(p, expressions::StmtWithSemi::No)
    }

    pub(crate) fn opt_visibility(p: &mut Parser) {
        let _ = super::opt_visibility(p);
    }

    // Parse a meta item , which excluded [], e.g : #[ MetaItem ]
    pub(crate) fn meta_item(p: &mut Parser) {
        fn is_delimiter(p: &mut Parser) -> bool {
            match p.current() {
                T!['{'] | T!['('] | T!['['] => true,
                _ => false,
            }
        }

        if is_delimiter(p) {
            items::token_tree(p);
            return;
        }

        let m = p.start();
        while !p.at(EOF) {
            if is_delimiter(p) {
                items::token_tree(p);
                break;
            } else {
                // https://doc.rust-lang.org/reference/attributes.html
                // https://doc.rust-lang.org/reference/paths.html#simple-paths
                // The start of an meta must be a simple path
                match p.current() {
                    IDENT | T![::] | T![super] | T![self] | T![crate] => p.bump_any(),
                    T![=] => {
                        p.bump_any();
                        match p.current() {
                            c if c.is_literal() => p.bump_any(),
                            T![true] | T![false] => p.bump_any(),
                            _ => {}
                        }
                        break;
                    }
                    _ => break,
                }
            }
        }

        m.complete(p, TOKEN_TREE);
    }

    pub(crate) fn item(p: &mut Parser) {
        items::item_or_macro(p, true, items::ItemFlavor::Mod)
    }

    pub(crate) fn macro_items(p: &mut Parser) {
        let m = p.start();
        items::mod_contents(p, false);
        m.complete(p, MACRO_ITEMS);
    }

    pub(crate) fn macro_stmts(p: &mut Parser) {
        let m = p.start();

        while !p.at(EOF) {
            if p.at(T![;]) {
                p.bump(T![;]);
                continue;
            }

            expressions::stmt(p, expressions::StmtWithSemi::Optional);
        }

        m.complete(p, MACRO_STMTS);
    }
}

pub(crate) fn reparser(
    node: SyntaxKind,
    first_child: Option<SyntaxKind>,
    parent: Option<SyntaxKind>,
) -> Option<fn(&mut Parser)> {
    let res = match node {
        BLOCK_EXPR => expressions::block_expr,
        RECORD_FIELD_DEF_LIST => items::record_field_def_list,
        RECORD_FIELD_LIST => items::record_field_list,
        ENUM_VARIANT_LIST => items::enum_variant_list,
        MATCH_ARM_LIST => items::match_arm_list,
        USE_TREE_LIST => items::use_tree_list,
        EXTERN_ITEM_LIST => items::extern_item_list,
        TOKEN_TREE if first_child? == T!['{'] => items::token_tree,
        ITEM_LIST => match parent? {
            IMPL_DEF => items::impl_item_list,
            TRAIT_DEF => items::trait_item_list,
            MODULE => items::mod_item_list,
            _ => return None,
        },
        _ => return None,
    };
    Some(res)
}

#[derive(Clone, Copy, PartialEq, Eq)]
enum BlockLike {
    Block,
    NotBlock,
}

impl BlockLike {
    fn is_block(self) -> bool {
        self == BlockLike::Block
    }
}

fn opt_visibility(p: &mut Parser) -> bool {
    match p.current() {
        T![pub] => {
            let m = p.start();
            p.bump(T![pub]);
            if p.at(T!['(']) {
                match p.nth(1) {
                    // test crate_visibility
                    // pub(crate) struct S;
                    // pub(self) struct S;
                    // pub(self) struct S;
                    // pub(self) struct S;
                    T![crate] | T![self] | T![super] => {
                        p.bump_any();
                        p.bump_any();
                        p.expect(T![')']);
                    }
                    T![in] => {
                        p.bump_any();
                        p.bump_any();
                        paths::use_path(p);
                        p.expect(T![')']);
                    }
                    _ => (),
                }
            }
            m.complete(p, VISIBILITY);
        }
        // test crate_keyword_vis
        // crate fn main() { }
        // struct S { crate field: u32 }
        // struct T(crate u32);
        //
        // test crate_keyword_path
        // fn foo() { crate::foo(); }
        T![crate] if !p.nth_at(1, T![::]) => {
            let m = p.start();
            p.bump(T![crate]);
            m.complete(p, VISIBILITY);
        }
        _ => return false,
    }
    true
}

fn opt_alias(p: &mut Parser) {
    if p.at(T![as]) {
        let m = p.start();
        p.bump(T![as]);
        if !p.eat(T![_]) {
            name(p);
        }
        m.complete(p, ALIAS);
    }
}

fn abi(p: &mut Parser) {
    assert!(p.at(T![extern]));
    let abi = p.start();
    p.bump(T![extern]);
    match p.current() {
        STRING | RAW_STRING => p.bump_any(),
        _ => (),
    }
    abi.complete(p, ABI);
}

fn opt_fn_ret_type(p: &mut Parser) -> bool {
    if p.at(T![->]) {
        let m = p.start();
        p.bump(T![->]);
        types::type_no_bounds(p);
        m.complete(p, RET_TYPE);
        true
    } else {
        false
    }
}

fn name_r(p: &mut Parser, recovery: TokenSet) {
    if p.at(IDENT) {
        let m = p.start();
        p.bump(IDENT);
        m.complete(p, NAME);
    } else {
        p.err_recover("expected a name", recovery);
    }
}

fn name(p: &mut Parser) {
    name_r(p, TokenSet::EMPTY)
}

fn name_ref(p: &mut Parser) {
    if p.at(IDENT) {
        let m = p.start();
        p.bump(IDENT);
        m.complete(p, NAME_REF);
    } else if p.at(T![self]) {
        let m = p.start();
        p.bump(T![self]);
        m.complete(p, T![self]);
    } else {
        p.err_and_bump("expected identifier");
    }
}

fn name_ref_or_index(p: &mut Parser) {
    assert!(p.at(IDENT) || p.at(INT_NUMBER));
    let m = p.start();
    p.bump_any();
    m.complete(p, NAME_REF);
}

fn error_block(p: &mut Parser, message: &str) {
    assert!(p.at(T!['{']));
    let m = p.start();
    p.error(message);
    p.bump(T!['{']);
    expressions::expr_block_contents(p);
    p.eat(T!['}']);
    m.complete(p, ERROR);
}
<|endoftext|>


<commit_before>use futures::sync::mpsc::{self, Sender};
use godcoin::{blockchain::ReindexOpts, get_epoch_ms, net::*, prelude::*};
use log::{error, info, warn};
use std::{
    io::Cursor,
    net::SocketAddr,
    path::PathBuf,
    sync::{
        atomic::{AtomicBool, Ordering},
        Arc,
    },
    time::Duration,
};
use tokio::{net::TcpListener, prelude::*, timer::Interval};
use tokio_tungstenite::tungstenite::{protocol, Message as WsMessage};

mod block_range;
mod forever;
pub mod minter;
pub mod pool;

pub mod prelude {
    pub use super::minter::*;
    pub use super::pool::SubscriptionPool;
}

use block_range::AsyncBlockRange;
use prelude::*;

pub struct ServerOpts {
    pub blocklog_loc: PathBuf,
    pub index_loc: PathBuf,
    pub minter_key: KeyPair,
    pub bind_addr: String,
    pub reindex: Option<ReindexOpts>,
    pub enable_stale_production: bool,
}

#[derive(Clone)]
pub struct ServerData {
    pub chain: Arc<Blockchain>,
    pub minter: Minter,
    pub sub_pool: SubscriptionPool,
}

pub fn start(opts: ServerOpts) {
    let blockchain = Arc::new(Blockchain::new(&opts.blocklog_loc, &opts.index_loc));

    let is_empty = blockchain.is_empty();
    if !is_empty && blockchain.index_status() != IndexStatus::Complete {
        warn!(
            "Indexing not complete (status = {:?})",
            blockchain.index_status()
        );
        match opts.reindex {
            Some(opts) => blockchain.reindex(opts),
            None => panic!("index incomplete, aborting..."),
        }
    }

    if is_empty {
        let info = blockchain.create_genesis_block(opts.minter_key.clone());
        info!("=> Generated new block chain");
        info!("=> {:?}", info.script);
        for (index, key) in info.wallet_keys.iter().enumerate() {
            info!("=> Wallet key {}: {}", index + 1, key.1.to_wif());
        }
    }

    info!(
        "Using height in block log at {}",
        blockchain.get_chain_height()
    );

    let sub_pool = SubscriptionPool::new();
    let minter = Minter::new(
        Arc::clone(&blockchain),
        opts.minter_key,
        sub_pool.clone(),
        opts.enable_stale_production,
    );
    minter.clone().start_production_loop();

    let data = Arc::new(ServerData {
        chain: Arc::clone(&blockchain),
        minter,
        sub_pool,
    });

    let addr = opts.bind_addr.parse::<SocketAddr>().unwrap();
    start_server(addr, data);
}

fn start_server(server_addr: SocketAddr, data: Arc<ServerData>) {
    let server = TcpListener::bind(&server_addr).unwrap();
    let incoming = forever::ListenForever::new(server.incoming());
    tokio::spawn(incoming.for_each(move |stream| {
        let peer_addr = stream.peer_addr().unwrap();
        let data = Arc::clone(&data);
        let config = Some(protocol::WebSocketConfig {
            // # of protocol Message's
            max_send_queue: Some(16),
            // 64 MiB
            max_message_size: Some(64 << 20),
            // 16 MiB
            max_frame_size: Some(16 << 20),
        });
        tokio::spawn(
            tokio_tungstenite::accept_async_with_config(stream, config)
                .and_then(move |ws| {
                    info!("[{}] Connection opened", peer_addr);

                    let (tx, rx) = mpsc::channel(32);
                    let (sink, stream) = ws.split();
                    let mut state = WsState::new(peer_addr, tx.clone());
                    let needs_pong = state.needs_pong();

                    let ws_reader = stream.for_each({
                        let data = Arc::clone(&data);
                        let tx = tx.clone();
                        move |msg| {
                            let res = process_ws_message(&data, &mut state, msg);
                            if let Some(res) = res {
                                future::Either::A(tx.clone().send(res).then(move |res| {
                                    if res.is_err() {
                                        error!("[{}] Failed to send message", peer_addr);
                                    }
                                    Ok(())
                                }))
                            } else {
                                future::Either::B(future::ok(()))
                            }
                        }
                    });
                    let ws_writer = rx.forward(sink.sink_map_err(move |e| {
                        error!("[{}] Sink send error: {:?}", peer_addr, e);
                    }));

                    let heartbeat_interval = Interval::new_interval(Duration::from_secs(20))
                        .take_while(move |_| Ok(!needs_pong.swap(true, Ordering::AcqRel)))
                        .for_each(move |_| {
                            let msg = Msg {
                                id: u32::max_value(),
                                body: Body::Ping(get_epoch_ms()),
                            };

                            let mut buf = Vec::with_capacity(16);
                            msg.serialize(&mut buf);
                            tx.clone().send(WsMessage::Binary(buf)).then(|_| Ok(()))
                        });

                    let conn = ws_reader.select2(ws_writer).select2(heartbeat_interval);
                    tokio::spawn(conn.then(move |_| {
                        info!("[{}] Connection closed", peer_addr);
                        // Remove block subscriptions if there are any
                        data.sub_pool.remove(peer_addr);
                        Ok(())
                    }));

                    Ok(())
                })
                .map_err(move |e| {
                    error!("[{}] WS accept error = {:?}", peer_addr, e);
                }),
        );
        Ok(())
    }));
}

pub fn process_ws_message(
    data: &ServerData,
    state: &mut WsState,
    msg: WsMessage,
) -> Option<WsMessage> {
    match msg {
        WsMessage::Binary(buf) => {
            state.set_needs_pong(false);

            let mut cur = Cursor::<&[u8]>::new(&buf);
            let msg = match Msg::deserialize(&mut cur) {
                Ok(msg) => {
                    let id = msg.id;
                    if cur.position() != buf.len() as u64 {
                        Msg {
                            id,
                            body: Body::Error(ErrorKind::BytesRemaining),
                        }
                    } else {
                        match handle_protocol_message(data, state, msg) {
                            Some(body) => Msg { id, body },
                            None => return None,
                        }
                    }
                }
                Err(e) => {
                    error!("Error occurred during deserialization: {:?}", e);
                    Msg {
                        id: u32::max_value(),
                        body: Body::Error(ErrorKind::Io),
                    }
                }
            };

            let mut buf = Vec::with_capacity(65536);
            msg.serialize(&mut buf);
            Some(WsMessage::Binary(buf))
        }
        WsMessage::Text(_) => Some(WsMessage::Close(Some(protocol::CloseFrame {
            code: protocol::frame::coding::CloseCode::Unsupported,
            reason: "text is not supported".into(),
        }))),
        _ => None,
    }
}

fn handle_protocol_message(data: &ServerData, state: &mut WsState, msg: Msg) -> Option<Body> {
    match msg.body {
        Body::Error(e) => {
            warn!(
                "[{}] Received error message from client: {:?}",
                state.addr(),
                e
            );
            None
        }
        Body::Request(req) => handle_rpc_request(data, state, msg.id, req),
        Body::Response(res) => {
            warn!(
                "[{}] Unexpected response from client: {:?}",
                state.addr(),
                res
            );
            None
        }
        Body::Ping(nonce) => Some(Body::Pong(nonce)),
        Body::Pong(_) => {
            // We don't need to update the `needs_pong` state as it has already been updated when the message was
            // deserialized
            None
        }
    }
}

fn handle_rpc_request(
    data: &ServerData,
    state: &mut WsState,
    id: u32,
    req: rpc::Request,
) -> Option<Body> {
    Some(match req {
        rpc::Request::Broadcast(tx) => {
            let res = data.minter.push_tx(tx);
            match res {
                Ok(_) => Body::Response(rpc::Response::Broadcast),
                Err(e) => Body::Error(ErrorKind::TxValidation(e)),
            }
        }
        rpc::Request::SetBlockFilter(filter) => {
            if filter.len() > 16 {
                return Some(Body::Error(ErrorKind::InvalidRequest));
            }
            state.filter = Some(filter);
            Body::Response(rpc::Response::SetBlockFilter)
        }
        rpc::Request::ClearBlockFilter => {
            state.filter = None;
            Body::Response(rpc::Response::ClearBlockFilter)
        }
        rpc::Request::Subscribe => {
            data.sub_pool.insert(state.addr(), state.sender());
            Body::Response(rpc::Response::Subscribe)
        }
        rpc::Request::Unsubscribe => {
            data.sub_pool.remove(state.addr());
            Body::Response(rpc::Response::Unsubscribe)
        }
        rpc::Request::GetProperties => {
            let props = data.chain.get_properties();
            Body::Response(rpc::Response::GetProperties(props))
        }
        rpc::Request::GetBlock(height) => match &state.filter {
            Some(filter) => match data.chain.get_filtered_block(height, filter) {
                Some(block) => Body::Response(rpc::Response::GetBlock(block)),
                None => Body::Error(ErrorKind::InvalidHeight),
            },
            None => match data.chain.get_block(height) {
                Some(block) => Body::Response(rpc::Response::GetBlock(FilteredBlock::Block(block))),
                None => Body::Error(ErrorKind::InvalidHeight),
            },
        },
        rpc::Request::GetFullBlock(height) => match data.chain.get_block(height) {
            Some(block) => Body::Response(rpc::Response::GetFullBlock(block)),
            None => Body::Error(ErrorKind::InvalidHeight),
        },
        rpc::Request::GetBlockRange(min_height, max_height) => {
            let range = AsyncBlockRange::try_new(Arc::clone(&data.chain), min_height, max_height);
            match range {
                Some(mut range) => {
                    if let Some(filter) = state.filter() {
                        range.set_filter(Some(filter.clone()));
                    }

                    let peer_addr = state.addr();
                    let tx = state.sender();
                    tokio::spawn(
                        range
                            .map(move |block| {
                                let msg = Msg {
                                    id,
                                    body: Body::Response(rpc::Response::GetBlock(block)),
                                };

                                let mut buf = Vec::with_capacity(65536);
                                msg.serialize(&mut buf);
                                WsMessage::Binary(buf)
                            })
                            .forward(tx.clone().sink_map_err(move |_| {
                                error!("[{}] Failed to send block range update", peer_addr);
                            }))
                            .and_then(move |_| {
                                let msg = Msg {
                                    id,
                                    body: Body::Response(rpc::Response::GetBlockRange),
                                };

                                let mut buf = Vec::with_capacity(32);
                                msg.serialize(&mut buf);
                                tx.send(WsMessage::Binary(buf))
                                    .map(|_sink| ())
                                    .map_err(move |_| {
                                        error!(
                                            "[{}] Failed to send block range finalizer",
                                            peer_addr
                                        );
                                    })
                            }),
                    );

                    return None;
                }
                None => Body::Error(ErrorKind::InvalidHeight),
            }
        }
        rpc::Request::GetAddressInfo(addr) => {
            let res = data.minter.get_addr_info(&addr);
            match res {
                Ok(info) => Body::Response(rpc::Response::GetAddressInfo(info)),
                Err(e) => Body::Error(ErrorKind::TxValidation(e)),
            }
        }
    })
}

pub struct WsState {
    filter: Option<BlockFilter>,
    addr: SocketAddr,
    tx: Sender<WsMessage>,
    needs_pong: Arc<AtomicBool>,
}

impl WsState {
    #[inline]
    pub fn new(addr: SocketAddr, tx: Sender<WsMessage>) -> Self {
        Self {
            filter: None,
            addr,
            tx,
            needs_pong: Arc::new(AtomicBool::new(false)),
        }
    }

    #[inline]
    pub fn needs_pong(&self) -> Arc<AtomicBool> {
        Arc::clone(&self.needs_pong)
    }

    #[inline]
    pub fn set_needs_pong(&self, flag: bool) {
        self.needs_pong.store(flag, Ordering::Release);
    }

    #[inline]
    pub fn addr(&self) -> SocketAddr {
        self.addr
    }

    #[inline]
    pub fn filter(&self) -> Option<&BlockFilter> {
        self.filter.as_ref()
    }

    #[inline]
    pub fn sender(&self) -> Sender<WsMessage> {
        self.tx.clone()
    }
}
<commit_msg>Add debug logging for ping/pong messages<commit_after>use futures::sync::mpsc::{self, Sender};
use godcoin::{blockchain::ReindexOpts, get_epoch_ms, net::*, prelude::*};
use log::{error, info, warn, debug};
use std::{
    io::Cursor,
    net::SocketAddr,
    path::PathBuf,
    sync::{
        atomic::{AtomicBool, Ordering},
        Arc,
    },
    time::Duration,
};
use tokio::{net::TcpListener, prelude::*, timer::Interval};
use tokio_tungstenite::tungstenite::{protocol, Message as WsMessage};

mod block_range;
mod forever;
pub mod minter;
pub mod pool;

pub mod prelude {
    pub use super::minter::*;
    pub use super::pool::SubscriptionPool;
}

use block_range::AsyncBlockRange;
use prelude::*;

pub struct ServerOpts {
    pub blocklog_loc: PathBuf,
    pub index_loc: PathBuf,
    pub minter_key: KeyPair,
    pub bind_addr: String,
    pub reindex: Option<ReindexOpts>,
    pub enable_stale_production: bool,
}

#[derive(Clone)]
pub struct ServerData {
    pub chain: Arc<Blockchain>,
    pub minter: Minter,
    pub sub_pool: SubscriptionPool,
}

pub fn start(opts: ServerOpts) {
    let blockchain = Arc::new(Blockchain::new(&opts.blocklog_loc, &opts.index_loc));

    let is_empty = blockchain.is_empty();
    if !is_empty && blockchain.index_status() != IndexStatus::Complete {
        warn!(
            "Indexing not complete (status = {:?})",
            blockchain.index_status()
        );
        match opts.reindex {
            Some(opts) => blockchain.reindex(opts),
            None => panic!("index incomplete, aborting..."),
        }
    }

    if is_empty {
        let info = blockchain.create_genesis_block(opts.minter_key.clone());
        info!("=> Generated new block chain");
        info!("=> {:?}", info.script);
        for (index, key) in info.wallet_keys.iter().enumerate() {
            info!("=> Wallet key {}: {}", index + 1, key.1.to_wif());
        }
    }

    info!(
        "Using height in block log at {}",
        blockchain.get_chain_height()
    );

    let sub_pool = SubscriptionPool::new();
    let minter = Minter::new(
        Arc::clone(&blockchain),
        opts.minter_key,
        sub_pool.clone(),
        opts.enable_stale_production,
    );
    minter.clone().start_production_loop();

    let data = Arc::new(ServerData {
        chain: Arc::clone(&blockchain),
        minter,
        sub_pool,
    });

    let addr = opts.bind_addr.parse::<SocketAddr>().unwrap();
    start_server(addr, data);
}

fn start_server(server_addr: SocketAddr, data: Arc<ServerData>) {
    let server = TcpListener::bind(&server_addr).unwrap();
    let incoming = forever::ListenForever::new(server.incoming());
    tokio::spawn(incoming.for_each(move |stream| {
        let peer_addr = stream.peer_addr().unwrap();
        let data = Arc::clone(&data);
        let config = Some(protocol::WebSocketConfig {
            // # of protocol Message's
            max_send_queue: Some(16),
            // 64 MiB
            max_message_size: Some(64 << 20),
            // 16 MiB
            max_frame_size: Some(16 << 20),
        });
        tokio::spawn(
            tokio_tungstenite::accept_async_with_config(stream, config)
                .and_then(move |ws| {
                    info!("[{}] Connection opened", peer_addr);

                    let (tx, rx) = mpsc::channel(32);
                    let (sink, stream) = ws.split();
                    let mut state = WsState::new(peer_addr, tx.clone());
                    let needs_pong = state.needs_pong();

                    let ws_reader = stream.for_each({
                        let data = Arc::clone(&data);
                        let tx = tx.clone();
                        move |msg| {
                            let res = process_ws_message(&data, &mut state, msg);
                            if let Some(res) = res {
                                future::Either::A(tx.clone().send(res).then(move |res| {
                                    if res.is_err() {
                                        error!("[{}] Failed to send message", peer_addr);
                                    }
                                    Ok(())
                                }))
                            } else {
                                future::Either::B(future::ok(()))
                            }
                        }
                    });
                    let ws_writer = rx.forward(sink.sink_map_err(move |e| {
                        error!("[{}] Sink send error: {:?}", peer_addr, e);
                    }));

                    let heartbeat_interval = Interval::new_interval(Duration::from_secs(20))
                        .take_while(move |_| Ok(!needs_pong.swap(true, Ordering::AcqRel)))
                        .for_each(move |_| {
                            let nonce = get_epoch_ms();
                            let msg = Msg {
                                id: u32::max_value(),
                                body: Body::Ping(nonce),
                            };
                            debug!("[{}] Sending ping: {}", peer_addr, nonce);

                            let mut buf = Vec::with_capacity(16);
                            msg.serialize(&mut buf);
                            tx.clone().send(WsMessage::Binary(buf)).then(|_| Ok(()))
                        });

                    let conn = ws_reader.select2(ws_writer).select2(heartbeat_interval);
                    tokio::spawn(conn.then(move |_| {
                        info!("[{}] Connection closed", peer_addr);
                        // Remove block subscriptions if there are any
                        data.sub_pool.remove(peer_addr);
                        Ok(())
                    }));

                    Ok(())
                })
                .map_err(move |e| {
                    error!("[{}] WS accept error = {:?}", peer_addr, e);
                }),
        );
        Ok(())
    }));
}

pub fn process_ws_message(
    data: &ServerData,
    state: &mut WsState,
    msg: WsMessage,
) -> Option<WsMessage> {
    match msg {
        WsMessage::Binary(buf) => {
            state.set_needs_pong(false);

            let mut cur = Cursor::<&[u8]>::new(&buf);
            let msg = match Msg::deserialize(&mut cur) {
                Ok(msg) => {
                    let id = msg.id;
                    if cur.position() != buf.len() as u64 {
                        Msg {
                            id,
                            body: Body::Error(ErrorKind::BytesRemaining),
                        }
                    } else {
                        match handle_protocol_message(data, state, msg) {
                            Some(body) => Msg { id, body },
                            None => return None,
                        }
                    }
                }
                Err(e) => {
                    error!("Error occurred during deserialization: {:?}", e);
                    Msg {
                        id: u32::max_value(),
                        body: Body::Error(ErrorKind::Io),
                    }
                }
            };

            let mut buf = Vec::with_capacity(65536);
            msg.serialize(&mut buf);
            Some(WsMessage::Binary(buf))
        }
        WsMessage::Text(_) => Some(WsMessage::Close(Some(protocol::CloseFrame {
            code: protocol::frame::coding::CloseCode::Unsupported,
            reason: "text is not supported".into(),
        }))),
        _ => None,
    }
}

fn handle_protocol_message(data: &ServerData, state: &mut WsState, msg: Msg) -> Option<Body> {
    match msg.body {
        Body::Error(e) => {
            warn!(
                "[{}] Received error message from client: {:?}",
                state.addr(),
                e
            );
            None
        }
        Body::Request(req) => handle_rpc_request(data, state, msg.id, req),
        Body::Response(res) => {
            warn!(
                "[{}] Unexpected response from client: {:?}",
                state.addr(),
                res
            );
            None
        }
        Body::Ping(nonce) => {
            debug!("[{}] Received ping: {}", state.addr(), nonce);
            Some(Body::Pong(nonce))
        }
        Body::Pong(nonce) => {
            debug!("[{}] Received pong: {}", state.addr(), nonce);
            // We don't need to update the `needs_pong` state as it has already been updated when the message was
            // deserialized
            None
        }
    }
}

fn handle_rpc_request(
    data: &ServerData,
    state: &mut WsState,
    id: u32,
    req: rpc::Request,
) -> Option<Body> {
    Some(match req {
        rpc::Request::Broadcast(tx) => {
            let res = data.minter.push_tx(tx);
            match res {
                Ok(_) => Body::Response(rpc::Response::Broadcast),
                Err(e) => Body::Error(ErrorKind::TxValidation(e)),
            }
        }
        rpc::Request::SetBlockFilter(filter) => {
            if filter.len() > 16 {
                return Some(Body::Error(ErrorKind::InvalidRequest));
            }
            state.filter = Some(filter);
            Body::Response(rpc::Response::SetBlockFilter)
        }
        rpc::Request::ClearBlockFilter => {
            state.filter = None;
            Body::Response(rpc::Response::ClearBlockFilter)
        }
        rpc::Request::Subscribe => {
            data.sub_pool.insert(state.addr(), state.sender());
            Body::Response(rpc::Response::Subscribe)
        }
        rpc::Request::Unsubscribe => {
            data.sub_pool.remove(state.addr());
            Body::Response(rpc::Response::Unsubscribe)
        }
        rpc::Request::GetProperties => {
            let props = data.chain.get_properties();
            Body::Response(rpc::Response::GetProperties(props))
        }
        rpc::Request::GetBlock(height) => match &state.filter {
            Some(filter) => match data.chain.get_filtered_block(height, filter) {
                Some(block) => Body::Response(rpc::Response::GetBlock(block)),
                None => Body::Error(ErrorKind::InvalidHeight),
            },
            None => match data.chain.get_block(height) {
                Some(block) => Body::Response(rpc::Response::GetBlock(FilteredBlock::Block(block))),
                None => Body::Error(ErrorKind::InvalidHeight),
            },
        },
        rpc::Request::GetFullBlock(height) => match data.chain.get_block(height) {
            Some(block) => Body::Response(rpc::Response::GetFullBlock(block)),
            None => Body::Error(ErrorKind::InvalidHeight),
        },
        rpc::Request::GetBlockRange(min_height, max_height) => {
            let range = AsyncBlockRange::try_new(Arc::clone(&data.chain), min_height, max_height);
            match range {
                Some(mut range) => {
                    if let Some(filter) = state.filter() {
                        range.set_filter(Some(filter.clone()));
                    }

                    let peer_addr = state.addr();
                    let tx = state.sender();
                    tokio::spawn(
                        range
                            .map(move |block| {
                                let msg = Msg {
                                    id,
                                    body: Body::Response(rpc::Response::GetBlock(block)),
                                };

                                let mut buf = Vec::with_capacity(65536);
                                msg.serialize(&mut buf);
                                WsMessage::Binary(buf)
                            })
                            .forward(tx.clone().sink_map_err(move |_| {
                                error!("[{}] Failed to send block range update", peer_addr);
                            }))
                            .and_then(move |_| {
                                let msg = Msg {
                                    id,
                                    body: Body::Response(rpc::Response::GetBlockRange),
                                };

                                let mut buf = Vec::with_capacity(32);
                                msg.serialize(&mut buf);
                                tx.send(WsMessage::Binary(buf))
                                    .map(|_sink| ())
                                    .map_err(move |_| {
                                        error!(
                                            "[{}] Failed to send block range finalizer",
                                            peer_addr
                                        );
                                    })
                            }),
                    );

                    return None;
                }
                None => Body::Error(ErrorKind::InvalidHeight),
            }
        }
        rpc::Request::GetAddressInfo(addr) => {
            let res = data.minter.get_addr_info(&addr);
            match res {
                Ok(info) => Body::Response(rpc::Response::GetAddressInfo(info)),
                Err(e) => Body::Error(ErrorKind::TxValidation(e)),
            }
        }
    })
}

pub struct WsState {
    filter: Option<BlockFilter>,
    addr: SocketAddr,
    tx: Sender<WsMessage>,
    needs_pong: Arc<AtomicBool>,
}

impl WsState {
    #[inline]
    pub fn new(addr: SocketAddr, tx: Sender<WsMessage>) -> Self {
        Self {
            filter: None,
            addr,
            tx,
            needs_pong: Arc::new(AtomicBool::new(false)),
        }
    }

    #[inline]
    pub fn needs_pong(&self) -> Arc<AtomicBool> {
        Arc::clone(&self.needs_pong)
    }

    #[inline]
    pub fn set_needs_pong(&self, flag: bool) {
        self.needs_pong.store(flag, Ordering::Release);
    }

    #[inline]
    pub fn addr(&self) -> SocketAddr {
        self.addr
    }

    #[inline]
    pub fn filter(&self) -> Option<&BlockFilter> {
        self.filter.as_ref()
    }

    #[inline]
    pub fn sender(&self) -> Sender<WsMessage> {
        self.tx.clone()
    }
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;
#[macro_use]
extern crate nickel;
extern crate redis;
extern crate r2d2;
extern crate r2d2_redis;
extern crate plugin;
extern crate typemap;

extern crate core;

use std::env;
use std::collections::HashMap;
use r2d2::NopErrorHandler;
use nickel::{Nickel, HttpRouter, JsonBody, MediaType, QueryString};
use nickel::status::StatusCode;
use core::ops::Deref;
use redis::{Commands, Connection, RedisError};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_serialize::json;

use redis_middleware::{RedisMiddleware, RedisRequestExtensions};
mod redis_middleware;

#[derive(RustcDecodable, RustcEncodable)]
struct RatingSubmission {
    uuid: String,
    mod_str: String,
    rating: Rating,
}

#[derive(Clone, Copy, Debug)]
enum Rating {
    Poor = 0,
    BelowAverage,
    Average,
    AboveAverage,
    Excellent,
}

impl From<u8> for Rating {
    fn from(rating: u8) -> Self {
        match rating {
            0 => Rating::Poor,
            1 => Rating::BelowAverage,
            2 => Rating::Average,
            3 => Rating::AboveAverage,
            _ => Rating::Excellent,
        }
    }
}

impl Decodable for Rating {
    fn decode<D: Decoder>(d: &mut D) -> Result<Rating, D::Error> {
        let r = try!(d.read_u8());
        Ok(Rating::from(r))
    }
}

impl Encodable for Rating {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        let as_u8 = *self as u8;
        s.emit_u8(as_u8)
    }
}

#[derive(RustcEncodable)]
struct RatingResults {
    average: HashMap<String, Rating>,
    amount: HashMap<String, usize>,
    own: Option<HashMap<String, Rating>>,
}

fn incr_requests(conn: &Connection) {
    if let Err(_) = conn.incr::<_, _, u64>("requests", 1) {
        println!("failed to incr request counter.")
    }
}

fn get_mod_rating(conn: &Connection, mod_str: &str) -> Result<(Rating, u32), RedisError> {
    let ratings = try!(conn.hvals::<_, Vec<u8>>(mod_str));
    let length = ratings.len() as u32;
    let mut sum = 0u32;
    for rating in ratings {
        sum += rating as u32;
    }
    match length {
        0 => Ok((Rating::Poor, length)),
        _ => Ok((Rating::from((sum / length) as u8), length)),
    }
}

const OK_RESP: (StatusCode, &'static str) = (StatusCode::Ok, "ok");

fn main() {
    let mut webserver = Nickel::new();

    let redis_url = env::var("DATABASE_URL").unwrap_or("redis://localhost/3".to_owned());
    println!("connecting to redis @ {}", redis_url);

    let redispool = RedisMiddleware::new(&*redis_url, 3, Box::new(NopErrorHandler)).unwrap();
    webserver.utilize(redispool);

    webserver.post("/submit",
                   middleware! { |request, response|
        let rcn_ref = request.redis_conn();
        let redis_conn = rcn_ref.deref();
        incr_requests(&redis_conn);
        let sbm = try_with!(response, {
            request.json_as::<RatingSubmission>().map_err(|e| (StatusCode::BadRequest, e))
        });
        println!("{} rates {} as {:?}", sbm.uuid, sbm.mod_str, sbm.rating);
        let _: bool = try_with!(response, {
            redis_conn.hset("mods", &*sbm.mod_str, true).map_err(|e| (StatusCode::BadRequest, e))
        });
        let _: u8 = try_with!(response, {
            redis_conn.hset(sbm.mod_str, sbm.uuid, sbm.rating as u8).map_err(|e|
                (StatusCode::BadRequest, e)
            )
        });
        OK_RESP
    });

    webserver.get("/rating/:mod",
                  middleware! { |request, response|
        let rcn_ref = request.redis_conn();
        let redis_conn = rcn_ref.deref();
        incr_requests(&redis_conn);
        let mod_str = request.param("mod").unwrap();
        let result = try_with!(response, {
            get_mod_rating(redis_conn, mod_str).map_err(|e| (StatusCode::BadRequest, e))
        });
        match result {
            (_, 0) => (StatusCode::NotFound, "Not Found!".to_owned()),
            (rating, sbm) => (StatusCode::Ok, format!("{:?}, {} submissions", rating, sbm)),
        }
    });

    webserver.get("/ratings",
                  middleware! { |request, mut response|
        let rcn_ref = request.redis_conn();
        let redis_conn = rcn_ref.deref();
        incr_requests(&redis_conn);

        let mods = try_with!(response, {
            redis_conn.hkeys::<_, Vec<String>>("mods").map_err(|e| (StatusCode::BadRequest, e))
        });

        let mut own_ratings: HashMap<String, Rating> = HashMap::new();
        let mut amount_ratings: HashMap<String, usize> = HashMap::new();
        let mut average_ratings: HashMap<String, Rating> = HashMap::new();

        for mod_str in mods {
            let mod_str = mod_str.as_str();
            let (rating, sbm) = try_with!(response, {
                get_mod_rating(redis_conn, mod_str).map_err(|e| (StatusCode::BadRequest, e))
            });
            if sbm == 0 {
                continue;
            }
            average_ratings.insert(mod_str.to_owned(), rating);
            amount_ratings.insert(mod_str.to_owned(), sbm);
            if let Some(uuid) = request.query().get("uuid") {
                if let Ok(rating) = redis_conn.hget::<_, _, u8>(mod_str, uuid) {
                    own_ratings.insert(mod_str.to_owned(), Rating::from(rating));
                }
            }
        }

        let result = RatingResults {
            average: average_ratings,
            amount: amount_ratings,
            own: match request.query().get("uuid") {
                Some(_) => Some(own_ratings),
                None => None,
            },
        };
        response.set(MediaType::Json);
        json::encode(&result).unwrap()
    });

    webserver.listen("127.0.0.1:7998")
}
<commit_msg>switch to usize<commit_after>extern crate rustc_serialize;
#[macro_use]
extern crate nickel;
extern crate redis;
extern crate r2d2;
extern crate r2d2_redis;
extern crate plugin;
extern crate typemap;

extern crate core;

use std::env;
use std::collections::HashMap;
use r2d2::NopErrorHandler;
use nickel::{Nickel, HttpRouter, JsonBody, MediaType, QueryString};
use nickel::status::StatusCode;
use core::ops::Deref;
use redis::{Commands, Connection, RedisError};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_serialize::json;

use redis_middleware::{RedisMiddleware, RedisRequestExtensions};
mod redis_middleware;

#[derive(RustcDecodable, RustcEncodable)]
struct RatingSubmission {
    uuid: String,
    mod_str: String,
    rating: Rating,
}

#[derive(Clone, Copy, Debug)]
enum Rating {
    Poor = 0,
    BelowAverage,
    Average,
    AboveAverage,
    Excellent,
}

impl From<u8> for Rating {
    fn from(rating: u8) -> Self {
        match rating {
            0 => Rating::Poor,
            1 => Rating::BelowAverage,
            2 => Rating::Average,
            3 => Rating::AboveAverage,
            _ => Rating::Excellent,
        }
    }
}

impl Decodable for Rating {
    fn decode<D: Decoder>(d: &mut D) -> Result<Rating, D::Error> {
        let r = try!(d.read_u8());
        Ok(Rating::from(r))
    }
}

impl Encodable for Rating {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        let as_u8 = *self as u8;
        s.emit_u8(as_u8)
    }
}

#[derive(RustcEncodable)]
struct RatingResults {
    average: HashMap<String, Rating>,
    amount: HashMap<String, usize>,
    own: Option<HashMap<String, Rating>>,
}

fn incr_requests(conn: &Connection) {
    if let Err(_) = conn.incr::<_, _, usize>("requests", 1) {
        println!("failed to incr request counter.")
    }
}

fn get_mod_rating(conn: &Connection, mod_str: &str) -> Result<(Rating, usize), RedisError> {
    let ratings = try!(conn.hvals::<_, Vec<usize>>(mod_str));
    let length = ratings.len();
    let mut sum = 0;
    for rating in ratings {
        sum += rating;
    }
    match length {
        0 => Ok((Rating::Poor, length)),
        _ => Ok((Rating::from((sum / length) as u8), length)),
    }
}

const OK_RESP: (StatusCode, &'static str) = (StatusCode::Ok, "ok");

fn main() {
    let mut webserver = Nickel::new();

    let redis_url = env::var("DATABASE_URL").unwrap_or("redis://localhost/3".to_owned());
    println!("connecting to redis @ {}", redis_url);

    let redispool = RedisMiddleware::new(&*redis_url, 3, Box::new(NopErrorHandler)).unwrap();
    webserver.utilize(redispool);

    webserver.post("/submit",
                   middleware! { |request, response|
        let rcn_ref = request.redis_conn();
        let redis_conn = rcn_ref.deref();
        incr_requests(&redis_conn);
        let sbm = try_with!(response, {
            request.json_as::<RatingSubmission>().map_err(|e| (StatusCode::BadRequest, e))
        });
        println!("{} rates {} as {:?}", sbm.uuid, sbm.mod_str, sbm.rating);
        let _: bool = try_with!(response, {
            redis_conn.hset("mods", &*sbm.mod_str, true).map_err(|e| (StatusCode::BadRequest, e))
        });
        let _: u8 = try_with!(response, {
            redis_conn.hset(sbm.mod_str, sbm.uuid, sbm.rating as u8).map_err(|e|
                (StatusCode::BadRequest, e)
            )
        });
        OK_RESP
    });

    webserver.get("/rating/:mod",
                  middleware! { |request, response|
        let rcn_ref = request.redis_conn();
        let redis_conn = rcn_ref.deref();
        incr_requests(&redis_conn);
        let mod_str = request.param("mod").unwrap();
        let result = try_with!(response, {
            get_mod_rating(redis_conn, mod_str).map_err(|e| (StatusCode::BadRequest, e))
        });
        match result {
            (_, 0) => (StatusCode::NotFound, "Not Found!".to_owned()),
            (rating, sbm) => (StatusCode::Ok, format!("{:?}, {} submissions", rating, sbm)),
        }
    });

    webserver.get("/ratings",
                  middleware! { |request, mut response|
        let rcn_ref = request.redis_conn();
        let redis_conn = rcn_ref.deref();
        incr_requests(&redis_conn);

        let mods = try_with!(response, {
            redis_conn.hkeys::<_, Vec<String>>("mods").map_err(|e| (StatusCode::BadRequest, e))
        });

        let mut own_ratings: HashMap<String, Rating> = HashMap::new();
        let mut amount_ratings: HashMap<String, usize> = HashMap::new();
        let mut average_ratings: HashMap<String, Rating> = HashMap::new();

        for mod_str in mods {
            let mod_str = mod_str.as_str();
            let (rating, sbm) = try_with!(response, {
                get_mod_rating(redis_conn, mod_str).map_err(|e| (StatusCode::BadRequest, e))
            });
            if sbm == 0 {
                continue;
            }
            average_ratings.insert(mod_str.to_owned(), rating);
            amount_ratings.insert(mod_str.to_owned(), sbm);
            if let Some(uuid) = request.query().get("uuid") {
                if let Ok(rating) = redis_conn.hget::<_, _, u8>(mod_str, uuid) {
                    own_ratings.insert(mod_str.to_owned(), Rating::from(rating));
                }
            }
        }

        let result = RatingResults {
            average: average_ratings,
            amount: amount_ratings,
            own: match request.query().get("uuid") {
                Some(_) => Some(own_ratings),
                None => None,
            },
        };
        response.set(MediaType::Json);
        json::encode(&result).unwrap()
    });

    webserver.listen("127.0.0.1:7998")
}
<|endoftext|>


<commit_before>use futures::compat::*;
use futures_legacy::task::Spawn as Spawn01;

#[allow(dead_code)]
struct Compat01As03SinkExposed<S, SinkItem> {
    inner: Spawn01<S>,
    buffer: Option<SinkItem>,
    close_started: bool,
}

pub fn exposed_compat_exec<S, SinkItem, F, T>(input: &Compat01As03Sink<S, SinkItem>, f: F) -> T
where
    F: FnOnce(&S) -> T,
{
    let exposed = unsafe { std::mem::transmute::<_, &Compat01As03SinkExposed<S, SinkItem>>(input) };
    f(exposed.inner.get_ref())
}
<commit_msg>Add Google license header to bincode-transport/src/compat.rs<commit_after>// Copyright 2018 Google LLC
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

use futures::compat::*;
use futures_legacy::task::Spawn as Spawn01;

#[allow(dead_code)]
struct Compat01As03SinkExposed<S, SinkItem> {
    inner: Spawn01<S>,
    buffer: Option<SinkItem>,
    close_started: bool,
}

pub fn exposed_compat_exec<S, SinkItem, F, T>(input: &Compat01As03Sink<S, SinkItem>, f: F) -> T
where
    F: FnOnce(&S) -> T,
{
    let exposed = unsafe { std::mem::transmute::<_, &Compat01As03SinkExposed<S, SinkItem>>(input) };
    f(exposed.inner.get_ref())
}
<|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 = "snowmew-render-gfx"]
#![crate_type = "lib"]

#![feature(phase)]
#![allow(dead_code)]

//extern crate debug;

extern crate sync;
extern crate time;
extern crate libc;

extern crate opencl;
extern crate cow;
extern crate glfw;

#[phase(plugin)]
extern crate gfx_macros;
extern crate gfx;
extern crate device;
extern crate render;
extern crate genmesh;

extern crate snowmew  = "snowmew-core";
extern crate position = "snowmew-position";
extern crate graphics = "snowmew-graphics";
extern crate render_data = "snowmew-render-data";

use std::collections::hashmap::HashMap;

use opencl::hl;
use sync::Arc;

use position::Positions;
use graphics::Graphics;
use snowmew::common::ObjectKey;
use snowmew::io::Window;

use graphics::geometry::{Geo, GeoTex, GeoNorm, GeoTexNorm, GeoTexNormTan};
use graphics::geometry::{VertexGeoTex, VertexGeoTexNorm};
use graphics::Drawable;

use cow::join::{join_set_to_map, join_maps};
use render_data::RenderData;

use gfx::{Device, DeviceHelper};

static VERTEX_SRC: gfx::ShaderSource = shaders! {
GLSL_150: b"
    #version 150 core
    uniform mat4 proj_mat;
    uniform mat4 view_mat;
    uniform mat4 model_mat;

    in vec3 position;
    in vec2 texture;

    out vec2 o_texture;

    void main() {
        gl_Position = proj_mat * view_mat * model_mat * vec4(position, 1.0);
        o_texture = texture;
    }
"
};

static FRAGMENT_SRC: gfx::ShaderSource = shaders! {
GLSL_150: b"
    #version 150 core
    uniform vec4 ka_color;
    uniform int ka_use_texture;
    uniform sampler2D ka_texture;

    in vec2 o_texture;

    out vec4 o_Color;

    void main() {
        if (1 == ka_use_texture) {
            o_Color = texture(ka_texture, o_texture);
        } else {
            o_Color = ka_color;
        }
    }
"
};

#[shader_param(MyProgram)]
struct Params {
    proj_mat: [[f32, ..4], ..4],
    view_mat: [[f32, ..4], ..4],
    model_mat: [[f32, ..4], ..4],
    ka_color: [f32, ..4],
    ka_use_texture: i32,
    ka_texture: gfx::shade::TextureParam,
}

struct Mesh {
    mesh: render::mesh::Mesh,
    index: device::BufferHandle<u32>
}

pub struct RenderManager {
    data: Params,
    graphics: render::Graphics<device::gl_device::GlDevice,
                               device::gl_device::GlCommandBuffer>,
    frame: render::target::Frame,
    state: render::state::DrawState,
    prog: device::Handle<u32,device::shade::ProgramInfo>,
    meshes: HashMap<ObjectKey, Mesh>,
    textures: HashMap<ObjectKey, device::TextureHandle>,
    sampler: device::SamplerHandle,
    window: Window
}

impl RenderManager {

    fn _new(mut device: gfx::GlDevice,
            window: Window,
            size: (i32, i32),
            _: Option<Arc<hl::Device>>) -> RenderManager {

        let (width, height) = size;
        let frame = gfx::Frame::new(width as u16, height as u16);
        let state = gfx::DrawState::new().depth(gfx::state::LessEqual, true);

        let sampler = device.create_sampler(
            gfx::tex::SamplerInfo::new(
                    gfx::tex::Bilinear, gfx::tex::Tile
            )
        );

        let (prog, data) = {
            let tinfo = gfx::tex::TextureInfo {
                width: 1,
                height: 1,
                depth: 1,
                levels: 1,
                kind: gfx::tex::Texture2D,
                format: gfx::tex::RGBA8,
            };

            let img_info = tinfo.to_image_info();
            let dummy_texture = device.create_texture(tinfo)
                                      .ok().expect("Failed to create texture");
            device.update_texture(&dummy_texture,
                                  &img_info,
                                  &vec![0u8, 0, 0, 0].as_slice());

            let data = Params {
                proj_mat: [
                    [1.0, 0.0, 0.0, 0.0],
                    [0.0, 1.0, 0.0, 0.0],
                    [0.0, 0.0, 1.0, 0.0],
                    [0.0, 0.0, 0.0, 1.0],
                ],
                view_mat: [
                    [1.0, 0.0, 0.0, 0.0],
                    [0.0, 1.0, 0.0, 0.0],
                    [0.0, 0.0, 1.0, 0.0],
                    [0.0, 0.0, 0.0, 1.0],
                ],
                model_mat: [
                    [1.0, 0.0, 0.0, 0.0],
                    [0.0, 1.0, 0.0, 0.0],
                    [0.0, 0.0, 1.0, 0.0],
                    [0.0, 0.0, 0.0, 1.0],
                ],
                ka_use_texture: 0,
                ka_color: [1., 1., 1., 1.],
                ka_texture: (dummy_texture, Some(sampler))
            };
            (device.link_program(VERTEX_SRC.clone(), FRAGMENT_SRC.clone())
                  .ok().expect("Failed to link program"),
             data)
        };

        RenderManager {
            data: data,
            graphics: gfx::Graphics::new(device),
            frame: frame,
            state: state,
            prog: prog,
            meshes: HashMap::new(),
            textures: HashMap::new(),
            sampler: sampler,
            window: window
        }
    }

    fn load_meshes<RD: RenderData>(&mut self, db: &RD) {
        for (oid, vb) in db.vertex_buffer_iter() {
            if self.meshes.find(oid).is_none() {
                let mesh = match vb.vertex {
                    Geo(ref d) => {
                        println!("Geo");
                        let data: Vec<VertexGeoTex> = d.iter()
                            .map(|v| {
                                VertexGeoTex {
                                    position: v.position,
                                    texture: [0., 0.]
                                }
                            })
                            .collect();
                        self.graphics.device.create_mesh(data)
                    },
                    GeoTex(ref d) => {
                        println!("GeoTex");
                        self.graphics.device.create_mesh(d.clone())
                    },
                    GeoNorm(ref d) => {
                        let data: Vec<VertexGeoTexNorm> = d.iter()
                            .map(|v| {
                                VertexGeoTexNorm {
                                    position: v.position,
                                    texture: [0., 0.],
                                    normal: v.normal
                                }
                            })
                            .collect();
                        self.graphics.device.create_mesh(data)
                    },
                    GeoTexNorm(ref d) => {
                        println!("GeoTexNorm");
                        self.graphics.device.create_mesh(d.clone())
                    },
                    GeoTexNormTan(ref d) => {
                        println!("GeoTexNormTan");
                        self.graphics.device.create_mesh(d.clone())
                    }
                };

                let vb: Vec<u32> = vb.index.iter().map(|&x| x as u32).collect();

                let index = self.graphics.device.create_buffer_static(&vb);

                self.meshes.insert(*oid, Mesh {
                    index: index,
                    mesh: mesh
                });
            }
        }
    }

    fn load_textures<RD: RenderData>(&mut self, db: &RD) {
        for (oid, text) in db.texture_iter() {
            if self.textures.find(oid).is_none() {
                let tinfo = gfx::tex::TextureInfo {
                    width: text.width() as u16,
                    height: text.height() as u16,
                    depth: 1 as u16,
                    levels: 1,
                    kind: gfx::tex::Texture2D,
                    format: match text.depth() {
                        4 => gfx::tex::Unsigned(gfx::tex::RGBA, 8, gfx::attrib::IntNormalized),
                        3 => gfx::tex::Unsigned(gfx::tex::RGB, 8, gfx::attrib::IntNormalized),
                        _ => fail!("Unsupported color depth")
                    }
                };

                let img_info = tinfo.to_image_info();
                let texture = self.graphics.device.create_texture(tinfo)
                                         .ok().expect("Failed to create texture");
                self.graphics.device.update_texture(&texture, &img_info, &text.data().to_vec());
                self.textures.insert(*oid, texture);
            }
        }
    }

    fn draw<RD: RenderData>(&mut self, db: &RD, scene: ObjectKey, camera: ObjectKey) {
        let cdata = gfx::ClearData {
            color: Some([0.3, 0.3, 0.3, 1.0]),
            depth: Some(1.0),
            stencil: None,
        };
        let start = time::precise_time_s();
        self.graphics.clear(cdata, &self.frame);

        let camera_trans = db.position(camera);
        let camera = snowmew::camera::Camera::new(camera_trans);

        let proj = camera.projection_matrix(16. / 9.);
        self.data.proj_mat =
            [[proj.x.x, proj.x.y, proj.x.z, proj.x.w],
             [proj.y.x, proj.y.y, proj.y.z, proj.y.w],
             [proj.z.x, proj.z.y, proj.z.z, proj.z.w],
             [proj.w.x, proj.w.y, proj.w.z, proj.w.w]];

        let view = camera.view_matrix();
        self.data.view_mat =
            [[view.x.x, view.x.y, view.x.z, view.x.w],
             [view.y.x, view.y.y, view.y.z, view.y.w],
             [view.z.x, view.z.y, view.z.z, view.z.w],
             [view.w.x, view.w.y, view.w.z, view.w.w]];

        let mut batches: HashMap<u32, MyProgram> = HashMap::new();

        for (_, draw) in db.drawable_iter() {
            if batches.contains_key(&draw.geometry) {
                continue;
            }

            let geo = db.geometry(draw.geometry).expect("failed to find geometry");
            let vb = self.meshes.find(&geo.vb).expect("Could not get vertex buffer");

            let batch: MyProgram = self.graphics.make_batch(
                &self.prog,
                &vb.mesh,
                gfx::IndexSlice32(gfx::TriangleList,
                                  vb.index,
                                  geo.offset as u32,
                                  geo.count as u32),
                &self.state
            ).unwrap();

            batches.insert(draw.geometry, batch);
        }

        for (id, (draw, _)) in join_set_to_map(db.scene_iter(scene),
                                               join_maps(db.drawable_iter(),
                                                         db.location_iter())) {

            let mat = db.material(draw.material).expect("Could not find material");
            let model = db.position(*id);

            self.data.model_mat =
                [[model.x.x, model.x.y, model.x.z, model.x.w],
                 [model.y.x, model.y.y, model.y.z, model.y.w],
                 [model.z.x, model.z.y, model.z.z, model.z.w],
                 [model.w.x, model.w.y, model.w.z, model.w.w]];

            self.data.ka_use_texture = match mat.map_ka() {
                Some(tid) => {
                    let &texture = self.textures.find(&tid).expect("Texture not loaded");
                    self.data.ka_texture = (texture, Some(self.sampler));
                    1
                }
                None => {
                    let [r, g, b] = mat.ka();
                    self.data.ka_color = [r, g, b, 1.];
                    0
                }
            };

            self.graphics.draw(
                batches.find(&draw.geometry).expect("Missing draw"),
                &self.data,
                &self.frame
            );
        }

        self.graphics.end_frame();
        self.window.swap_buffers();
        let end = time::precise_time_s();
        println!("{0:4.3}ms", (end - start) * 1000.);
    }
}

impl<RD: RenderData+Send> snowmew::Render<RD> for RenderManager {
    fn update(&mut self, db: RD, scene: ObjectKey, camera: ObjectKey) {
        self.load_meshes(&db);
        self.load_textures(&db);
        self.draw(&db, scene, camera);
    }
}

impl<RD: RenderData+Send> snowmew::RenderFactory<RD, RenderManager> for RenderFactory {
    fn init(self: Box<RenderFactory>,
            io: &snowmew::IOManager,
            window: Window,
            size: (i32, i32),
            cl: Option<Arc<hl::Device>>) -> RenderManager {

        window.make_context_current();

        let mut device = gfx::GlDevice::new(|s| io.get_proc_address(s));
        RenderManager::_new(device, window, size, cl)
    }
}

pub struct RenderFactory;

impl RenderFactory {
    pub fn new() -> RenderFactory { RenderFactory }
}<commit_msg>cleanup draw()<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 = "snowmew-render-gfx"]
#![crate_type = "lib"]

#![feature(phase)]
#![allow(dead_code)]

//extern crate debug;

extern crate sync;
extern crate time;
extern crate libc;

extern crate opencl;
extern crate cow;
extern crate glfw;

#[phase(plugin)]
extern crate gfx_macros;
extern crate gfx;
extern crate device;
extern crate render;
extern crate genmesh;

extern crate snowmew  = "snowmew-core";
extern crate position = "snowmew-position";
extern crate graphics = "snowmew-graphics";
extern crate render_data = "snowmew-render-data";

use std::collections::hashmap::HashMap;

use opencl::hl;
use sync::Arc;

use position::Positions;
use graphics::Graphics;
use snowmew::common::ObjectKey;
use snowmew::io::Window;

use graphics::geometry::{Geo, GeoTex, GeoNorm, GeoTexNorm, GeoTexNormTan};
use graphics::geometry::{VertexGeoTex, VertexGeoTexNorm};
use graphics::Drawable;

use cow::join::{join_set_to_map, join_maps};
use render_data::RenderData;

use gfx::{Device, DeviceHelper};

static VERTEX_SRC: gfx::ShaderSource = shaders! {
GLSL_150: b"
    #version 150 core
    uniform mat4 proj_mat;
    uniform mat4 view_mat;
    uniform mat4 model_mat;

    in vec3 position;
    in vec2 texture;

    out vec2 o_texture;

    void main() {
        gl_Position = proj_mat * view_mat * model_mat * vec4(position, 1.0);
        o_texture = texture;
    }
"
};

static FRAGMENT_SRC: gfx::ShaderSource = shaders! {
GLSL_150: b"
    #version 150 core
    uniform vec4 ka_color;
    uniform int ka_use_texture;
    uniform sampler2D ka_texture;

    in vec2 o_texture;

    out vec4 o_Color;

    void main() {
        if (1 == ka_use_texture) {
            o_Color = texture(ka_texture, o_texture);
        } else {
            o_Color = ka_color;
        }
    }
"
};

#[shader_param(MyProgram)]
struct Params {
    proj_mat: [[f32, ..4], ..4],
    view_mat: [[f32, ..4], ..4],
    model_mat: [[f32, ..4], ..4],
    ka_color: [f32, ..4],
    ka_use_texture: i32,
    ka_texture: gfx::shade::TextureParam,
}

struct Mesh {
    mesh: render::mesh::Mesh,
    index: device::BufferHandle<u32>
}

pub struct RenderManager {
    data: Params,
    graphics: render::Graphics<device::gl_device::GlDevice,
                               device::gl_device::GlCommandBuffer>,
    frame: render::target::Frame,
    state: render::state::DrawState,
    prog: device::Handle<u32,device::shade::ProgramInfo>,
    meshes: HashMap<ObjectKey, Mesh>,
    textures: HashMap<ObjectKey, device::TextureHandle>,
    sampler: device::SamplerHandle,
    window: Window
}

impl RenderManager {

    fn _new(mut device: gfx::GlDevice,
            window: Window,
            size: (i32, i32),
            _: Option<Arc<hl::Device>>) -> RenderManager {

        let (width, height) = size;
        let frame = gfx::Frame::new(width as u16, height as u16);
        let state = gfx::DrawState::new().depth(gfx::state::LessEqual, true);

        let sampler = device.create_sampler(
            gfx::tex::SamplerInfo::new(
                    gfx::tex::Bilinear, gfx::tex::Tile
            )
        );

        let (prog, data) = {
            let tinfo = gfx::tex::TextureInfo {
                width: 1,
                height: 1,
                depth: 1,
                levels: 1,
                kind: gfx::tex::Texture2D,
                format: gfx::tex::RGBA8,
            };

            let img_info = tinfo.to_image_info();
            let dummy_texture = device.create_texture(tinfo)
                                      .ok().expect("Failed to create texture");
            device.update_texture(&dummy_texture,
                                  &img_info,
                                  &vec![0u8, 0, 0, 0].as_slice());

            let data = Params {
                proj_mat: [
                    [1.0, 0.0, 0.0, 0.0],
                    [0.0, 1.0, 0.0, 0.0],
                    [0.0, 0.0, 1.0, 0.0],
                    [0.0, 0.0, 0.0, 1.0],
                ],
                view_mat: [
                    [1.0, 0.0, 0.0, 0.0],
                    [0.0, 1.0, 0.0, 0.0],
                    [0.0, 0.0, 1.0, 0.0],
                    [0.0, 0.0, 0.0, 1.0],
                ],
                model_mat: [
                    [1.0, 0.0, 0.0, 0.0],
                    [0.0, 1.0, 0.0, 0.0],
                    [0.0, 0.0, 1.0, 0.0],
                    [0.0, 0.0, 0.0, 1.0],
                ],
                ka_use_texture: 0,
                ka_color: [1., 1., 1., 1.],
                ka_texture: (dummy_texture, Some(sampler))
            };
            (device.link_program(VERTEX_SRC.clone(), FRAGMENT_SRC.clone())
                  .ok().expect("Failed to link program"),
             data)
        };

        RenderManager {
            data: data,
            graphics: gfx::Graphics::new(device),
            frame: frame,
            state: state,
            prog: prog,
            meshes: HashMap::new(),
            textures: HashMap::new(),
            sampler: sampler,
            window: window
        }
    }

    fn load_meshes<RD: RenderData>(&mut self, db: &RD) {
        for (oid, vb) in db.vertex_buffer_iter() {
            if self.meshes.find(oid).is_none() {
                let mesh = match vb.vertex {
                    Geo(ref d) => {
                        println!("Geo");
                        let data: Vec<VertexGeoTex> = d.iter()
                            .map(|v| {
                                VertexGeoTex {
                                    position: v.position,
                                    texture: [0., 0.]
                                }
                            })
                            .collect();
                        self.graphics.device.create_mesh(data)
                    },
                    GeoTex(ref d) => {
                        println!("GeoTex");
                        self.graphics.device.create_mesh(d.clone())
                    },
                    GeoNorm(ref d) => {
                        let data: Vec<VertexGeoTexNorm> = d.iter()
                            .map(|v| {
                                VertexGeoTexNorm {
                                    position: v.position,
                                    texture: [0., 0.],
                                    normal: v.normal
                                }
                            })
                            .collect();
                        self.graphics.device.create_mesh(data)
                    },
                    GeoTexNorm(ref d) => {
                        println!("GeoTexNorm");
                        self.graphics.device.create_mesh(d.clone())
                    },
                    GeoTexNormTan(ref d) => {
                        println!("GeoTexNormTan");
                        self.graphics.device.create_mesh(d.clone())
                    }
                };

                let vb: Vec<u32> = vb.index.iter().map(|&x| x as u32).collect();

                let index = self.graphics.device.create_buffer_static(&vb);

                self.meshes.insert(*oid, Mesh {
                    index: index,
                    mesh: mesh
                });
            }
        }
    }

    fn load_textures<RD: RenderData>(&mut self, db: &RD) {
        for (oid, text) in db.texture_iter() {
            if self.textures.find(oid).is_none() {
                let tinfo = gfx::tex::TextureInfo {
                    width: text.width() as u16,
                    height: text.height() as u16,
                    depth: 1 as u16,
                    levels: 1,
                    kind: gfx::tex::Texture2D,
                    format: match text.depth() {
                        4 => gfx::tex::Unsigned(gfx::tex::RGBA, 8, gfx::attrib::IntNormalized),
                        3 => gfx::tex::Unsigned(gfx::tex::RGB, 8, gfx::attrib::IntNormalized),
                        _ => fail!("Unsupported color depth")
                    }
                };

                let img_info = tinfo.to_image_info();
                let texture = self.graphics.device.create_texture(tinfo)
                                         .ok().expect("Failed to create texture");
                self.graphics.device.update_texture(&texture, &img_info, &text.data().to_vec());
                self.textures.insert(*oid, texture);
            }
        }
    }

    fn create_geometry_batches<RD: RenderData>(&mut self, db: &RD, scene: ObjectKey) -> HashMap<u32, MyProgram> {
        let mut batches: HashMap<u32, MyProgram> = HashMap::new();

        for (_, draw) in join_set_to_map(db.scene_iter(scene), db.drawable_iter()) {
            if batches.contains_key(&draw.geometry) {
                continue;
            }

            let geo = db.geometry(draw.geometry).expect("failed to find geometry");
            let vb = self.meshes.find(&geo.vb).expect("Could not get vertex buffer");

            let batch: MyProgram = self.graphics.make_batch(
                &self.prog,
                &vb.mesh,
                gfx::IndexSlice32(gfx::TriangleList,
                                  vb.index,
                                  geo.offset as u32,
                                  geo.count as u32),
                &self.state
            ).unwrap();

            batches.insert(draw.geometry, batch);
        }

        return batches;
    }

    fn draw<RD: RenderData>(&mut self, db: &RD, scene: ObjectKey, camera: ObjectKey) {
        let cdata = gfx::ClearData {
            color: Some([0.3, 0.3, 0.3, 1.0]),
            depth: Some(1.0),
            stencil: None,
        };
        let start = time::precise_time_s();
        self.graphics.clear(cdata, &self.frame);

        let camera_trans = db.position(camera);
        let camera = snowmew::camera::Camera::new(camera_trans);

        let proj = camera.projection_matrix(16. / 9.);
        self.data.proj_mat =
            [[proj.x.x, proj.x.y, proj.x.z, proj.x.w],
             [proj.y.x, proj.y.y, proj.y.z, proj.y.w],
             [proj.z.x, proj.z.y, proj.z.z, proj.z.w],
             [proj.w.x, proj.w.y, proj.w.z, proj.w.w]];

        let view = camera.view_matrix();
        self.data.view_mat =
            [[view.x.x, view.x.y, view.x.z, view.x.w],
             [view.y.x, view.y.y, view.y.z, view.y.w],
             [view.z.x, view.z.y, view.z.z, view.z.w],
             [view.w.x, view.w.y, view.w.z, view.w.w]];

        let batches = self.create_geometry_batches(db, scene);

        for (id, (draw, _)) in join_set_to_map(db.scene_iter(scene),
                                               join_maps(db.drawable_iter(),
                                                         db.location_iter())) {

            let mat = db.material(draw.material).expect("Could not find material");
            let model = db.position(*id);

            self.data.model_mat =
                [[model.x.x, model.x.y, model.x.z, model.x.w],
                 [model.y.x, model.y.y, model.y.z, model.y.w],
                 [model.z.x, model.z.y, model.z.z, model.z.w],
                 [model.w.x, model.w.y, model.w.z, model.w.w]];

            self.data.ka_use_texture = match mat.map_ka() {
                Some(tid) => {
                    let &texture = self.textures.find(&tid).expect("Texture not loaded");
                    self.data.ka_texture = (texture, Some(self.sampler));
                    1
                }
                None => {
                    let [r, g, b] = mat.ka();
                    self.data.ka_color = [r, g, b, 1.];
                    0
                }
            };

            self.graphics.draw(
                batches.find(&draw.geometry).expect("Missing draw"),
                &self.data,
                &self.frame
            );
        }

        self.graphics.end_frame();
        self.window.swap_buffers();
        let end = time::precise_time_s();
        println!("{0:4.3}ms", (end - start) * 1000.);
    }
}

impl<RD: RenderData+Send> snowmew::Render<RD> for RenderManager {
    fn update(&mut self, db: RD, scene: ObjectKey, camera: ObjectKey) {
        self.load_meshes(&db);
        self.load_textures(&db);
        self.draw(&db, scene, camera);
    }
}

impl<RD: RenderData+Send> snowmew::RenderFactory<RD, RenderManager> for RenderFactory {
    fn init(self: Box<RenderFactory>,
            io: &snowmew::IOManager,
            window: Window,
            size: (i32, i32),
            cl: Option<Arc<hl::Device>>) -> RenderManager {

        window.make_context_current();

        let mut device = gfx::GlDevice::new(|s| io.get_proc_address(s));
        RenderManager::_new(device, window, size, cl)
    }
}

pub struct RenderFactory;

impl RenderFactory {
    pub fn new() -> RenderFactory { RenderFactory }
}<|endoftext|>


<commit_before><ATTRIBUTE>#[macro_use]</ATTRIBUTE>
extern crate <CRATE>log</CRATE>;

use std::collections::<STRUCT>HashMap</STRUCT>;
use std::rc::<STRUCT>Rc</STRUCT>;

mod <MODULE>stuff</MODULE>;

pub enum <ENUM>Flag</ENUM> {
    <ENUM_VARIANT>Good</ENUM_VARIANT>,
    <ENUM_VARIANT>Bad</ENUM_VARIANT>,
    <ENUM_VARIANT>Ugly</ENUM_VARIANT>
}

const <CONSTANT>QUALITY</CONSTANT>: <ENUM>Flag</ENUM> = <ENUM>Flag</ENUM>::<ENUM_VARIANT>Good</ENUM_VARIANT>;

struct Table<const <CONST_PARAMETER>N</CONST_PARAMETER>: usize>([[i32; <CONST_PARAMETER>N</CONST_PARAMETER>]; <CONST_PARAMETER>N</CONST_PARAMETER>])

pub trait <TRAIT>Write</TRAIT> {
    fn <METHOD>write</METHOD>(&mut <SELF_PARAMETER>self</SELF_PARAMETER>, <PARAMETER>buf</PARAMETER>: &[<PRIMITIVE_TYPE>u8</PRIMITIVE_TYPE>]) -> <ENUM>Result</ENUM><usize>;
}

struct <STRUCT>Object</STRUCT><<TYPE_PARAMETER>T</TYPE_PARAMETER>> {
    <FIELD>flag</FIELD>: <ENUM>Flag</ENUM>,
    <FIELD>fields</FIELD>: <STRUCT>HashMap</STRUCT><<TYPE_PARAMETER>T</TYPE_PARAMETER>, <PRIMITIVE_TYPE>u64</PRIMITIVE_TYPE>>
}

<KEYWORD>union</KEYWORD> <UNION>MyUnion</UNION> {
    <FIELD>f1</FIELD>: <PRIMITIVE_TYPE>u32</PRIMITIVE_TYPE>,
    <FIELD>f2</FIELD>: <PRIMITIVE_TYPE>f32</PRIMITIVE_TYPE>,
}

type <TYPE_ALIAS>RcObject</TYPE_ALIAS><<TYPE_PARAMETER>T</TYPE_PARAMETER>> = <STRUCT>Rc</STRUCT><<STRUCT>Object</STRUCT><<TYPE_PARAMETER>T</TYPE_PARAMETER>>>;

impl<<TYPE_PARAMETER>T</TYPE_PARAMETER>> Write for <STRUCT>Object</STRUCT><<TYPE_PARAMETER>T</TYPE_PARAMETER>> {
    fn <METHOD>write</METHOD>(&mut <SELF_PARAMETER>self</SELF_PARAMETER>, <PARAMETER>buf</PARAMETER>: &[<PRIMITIVE_TYPE>u8</PRIMITIVE_TYPE>]) -> <ENUM>Result</ENUM><usize> {
        let <VARIABLE>s</VARIABLE> = stuff::<FUNCTION_CALL>write_map</FUNCTION_CALL>(&self.<FIELD>fields</FIELD>, <PARAMETER>buf</PARAMETER>)<Q_OPERATOR>?</Q_OPERATOR>;
        <MACRO>info!</MACRO>("{} byte(s) written", <VARIABLE>s</VARIABLE>);
        <ENUM_VARIANT>Ok</ENUM_VARIANT>(<VARIABLE>s</VARIABLE>)
    }
}

impl<<TYPE_PARAMETER>T</TYPE_PARAMETER>> <TRAIT>Default</TRAIT> for <STRUCT>Object</STRUCT><<TYPE_PARAMETER>T</TYPE_PARAMETER>> {
    fn <ASSOC_FUNCTION>default</ASSOC_FUNCTION>() -> Self {
        <STRUCT>Object</STRUCT> { <FIELD>flag</FIELD>: <ENUM>Flag</ENUM>::<ENUM_VARIANT>Good</ENUM_VARIANT>, <FIELD>fields</FIELD>: <STRUCT>HashMap</STRUCT>::<ASSOC_FUNCTION_CALL>new</ASSOC_FUNCTION_CALL>() }
    }
}

/* Block comment */
fn <FUNCTION>main</FUNCTION>() {
    // A simple integer calculator:
    // `+` or `-` means add or subtract by 1
    // `*` or `/` means multiply or divide by 2
    <MODULE>stuff</MODULE>::<STRUCT>AppVersion</STRUCT>::<ASSOC_FUNCTION_CALL>print</ASSOC_FUNCTION_CALL>();

    let <VARIABLE>input</VARIABLE> = <ENUM>Option</ENUM>::<ENUM_VARIANT>None</ENUM_VARIANT>;
    let <VARIABLE>program</VARIABLE> = <VARIABLE>input</VARIABLE>.<METHOD_CALL>unwrap_or_else</METHOD_CALL>(|| "+ + * - /");
    let mut <MUT_BINDING><VARIABLE>accumulator</VARIABLE></MUT_BINDING> = 0;

    for <VARIABLE>token</VARIABLE> in <VARIABLE>program</VARIABLE>.<METHOD_CALL>chars</METHOD_CALL>() {
        match <VARIABLE>token</VARIABLE> {
            '+' => <MUT_BINDING><VARIABLE>accumulator</VARIABLE></MUT_BINDING> += 1,
            '-' => <MUT_BINDING><VARIABLE>accumulator</VARIABLE></MUT_BINDING> -= 1,
            '*' => <MUT_BINDING><VARIABLE>accumulator</VARIABLE></MUT_BINDING> *= 2,
            '/' => <MUT_BINDING><VARIABLE>accumulator</VARIABLE></MUT_BINDING> /= 2,
            _ => { /* ignore everything else */ }
        }
    }

    <MACRO>info!</MACRO>("The program \"{}\" calculates the value {}",
            <VARIABLE>program</VARIABLE>, <MUT_BINDING><VARIABLE>accumulator</VARIABLE></MUT_BINDING>);
}

<DOC_COMMENT>/// Some documentation <DOC_CODE>`with a code`</DOC_CODE>, <DOC_EMPHASIS>*an italic text*</DOC_EMPHASIS>
/// and <DOC_STRONG>**a bold text**</DOC_STRONG>
/// <DOC_HEADING># Heading</DOC_HEADING>
/// <DOC_LINK>[Rust](https://www.rust-lang.org/)</DOC_LINK></DOC_COMMENT>
<ATTRIBUTE>#[cfg(target_os=</ATTRIBUTE>"linux"<ATTRIBUTE>)]</ATTRIBUTE>
<KEYWORD_UNSAFE>unsafe</KEYWORD_UNSAFE> fn <FUNCTION>a_function</FUNCTION><<TYPE_PARAMETER>T</TYPE_PARAMETER>: <LIFETIME>'lifetime</LIFETIME>>(<MUT_PARAMETER>count</MUT_PARAMETER>: &mut i64) -> ! {
    <MUT_PARAMETER>count</MUT_PARAMETER> += 1;
    'label: loop {
        let <VARIABLE>str_with_escapes</VARIABLE> = "Hello\x20W\u{f3}rld!\u{abcdef}";
        <MACRO>println!</MACRO>("<FORMAT_PARAMETER>{}</FORMAT_PARAMETER> <FORMAT_PARAMETER>{<FORMAT_SPECIFIER>foo</FORMAT_SPECIFIER>:<<FORMAT_SPECIFIER>4</FORMAT_SPECIFIER>}</FORMAT_PARAMETER>", str_with_escapes, foo = 42);
    }
}

fn <FUNCTION>test</FUNCTION>() {
    <KEYWORD_UNSAFE>unsafe</KEYWORD_UNSAFE> {
        <UNSAFE_CODE>a_function</UNSAFE_CODE>(1);
    }
}
<commit_msg>#8734: add highlighting example of cfg disabled code in color settings<commit_after><ATTRIBUTE>#[macro_use]</ATTRIBUTE>
extern crate <CRATE>log</CRATE>;

use std::collections::<STRUCT>HashMap</STRUCT>;
use std::rc::<STRUCT>Rc</STRUCT>;

mod <MODULE>stuff</MODULE>;

pub enum <ENUM>Flag</ENUM> {
    <ENUM_VARIANT>Good</ENUM_VARIANT>,
    <ENUM_VARIANT>Bad</ENUM_VARIANT>,
    <ENUM_VARIANT>Ugly</ENUM_VARIANT>
}

const <CONSTANT>QUALITY</CONSTANT>: <ENUM>Flag</ENUM> = <ENUM>Flag</ENUM>::<ENUM_VARIANT>Good</ENUM_VARIANT>;

struct Table<const <CONST_PARAMETER>N</CONST_PARAMETER>: usize>([[i32; <CONST_PARAMETER>N</CONST_PARAMETER>]; <CONST_PARAMETER>N</CONST_PARAMETER>])

pub trait <TRAIT>Write</TRAIT> {
    fn <METHOD>write</METHOD>(&mut <SELF_PARAMETER>self</SELF_PARAMETER>, <PARAMETER>buf</PARAMETER>: &[<PRIMITIVE_TYPE>u8</PRIMITIVE_TYPE>]) -> <ENUM>Result</ENUM><usize>;
}

struct <STRUCT>Object</STRUCT><<TYPE_PARAMETER>T</TYPE_PARAMETER>> {
    <FIELD>flag</FIELD>: <ENUM>Flag</ENUM>,
    <FIELD>fields</FIELD>: <STRUCT>HashMap</STRUCT><<TYPE_PARAMETER>T</TYPE_PARAMETER>, <PRIMITIVE_TYPE>u64</PRIMITIVE_TYPE>>
}

<KEYWORD>union</KEYWORD> <UNION>MyUnion</UNION> {
    <FIELD>f1</FIELD>: <PRIMITIVE_TYPE>u32</PRIMITIVE_TYPE>,
    <FIELD>f2</FIELD>: <PRIMITIVE_TYPE>f32</PRIMITIVE_TYPE>,
}

type <TYPE_ALIAS>RcObject</TYPE_ALIAS><<TYPE_PARAMETER>T</TYPE_PARAMETER>> = <STRUCT>Rc</STRUCT><<STRUCT>Object</STRUCT><<TYPE_PARAMETER>T</TYPE_PARAMETER>>>;

impl<<TYPE_PARAMETER>T</TYPE_PARAMETER>> Write for <STRUCT>Object</STRUCT><<TYPE_PARAMETER>T</TYPE_PARAMETER>> {
    fn <METHOD>write</METHOD>(&mut <SELF_PARAMETER>self</SELF_PARAMETER>, <PARAMETER>buf</PARAMETER>: &[<PRIMITIVE_TYPE>u8</PRIMITIVE_TYPE>]) -> <ENUM>Result</ENUM><usize> {
        let <VARIABLE>s</VARIABLE> = stuff::<FUNCTION_CALL>write_map</FUNCTION_CALL>(&self.<FIELD>fields</FIELD>, <PARAMETER>buf</PARAMETER>)<Q_OPERATOR>?</Q_OPERATOR>;
        <MACRO>info!</MACRO>("{} byte(s) written", <VARIABLE>s</VARIABLE>);
        <ENUM_VARIANT>Ok</ENUM_VARIANT>(<VARIABLE>s</VARIABLE>)
    }
}

impl<<TYPE_PARAMETER>T</TYPE_PARAMETER>> <TRAIT>Default</TRAIT> for <STRUCT>Object</STRUCT><<TYPE_PARAMETER>T</TYPE_PARAMETER>> {
    fn <ASSOC_FUNCTION>default</ASSOC_FUNCTION>() -> Self {
        <STRUCT>Object</STRUCT> { <FIELD>flag</FIELD>: <ENUM>Flag</ENUM>::<ENUM_VARIANT>Good</ENUM_VARIANT>, <FIELD>fields</FIELD>: <STRUCT>HashMap</STRUCT>::<ASSOC_FUNCTION_CALL>new</ASSOC_FUNCTION_CALL>() }
    }
}

/* Block comment */
fn <FUNCTION>main</FUNCTION>() {
    // A simple integer calculator:
    // `+` or `-` means add or subtract by 1
    // `*` or `/` means multiply or divide by 2
    <MODULE>stuff</MODULE>::<STRUCT>AppVersion</STRUCT>::<ASSOC_FUNCTION_CALL>print</ASSOC_FUNCTION_CALL>();

    let <VARIABLE>input</VARIABLE> = <ENUM>Option</ENUM>::<ENUM_VARIANT>None</ENUM_VARIANT>;
    let <VARIABLE>program</VARIABLE> = <VARIABLE>input</VARIABLE>.<METHOD_CALL>unwrap_or_else</METHOD_CALL>(|| "+ + * - /");
    let mut <MUT_BINDING><VARIABLE>accumulator</VARIABLE></MUT_BINDING> = 0;

    for <VARIABLE>token</VARIABLE> in <VARIABLE>program</VARIABLE>.<METHOD_CALL>chars</METHOD_CALL>() {
        match <VARIABLE>token</VARIABLE> {
            '+' => <MUT_BINDING><VARIABLE>accumulator</VARIABLE></MUT_BINDING> += 1,
            '-' => <MUT_BINDING><VARIABLE>accumulator</VARIABLE></MUT_BINDING> -= 1,
            '*' => <MUT_BINDING><VARIABLE>accumulator</VARIABLE></MUT_BINDING> *= 2,
            '/' => <MUT_BINDING><VARIABLE>accumulator</VARIABLE></MUT_BINDING> /= 2,
            _ => { /* ignore everything else */ }
        }
    }

    <MACRO>info!</MACRO>("The program \"{}\" calculates the value {}",
            <VARIABLE>program</VARIABLE>, <MUT_BINDING><VARIABLE>accumulator</VARIABLE></MUT_BINDING>);
}

<DOC_COMMENT>/// Some documentation <DOC_CODE>`with a code`</DOC_CODE>, <DOC_EMPHASIS>*an italic text*</DOC_EMPHASIS>
/// and <DOC_STRONG>**a bold text**</DOC_STRONG>
/// <DOC_HEADING># Heading</DOC_HEADING>
/// <DOC_LINK>[Rust](https://www.rust-lang.org/)</DOC_LINK></DOC_COMMENT>
<ATTRIBUTE>#[cfg(target_os=</ATTRIBUTE>"linux"<ATTRIBUTE>)]</ATTRIBUTE>
<KEYWORD_UNSAFE>unsafe</KEYWORD_UNSAFE> fn <FUNCTION>a_function</FUNCTION><<TYPE_PARAMETER>T</TYPE_PARAMETER>: <LIFETIME>'lifetime</LIFETIME>>(<MUT_PARAMETER>count</MUT_PARAMETER>: &mut i64) -> ! {
    <MUT_PARAMETER>count</MUT_PARAMETER> += 1;
    'label: loop {
        let <VARIABLE>str_with_escapes</VARIABLE> = "Hello\x20W\u{f3}rld!\u{abcdef}";
        <MACRO>println!</MACRO>("<FORMAT_PARAMETER>{}</FORMAT_PARAMETER> <FORMAT_PARAMETER>{<FORMAT_SPECIFIER>foo</FORMAT_SPECIFIER>:<<FORMAT_SPECIFIER>4</FORMAT_SPECIFIER>}</FORMAT_PARAMETER>", str_with_escapes, foo = 42);
    }
}

fn <FUNCTION>test</FUNCTION>() {
    <KEYWORD_UNSAFE>unsafe</KEYWORD_UNSAFE> {
        <UNSAFE_CODE>a_function</UNSAFE_CODE>(1);
    }
}

<CFG_DISABLED_CODE>#[cfg(feature = "disabled_feature")]
fn cfg_disabled_function() {}</CFG_DISABLED_CODE>
<|endoftext|>


<commit_before>#[macro_export]
macro_rules! getter {
    ( $name:ident, $name_type:ident ) => {
        pub fn $name(&self) -> $name_type {
            self.$name
        }
    }
}

#[macro_export]
macro_rules! field_getter {
    ( $($name:ident, $name_type:ident),+ ) => {
        $(
            getter!($name, $name_type);
            )+
    }
}

#[macro_export]
macro_rules! setter {
    ( $name:ident, $set_name:ident, $name_type:ident ) => {
        pub fn $set_name(&mut self, to_set: $name_type) {
            self.$name = to_set;
        }
    }
}

#[macro_export]
macro_rules! ref_getter {
    ( $name:ident, $name_type:ident ) => {
        pub fn $name(&self) -> &$name_type {
            &self.$name
        }
    }
}
<commit_msg>Added field_setter.<commit_after>#[macro_export]
macro_rules! getter {
    ( $name:ident, $name_type:ident ) => {
        pub fn $name(&self) -> $name_type {
            self.$name
        }
    }
}

#[macro_export]
macro_rules! field_getter {
    ( $($name:ident, $name_type:ident),+ ) => {
        $(
            getter!($name, $name_type);
            )+
    }
}

#[macro_export]
macro_rules! setter {
    ( $name:ident, $set_name:ident, $name_type:ident ) => {
        pub fn $set_name(&mut self, to_set: $name_type) {
            self.$name = to_set;
        }
    }
}

#[macro_export]
macro_rules! field_setter {
    ( $($name:ident, $set_name:ident, $name_type:ident ),+ ) => {
        $(
            setter!($ident, $set_name, $name_type);
            )+
    }
}

#[macro_export]
macro_rules! ref_getter {
    ( $name:ident, $name_type:ident ) => {
        pub fn $name(&self) -> &$name_type {
            &self.$name
        }
    }
}
<|endoftext|>