<commit_before>use hyper;
use hyper::client::IntoUrl;
use hyper::header::{Headers, UserAgent};
use super::Response;
use super::Result;

const DEFAULT_USER_AGENT: &'static str = concat!("requests-rs/", env!("CARGO_PKG_VERSION"));

pub struct Request {
    headers: Headers,
    params: Vec<String>,
}

impl Default for Request {
    fn default() -> Self {
        let mut request = Request::new();
        request.user_agent(DEFAULT_USER_AGENT);
        request
    }
}

impl Request {
    pub fn new() -> Self {
        Request {
            headers: Headers::new(),
            params: Vec::<String>::new(),
        }
    }

    fn params<T, U>(&mut self, params: U) -> &mut Self
        where T: Into<String>,
              U: IntoIterator<Item = (T, T)>
    {
        for (key, value) in params {
            self.param(key, value);
        }
        self
    }

    fn param<T>(&mut self, key: T, value: T) -> &mut Self
        where T: Into<String>
    {
        self.params.push(format!("{}={}", key.into(), value.into()));
        self
    }

    pub fn user_agent(&mut self, ua: &str) {
        self.headers.set(UserAgent(ua.to_owned()))
    }

    pub fn get<U: IntoUrl>(&self, url: U) -> Result {
        hyper::Client::new()
            .get(url)
            .headers(self.headers.clone())
            .send()
            .map(Response::from)
    }

    pub fn post<U: IntoUrl>(&self, url: U) -> Result {
        hyper::Client::new()
            .post(url)
            .headers(self.headers.clone())
            .send()
            .map(Response::from)
    }

    pub fn put<U: IntoUrl>(&self, url: U) -> Result {
        hyper::Client::new()
            .put(url)
            .headers(self.headers.clone())
            .send()
            .map(Response::from)
    }

    pub fn head<U: IntoUrl>(&self, url: U) -> Result {
        hyper::Client::new()
            .head(url)
            .headers(self.headers.clone())
            .send()
            .map(Response::from)
    }

    pub fn delete<U: IntoUrl>(&self, url: U) -> Result {
        hyper::Client::new()
            .delete(url)
            .headers(self.headers.clone())
            .send()
            .map(Response::from)
    }
}
<commit_msg>params is not ready yet<commit_after>use hyper;
use hyper::client::IntoUrl;
use hyper::header::{Headers, UserAgent};
use super::Response;
use super::Result;

const DEFAULT_USER_AGENT: &'static str = concat!("requests-rs/", env!("CARGO_PKG_VERSION"));

pub struct Request {
    headers: Headers,
}

impl Default for Request {
    fn default() -> Self {
        let mut request = Request::new();
        request.user_agent(DEFAULT_USER_AGENT);
        request
    }
}

impl Request {
    pub fn new() -> Self {
        Request {
            headers: Headers::new(),
        }
    }

    pub fn user_agent(&mut self, ua: &str) {
        self.headers.set(UserAgent(ua.to_owned()))
    }

    pub fn get<U: IntoUrl>(&self, url: U) -> Result {
        hyper::Client::new()
            .get(url)
            .headers(self.headers.clone())
            .send()
            .map(Response::from)
    }

    pub fn post<U: IntoUrl>(&self, url: U) -> Result {
        hyper::Client::new()
            .post(url)
            .headers(self.headers.clone())
            .send()
            .map(Response::from)
    }

    pub fn put<U: IntoUrl>(&self, url: U) -> Result {
        hyper::Client::new()
            .put(url)
            .headers(self.headers.clone())
            .send()
            .map(Response::from)
    }

    pub fn head<U: IntoUrl>(&self, url: U) -> Result {
        hyper::Client::new()
            .head(url)
            .headers(self.headers.clone())
            .send()
            .map(Response::from)
    }

    pub fn delete<U: IntoUrl>(&self, url: U) -> Result {
        hyper::Client::new()
            .delete(url)
            .headers(self.headers.clone())
            .send()
            .map(Response::from)
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![feature(custom_derive)]
#![plugin(serde_macros)]

extern crate docopt;
extern crate env_logger;
extern crate raft;
extern crate serde;
extern crate rustc_serialize;

use std::net::SocketAddr;
use std::str::FromStr;
use std::io::{Error, Result};
use std::collections::HashMap;
use std::fmt::Debug;
use std::hash::Hash;

use serde::json::{self, Value};
use serde::{Serialize, Deserialize};
use docopt::Docopt;

use raft::{
    state_machine,
    persistent_log,
    ServerId,
    Server,
    Client,
};
use Message::*;

static USAGE: &'static str = "
A replicated mutable value. Operations on the register have serializable
consistency, but no durability (once all register servers are terminated the
value is lost).

Each register server holds a replica of the register, and coordinates with its
peers to update the register's value according to client commands. The register
is available for reading and writing only if a majority of register servers are
available.

Commands:

  get     Returns the current value of the key.

  put     Sets the current value of the key, and returns the previous
          value.

  cas     (compare and set) Conditionally sets the value of the key if the
          current value matches an expected value, returning true if the
          key was set.

  server  Starts a key server. Servers must be provided a unique ID and
          address (ip:port) at startup, along with the ID and address of all
          peer servers.register

Usage:
  hashmap get <key> (<node-address>)...
  hashmap put <key> <new-value> (<node-address>)...
  hashmap cas <key> <expected-value> <new-value> (<node-address>)...
  hashmap server <id> [<node-id> <node-address>]...
  hashmap (-h | --help)

Options:
  -h --help   Show a help message.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    cmd_server: bool,
    cmd_get: bool,
    cmd_put: bool,
    cmd_cas: bool,

    arg_id: Option<u64>,
    arg_node_id: Vec<u64>,
    arg_node_address: Vec<String>,
    arg_server_id: Option<u64>,

    arg_key: String,
    arg_new_value: String,
    arg_expected_value: String,
}

fn main() {
    let _ = env_logger::init();
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());
    if args.cmd_server {
        server(&args);
    } else if args.cmd_get {
        get(&args);
    } else if args.cmd_put {
        put(&args);
    } else if args.cmd_cas {
        cas(&args);
    }
}

fn parse_addr(addr: &str) -> SocketAddr {
    SocketAddr::from_str(addr)
               .ok()
               .expect(&format!("unable to parse socket address: {}", addr))
}

fn server(args: &Args) {
    let persistent_log = persistent_log::MemLog::new();
    let state_machine = HashmapStateMachine::new();

    let id = ServerId::from(args.arg_id.unwrap());
    let mut peers = args.arg_node_id
                    .iter()
                    .zip(args.arg_node_address.iter())
                    .map(|(&id, addr)| (ServerId::from(id), parse_addr(&addr)))
                    .collect::<HashMap<_,_>>();

    let addr = peers.remove(&id).unwrap();
    Server::run(id, addr, peers, persistent_log, state_machine).unwrap();
}

fn get(args: &Args) {
    let cluster = args.arg_node_address.iter()
        .map(|v| parse_addr(&v))
        .collect();
    let mut client = Client::new(cluster);
    let payload = json::to_string(&Message::Get(args.arg_key.clone())).unwrap();
    let response = client.query(payload.as_bytes()).unwrap();
    println!("{}", String::from_utf8(response).unwrap())
}

fn put(args: &Args) {
    let cluster = args.arg_node_address.iter()
        .map(|v| parse_addr(&v))
        .collect();
    let mut client = Client::new(cluster);
    let new_value = json::to_value(&args.arg_new_value);
    let payload = json::to_string(&Message::Put(args.arg_key.clone(), new_value)).unwrap();
    let response = client.propose(payload.as_bytes()).unwrap();
    println!("{}", String::from_utf8(response).unwrap())
}

fn cas(_args: &Args) {
    panic!("unimplemented: waiting on changes to the Raft Client and StateMachine APIs");
}

/// A state machine that holds a hashmap.
#[derive(Debug)]
pub struct HashmapStateMachine {
    map: HashMap<String, Value>,
}

#[derive(Serialize, Deserialize)]
pub enum Message {
    Get(String),
    Put(String, Value),
    Cas(String, Value, Value),
}

impl HashmapStateMachine {
    pub fn new() -> HashmapStateMachine {
        HashmapStateMachine {
            map: HashMap::new(),
        }
    }
}

impl state_machine::StateMachine for HashmapStateMachine {

    type Error = Error;

    fn apply(&mut self, new_value: &[u8]) -> Result<Vec<u8>> {
        let string = String::from_utf8_lossy(new_value);
        let message = json::from_str(&string).unwrap();

        let response = match message {
            Get(key) => {
                let old_value = &self.map.get(&key).map(|v| v.clone());
                json::to_string(old_value)
            },
            Put(key, value) => {
                let old_value = &self.map.insert(key, value);
                json::to_string(old_value)
            },
            Cas(key, old_check, new) => {
                if *self.map.get(&key).unwrap() == old_check {
                    let _ = self.map.insert(key, new);
                    json::to_string(&true)
                } else {
                    json::to_string(&false)
                }
            },
        };

        Ok(response.unwrap().into_bytes())
    }

    fn query(&self, query: &[u8]) -> Result<Vec<u8>> {
        let string = String::from_utf8_lossy(query);
        let message = json::from_str(&string).unwrap();

        let response = match message {
            Get(key) => {
                let old_value = &self.map.get(&key).map(|v| v.clone());
                json::to_string(old_value)
            },
            _ => panic!("Can't do mutating requests in query"),
        };

        Ok(response.unwrap().into_bytes())
    }

    fn snapshot(&self) -> Result<Vec<u8>> {
        Ok(json::to_string(&self.map)
            .unwrap()
            .into_bytes())
    }

    fn restore_snapshot(&mut self, snapshot_value: Vec<u8>) -> Result<()> {
        self.map = json::from_str(&String::from_utf8_lossy(&snapshot_value)).unwrap();
        Ok(())
    }
}
<commit_msg>Additional comments on hashmap<commit_after>//! This example demonstrates using Raft to implement a replicated hashmap over `n` servers and
//! interact with them over `m` clients.
//!
//! Comments below will aim to be tailored towards Raft and it's usage. If you have any questions,
//! Please, just open an issue.
//!
//! TODO: For the sake of simplicity of this example, we don't implement a `Log` and just use a
//! simple testing one. We should improve this in the future.

// In order to use Serde we need to enable these nightly features.
#![feature(plugin)]
#![feature(custom_derive)]
#![plugin(serde_macros)]

extern crate raft; // <--- Kind of a big deal
extern crate env_logger;
extern crate docopt;
extern crate serde;
extern crate rustc_serialize;

use std::net::SocketAddr;
use std::str::FromStr;
use std::io::{Error, Result};
use std::collections::HashMap;
use std::fmt::Debug;
use std::hash::Hash;

use serde::json::{self, Value};
use serde::{Serialize, Deserialize};
use docopt::Docopt;

// Raft's major components. See comments in code on usage and things.
use raft::{
    Server,
    Client,
    state_machine,
    persistent_log,
    ServerId,
};
// A payload datatype. We're just using a simple enum. You can use whatever.
use Message::*;

// Using docopt we define the overall usage of the application.
static USAGE: &'static str = "
A replicated mutable value. Operations on the register have serializable
consistency, but no durability (once all register servers are terminated the
value is lost).

Each register server holds a replica of the register, and coordinates with its
peers to update the register's value according to client commands. The register
is available for reading and writing only if a majority of register servers are
available.

Commands:

  get     Returns the current value of the key.

  put     Sets the current value of the key, and returns the previous
          value.

  cas     (compare and set) Conditionally sets the value of the key if the
          current value matches an expected value, returning true if the
          key was set.

  server  Starts a key server. Servers must be provided a unique ID and
          address (ip:port) at startup, along with the ID and address of all
          peer servers.register

Usage:
  hashmap get <key> (<node-address>)...
  hashmap put <key> <new-value> (<node-address>)...
  hashmap cas <key> <expected-value> <new-value> (<node-address>)...
  hashmap server <id> [<node-id> <node-address>]...
  hashmap (-h | --help)

Options:
  -h --help   Show a help message.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    cmd_server: bool,
    cmd_get: bool,
    cmd_put: bool,
    cmd_cas: bool,

    // When creating a server you will necessarily need some sort of unique ID for it as well
    // as a list of peers. In this example we just accept them straight from args. You might
    // find it best to use a `toml` or `yaml` or `json` file.
    arg_id: Option<u64>,
    arg_node_id: Vec<u64>,
    arg_node_address: Vec<String>,

    // In this example keys and values are associated. In your application you can model your data
    // however you please.
    arg_key: String,
    arg_new_value: String,
    arg_expected_value: String,
}

/// This is the defined message type for this example. For the sake of simplicity we don't go very
/// far with this. In a "real" application you may want to more distinctly distinguish between
/// data meant for `.query()` and data meant for `.propose()`.
#[derive(Serialize, Deserialize)]
pub enum Message {
    Get(String),
    Put(String, Value),
    Cas(String, Value, Value),
}

/// Just a plain old boring "parse args and dispatch" call.
fn main() {
    let _ = env_logger::init();
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());
    if args.cmd_server {
        server(&args);
    } else if args.cmd_get {
        get(&args);
    } else if args.cmd_put {
        put(&args);
    } else if args.cmd_cas {
        cas(&args);
    }
}

/// A simple convenience method since this is an example and it should exit if given invalid params.
fn parse_addr(addr: &str) -> SocketAddr {
    SocketAddr::from_str(addr)
               .ok()
               .expect(&format!("unable to parse socket address: {}", addr))
}

/// Creates a Raft server using the specified ID from the list of nodes.
fn server(args: &Args) {
    // Creating a raft server requires several things:

    // A persistent log implementation, which manages the persistent, replicated log...
    let persistent_log = persistent_log::MemLog::new();

    // A state machine which replicated state. This state should be the same on all nodes.
    let state_machine = HashmapStateMachine::new();

    // As well as a unique server id.
    let id = ServerId::from(args.arg_id.unwrap());

    // ...  And a list of peers.
    let mut peers = args.arg_node_id
                    .iter()
                    .zip(args.arg_node_address.iter())
                    .map(|(&id, addr)| (ServerId::from(id), parse_addr(&addr)))
                    .collect::<HashMap<_,_>>();

    // The Raft Server will panic if it's ID is inside of it's peer set. Don't do that.
    // Instead, take it out and use it!
    let addr = peers.remove(&id).unwrap();

    // Using all of the above components.
    // You probably shouldn't `.unwrap()` in production code unless you're totally sure it works
    // 100% of the time, all the time.
    Server::run(id, addr, peers, persistent_log, state_machine).unwrap();
}

/// Gets a value for a given key from the provided Raft cluster.
fn get(args: &Args) {
    // Clients necessarily need to now the valid set of nodes which they can talk to.
    // This is both so they can try to talk to all the nodes if some are failing, and so that it
    // can verify that it's not being lead astray somehow in redirections on leadership changes.
    let cluster = args.arg_node_address.iter()
        .map(|v| parse_addr(&v))
        .collect();

    // Clients and be stored and reused, or used once and discarded.
    // There is very small overhead in connecting a new client to a cluster as it must discover and
    // identify itself to the leader.
    let mut client = Client::new(cluster);

    // In this example `serde::json` is used to serialize and deserialize messages.
    // Since Raft accepts `[u8]` the way you structure your data, the serialization method you
    // choose, and how you interpret that data is entirely up to you.
    let payload = json::to_string(&Message::Get(args.arg_key.clone())).unwrap();

    // A query executes **immutably** on the leader of the cluster and does not pass through the
    // persistent log. This is intended for querying the current state of the state machine.
    let response = client.query(payload.as_bytes()).unwrap();

    // A response will block until it's query is complete. This is intended and expected behavior
    // based on the papers specifications.
    println!("{}", String::from_utf8(response).unwrap())
}

/// Sets a value for a given key in the provided Raft cluster.
fn put(args: &Args) {
    // Same as above.
    let cluster = args.arg_node_address.iter()
        .map(|v| parse_addr(&v))
        .collect();

    let mut client = Client::new(cluster);

    let new_value = json::to_value(&args.arg_new_value);
    let payload = json::to_string(&Message::Put(args.arg_key.clone(), new_value)).unwrap();

    // A propose will go through the persistent log and mutably modify the state machine in some
    // way. This is **much** slower than `.query()`.
    let response = client.propose(payload.as_bytes()).unwrap();

    // A response will block until it's proposal is complete. This is intended and expected behavior
    // based on the papers specifications.
    println!("{}", String::from_utf8(response).unwrap())
}

fn cas(_args: &Args) {
    panic!("unimplemented: waiting on changes to the Raft Client and StateMachine APIs");
}

/// A state machine that holds a hashmap.
#[derive(Debug)]
pub struct HashmapStateMachine {
    map: HashMap<String, Value>,
}

/// Implement anything you want... A `new()` is generally a great idea.
impl HashmapStateMachine {
    pub fn new() -> HashmapStateMachine {
        HashmapStateMachine {
            map: HashMap::new(),
        }
    }
}

/// Implementing `state_machine::StateMachine` allows your application specific state machine to be
/// used in Raft. Feel encouraged to base yours of one of ours in these examples.
impl state_machine::StateMachine for HashmapStateMachine {

    type Error = Error;

    /// `apply()` is called on when a client's `.propose()` is commited and reaches the state
    /// machine. At this point it is durable and is going to be applied on at least half the nodes
    /// within the next couple round trips.
    fn apply(&mut self, new_value: &[u8]) -> Result<Vec<u8>> {
        // Deserialize
        let string = String::from_utf8_lossy(new_value);
        let message = json::from_str(&string).unwrap();

        // Handle
        let response = match message {
            Get(key) => {
                let old_value = &self.map.get(&key).map(|v| v.clone());
                json::to_string(old_value)
            },
            Put(key, value) => {
                let old_value = &self.map.insert(key, value);
                json::to_string(old_value)
            },
            Cas(key, old_check, new) => {
                if *self.map.get(&key).unwrap() == old_check {
                    let _ = self.map.insert(key, new);
                    json::to_string(&true)
                } else {
                    json::to_string(&false)
                }
            },
        };

        // Respond.
        Ok(response.unwrap().into_bytes())
    }

    /// `query()` is called on when a client's `.query()` is recieved. It does not go through the
    /// persistent log, it does not mutate the state of the state machine, and it is intended to be
    /// fast.
    fn query(&self, query: &[u8]) -> Result<Vec<u8>> {
        // Deserialize
        let string = String::from_utf8_lossy(query);
        let message = json::from_str(&string).unwrap();

        // Handle
        let response = match message {
            Get(key) => {
                let old_value = &self.map.get(&key).map(|v| v.clone());
                json::to_string(old_value)
            },
            _ => panic!("Can't do mutating requests in query"),
        };

        // Respond.
        Ok(response.unwrap().into_bytes())
    }

    fn snapshot(&self) -> Result<Vec<u8>> {
        Ok(json::to_string(&self.map)
            .unwrap()
            .into_bytes())
    }

    fn restore_snapshot(&mut self, snapshot_value: Vec<u8>) -> Result<()> {
        self.map = json::from_str(&String::from_utf8_lossy(&snapshot_value)).unwrap();
        Ok(())
    }
}
<|endoftext|>


<commit_before>//! Runs decompiler stages on main function of /bin/ls

#[macro_use] extern crate radeco_lib;
extern crate r2pipe;
extern crate r2api;
extern crate serde_json;
extern crate petgraph;

use std::fs::File;
use std::io::prelude::*;

use petgraph::graph::NodeIndex;

use r2api::structs::{LFunctionInfo, LRegInfo};

use radeco_lib::frontend::bindings::{RadecoBindings, RBind, RBindings, Binding};
use radeco_lib::frontend::containers::{RadecoFunction, RFunction};
use radeco_lib::frontend::containers::{RadecoModule, RModule};
use radeco_lib::frontend::source::FileSource;
use radeco_lib::middle::ssa::ssastorage::SSAStorage;
use radeco_lib::middle::ir_writer::IRWriter;
use radeco_lib::middle::{dce, dot};
use radeco_lib::analysis::sccp;
use radeco_lib::analysis::cse::cse::CSE;
use radeco_lib::analysis::valueset::fixcall::CallFixer;

pub type DefaultFnTy = RadecoFunction<RadecoBindings<Binding<NodeIndex>>>;

fn run_dce(rmod: &mut RadecoModule<DefaultFnTy>)
{
    let functions = rmod.functions.clone();
    let mut matched_func_vec: Vec<u64> =
        functions.iter().map(|(fn_addr, rfn)| fn_addr.clone()).collect();
    for fn_addr in &matched_func_vec {
        let rfn = rmod.functions.get_mut(fn_addr)
                        .expect("RadecoFunction Not Found!");
        let ssa = rfn.ssa_mut();
        dce::collect(ssa);
    }
}

fn run_sccp(rmod: &mut RadecoModule<DefaultFnTy>)
{
    let functions = rmod.functions.clone();
    let mut matched_func_vec: Vec<u64> =
        functions.iter().map(|(fn_addr, rfn)| fn_addr.clone()).collect();
    for fn_addr in &matched_func_vec {
        let mut writer: IRWriter = Default::default();
        let rfn = rmod.functions.get_mut(fn_addr)
                        .expect("RadecoFunction Not Found!");
        let mut ssa = rfn.ssa_mut().clone();
        let mut analyzer = sccp::Analyzer::new(&mut ssa);
        analyzer.analyze();
        rfn.ssa = analyzer.emit_ssa();
    }
}

fn run_cse(rmod: &mut RadecoModule<DefaultFnTy>)
{
    let functions = rmod.functions.clone();
    let mut matched_func_vec: Vec<u64> =
        functions.iter().map(|(fn_addr, rfn)| fn_addr.clone()).collect();
    for fn_addr in &matched_func_vec {
        let rfn = rmod.functions.get_mut(fn_addr)
                        .expect("RadecoFunction Not Found!");
        let ssa = rfn.ssa_mut();
        let mut cse = CSE::new(ssa);
        cse.run();
    }
}

fn run_write(rmod: &RadecoModule<DefaultFnTy>)
{
    let functions = rmod.functions.clone();
    let mut matched_func_vec: Vec<u64> =
        functions.iter().map(|(fn_addr, rfn)| fn_addr.clone()).collect();
    for fn_addr in &matched_func_vec {
        let mut writer: IRWriter = Default::default();
        let rfn = rmod.functions.get(fn_addr)
                        .expect("RadecoFunction Not Found!");
        let ssa = rfn.ssa_ref();
        println!("{}", writer.emit_il(Some("main".to_owned()), ssa));
    }
}

#[test]
fn bin_file_construction() {
    let mut fsource = FileSource::open(Some("./test_files/bin_file/bin_file"));
    let mut rmod = RadecoModule::from(&mut fsource);

    //run_write(&rmod);
}

#[test]
fn bin_file_dce() {
    let mut fsource = FileSource::open(Some("./test_files/bin_file/bin_file"));
    let mut rmod = RadecoModule::from(&mut fsource);

    run_dce(&mut rmod);
    //run_write(&rmod);
}

#[test]
fn bin_file_dce_sccp() {
    let mut fsource = FileSource::open(Some("./test_files/bin_file/bin_file"));
    let mut rmod = RadecoModule::from(&mut fsource);

    run_dce(&mut rmod);
    run_sccp(&mut rmod);
    //run_write(&rmod);
}

#[test]
fn bin_file_dce_cse() {
    let mut fsource = FileSource::open(Some("./test_files/bin_file/bin_file"));
    let mut rmod = RadecoModule::from(&mut fsource);

    run_dce(&mut rmod);
    run_cse(&mut rmod);
    //run_write(&rmod);
}

#[test]
fn bin_file_dce_cse_sccp() {
    let mut fsource = FileSource::open(Some("./test_files/bin_file/bin_file"));
    let mut rmod = RadecoModule::from(&mut fsource);

    run_dce(&mut rmod);
    run_cse(&mut rmod);
    run_sccp(&mut rmod);
    //run_write(&rmod);
}

#[test]
fn bin_file_dce_fix() {
    let mut fsource = FileSource::open(Some("./test_files/bin_file/bin_file"));
    let mut rmod = RadecoModule::from(&mut fsource);

    run_dce(&mut rmod);
    {
        let mut callfixer = CallFixer::new(&mut rmod);
        callfixer.rounded_analysis();
    }
    //run_write(&rmod);
}

#[test]
fn bin_file_dce_fix_sccp() {
    let mut fsource = FileSource::open(Some("./test_files/bin_file/bin_file"));
    let mut rmod = RadecoModule::from(&mut fsource);

    run_dce(&mut rmod);
    {
        let mut callfixer = CallFixer::new(&mut rmod);
        callfixer.rounded_analysis();
    }
    run_sccp(&mut rmod);
    //run_write(&rmod);
}

#[test]
fn bin_file_dce_fix_cse() {
    let mut fsource = FileSource::open(Some("./test_files/bin_file/bin_file"));
    let mut rmod = RadecoModule::from(&mut fsource);

    run_dce(&mut rmod);
    {
        let mut callfixer = CallFixer::new(&mut rmod);
        callfixer.rounded_analysis();
    }
    run_cse(&mut rmod);
    //run_write(&rmod);
}

#[test]
fn bin_file_dce_fix_cse_sccp() {
    let mut fsource = FileSource::open(Some("./test_files/bin_file/bin_file"));
    let mut rmod = RadecoModule::from(&mut fsource);

    run_dce(&mut rmod);
    {
        let mut callfixer = CallFixer::new(&mut rmod);
        callfixer.rounded_analysis();
    }
    run_cse(&mut rmod);
    run_sccp(&mut rmod);
    //run_write(&rmod);
}
<commit_msg>Add writeIL in test<commit_after>//! Runs decompiler stages on main function of /bin/ls

#[macro_use] extern crate radeco_lib;
extern crate r2pipe;
extern crate r2api;
extern crate serde_json;
extern crate petgraph;

use std::fs::File;
use std::io::prelude::*;

use petgraph::graph::NodeIndex;

use r2api::structs::{LFunctionInfo, LRegInfo};

use radeco_lib::frontend::bindings::{RadecoBindings, RBind, RBindings, Binding};
use radeco_lib::frontend::containers::{RadecoFunction, RFunction};
use radeco_lib::frontend::containers::{RadecoModule, RModule};
use radeco_lib::frontend::source::FileSource;
use radeco_lib::middle::ssa::ssastorage::SSAStorage;
use radeco_lib::middle::ir_writer::IRWriter;
use radeco_lib::middle::{dce, dot};
use radeco_lib::analysis::sccp;
use radeco_lib::analysis::cse::cse::CSE;
use radeco_lib::analysis::valueset::fixcall::CallFixer;

pub type DefaultFnTy = RadecoFunction<RadecoBindings<Binding<NodeIndex>>>;

fn run_dce(rmod: &mut RadecoModule<DefaultFnTy>)
{
    let functions = rmod.functions.clone();
    let mut matched_func_vec: Vec<u64> =
        functions.iter().map(|(fn_addr, rfn)| fn_addr.clone()).collect();
    for fn_addr in &matched_func_vec {
        let rfn = rmod.functions.get_mut(fn_addr)
                        .expect("RadecoFunction Not Found!");
        let ssa = rfn.ssa_mut();
        dce::collect(ssa);
    }
}

fn run_sccp(rmod: &mut RadecoModule<DefaultFnTy>)
{
    let functions = rmod.functions.clone();
    let mut matched_func_vec: Vec<u64> =
        functions.iter().map(|(fn_addr, rfn)| fn_addr.clone()).collect();
    for fn_addr in &matched_func_vec {
        let mut writer: IRWriter = Default::default();
        let rfn = rmod.functions.get_mut(fn_addr)
                        .expect("RadecoFunction Not Found!");
        let mut ssa = rfn.ssa_mut().clone();
        let mut analyzer = sccp::Analyzer::new(&mut ssa);
        analyzer.analyze();
        rfn.ssa = analyzer.emit_ssa();
    }
}

fn run_cse(rmod: &mut RadecoModule<DefaultFnTy>)
{
    let functions = rmod.functions.clone();
    let mut matched_func_vec: Vec<u64> =
        functions.iter().map(|(fn_addr, rfn)| fn_addr.clone()).collect();
    for fn_addr in &matched_func_vec {
        let rfn = rmod.functions.get_mut(fn_addr)
                        .expect("RadecoFunction Not Found!");
        let ssa = rfn.ssa_mut();
        let mut cse = CSE::new(ssa);
        cse.run();
    }
}

fn run_write(rmod: &RadecoModule<DefaultFnTy>)
{
    let functions = rmod.functions.clone();
    let mut matched_func_vec: Vec<u64> =
        functions.iter().map(|(fn_addr, rfn)| fn_addr.clone()).collect();
    for fn_addr in &matched_func_vec {
        let mut writer: IRWriter = Default::default();
        let rfn = rmod.functions.get(fn_addr)
                        .expect("RadecoFunction Not Found!");
        let ssa = rfn.ssa_ref();
        println!("{}", writer.emit_il(Some("main".to_owned()), ssa));
    }
}

#[test]
fn bin_file_construction() {
    let mut fsource = FileSource::open(Some("./test_files/bin_file/bin_file"));
    let mut rmod = RadecoModule::from(&mut fsource);

    run_write(&rmod);
}

#[test]
fn bin_file_dce() {
    let mut fsource = FileSource::open(Some("./test_files/bin_file/bin_file"));
    let mut rmod = RadecoModule::from(&mut fsource);

    run_dce(&mut rmod);
    run_write(&rmod);
}

#[test]
fn bin_file_dce_sccp() {
    let mut fsource = FileSource::open(Some("./test_files/bin_file/bin_file"));
    let mut rmod = RadecoModule::from(&mut fsource);

    run_dce(&mut rmod);
    run_sccp(&mut rmod);
    run_write(&rmod);
}

#[test]
fn bin_file_dce_cse() {
    let mut fsource = FileSource::open(Some("./test_files/bin_file/bin_file"));
    let mut rmod = RadecoModule::from(&mut fsource);

    run_dce(&mut rmod);
    run_cse(&mut rmod);
    run_write(&rmod);
}

#[test]
fn bin_file_dce_cse_sccp() {
    let mut fsource = FileSource::open(Some("./test_files/bin_file/bin_file"));
    let mut rmod = RadecoModule::from(&mut fsource);

    run_dce(&mut rmod);
    run_cse(&mut rmod);
    run_sccp(&mut rmod);
    run_write(&rmod);
}

#[test]
fn bin_file_dce_fix() {
    let mut fsource = FileSource::open(Some("./test_files/bin_file/bin_file"));
    let mut rmod = RadecoModule::from(&mut fsource);

    run_dce(&mut rmod);
    {
        let mut callfixer = CallFixer::new(&mut rmod);
        callfixer.rounded_analysis();
    }
    run_write(&rmod);
}

#[test]
fn bin_file_dce_fix_sccp() {
    let mut fsource = FileSource::open(Some("./test_files/bin_file/bin_file"));
    let mut rmod = RadecoModule::from(&mut fsource);

    run_dce(&mut rmod);
    {
        let mut callfixer = CallFixer::new(&mut rmod);
        callfixer.rounded_analysis();
    }
    run_sccp(&mut rmod);
    run_write(&rmod);
}

#[test]
fn bin_file_dce_fix_cse() {
    let mut fsource = FileSource::open(Some("./test_files/bin_file/bin_file"));
    let mut rmod = RadecoModule::from(&mut fsource);

    run_dce(&mut rmod);
    {
        let mut callfixer = CallFixer::new(&mut rmod);
        callfixer.rounded_analysis();
    }
    run_cse(&mut rmod);
    run_write(&rmod);
}

#[test]
fn bin_file_dce_fix_cse_sccp() {
    let mut fsource = FileSource::open(Some("./test_files/bin_file/bin_file"));
    let mut rmod = RadecoModule::from(&mut fsource);

    run_dce(&mut rmod);
    {
        let mut callfixer = CallFixer::new(&mut rmod);
        callfixer.rounded_analysis();
    }
    run_cse(&mut rmod);
    run_sccp(&mut rmod);
    run_write(&rmod);
}
<|endoftext|>


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

use api::{BuiltDisplayList, DisplayListWithCache, ColorF, DynamicProperties, Epoch, FontRenderMode};
use api::{PipelineId, PropertyBinding, PropertyBindingId, PropertyValue, MixBlendMode, StackingContext};
use api::MemoryReport;
use api::units::*;
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use crate::composite::CompositorKind;
use crate::clip::{ClipStore, ClipDataStore};
use crate::picture::{SliceId, TileCacheParams};
use crate::spatial_tree::{SpatialTree, SpatialNodeIndex};
use crate::frame_builder::{ChasePrimitive, FrameBuilderConfig};
use crate::hit_test::{HitTester, HitTestingScene, HitTestingSceneStats};
use crate::internal_types::{FastHashMap, FastHashSet};
use crate::prim_store::{PrimitiveStore, PrimitiveStoreStats, PictureIndex};
use std::sync::Arc;

/// Stores a map of the animated property bindings for the current display list. These
/// can be used to animate the transform and/or opacity of a display list without
/// re-submitting the display list itself.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct SceneProperties {
    transform_properties: FastHashMap<PropertyBindingId, LayoutTransform>,
    float_properties: FastHashMap<PropertyBindingId, f32>,
    color_properties: FastHashMap<PropertyBindingId, ColorF>,
    current_properties: DynamicProperties,
    pending_properties: Option<DynamicProperties>,
}

impl SceneProperties {
    pub fn new() -> Self {
        SceneProperties {
            transform_properties: FastHashMap::default(),
            float_properties: FastHashMap::default(),
            color_properties: FastHashMap::default(),
            current_properties: DynamicProperties::default(),
            pending_properties: None,
        }
    }

    /// Set the current property list for this display list.
    pub fn set_properties(&mut self, properties: DynamicProperties) {
        self.pending_properties = Some(properties);
    }

    /// Add to the current property list for this display list.
    pub fn add_transforms(&mut self, transforms: Vec<PropertyValue<LayoutTransform>>) {
        let mut pending_properties = self.pending_properties
            .take()
            .unwrap_or_default();

        pending_properties.transforms.extend(transforms);

        self.pending_properties = Some(pending_properties);
    }

    /// Flush any pending updates to the scene properties. Returns
    /// true if the properties have changed since the last flush
    /// was called. This code allows properties to be changed by
    /// multiple set_properties and add_properties calls during a
    /// single transaction, and still correctly determine if any
    /// properties have changed. This can have significant power
    /// saving implications, allowing a frame build to be skipped
    /// if the properties haven't changed in many cases.
    pub fn flush_pending_updates(&mut self) -> bool {
        let mut properties_changed = false;

        if let Some(ref pending_properties) = self.pending_properties {
            if *pending_properties != self.current_properties {
                self.transform_properties.clear();
                self.float_properties.clear();

                for property in &pending_properties.transforms {
                    self.transform_properties
                        .insert(property.key.id, property.value);
                }

                for property in &pending_properties.floats {
                    self.float_properties
                        .insert(property.key.id, property.value);
                }

                for property in &pending_properties.colors {
                    self.color_properties
                        .insert(property.key.id, property.value);
                }

                self.current_properties = pending_properties.clone();
                properties_changed = true;
            }
        }

        properties_changed
    }

    /// Get the current value for a transform property.
    pub fn resolve_layout_transform(
        &self,
        property: &PropertyBinding<LayoutTransform>,
    ) -> LayoutTransform {
        match *property {
            PropertyBinding::Value(value) => value,
            PropertyBinding::Binding(ref key, v) => {
                self.transform_properties
                    .get(&key.id)
                    .cloned()
                    .unwrap_or(v)
            }
        }
    }

    /// Get the current value for a float property.
    pub fn resolve_float(
        &self,
        property: &PropertyBinding<f32>
    ) -> f32 {
        match *property {
            PropertyBinding::Value(value) => value,
            PropertyBinding::Binding(ref key, v) => {
                self.float_properties
                    .get(&key.id)
                    .cloned()
                    .unwrap_or(v)
            }
        }
    }

    pub fn float_properties(&self) -> &FastHashMap<PropertyBindingId, f32> {
        &self.float_properties
    }

    /// Get the current value for a color property.
    pub fn resolve_color(
        &self,
        property: &PropertyBinding<ColorF>
    ) -> ColorF {
        match *property {
            PropertyBinding::Value(value) => value,
            PropertyBinding::Binding(ref key, v) => {
                self.color_properties
                    .get(&key.id)
                    .cloned()
                    .unwrap_or(v)
            }
        }
    }

    pub fn color_properties(&self) -> &FastHashMap<PropertyBindingId, ColorF> {
        &self.color_properties
    }

}

/// A representation of the layout within the display port for a given document or iframe.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Clone)]
pub struct ScenePipeline {
    pub pipeline_id: PipelineId,
    pub viewport_size: LayoutSize,
    pub content_size: LayoutSize,
    pub background_color: Option<ColorF>,
    pub display_list: DisplayListWithCache,
}

/// A complete representation of the layout bundling visible pipelines together.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Clone)]
pub struct Scene {
    pub root_pipeline_id: Option<PipelineId>,
    pub pipelines: FastHashMap<PipelineId, ScenePipeline>,
    pub pipeline_epochs: FastHashMap<PipelineId, Epoch>,
}

impl Scene {
    pub fn new() -> Self {
        Scene {
            root_pipeline_id: None,
            pipelines: FastHashMap::default(),
            pipeline_epochs: FastHashMap::default(),
        }
    }

    pub fn set_root_pipeline_id(&mut self, pipeline_id: PipelineId) {
        self.root_pipeline_id = Some(pipeline_id);
    }

    pub fn set_display_list(
        &mut self,
        pipeline_id: PipelineId,
        epoch: Epoch,
        display_list: BuiltDisplayList,
        background_color: Option<ColorF>,
        viewport_size: LayoutSize,
        content_size: LayoutSize,
    ) {
        // Adds a cache to the given display list. If this pipeline already had
        // a display list before, that display list is updated and used instead.
        let display_list = match self.pipelines.remove(&pipeline_id) {
            Some(mut pipeline) => {
                pipeline.display_list.update(display_list);
                pipeline.display_list
            }
            None => DisplayListWithCache::new_from_list(display_list)
        };

        let new_pipeline = ScenePipeline {
            pipeline_id,
            viewport_size,
            content_size,
            background_color,
            display_list,
        };

        self.pipelines.insert(pipeline_id, new_pipeline);
        self.pipeline_epochs.insert(pipeline_id, epoch);
    }

    pub fn remove_pipeline(&mut self, pipeline_id: PipelineId) {
        if self.root_pipeline_id == Some(pipeline_id) {
            self.root_pipeline_id = None;
        }
        self.pipelines.remove(&pipeline_id);
        self.pipeline_epochs.remove(&pipeline_id);
    }

    pub fn update_epoch(&mut self, pipeline_id: PipelineId, epoch: Epoch) {
        self.pipeline_epochs.insert(pipeline_id, epoch);
    }

    pub fn has_root_pipeline(&self) -> bool {
        if let Some(ref root_id) = self.root_pipeline_id {
            return self.pipelines.contains_key(root_id);
        }

        false
    }

    pub fn report_memory(
        &self,
        ops: &mut MallocSizeOfOps,
        report: &mut MemoryReport
    ) {
        for (_, pipeline) in &self.pipelines {
            report.display_list += pipeline.display_list.size_of(ops)
        }
    }
}

pub trait StackingContextHelpers {
    fn mix_blend_mode_for_compositing(&self) -> Option<MixBlendMode>;
}

impl StackingContextHelpers for StackingContext {
    fn mix_blend_mode_for_compositing(&self) -> Option<MixBlendMode> {
        match self.mix_blend_mode {
            MixBlendMode::Normal => None,
            _ => Some(self.mix_blend_mode),
        }
    }
}

/// WebRender's internal representation of the scene.
pub struct BuiltScene {
    pub has_root_pipeline: bool,
    pub pipeline_epochs: FastHashMap<PipelineId, Epoch>,
    pub output_rect: DeviceIntRect,
    pub background_color: Option<ColorF>,
    pub root_pic_index: PictureIndex,
    pub prim_store: PrimitiveStore,
    pub clip_store: ClipStore,
    pub config: FrameBuilderConfig,
    pub spatial_tree: SpatialTree,
    pub hit_testing_scene: Arc<HitTestingScene>,
    pub content_slice_count: usize,
    pub picture_cache_spatial_nodes: FastHashSet<SpatialNodeIndex>,
    pub tile_caches: FastHashMap<SliceId, TileCacheParams>,
}

impl BuiltScene {
    pub fn empty() -> Self {
        BuiltScene {
            has_root_pipeline: false,
            pipeline_epochs: FastHashMap::default(),
            output_rect: DeviceIntRect::zero(),
            background_color: None,
            root_pic_index: PictureIndex(0),
            prim_store: PrimitiveStore::new(&PrimitiveStoreStats::empty()),
            clip_store: ClipStore::new(),
            spatial_tree: SpatialTree::new(),
            hit_testing_scene: Arc::new(HitTestingScene::new(&HitTestingSceneStats::empty())),
            content_slice_count: 0,
            picture_cache_spatial_nodes: FastHashSet::default(),
            tile_caches: FastHashMap::default(),
            config: FrameBuilderConfig {
                default_font_render_mode: FontRenderMode::Mono,
                dual_source_blending_is_enabled: true,
                dual_source_blending_is_supported: false,
                chase_primitive: ChasePrimitive::Nothing,
                global_enable_picture_caching: false,
                testing: false,
                gpu_supports_fast_clears: false,
                gpu_supports_advanced_blend: false,
                advanced_blend_is_coherent: false,
                batch_lookback_count: 0,
                background_color: None,
                compositor_kind: CompositorKind::default(),
                tile_size_override: None,
                max_depth_ids: 0,
                max_target_size: 0,
            },
        }
    }

    /// Get the memory usage statistics to pre-allocate for the next scene.
    pub fn get_stats(&self) -> SceneStats {
        SceneStats {
            prim_store_stats: self.prim_store.get_stats(),
            hit_test_stats: self.hit_testing_scene.get_stats(),
        }
    }

    pub fn create_hit_tester(
        &mut self,
        clip_data_store: &ClipDataStore,
    ) -> HitTester {
        HitTester::new(
            Arc::clone(&self.hit_testing_scene),
            &self.spatial_tree,
            &self.clip_store,
            clip_data_store,
        )
    }
}

/// Stores the allocation sizes of various arrays in the built
/// scene. This is retrieved from the current frame builder
/// and used to reserve an approximately correct capacity of
/// the arrays for the next scene that is getting built.
pub struct SceneStats {
    pub prim_store_stats: PrimitiveStoreStats,
    pub hit_test_stats: HitTestingSceneStats,
}

impl SceneStats {
    pub fn empty() -> Self {
        SceneStats {
            prim_store_stats: PrimitiveStoreStats::empty(),
            hit_test_stats: HitTestingSceneStats::empty(),
        }
    }
}
<commit_msg>Bug 1650354 - Clear color animation properties in flush_pending_updates. r=boris<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use api::{BuiltDisplayList, DisplayListWithCache, ColorF, DynamicProperties, Epoch, FontRenderMode};
use api::{PipelineId, PropertyBinding, PropertyBindingId, PropertyValue, MixBlendMode, StackingContext};
use api::MemoryReport;
use api::units::*;
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use crate::composite::CompositorKind;
use crate::clip::{ClipStore, ClipDataStore};
use crate::picture::{SliceId, TileCacheParams};
use crate::spatial_tree::{SpatialTree, SpatialNodeIndex};
use crate::frame_builder::{ChasePrimitive, FrameBuilderConfig};
use crate::hit_test::{HitTester, HitTestingScene, HitTestingSceneStats};
use crate::internal_types::{FastHashMap, FastHashSet};
use crate::prim_store::{PrimitiveStore, PrimitiveStoreStats, PictureIndex};
use std::sync::Arc;

/// Stores a map of the animated property bindings for the current display list. These
/// can be used to animate the transform and/or opacity of a display list without
/// re-submitting the display list itself.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct SceneProperties {
    transform_properties: FastHashMap<PropertyBindingId, LayoutTransform>,
    float_properties: FastHashMap<PropertyBindingId, f32>,
    color_properties: FastHashMap<PropertyBindingId, ColorF>,
    current_properties: DynamicProperties,
    pending_properties: Option<DynamicProperties>,
}

impl SceneProperties {
    pub fn new() -> Self {
        SceneProperties {
            transform_properties: FastHashMap::default(),
            float_properties: FastHashMap::default(),
            color_properties: FastHashMap::default(),
            current_properties: DynamicProperties::default(),
            pending_properties: None,
        }
    }

    /// Set the current property list for this display list.
    pub fn set_properties(&mut self, properties: DynamicProperties) {
        self.pending_properties = Some(properties);
    }

    /// Add to the current property list for this display list.
    pub fn add_transforms(&mut self, transforms: Vec<PropertyValue<LayoutTransform>>) {
        let mut pending_properties = self.pending_properties
            .take()
            .unwrap_or_default();

        pending_properties.transforms.extend(transforms);

        self.pending_properties = Some(pending_properties);
    }

    /// Flush any pending updates to the scene properties. Returns
    /// true if the properties have changed since the last flush
    /// was called. This code allows properties to be changed by
    /// multiple set_properties and add_properties calls during a
    /// single transaction, and still correctly determine if any
    /// properties have changed. This can have significant power
    /// saving implications, allowing a frame build to be skipped
    /// if the properties haven't changed in many cases.
    pub fn flush_pending_updates(&mut self) -> bool {
        let mut properties_changed = false;

        if let Some(ref pending_properties) = self.pending_properties {
            if *pending_properties != self.current_properties {
                self.transform_properties.clear();
                self.float_properties.clear();
                self.color_properties.clear();

                for property in &pending_properties.transforms {
                    self.transform_properties
                        .insert(property.key.id, property.value);
                }

                for property in &pending_properties.floats {
                    self.float_properties
                        .insert(property.key.id, property.value);
                }

                for property in &pending_properties.colors {
                    self.color_properties
                        .insert(property.key.id, property.value);
                }

                self.current_properties = pending_properties.clone();
                properties_changed = true;
            }
        }

        properties_changed
    }

    /// Get the current value for a transform property.
    pub fn resolve_layout_transform(
        &self,
        property: &PropertyBinding<LayoutTransform>,
    ) -> LayoutTransform {
        match *property {
            PropertyBinding::Value(value) => value,
            PropertyBinding::Binding(ref key, v) => {
                self.transform_properties
                    .get(&key.id)
                    .cloned()
                    .unwrap_or(v)
            }
        }
    }

    /// Get the current value for a float property.
    pub fn resolve_float(
        &self,
        property: &PropertyBinding<f32>
    ) -> f32 {
        match *property {
            PropertyBinding::Value(value) => value,
            PropertyBinding::Binding(ref key, v) => {
                self.float_properties
                    .get(&key.id)
                    .cloned()
                    .unwrap_or(v)
            }
        }
    }

    pub fn float_properties(&self) -> &FastHashMap<PropertyBindingId, f32> {
        &self.float_properties
    }

    /// Get the current value for a color property.
    pub fn resolve_color(
        &self,
        property: &PropertyBinding<ColorF>
    ) -> ColorF {
        match *property {
            PropertyBinding::Value(value) => value,
            PropertyBinding::Binding(ref key, v) => {
                self.color_properties
                    .get(&key.id)
                    .cloned()
                    .unwrap_or(v)
            }
        }
    }

    pub fn color_properties(&self) -> &FastHashMap<PropertyBindingId, ColorF> {
        &self.color_properties
    }

}

/// A representation of the layout within the display port for a given document or iframe.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Clone)]
pub struct ScenePipeline {
    pub pipeline_id: PipelineId,
    pub viewport_size: LayoutSize,
    pub content_size: LayoutSize,
    pub background_color: Option<ColorF>,
    pub display_list: DisplayListWithCache,
}

/// A complete representation of the layout bundling visible pipelines together.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Clone)]
pub struct Scene {
    pub root_pipeline_id: Option<PipelineId>,
    pub pipelines: FastHashMap<PipelineId, ScenePipeline>,
    pub pipeline_epochs: FastHashMap<PipelineId, Epoch>,
}

impl Scene {
    pub fn new() -> Self {
        Scene {
            root_pipeline_id: None,
            pipelines: FastHashMap::default(),
            pipeline_epochs: FastHashMap::default(),
        }
    }

    pub fn set_root_pipeline_id(&mut self, pipeline_id: PipelineId) {
        self.root_pipeline_id = Some(pipeline_id);
    }

    pub fn set_display_list(
        &mut self,
        pipeline_id: PipelineId,
        epoch: Epoch,
        display_list: BuiltDisplayList,
        background_color: Option<ColorF>,
        viewport_size: LayoutSize,
        content_size: LayoutSize,
    ) {
        // Adds a cache to the given display list. If this pipeline already had
        // a display list before, that display list is updated and used instead.
        let display_list = match self.pipelines.remove(&pipeline_id) {
            Some(mut pipeline) => {
                pipeline.display_list.update(display_list);
                pipeline.display_list
            }
            None => DisplayListWithCache::new_from_list(display_list)
        };

        let new_pipeline = ScenePipeline {
            pipeline_id,
            viewport_size,
            content_size,
            background_color,
            display_list,
        };

        self.pipelines.insert(pipeline_id, new_pipeline);
        self.pipeline_epochs.insert(pipeline_id, epoch);
    }

    pub fn remove_pipeline(&mut self, pipeline_id: PipelineId) {
        if self.root_pipeline_id == Some(pipeline_id) {
            self.root_pipeline_id = None;
        }
        self.pipelines.remove(&pipeline_id);
        self.pipeline_epochs.remove(&pipeline_id);
    }

    pub fn update_epoch(&mut self, pipeline_id: PipelineId, epoch: Epoch) {
        self.pipeline_epochs.insert(pipeline_id, epoch);
    }

    pub fn has_root_pipeline(&self) -> bool {
        if let Some(ref root_id) = self.root_pipeline_id {
            return self.pipelines.contains_key(root_id);
        }

        false
    }

    pub fn report_memory(
        &self,
        ops: &mut MallocSizeOfOps,
        report: &mut MemoryReport
    ) {
        for (_, pipeline) in &self.pipelines {
            report.display_list += pipeline.display_list.size_of(ops)
        }
    }
}

pub trait StackingContextHelpers {
    fn mix_blend_mode_for_compositing(&self) -> Option<MixBlendMode>;
}

impl StackingContextHelpers for StackingContext {
    fn mix_blend_mode_for_compositing(&self) -> Option<MixBlendMode> {
        match self.mix_blend_mode {
            MixBlendMode::Normal => None,
            _ => Some(self.mix_blend_mode),
        }
    }
}

/// WebRender's internal representation of the scene.
pub struct BuiltScene {
    pub has_root_pipeline: bool,
    pub pipeline_epochs: FastHashMap<PipelineId, Epoch>,
    pub output_rect: DeviceIntRect,
    pub background_color: Option<ColorF>,
    pub root_pic_index: PictureIndex,
    pub prim_store: PrimitiveStore,
    pub clip_store: ClipStore,
    pub config: FrameBuilderConfig,
    pub spatial_tree: SpatialTree,
    pub hit_testing_scene: Arc<HitTestingScene>,
    pub content_slice_count: usize,
    pub picture_cache_spatial_nodes: FastHashSet<SpatialNodeIndex>,
    pub tile_caches: FastHashMap<SliceId, TileCacheParams>,
}

impl BuiltScene {
    pub fn empty() -> Self {
        BuiltScene {
            has_root_pipeline: false,
            pipeline_epochs: FastHashMap::default(),
            output_rect: DeviceIntRect::zero(),
            background_color: None,
            root_pic_index: PictureIndex(0),
            prim_store: PrimitiveStore::new(&PrimitiveStoreStats::empty()),
            clip_store: ClipStore::new(),
            spatial_tree: SpatialTree::new(),
            hit_testing_scene: Arc::new(HitTestingScene::new(&HitTestingSceneStats::empty())),
            content_slice_count: 0,
            picture_cache_spatial_nodes: FastHashSet::default(),
            tile_caches: FastHashMap::default(),
            config: FrameBuilderConfig {
                default_font_render_mode: FontRenderMode::Mono,
                dual_source_blending_is_enabled: true,
                dual_source_blending_is_supported: false,
                chase_primitive: ChasePrimitive::Nothing,
                global_enable_picture_caching: false,
                testing: false,
                gpu_supports_fast_clears: false,
                gpu_supports_advanced_blend: false,
                advanced_blend_is_coherent: false,
                batch_lookback_count: 0,
                background_color: None,
                compositor_kind: CompositorKind::default(),
                tile_size_override: None,
                max_depth_ids: 0,
                max_target_size: 0,
            },
        }
    }

    /// Get the memory usage statistics to pre-allocate for the next scene.
    pub fn get_stats(&self) -> SceneStats {
        SceneStats {
            prim_store_stats: self.prim_store.get_stats(),
            hit_test_stats: self.hit_testing_scene.get_stats(),
        }
    }

    pub fn create_hit_tester(
        &mut self,
        clip_data_store: &ClipDataStore,
    ) -> HitTester {
        HitTester::new(
            Arc::clone(&self.hit_testing_scene),
            &self.spatial_tree,
            &self.clip_store,
            clip_data_store,
        )
    }
}

/// Stores the allocation sizes of various arrays in the built
/// scene. This is retrieved from the current frame builder
/// and used to reserve an approximately correct capacity of
/// the arrays for the next scene that is getting built.
pub struct SceneStats {
    pub prim_store_stats: PrimitiveStoreStats,
    pub hit_test_stats: HitTestingSceneStats,
}

impl SceneStats {
    pub fn empty() -> Self {
        SceneStats {
            prim_store_stats: PrimitiveStoreStats::empty(),
            hit_test_stats: HitTestingSceneStats::empty(),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016
// Jeff Nettleton
//
// Licensed under the MIT license (http://opensource.org/licenses/MIT). This
// file may not be copied, modified, or distributed except according to those
// terms

use std;
use std::collections::HashMap;
use rustc_serialize::{json, Decodable};

/// This enum represents the various types of HTTP requests.
#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
pub enum Method {
    Get,
    Put,
    Post,
    Delete,
    NoImpl,
}

/// This enum represents the errors that might be encountered.
#[derive(Debug)]
pub enum RequestError {
    JsonObjError(json::BuilderError),
    JsonStrError(json::DecoderError),
    StrCopyError(std::string::FromUtf8Error),
}

impl From<json::BuilderError> for RequestError {
    fn from(err: json::BuilderError) -> RequestError {
        RequestError::JsonObjError(err)
    }
}

impl From<json::DecoderError> for RequestError {
    fn from(err: json::DecoderError) -> RequestError {
        RequestError::JsonStrError(err)
    }
}

impl From<std::string::FromUtf8Error> for RequestError {
    fn from(err: std::string::FromUtf8Error) -> RequestError {
        RequestError::StrCopyError(err)
    }
}

/// A trait that allows for extracting variables from URIs.
pub trait FromUri {
    /// A function to parse a string into the correct type.
    fn from_uri(data: &str) -> Self;
}

impl FromUri for String {
    fn from_uri(data: &str) -> String {
        String::from(data)
    }
}

impl FromUri for i32 {
    fn from_uri(data: &str) -> i32 {
        match data.parse::<i32>() {
            Ok(v)  => v,
            Err(e) => panic!("matched integer can't be parsed: {:?}", e),
        }
    }
}

impl FromUri for u32 {
    fn from_uri(data: &str) -> u32 {
        match data.parse::<u32>() {
            Ok(v)  => v,
            Err(e) => panic!("matched integer can't be parsed: {:?}", e),
        }
    }
}

impl FromUri for f32 {
    fn from_uri(data: &str) -> f32 {
        match data.parse::<f32>() {
            Ok(v)  => v,
            Err(e) => panic!("matched float can't be parsed: {:?}", e),
        }
    }
}

/// This struct represents a request from an HTTP client.
#[derive(Debug)]
pub struct Request {
    pub method:  Method,
    pub path:    String,
    pub payload: Vec<u8>,
    pub params:  HashMap<String, String>,
    headers:     HashMap<String, String>,
}

impl Request {
    /// Create a new, empty Request.
    pub fn new() -> Request {
        Request {
            method:  Method::NoImpl,
            path:    String::new(),
            headers: HashMap::new(),
            params:  HashMap::new(),
            payload: Vec::with_capacity(2048),
        }
    }

    /// Create a Request from an HTTP request string.
    pub fn from_str(rqstr: &str) -> Request {
        let mut req = Request::new();
        req.parse(rqstr);
        req
    }

    /// Get an HTTP header contained in the Request.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::{Request, Response};
    /// use canteen::utils;
    ///
    /// // Given the route "/hello"
    /// fn handler(req: &Request) -> Response {
    ///     let browser = req.get_header("User-Agent");
    ///
    ///     match browser {
    ///         Some(ua) => utils::make_response(format!("You're using {}!", ua), "text/plain", 200),
    ///         None     => utils::make_response("Bad browser, no user agent!", "text/plain", 200),
    ///     }
    /// }
    /// ```
    pub fn get_header(&self, name: &str) -> Option<String> {
        let key = String::from(name);

        match self.headers.get(&key) {
            Some(val)   => Some(val.clone()),
            None        => None,
        }
    }

    /// Get a variable from the URI.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::{Request, Response};
    /// use canteen::utils;
    ///
    /// // Given the route "/hello/<str:name>"
    /// fn handler(req: &Request) -> Response {
    ///     let name: String = req.get("name");
    ///     utils::make_response(format!("<b>Hello, {}!</b>", name), "text/html", 200)
    /// }
    /// ```
    pub fn get<T: FromUri>(&self, name: &str) -> T {
        if !self.params.contains_key(name) {
            panic!("invalid route parameter {:?}", name);
        }

        FromUri::from_uri(&self.params[name])
    }

    /// Get a raw JSON payload from the request.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::{Request, Response};
    /// use canteen::utils;
    ///
    /// // Given the POST route "/hello"
    /// fn handler(req: &Request) -> Response {
    ///     let data = req.get_json();
    ///
    ///     match data {
    ///         Ok(val) => utils::make_response(format!("We got: {}", val), "text/plain", 200),
    ///         Err(_)  => utils::make_response("We got nothing :(", "text/plain", 200),
    ///     }
    /// }
    /// ```
    pub fn get_json(&self) -> Result<json::Json, RequestError> {
        let payload = try!(String::from_utf8(self.payload.clone()));
        let data = try!(json::Json::from_str(&payload));

        Ok(data)
    }

    /// Get a composed JSON payload from the request.
    ///
    /// # Examples
    ///
    /// ```rust,ignore
    /// use canteen::{Request, Response};
    ///
    /// #[derive(RustcDecodable)]
    /// struct Foo {
    ///     item: i32,
    /// }
    ///
    /// // Given the POST route "/hello"
    /// fn handler(req: &Request) -> Response {
    ///     let data: Foo = req.get_json_obj();
    ///
    ///     match data {
    ///         Ok(foo) => utils::make_response(format!("We got: {}!", data.item), "text/plain", 200),
    ///         Err(_)  => utils::make_response("We got nothing :(", "text/plain", 200),
    ///     }
    /// }
    /// ```
    pub fn get_json_obj<T: Decodable>(&self) -> Result<T, RequestError> {
        let payload = try!(String::from_utf8(self.payload.clone()));
        let data = try!(json::decode(&payload));

        Ok(data)
    }

    fn parse(&mut self, rqstr: &str) {
        let mut buf: Vec<&str> = rqstr.splitn(2, "\r\n").collect();
        let ask: Vec<&str> = buf[0].splitn(3, ' ').collect();

        self.method = match ask[0] {
            "GET"           => Method::Get,
            "PUT" | "PATCH" => Method::Put,
            "POST"          => Method::Post,
            "DELETE"        => Method::Delete,
            _               => Method::NoImpl,
        };
        self.path = String::from(ask[1]);

        loop {
            buf = buf[1].splitn(2, "\r\n").collect();

            if buf[0] == "" {
                if buf.len() == 1 || buf[1] == "" {
                    // no payload
                    break;
                }

                self.payload.extend(buf[1].as_bytes());
                break;
            }

            let hdr: Vec<&str> = buf[0].splitn(2, ": ").collect();

            if hdr.len() == 2 {
                self.headers.insert(String::from(hdr[0]), String::from(hdr[1]));
            }
        }
    }
}

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

    #[derive(RustcDecodable)]
    struct Foo {
        item: i32,
    }

    #[test]
    fn test_fromuri_trait_i32() {
        let pos = String::from("1234");
        assert_eq!(1234, FromUri::from_uri(&pos));

        let neg = String::from("-4321");
        assert_eq!(-4321, FromUri::from_uri(&neg));
    }

    #[test]
    fn test_fromuri_trait_u32() {
        let orig = String::from("1234");
        assert_eq!(1234, FromUri::from_uri(&orig));
    }

    #[test]
    fn test_fromuri_trait_string() {
        let orig = String::from("foobar");
        assert_eq!("foobar", <String as FromUri>::from_uri(&orig));
    }

    #[test]
    fn test_fromuri_trait_float() {
        let pos = String::from("123.45");
        assert_eq!(123.45f32, FromUri::from_uri(&pos));

        let neg = String::from("-54.321");
        assert_eq!(-54.321f32, FromUri::from_uri(&neg));
    }

    #[test]
    fn test_get_fromuri_i32() {
        let mut req = Request::new();
        req.params.insert(String::from("test"), String::from("1234"));

        assert_eq!(1234, req.get("test"));
    }

    #[test]
    fn test_get_json() {
        let mut req = Request::new();
        req.payload.extend_from_slice("{ \"item\": 123 }".as_bytes());

        let data = req.get_json().unwrap();

        assert_eq!(true, data.is_object());

        let obj = data.as_object().unwrap();
        let val = obj.get("item").unwrap();

        assert_eq!(true, val.is_u64());
        assert_eq!(123u64, val.as_u64().unwrap());
    }

    #[test]
    fn test_get_json_obj() {
        let mut req = Request::new();
        req.payload.extend_from_slice("{ \"item\": 123 }".as_bytes());

        let data: Foo = req.get_json_obj().unwrap();

        assert_eq!(123, data.item);
    }
}
<commit_msg>use Result::expect in FromUri trait implementations<commit_after>// Copyright (c) 2016
// Jeff Nettleton
//
// Licensed under the MIT license (http://opensource.org/licenses/MIT). This
// file may not be copied, modified, or distributed except according to those
// terms

use std;
use std::collections::HashMap;
use rustc_serialize::{json, Decodable};

/// This enum represents the various types of HTTP requests.
#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
pub enum Method {
    Get,
    Put,
    Post,
    Delete,
    NoImpl,
}

/// This enum represents the errors that might be encountered.
#[derive(Debug)]
pub enum RequestError {
    JsonObjError(json::BuilderError),
    JsonStrError(json::DecoderError),
    StrCopyError(std::string::FromUtf8Error),
}

impl From<json::BuilderError> for RequestError {
    fn from(err: json::BuilderError) -> RequestError {
        RequestError::JsonObjError(err)
    }
}

impl From<json::DecoderError> for RequestError {
    fn from(err: json::DecoderError) -> RequestError {
        RequestError::JsonStrError(err)
    }
}

impl From<std::string::FromUtf8Error> for RequestError {
    fn from(err: std::string::FromUtf8Error) -> RequestError {
        RequestError::StrCopyError(err)
    }
}

/// A trait that allows for extracting variables from URIs.
pub trait FromUri {
    /// A function to parse a string into the correct type.
    fn from_uri(data: &str) -> Self;
}

impl FromUri for String {
    fn from_uri(data: &str) -> String {
        String::from(data)
    }
}

impl FromUri for i32 {
    fn from_uri(data: &str) -> i32 {
        data.parse::<i32>().expect("matched integer can't be parsed")
    }
}

impl FromUri for u32 {
    fn from_uri(data: &str) -> u32 {
        data.parse::<u32>().expect("matched integer can't be parsed")
    }
}

impl FromUri for f32 {
    fn from_uri(data: &str) -> f32 {
        data.parse::<f32>().expect("matched float can't be parsed")
    }
}

/// This struct represents a request from an HTTP client.
#[derive(Debug)]
pub struct Request {
    pub method:  Method,
    pub path:    String,
    pub payload: Vec<u8>,
    pub params:  HashMap<String, String>,
    headers:     HashMap<String, String>,
}

impl Request {
    /// Create a new, empty Request.
    pub fn new() -> Request {
        Request {
            method:  Method::NoImpl,
            path:    String::new(),
            headers: HashMap::new(),
            params:  HashMap::new(),
            payload: Vec::with_capacity(2048),
        }
    }

    /// Create a Request from an HTTP request string.
    pub fn from_str(rqstr: &str) -> Request {
        let mut req = Request::new();
        req.parse(rqstr);
        req
    }

    /// Get an HTTP header contained in the Request.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::{Request, Response};
    /// use canteen::utils;
    ///
    /// // Given the route "/hello"
    /// fn handler(req: &Request) -> Response {
    ///     let browser = req.get_header("User-Agent");
    ///
    ///     match browser {
    ///         Some(ua) => utils::make_response(format!("You're using {}!", ua), "text/plain", 200),
    ///         None     => utils::make_response("Bad browser, no user agent!", "text/plain", 200),
    ///     }
    /// }
    /// ```
    pub fn get_header(&self, name: &str) -> Option<String> {
        let key = String::from(name);

        match self.headers.get(&key) {
            Some(val)   => Some(val.clone()),
            None        => None,
        }
    }

    /// Get a variable from the URI.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::{Request, Response};
    /// use canteen::utils;
    ///
    /// // Given the route "/hello/<str:name>"
    /// fn handler(req: &Request) -> Response {
    ///     let name: String = req.get("name");
    ///     utils::make_response(format!("<b>Hello, {}!</b>", name), "text/html", 200)
    /// }
    /// ```
    pub fn get<T: FromUri>(&self, name: &str) -> T {
        if !self.params.contains_key(name) {
            panic!("invalid route parameter {:?}", name);
        }

        FromUri::from_uri(&self.params[name])
    }

    /// Get a raw JSON payload from the request.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::{Request, Response};
    /// use canteen::utils;
    ///
    /// // Given the POST route "/hello"
    /// fn handler(req: &Request) -> Response {
    ///     let data = req.get_json();
    ///
    ///     match data {
    ///         Ok(val) => utils::make_response(format!("We got: {}", val), "text/plain", 200),
    ///         Err(_)  => utils::make_response("We got nothing :(", "text/plain", 200),
    ///     }
    /// }
    /// ```
    pub fn get_json(&self) -> Result<json::Json, RequestError> {
        let payload = try!(String::from_utf8(self.payload.clone()));
        let data = try!(json::Json::from_str(&payload));

        Ok(data)
    }

    /// Get a composed JSON payload from the request.
    ///
    /// # Examples
    ///
    /// ```rust,ignore
    /// use canteen::{Request, Response};
    ///
    /// #[derive(RustcDecodable)]
    /// struct Foo {
    ///     item: i32,
    /// }
    ///
    /// // Given the POST route "/hello"
    /// fn handler(req: &Request) -> Response {
    ///     let data: Foo = req.get_json_obj();
    ///
    ///     match data {
    ///         Ok(foo) => utils::make_response(format!("We got: {}!", data.item), "text/plain", 200),
    ///         Err(_)  => utils::make_response("We got nothing :(", "text/plain", 200),
    ///     }
    /// }
    /// ```
    pub fn get_json_obj<T: Decodable>(&self) -> Result<T, RequestError> {
        let payload = try!(String::from_utf8(self.payload.clone()));
        let data = try!(json::decode(&payload));

        Ok(data)
    }

    fn parse(&mut self, rqstr: &str) {
        let mut buf: Vec<&str> = rqstr.splitn(2, "\r\n").collect();
        let ask: Vec<&str> = buf[0].splitn(3, ' ').collect();

        self.method = match ask[0] {
            "GET"           => Method::Get,
            "PUT" | "PATCH" => Method::Put,
            "POST"          => Method::Post,
            "DELETE"        => Method::Delete,
            _               => Method::NoImpl,
        };
        self.path = String::from(ask[1]);

        loop {
            buf = buf[1].splitn(2, "\r\n").collect();

            if buf[0] == "" {
                if buf.len() == 1 || buf[1] == "" {
                    // no payload
                    break;
                }

                self.payload.extend(buf[1].as_bytes());
                break;
            }

            let hdr: Vec<&str> = buf[0].splitn(2, ": ").collect();

            if hdr.len() == 2 {
                self.headers.insert(String::from(hdr[0]), String::from(hdr[1]));
            }
        }
    }
}

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

    #[derive(RustcDecodable)]
    struct Foo {
        item: i32,
    }

    #[test]
    fn test_fromuri_trait_i32() {
        let pos = String::from("1234");
        assert_eq!(1234, FromUri::from_uri(&pos));

        let neg = String::from("-4321");
        assert_eq!(-4321, FromUri::from_uri(&neg));
    }

    #[test]
    fn test_fromuri_trait_u32() {
        let orig = String::from("1234");
        assert_eq!(1234, FromUri::from_uri(&orig));
    }

    #[test]
    fn test_fromuri_trait_string() {
        let orig = String::from("foobar");
        assert_eq!("foobar", <String as FromUri>::from_uri(&orig));
    }

    #[test]
    fn test_fromuri_trait_float() {
        let pos = String::from("123.45");
        assert_eq!(123.45f32, FromUri::from_uri(&pos));

        let neg = String::from("-54.321");
        assert_eq!(-54.321f32, FromUri::from_uri(&neg));
    }

    #[test]
    fn test_get_fromuri_i32() {
        let mut req = Request::new();
        req.params.insert(String::from("test"), String::from("1234"));

        assert_eq!(1234, req.get("test"));
    }

    #[test]
    fn test_get_json() {
        let mut req = Request::new();
        req.payload.extend_from_slice("{ \"item\": 123 }".as_bytes());

        let data = req.get_json().unwrap();

        assert_eq!(true, data.is_object());

        let obj = data.as_object().unwrap();
        let val = obj.get("item").unwrap();

        assert_eq!(true, val.is_u64());
        assert_eq!(123u64, val.as_u64().unwrap());
    }

    #[test]
    fn test_get_json_obj() {
        let mut req = Request::new();
        req.payload.extend_from_slice("{ \"item\": 123 }".as_bytes());

        let data: Foo = req.get_json_obj().unwrap();

        assert_eq!(123, data.item);
    }
}
<|endoftext|>


<commit_before>use std::io::{Result, Write};

use analysis;
use analysis::upcasts::Upcasts;
use chunk::{ffi_function_todo, Chunk};
use env::Env;
use super::function_body;
use super::function_body_chunk;
use super::general::version_condition;
use super::parameter::ToParameter;
use super::return_value::{out_parameters_as_return, ToReturnValue};
use super::translate_from_glib::TranslateFromGlib;
use super::translate_to_glib::TranslateToGlib;
use writer::primitives::{format_block, tabs};
use writer::ToCode;

pub fn generate(w: &mut Write, env: &Env, analysis: &analysis::functions::Info,
    in_trait: bool, only_declaration: bool, indent: usize) -> Result<()> {

    let comment_prefix = if analysis.comented { "//" } else { "" };
    let pub_prefix = if in_trait { "" } else { "pub " };
    let declaration = declaration(env, analysis);
    let suffix = if only_declaration { ";" } else { " {" };

    try!(version_condition(w, &env.config.library_name,
        env.config.min_cfg_version, analysis.version, analysis.comented, indent));
    try!(writeln!(w, "{}{}{}{}{}", tabs(indent),
        comment_prefix, pub_prefix, declaration, suffix));

    if !only_declaration {
        let body = if analysis.comented {
            let ch = ffi_function_todo(&analysis.glib_name);
            ch.to_code()
        } else if let Some(chunk) = body_chunk(env, analysis, in_trait) {
            chunk.to_code()
        } else {
            let body = body(env, analysis, in_trait);
            format_block("", "}", &body)
        };
        for s in body {
            try!(writeln!(w, "{}{}", tabs(indent), s));
        }
        try!(writeln!(w, ""));
    }

    Ok(())
}

pub fn declaration(env: &Env, analysis: &analysis::functions::Info) -> String {
    let outs_as_return = !analysis.outs.is_empty();
    let return_str = if outs_as_return {
        out_parameters_as_return(env, analysis)
    } else {
        analysis.ret.to_return_value(env)
    };
    let mut param_str = String::with_capacity(100);

    let upcasts = upcasts(&analysis.upcasts);

    for (pos, par) in analysis.parameters.iter().enumerate() {
        if outs_as_return && analysis.outs.iter().any(|p| p.name==par.name) {
            continue;
        }
        if pos > 0 { param_str.push_str(", ") }
        let s = par.to_parameter(env, &analysis.upcasts);
        param_str.push_str(&s);
    }

    format!("fn {}{}({}){}", analysis.name, upcasts, param_str, return_str)
}

fn upcasts(upcasts: &Upcasts) -> String {
    if upcasts.is_empty() { return String::new() }
    let strs: Vec<String> = upcasts.iter()
        .map(|upcast| { format!("{}: Upcast<{}>", upcast.1, upcast.2)})
        .collect();
    format!("<{}>", strs.join(", "))
}

pub fn body_chunk(env: &Env, analysis: &analysis::functions::Info,
    in_trait: bool) -> Option<Chunk> {
    let outs_as_return = !analysis.outs.is_empty();
    let mut builder = function_body_chunk::Builder::new();
    builder.glib_name(&analysis.glib_name)
        .from_glib(analysis.ret.translate_from_glib_as_function(env))
        .outs_mode(analysis.outs.mode);

    //TODO: change to map on parameters with pass Vec<String> to builder
    for par in &analysis.parameters {
        if outs_as_return && analysis.outs.iter().any(|p| p.name==par.name) {
            let name = par.name.clone();
            let (prefix, suffix) = par.translate_from_glib_as_function(env);
            builder.out_parameter(name, prefix, suffix);
        } else {
            let upcast = in_trait && par.instance_parameter
                || analysis.upcasts.iter().any(|&(ref name, _, _)| name == &par.name);
            let s = par.translate_to_glib(&env.library, upcast);
            builder.parameter(s);
        }
    }

    builder.generate()
}

pub fn body(env: &Env, analysis: &analysis::functions::Info,
    in_trait: bool) -> Vec<String> {
    let outs_as_return = !analysis.outs.is_empty();
    let mut builder = function_body::Builder::new();
    builder.glib_name(&analysis.glib_name)
        .from_glib(analysis.ret.translate_from_glib_as_function(env))
        .outs_mode(analysis.outs.mode);

    //TODO: change to map on parameters with pass Vec<String> to builder
    for par in &analysis.parameters {
        if outs_as_return && analysis.outs.iter().any(|p| p.name==par.name) {
            let name = par.name.clone();
            let (prefix, suffix) = par.translate_from_glib_as_function(env);
            builder.out_parameter(name, prefix, suffix);
        } else {
            let upcast = in_trait && par.instance_parameter
                || analysis.upcasts.iter().any(|&(ref name, _, _)| name == &par.name);
            let s = par.translate_to_glib(&env.library, upcast);
            builder.parameter(s);
        }
    }

    builder.generate()
}
<commit_msg>Move chunk for commented functions to body_chunk<commit_after>use std::io::{Result, Write};

use analysis;
use analysis::upcasts::Upcasts;
use chunk::{ffi_function_todo, Chunk};
use env::Env;
use super::function_body;
use super::function_body_chunk;
use super::general::version_condition;
use super::parameter::ToParameter;
use super::return_value::{out_parameters_as_return, ToReturnValue};
use super::translate_from_glib::TranslateFromGlib;
use super::translate_to_glib::TranslateToGlib;
use writer::primitives::{format_block, tabs};
use writer::ToCode;

pub fn generate(w: &mut Write, env: &Env, analysis: &analysis::functions::Info,
    in_trait: bool, only_declaration: bool, indent: usize) -> Result<()> {

    let comment_prefix = if analysis.comented { "//" } else { "" };
    let pub_prefix = if in_trait { "" } else { "pub " };
    let declaration = declaration(env, analysis);
    let suffix = if only_declaration { ";" } else { " {" };

    try!(version_condition(w, &env.config.library_name,
        env.config.min_cfg_version, analysis.version, analysis.comented, indent));
    try!(writeln!(w, "{}{}{}{}{}", tabs(indent),
        comment_prefix, pub_prefix, declaration, suffix));

    if !only_declaration {
        let body = if let Some(chunk) = body_chunk(env, analysis, in_trait) {
            chunk.to_code()
        } else {
            let body = body(env, analysis, in_trait);
            format_block("", "}", &body)
        };
        for s in body {
            try!(writeln!(w, "{}{}", tabs(indent), s));
        }
        try!(writeln!(w, ""));
    }

    Ok(())
}

pub fn declaration(env: &Env, analysis: &analysis::functions::Info) -> String {
    let outs_as_return = !analysis.outs.is_empty();
    let return_str = if outs_as_return {
        out_parameters_as_return(env, analysis)
    } else {
        analysis.ret.to_return_value(env)
    };
    let mut param_str = String::with_capacity(100);

    let upcasts = upcasts(&analysis.upcasts);

    for (pos, par) in analysis.parameters.iter().enumerate() {
        if outs_as_return && analysis.outs.iter().any(|p| p.name==par.name) {
            continue;
        }
        if pos > 0 { param_str.push_str(", ") }
        let s = par.to_parameter(env, &analysis.upcasts);
        param_str.push_str(&s);
    }

    format!("fn {}{}({}){}", analysis.name, upcasts, param_str, return_str)
}

fn upcasts(upcasts: &Upcasts) -> String {
    if upcasts.is_empty() { return String::new() }
    let strs: Vec<String> = upcasts.iter()
        .map(|upcast| { format!("{}: Upcast<{}>", upcast.1, upcast.2)})
        .collect();
    format!("<{}>", strs.join(", "))
}

pub fn body_chunk(env: &Env, analysis: &analysis::functions::Info,
    in_trait: bool) -> Option<Chunk> {
    if analysis.comented {
        return Some(ffi_function_todo(&analysis.glib_name));
    }

    let outs_as_return = !analysis.outs.is_empty();
    let mut builder = function_body_chunk::Builder::new();
    builder.glib_name(&analysis.glib_name)
        .from_glib(analysis.ret.translate_from_glib_as_function(env))
        .outs_mode(analysis.outs.mode);

    //TODO: change to map on parameters with pass Vec<String> to builder
    for par in &analysis.parameters {
        if outs_as_return && analysis.outs.iter().any(|p| p.name==par.name) {
            let name = par.name.clone();
            let (prefix, suffix) = par.translate_from_glib_as_function(env);
            builder.out_parameter(name, prefix, suffix);
        } else {
            let upcast = in_trait && par.instance_parameter
                || analysis.upcasts.iter().any(|&(ref name, _, _)| name == &par.name);
            let s = par.translate_to_glib(&env.library, upcast);
            builder.parameter(s);
        }
    }

    builder.generate()
}

pub fn body(env: &Env, analysis: &analysis::functions::Info,
    in_trait: bool) -> Vec<String> {
    let outs_as_return = !analysis.outs.is_empty();
    let mut builder = function_body::Builder::new();
    builder.glib_name(&analysis.glib_name)
        .from_glib(analysis.ret.translate_from_glib_as_function(env))
        .outs_mode(analysis.outs.mode);

    //TODO: change to map on parameters with pass Vec<String> to builder
    for par in &analysis.parameters {
        if outs_as_return && analysis.outs.iter().any(|p| p.name==par.name) {
            let name = par.name.clone();
            let (prefix, suffix) = par.translate_from_glib_as_function(env);
            builder.out_parameter(name, prefix, suffix);
        } else {
            let upcast = in_trait && par.instance_parameter
                || analysis.upcasts.iter().any(|&(ref name, _, _)| name == &par.name);
            let s = par.translate_to_glib(&env.library, upcast);
            builder.parameter(s);
        }
    }

    builder.generate()
}
<|endoftext|>


<commit_before>extern crate portmidi as pm;

extern crate rustc_serialize;
extern crate docopt;

use std::time::Duration;
use std::thread;

const USAGE: &'static str = r#"
portmidi-rs: monitor-device example

Usage:
    monitor-device <device-id>

Options:
    -h --help   Show this screen.

Omitting <device-id> will list the available devices.
"#;

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_device_id: i32,
}

fn print_devices(pm: &pm::PortMidi) {
    for dev in pm.devices().unwrap() {
        println!("{}", dev);
    }
}

fn main() {
    // initialize the PortMidi context.
    let context = pm::PortMidi::new().unwrap();
    let timeout = Duration::from_millis(10);

    // setup the command line interface
    let args: Args = docopt::Docopt::new(USAGE).and_then(|d| d.decode()).unwrap_or_else(|err| {
        print_devices(&context);
        err.exit();
    });

    // get the device info for the given id
    let info = context.device(args.arg_device_id).unwrap();
    println!("Listening on: {}) {}", info.id(), info.name());

    // get the device's input port
    let in_port = context.input_port(info, 1024).unwrap();

    while let Ok(_) = in_port.poll() {
        if let Ok(Some(event)) = in_port.read_n(1024) {
            println!("{:?}", event);
            // there is no blocking receive method in PortMidi, therefore
            // we have to sleep some time to prevent a busy-wait loop
            thread::sleep(timeout)
        }
    }
}
<commit_msg>Update monitor.rs<commit_after>extern crate portmidi as pm;

extern crate rustc_serialize;
extern crate docopt;

use std::time::Duration;
use std::thread;

const USAGE: &'static str = r#"
portmidi-rs: monitor-device example

Usage:
    monitor-device <device-id>

Options:
    -h --help   Show this screen.

Omitting <device-id> will list the available devices.
"#;

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_device_id: i32,
}

fn print_devices(pm: &pm::PortMidi) {
    for dev in pm.devices().unwrap() {
        println!("{}", dev);
    }
}

fn main() {
    // initialize the PortMidi context.
    let context = pm::PortMidi::new().unwrap();
    let timeout = Duration::from_millis(10);

    // setup the command line interface
    let args: Args = docopt::Docopt::new(USAGE).and_then(|d| d.decode()).unwrap_or_else(|err| {
        print_devices(&context);
        err.exit();
    });

    // get the device info for the given id
    let info = context.device(args.arg_device_id).unwrap();
    println!("Listening on: {}) {}", info.id(), info.name());

    // get the device's input port
    let in_port = context.input_port(info, 1024).unwrap();

    while let Ok(_) = in_port.poll() {
        if let Ok(Some(event)) = in_port.read_n(1024) {
            println!("{:?}", event);
        }
        // there is no blocking receive method in PortMidi, therefore
        // we have to sleep some time to prevent a busy-wait loop
        thread::sleep(timeout);
    }
}
<|endoftext|>