<commit_before>//! Common configuration utilities

use directories::ProjectDirs;
#[cfg(unix)]
use std::path::Path;
use std::{env, path::PathBuf};

/// Default configuration file path
pub fn get_default_config_path() -> Option<PathBuf> {
    // config.json in the current working directory ($PWD)
    if let Ok(mut path) = env::current_dir() {
        path.push("config.json");

        if path.exists() {
            return Some(path);
        }
    }

    // config.json in the current working directory (relative path)
    let relative_path = PathBuf::from("config.json");
    if relative_path.exists() {
        return Some(relative_path);
    }

    // System standard directories
    if let Some(project_dirs) = ProjectDirs::from("org", "shadowsocks", "shadowsocks-rust") {
        // Linux: $XDG_CONFIG_HOME/shadowsocks-rust/config.json
        //        $HOME/.config/shadowsocks-rust/config.json
        // macOS: $HOME/Library/Application Support/org.shadowsocks.shadowsocks-rust/config.json
        // Windows: {FOLDERID_RoamingAppData}/shadowsocks/shadowsocks-rust/config/config.json

        let mut config_path = project_dirs.config_dir().to_path_buf();
        config_path.push("config.json");

        if config_path.exists() {
            return Some(config_path);
        }
    }

    // UNIX systems, XDG Base Directory
    // https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
    #[cfg(unix)]
    if let Ok(base_directories) = xdg::BaseDirectories::with_prefix("shadowsocks-rust") {
        // $XDG_CONFIG_HOME/shadowsocks-rust/config.json
        // for dir in $XDG_CONFIG_DIRS; $dir/shadowsocks-rust/config.json
        if let Some(config_path) = base_directories.find_config_file("config.json") {
            return Some(config_path);
        }
    }

    // UNIX global configuration file
    #[cfg(unix)]
    {
        let global_config_path = Path::new("/etc/shadowsocks-rust/config.json");
        if global_config_path.exists() {
            return Some(global_config_path.to_path_buf());
        }
    }

    None
}
<commit_msg>default config relative path only required if $PWD doesnt exist<commit_after>//! Common configuration utilities

use directories::ProjectDirs;
#[cfg(unix)]
use std::path::Path;
use std::{env, path::PathBuf};

/// Default configuration file path
pub fn get_default_config_path() -> Option<PathBuf> {
    // config.json in the current working directory ($PWD)
    if let Ok(mut path) = env::current_dir() {
        path.push("config.json");

        if path.exists() {
            return Some(path);
        }
    } else {
        // config.json in the current working directory (relative path)
        let relative_path = PathBuf::from("config.json");
        if relative_path.exists() {
            return Some(relative_path);
        }
    }

    // System standard directories
    if let Some(project_dirs) = ProjectDirs::from("org", "shadowsocks", "shadowsocks-rust") {
        // Linux: $XDG_CONFIG_HOME/shadowsocks-rust/config.json
        //        $HOME/.config/shadowsocks-rust/config.json
        // macOS: $HOME/Library/Application Support/org.shadowsocks.shadowsocks-rust/config.json
        // Windows: {FOLDERID_RoamingAppData}/shadowsocks/shadowsocks-rust/config/config.json

        let mut config_path = project_dirs.config_dir().to_path_buf();
        config_path.push("config.json");

        if config_path.exists() {
            return Some(config_path);
        }
    }

    // UNIX systems, XDG Base Directory
    // https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
    #[cfg(unix)]
    if let Ok(base_directories) = xdg::BaseDirectories::with_prefix("shadowsocks-rust") {
        // $XDG_CONFIG_HOME/shadowsocks-rust/config.json
        // for dir in $XDG_CONFIG_DIRS; $dir/shadowsocks-rust/config.json
        if let Some(config_path) = base_directories.find_config_file("config.json") {
            return Some(config_path);
        }
    }

    // UNIX global configuration file
    #[cfg(unix)]
    {
        let global_config_path = Path::new("/etc/shadowsocks-rust/config.json");
        if global_config_path.exists() {
            return Some(global_config_path.to_path_buf());
        }
    }

    None
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::fs::File;
use std::str::FromStr;
use docopt::Docopt;
use toml;

use gobjects;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum WorkMode {
    Normal,     //generate widgets etc.
    Sys,        //generate -sys with ffi
}

impl Default for WorkMode {
    fn default() -> WorkMode { WorkMode::Normal }
}

impl FromStr for WorkMode {
    type Err = String;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "normal" => Ok(WorkMode::Normal),
            "sys" => Ok(WorkMode::Sys),
            _ => Err("Wrong work mode".into())
        }
    }
}

static USAGE: &'static str = "
Usage: gir [options] [<library> <version>]

Options:
    -d PATH             Directory for girs
    -m MODE             Work mode: normal or sys
    -o PATH             Target root path
";

#[derive(Debug)]
pub struct Config {
    pub work_mode: WorkMode,
    pub girs_dir: String,
    pub library_name: String,
    pub library_version: String,
    pub target_path: String,
    pub objects: gobjects::GObjects,
}

impl Config {
    pub fn new() -> Config {
        let args = Docopt::new(USAGE)
            .and_then(|dopt| dopt.parse())
            .unwrap_or_else(|e| e.exit());

        let toml = read_toml("Gir.toml");

        let work_mode_str = match args.get_str("-m") {
            "" => toml.lookup("options.work_mode")
                    .unwrap_or_else(|| panic!("No options.work_mode in config"))
                    .as_str().unwrap(),
            a => a,
        };
        let work_mode = WorkMode::from_str(work_mode_str)
            .unwrap_or_else(|_| panic!("Wrong work mode"));

        let girs_dir = match args.get_str("-d") {
            "" => toml.lookup("options.girs_dir")
                      .unwrap_or_else(|| panic!("No options.girs_dir in config"))
                      .as_str().unwrap(),
            a => a
        };

        let (library_name, library_version) =
            match (args.get_str("<library>"), args.get_str("<version>")) {
            ("", "") => (
                toml.lookup("options.library")
                    .unwrap_or_else(|| panic!("No options.library in config"))
                    .as_str().unwrap(),
                toml.lookup("options.version")
                    .unwrap_or_else(|| panic!("No options.version in config"))
                    .as_str().unwrap()
            ),
            ("", _) | (_, "") => panic!("Library and version can not be specified separately"),
            (a, b) => (a, b)
        };

        let target_path = match args.get_str("-o") {
            "" => toml.lookup("options.target_path")
                    .unwrap_or_else(|| panic!("No options.target_path in config"))
                    .as_str().unwrap(),
            a => a
        };

        let objects = gobjects::parse_toml(toml.lookup("object").unwrap());

        Config {
            work_mode: work_mode,
            girs_dir: girs_dir.into(),
            library_name: library_name.into(),
            library_version: library_version.into(),
            target_path: target_path.into(),
            objects: objects,
        }
    }

    pub fn library_full_name(&self) -> String {
        format!("{}-{}", self.library_name, self.library_version)
    }
}

fn read_toml(filename: &str) -> toml::Value {
    let mut input = String::new();
    File::open(filename).and_then(|mut f| {
        f.read_to_string(&mut input)
    }).unwrap();
    let mut parser = toml::Parser::new(&input);
    match parser.parse() {
        Some(toml) => toml::Value::Table(toml),
        None => {
            for err in &parser.errors {
                let (loline, locol) = parser.to_linecol(err.lo);
                let (hiline, hicol) = parser.to_linecol(err.hi);
                println!("{}:{}:{}-{}:{} error: {}",
                         filename, loline, locol, hiline, hicol, err.desc);
            }
            panic!("Errors in config")
        }
    }
}
<commit_msg>Add --help parameter<commit_after>use std::io::prelude::*;
use std::fs::File;
use std::str::FromStr;
use docopt::Docopt;
use toml;

use gobjects;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum WorkMode {
    Normal,     //generate widgets etc.
    Sys,        //generate -sys with ffi
}

impl Default for WorkMode {
    fn default() -> WorkMode { WorkMode::Normal }
}

impl FromStr for WorkMode {
    type Err = String;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "normal" => Ok(WorkMode::Normal),
            "sys" => Ok(WorkMode::Sys),
            _ => Err("Wrong work mode".into())
        }
    }
}

static USAGE: &'static str = "
Usage: gir [options] [<library> <version>]
       gir --help

Options:
    -h, --help          Show this message.
    -d GIRSPATH         Directory for girs
    -m MODE             Work mode: normal or sys
    -o PATH             Target root path
";

#[derive(Debug)]
pub struct Config {
    pub work_mode: WorkMode,
    pub girs_dir: String,
    pub library_name: String,
    pub library_version: String,
    pub target_path: String,
    pub objects: gobjects::GObjects,
}

impl Config {
    pub fn new() -> Config {
        let args = Docopt::new(USAGE)
            .and_then(|dopt| dopt.parse())
            .unwrap_or_else(|e| e.exit());

        let toml = read_toml("Gir.toml");

        let work_mode_str = match args.get_str("-m") {
            "" => toml.lookup("options.work_mode")
                    .unwrap_or_else(|| panic!("No options.work_mode in config"))
                    .as_str().unwrap(),
            a => a,
        };
        let work_mode = WorkMode::from_str(work_mode_str)
            .unwrap_or_else(|_| panic!("Wrong work mode"));

        let girs_dir = match args.get_str("-d") {
            "" => toml.lookup("options.girs_dir")
                      .unwrap_or_else(|| panic!("No options.girs_dir in config"))
                      .as_str().unwrap(),
            a => a
        };

        let (library_name, library_version) =
            match (args.get_str("<library>"), args.get_str("<version>")) {
            ("", "") => (
                toml.lookup("options.library")
                    .unwrap_or_else(|| panic!("No options.library in config"))
                    .as_str().unwrap(),
                toml.lookup("options.version")
                    .unwrap_or_else(|| panic!("No options.version in config"))
                    .as_str().unwrap()
            ),
            ("", _) | (_, "") => panic!("Library and version can not be specified separately"),
            (a, b) => (a, b)
        };

        let target_path = match args.get_str("-o") {
            "" => toml.lookup("options.target_path")
                    .unwrap_or_else(|| panic!("No options.target_path in config"))
                    .as_str().unwrap(),
            a => a
        };

        let objects = gobjects::parse_toml(toml.lookup("object").unwrap());

        Config {
            work_mode: work_mode,
            girs_dir: girs_dir.into(),
            library_name: library_name.into(),
            library_version: library_version.into(),
            target_path: target_path.into(),
            objects: objects,
        }
    }

    pub fn library_full_name(&self) -> String {
        format!("{}-{}", self.library_name, self.library_version)
    }
}

fn read_toml(filename: &str) -> toml::Value {
    let mut input = String::new();
    File::open(filename).and_then(|mut f| {
        f.read_to_string(&mut input)
    }).unwrap();
    let mut parser = toml::Parser::new(&input);
    match parser.parse() {
        Some(toml) => toml::Value::Table(toml),
        None => {
            for err in &parser.errors {
                let (loline, locol) = parser.to_linecol(err.lo);
                let (hiline, hicol) = parser.to_linecol(err.hi);
                println!("{}:{}:{}-{}:{} error: {}",
                         filename, loline, locol, hiline, hicol, err.desc);
            }
            panic!("Errors in config")
        }
    }
}
<|endoftext|>


<commit_before>//! Configuration to create a Consumer or Producer.
extern crate rdkafka_sys as rdkafka;

use self::rdkafka::types::*;

use std::collections::HashMap;
use std::ffi::{CStr, CString};
use util::bytes_cstr_to_owned;

use error::{KafkaError, KafkaResult, IsError};
use client::Context;

const ERR_LEN: usize = 256;

unsafe extern "C" fn log_cb(_client: *const RDKafkaState, level: i32, _fac: *const i8, buf: *const i8) {
    let buf_str = CStr::from_ptr(buf).to_string_lossy();
    match level {
        0 => error!("rdkafka: {}", buf_str),
        1 => error!("rdkafka: {}", buf_str),
        2 => error!("rdkafka: {}", buf_str),
        3 => error!("rdkafka: {}", buf_str),
        4 => warn!("rdkafka: {}", buf_str),
        5 => info!("rdkafka: {}", buf_str),
        6 => info!("rdkafka: {}", buf_str),
        _ => debug!("rdkafka: {}", buf_str),
    }
}

/// Client configuration.
#[derive(Clone)]
pub struct ClientConfig {
    conf_map: HashMap<String, String>,
    default_topic_config: Option<TopicConfig>,
}

impl ClientConfig {
    /// Creates a new empty configuration.
    pub fn new() -> ClientConfig {
        ClientConfig {
            conf_map: HashMap::new(),
            default_topic_config: None,
        }
    }

    /// Sets a new parameter in the configuration.
    pub fn set<'a>(&'a mut self, key: &str, value: &str) -> &'a mut ClientConfig {
        self.conf_map.insert(key.to_string(), value.to_string());
        self
    }

    /// Sets the default topic configuration to use for automatically subscribed
    /// topics (e.g., through pattern-matched topics).
    pub fn set_default_topic_config<'a>(&'a mut self, default_topic_config: TopicConfig) -> &'a mut ClientConfig {
        self.default_topic_config = Some(default_topic_config);
        self
    }

    /// Returns the native rdkafka-sys configuration.
    pub fn create_native_config(&self) -> KafkaResult<*mut RDKafkaConf> {
        let conf = unsafe { rdkafka::rd_kafka_conf_new() };
        let errstr = [0; ERR_LEN];
        for (key, value) in &self.conf_map {
            let key_c = try!(CString::new(key.to_string()));
            let value_c = try!(CString::new(value.to_string()));
            let ret = unsafe {
                rdkafka::rd_kafka_conf_set(conf, key_c.as_ptr(), value_c.as_ptr(),
                                           errstr.as_ptr() as *mut i8, errstr.len())
            };
            if ret.is_error() {
                let descr = unsafe { bytes_cstr_to_owned(&errstr) };
                return Err(KafkaError::ClientConfig((ret, descr, key.to_string(), value.to_string())));
            }
        }
        if let Some(topic_config) = self.create_native_default_topic_config() {
            if let Err(e) = topic_config {
                return Err(e);
            } else {
                unsafe { rdkafka::rd_kafka_conf_set_default_topic_conf(conf, topic_config.unwrap()) };
            }
        }
        unsafe { rdkafka::rd_kafka_conf_set_log_cb(conf, Some(log_cb)) };
        Ok(conf)
    }

    fn create_native_default_topic_config(&self) -> Option<KafkaResult<*mut RDKafkaTopicConf>> {
        self.default_topic_config.as_ref().map(|c| c.create_native_config())
    }

    /// Uses the current configuration to create a new Consumer or Producer.
    pub fn create<T: FromClientConfig>(&self) -> KafkaResult<T> {
        T::from_config(self)
    }

    /// Uses the current configuration and the provided context to create a new Consumer or Producer.
    pub fn create_with_context<C, T>(&self, context: C) -> KafkaResult<T>
            where C: Context,
                  T: FromClientConfigAndContext<C> {
        T::from_config_and_context(self, context)
    }
}

/// Create a new client based on the provided configuration.
pub trait FromClientConfig: Sized {
    fn from_config(&ClientConfig) -> KafkaResult<Self>;
}

/// Create a new client based on the provided configuration and context.
pub trait FromClientConfigAndContext<C: Context>: Sized {
    fn from_config_and_context(&ClientConfig, C) -> KafkaResult<Self>;
}

/// Topic configuration.
#[derive(Clone)]
pub struct TopicConfig {
    conf_map: HashMap<String, String>,
}

impl TopicConfig {
    /// Returns a new TopicConfig for the specified topic name and client.
    pub fn new() -> TopicConfig {
        TopicConfig {
            conf_map: HashMap::new(),
        }
    }

    /// Adds a new key-value pair in the topic configution.
    pub fn set(&mut self, key: &str, value: &str) -> &mut TopicConfig {
        self.conf_map.insert(key.to_string(), value.to_string());
        self
    }

    /// Finalizes the creation of the topic configuration. Useful at the end of a chain of setters,
    /// if you need to store the resulting topic configuration before its use.
    pub fn finalize(&self) -> TopicConfig {
        TopicConfig { conf_map: self.conf_map.clone() }
    }

    /// Creates a native rdkafka-sys topic configuration.
    pub fn create_native_config(&self) -> KafkaResult<*mut RDKafkaTopicConf> {
        let config_ptr = unsafe { rdkafka::rd_kafka_topic_conf_new() };
        let errstr = [0; ERR_LEN];
        for (name, value) in &self.conf_map {
            let name_c = try!(CString::new(name.to_string()));
            let value_c = try!(CString::new(value.to_string()));
            let ret = unsafe {
                rdkafka::rd_kafka_topic_conf_set(config_ptr, name_c.as_ptr(), value_c.as_ptr(),
                                                 errstr.as_ptr() as *mut i8, errstr.len())
            };
            if ret.is_error() {
                let descr = unsafe { bytes_cstr_to_owned(&errstr) };
                return Err(KafkaError::TopicConfig((ret, descr, name.to_string(), value.to_string())));
            }
        }
        Ok(config_ptr)
    }
}
<commit_msg>Change rdkafka prefix to librdkafka<commit_after>//! Configuration to create a Consumer or Producer.
extern crate rdkafka_sys as rdkafka;

use self::rdkafka::types::*;

use std::collections::HashMap;
use std::ffi::{CStr, CString};
use util::bytes_cstr_to_owned;

use error::{KafkaError, KafkaResult, IsError};
use client::Context;

const ERR_LEN: usize = 256;

unsafe extern "C" fn log_cb(_client: *const RDKafkaState, level: i32, _fac: *const i8, buf: *const i8) {
    let buf_str = CStr::from_ptr(buf).to_string_lossy();
    match level {
        0 => error!("librdkafka: {}", buf_str),
        1 => error!("librdkafka: {}", buf_str),
        2 => error!("librdkafka: {}", buf_str),
        3 => error!("librdkafka: {}", buf_str),
        4 => warn!("librdkafka: {}", buf_str),
        5 => info!("librdkafka: {}", buf_str),
        6 => info!("librdkafka: {}", buf_str),
        _ => debug!("librdkafka: {}", buf_str),
    }
}

/// Client configuration.
#[derive(Clone)]
pub struct ClientConfig {
    conf_map: HashMap<String, String>,
    default_topic_config: Option<TopicConfig>,
}

impl ClientConfig {
    /// Creates a new empty configuration.
    pub fn new() -> ClientConfig {
        ClientConfig {
            conf_map: HashMap::new(),
            default_topic_config: None,
        }
    }

    /// Sets a new parameter in the configuration.
    pub fn set<'a>(&'a mut self, key: &str, value: &str) -> &'a mut ClientConfig {
        self.conf_map.insert(key.to_string(), value.to_string());
        self
    }

    /// Sets the default topic configuration to use for automatically subscribed
    /// topics (e.g., through pattern-matched topics).
    pub fn set_default_topic_config<'a>(&'a mut self, default_topic_config: TopicConfig) -> &'a mut ClientConfig {
        self.default_topic_config = Some(default_topic_config);
        self
    }

    /// Returns the native rdkafka-sys configuration.
    pub fn create_native_config(&self) -> KafkaResult<*mut RDKafkaConf> {
        let conf = unsafe { rdkafka::rd_kafka_conf_new() };
        let errstr = [0; ERR_LEN];
        for (key, value) in &self.conf_map {
            let key_c = try!(CString::new(key.to_string()));
            let value_c = try!(CString::new(value.to_string()));
            let ret = unsafe {
                rdkafka::rd_kafka_conf_set(conf, key_c.as_ptr(), value_c.as_ptr(),
                                           errstr.as_ptr() as *mut i8, errstr.len())
            };
            if ret.is_error() {
                let descr = unsafe { bytes_cstr_to_owned(&errstr) };
                return Err(KafkaError::ClientConfig((ret, descr, key.to_string(), value.to_string())));
            }
        }
        if let Some(topic_config) = self.create_native_default_topic_config() {
            if let Err(e) = topic_config {
                return Err(e);
            } else {
                unsafe { rdkafka::rd_kafka_conf_set_default_topic_conf(conf, topic_config.unwrap()) };
            }
        }
        unsafe { rdkafka::rd_kafka_conf_set_log_cb(conf, Some(log_cb)) };
        Ok(conf)
    }

    fn create_native_default_topic_config(&self) -> Option<KafkaResult<*mut RDKafkaTopicConf>> {
        self.default_topic_config.as_ref().map(|c| c.create_native_config())
    }

    /// Uses the current configuration to create a new Consumer or Producer.
    pub fn create<T: FromClientConfig>(&self) -> KafkaResult<T> {
        T::from_config(self)
    }

    /// Uses the current configuration and the provided context to create a new Consumer or Producer.
    pub fn create_with_context<C, T>(&self, context: C) -> KafkaResult<T>
            where C: Context,
                  T: FromClientConfigAndContext<C> {
        T::from_config_and_context(self, context)
    }
}

/// Create a new client based on the provided configuration.
pub trait FromClientConfig: Sized {
    fn from_config(&ClientConfig) -> KafkaResult<Self>;
}

/// Create a new client based on the provided configuration and context.
pub trait FromClientConfigAndContext<C: Context>: Sized {
    fn from_config_and_context(&ClientConfig, C) -> KafkaResult<Self>;
}

/// Topic configuration.
#[derive(Clone)]
pub struct TopicConfig {
    conf_map: HashMap<String, String>,
}

impl TopicConfig {
    /// Returns a new TopicConfig for the specified topic name and client.
    pub fn new() -> TopicConfig {
        TopicConfig {
            conf_map: HashMap::new(),
        }
    }

    /// Adds a new key-value pair in the topic configution.
    pub fn set(&mut self, key: &str, value: &str) -> &mut TopicConfig {
        self.conf_map.insert(key.to_string(), value.to_string());
        self
    }

    /// Finalizes the creation of the topic configuration. Useful at the end of a chain of setters,
    /// if you need to store the resulting topic configuration before its use.
    pub fn finalize(&self) -> TopicConfig {
        TopicConfig { conf_map: self.conf_map.clone() }
    }

    /// Creates a native rdkafka-sys topic configuration.
    pub fn create_native_config(&self) -> KafkaResult<*mut RDKafkaTopicConf> {
        let config_ptr = unsafe { rdkafka::rd_kafka_topic_conf_new() };
        let errstr = [0; ERR_LEN];
        for (name, value) in &self.conf_map {
            let name_c = try!(CString::new(name.to_string()));
            let value_c = try!(CString::new(value.to_string()));
            let ret = unsafe {
                rdkafka::rd_kafka_topic_conf_set(config_ptr, name_c.as_ptr(), value_c.as_ptr(),
                                                 errstr.as_ptr() as *mut i8, errstr.len())
            };
            if ret.is_error() {
                let descr = unsafe { bytes_cstr_to_owned(&errstr) };
                return Err(KafkaError::TopicConfig((ret, descr, name.to_string(), value.to_string())));
            }
        }
        Ok(config_ptr)
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::io;
use std::path::{Path, PathBuf};
use toml;
use semver::Version;
use cargo_shim::CargoPackage;

use build::Backend;
use utils::read;
use error::Error;

fn is_all_strings( array: &[toml::Value] ) -> bool {
    array.iter().all( |element| element.is_str() )
}

fn from_string_or_array_of_strings( path_in_toml: &str, config: &Config, prepend_js: toml::Value ) -> Result< Vec< String >, Error > {
    match prepend_js {
        toml::Value::String( path ) => Ok( vec![ path ] ),
        toml::Value::Array( ref array ) if is_all_strings( &array ) => {
            Ok( array.iter().map( |value| value.clone().try_into().unwrap() ).collect() )
        },
        _ => {
            Err( format!(
                "{}: '{}' must be either a string or an array of strings",
                config.source(),
                path_in_toml
            ).into() )
        }
    }
}

#[derive(Debug, Default)]
pub struct PerTargetConfig {
    pub link_args: Option< Vec< String > >,
    pub prepend_js: Option< Vec< String > >
}

#[derive(Debug, Default)]
pub struct Config {
    crate_name: Option< String >,
    pub config_path: Option< PathBuf >,

    pub minimum_cargo_web_version: Option< Version >,
    pub per_target: HashMap< Backend, PerTargetConfig >
}

impl Config {
    pub fn source( &self ) -> String {
        if let Some( ref name ) = self.crate_name {
            format!( "`{}`'s Web.toml", name )
        } else if let Some( ref path ) = self.config_path {
            format!( "{:?}", path )
        } else {
            "Web.toml".into()
        }
    }

    pub fn get_link_args( &self, backend: Backend ) -> Option< &Vec< String > > {
        self.per_target.get( &backend ).and_then( |per_target| per_target.link_args.as_ref() )
    }

    pub fn get_prepend_js( &self, backend: Backend ) -> Option< &Vec< String > > {
        self.per_target.get( &backend ).and_then( |per_target| per_target.prepend_js.as_ref() )
    }
}

pub enum Warning {
    UnknownKey( String ),
    Deprecation( String, Option< String > )
}

fn add_link_args( config: &mut Config, backend: Backend, link_args: Vec< String > ) -> Result< (), Error > {
    {
        let per_target = config.per_target.entry( backend ).or_insert( Default::default() );
        if per_target.link_args.is_none() {
            per_target.link_args = Some( link_args.clone() );
            return Ok(());
        }
    }

    return Err( format!( "{}: you can't have multiple 'link-args' defined for a single target", config.source() ).into() );
}

fn add_prepend_js( config: &mut Config, backend: Backend, prepend_js: Vec< String > ) -> Result< (), Error > {
    {
        let per_target = config.per_target.entry( backend ).or_insert( Default::default() );
        if per_target.prepend_js.is_none() {
            per_target.prepend_js = Some( prepend_js );
            return Ok(());
        }
    }

    return Err( format!( "{}: you can't have multiple 'prepend-js' defined for a single target", config.source() ).into() );
}

const ALL_BACKENDS: &'static [Backend] = &[
    Backend::EmscriptenAsmJs,
    Backend::EmscriptenWebAssembly,
    Backend::WebAssembly
];

impl Config {
    pub fn load_from_file< P >(
            path: P,
            crate_name: Option< String >
        ) -> Result< Option< (Self, Vec< Warning >) >, Error > where P: AsRef< Path >
    {
        let path = path.as_ref();

        let mut config = Config::default();
        config.config_path = Some( path.into() );
        config.crate_name = crate_name.clone();

        let config_toml = match read( path ) {
            Ok( config ) => config,
            Err( error ) => {
                if error.kind() == io::ErrorKind::NotFound {
                    return Ok( None );
                } else {
                    return Err( format!( "cannot load {}: {}", config.source(), error ).into() );
                }
            }
        };

        debug!( "Loading {:?}...", path );

        let raw: toml::Value = toml::from_str( config_toml.as_str() ).unwrap();
        let mut warnings = Vec::new();

        // TODO: This is getting way too long. Split it into multiple functions.
        trace!( "Loaded config: {:#?}", raw );
        match raw {
            toml::Value::Table( table ) => {
                for (toplevel_key, toplevel_value) in table {
                    match toplevel_key.as_str() {
                        // TODO: Remove this in the future.
                        "link-args" => {
                            let link_args: Vec< String > =
                                toplevel_value.try_into().map_err( |_|
                                    format!( "{}: 'link-args' is not an array of strings", config.source()
                                ))?;

                            warnings.push( Warning::Deprecation(
                                "link-args".to_owned(),
                                Some( "it should be moved to the '[target.emscripten]' section".to_owned() )
                            ));

                            for backend in ALL_BACKENDS.iter().cloned() {
                                add_link_args( &mut config, backend, link_args.clone() )?;
                            }
                        },
                        "prepend-js" => {
                            let toplevel_value = from_string_or_array_of_strings( &toplevel_key, &config, toplevel_value )?;
                            for backend in ALL_BACKENDS.iter().cloned() {
                                add_prepend_js( &mut config, backend, toplevel_value.clone() )?;
                            }
                        },
                        "cargo-web" => {
                            let cargo_web_table: toml::value::Table =
                                toplevel_value.try_into()
                                .map_err( |_| format!( "{}: 'cargo-web' should be a section", config.source() ) )?;

                            for (cargo_web_key, cargo_web_value) in cargo_web_table {
                                match cargo_web_key.as_str() {
                                    "minimum-version" => {
                                        let version: String = cargo_web_value.try_into().map_err( |_| format!( "{}; 'cargo-web.minimum-version' is not a string", config.source() ) )?;
                                        let version = Version::parse( &version ).map_err( |_| format!( "{}: 'cargo-web.minimum-version' is not a valid version", config.source() ) )?;
                                        config.minimum_cargo_web_version = Some( version );
                                    },
                                    cargo_web_key => {
                                        warnings.push( Warning::UnknownKey( format!( "cargo-web.{}", cargo_web_key ) ) );
                                    }
                                }
                            }
                        },
                        "target" => {
                            let target_table: toml::value::Table =
                                toplevel_value.try_into()
                                .map_err( |_| format!( "{}: 'target' should be a section", config.source() ) )?;

                            for (target_key, target_value) in target_table {
                                let backends = match target_key.as_str() {
                                    "wasm32-unknown-unknown" => &[Backend::WebAssembly][..],
                                    "wasm32-unknown-emscripten" => &[Backend::EmscriptenWebAssembly][..],
                                    "asmjs-unknown-emscripten" => &[Backend::EmscriptenAsmJs][..],
                                    "emscripten" => &[Backend::EmscriptenWebAssembly, Backend::EmscriptenAsmJs][..],
                                    target_key => {
                                        warnings.push( Warning::UnknownKey( format!( "target.{}", target_key ) ) );
                                        continue;
                                    }
                                };

                                let target_subtable: toml::value::Table =
                                    target_value.try_into()
                                    .map_err( |_| format!( "{}: 'target.{}' should be a section", config.source(), target_key ) )?;

                                for (per_target_key, per_target_value) in target_subtable {
                                    let path_in_toml = format!( "target.{}.{}", target_key, per_target_key );
                                    match per_target_key.as_str() {
                                        "link-args" => {
                                            let link_args: Vec< String > =
                                                per_target_value.try_into().map_err( |_|
                                                    format!(
                                                        "{}: '{}' is not an array of strings",
                                                        config.source(),
                                                        path_in_toml
                                                    )
                                                )?;

                                            for backend in backends.iter().cloned() {
                                                add_link_args( &mut config, backend, link_args.clone() )?;
                                            }
                                        },
                                        "prepend-js" => {
                                            let per_target_value = from_string_or_array_of_strings( &path_in_toml, &config, per_target_value )?;
                                            for backend in backends.iter().cloned() {
                                                add_prepend_js( &mut config, backend, per_target_value.clone() )?;
                                            }
                                        },
                                        _ => {
                                            warnings.push( Warning::UnknownKey( path_in_toml ) );
                                        }
                                    }
                                }
                            }
                        },
                        toplevel_key => {
                            warnings.push( Warning::UnknownKey( toplevel_key.into() ) );
                        }
                    }
                }
            },
            _ => panic!()
        }

        Ok( Some( (config, warnings) ) )
    }

    pub fn load_for_package( package: &CargoPackage ) -> Result< Option< (Self, Vec< Warning >) >, Error > {
        let path = package.manifest_path.with_file_name( "Web.toml" );
        let config = match Config::load_from_file( path, Some( package.name.clone() ) )? {
            None => return Ok( None ),
            Some( config ) => config
        };

        Ok( Some( config ) )
    }

    pub fn load_for_package_printing_warnings( package: &CargoPackage ) -> Result< Option< Self >, Error > {
        let (config, warnings) = match Config::load_for_package( package )? {
            Some( (config, warnings) ) => (config, warnings),
            None => return Ok( None )
        };

        for warning in warnings {
            match warning {
                Warning::UnknownKey( key ) => {
                    eprintln!( "warning: unknown key in {}: {}", config.source(), key );
                },
                Warning::Deprecation( key, None ) => {
                    eprintln!( "warning: key in {} is deprecated: {}", config.source(), key );
                },
                Warning::Deprecation( key, Some( description ) ) => {
                    eprintln!( "warning: key in {} is deprecated: {} ({})", config.source(), key, description );
                }
            }
        }

        Ok( Some( config ) )
    }
}
<commit_msg>Fix a minor typo in one of the errors<commit_after>use std::collections::HashMap;
use std::io;
use std::path::{Path, PathBuf};
use toml;
use semver::Version;
use cargo_shim::CargoPackage;

use build::Backend;
use utils::read;
use error::Error;

fn is_all_strings( array: &[toml::Value] ) -> bool {
    array.iter().all( |element| element.is_str() )
}

fn from_string_or_array_of_strings( path_in_toml: &str, config: &Config, prepend_js: toml::Value ) -> Result< Vec< String >, Error > {
    match prepend_js {
        toml::Value::String( path ) => Ok( vec![ path ] ),
        toml::Value::Array( ref array ) if is_all_strings( &array ) => {
            Ok( array.iter().map( |value| value.clone().try_into().unwrap() ).collect() )
        },
        _ => {
            Err( format!(
                "{}: '{}' must be either a string or an array of strings",
                config.source(),
                path_in_toml
            ).into() )
        }
    }
}

#[derive(Debug, Default)]
pub struct PerTargetConfig {
    pub link_args: Option< Vec< String > >,
    pub prepend_js: Option< Vec< String > >
}

#[derive(Debug, Default)]
pub struct Config {
    crate_name: Option< String >,
    pub config_path: Option< PathBuf >,

    pub minimum_cargo_web_version: Option< Version >,
    pub per_target: HashMap< Backend, PerTargetConfig >
}

impl Config {
    pub fn source( &self ) -> String {
        if let Some( ref name ) = self.crate_name {
            format!( "`{}`'s Web.toml", name )
        } else if let Some( ref path ) = self.config_path {
            format!( "{:?}", path )
        } else {
            "Web.toml".into()
        }
    }

    pub fn get_link_args( &self, backend: Backend ) -> Option< &Vec< String > > {
        self.per_target.get( &backend ).and_then( |per_target| per_target.link_args.as_ref() )
    }

    pub fn get_prepend_js( &self, backend: Backend ) -> Option< &Vec< String > > {
        self.per_target.get( &backend ).and_then( |per_target| per_target.prepend_js.as_ref() )
    }
}

pub enum Warning {
    UnknownKey( String ),
    Deprecation( String, Option< String > )
}

fn add_link_args( config: &mut Config, backend: Backend, link_args: Vec< String > ) -> Result< (), Error > {
    {
        let per_target = config.per_target.entry( backend ).or_insert( Default::default() );
        if per_target.link_args.is_none() {
            per_target.link_args = Some( link_args.clone() );
            return Ok(());
        }
    }

    return Err( format!( "{}: you can't have multiple 'link-args' defined for a single target", config.source() ).into() );
}

fn add_prepend_js( config: &mut Config, backend: Backend, prepend_js: Vec< String > ) -> Result< (), Error > {
    {
        let per_target = config.per_target.entry( backend ).or_insert( Default::default() );
        if per_target.prepend_js.is_none() {
            per_target.prepend_js = Some( prepend_js );
            return Ok(());
        }
    }

    return Err( format!( "{}: you can't have multiple 'prepend-js' defined for a single target", config.source() ).into() );
}

const ALL_BACKENDS: &'static [Backend] = &[
    Backend::EmscriptenAsmJs,
    Backend::EmscriptenWebAssembly,
    Backend::WebAssembly
];

impl Config {
    pub fn load_from_file< P >(
            path: P,
            crate_name: Option< String >
        ) -> Result< Option< (Self, Vec< Warning >) >, Error > where P: AsRef< Path >
    {
        let path = path.as_ref();

        let mut config = Config::default();
        config.config_path = Some( path.into() );
        config.crate_name = crate_name.clone();

        let config_toml = match read( path ) {
            Ok( config ) => config,
            Err( error ) => {
                if error.kind() == io::ErrorKind::NotFound {
                    return Ok( None );
                } else {
                    return Err( format!( "cannot load {}: {}", config.source(), error ).into() );
                }
            }
        };

        debug!( "Loading {:?}...", path );

        let raw: toml::Value = toml::from_str( config_toml.as_str() ).unwrap();
        let mut warnings = Vec::new();

        // TODO: This is getting way too long. Split it into multiple functions.
        trace!( "Loaded config: {:#?}", raw );
        match raw {
            toml::Value::Table( table ) => {
                for (toplevel_key, toplevel_value) in table {
                    match toplevel_key.as_str() {
                        // TODO: Remove this in the future.
                        "link-args" => {
                            let link_args: Vec< String > =
                                toplevel_value.try_into().map_err( |_|
                                    format!( "{}: 'link-args' is not an array of strings", config.source()
                                ))?;

                            warnings.push( Warning::Deprecation(
                                "link-args".to_owned(),
                                Some( "it should be moved to the '[target.emscripten]' section".to_owned() )
                            ));

                            for backend in ALL_BACKENDS.iter().cloned() {
                                add_link_args( &mut config, backend, link_args.clone() )?;
                            }
                        },
                        "prepend-js" => {
                            let toplevel_value = from_string_or_array_of_strings( &toplevel_key, &config, toplevel_value )?;
                            for backend in ALL_BACKENDS.iter().cloned() {
                                add_prepend_js( &mut config, backend, toplevel_value.clone() )?;
                            }
                        },
                        "cargo-web" => {
                            let cargo_web_table: toml::value::Table =
                                toplevel_value.try_into()
                                .map_err( |_| format!( "{}: 'cargo-web' should be a section", config.source() ) )?;

                            for (cargo_web_key, cargo_web_value) in cargo_web_table {
                                match cargo_web_key.as_str() {
                                    "minimum-version" => {
                                        let version: String = cargo_web_value.try_into().map_err( |_| format!( "{}: 'cargo-web.minimum-version' is not a string", config.source() ) )?;
                                        let version = Version::parse( &version ).map_err( |_| format!( "{}: 'cargo-web.minimum-version' is not a valid version", config.source() ) )?;
                                        config.minimum_cargo_web_version = Some( version );
                                    },
                                    cargo_web_key => {
                                        warnings.push( Warning::UnknownKey( format!( "cargo-web.{}", cargo_web_key ) ) );
                                    }
                                }
                            }
                        },
                        "target" => {
                            let target_table: toml::value::Table =
                                toplevel_value.try_into()
                                .map_err( |_| format!( "{}: 'target' should be a section", config.source() ) )?;

                            for (target_key, target_value) in target_table {
                                let backends = match target_key.as_str() {
                                    "wasm32-unknown-unknown" => &[Backend::WebAssembly][..],
                                    "wasm32-unknown-emscripten" => &[Backend::EmscriptenWebAssembly][..],
                                    "asmjs-unknown-emscripten" => &[Backend::EmscriptenAsmJs][..],
                                    "emscripten" => &[Backend::EmscriptenWebAssembly, Backend::EmscriptenAsmJs][..],
                                    target_key => {
                                        warnings.push( Warning::UnknownKey( format!( "target.{}", target_key ) ) );
                                        continue;
                                    }
                                };

                                let target_subtable: toml::value::Table =
                                    target_value.try_into()
                                    .map_err( |_| format!( "{}: 'target.{}' should be a section", config.source(), target_key ) )?;

                                for (per_target_key, per_target_value) in target_subtable {
                                    let path_in_toml = format!( "target.{}.{}", target_key, per_target_key );
                                    match per_target_key.as_str() {
                                        "link-args" => {
                                            let link_args: Vec< String > =
                                                per_target_value.try_into().map_err( |_|
                                                    format!(
                                                        "{}: '{}' is not an array of strings",
                                                        config.source(),
                                                        path_in_toml
                                                    )
                                                )?;

                                            for backend in backends.iter().cloned() {
                                                add_link_args( &mut config, backend, link_args.clone() )?;
                                            }
                                        },
                                        "prepend-js" => {
                                            let per_target_value = from_string_or_array_of_strings( &path_in_toml, &config, per_target_value )?;
                                            for backend in backends.iter().cloned() {
                                                add_prepend_js( &mut config, backend, per_target_value.clone() )?;
                                            }
                                        },
                                        _ => {
                                            warnings.push( Warning::UnknownKey( path_in_toml ) );
                                        }
                                    }
                                }
                            }
                        },
                        toplevel_key => {
                            warnings.push( Warning::UnknownKey( toplevel_key.into() ) );
                        }
                    }
                }
            },
            _ => panic!()
        }

        Ok( Some( (config, warnings) ) )
    }

    pub fn load_for_package( package: &CargoPackage ) -> Result< Option< (Self, Vec< Warning >) >, Error > {
        let path = package.manifest_path.with_file_name( "Web.toml" );
        let config = match Config::load_from_file( path, Some( package.name.clone() ) )? {
            None => return Ok( None ),
            Some( config ) => config
        };

        Ok( Some( config ) )
    }

    pub fn load_for_package_printing_warnings( package: &CargoPackage ) -> Result< Option< Self >, Error > {
        let (config, warnings) = match Config::load_for_package( package )? {
            Some( (config, warnings) ) => (config, warnings),
            None => return Ok( None )
        };

        for warning in warnings {
            match warning {
                Warning::UnknownKey( key ) => {
                    eprintln!( "warning: unknown key in {}: {}", config.source(), key );
                },
                Warning::Deprecation( key, None ) => {
                    eprintln!( "warning: key in {} is deprecated: {}", config.source(), key );
                },
                Warning::Deprecation( key, Some( description ) ) => {
                    eprintln!( "warning: key in {} is deprecated: {} ({})", config.source(), key, description );
                }
            }
        }

        Ok( Some( config ) )
    }
}
<|endoftext|>


<commit_before>use scene::{BoxedScene, Scene, SceneChangeEvent, SceneName};
use engine::EngineData;
use text_renderer::TextRenderer;
use sdl2::pixels::{Color, PixelFormatEnum};
use sdl2::surface::Surface;
use std::io::Result;
use std::path::Path;
use uorustlibs::art::{ArtReader, Art};
use uorustlibs::hues::{HueReader, HueGroup, Hue};
use uorustlibs::color::Color as ColorTrait;
use uorustlibs::map::{MapReader, Block};

use std::io::{Error, };
use sdl2::render::{Renderer, Texture, TextureQuery};
use sdl2::rect::Rect;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;

pub struct MapScene {
    reader: Result<MapReader>,
    x: u32,
    y: u32,
    texture: Option<Texture>
}

impl MapScene {
    pub fn new<'a>(renderer: &mut Renderer, engine_data: &mut EngineData<'a>) -> BoxedScene<SceneName, EngineData<'a>> {
        let mut scene = Box::new(MapScene {
            reader: MapReader::new(&Path::new("./assets/map0.mul"), 768, 512),
            x: 0,
            y: 0,
            texture: None
        });
        scene.draw_page(renderer, engine_data);
        scene
    }

    pub fn draw_page(&mut self, renderer: &mut Renderer, engine_data: &mut EngineData) {
        let block = match self.reader {
            Ok(ref mut reader) => {
                reader.read_block_from_coordinates(self.x, self.y).ok()
            },
            _ => None
        };
        self.texture = match block {
            Some(block) => {
                let mut surface = Surface::new(1024, 768, PixelFormatEnum::RGBA8888).unwrap();
                let block_surface = self.draw_block(&block);
                block_surface.blit(None, &mut surface, Some(Rect::new(0, 0, block_surface.width(), block_surface.height())));
                Some(renderer.create_texture_from_surface(&surface).unwrap())
            },
            _ => None
        };
    }

    pub fn draw_block(&self, block: &Block) -> Surface {
        let mut surface = Surface::new(8, 8, PixelFormatEnum::RGBA8888).unwrap();
        surface.with_lock_mut(|bitmap| {
            let mut read_idx = 0;

            for y in 0..8 {
                for x in 0..8 {
                    let target = (x + (y * 8));
                    let height = (block.cells[target].altitude as i16 + 128) as u8;
                    bitmap[target * 4] = 255;
                    bitmap[target * 4 + 1] = height;
                    bitmap[target * 4 + 2] = height;
                    bitmap[target * 4 + 3] = height;
                }
            };
        });
        surface
    }
}

impl<'a> Scene<SceneName, EngineData<'a>> for MapScene {
    fn render(&self, renderer: &mut Renderer, engine_data: &mut EngineData) {
        renderer.clear();
        match self.texture {
            Some(ref texture) => {
                renderer.copy(texture, None, None).unwrap();
            },
            None => ()
        };
        renderer.present();
    }

    fn handle_event(&mut self, event: &Event, renderer: &mut Renderer, engine_data: &mut EngineData) -> Option<SceneChangeEvent<SceneName>> {
        match *event {
            Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                Some(SceneChangeEvent::PopScene)
            },
            Event::KeyDown { keycode: Some(Keycode::Left), .. } => {
                if self.x > 0 {
                    self.x -= 1;
                    self.draw_page(renderer, engine_data);
                }
                None
            },
            Event::KeyDown { keycode: Some(Keycode::Right), .. } => {
                self.x += 1;
                self.draw_page(renderer, engine_data);
                None
            },
            Event::KeyDown { keycode: Some(Keycode::Up), .. } => {
                if self.y > 0 {
                    self.y -= 1;
                    self.draw_page(renderer, engine_data);
                }
                None
            },
            Event::KeyDown { keycode: Some(Keycode::Down), .. } => {
                self.y += 1;
                self.draw_page(renderer, engine_data);
                None
            },
             _ => None
        }
    }
}
<commit_msg>Rendering larger lens<commit_after>use scene::{BoxedScene, Scene, SceneChangeEvent, SceneName};
use engine::EngineData;
use text_renderer::TextRenderer;
use sdl2::pixels::{Color, PixelFormatEnum};
use sdl2::surface::Surface;
use std::io::Result;
use std::path::Path;
use uorustlibs::art::{ArtReader, Art};
use uorustlibs::hues::{HueReader, HueGroup, Hue};
use uorustlibs::color::Color as ColorTrait;
use uorustlibs::map::{MapReader, Block};

use std::io::{Error, };
use sdl2::render::{Renderer, Texture, TextureQuery};
use sdl2::rect::Rect;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;

const MAX_BLOCKS_WIDTH: usize = 64;
const MAX_BLOCKS_HEIGHT: usize = 64;

pub struct MapScene {
    reader: Result<MapReader>,
    x: u32,
    y: u32,
    texture: Option<Texture>
}

impl MapScene {
    pub fn new<'a>(renderer: &mut Renderer, engine_data: &mut EngineData<'a>) -> BoxedScene<SceneName, EngineData<'a>> {
        let mut scene = Box::new(MapScene {
            reader: MapReader::new(&Path::new("./assets/map0.mul"), 768, 512),
            x: 0,
            y: 0,
            texture: None
        });
        scene.draw_page(renderer, engine_data);
        scene
    }

    pub fn draw_page(&mut self, renderer: &mut Renderer, engine_data: &mut EngineData) {
        let mut blocks = vec![];

        match self.reader {
            Ok(ref mut reader) => {

                for y in 0..MAX_BLOCKS_WIDTH {
                    for x in 0..MAX_BLOCKS_HEIGHT {
                        blocks.push(reader.read_block_from_coordinates(self.x + x as u32, self.y + y as u32));
                    }
                }
            },
            _ => ()
        };
        let mut surface = Surface::new(1024, 768, PixelFormatEnum::RGBA8888).unwrap();
        for y in 0..MAX_BLOCKS_HEIGHT {
            for x in 0..MAX_BLOCKS_WIDTH {
                match blocks[x + (y * 8)] {
                    Ok(ref block) => {
                        let block_surface = self.draw_block(block);
                        block_surface.blit(None, &mut surface, Some(Rect::new(x as i32 * 8, y as i32* 8, block_surface.width(), block_surface.height())));
                    },
                    _ => ()
                }
            }
        }
        self.texture = Some(renderer.create_texture_from_surface(&surface).unwrap());
    }

    pub fn draw_block(&self, block: &Block) -> Surface {
        let mut surface = Surface::new(8, 8, PixelFormatEnum::RGBA8888).unwrap();
        surface.with_lock_mut(|bitmap| {
            let mut read_idx = 0;

            for y in 0..8 {
                for x in 0..8 {
                    let target = (x + (y * 8));
                    let height = (block.cells[target].altitude as i16 + 128) as u8;
                    bitmap[target * 4] = 255;
                    bitmap[target * 4 + 1] = height;
                    bitmap[target * 4 + 2] = height;
                    bitmap[target * 4 + 3] = height;
                }
            };
        });
        surface
    }
}

impl<'a> Scene<SceneName, EngineData<'a>> for MapScene {
    fn render(&self, renderer: &mut Renderer, engine_data: &mut EngineData) {
        renderer.clear();
        match self.texture {
            Some(ref texture) => {
                renderer.copy(texture, None, None).unwrap();
            },
            None => ()
        };
        renderer.present();
    }

    fn handle_event(&mut self, event: &Event, renderer: &mut Renderer, engine_data: &mut EngineData) -> Option<SceneChangeEvent<SceneName>> {
        match *event {
            Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                Some(SceneChangeEvent::PopScene)
            },
            Event::KeyDown { keycode: Some(Keycode::Left), .. } => {
                if self.x > 0 {
                    self.x -= 1;
                    self.draw_page(renderer, engine_data);
                }
                None
            },
            Event::KeyDown { keycode: Some(Keycode::Right), .. } => {
                self.x += 1;
                self.draw_page(renderer, engine_data);
                None
            },
            Event::KeyDown { keycode: Some(Keycode::Up), .. } => {
                if self.y > 0 {
                    self.y -= 1;
                    self.draw_page(renderer, engine_data);
                }
                None
            },
            Event::KeyDown { keycode: Some(Keycode::Down), .. } => {
                self.y += 1;
                self.draw_page(renderer, engine_data);
                None
            },
             _ => None
        }
    }
}
<|endoftext|>


<commit_before>use super::methods::*;
use libp2p::core::{upgrade, InboundUpgrade, OutboundUpgrade, UpgradeInfo};
use ssz::{ssz_encode, Decodable, Encodable, SszStream};
use std::io;
use std::iter;
use tokio::io::{AsyncRead, AsyncWrite};

/// The maximum bytes that can be sent across the RPC.
const MAX_READ_SIZE: usize = 4_194_304; // 4M

/// Implementation of the `ConnectionUpgrade` for the rpc protocol.

#[derive(Debug, Clone)]
pub struct RPCProtocol;

impl UpgradeInfo for RPCProtocol {
    type Info = &'static [u8];
    type InfoIter = iter::Once<Self::Info>;

    #[inline]
    fn protocol_info(&self) -> Self::InfoIter {
        iter::once(b"/eth/serenity/rpc/1.0.0")
    }
}

impl Default for RPCProtocol {
    fn default() -> Self {
        RPCProtocol
    }
}

/// The RPC types which are sent/received in this protocol.
#[derive(Debug, Clone)]
pub enum RPCEvent {
    Request {
        id: u64,
        method_id: u16,
        body: RPCRequest,
    },
    Response {
        id: u64,
        method_id: u16, //TODO: Remove and process decoding upstream
        result: RPCResponse,
    },
}

impl UpgradeInfo for RPCEvent {
    type Info = &'static [u8];
    type InfoIter = iter::Once<Self::Info>;

    #[inline]
    fn protocol_info(&self) -> Self::InfoIter {
        iter::once(b"/eth/serenity/rpc/1.0.0")
    }
}

impl<TSocket> InboundUpgrade<TSocket> for RPCProtocol
where
    TSocket: AsyncRead + AsyncWrite,
{
    type Output = RPCEvent;
    type Error = DecodeError;
    type Future =
        upgrade::ReadOneThen<TSocket, (), fn(Vec<u8>, ()) -> Result<RPCEvent, DecodeError>>;

    fn upgrade_inbound(self, socket: TSocket, _: Self::Info) -> Self::Future {
        upgrade::read_one_then(socket, MAX_READ_SIZE, (), |packet, ()| Ok(decode(packet)?))
    }
}

fn decode(packet: Vec<u8>) -> Result<RPCEvent, DecodeError> {
    // decode the header of the rpc
    // request/response
    let (request, index) = bool::ssz_decode(&packet, 0)?;
    let (id, index) = u64::ssz_decode(&packet, index)?;
    let (method_id, index) = u16::ssz_decode(&packet, index)?;

    if request {
        let body = match RPCMethod::from(method_id) {
            RPCMethod::Hello => {
                let (hello_body, _index) = HelloMessage::ssz_decode(&packet, index)?;
                RPCRequest::Hello(hello_body)
            }
            RPCMethod::Goodbye => {
                let (goodbye_code, _index) = u64::ssz_decode(&packet, index)?;
                RPCRequest::Goodbye(goodbye_code)
            }
            RPCMethod::BeaconBlockRoots => {
                let (block_roots_request, _index) =
                    BeaconBlockRootsRequest::ssz_decode(&packet, index)?;
                RPCRequest::BeaconBlockRoots(block_roots_request)
            }
            RPCMethod::Unknown | _ => return Err(DecodeError::UnknownRPCMethod),
        };

        Ok(RPCEvent::Request {
            id,
            method_id,
            body,
        })
    }
    // we have received a response
    else {
        let result = match RPCMethod::from(method_id) {
            RPCMethod::Hello => {
                let (body, _index) = HelloMessage::ssz_decode(&packet, index)?;
                RPCResponse::Hello(body)
            }
            RPCMethod::Goodbye => unreachable!("Should never receive a goodbye response"),
            RPCMethod::BeaconBlockRoots => {
                let (body, _index) = BeaconBlockRootsResponse::ssz_decode(&packet, index)?;
                RPCResponse::BeaconBlockRoots(body)
            }
            RPCMethod::Unknown | _ => return Err(DecodeError::UnknownRPCMethod),
        };
        Ok(RPCEvent::Response {
            id,
            method_id,
            result,
        })
    }
}

impl<TSocket> OutboundUpgrade<TSocket> for RPCEvent
where
    TSocket: AsyncWrite,
{
    type Output = ();
    type Error = io::Error;
    type Future = upgrade::WriteOne<TSocket>;

    #[inline]
    fn upgrade_outbound(self, socket: TSocket, _: Self::Info) -> Self::Future {
        let bytes = ssz_encode(&self);
        upgrade::write_one(socket, bytes)
    }
}

impl Encodable for RPCEvent {
    fn ssz_append(&self, s: &mut SszStream) {
        match self {
            RPCEvent::Request {
                id,
                method_id,
                body,
            } => {
                s.append(&true);
                s.append(id);
                s.append(method_id);
                match body {
                    RPCRequest::Hello(body) => {
                        s.append(body);
                    }
                    _ => {}
                }
            }
            RPCEvent::Response {
                id,
                method_id,
                result,
            } => {
                s.append(&false);
                s.append(id);
                s.append(method_id);
                match result {
                    RPCResponse::Hello(response) => {
                        s.append(response);
                    }
                    _ => {}
                }
            }
        }
    }
}

#[derive(Debug)]
pub enum DecodeError {
    ReadError(upgrade::ReadOneError),
    SSZDecodeError(ssz::DecodeError),
    UnknownRPCMethod,
}

impl From<upgrade::ReadOneError> for DecodeError {
    #[inline]
    fn from(err: upgrade::ReadOneError) -> Self {
        DecodeError::ReadError(err)
    }
}

impl From<ssz::DecodeError> for DecodeError {
    #[inline]
    fn from(err: ssz::DecodeError) -> Self {
        DecodeError::SSZDecodeError(err)
    }
}
<commit_msg>Implement BeaconBlockHeaders RPC method<commit_after>use super::methods::*;
use libp2p::core::{upgrade, InboundUpgrade, OutboundUpgrade, UpgradeInfo};
use ssz::{ssz_encode, Decodable, Encodable, SszStream};
use std::io;
use std::iter;
use tokio::io::{AsyncRead, AsyncWrite};

/// The maximum bytes that can be sent across the RPC.
const MAX_READ_SIZE: usize = 4_194_304; // 4M

/// Implementation of the `ConnectionUpgrade` for the rpc protocol.

#[derive(Debug, Clone)]
pub struct RPCProtocol;

impl UpgradeInfo for RPCProtocol {
    type Info = &'static [u8];
    type InfoIter = iter::Once<Self::Info>;

    #[inline]
    fn protocol_info(&self) -> Self::InfoIter {
        iter::once(b"/eth/serenity/rpc/1.0.0")
    }
}

impl Default for RPCProtocol {
    fn default() -> Self {
        RPCProtocol
    }
}

/// The RPC types which are sent/received in this protocol.
#[derive(Debug, Clone)]
pub enum RPCEvent {
    Request {
        id: u64,
        method_id: u16,
        body: RPCRequest,
    },
    Response {
        id: u64,
        method_id: u16, //TODO: Remove and process decoding upstream
        result: RPCResponse,
    },
}

impl UpgradeInfo for RPCEvent {
    type Info = &'static [u8];
    type InfoIter = iter::Once<Self::Info>;

    #[inline]
    fn protocol_info(&self) -> Self::InfoIter {
        iter::once(b"/eth/serenity/rpc/1.0.0")
    }
}

impl<TSocket> InboundUpgrade<TSocket> for RPCProtocol
where
    TSocket: AsyncRead + AsyncWrite,
{
    type Output = RPCEvent;
    type Error = DecodeError;
    type Future =
        upgrade::ReadOneThen<TSocket, (), fn(Vec<u8>, ()) -> Result<RPCEvent, DecodeError>>;

    fn upgrade_inbound(self, socket: TSocket, _: Self::Info) -> Self::Future {
        upgrade::read_one_then(socket, MAX_READ_SIZE, (), |packet, ()| Ok(decode(packet)?))
    }
}

fn decode(packet: Vec<u8>) -> Result<RPCEvent, DecodeError> {
    // decode the header of the rpc
    // request/response
    let (request, index) = bool::ssz_decode(&packet, 0)?;
    let (id, index) = u64::ssz_decode(&packet, index)?;
    let (method_id, index) = u16::ssz_decode(&packet, index)?;

    if request {
        let body = match RPCMethod::from(method_id) {
            RPCMethod::Hello => {
                let (hello_body, _index) = HelloMessage::ssz_decode(&packet, index)?;
                RPCRequest::Hello(hello_body)
            }
            RPCMethod::Goodbye => {
                let (goodbye_code, _index) = u64::ssz_decode(&packet, index)?;
                RPCRequest::Goodbye(goodbye_code)
            }
            RPCMethod::BeaconBlockRoots => {
                let (block_roots_request, _index) =
                    BeaconBlockRootsRequest::ssz_decode(&packet, index)?;
                RPCRequest::BeaconBlockRoots(block_roots_request)
            }
            RPCMethod::BeaconBlockHeaders => {
                let (block_headers_request, _index) =
                    BeaconBlockHeadersRequest::ssz_decode(&packet, index)?;
                RPCRequest::BeaconBlockHeaders(block_headers_request)
            }
            RPCMethod::Unknown | _ => return Err(DecodeError::UnknownRPCMethod),
        };

        Ok(RPCEvent::Request {
            id,
            method_id,
            body,
        })
    }
    // we have received a response
    else {
        let result = match RPCMethod::from(method_id) {
            RPCMethod::Hello => {
                let (body, _index) = HelloMessage::ssz_decode(&packet, index)?;
                RPCResponse::Hello(body)
            }
            RPCMethod::Goodbye => unreachable!("Should never receive a goodbye response"),
            RPCMethod::BeaconBlockRoots => {
                let (body, _index) = BeaconBlockRootsResponse::ssz_decode(&packet, index)?;
                RPCResponse::BeaconBlockRoots(body)
            }
            RPCMethod::BeaconBlockHeaders => {
                let (body, _index) = BeaconBlockHeadersResponse::ssz_decode(&packet, index)?;
                RPCResponse::BeaconBlockHeaders(body)
            }
            RPCMethod::Unknown | _ => return Err(DecodeError::UnknownRPCMethod),
        };
        Ok(RPCEvent::Response {
            id,
            method_id,
            result,
        })
    }
}

impl<TSocket> OutboundUpgrade<TSocket> for RPCEvent
where
    TSocket: AsyncWrite,
{
    type Output = ();
    type Error = io::Error;
    type Future = upgrade::WriteOne<TSocket>;

    #[inline]
    fn upgrade_outbound(self, socket: TSocket, _: Self::Info) -> Self::Future {
        let bytes = ssz_encode(&self);
        upgrade::write_one(socket, bytes)
    }
}

impl Encodable for RPCEvent {
    fn ssz_append(&self, s: &mut SszStream) {
        match self {
            RPCEvent::Request {
                id,
                method_id,
                body,
            } => {
                s.append(&true);
                s.append(id);
                s.append(method_id);
                match body {
                    RPCRequest::Hello(body) => {
                        s.append(body);
                    }
                    _ => {}
                }
            }
            RPCEvent::Response {
                id,
                method_id,
                result,
            } => {
                s.append(&false);
                s.append(id);
                s.append(method_id);
                match result {
                    RPCResponse::Hello(response) => {
                        s.append(response);
                    }
                    _ => {}
                }
            }
        }
    }
}

#[derive(Debug)]
pub enum DecodeError {
    ReadError(upgrade::ReadOneError),
    SSZDecodeError(ssz::DecodeError),
    UnknownRPCMethod,
}

impl From<upgrade::ReadOneError> for DecodeError {
    #[inline]
    fn from(err: upgrade::ReadOneError) -> Self {
        DecodeError::ReadError(err)
    }
}

impl From<ssz::DecodeError> for DecodeError {
    #[inline]
    fn from(err: ssz::DecodeError) -> Self {
        DecodeError::SSZDecodeError(err)
    }
}
<|endoftext|>


<commit_before>pub mod operation {
    use std::str::FromStr;

    #[derive(Debug)]
    enum OperationSource {
        UNKNOWN(String),
        SOAP,
        REST,
        WEBSITE,
        BATCH
    }

    impl OperationSource {
        fn from_str(data: &str) -> OperationSource {
            match data {
                "SOAP" => OperationSource::SOAP,
                "REST" => OperationSource::REST,
                "WEBSITE" => OperationSource::WEBSITE,
                "BATCH" => OperationSource::BATCH,
                _ => OperationSource::UNKNOWN(data.to_string())
            }
        }
    }

    #[derive(Debug)]
    enum OperationMethod {
        UNKNOWN(String),
        GET,
        PUT,
        DELETE
    }

    impl OperationMethod {
        fn from_str(data: &str) -> OperationMethod {
            match data {
                "GET" => OperationMethod::GET,
                "PUT" => OperationMethod::PUT,
                "DELETE" => OperationMethod::DELETE,
                _ => OperationMethod::UNKNOWN(data.to_string())
            }
        }
    }

    #[derive(Debug)]
    enum OperationResourceType {
        UNKNOWN(String),
        OBJECT
    }

    impl OperationResourceType {
        fn from_str(data: &str) -> OperationResourceType {
            match data {
                "OBJECT" => OperationResourceType::OBJECT,
                _ => OperationResourceType::UNKNOWN(data.to_string())
            }
        }
    }

    #[derive(Debug)]
    pub struct Operation {
        source: OperationSource,
        method: OperationMethod,
        resource_type: OperationResourceType
    }

    impl FromStr for Operation {
        type Err = &'static str;

        fn from_str(data: &str) -> Result<Operation, &'static str> {
            let mut parts = data.split(".");
            let source_option = parts.next();
            let method_option = parts.next();
            let resource_type_option = parts.next();

            let source = match source_option {
                Some(s) => s,
                None => return Err("Unable to find source")
            };

            let method = match method_option {
                Some(s) => s,
                None => return Err("Unable to find match")
            };

            let resource_type = match resource_type_option {
                Some(s) => s,
                None => return Err("Unable to find resource type")
            };

            Ok(Operation {
                source: OperationSource::from_str(source),
                method: OperationMethod::from_str(method),
                resource_type: OperationResourceType::from_str(resource_type)
            })
        }
    }
}
<commit_msg>Allow operations to be compared<commit_after>pub mod operation {
    use std::str::FromStr;

    #[derive(Debug,PartialEq)]
    pub enum OperationSource {
        UNKNOWN(String),
        SOAP,
        REST,
        WEBSITE,
        BATCH
    }

    impl OperationSource {
        fn from_str(data: &str) -> OperationSource {
            match data {
                "SOAP" => OperationSource::SOAP,
                "REST" => OperationSource::REST,
                "WEBSITE" => OperationSource::WEBSITE,
                "BATCH" => OperationSource::BATCH,
                _ => OperationSource::UNKNOWN(data.to_string())
            }
        }
    }

    #[derive(Debug,PartialEq)]
    pub enum OperationMethod {
        UNKNOWN(String),
        GET,
        PUT,
        DELETE
    }

    impl OperationMethod {
        fn from_str(data: &str) -> OperationMethod {
            match data {
                "GET" => OperationMethod::GET,
                "PUT" => OperationMethod::PUT,
                "DELETE" => OperationMethod::DELETE,
                _ => OperationMethod::UNKNOWN(data.to_string())
            }
        }
    }

    #[derive(Debug,PartialEq)]
    pub enum OperationResourceType {
        UNKNOWN(String),
        OBJECT
    }

    impl OperationResourceType {
        fn from_str(data: &str) -> OperationResourceType {
            match data {
                "OBJECT" => OperationResourceType::OBJECT,
                _ => OperationResourceType::UNKNOWN(data.to_string())
            }
        }
    }

    #[derive(Debug)]
    pub struct Operation {
        pub source: OperationSource,
        pub method: OperationMethod,
        pub resource_type: OperationResourceType
    }

    impl Default for Operation {
        fn default() -> Operation {
            Operation {
                source: OperationSource::BATCH,
                method: OperationMethod::GET,
                resource_type: OperationResourceType::OBJECT
            }
        }
    }

    impl FromStr for Operation {
        type Err = &'static str;

        fn from_str(data: &str) -> Result<Operation, &'static str> {
            let mut parts = data.split(".");
            let source_option = parts.next();
            let method_option = parts.next();
            let resource_type_option = parts.next();

            let source = match source_option {
                Some(s) => s,
                None => return Err("Unable to find source")
            };

            let method = match method_option {
                Some(s) => s,
                None => return Err("Unable to find match")
            };

            let resource_type = match resource_type_option {
                Some(s) => s,
                None => return Err("Unable to find resource type")
            };

            Ok(Operation {
                source: OperationSource::from_str(source),
                method: OperationMethod::from_str(method),
                resource_type: OperationResourceType::from_str(resource_type)
            })
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;

use structs::{Op, OpStream};
use structs::Op::*;

impl OpStream {
    pub fn optimize(&mut self) {
        let mut i = 0;
        while i < self.ops.len() {
            match &self.ops[i..] {
                [Add(a), Add(b), ..] => {
                    self.ops[i] = Add(a.wrapping_add(b));
                    self.ops.remove(i + 1);
                }
                [Mov(a), Mov(b), ..] => {
                    self.ops[i] = Mov(a + b);
                    self.ops.remove(i + 1);
                }
                [Add(0), ..] | [Mov(0), ..] => {
                    self.ops.remove(i);
                    if i > 0 {
                        i -= 1;
                    }
                }
                [Loop(_), ..] => {
                    let maybe_new_op;

                    if let &mut Loop(ref mut stream) = &mut self.ops[i] {
                        stream.optimize();
                        maybe_new_op = stream.find_alternative();
                    } else {
                        unreachable!()
                    }

                    if let Some(new_op) = maybe_new_op {
                        self.ops[i] = new_op;
                    }

                    i += 1
                }
                _ => i += 1,
            }
        }
    }

    fn find_alternative(&self) -> Option<Op> {
        let mut map: BTreeMap<isize, u8> = BTreeMap::new();
        let mut rel_index = 0;

        for op in &self.ops[..] {
            match *op {
                Add(x) => {
                    let new_val = map.get(&rel_index).unwrap_or(&0).wrapping_add(x);
                    map.insert(rel_index, new_val);
                }
                Mov(x) => {
                    rel_index += x;
                }
                _ => {
                    return None;
                }
            }
        }

        if rel_index != 0 {
            return None;
        }

        Some(Transfer(map.remove(&0).unwrap_or(0), map.into_iter().collect()))
    }
}

#[cfg(test)]
mod tests {
    use structs::OpStream;
    use structs::Op::*;

    #[test]
    fn test_opstream_optimize() {
        let mut opstream = OpStream {
            ops: vec![Mov(1),
                      Mov(1),
                      Add(0x01),
                      Add(0x0ff),
                      Add(0x0ff),
                      Mov(1),
                      Mov(-1),
                      Loop(OpStream { ops: vec![Mov(2), Mov(3)] })],
        };
        opstream.optimize();

        assert_eq!(opstream,
                   OpStream { ops: vec![Mov(2), Add(0xff), Loop(OpStream { ops: vec![Mov(5)] })] });
    }

    #[test]
    fn test_opstream_optimize_transfer() {
        let mut opstream = OpStream {
            ops: vec![Loop(OpStream { ops: vec![Add(0x01), Mov(3), Add(0xff), Mov(-3)] })],
        };
        opstream.optimize();

        assert_eq!(opstream,
                   OpStream { ops: vec![Transfer(1, vec![(3, 255)])] });
    }
}
<commit_msg>chore: adjust to rust slice matching changes<commit_after>use std::collections::BTreeMap;

use structs::{Op, OpStream};
use structs::Op::*;

impl OpStream {
    pub fn optimize(&mut self) {
        let mut i = 0;
        while i < self.ops.len() {
            match &self.ops[i..] {
                &[Add(a), Add(b), ..] => {
                    self.ops[i] = Add(a.wrapping_add(b));
                    self.ops.remove(i + 1);
                }
                &[Mov(a), Mov(b), ..] => {
                    self.ops[i] = Mov(a + b);
                    self.ops.remove(i + 1);
                }
                &[Add(0), ..] | &[Mov(0), ..] => {
                    self.ops.remove(i);
                    if i > 0 {
                        i -= 1;
                    }
                }
                &[Loop(_), ..] => {
                    let maybe_new_op;

                    if let &mut Loop(ref mut stream) = &mut self.ops[i] {
                        stream.optimize();
                        maybe_new_op = stream.find_alternative();
                    } else {
                        unreachable!()
                    }

                    if let Some(new_op) = maybe_new_op {
                        self.ops[i] = new_op;
                    }

                    i += 1
                }
                _ => i += 1,
            }
        }
    }

    fn find_alternative(&self) -> Option<Op> {
        let mut map: BTreeMap<isize, u8> = BTreeMap::new();
        let mut rel_index = 0;

        for op in &self.ops[..] {
            match *op {
                Add(x) => {
                    let new_val = map.get(&rel_index).unwrap_or(&0).wrapping_add(x);
                    map.insert(rel_index, new_val);
                }
                Mov(x) => {
                    rel_index += x;
                }
                _ => {
                    return None;
                }
            }
        }

        if rel_index != 0 {
            return None;
        }

        Some(Transfer(map.remove(&0).unwrap_or(0), map.into_iter().collect()))
    }
}

#[cfg(test)]
mod tests {
    use structs::OpStream;
    use structs::Op::*;

    #[test]
    fn test_opstream_optimize() {
        let mut opstream = OpStream {
            ops: vec![Mov(1),
                      Mov(1),
                      Add(0x01),
                      Add(0x0ff),
                      Add(0x0ff),
                      Mov(1),
                      Mov(-1),
                      Loop(OpStream { ops: vec![Mov(2), Mov(3)] })],
        };
        opstream.optimize();

        assert_eq!(opstream,
                   OpStream { ops: vec![Mov(2), Add(0xff), Loop(OpStream { ops: vec![Mov(5)] })] });
    }

    #[test]
    fn test_opstream_optimize_transfer() {
        let mut opstream = OpStream {
            ops: vec![Loop(OpStream { ops: vec![Add(0x01), Mov(3), Add(0xff), Mov(-3)] })],
        };
        opstream.optimize();

        assert_eq!(opstream,
                   OpStream { ops: vec![Transfer(1, vec![(3, 255)])] });
    }
}
<|endoftext|>


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

use texturegl::Texture;
use tiling::TileGrid;

use geom::matrix::{Matrix4, identity};
use geom::size::Size2D;
use geom::rect::Rect;
use platform::surface::{NativePaintingGraphicsContext, NativeSurfaceMethods, NativeSurface};
use std::cell::{RefCell, RefMut};
use std::rc::Rc;

pub enum Format {
    ARGB32Format,
    RGB24Format
}

pub struct Layer<T> {
    pub children: RefCell<Vec<Rc<Layer<T>>>>,
    pub tiles: RefCell<Vec<Rc<TextureLayer>>>,
    pub transform: RefCell<Matrix4<f32>>,
    pub bounds: RefCell<Rect<f32>>,
    tile_size: uint,
    pub extra_data: RefCell<T>,
    tile_grid: RefCell<TileGrid>,
}

impl<T> Layer<T> {
    pub fn new(bounds: Rect<f32>, tile_size: uint, data: T) -> Layer<T> {
        Layer {
            children: RefCell::new(vec!()),
            tiles: RefCell::new(vec!()),
            transform: RefCell::new(identity()),
            bounds: RefCell::new(bounds),
            tile_size: tile_size,
            extra_data: RefCell::new(data),
            tile_grid: RefCell::new(TileGrid::new(tile_size)),
        }
    }

    pub fn children<'a>(&'a self) -> RefMut<'a,Vec<Rc<Layer<T>>>> {
        self.children.borrow_mut()
    }

    pub fn add_child(this: Rc<Layer<T>>, new_child: Rc<Layer<T>>) {
        this.children().push(new_child);
    }

    pub fn tile_size(this: Rc<Layer<T>>) -> uint {
        this.tile_size
    }

    pub fn get_tile_rects_page(this: Rc<Layer<T>>, window: Rect<f32>, scale: f32) -> (Vec<BufferRequest>, Vec<Box<LayerBuffer>>) {
        let mut tile_grid = this.tile_grid.borrow_mut();
        (tile_grid.get_buffer_requests_in_rect(window, scale), tile_grid.take_unused_tiles())
    }

    pub fn resize(this: Rc<Layer<T>>, new_size: Size2D<f32>) {
        this.bounds.borrow_mut().size = new_size;
    }

    pub fn do_for_all_tiles(this: Rc<Layer<T>>, f: |&Box<LayerBuffer>|) {
        this.tile_grid.borrow().do_for_all_tiles(f);
    }

    pub fn add_tile_pixel(this: Rc<Layer<T>>, tile: Box<LayerBuffer>) {
        this.tile_grid.borrow_mut().add_tile(tile);
    }

    pub fn collect_unused_tiles(this: Rc<Layer<T>>) -> Vec<Box<LayerBuffer>> {
        this.tile_grid.borrow_mut().take_unused_tiles()
    }

    pub fn collect_tiles(this: Rc<Layer<T>>) -> Vec<Box<LayerBuffer>> {
        this.tile_grid.borrow_mut().collect_tiles()
    }

    pub fn flush_pending_buffer_requests(&self) -> (Vec<BufferRequest>, f32) {
        self.tile_grid.borrow_mut().flush_pending_buffer_requests()
    }

    pub fn contents_changed(&self) {
        self.tile_grid.borrow_mut().contents_changed()
    }
}

/// Whether a texture should be flipped.
#[deriving(PartialEq)]
pub enum Flip {
    /// The texture should not be flipped.
    NoFlip,
    /// The texture should be flipped vertically.
    VerticalFlip,
}

pub struct TextureLayer {
    /// A handle to the GPU texture.
    pub texture: Texture,
    /// The size of the texture in pixels.
    size: Size2D<uint>,
    /// Whether this texture is flipped vertically.
    pub flip: Flip,

    pub transform: Matrix4<f32>,
}

impl TextureLayer {
    pub fn new(texture: Texture, size: Size2D<uint>, flip: Flip, transform: Matrix4<f32>) -> TextureLayer {
        TextureLayer {
            texture: texture,
            size: size,
            flip: flip,
            transform: transform,
        }
    }
}

/// A request from the compositor to the renderer for tiles that need to be (re)displayed.
#[deriving(Clone)]
pub struct BufferRequest {
    // The rect in pixels that will be drawn to the screen
    pub screen_rect: Rect<uint>,

    // The rect in page coordinates that this tile represents
    pub page_rect: Rect<f32>,
}

impl BufferRequest {
    pub fn new(screen_rect: Rect<uint>, page_rect: Rect<f32>) -> BufferRequest {
        BufferRequest {
            screen_rect: screen_rect,
            page_rect: page_rect,
        }
    }
}

pub struct LayerBuffer {
    /// The native surface which can be shared between threads or processes. On Mac this is an
    /// `IOSurface`; on Linux this is an X Pixmap; on Android this is an `EGLImageKHR`.
    pub native_surface: NativeSurface,

    /// The rect in the containing RenderLayer that this represents.
    pub rect: Rect<f32>,

    /// The rect in pixels that will be drawn to the screen.
    pub screen_pos: Rect<uint>,

    /// The scale at which this tile is rendered
    pub resolution: f32,

    /// NB: stride is in pixels, like OpenGL GL_UNPACK_ROW_LENGTH.
    pub stride: uint,
}

/// A set of layer buffers. This is an atomic unit used to switch between the front and back
/// buffers.
pub struct LayerBufferSet {
    pub buffers: Vec<Box<LayerBuffer>>
}

impl LayerBufferSet {
    /// Notes all buffer surfaces will leak if not destroyed via a call to `destroy`.
    pub fn mark_will_leak(&mut self) {
        for buffer in self.buffers.mut_iter() {
            buffer.native_surface.mark_will_leak()
        }
    }
}

/// The interface used by the BufferMap to get info about layer buffers.
pub trait Tile {
    /// Returns the amount of memory used by the tile
    fn get_mem(&self) -> uint;

    /// Returns true if the tile is displayable at the given scale
    fn is_valid(&self, f32) -> bool;

    /// Returns the Size2D of the tile
    fn get_size_2d(&self) -> Size2D<uint>;

    /// Marks the layer buffer as not leaking. See comments on
    /// `NativeSurfaceMethods::mark_wont_leak` for how this is used.
    fn mark_wont_leak(&mut self);

    /// Destroys the layer buffer. Painting task only.
    fn destroy(self, graphics_context: &NativePaintingGraphicsContext);
}

impl Tile for Box<LayerBuffer> {
    fn get_mem(&self) -> uint {
        // This works for now, but in the future we may want a better heuristic
        self.screen_pos.size.width * self.screen_pos.size.height
    }
    fn is_valid(&self, scale: f32) -> bool {
        (self.resolution - scale).abs() < 1.0e-6
    }
    fn get_size_2d(&self) -> Size2D<uint> {
        self.screen_pos.size
    }
    fn mark_wont_leak(&mut self) {
        self.native_surface.mark_wont_leak()
    }
    fn destroy(self, graphics_context: &NativePaintingGraphicsContext) {
        let mut this = self;
        this.native_surface.destroy(graphics_context)
    }
}

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

use texturegl::Texture;
use tiling::TileGrid;

use geom::matrix::{Matrix4, identity};
use geom::size::Size2D;
use geom::rect::Rect;
use platform::surface::{NativePaintingGraphicsContext, NativeSurfaceMethods, NativeSurface};
use std::cell::{RefCell, RefMut};
use std::rc::Rc;

pub enum Format {
    ARGB32Format,
    RGB24Format
}

pub struct Layer<T> {
    pub children: RefCell<Vec<Rc<Layer<T>>>>,
    pub tiles: RefCell<Vec<Rc<TextureLayer>>>,
    pub transform: RefCell<Matrix4<f32>>,
    pub bounds: RefCell<Rect<f32>>,
    pub tile_size: uint,
    pub extra_data: RefCell<T>,
    tile_grid: RefCell<TileGrid>,
}

impl<T> Layer<T> {
    pub fn new(bounds: Rect<f32>, tile_size: uint, data: T) -> Layer<T> {
        Layer {
            children: RefCell::new(vec!()),
            tiles: RefCell::new(vec!()),
            transform: RefCell::new(identity()),
            bounds: RefCell::new(bounds),
            tile_size: tile_size,
            extra_data: RefCell::new(data),
            tile_grid: RefCell::new(TileGrid::new(tile_size)),
        }
    }

    pub fn children<'a>(&'a self) -> RefMut<'a,Vec<Rc<Layer<T>>>> {
        self.children.borrow_mut()
    }

    pub fn add_child(&self, new_child: Rc<Layer<T>>) {
        self.children().push(new_child);
    }

    pub fn get_tile_rects_page(&self, window: Rect<f32>, scale: f32) -> (Vec<BufferRequest>, Vec<Box<LayerBuffer>>) {
        let mut tile_grid = self.tile_grid.borrow_mut();
        (tile_grid.get_buffer_requests_in_rect(window, scale), tile_grid.take_unused_tiles())
    }

    pub fn resize(&self, new_size: Size2D<f32>) {
        self.bounds.borrow_mut().size = new_size;
    }

    pub fn do_for_all_tiles(&self, f: |&Box<LayerBuffer>|) {
        self.tile_grid.borrow().do_for_all_tiles(f);
    }

    pub fn add_tile_pixel(&self, tile: Box<LayerBuffer>) {
        self.tile_grid.borrow_mut().add_tile(tile);
    }

    pub fn collect_unused_tiles(&self) -> Vec<Box<LayerBuffer>> {
        self.tile_grid.borrow_mut().take_unused_tiles()
    }

    pub fn collect_tiles(&self) -> Vec<Box<LayerBuffer>> {
        self.tile_grid.borrow_mut().collect_tiles()
    }

    pub fn flush_pending_buffer_requests(&self) -> (Vec<BufferRequest>, f32) {
        self.tile_grid.borrow_mut().flush_pending_buffer_requests()
    }

    pub fn contents_changed(&self) {
        self.tile_grid.borrow_mut().contents_changed()
    }
}

/// Whether a texture should be flipped.
#[deriving(PartialEq)]
pub enum Flip {
    /// The texture should not be flipped.
    NoFlip,
    /// The texture should be flipped vertically.
    VerticalFlip,
}

pub struct TextureLayer {
    /// A handle to the GPU texture.
    pub texture: Texture,
    /// The size of the texture in pixels.
    size: Size2D<uint>,
    /// Whether this texture is flipped vertically.
    pub flip: Flip,

    pub transform: Matrix4<f32>,
}

impl TextureLayer {
    pub fn new(texture: Texture, size: Size2D<uint>, flip: Flip, transform: Matrix4<f32>) -> TextureLayer {
        TextureLayer {
            texture: texture,
            size: size,
            flip: flip,
            transform: transform,
        }
    }
}

/// A request from the compositor to the renderer for tiles that need to be (re)displayed.
#[deriving(Clone)]
pub struct BufferRequest {
    // The rect in pixels that will be drawn to the screen
    pub screen_rect: Rect<uint>,

    // The rect in page coordinates that this tile represents
    pub page_rect: Rect<f32>,
}

impl BufferRequest {
    pub fn new(screen_rect: Rect<uint>, page_rect: Rect<f32>) -> BufferRequest {
        BufferRequest {
            screen_rect: screen_rect,
            page_rect: page_rect,
        }
    }
}

pub struct LayerBuffer {
    /// The native surface which can be shared between threads or processes. On Mac this is an
    /// `IOSurface`; on Linux this is an X Pixmap; on Android this is an `EGLImageKHR`.
    pub native_surface: NativeSurface,

    /// The rect in the containing RenderLayer that this represents.
    pub rect: Rect<f32>,

    /// The rect in pixels that will be drawn to the screen.
    pub screen_pos: Rect<uint>,

    /// The scale at which this tile is rendered
    pub resolution: f32,

    /// NB: stride is in pixels, like OpenGL GL_UNPACK_ROW_LENGTH.
    pub stride: uint,
}

/// A set of layer buffers. This is an atomic unit used to switch between the front and back
/// buffers.
pub struct LayerBufferSet {
    pub buffers: Vec<Box<LayerBuffer>>
}

impl LayerBufferSet {
    /// Notes all buffer surfaces will leak if not destroyed via a call to `destroy`.
    pub fn mark_will_leak(&mut self) {
        for buffer in self.buffers.mut_iter() {
            buffer.native_surface.mark_will_leak()
        }
    }
}

/// The interface used by the BufferMap to get info about layer buffers.
pub trait Tile {
    /// Returns the amount of memory used by the tile
    fn get_mem(&self) -> uint;

    /// Returns true if the tile is displayable at the given scale
    fn is_valid(&self, f32) -> bool;

    /// Returns the Size2D of the tile
    fn get_size_2d(&self) -> Size2D<uint>;

    /// Marks the layer buffer as not leaking. See comments on
    /// `NativeSurfaceMethods::mark_wont_leak` for how this is used.
    fn mark_wont_leak(&mut self);

    /// Destroys the layer buffer. Painting task only.
    fn destroy(self, graphics_context: &NativePaintingGraphicsContext);
}

impl Tile for Box<LayerBuffer> {
    fn get_mem(&self) -> uint {
        // This works for now, but in the future we may want a better heuristic
        self.screen_pos.size.width * self.screen_pos.size.height
    }
    fn is_valid(&self, scale: f32) -> bool {
        (self.resolution - scale).abs() < 1.0e-6
    }
    fn get_size_2d(&self) -> Size2D<uint> {
        self.screen_pos.size
    }
    fn mark_wont_leak(&mut self) {
        self.native_surface.mark_wont_leak()
    }
    fn destroy(self, graphics_context: &NativePaintingGraphicsContext) {
        let mut this = self;
        this.native_surface.destroy(graphics_context)
    }
}

<|endoftext|>


<commit_before>/// Which parse to use (when possible).
pub enum WhichParser {
    /// Pure Rust parser.
    Pure,
    /// Parse using external `protoc` command.
    Protoc,
}
<commit_msg>Minor doc cleanup<commit_after>/// Which parse to use to parse `.proto` files.
pub enum WhichParser {
    /// Pure Rust parser implemented by this crate.
    Pure,
    /// Parse `.proto` files using `protoc --descriptor_set_out=...` command.
    Protoc,
}
<|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/. */

mod ns_com_ptr;
mod ns_css_shadow_array;
mod ns_style_auto_array;
pub mod ns_style_coord;
mod ns_t_array;
pub mod ownership;
pub mod refptr;
mod style_complex_color;
<commit_msg>style: Describe the sugar module.<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/. */

//! Rust sugar and convenience methods for Gecko types.

mod ns_com_ptr;
mod ns_css_shadow_array;
mod ns_style_auto_array;
pub mod ns_style_coord;
mod ns_t_array;
pub mod ownership;
pub mod refptr;
mod style_complex_color;
<|endoftext|>