<commit_before>use std::fmt;

#[derive(Debug, Clone, Copy)]
pub enum Val {
    Byte(u8),
    Int(i64),
    Float(f64),
}

impl Val {
    pub fn to_i64(&self) -> i64 {
        match *self {
            Val::Byte(val) => i64::from(val),
            Val::Int(val) => val,
            Val::Float(val) => val.trunc() as i64,
        }
    }

    pub fn to_u8(&self) -> u8 {
        match *self {
            Val::Byte(val) => val,
            Val::Int(val) => val as u8,
            Val::Float(val) => val.trunc() as u8,
        }
    }

    pub fn to_f64(&self) -> f64 {
        match *self {
            Val::Byte(val) => f64::from(val),
            Val::Int(val) => val as f64,
            Val::Float(val) => val,
        }
    }

    pub fn checked_add(&self, other: Self) -> Option<Val> {
        match (*self, other) {
            (Val::Float(f), v) => Some(Val::Float(f + v.to_f64())),
            (v, Val::Float(f)) => Some(Val::Float(v.to_f64() + f)),
            _ => self.to_i64().checked_add(other.to_i64()).map(Val::Int),
        }
    }

    pub fn checked_sub(&self, other: Self) -> Option<Val> {
        match (*self, other) {
            (Val::Float(f), v) => Some(Val::Float(f - v.to_f64())),
            (v, Val::Float(f)) => Some(Val::Float(v.to_f64() - f)),
            _ => self.to_i64().checked_sub(other.to_i64()).map(Val::Int),
        }
    }

    pub fn checked_mul(&self, other: Self) -> Option<Val> {
        match (*self, other) {
            (Val::Float(f), v) => Some(Val::Float(f * v.to_f64())),
            (v, Val::Float(f)) => Some(Val::Float(v.to_f64() * f)),
            _ => self.to_i64().checked_mul(other.to_i64()).map(Val::Int),
        }
    }
}

impl PartialEq for Val {
    fn eq(&self, other: &Self) -> bool {
        match (*self, *other) {
            (Val::Float(a), Val::Float(b)) => a == b,
            (Val::Float(_), _) | (_, Val::Float(_)) => false,
            _ => self.to_i64() == other.to_i64(),
        }
    }
}

impl fmt::Display for Val {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Val::Byte(val) => write!(f, "{}", val),
            Val::Int(val) => write!(f, "{}", val),
            Val::Float(val) => write!(f, "{}", val),
        }
    }
}

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

    #[test]
    fn val_to_u8_works() {
        let val = Val::Byte(15);
        assert_eq!(val.to_u8(), 15);

        let val = Val::Int(54);
        assert_eq!(val.to_u8(), 54);
    }

    #[test]
    fn val_to_i64_works() {
        let val = Val::Byte(15);
        assert_eq!(val.to_i64(), 15);

        let val = Val::Int(54);
        assert_eq!(val.to_i64(), 54)
    }

    #[test]
    fn val_to_f64_works() {
        let val = Val::Byte(15);
        assert_eq!(val.to_f64(), 15.0);
    }

    #[test]
    fn val_eq_works() {
        assert_eq!(Val::Byte(1), Val::Byte(1));
        assert_eq!(Val::Byte(1), Val::Int(1));
        assert_eq!(Val::Int(1), Val::Int(1));
        assert_eq!(Val::Float(1.0), Val::Float(1.0));

        assert_ne!(Val::Byte(1), Val::Byte(2));
        assert_ne!(Val::Int(1), Val::Int(2));
        assert_ne!(Val::Float(1.0), Val::Float(2.0));

        assert_ne!(Val::Byte(1), Val::Float(1.0));
        assert_ne!(Val::Int(1), Val::Float(1.0));
    }
}
<commit_msg>Implement `From' for Val<commit_after>use std::fmt;

#[derive(Debug, Clone, Copy)]
pub enum Val {
    Byte(u8),
    Int(i64),
    Float(f64),
}

impl Val {
    pub fn to_i64(&self) -> i64 {
        match *self {
            Val::Byte(val) => i64::from(val),
            Val::Int(val) => val,
            Val::Float(val) => val.trunc() as i64,
        }
    }

    pub fn to_u8(&self) -> u8 {
        match *self {
            Val::Byte(val) => val,
            Val::Int(val) => val as u8,
            Val::Float(val) => val.trunc() as u8,
        }
    }

    pub fn to_f64(&self) -> f64 {
        match *self {
            Val::Byte(val) => f64::from(val),
            Val::Int(val) => val as f64,
            Val::Float(val) => val,
        }
    }

    pub fn checked_add(&self, other: Self) -> Option<Val> {
        match (*self, other) {
            (Val::Float(f), v) => Some(Val::Float(f + v.to_f64())),
            (v, Val::Float(f)) => Some(Val::Float(v.to_f64() + f)),
            _ => self.to_i64().checked_add(other.to_i64()).map(Val::Int),
        }
    }

    pub fn checked_sub(&self, other: Self) -> Option<Val> {
        match (*self, other) {
            (Val::Float(f), v) => Some(Val::Float(f - v.to_f64())),
            (v, Val::Float(f)) => Some(Val::Float(v.to_f64() - f)),
            _ => self.to_i64().checked_sub(other.to_i64()).map(Val::Int),
        }
    }

    pub fn checked_mul(&self, other: Self) -> Option<Val> {
        match (*self, other) {
            (Val::Float(f), v) => Some(Val::Float(f * v.to_f64())),
            (v, Val::Float(f)) => Some(Val::Float(v.to_f64() * f)),
            _ => self.to_i64().checked_mul(other.to_i64()).map(Val::Int),
        }
    }
}

impl From<u8> for Val {
    fn from(v: u8) -> Self {
        Val::Byte(v)
    }
}

impl From<i64> for Val {
    fn from(v: i64) -> Self {
        Val::Int(v)
    }
}

impl From<f64> for Val {
    fn from(v: f64) -> Self {
        Val::Float(v)
    }
}

impl From<Val> for u8 {
    fn from(v: Val) -> Self {
        v.to_u8()
    }
}

impl From<Val> for i64 {
    fn from(v: Val) -> Self {
        v.to_i64()
    }
}

impl From<Val> for f64 {
    fn from(v: Val) -> Self {
        v.to_f64()
    }
}

impl PartialEq for Val {
    fn eq(&self, other: &Self) -> bool {
        match (*self, *other) {
            (Val::Float(a), Val::Float(b)) => a == b,
            (Val::Float(_), _) | (_, Val::Float(_)) => false,
            _ => self.to_i64() == other.to_i64(),
        }
    }
}

impl fmt::Display for Val {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Val::Byte(val) => write!(f, "{}", val),
            Val::Int(val) => write!(f, "{}", val),
            Val::Float(val) => write!(f, "{}", val),
        }
    }
}

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

    #[test]
    fn val_to_u8_works() {
        let val = Val::Byte(15);
        assert_eq!(val.to_u8(), 15);

        let val = Val::Int(54);
        assert_eq!(val.to_u8(), 54);
    }

    #[test]
    fn val_to_i64_works() {
        let val = Val::Byte(15);
        assert_eq!(val.to_i64(), 15);

        let val = Val::Int(54);
        assert_eq!(val.to_i64(), 54)
    }

    #[test]
    fn val_to_f64_works() {
        let val = Val::Byte(15);
        assert_eq!(val.to_f64(), 15.0);
    }

    #[test]
    fn from_works() {
        assert_eq!(Val::from(b'a'), Val::Byte(b'a'));
        assert_eq!(Val::from(-512i64), Val::Int(-512));
        assert_eq!(Val::from(3.14), Val::Float(3.14));
    }

    #[test]
    fn generated_into_works() {
        let val: Val = b'a'.into();
        assert_eq!(val, Val::Byte(b'a'));

        let val: Val = (-512i64).into();
        assert_eq!(val, Val::Int(-512));

        let val: Val = 3.14.into();
        assert_eq!(val, Val::Float(3.14));
    }

    #[test]
    fn from_val_works() {
        let v = u8::from(Val::Byte(b'a'));
        assert_eq!(v, b'a');

        let v = i64::from(Val::Int(-512));
        assert_eq!(v, -512);

        let v = f64::from(Val::Float(3.14));
        assert_eq!(v, 3.14);
    }

    #[test]
    fn generated_val_into_works() {
        let v: u8 = Val::Byte(b'a').into();
        assert_eq!(v, b'a');

        let v: i64 = Val::Int(-512).into();
        assert_eq!(v, -512);

        let v: f64 = Val::Float(3.14).into();
        assert_eq!(v, 3.14);
    }

    #[test]
    fn val_eq_works() {
        assert_eq!(Val::Byte(1), Val::Byte(1));
        assert_eq!(Val::Byte(1), Val::Int(1));
        assert_eq!(Val::Int(1), Val::Int(1));
        assert_eq!(Val::Float(1.0), Val::Float(1.0));

        assert_ne!(Val::Byte(1), Val::Byte(2));
        assert_ne!(Val::Int(1), Val::Int(2));
        assert_ne!(Val::Float(1.0), Val::Float(2.0));

        assert_ne!(Val::Byte(1), Val::Float(1.0));
        assert_ne!(Val::Int(1), Val::Float(1.0));
    }
}
<|endoftext|>


<commit_before>use bosun::{Metadata, Rate, Sample};
use collectors::*;
use config::Config;

use std::num::ParseFloatError;
#[cfg(target_os = "linux")]
use procinfo::pid;

pub static RS_COLLECTOR_STATS_SAMPLES_METRICNAME: &'static str = "rs-collector.stats.samples";
static VERSION: &'static str = env!("CARGO_PKG_VERSION");

#[derive(Debug)]
#[derive(RustcDecodable)]
#[allow(non_snake_case)]
pub struct RsCollectorConfig {}

#[derive(Clone)]
pub struct RsCollector {
    id: Id,
}

pub fn create_instances(_: &Config) -> Vec<Box<Collector + Send>> {
    let id = format!("rscollector");
    info!("Created instance of RsCollector collector: {}", id);

    let collector = RsCollector { id: id };
    vec![Box::new(collector)]
}

impl Collector for RsCollector {
    fn init(&mut self) -> Result<(), Box<Error>> {
        Ok(())
    }

    fn id(&self) -> &Id {
        &self.id
    }

    fn collect(&self) -> Result<Vec<Sample>, Error> {
        let mut samples = try!(collect_internal_metrics());
        debug!("{:#?}", samples);

        Ok(samples)
    }

    fn shutdown(&mut self) {}

    fn metadata(&self) -> Vec<Metadata> {
        vec![
            Metadata::new("rs-collector.version",
                          Rate::Gauge,
                          "",
                          "Shows the version 'x.y.z' of rs-collector as x*1.000.0000 + y*1000 + z."),
             Metadata::new("rs-collector.stats.rss",
                          Rate::Gauge,
                          "KB",
                          "Shows resident set size (physical memory) in KB consumed by rs-collector; if supported."),
             // This value is actually computed and send in the Bosun module directly.
             Metadata::new(RS_COLLECTOR_STATS_SAMPLES_METRICNAME,
                          Rate::Gauge,
                          "Samples",
                          "Shows transmitted samples."),        ]
    }
}

fn collect_internal_metrics() -> Result<Vec<Sample>, Error> {
    let mut samples = Vec::new();

    let version = parse_version_string(VERSION).or(Some(-1f64)).unwrap();
    samples.push(Sample::new("rs-collector.version", version));

    let rss = get_rss().or(Some(-1f64)).unwrap();
    samples.push(Sample::new("rs-collector.stats.rss", rss));

    Ok(samples)
}

fn parse_version_string<T: Into<String>>(version: T) -> Option<f64> {
    let version_triple: Vec<Result<f64, ParseFloatError>> = version.into()
        .split('.')
        .map(|s| s.parse::<f64>())
        .filter(|f| f.is_ok())
        .collect();

    if version_triple.len() == 3 {
        let version_value = version_triple[0].as_ref().unwrap() * 1000000f64
            + version_triple[1].as_ref().unwrap() * 1000f64
            + version_triple[2].as_ref().unwrap();

        Some(version_value)
    } else {
        None
    }
}

#[cfg(target_os = "linux")]
fn get_rss() -> Option<f64> {
    let status = pid::status_self();
    status.ok().map(|s| s.vm_rss as f64)
}

#[cfg(not(target_os = "linux"))]
fn get_rss() -> Option<f64> {
    None
}
<commit_msg>Update metric descriptions<commit_after>use bosun::{Metadata, Rate, Sample};
use collectors::*;
use config::Config;

use std::num::ParseFloatError;
#[cfg(target_os = "linux")]
use procinfo::pid;

pub static RS_COLLECTOR_STATS_SAMPLES_METRICNAME: &'static str = "rs-collector.stats.samples";
static VERSION: &'static str = env!("CARGO_PKG_VERSION");

#[derive(Debug)]
#[derive(RustcDecodable)]
#[allow(non_snake_case)]
pub struct RsCollectorConfig {}

#[derive(Clone)]
pub struct RsCollector {
    id: Id,
}

pub fn create_instances(_: &Config) -> Vec<Box<Collector + Send>> {
    let id = format!("rscollector");
    info!("Created instance of RsCollector collector: {}", id);

    let collector = RsCollector { id: id };
    vec![Box::new(collector)]
}

impl Collector for RsCollector {
    fn init(&mut self) -> Result<(), Box<Error>> {
        Ok(())
    }

    fn id(&self) -> &Id {
        &self.id
    }

    fn collect(&self) -> Result<Vec<Sample>, Error> {
        let mut samples = try!(collect_internal_metrics());
        debug!("{:#?}", samples);

        Ok(samples)
    }

    fn shutdown(&mut self) {}

    fn metadata(&self) -> Vec<Metadata> {
        vec![
            Metadata::new("rs-collector.version",
                          Rate::Gauge,
                          "",
                          "Shows the version 'x.y.z' of rs-collector as x*1.000.0000 + y*1000 + z."),
            Metadata::new("rs-collector.stats.rss",
                          Rate::Gauge,
                          "KB",
                          "Shows the resident set size (physical memory) in KB consumed by rs-collector; if supported."),
            // This value is actually computed and send in the Bosun module directly.
            Metadata::new(RS_COLLECTOR_STATS_SAMPLES_METRICNAME,
                          Rate::Gauge,
                          "Samples",
                          "Shows the number of transmitted samples."),
        ]
    }
}

fn collect_internal_metrics() -> Result<Vec<Sample>, Error> {
    let mut samples = Vec::new();

    let version = parse_version_string(VERSION).or(Some(-1f64)).unwrap();
    samples.push(Sample::new("rs-collector.version", version));

    let rss = get_rss().or(Some(-1f64)).unwrap();
    samples.push(Sample::new("rs-collector.stats.rss", rss));

    Ok(samples)
}

fn parse_version_string<T: Into<String>>(version: T) -> Option<f64> {
    let version_triple: Vec<Result<f64, ParseFloatError>> = version.into()
        .split('.')
        .map(|s| s.parse::<f64>())
        .filter(|f| f.is_ok())
        .collect();

    if version_triple.len() == 3 {
        let version_value = version_triple[0].as_ref().unwrap() * 1000000f64
            + version_triple[1].as_ref().unwrap() * 1000f64
            + version_triple[2].as_ref().unwrap();

        Some(version_value)
    } else {
        None
    }
}

#[cfg(target_os = "linux")]
fn get_rss() -> Option<f64> {
    let status = pid::status_self();
    status.ok().map(|s| s.vm_rss as f64)
}

#[cfg(not(target_os = "linux"))]
fn get_rss() -> Option<f64> {
    None
}
<|endoftext|>


<commit_before>use command::{Command, Query};
use commandlinable::Escape;

#[derive(Clone, Debug)]
pub struct CommandLine {
    command: Command,
    arguments: Query,
}

impl CommandLine {
    pub fn new(command: Command, query: Query) -> CommandLine {
        CommandLine {
            command: command,
            arguments: query,
        }
    }

    /// Get command enum constant to construct command line query.
    pub fn get_command(&mut self) -> Command {
        self.command.clone()
    }

    /// Get vectorize `("key", "value")` pairs to construct command line query.
    pub fn get_argument(&mut self) -> Query {
        self.arguments.clone()
    }

    /// Set vectorize `("key", "value")` pairs to construct command line query.
    pub fn set_argument(&mut self, arguments: Query) {
        self.arguments = arguments
    }

    /// Create command line style command query.
    ///
    /// `vec![("key","value")]` interprets to `"--key value"`.
    /// And two or more value pair are concatinate with ` `(a space).
    pub fn make_command(&mut self) -> String {
        let mut output = String::new();
        for query in self.arguments.to_owned() {
            let (key, value) = query;
            if output.len() > 0 {
                output.push_str(" ");
            }
            let format_string = format!("--{} {}", &*key, Escape(&*value));
            output.push_str(format_string.as_str());
        }
        output
    }

    ///
    /// Create Groonga command line style command.
    pub fn encode(&mut self) -> String {
        format!("{} {}", self.get_command(), self.make_command())
            .trim()
            .clone()
    }
}

#[cfg(test)]
mod test {
    use super::CommandLine;
    use select::SelectCommand;
    use load::{LoadCommand, InputType};
    use status::StatusCommand;
    use dump::DumpCommand;
    use delete::DeleteCommand;
    use table_create::TableCreateCommand;
    use types::table_flag_type::TableFlagType;
    use column_create::ColumnCreateCommand;
    use types::data_type::DataType;

    #[test]
    fn test_select() {
        let (command, query) = SelectCommand::new("Test".to_string())
                                   .filter("output_column @ \"type_safe\"".to_string())
                                   .build();
        let mut command = CommandLine::new(command, query);
        let cli_encoded = "select --table Test --filter \'output_column @ \"type_safe\"\'";
        assert_eq!(cli_encoded.to_string(), command.encode());
    }

    #[test]
    fn test_load() {
        let load_data: &'static str = r#"[
{"_key":"http://example.org/","title":"This is test record 1!"},
]"#;
        let (command, query, values) = LoadCommand::new("Test".to_string(), load_data.to_string())
                                           .input_type(InputType::Json)
                                           .build();
        let mut command = CommandLine::new(command, query);
        let cli_encoded = "load --table Test --input_type json";
        assert_eq!(cli_encoded.to_string(), command.encode());
        assert_eq!(load_data.to_string(), values);
    }

    #[test]
    fn test_status() {
        let (command, query) = StatusCommand::new().build();
        let mut command = CommandLine::new(command, query);
        let cli_encoded = "status";
        assert_eq!(cli_encoded.to_string(), command.encode());
    }

    #[test]
    fn test_dump() {
        let (command, query) = DumpCommand::new()
                                   .tables(vec!["Books".to_string(), "Categories".to_string()])
                                   .build();
        let mut command = CommandLine::new(command, query);
        let cli_encoded = "dump --tables Books,Categories";
        assert_eq!(cli_encoded.to_string(), command.encode());
    }

    #[test]
    fn test_delete() {
        let (command, query) = DeleteCommand::new("Books".to_string())
                                   .filter("author == unknown".to_string())
                                   .build();
        let mut command = CommandLine::new(command, query);
        let cli_encoded = "delete --table Books --filter \'author == unknown\'";
        assert_eq!(cli_encoded.to_string(), command.encode());
    }

    #[test]
    fn test_table_create() {
        let (command, query) = TableCreateCommand::new("Test".to_string())
                                   .flags(vec![(TableFlagType::PatKey),
                                               (TableFlagType::KeyWithSIS)])
                                   .build();
        let mut command = CommandLine::new(command, query);
        let url_encoded = "table_create --name Test --flags TABLE_PAT_KEY|KEY_WITH_SIS";
        assert_eq!(url_encoded.to_string(), command.encode());
    }

    #[test]
    fn test_column_create() {
        let (command, query) = ColumnCreateCommand::new("Test".to_string(), "element".to_string())
                                   .column_type(DataType::LongText)
                                   .build();
        let mut command = CommandLine::new(command, query);
        let cli_encoded = "column_create --table Test --name element --type LongText";
        assert_eq!(cli_encoded.to_string(), command.encode());
    }
}
<commit_msg>Fix build error<commit_after>use command::{Command, Query};
use commandlinable::Escape;

#[derive(Clone, Debug)]
pub struct CommandLine {
    command: Command,
    arguments: Query,
}

impl CommandLine {
    pub fn new(command: Command, query: Query) -> CommandLine {
        CommandLine {
            command: command,
            arguments: query,
        }
    }

    /// Get command enum constant to construct command line query.
    pub fn get_command(&mut self) -> Command {
        self.command.clone()
    }

    /// Get vectorize `("key", "value")` pairs to construct command line query.
    pub fn get_argument(&mut self) -> Query {
        self.arguments.clone()
    }

    /// Set vectorize `("key", "value")` pairs to construct command line query.
    pub fn set_argument(&mut self, arguments: Query) {
        self.arguments = arguments
    }

    /// Create command line style command query.
    ///
    /// `vec![("key","value")]` interprets to `"--key value"`.
    /// And two or more value pair are concatinate with ` `(a space).
    pub fn make_command(&mut self) -> String {
        let mut output = String::new();
        for query in self.arguments.to_owned() {
            let (key, value) = query;
            if output.len() > 0 {
                output.push_str(" ");
            }
            let format_string = format!("--{} {}", &*key, Escape(&*value));
            output.push_str(format_string.as_str());
        }
        output
    }

    ///
    /// Create Groonga command line style command.
    pub fn encode(&mut self) -> String {
        format!("{} {}", self.get_command(), self.make_command())
            .trim()
            .to_string()
    }
}

#[cfg(test)]
mod test {
    use super::CommandLine;
    use select::SelectCommand;
    use load::{LoadCommand, InputType};
    use status::StatusCommand;
    use dump::DumpCommand;
    use delete::DeleteCommand;
    use table_create::TableCreateCommand;
    use types::table_flag_type::TableFlagType;
    use column_create::ColumnCreateCommand;
    use types::data_type::DataType;

    #[test]
    fn test_select() {
        let (command, query) = SelectCommand::new("Test".to_string())
                                   .filter("output_column @ \"type_safe\"".to_string())
                                   .build();
        let mut command = CommandLine::new(command, query);
        let cli_encoded = "select --table Test --filter \'output_column @ \"type_safe\"\'";
        assert_eq!(cli_encoded.to_string(), command.encode());
    }

    #[test]
    fn test_load() {
        let load_data: &'static str = r#"[
{"_key":"http://example.org/","title":"This is test record 1!"},
]"#;
        let (command, query, values) = LoadCommand::new("Test".to_string(), load_data.to_string())
                                           .input_type(InputType::Json)
                                           .build();
        let mut command = CommandLine::new(command, query);
        let cli_encoded = "load --table Test --input_type json";
        assert_eq!(cli_encoded.to_string(), command.encode());
        assert_eq!(load_data.to_string(), values);
    }

    #[test]
    fn test_status() {
        let (command, query) = StatusCommand::new().build();
        let mut command = CommandLine::new(command, query);
        let cli_encoded = "status";
        assert_eq!(cli_encoded.to_string(), command.encode());
    }

    #[test]
    fn test_dump() {
        let (command, query) = DumpCommand::new()
                                   .tables(vec!["Books".to_string(), "Categories".to_string()])
                                   .build();
        let mut command = CommandLine::new(command, query);
        let cli_encoded = "dump --tables Books,Categories";
        assert_eq!(cli_encoded.to_string(), command.encode());
    }

    #[test]
    fn test_delete() {
        let (command, query) = DeleteCommand::new("Books".to_string())
                                   .filter("author == unknown".to_string())
                                   .build();
        let mut command = CommandLine::new(command, query);
        let cli_encoded = "delete --table Books --filter \'author == unknown\'";
        assert_eq!(cli_encoded.to_string(), command.encode());
    }

    #[test]
    fn test_table_create() {
        let (command, query) = TableCreateCommand::new("Test".to_string())
                                   .flags(vec![(TableFlagType::PatKey),
                                               (TableFlagType::KeyWithSIS)])
                                   .build();
        let mut command = CommandLine::new(command, query);
        let url_encoded = "table_create --name Test --flags TABLE_PAT_KEY|KEY_WITH_SIS";
        assert_eq!(url_encoded.to_string(), command.encode());
    }

    #[test]
    fn test_column_create() {
        let (command, query) = ColumnCreateCommand::new("Test".to_string(), "element".to_string())
                                   .column_type(DataType::LongText)
                                   .build();
        let mut command = CommandLine::new(command, query);
        let cli_encoded = "column_create --table Test --name element --type LongText";
        assert_eq!(cli_encoded.to_string(), command.encode());
    }
}
<|endoftext|>


<commit_before>#![feature(phase)]

extern crate seq;
#[phase(plugin)]
extern crate seq_macros;

use std::collections::{Bitv, HashMap, HashSet, VecMap, TreeMap, TreeSet};

#[test]
fn bitv() {
    let mut v = Bitv::new();
    assert_eq!(v, seq![]);

    v.push(true);
    v.push(false);
    v.push(true);
    assert_eq!(v, seq![true, false, true]);
}

#[test]
fn hashmap() {
    let mut m = HashMap::new();
    assert_eq!(m, seq!{});

    m.insert('b', "banana".to_string());
    m.insert('c', "coconut".to_string());
    m.insert('a', "apple".to_string());
    assert_eq!(m, seq!{
        'a' => "apple".to_string(),
        'b' => "banana".to_string(),
        'c' => "coconut".to_string(),
    });
}

#[test]
fn hashset() {
    let mut s = HashSet::new();
    assert_eq!(s, seq!{});

    s.insert("three");
    s.insert("one");
    s.insert("two");
    assert_eq!(s, seq!["one", "two", "three"]);
}

#[test]
fn vecmap() {
    let mut m = VecMap::new();
    assert_eq!(m, seq!{});

    m.insert(2, "two");
    m.insert(3, "three");
    m.insert(5, "five");
    assert_eq!(m, seq!{
        2 => "two",
        3 => "three",
        5 => "five",
    });
}

#[test]
fn treemap() {
    let mut m = TreeMap::new();
    assert_eq!(m, seq!{});

    m.insert('b', "banana".to_string());
    m.insert('c', "coconut".to_string());
    m.insert('a', "apple".to_string());
    assert_eq!(m, seq!{
        'a' => "apple".to_string(),
        'b' => "banana".to_string(),
        'c' => "coconut".to_string(),
    });
}

#[test]
fn treeset() {
    let mut s = TreeSet::new();
    assert_eq!(s, seq!{});

    s.insert("three");
    s.insert("one");
    s.insert("two");
    assert_eq!(s, seq!["one", "two", "three"]);
}

#[test]
fn vec() {
    let mut v = Vec::new();
    assert_eq!(v, seq![]);

    v.push(1u8);
    v.push(2);
    v.push(3);
    assert_eq!(v, seq![1, 2, 3]);
}
<commit_msg>fix(tests): `==` no longer forces "same-type"-ness with `Vec`<commit_after>#![feature(phase)]

extern crate seq;
#[phase(plugin)]
extern crate seq_macros;

use std::collections::{Bitv, HashMap, HashSet, VecMap, TreeMap, TreeSet};

#[test]
fn bitv() {
    let mut v = Bitv::new();
    assert_eq!(v, seq![]);

    v.push(true);
    v.push(false);
    v.push(true);
    assert_eq!(v, seq![true, false, true]);
}

#[test]
fn hashmap() {
    let mut m = HashMap::new();
    assert_eq!(m, seq!{});

    m.insert('b', "banana".to_string());
    m.insert('c', "coconut".to_string());
    m.insert('a', "apple".to_string());
    assert_eq!(m, seq!{
        'a' => "apple".to_string(),
        'b' => "banana".to_string(),
        'c' => "coconut".to_string(),
    });
}

#[test]
fn hashset() {
    let mut s = HashSet::new();
    assert_eq!(s, seq!{});

    s.insert("three");
    s.insert("one");
    s.insert("two");
    assert_eq!(s, seq!["one", "two", "three"]);
}

#[test]
fn vecmap() {
    let mut m = VecMap::new();
    assert_eq!(m, seq!{});

    m.insert(2, "two");
    m.insert(3, "three");
    m.insert(5, "five");
    assert_eq!(m, seq!{
        2 => "two",
        3 => "three",
        5 => "five",
    });
}

#[test]
fn treemap() {
    let mut m = TreeMap::new();
    assert_eq!(m, seq!{});

    m.insert('b', "banana".to_string());
    m.insert('c', "coconut".to_string());
    m.insert('a', "apple".to_string());
    assert_eq!(m, seq!{
        'a' => "apple".to_string(),
        'b' => "banana".to_string(),
        'c' => "coconut".to_string(),
    });
}

#[test]
fn treeset() {
    let mut s = TreeSet::new();
    assert_eq!(s, seq!{});

    s.insert("three");
    s.insert("one");
    s.insert("two");
    assert_eq!(s, seq!["one", "two", "three"]);
}

#[test]
fn vec() {
    let mut v = Vec::new();
    let rhs: Vec<_> = seq![];
    assert_eq!(v, rhs);

    v.push(1u8);
    v.push(2);
    v.push(3);
    let rhs: Vec<_> = seq![1, 2, 3];
    assert_eq!(v, rhs);
}
<|endoftext|>


<commit_before>extern {
    static dc_qlookup_Q3: [i16; 256];
    static ac_qlookup_Q3: [i16; 256];
}

pub fn dc_q(qindex: usize) -> i16 {
    unsafe {
        dc_qlookup_Q3[qindex]
    }
}

pub fn ac_q(qindex: usize) -> i16 {
    unsafe {
        ac_qlookup_Q3[qindex]
    }
}

pub fn quantize_in_place(qindex: usize, coeffs: &mut [i32]) {
    coeffs[0] /= dc_q(qindex) as i32;
    for c in coeffs[1..].iter_mut() {
        *c /= ac_q(qindex) as i32;
    }
    coeffs[15] = 0;
}

pub fn dequantize(qindex:usize, coeffs: &[i32], rcoeffs: &mut [i32]) {
    rcoeffs[0] = coeffs[0] * dc_q(qindex) as i32;
    for i in 1..16 {
        rcoeffs[i] = coeffs[i] * ac_q(qindex) as i32;
    }
}
<commit_msg>Make quantization functions work for any block size.<commit_after>extern {
    static dc_qlookup_Q3: [i16; 256];
    static ac_qlookup_Q3: [i16; 256];
}

pub fn dc_q(qindex: usize) -> i16 {
    unsafe {
        dc_qlookup_Q3[qindex]
    }
}

pub fn ac_q(qindex: usize) -> i16 {
    unsafe {
        ac_qlookup_Q3[qindex]
    }
}

pub fn quantize_in_place(qindex: usize, coeffs: &mut [i32]) {
    coeffs[0] /= dc_q(qindex) as i32;
    for c in coeffs[1..].iter_mut() {
        *c /= ac_q(qindex) as i32;
    }
    // workaround for bug in token coder
    *coeffs.last_mut().unwrap() = 0;
}

pub fn dequantize(qindex:usize, coeffs: &[i32], rcoeffs: &mut [i32]) {
    rcoeffs[0] = coeffs[0] * dc_q(qindex) as i32;
    for i in 1..coeffs.len() {
        rcoeffs[i] = coeffs[i] * ac_q(qindex) as i32;
    }
}
<|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/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

// TODO: other background-* properties
<%helpers:shorthand name="background"
                    sub_properties="background-color background-position-x background-position-y background-repeat
                                    background-attachment background-image background-size background-origin
                                    background-clip"
                    spec="https://drafts.csswg.org/css-backgrounds/#the-background">
    use properties::longhands::{background_position_x, background_position_y, background_repeat};
    use properties::longhands::{background_attachment, background_image, background_size, background_origin};
    use properties::longhands::background_clip;
    use properties::longhands::background_clip::single_value::computed_value::T as Clip;
    use properties::longhands::background_origin::single_value::computed_value::T as Origin;
    use values::specified::{CSSColor, Position, PositionComponent};
    use parser::Parse;

    impl From<background_origin::single_value::SpecifiedValue> for background_clip::single_value::SpecifiedValue {
        fn from(origin: background_origin::single_value::SpecifiedValue) ->
            background_clip::single_value::SpecifiedValue {
            match origin {
                background_origin::single_value::SpecifiedValue::content_box =>
                    background_clip::single_value::SpecifiedValue::content_box,
                background_origin::single_value::SpecifiedValue::padding_box =>
                    background_clip::single_value::SpecifiedValue::padding_box,
                background_origin::single_value::SpecifiedValue::border_box =>
                    background_clip::single_value::SpecifiedValue::border_box,
            }
        }
    }

    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        let mut background_color = None;

        % for name in "image position_x position_y repeat size attachment origin clip".split():
            let mut background_${name} = background_${name}::SpecifiedValue(Vec::new());
        % endfor
        try!(input.parse_comma_separated(|input| {
            // background-color can only be in the last element, so if it
            // is parsed anywhere before, the value is invalid.
            if background_color.is_some() {
                return Err(());
            }

            % for name in "image position repeat size attachment origin clip".split():
                let mut ${name} = None;
            % endfor
            loop {
                if background_color.is_none() {
                    if let Ok(value) = input.try(|i| CSSColor::parse(context, i)) {
                        background_color = Some(value);
                        continue
                    }
                }
                if position.is_none() {
                    if let Ok(value) = input.try(|input| Position::parse(context, input)) {
                        position = Some(value);

                        // Parse background size, if applicable.
                        size = input.try(|input| {
                            try!(input.expect_delim('/'));
                            background_size::single_value::parse(context, input)
                        }).ok();

                        continue
                    }
                }
                % for name in "image repeat attachment origin clip".split():
                    if ${name}.is_none() {
                        if let Ok(value) = input.try(|input| background_${name}::single_value
                                                                               ::parse(context, input)) {
                            % if name == "clip" and product == "gecko":
                            // "text" value of background-clip should not be part of background
                            // shorthand per current spec and impls.
                            if value == background_clip::single_value::SpecifiedValue::text {
                                return Err(());
                            }
                            % endif
                            ${name} = Some(value);
                            continue
                        }
                    }
                % endfor
                break
            }
            if clip.is_none() {
                if let Some(origin) = origin {
                    clip = Some(background_clip::single_value::SpecifiedValue::from(origin));
                }
            }
            let mut any = false;
            % for name in "image position repeat size attachment origin clip".split():
                any = any || ${name}.is_some();
            % endfor
            any = any || background_color.is_some();
            if any {
                if let Some(position) = position {
                    background_position_x.0.push(position.horizontal);
                    background_position_y.0.push(position.vertical);
                } else {
                    background_position_x.0.push(PositionComponent::zero());
                    background_position_y.0.push(PositionComponent::zero());
                }
                % for name in "image repeat size attachment origin clip".split():
                    if let Some(bg_${name}) = ${name} {
                        background_${name}.0.push(bg_${name});
                    } else {
                        background_${name}.0.push(background_${name}::single_value
                                                                    ::get_initial_specified_value());
                    }
                % endfor
                Ok(())
            } else {
                Err(())
            }
        }));

        Ok(expanded! {
             background_color: background_color.unwrap_or(CSSColor::transparent()),
             background_image: background_image,
             background_position_x: background_position_x,
             background_position_y: background_position_y,
             background_repeat: background_repeat,
             background_attachment: background_attachment,
             background_size: background_size,
             background_origin: background_origin,
             background_clip: background_clip,
         })
    }

    impl<'a> ToCss for LonghandsToSerialize<'a>  {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            let len = self.background_image.0.len();
            // There should be at least one declared value
            if len == 0 {
                return Ok(());
            }

            // If a value list length is differs then we don't do a shorthand serialization.
            // The exceptions to this is color which appears once only and is serialized
            // with the last item.
            % for name in "image position_x position_y size repeat origin clip attachment".split():
                if len != self.background_${name}.0.len() {
                    return Ok(());
                }
            % endfor

            for i in 0..len {
                % for name in "image position_x position_y repeat size attachment origin clip".split():
                    let ${name} = &self.background_${name}.0[i];
                % endfor

                if i != 0 {
                    try!(write!(dest, ", "));
                }

                if i == len - 1 {
                    try!(self.background_color.to_css(dest));
                    try!(write!(dest, " "));
                }

                try!(image.to_css(dest));
                % for name in "repeat attachment".split():
                    try!(write!(dest, " "));
                    try!(${name}.to_css(dest));
                % endfor

                try!(write!(dest, " "));
                Position {
                    horizontal: position_x.clone(),
                    vertical: position_y.clone()
                }.to_css(dest)?;

                if *size != background_size::single_value::get_initial_specified_value() {
                    try!(write!(dest, " / "));
                    try!(size.to_css(dest));
                }

                if *origin != Origin::padding_box || *clip != Clip::border_box {
                    try!(write!(dest, " "));
                    try!(origin.to_css(dest));
                    if *clip != From::from(*origin) {
                        try!(write!(dest, " "));
                        try!(clip.to_css(dest));
                    }
                }
            }

            Ok(())
        }
    }
</%helpers:shorthand>

<%helpers:shorthand name="background-position"
                    sub_properties="background-position-x background-position-y"
                    spec="https://drafts.csswg.org/css-backgrounds-4/#the-background-position">
    use properties::longhands::{background_position_x, background_position_y};
    use values::specified::AllowQuirks;
    use values::specified::position::Position;

    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        let mut position_x = background_position_x::SpecifiedValue(Vec::new());
        let mut position_y = background_position_y::SpecifiedValue(Vec::new());
        let mut any = false;

        input.parse_comma_separated(|input| {
            let value = Position::parse_quirky(context, input, AllowQuirks::Yes)?;
            position_x.0.push(value.horizontal);
            position_y.0.push(value.vertical);
            any = true;
            Ok(())
        })?;
        if !any {
            return Err(());
        }

        Ok(expanded! {
            background_position_x: position_x,
            background_position_y: position_y,
        })
    }

    impl<'a> ToCss for LonghandsToSerialize<'a>  {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            let len = self.background_position_x.0.len();
            if len == 0 || len != self.background_position_y.0.len() {
                return Ok(());
            }
            for i in 0..len {
                Position {
                    horizontal: self.background_position_x.0[i].clone(),
                    vertical: self.background_position_y.0[i].clone()
                }.to_css(dest)?;

                if i < len - 1 {
                    dest.write_str(", ")?;
                }
            }
            Ok(())
        }
    }
</%helpers:shorthand>
<commit_msg>Auto merge of #17035 - upsuper:bug1188074, r=heycam<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/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

// TODO: other background-* properties
<%helpers:shorthand name="background"
                    sub_properties="background-color background-position-x background-position-y background-repeat
                                    background-attachment background-image background-size background-origin
                                    background-clip"
                    spec="https://drafts.csswg.org/css-backgrounds/#the-background">
    use properties::longhands::{background_position_x, background_position_y, background_repeat};
    use properties::longhands::{background_attachment, background_image, background_size, background_origin};
    use properties::longhands::background_clip;
    use properties::longhands::background_clip::single_value::computed_value::T as Clip;
    use properties::longhands::background_origin::single_value::computed_value::T as Origin;
    use values::specified::{CSSColor, Position, PositionComponent};
    use parser::Parse;

    impl From<background_origin::single_value::SpecifiedValue> for background_clip::single_value::SpecifiedValue {
        fn from(origin: background_origin::single_value::SpecifiedValue) ->
            background_clip::single_value::SpecifiedValue {
            match origin {
                background_origin::single_value::SpecifiedValue::content_box =>
                    background_clip::single_value::SpecifiedValue::content_box,
                background_origin::single_value::SpecifiedValue::padding_box =>
                    background_clip::single_value::SpecifiedValue::padding_box,
                background_origin::single_value::SpecifiedValue::border_box =>
                    background_clip::single_value::SpecifiedValue::border_box,
            }
        }
    }

    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        let mut background_color = None;

        % for name in "image position_x position_y repeat size attachment origin clip".split():
            let mut background_${name} = background_${name}::SpecifiedValue(Vec::new());
        % endfor
        try!(input.parse_comma_separated(|input| {
            // background-color can only be in the last element, so if it
            // is parsed anywhere before, the value is invalid.
            if background_color.is_some() {
                return Err(());
            }

            % for name in "image position repeat size attachment origin clip".split():
                let mut ${name} = None;
            % endfor
            loop {
                if background_color.is_none() {
                    if let Ok(value) = input.try(|i| CSSColor::parse(context, i)) {
                        background_color = Some(value);
                        continue
                    }
                }
                if position.is_none() {
                    if let Ok(value) = input.try(|input| Position::parse(context, input)) {
                        position = Some(value);

                        // Parse background size, if applicable.
                        size = input.try(|input| {
                            try!(input.expect_delim('/'));
                            background_size::single_value::parse(context, input)
                        }).ok();

                        continue
                    }
                }
                % for name in "image repeat attachment origin clip".split():
                    if ${name}.is_none() {
                        if let Ok(value) = input.try(|input| background_${name}::single_value
                                                                               ::parse(context, input)) {
                            ${name} = Some(value);
                            continue
                        }
                    }
                % endfor
                break
            }
            if clip.is_none() {
                if let Some(origin) = origin {
                    clip = Some(background_clip::single_value::SpecifiedValue::from(origin));
                }
            }
            let mut any = false;
            % for name in "image position repeat size attachment origin clip".split():
                any = any || ${name}.is_some();
            % endfor
            any = any || background_color.is_some();
            if any {
                if let Some(position) = position {
                    background_position_x.0.push(position.horizontal);
                    background_position_y.0.push(position.vertical);
                } else {
                    background_position_x.0.push(PositionComponent::zero());
                    background_position_y.0.push(PositionComponent::zero());
                }
                % for name in "image repeat size attachment origin clip".split():
                    if let Some(bg_${name}) = ${name} {
                        background_${name}.0.push(bg_${name});
                    } else {
                        background_${name}.0.push(background_${name}::single_value
                                                                    ::get_initial_specified_value());
                    }
                % endfor
                Ok(())
            } else {
                Err(())
            }
        }));

        Ok(expanded! {
             background_color: background_color.unwrap_or(CSSColor::transparent()),
             background_image: background_image,
             background_position_x: background_position_x,
             background_position_y: background_position_y,
             background_repeat: background_repeat,
             background_attachment: background_attachment,
             background_size: background_size,
             background_origin: background_origin,
             background_clip: background_clip,
         })
    }

    impl<'a> ToCss for LonghandsToSerialize<'a>  {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            let len = self.background_image.0.len();
            // There should be at least one declared value
            if len == 0 {
                return Ok(());
            }

            // If a value list length is differs then we don't do a shorthand serialization.
            // The exceptions to this is color which appears once only and is serialized
            // with the last item.
            % for name in "image position_x position_y size repeat origin clip attachment".split():
                if len != self.background_${name}.0.len() {
                    return Ok(());
                }
            % endfor

            for i in 0..len {
                % for name in "image position_x position_y repeat size attachment origin clip".split():
                    let ${name} = &self.background_${name}.0[i];
                % endfor

                if i != 0 {
                    try!(write!(dest, ", "));
                }

                if i == len - 1 {
                    try!(self.background_color.to_css(dest));
                    try!(write!(dest, " "));
                }

                try!(image.to_css(dest));
                % for name in "repeat attachment".split():
                    try!(write!(dest, " "));
                    try!(${name}.to_css(dest));
                % endfor

                try!(write!(dest, " "));
                Position {
                    horizontal: position_x.clone(),
                    vertical: position_y.clone()
                }.to_css(dest)?;

                if *size != background_size::single_value::get_initial_specified_value() {
                    try!(write!(dest, " / "));
                    try!(size.to_css(dest));
                }

                if *origin != Origin::padding_box || *clip != Clip::border_box {
                    try!(write!(dest, " "));
                    try!(origin.to_css(dest));
                    if *clip != From::from(*origin) {
                        try!(write!(dest, " "));
                        try!(clip.to_css(dest));
                    }
                }
            }

            Ok(())
        }
    }
</%helpers:shorthand>

<%helpers:shorthand name="background-position"
                    sub_properties="background-position-x background-position-y"
                    spec="https://drafts.csswg.org/css-backgrounds-4/#the-background-position">
    use properties::longhands::{background_position_x, background_position_y};
    use values::specified::AllowQuirks;
    use values::specified::position::Position;

    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        let mut position_x = background_position_x::SpecifiedValue(Vec::new());
        let mut position_y = background_position_y::SpecifiedValue(Vec::new());
        let mut any = false;

        input.parse_comma_separated(|input| {
            let value = Position::parse_quirky(context, input, AllowQuirks::Yes)?;
            position_x.0.push(value.horizontal);
            position_y.0.push(value.vertical);
            any = true;
            Ok(())
        })?;
        if !any {
            return Err(());
        }

        Ok(expanded! {
            background_position_x: position_x,
            background_position_y: position_y,
        })
    }

    impl<'a> ToCss for LonghandsToSerialize<'a>  {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            let len = self.background_position_x.0.len();
            if len == 0 || len != self.background_position_y.0.len() {
                return Ok(());
            }
            for i in 0..len {
                Position {
                    horizontal: self.background_position_x.0[i].clone(),
                    vertical: self.background_position_y.0[i].clone()
                }.to_css(dest)?;

                if i < len - 1 {
                    dest.write_str(", ")?;
                }
            }
            Ok(())
        }
    }
</%helpers:shorthand>
<|endoftext|>


<commit_before>pub mod expression;

mod backend;
mod query_builder;
mod connection;
pub mod types;
pub mod upsert;

pub use self::backend::{Pg, PgTypeMetadata};
pub use self::connection::PgConnection;
pub use self::query_builder::PgQueryBuilder;

pub mod data_types {
    #[doc(inline)]
    pub use super::types::date_and_time::{PgTimestamp, PgDate, PgTime, PgInterval};
    #[doc(inline)]
    pub use super::types::floats::PgNumeric;
    #[doc(inline)]
    pub use super::types::money::PgMoney as Cents;
}
<commit_msg>export `PgMoney` in `pg::data_types` un-aliased as well<commit_after>pub mod expression;

mod backend;
mod query_builder;
mod connection;
pub mod types;
pub mod upsert;

pub use self::backend::{Pg, PgTypeMetadata};
pub use self::connection::PgConnection;
pub use self::query_builder::PgQueryBuilder;

pub mod data_types {
    #[doc(inline)]
    pub use super::types::date_and_time::{PgTimestamp, PgDate, PgTime, PgInterval};
    #[doc(inline)]
    pub use super::types::floats::PgNumeric;
    #[doc(inline)]
    pub use super::types::money::PgMoney;
    #[doc(inline)]
    pub use super::types::money::PgMoney as Cents;
}
<|endoftext|>


<commit_before>// Copyright(C) 2016 Chris Liebert
extern crate glium;
extern crate image;
extern crate nalgebra;

use std::collections::HashMap;
use std::io::ErrorKind;

use common;
use common::{Camera, Mesh, Scene, Shader, Vertex8f32};
use loader::DBLoader;

use glium::backend::glutin_backend::GlutinFacade;
use glium::{Program, Surface, Version};

implement_vertex!(Vertex8f32, position, normal, texcoord);

pub struct Renderer {
	pub index_buffer: glium::index::NoIndices,
	pub scene: Scene,
	pub textures: HashMap<String, glium::texture::CompressedSrgbTexture2d>,
	pub vertex_buffers: Vec<glium::vertex::VertexBuffer<common::Vertex8f32>>,
}

use std::io::Error;

impl Renderer {
	pub fn new(display: &GlutinFacade, scene: Scene) -> Renderer {

		let mut vertex_buffers: Vec<glium::vertex::VertexBuffer<common::Vertex8f32>> =
			Vec::with_capacity(scene.meshes.len());

		for i in 0..scene.meshes.len() {
			vertex_buffers.push(glium::vertex::VertexBuffer::new(display, &scene.meshes[i].vertices).unwrap());
		}

		let index_buffer: glium::index::NoIndices =
			glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList);

		let mut textures: HashMap<String, glium::texture::CompressedSrgbTexture2d> = HashMap::new();

		for i in 0..scene.images.len() {
			//TODO: determine image format by name extension if nessisary
			//let image = image::load_from_memory_with_format(&scene.images[i].image, image::PNG).unwrap().to_rgba();
			let image = image::load_from_memory(&scene.images[i].image).unwrap().to_rgba();

			let image_dimensions = image.dimensions();
			let image = glium::texture::RawImage2d::from_raw_rgba_reversed(image.into_raw(),
			                                                               image_dimensions);
			let opengl_texture: glium::texture::CompressedSrgbTexture2d =
				glium::texture::CompressedSrgbTexture2d::new(display, image).unwrap();
			textures.insert(scene.images[i].name.clone(), opengl_texture);
		}

		Renderer {
			index_buffer: index_buffer,
			scene: scene,
			textures: textures,
			vertex_buffers: vertex_buffers,
		}
	}

	pub fn get_mesh(&self, name: &str) -> Result<&Mesh, Error> {
		for i in 0..self.vertex_buffers.len() as usize {
			if self.scene.meshes[i].name.eq(name) {
				return Ok(&self.scene.meshes[i]);
			}
		}
		return Err(Error::new(ErrorKind::NotFound, "Unable to load mesh"));
	}

	#[allow(unused_assignments)]
	pub fn create_shader_program(&self, shader_name: &str, dbloader: &DBLoader, display: &GlutinFacade) -> glium::program::Program {
		let supported_glsl_version: Version = display.get_supported_glsl_version();
		let api: glium::Api = supported_glsl_version.0;
		let major_version : u8 = supported_glsl_version.1;
		let minor_version : u8 = supported_glsl_version.2;
		let mut glsl_version_string: String = major_version.to_string();
		glsl_version_string.push_str(&minor_version.to_string());
		glsl_version_string.push('0');
		let mut use_gles: bool = false;// Use OpenGLES instead of OpenGL (for mobile devices)

		match api {
				glium::Api::Gl => {
					use_gles = false;
				},
				glium::Api::GlEs => {
					use_gles = true;
					glsl_version_string.push_str(" es");
				},
		};

		let glsl_version_number: u32 = match glsl_version_string.parse() {
			Ok(s) => s,
			Err(e) =>  {
				// This is not likely to happen
				panic!("Unable to parse supported glsl version string: {}", e);
			},
		};

		println!("Using glsl version {}", &glsl_version_string);

		let shader: Shader = dbloader.load_shader(shader_name, &glsl_version_string);

		let program: Program;

		if use_gles {
			program = program!(display,
				glsl_version_number es => {
					vertex: &shader.vertex_source,
					fragment: &shader.fragment_source,
				},
			)
			.unwrap();
		} else {
			program = program!(display,
				glsl_version_number => {
					vertex: &shader.vertex_source,
					fragment: &shader.fragment_source,
				},
			)
			.unwrap();
		}

		// Shader compilation no longer required
		display.release_shader_compiler();
		return program;
	}

	pub fn render(&self, display: &GlutinFacade, program: &glium::program::Program, camera: &Camera) {
		let mut target = display.draw();
		// TODO: generate this texture instead of loading from sqlite
		let default_blank_texture = &self.textures["DEFAULT_BLANK_TEXTURE.png"];
		target.clear_color_and_depth((0.0, 0.0, 0.0, 0.0), 1.0);
		for i in 0..self.vertex_buffers.len() as usize {
			let material_index: usize = self.scene.meshes[i].material_index.clone();
			let diffuse = self.scene.materials[material_index].diffuse.clone();
			let diffuse_texname: String =
				self.scene.materials[material_index].diffuse_texname.clone();
			let opengl_texture: &glium::texture::CompressedSrgbTexture2d;
			if diffuse_texname.len() == 0 {
				opengl_texture = &default_blank_texture;
			} else {
				match self.textures.get(&diffuse_texname) {
					Some(t) => {
						opengl_texture = &t;
					},
					None => {
						println!("Unable to load {}, using blank texture instead.", diffuse_texname);
						opengl_texture = &default_blank_texture;
					},
				}
			}
			let uniforms: glium::uniforms::UniformsStorage<_, _> = uniform! {
				projection: *camera.projection_matrix.borrow(),
				modelview: *camera.modelview_matrix.borrow(),
				light_position_worldspace: [2.0, 10.0, 1.0f32],
				diffuse: diffuse,
				diffuse_texture: opengl_texture,
				model: *(*self.scene.meshes[i].matrix.borrow()).as_ref(),
			};

			let params = glium::DrawParameters {
	            depth: glium::Depth {
	                test: glium::DepthTest::IfLess,
	                write: true,
	                .. Default::default()
	            },
	            .. Default::default()
	        };

			target.draw(&self.vertex_buffers[i],
				&self.index_buffer,
				program,
				&uniforms,
				&params)
				.unwrap();
		}
		target.finish().unwrap();
	}
}
<commit_msg>Added additional method for attempting to load specific shader GLSL versions.<commit_after>// Copyright(C) 2016 Chris Liebert
extern crate glium;
extern crate image;
extern crate nalgebra;

use std::collections::HashMap;
use std::io::Error;
use std::io::ErrorKind;

use common;
use common::{Camera, Mesh, Scene, Shader, Vertex8f32};
use loader::DBLoader;

use glium::backend::glutin_backend::GlutinFacade;
use glium::{Program, Surface, Version};

implement_vertex!(Vertex8f32, position, normal, texcoord);

pub struct Renderer {
	pub index_buffer: glium::index::NoIndices,
	pub scene: Scene,
	pub textures: HashMap<String, glium::texture::CompressedSrgbTexture2d>,
	pub vertex_buffers: Vec<glium::vertex::VertexBuffer<common::Vertex8f32>>,
}

impl Renderer {
	pub fn new(display: &GlutinFacade, scene: Scene) -> Renderer {

		let mut vertex_buffers: Vec<glium::vertex::VertexBuffer<common::Vertex8f32>> =
			Vec::with_capacity(scene.meshes.len());

		for i in 0..scene.meshes.len() {
			vertex_buffers.push(glium::vertex::VertexBuffer::new(display, &scene.meshes[i].vertices).unwrap());
		}

		let index_buffer: glium::index::NoIndices =
			glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList);

		let mut textures: HashMap<String, glium::texture::CompressedSrgbTexture2d> = HashMap::new();

		for i in 0..scene.images.len() {
			//TODO: determine image format by name extension if nessisary
			//let image = image::load_from_memory_with_format(&scene.images[i].image, image::PNG).unwrap().to_rgba();
			let image = image::load_from_memory(&scene.images[i].image).unwrap().to_rgba();

			let image_dimensions = image.dimensions();
			let image = glium::texture::RawImage2d::from_raw_rgba_reversed(image.into_raw(),
			                                                               image_dimensions);
			let opengl_texture: glium::texture::CompressedSrgbTexture2d =
				glium::texture::CompressedSrgbTexture2d::new(display, image).unwrap();
			textures.insert(scene.images[i].name.clone(), opengl_texture);
		}

		Renderer {
			index_buffer: index_buffer,
			scene: scene,
			textures: textures,
			vertex_buffers: vertex_buffers,
		}
	}

	pub fn get_mesh(&self, name: &str) -> Result<&Mesh, Error> {
		for i in 0..self.vertex_buffers.len() as usize {
			if self.scene.meshes[i].name.eq(name) {
				return Ok(&self.scene.meshes[i]);
			}
		}
		return Err(Error::new(ErrorKind::NotFound, "Unable to load mesh"));
	}

	#[allow(unused_assignments)]
	pub fn create_shader_program(&self, shader_name: &str, dbloader: &DBLoader, display: &GlutinFacade) -> glium::program::Program {
		let supported_glsl_version: Version = display.get_supported_glsl_version();
		let api: glium::Api = supported_glsl_version.0;
		let major_version : u8 = supported_glsl_version.1;
		let minor_version : u8 = supported_glsl_version.2;
		let mut glsl_version_string: String = major_version.to_string();
		glsl_version_string.push_str(&minor_version.to_string());
		glsl_version_string.push('0');
		let mut use_gles: bool = false;// Use OpenGLES instead of OpenGL (for mobile devices)

		match api {
				glium::Api::Gl => {
					use_gles = false;
				},
				glium::Api::GlEs => {
					use_gles = true;
					glsl_version_string.push_str(" es");
				},
		};

		let glsl_version_number: u32 = match glsl_version_string.parse() {
			Ok(s) => s,
			Err(e) =>  {
				// This is not likely to happen
				panic!("Unable to parse supported glsl version string: {}", e);
			},
		};

		println!("Using glsl version {}", &glsl_version_string);

		let shader: Shader = dbloader.load_shader(shader_name, &glsl_version_string);

		let program: Program;

		if use_gles {
			program = program!(display,
				glsl_version_number es => {
					vertex: &shader.vertex_source,
					fragment: &shader.fragment_source,
				},
			)
			.unwrap();
		} else {
			program = program!(display,
				glsl_version_number => {
					vertex: &shader.vertex_source,
					fragment: &shader.fragment_source,
				},
			)
			.unwrap();
		}

		// Shader compilation no longer required
		display.release_shader_compiler();
		return program;
	}

	pub fn create_shader_program_with_version(&self, shader_name: &str, dbloader: &DBLoader, glsl_version: &Version, display: &GlutinFacade) -> Result<glium::program::Program, Error> {
		if !display.is_glsl_version_supported(&glsl_version) {
			return Err(Error::new(ErrorKind::InvalidData, "Unsupported GLSL version"));
		}

		let api: glium::Api = glsl_version.0;
		let major_version : u8 = glsl_version.1;
		let minor_version : u8 = glsl_version.2;
		let mut glsl_version_string: String = major_version.to_string();
		glsl_version_string.push_str(&minor_version.to_string());
		glsl_version_string.push('0');
		let mut use_gles: bool = false;// Use OpenGLES instead of OpenGL (for mobile devices)

		match api {
				glium::Api::Gl => {
					use_gles = false;
				},
				glium::Api::GlEs => {
					use_gles = true;
					glsl_version_string.push_str(" es");
				},
		};

		let glsl_version_number: u32 = match glsl_version_string.parse() {
			Ok(s) => s,
			Err(e) =>  {
				// This is not likely to happen
				panic!("Unable to parse supported glsl version string: {}", e);
			},
		};

		println!("Using glsl version {}", &glsl_version_string);

		let shader: Shader = dbloader.load_shader(shader_name, &glsl_version_string);

		let program;

		if use_gles {
			program = program!(display,
				glsl_version_number es => {
					vertex: &shader.vertex_source,
					fragment: &shader.fragment_source,
				},
			)
		} else {
			program = program!(display,
				glsl_version_number => {
					vertex: &shader.vertex_source,
					fragment: &shader.fragment_source,
				},
			)
		}

		match program {
			Ok(p) => Ok(p),
			Err(e) => Err(Error::new(ErrorKind::InvalidData, e)),
		}
	}

	pub fn render(&self, display: &GlutinFacade, program: &glium::program::Program, camera: &Camera) {
		let mut target = display.draw();
		// TODO: generate this texture instead of loading from sqlite
		let default_blank_texture = &self.textures["DEFAULT_BLANK_TEXTURE.png"];
		target.clear_color_and_depth((0.0, 0.0, 0.0, 0.0), 1.0);
		for i in 0..self.vertex_buffers.len() as usize {
			let material_index: usize = self.scene.meshes[i].material_index.clone();
			let diffuse = self.scene.materials[material_index].diffuse.clone();
			let diffuse_texname: String =
				self.scene.materials[material_index].diffuse_texname.clone();
			let opengl_texture: &glium::texture::CompressedSrgbTexture2d;
			if diffuse_texname.len() == 0 {
				opengl_texture = &default_blank_texture;
			} else {
				match self.textures.get(&diffuse_texname) {
					Some(t) => {
						opengl_texture = &t;
					},
					None => {
						println!("Unable to load {}, using blank texture instead.", diffuse_texname);
						opengl_texture = &default_blank_texture;
					},
				}
			}
			let uniforms: glium::uniforms::UniformsStorage<_, _> = uniform! {
				projection: *camera.projection_matrix.borrow(),
				modelview: *camera.modelview_matrix.borrow(),
				light_position_worldspace: [2.0, 10.0, 1.0f32],
				diffuse: diffuse,
				diffuse_texture: opengl_texture,
				model: *(*self.scene.meshes[i].matrix.borrow()).as_ref(),
			};

			let params = glium::DrawParameters {
	            depth: glium::Depth {
	                test: glium::DepthTest::IfLess,
	                write: true,
	                .. Default::default()
	            },
	            .. Default::default()
	        };

			target.draw(&self.vertex_buffers[i],
				&self.index_buffer,
				program,
				&uniforms,
				&params)
				.unwrap();
		}
		target.finish().unwrap();
	}
}
<|endoftext|>


<commit_before>use ra_syntax::{
    AstNode,
    ast::{self, VisibilityOwner, NameOwner},
    SyntaxKind::{VISIBILITY, FN_KW, MOD_KW, STRUCT_KW, ENUM_KW, TRAIT_KW, FN_DEF, MODULE, STRUCT_DEF, ENUM_DEF, TRAIT_DEF, IDENT},
};

use crate::assists::{AssistCtx, Assist};

pub fn change_visibility(ctx: AssistCtx) -> Option<Assist> {
    if let Some(vis) = ctx.node_at_offset::<ast::Visibility>() {
        return change_vis(ctx, vis);
    }
    add_vis(ctx)
}

fn add_vis(ctx: AssistCtx) -> Option<Assist> {
    let item_keyword = ctx.leaf_at_offset().find(|leaf| match leaf.kind() {
        FN_KW | MOD_KW | STRUCT_KW | ENUM_KW | TRAIT_KW => true,
        _ => false,
    });

    let offset = if let Some(keyword) = item_keyword {
        let parent = keyword.parent()?;
        let def_kws = vec![FN_DEF, MODULE, STRUCT_DEF, ENUM_DEF, TRAIT_DEF];
        // Parent is not a definition, can't add visibility
        if !def_kws.iter().any(|&def_kw| def_kw == parent.kind()) {
            return None;
        }
        // Already have visibility, do nothing
        if parent.children().any(|child| child.kind() == VISIBILITY) {
            return None;
        }
        parent.range().start()
    } else {
        let ident = ctx.leaf_at_offset().find(|leaf| leaf.kind() == IDENT)?;
        let field = ident.ancestors().find_map(ast::NamedFieldDef::cast)?;
        if field.name()?.syntax().range() != ident.range() && field.visibility().is_some() {
            return None;
        }
        field.syntax().range().start()
    };

    ctx.build("make pub(crate)", |edit| {
        edit.insert(offset, "pub(crate) ");
        edit.set_cursor(offset);
    })
}

fn change_vis(ctx: AssistCtx, vis: &ast::Visibility) -> Option<Assist> {
    if vis.syntax().text() != "pub" {
        return None;
    }
    ctx.build("chage to pub(crate)", |edit| {
        edit.replace(vis.syntax().range(), "pub(crate)");
        edit.set_cursor(vis.syntax().range().start());
    })
}

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

    #[test]
    fn change_visibility_adds_pub_crate_to_items() {
        check_assist(
            change_visibility,
            "<|>fn foo() {}",
            "<|>pub(crate) fn foo() {}",
        );
        check_assist(
            change_visibility,
            "f<|>n foo() {}",
            "<|>pub(crate) fn foo() {}",
        );
        check_assist(
            change_visibility,
            "<|>struct Foo {}",
            "<|>pub(crate) struct Foo {}",
        );
        check_assist(
            change_visibility,
            "<|>mod foo {}",
            "<|>pub(crate) mod foo {}",
        );
        check_assist(
            change_visibility,
            "<|>trait Foo {}",
            "<|>pub(crate) trait Foo {}",
        );
        check_assist(change_visibility, "m<|>od {}", "<|>pub(crate) mod {}");
        check_assist(
            change_visibility,
            "unsafe f<|>n foo() {}",
            "<|>pub(crate) unsafe fn foo() {}",
        );
    }

    #[test]
    fn change_visibility_works_with_struct_fields() {
        check_assist(
            change_visibility,
            "struct S { <|>field: u32 }",
            "struct S { <|>pub(crate) field: u32 }",
        )
    }

    #[test]
    fn change_visibility_pub_to_pub_crate() {
        check_assist(
            change_visibility,
            "<|>pub fn foo() {}",
            "<|>pub(crate) fn foo() {}",
        )
    }
}
<commit_msg>better change visibility assist<commit_after>use ra_syntax::{
    AstNode, SyntaxNode, TextUnit,
    ast::{self, VisibilityOwner, NameOwner},
    SyntaxKind::{VISIBILITY, FN_KW, MOD_KW, STRUCT_KW, ENUM_KW, TRAIT_KW, FN_DEF, MODULE, STRUCT_DEF, ENUM_DEF, TRAIT_DEF, IDENT, WHITESPACE, COMMENT, ATTR},
};

use crate::assists::{AssistCtx, Assist};

pub fn change_visibility(ctx: AssistCtx) -> Option<Assist> {
    if let Some(vis) = ctx.node_at_offset::<ast::Visibility>() {
        return change_vis(ctx, vis);
    }
    add_vis(ctx)
}

fn add_vis(ctx: AssistCtx) -> Option<Assist> {
    let item_keyword = ctx.leaf_at_offset().find(|leaf| match leaf.kind() {
        FN_KW | MOD_KW | STRUCT_KW | ENUM_KW | TRAIT_KW => true,
        _ => false,
    });

    let offset = if let Some(keyword) = item_keyword {
        let parent = keyword.parent()?;
        let def_kws = vec![FN_DEF, MODULE, STRUCT_DEF, ENUM_DEF, TRAIT_DEF];
        // Parent is not a definition, can't add visibility
        if !def_kws.iter().any(|&def_kw| def_kw == parent.kind()) {
            return None;
        }
        // Already have visibility, do nothing
        if parent.children().any(|child| child.kind() == VISIBILITY) {
            return None;
        }
        vis_offset(parent)
    } else {
        let ident = ctx.leaf_at_offset().find(|leaf| leaf.kind() == IDENT)?;
        let field = ident.ancestors().find_map(ast::NamedFieldDef::cast)?;
        if field.name()?.syntax().range() != ident.range() && field.visibility().is_some() {
            return None;
        }
        vis_offset(field.syntax())
    };

    ctx.build("make pub(crate)", |edit| {
        edit.insert(offset, "pub(crate) ");
        edit.set_cursor(offset);
    })
}

fn vis_offset(node: &SyntaxNode) -> TextUnit {
    node.children()
        .skip_while(|it| match it.kind() {
            WHITESPACE | COMMENT | ATTR => true,
            _ => false,
        })
        .next()
        .map(|it| it.range().start())
        .unwrap_or(node.range().start())
}

fn change_vis(ctx: AssistCtx, vis: &ast::Visibility) -> Option<Assist> {
    if vis.syntax().text() == "pub" {
        return ctx.build("chage to pub(crate)", |edit| {
            edit.replace(vis.syntax().range(), "pub(crate)");
            edit.set_cursor(vis.syntax().range().start());
        });
    }
    if vis.syntax().text() == "pub(crate)" {
        return ctx.build("chage to pub", |edit| {
            edit.replace(vis.syntax().range(), "pub");
            edit.set_cursor(vis.syntax().range().start());
        });
    }
    None
}

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

    #[test]
    fn change_visibility_adds_pub_crate_to_items() {
        check_assist(
            change_visibility,
            "<|>fn foo() {}",
            "<|>pub(crate) fn foo() {}",
        );
        check_assist(
            change_visibility,
            "f<|>n foo() {}",
            "<|>pub(crate) fn foo() {}",
        );
        check_assist(
            change_visibility,
            "<|>struct Foo {}",
            "<|>pub(crate) struct Foo {}",
        );
        check_assist(
            change_visibility,
            "<|>mod foo {}",
            "<|>pub(crate) mod foo {}",
        );
        check_assist(
            change_visibility,
            "<|>trait Foo {}",
            "<|>pub(crate) trait Foo {}",
        );
        check_assist(change_visibility, "m<|>od {}", "<|>pub(crate) mod {}");
        check_assist(
            change_visibility,
            "unsafe f<|>n foo() {}",
            "<|>pub(crate) unsafe fn foo() {}",
        );
    }

    #[test]
    fn change_visibility_works_with_struct_fields() {
        check_assist(
            change_visibility,
            "struct S { <|>field: u32 }",
            "struct S { <|>pub(crate) field: u32 }",
        )
    }

    #[test]
    fn change_visibility_pub_to_pub_crate() {
        check_assist(
            change_visibility,
            "<|>pub fn foo() {}",
            "<|>pub(crate) fn foo() {}",
        )
    }

    #[test]
    fn change_visibility_pub_crate_to_pub() {
        check_assist(
            change_visibility,
            "<|>pub(crate) fn foo() {}",
            "<|>pub fn foo() {}",
        )
    }

    #[test]
    fn change_visibility_handles_comment_attrs() {
        check_assist(
            change_visibility,
            "
            /// docs

            // comments

            #[derive(Debug)]
            <|>struct Foo;
            ",
            "
            /// docs

            // comments

            #[derive(Debug)]
            <|>pub(crate) struct Foo;
            ",
        )
    }
}
<|endoftext|>


<commit_before>use core::intrinsics::{transmute, size_of};
use core::fmt::Write;

use arch;

pub use drv;

extern {
    static _selftest_start: u8;
    static _selftest_end: u8;
}

pub type TestFn = fn (mut uart : &mut drv::uart::UartWriter) -> bool;

#[packed]
pub struct TestEntry {
    pub func : TestFn,
    pub name : &'static str,
}

#[macro_export]
#[cfg(feature = "selftest")]
macro_rules! selftest {
    ($name:ident ($uart:ident : $uart_t:ty) $code:block) => {

        fn $name($uart: $uart_t) -> bool {

            use ::titanium::selftest::TestEntry;

            static TEST_ENTRY : TestEntry = TestEntry {
                func: $name,
                name: stringify!($name),
            };

            #[allow(dead_code)]
            #[link_section = ".titanium.selftest"]
            static TEST_ENTRY_P : &'static TestEntry = &TEST_ENTRY;

            $code
        }
    }
}

#[macro_export]
#[cfg(not(feature = "selftest"))]
macro_rules! selftest {
    ($name:ident ($uart:ident : $uart_t:ty) $code:block) => {

        #[link_section = ".titanium.discard"]
        fn $name($uart: $uart_t) -> bool {

            use ::titanium::selftest::TestEntry;

            static TEST_ENTRY : TestEntry = TestEntry {
                func: $name,
                name: stringify!($name),
            };

            #[allow(dead_code)]
            #[link_section = ".titanium.discard"]
            static TEST_ENTRY_P : &'static TestEntry = &TEST_ENTRY;

            $code
        }
    }
}

/// Start selftest
#[allow(dead_code)]
fn selftest_run(mut uart : &mut drv::uart::UartWriter) {

    let start : usize = &_selftest_start as *const _ as usize;
    let end : usize = &_selftest_end as *const _ as usize;

    let mut err_i = 0u32;
    let mut ok_i = 0u32;

    write!(uart, "SELFTEST START\n").unwrap();
    for addr in (start..end).step_by(unsafe {size_of::<usize>()}) {

        let t : &TestEntry = {
            unsafe {
                let addr : &usize = transmute(addr);
                transmute(*addr)
            }
        };

        write!(uart, "{}...", t.name).unwrap();
        let ret = (t.func)(uart);
        if ret {
            ok_i += 1;
            write!(uart, " OK\n").unwrap();
        } else {
            err_i += 1;
            write!(uart, " FAIL\n").unwrap();
        }

    }
    write!(uart, "SELFTEST END: {} ERR; {} OK; {} TOTAL\n", err_i, ok_i, ok_i + err_i).unwrap();

    arch::semihosting::exit();
}

#[cfg(feature = "selftest")]
pub fn selftest(uart : &mut drv::uart::UartWriter) {
    selftest_run(uart);
}

#[cfg(not(feature = "selftest"))]
pub fn selftest(_ : &mut drv::uart::UartWriter) {}
<commit_msg>Add FIXME.<commit_after>use core::intrinsics::{transmute, size_of};
use core::fmt::Write;

use arch;

pub use drv;

extern {
    static _selftest_start: u8;
    static _selftest_end: u8;
}

pub type TestFn = fn (mut uart : &mut drv::uart::UartWriter) -> bool;

#[packed]
pub struct TestEntry {
    pub func : TestFn,
    pub name : &'static str,
}

#[macro_export]
#[cfg(feature = "selftest")]
macro_rules! selftest {
    ($name:ident ($uart:ident : $uart_t:ty) $code:block) => {

        fn $name($uart: $uart_t) -> bool {

            use ::titanium::selftest::TestEntry;

            static TEST_ENTRY : TestEntry = TestEntry {
                func: $name,
                name: stringify!($name),
            };

            /* FIXME: TODO: Rustc will not emit this :(
             * We need __attribute__((used)) or a workaround. */
            #[allow(dead_code)]
            #[link_section = ".titanium.selftest"]
            static TEST_ENTRY_P : &'static TestEntry = &TEST_ENTRY;

            $code
        }
    }
}

#[macro_export]
#[cfg(not(feature = "selftest"))]
macro_rules! selftest {
    ($name:ident ($uart:ident : $uart_t:ty) $code:block) => {

        #[link_section = ".titanium.discard"]
        fn $name($uart: $uart_t) -> bool {

            use ::titanium::selftest::TestEntry;

            static TEST_ENTRY : TestEntry = TestEntry {
                func: $name,
                name: stringify!($name),
            };

            #[allow(dead_code)]
            #[link_section = ".titanium.discard"]
            static TEST_ENTRY_P : &'static TestEntry = &TEST_ENTRY;

            $code
        }
    }
}

/// Start selftest
#[allow(dead_code)]
fn selftest_run(mut uart : &mut drv::uart::UartWriter) {

    let start : usize = &_selftest_start as *const _ as usize;
    let end : usize = &_selftest_end as *const _ as usize;

    let mut err_i = 0u32;
    let mut ok_i = 0u32;

    write!(uart, "SELFTEST START\n").unwrap();
    for addr in (start..end).step_by(unsafe {size_of::<usize>()}) {

        let t : &TestEntry = {
            unsafe {
                let addr : &usize = transmute(addr);
                transmute(*addr)
            }
        };

        write!(uart, "{}...", t.name).unwrap();
        let ret = (t.func)(uart);
        if ret {
            ok_i += 1;
            write!(uart, " OK\n").unwrap();
        } else {
            err_i += 1;
            write!(uart, " FAIL\n").unwrap();
        }

    }
    write!(uart, "SELFTEST END: {} ERR; {} OK; {} TOTAL\n", err_i, ok_i, ok_i + err_i).unwrap();

    arch::semihosting::exit();
}

#[cfg(feature = "selftest")]
pub fn selftest(uart : &mut drv::uart::UartWriter) {
    selftest_run(uart);
}

#[cfg(not(feature = "selftest"))]
pub fn selftest(_ : &mut drv::uart::UartWriter) {}
<|endoftext|>