<commit_before>use super::*;
use byteorder::BigEndian;
use byteorder::WriteBytesExt;
use client;
use futures::prelude::*;
use index::btree;
use index::btree::test::u64_to_slice;
use index::key_with_id;
use index::lsmtree::tree::KeyRange;
use index::lsmtree::tree::LSMTree;
use index::Cursor;
use index::Ordering;
use itertools::Itertools;
use ram::types::Id;
use rand::distributions::Uniform;
use rand::thread_rng;
use rand::Rng;
use rayon::prelude::*;
use server::NebServer;
use server::ServerOptions;
use smallvec::SmallVec;
use std::env;
use std::io::Cursor as StdCursor;
use std::sync::Arc;
use std::thread;
use std::time::Duration;

fn dump_trees(lsm_tree: &LSMTree, name: &str) {
    for i in 0..lsm_tree.trees.len() {
        lsm_tree.trees[i].dump(&format!("{}_lsm_{}_dump.json", name, i));
    }
}

fn default_key_range() -> KeyRange {
    (smallvec!(), smallvec!())
}

#[test]
pub fn insertions() {
    env_logger::init();
    let tree = Arc::new(LSMTree::new(default_key_range(), Id::unit_id()));
    let num = env::var("LSM_TREE_TEST_ITEMS")
        // this value cannot do anything useful to the test
        // must arrange a long-term test to cover every levels
        .unwrap_or("331776".to_string())
        .parse::<u64>()
        .unwrap();

    let tree_clone = tree.clone();
    debug!("Testing LSM-tree");
    thread::spawn(move || loop {
        thread::sleep(Duration::from_secs(10));
        let tree_len = tree_clone.len();
        debug!(
            "LSM-Tree now have {}/{} elements, total {:.2}%",
            tree_len,
            num,
            tree_len as f32 / num as f32 * 100.0
        );
    });

    (0..num).collect::<Vec<_>>().par_iter().for_each(|i| {
        let i = *i;
        let id = Id::new(0, i);
        let key_slice = u64_to_slice(i);
        let mut key = SmallVec::from_slice(&key_slice);
        key_with_id(&mut key, &id);
        tree.insert(key);
    });

    debug!("Start point search validations");
    tree.ensure_trees_in_order();
    (0..num).collect::<Vec<_>>().par_iter().for_each(|i| {
        let i = *i;
        let id = Id::new(0, i);
        let key_slice = u64_to_slice(i);
        let mut key = SmallVec::from_slice(&key_slice);
        debug!("checking: {}", i);
        let cursor = tree.seek(&key, Ordering::Forward);
        key_with_id(&mut key, &id);
        assert_eq!(cursor.current(), Some(&key), "{}", i);
    });

    dump_trees(&*tree, "stage_1_before_insertion");
    for _ in 0..50 {
        tree.check_and_merge();
    }
    dump_trees(&*tree, "stage_1_after_insertion");

    debug!("Start point search validations");
    (0..num).collect::<Vec<_>>().iter().for_each(|i| {
        let i = *i;
        let id = Id::new(0, i);
        let key_slice = u64_to_slice(i);
        let mut key = SmallVec::from_slice(&key_slice);
        debug!("checking: {}", i);
        let cursor = tree.seek(&key, Ordering::Forward);
        key_with_id(&mut key, &id);
        assert_eq!(cursor.current(), Some(&key), "{}, looking for {:?}", i, key);
    });
}

#[test]
pub fn hybrid() {
    env_logger::init();
    let tree = Arc::new(LSMTree::new(default_key_range(), Id::unit_id()));
    let num = env::var("LSM_TREE_TEST_ITEMS")
        // this value cannot do anything useful to the test
        // must arrange a long-term test to cover every levels
        .unwrap_or("663552".to_string())
        .parse::<u64>()
        .unwrap();

    LSMTree::start_sentinel(&tree);
    let tree_clone = tree.clone();
    debug!("Testing LSM-tree");
    thread::spawn(move || loop {
        thread::sleep(Duration::from_secs(10));
        let tree_len = tree_clone.len();
        debug!(
            "LSM-Tree now have {}/{} elements, total {:.2}%",
            tree_len,
            num,
            tree_len as f32 / num as f32 * 100.0
        );
    });

    let mut test_data = (0..num).collect_vec();
    thread_rng().shuffle(test_data.as_mut_slice());
    test_data.par_iter().for_each(|i| {
        let i = *i;
        let id = Id::new(0, i);
        let key_slice = u64_to_slice(i);
        let mut key = SmallVec::from_slice(&key_slice);
        key_with_id(&mut key, &id);
        tree.insert(key);
    });

    tree.ensure_trees_in_order();
    dump_trees(&*tree, "hybird_after_insertion");
    thread::sleep(Duration::new(30, 0));
    dump_trees(&*tree, "hybird_after_sleep");
    tree.ensure_trees_in_order();

    debug!("Start point search validations");
    (0..num).collect::<Vec<_>>().par_iter().for_each(|i| {
        let i = *i;
        let id = Id::new(0, i);
        let key_slice = u64_to_slice(i);
        let mut key = SmallVec::from_slice(&key_slice);
        debug!("checking: {}", i);
        let cursor = tree.seek(&key, Ordering::Forward);
        key_with_id(&mut key, &id);
        assert_eq!(cursor.current(), Some(&key), "{}", i);
    });
}
<commit_msg>remove par validation<commit_after>use super::*;
use byteorder::BigEndian;
use byteorder::WriteBytesExt;
use client;
use futures::prelude::*;
use index::btree;
use index::btree::test::u64_to_slice;
use index::key_with_id;
use index::lsmtree::tree::KeyRange;
use index::lsmtree::tree::LSMTree;
use index::Cursor;
use index::Ordering;
use itertools::Itertools;
use ram::types::Id;
use rand::distributions::Uniform;
use rand::thread_rng;
use rand::Rng;
use rayon::prelude::*;
use server::NebServer;
use server::ServerOptions;
use smallvec::SmallVec;
use std::env;
use std::io::Cursor as StdCursor;
use std::sync::Arc;
use std::thread;
use std::time::Duration;

fn dump_trees(lsm_tree: &LSMTree, name: &str) {
    for i in 0..lsm_tree.trees.len() {
        lsm_tree.trees[i].dump(&format!("{}_lsm_{}_dump.json", name, i));
    }
}

fn default_key_range() -> KeyRange {
    (smallvec!(), smallvec!())
}

#[test]
pub fn insertions() {
    env_logger::init();
    let tree = Arc::new(LSMTree::new(default_key_range(), Id::unit_id()));
    let num = env::var("LSM_TREE_TEST_ITEMS")
        // this value cannot do anything useful to the test
        // must arrange a long-term test to cover every levels
        .unwrap_or("331776".to_string())
        .parse::<u64>()
        .unwrap();

    let tree_clone = tree.clone();
    debug!("Testing LSM-tree");
    thread::spawn(move || loop {
        thread::sleep(Duration::from_secs(10));
        let tree_len = tree_clone.len();
        debug!(
            "LSM-Tree now have {}/{} elements, total {:.2}%",
            tree_len,
            num,
            tree_len as f32 / num as f32 * 100.0
        );
    });

    (0..num).collect::<Vec<_>>().par_iter().for_each(|i| {
        let i = *i;
        let id = Id::new(0, i);
        let key_slice = u64_to_slice(i);
        let mut key = SmallVec::from_slice(&key_slice);
        key_with_id(&mut key, &id);
        tree.insert(key);
    });

    debug!("Start point search validations");
    tree.ensure_trees_in_order();
    (0..num).collect::<Vec<_>>().par_iter().for_each(|i| {
        let i = *i;
        let id = Id::new(0, i);
        let key_slice = u64_to_slice(i);
        let mut key = SmallVec::from_slice(&key_slice);
        debug!("checking: {}", i);
        let cursor = tree.seek(&key, Ordering::Forward);
        key_with_id(&mut key, &id);
        assert_eq!(cursor.current(), Some(&key), "{}", i);
    });

    dump_trees(&*tree, "stage_1_before_insertion");
    for _ in 0..50 {
        tree.check_and_merge();
    }
    dump_trees(&*tree, "stage_1_after_insertion");

    debug!("Start point search validations");
    (0..num).collect::<Vec<_>>().iter().for_each(|i| {
        let i = *i;
        let id = Id::new(0, i);
        let key_slice = u64_to_slice(i);
        let mut key = SmallVec::from_slice(&key_slice);
        debug!("checking: {}", i);
        let cursor = tree.seek(&key, Ordering::Forward);
        key_with_id(&mut key, &id);
        assert_eq!(cursor.current(), Some(&key), "{}, looking for {:?}", i, key);
    });
}

#[test]
pub fn hybrid() {
    env_logger::init();
    let tree = Arc::new(LSMTree::new(default_key_range(), Id::unit_id()));
    let num = env::var("LSM_TREE_TEST_ITEMS")
        // this value cannot do anything useful to the test
        // must arrange a long-term test to cover every levels
        .unwrap_or("663552".to_string())
        .parse::<u64>()
        .unwrap();

    LSMTree::start_sentinel(&tree);
    let tree_clone = tree.clone();
    debug!("Testing LSM-tree");
    thread::spawn(move || loop {
        thread::sleep(Duration::from_secs(10));
        let tree_len = tree_clone.len();
        debug!(
            "LSM-Tree now have {}/{} elements, total {:.2}%",
            tree_len,
            num,
            tree_len as f32 / num as f32 * 100.0
        );
    });

    let mut test_data = (0..num).collect_vec();
    thread_rng().shuffle(test_data.as_mut_slice());
    test_data.par_iter().for_each(|i| {
        let i = *i;
        let id = Id::new(0, i);
        let key_slice = u64_to_slice(i);
        let mut key = SmallVec::from_slice(&key_slice);
        key_with_id(&mut key, &id);
        tree.insert(key);
    });

    tree.ensure_trees_in_order();
    dump_trees(&*tree, "hybird_after_insertion");
    thread::sleep(Duration::new(30, 0));
    dump_trees(&*tree, "hybird_after_sleep");
    tree.ensure_trees_in_order();

    debug!("Start point search validations");
    (0..num).collect::<Vec<_>>().iter().for_each(|i| {
        let i = *i;
        let id = Id::new(0, i);
        let key_slice = u64_to_slice(i);
        let mut key = SmallVec::from_slice(&key_slice);
        debug!("checking: {}", i);
        let cursor = tree.seek(&key, Ordering::Forward);
        key_with_id(&mut key, &id);
        assert_eq!(cursor.current(), Some(&key), "{}", i);
    });
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate quote;
extern crate reqwest;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate lazy_static;

use std::fs::File;
use serde_json::{ Value, Map };
use std::collections::HashSet;

mod util;

use util::*;

mod errors {
    error_chain! {
        types {
            Error, ErrorKind, ResultExt, Result;
        }

        links {
        }

        foreign_links {
            ReqwestError(::reqwest::Error);
            JsonError(::serde_json::Error);
            IoError(::std::io::Error);
        }

        errors {
            MissingSource {
                description("No source for sample specified")
            }
            ExistingType(t: String) {
                display("No code generated, JSON matches existing type {}", t)
            }
        }
    }
}

pub use errors::*;

const RUST_KEYWORDS_ARR: &'static [&'static str] = &["abstract", "alignof", "as", "become", "box",
    "break", "const", "continue", "crate", "do", "else", "enum", "extern", "false", "final", "fn",
    "for", "if", "impl", "in", "let", "loop", "macro", "match", "mod", "move", "mut", "offsetof",
    "override", "priv", "proc", "pub", "pure", "ref", "return", "Self", "self", "sizeof", "static",
    "struct", "super", "trait", "true", "type", "typeof", "unsafe", "unsized", "use", "virtual",
    "where", "while", "yield"];

lazy_static! {
    static ref RUST_KEYWORDS: HashSet<&'static str> = {
        RUST_KEYWORDS_ARR.iter().cloned().collect()
    };
}

pub enum SampleSource<'a> {
    Url(&'a str),
    File(&'a str),
    Text(&'a str),
}

pub struct Options {
    use_serde: bool,
    extern_crate: bool,
    runnable_example: bool
}

impl Default for Options {
    fn default() -> Options {
        Options {
            use_serde: true,
            extern_crate: false,
            runnable_example: false
        }
    }
}

struct Ctxt {
    options: Options
}

pub fn codegen_from_sample(name: &str, source: SampleSource) -> Result<quote::Tokens> {
    let sample = get_and_parse_sample(source)?;
    let mut ctxt = Ctxt {
        options: Options::default()
    };
    let (type_name, type_def) = generate_type_from_value(&mut ctxt, name, &sample);

    let example = if ctxt.options.runnable_example {
        ctxt.options.extern_crate = true;
        Some(usage_example(&type_name))
    } else {
        None
    };

    let crates = if ctxt.options.extern_crate {
        Some(quote! {
            #[macro_use]
            extern crate serde_derive;

            extern crate serde_json;
        })
    } else {
        None
    };

    if type_def.is_none() && !ctxt.options.runnable_example {
        return Err(ErrorKind::ExistingType(String::from(type_name.as_str())).into());
    }

    Ok(quote! {
        #crates

        #type_def

        #example
    })
}

fn usage_example(type_id: &quote::Tokens) -> quote::Tokens {
    let var_id = quote::Ident::from(snake_case(type_id.as_str()));

    quote! {
        fn main() {
            let #var_id: #type_id = Default::default();

            let serialized = serde_json::to_string(&#var_id).unwrap();

            println!("serialized = {}", serialized);

            let deserialized: #type_id = serde_json::from_str(&serialized).unwrap();

            println!("deserialized = {:?}", deserialized);
        }
    }
}

fn generate_type_from_value(ctxt: &mut Ctxt, path: &str, value: &Value) -> (quote::Tokens, Option<quote::Tokens>) {
    match *value {
        Value::Null => (quote!{ Option<::serde_json::Value> }, None),
        Value::Bool(_) => (quote!{ bool }, None),
        Value::Number(ref n) => {
            if n.is_i64() {
                (quote!{ i64 }, None)
            } else {
                (quote!{ f64 }, None)
            }
        },
        Value::String(_) => (quote!{ String }, None),
        Value::Array(ref values) => {
            generate_type_for_array(ctxt, path, values)
        },
        Value::Object(ref map) => {
            generate_struct_from_object(ctxt, path, map)
        }
    }
}

fn generate_type_for_array(ctxt: &mut Ctxt, path: &str, values: &Vec<Value>) -> (quote::Tokens, Option<quote::Tokens>) {
    let mut defs = Vec::new();
    let mut types = HashSet::new();

    for value in values.iter() {
        let (elemtype, elemtype_def) = generate_type_from_value(ctxt, path, value);
        types.insert(elemtype.into_string());
        if let Some(def) = elemtype_def {
            defs.push(def);
        }
    }

    if types.len() == 1 {
        let ident = quote::Ident::new(types.into_iter().next().unwrap());
        (quote! { Vec<#ident> }, defs.into_iter().next())
    } else {
        (quote! { Vec<::serde_json::Value> }, None)
    }
}

fn generate_struct_from_object(ctxt: &mut Ctxt, path: &str, map: &Map<String, Value>) -> (quote::Tokens, Option<quote::Tokens>) {
    let type_name = type_case(path);
    let ident = quote::Ident::new(&type_name as &str);
    let mut defs = Vec::new();

    let fields: Vec<quote::Tokens> = map.iter()
        .map(|(name, value)| {
            let mut field_name = snake_case(name);
            if RUST_KEYWORDS.contains::<str>(&field_name) {
                field_name.push_str("_field")
            }
            let rename = if &field_name == name {
                None
            } else {
                Some(quote! { #[serde(rename = #name)] })
            };
            let field_ident = quote::Ident::new(&field_name as &str);
            let (fieldtype, fieldtype_def) = generate_type_from_value(ctxt, name, value);
            if let Some(def) = fieldtype_def {
                defs.push(def);
            }
            quote! {
                #rename
                #field_ident: #fieldtype
            }
        })
        .collect();

    let derives = if ctxt.options.use_serde {
        quote! { #[derive(Default, Debug, Clone, Serialize, Deserialize)] }
    } else {
        quote! { #[derive(Default, Debug, Clone)] }
    };

    let code = quote! {
        #derives
        struct #ident {
            #(#fields),*
        }

        #(#defs)*
    };

    (quote! { #ident }, Some(code))
}

fn get_and_parse_sample(source: SampleSource) -> Result<Value> {
    let parse_result = match source {
        SampleSource::Url(url) => serde_json::de::from_reader(reqwest::get(url)?),
        SampleSource::File(path) => serde_json::de::from_reader(File::open(path)?),
        SampleSource::Text(text) => serde_json::from_str(text),
    };
    Ok(parse_result.chain_err(|| "Unable to parse JSON sample")?)
}
<commit_msg>shared: Add macro some_if! => if x Some else None<commit_after>#[macro_use]
extern crate quote;
extern crate reqwest;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate lazy_static;

use std::fs::File;
use serde_json::{ Value, Map };
use std::collections::HashSet;

mod util;

use util::*;

mod errors {
    error_chain! {
        types {
            Error, ErrorKind, ResultExt, Result;
        }

        links {
        }

        foreign_links {
            ReqwestError(::reqwest::Error);
            JsonError(::serde_json::Error);
            IoError(::std::io::Error);
        }

        errors {
            MissingSource {
                description("No source for sample specified")
            }
            ExistingType(t: String) {
                display("No code generated, JSON matches existing type {}", t)
            }
        }
    }
}

pub use errors::*;

const RUST_KEYWORDS_ARR: &'static [&'static str] = &["abstract", "alignof", "as", "become", "box",
    "break", "const", "continue", "crate", "do", "else", "enum", "extern", "false", "final", "fn",
    "for", "if", "impl", "in", "let", "loop", "macro", "match", "mod", "move", "mut", "offsetof",
    "override", "priv", "proc", "pub", "pure", "ref", "return", "Self", "self", "sizeof", "static",
    "struct", "super", "trait", "true", "type", "typeof", "unsafe", "unsized", "use", "virtual",
    "where", "while", "yield"];

lazy_static! {
    static ref RUST_KEYWORDS: HashSet<&'static str> = {
        RUST_KEYWORDS_ARR.iter().cloned().collect()
    };
}

pub enum SampleSource<'a> {
    Url(&'a str),
    File(&'a str),
    Text(&'a str),
}

pub struct Options {
    use_serde: bool,
    extern_crate: bool,
    runnable_example: bool
}

impl Default for Options {
    fn default() -> Options {
        Options {
            use_serde: true,
            extern_crate: false,
            runnable_example: false
        }
    }
}

struct Ctxt {
    options: Options
}

macro_rules! some_if {
    ($cond:expr, $then:expr) => ({
        if $cond {
            Some($then)
        } else {
            None
        }
    })
}

pub fn codegen_from_sample(name: &str, source: SampleSource) -> Result<quote::Tokens> {
    let sample = get_and_parse_sample(source)?;
    let mut ctxt = Ctxt {
        options: Options::default()
    };
    let (type_name, type_def) = generate_type_from_value(&mut ctxt, name, &sample);

    let example = some_if!(ctxt.options.runnable_example, {
        ctxt.options.extern_crate = true;
        usage_example(&type_name)
    });

    let crates = some_if!(ctxt.options.extern_crate, quote! {
        #[macro_use]
        extern crate serde_derive;
        extern crate serde_json;
    });

    if type_def.is_none() && !ctxt.options.runnable_example {
        return Err(ErrorKind::ExistingType(String::from(type_name.as_str())).into());
    }

    Ok(quote! {
        #crates

        #type_def

        #example
    })
}

fn usage_example(type_id: &quote::Tokens) -> quote::Tokens {
    let var_id = quote::Ident::from(snake_case(type_id.as_str()));

    quote! {
        fn main() {
            let #var_id: #type_id = Default::default();

            let serialized = serde_json::to_string(&#var_id).unwrap();

            println!("serialized = {}", serialized);

            let deserialized: #type_id = serde_json::from_str(&serialized).unwrap();

            println!("deserialized = {:?}", deserialized);
        }
    }
}

fn generate_type_from_value(ctxt: &mut Ctxt, path: &str, value: &Value) -> (quote::Tokens, Option<quote::Tokens>) {
    match *value {
        Value::Null => (quote! { Option<::serde_json::Value> }, None),
        Value::Bool(_) => (quote! { bool }, None),
        Value::Number(ref n) => {
            if n.is_i64() {
                (quote! { i64 }, None)
            } else {
                (quote! { f64 }, None)
            }
        },
        Value::String(_) => (quote! { String }, None),
        Value::Array(ref values) => {
            generate_type_for_array(ctxt, path, values)
        },
        Value::Object(ref map) => {
            generate_struct_from_object(ctxt, path, map)
        }
    }
}

fn generate_type_for_array(ctxt: &mut Ctxt, path: &str, values: &Vec<Value>) -> (quote::Tokens, Option<quote::Tokens>) {
    let mut defs = Vec::new();
    let mut types = HashSet::new();

    for value in values.iter() {
        let (elemtype, elemtype_def) = generate_type_from_value(ctxt, path, value);
        types.insert(elemtype.into_string());
        if let Some(def) = elemtype_def {
            defs.push(def);
        }
    }

    if types.len() == 1 {
        let ident = quote::Ident::new(types.into_iter().next().unwrap());
        (quote! { Vec<#ident> }, defs.into_iter().next())
    } else {
        (quote! { Vec<::serde_json::Value> }, None)
    }
}

fn generate_struct_from_object(ctxt: &mut Ctxt, path: &str, map: &Map<String, Value>) -> (quote::Tokens, Option<quote::Tokens>) {
    let type_name = type_case(path);
    let ident = quote::Ident::new(&type_name as &str);
    let mut defs = Vec::new();

    let fields: Vec<quote::Tokens> = map.iter()
        .map(|(name, value)| {
            let mut field_name = snake_case(name);
            if RUST_KEYWORDS.contains::<str>(&field_name) {
                field_name.push_str("_field")
            }
            let rename = some_if!(&field_name != name,
                quote! { #[serde(rename = #name)] });

            let field_ident = quote::Ident::new(&field_name as &str);
            let (fieldtype, fieldtype_def) = generate_type_from_value(ctxt, name, value);
            if let Some(def) = fieldtype_def {
                defs.push(def);
            }
            quote! {
                #rename
                #field_ident: #fieldtype
            }
        })
        .collect();

    let derives = if ctxt.options.use_serde {
        quote! { #[derive(Default, Debug, Clone, Serialize, Deserialize)] }
    } else {
        quote! { #[derive(Default, Debug, Clone)] }
    };

    let code = quote! {
        #derives
        struct #ident {
            #(#fields),*
        }

        #(#defs)*
    };

    (quote! { #ident }, Some(code))
}

fn get_and_parse_sample(source: SampleSource) -> Result<Value> {
    let parse_result = match source {
        SampleSource::Url(url) => serde_json::de::from_reader(reqwest::get(url)?),
        SampleSource::File(path) => serde_json::de::from_reader(File::open(path)?),
        SampleSource::Text(text) => serde_json::from_str(text),
    };
    Ok(parse_result.chain_err(|| "Unable to parse JSON sample")?)
}
<|endoftext|>


<commit_before>#![feature(phase)]
#![feature(unboxed_closures)]

#[phase(plugin)]
extern crate glium_macros;

extern crate glutin;
extern crate glium;

use std::default::Default;
use glium::Surface;

mod support;

fn build_program(display: &glium::Display) -> glium::Program {
    glium::Program::new(display,
        "
            #version 110

            attribute vec2 position;

            void main() {
                gl_Position = vec4(position, 0.0, 1.0);
            }
        ",
        "
            #version 110

            void main() {
                gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
            }
        ",
        None).unwrap()
}

#[vertex_format]
#[deriving(Copy)]
struct Vertex {
    position: [f32, ..2],
}

#[test]
fn triangles_list_cpu() {
    // ignoring test on travis
    // TODO: find out why they are failing
    if ::std::os::getenv("TRAVIS").is_some() {
        return;
    }

    let display = support::build_display();
    let program = build_program(&display);

    let vb = glium::VertexBuffer::new(&display, vec![
        Vertex { position: [-1.0,  1.0] }, Vertex { position: [1.0,  1.0] },
        Vertex { position: [-1.0, -1.0] }, Vertex { position: [1.0, -1.0] },
    ]);

    let indices = glium::index_buffer::TrianglesList(vec![0u8, 1, 2, 2, 1, 3]);

    let mut target = display.draw();
    target.clear_color(0.0, 0.0, 0.0, 0.0);
    target.draw(&vb, &indices, &program, &glium::uniforms::EmptyUniforms, &Default::default());
    target.finish();

    let data: Vec<Vec<(u8, u8, u8)>> = display.read_front_buffer();

    assert_eq!(data[0][0], (255, 0, 0));
    assert_eq!(data.last().unwrap().last().unwrap(), &(255, 0, 0));

    display.assert_no_error();
}

#[test]
fn triangle_strip_cpu() {
    // ignoring test on travis
    // TODO: find out why they are failing
    if ::std::os::getenv("TRAVIS").is_some() {
        return;
    }

    let display = support::build_display();
    let program = build_program(&display);

    let vb = glium::VertexBuffer::new(&display, vec![
        Vertex { position: [-1.0,  1.0] }, Vertex { position: [1.0,  1.0] },
        Vertex { position: [-1.0, -1.0] }, Vertex { position: [1.0, -1.0] },
    ]);

    let indices = glium::index_buffer::TriangleStrip(vec![0u8, 1, 2, 3]);

    let mut target = display.draw();
    target.clear_color(0.0, 0.0, 0.0, 0.0);
    target.draw(&vb, &indices, &program, &glium::uniforms::EmptyUniforms, &Default::default());
    target.finish();

    let data: Vec<Vec<(u8, u8, u8)>> = display.read_front_buffer();

    assert_eq!(data[0][0], (255, 0, 0));
    assert_eq!(data.last().unwrap().last().unwrap(), &(255, 0, 0));

    display.assert_no_error();
}

#[test]
fn triangles_list_gpu() {
    // ignoring test on travis
    // TODO: find out why they are failing
    if ::std::os::getenv("TRAVIS").is_some() {
        return;
    }

    let display = support::build_display();
    let program = build_program(&display);

    let vb = glium::VertexBuffer::new(&display, vec![
        Vertex { position: [-1.0,  1.0] }, Vertex { position: [1.0,  1.0] },
        Vertex { position: [-1.0, -1.0] }, Vertex { position: [1.0, -1.0] },
    ]);

    let indices = glium::index_buffer::TrianglesList(vec![0u8, 1, 2, 2, 1, 3]);
    let indices = glium::IndexBuffer::new(&display, indices);

    let mut target = display.draw();
    target.clear_color(0.0, 0.0, 0.0, 0.0);
    target.draw(&vb, &indices, &program, &glium::uniforms::EmptyUniforms, &Default::default());
    target.finish();

    let data: Vec<Vec<(u8, u8, u8)>> = display.read_front_buffer();

    assert_eq!(data[0][0], (255, 0, 0));
    assert_eq!(data.last().unwrap().last().unwrap(), &(255, 0, 0));

    display.assert_no_error();
}

#[test]
fn triangle_strip_gpu() {
    // ignoring test on travis
    // TODO: find out why they are failing
    if ::std::os::getenv("TRAVIS").is_some() {
        return;
    }

    let display = support::build_display();
    let program = build_program(&display);

    let vb = glium::VertexBuffer::new(&display, vec![
        Vertex { position: [-1.0,  1.0] }, Vertex { position: [1.0,  1.0] },
        Vertex { position: [-1.0, -1.0] }, Vertex { position: [1.0, -1.0] },
    ]);

    let indices = glium::index_buffer::TriangleStrip(vec![0u8, 1, 2, 3]);
    let indices = glium::IndexBuffer::new(&display, indices);

    let mut target = display.draw();
    target.clear_color(0.0, 0.0, 0.0, 0.0);
    target.draw(&vb, &indices, &program, &glium::uniforms::EmptyUniforms, &Default::default());
    target.finish();

    let data: Vec<Vec<(u8, u8, u8)>> = display.read_front_buffer();

    assert_eq!(data[0][0], (255, 0, 0));
    assert_eq!(data.last().unwrap().last().unwrap(), &(255, 0, 0));

    display.assert_no_error();
}

#[test]
fn get_primitives_type() {
    let display = support::build_display();

    let indices = glium::index_buffer::TriangleStrip(vec![0u8, 1, 2, 3]);
    let indices = glium::IndexBuffer::new(&display, indices);

    assert_eq!(indices.get_primitives_type(), glium::index_buffer::PrimitiveType::TriangleStrip);

    display.assert_no_error();
}

#[test]
fn get_indices_type() {
    let display = support::build_display();

    let indices = glium::index_buffer::TriangleStrip(vec![0u8, 1, 2, 3]);
    let indices = glium::IndexBuffer::new(&display, indices);

    assert_eq!(indices.get_indices_type(), glium::index_buffer::IndexType::U8);

    display.assert_no_error();
}
<commit_msg>Remove travis filtering from tests/indices.rs<commit_after>#![feature(phase)]
#![feature(unboxed_closures)]

#[phase(plugin)]
extern crate glium_macros;

extern crate glutin;
extern crate glium;

use std::default::Default;
use glium::Surface;

mod support;

fn build_program(display: &glium::Display) -> glium::Program {
    glium::Program::new(display,
        "
            #version 110

            attribute vec2 position;

            void main() {
                gl_Position = vec4(position, 0.0, 1.0);
            }
        ",
        "
            #version 110

            void main() {
                gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
            }
        ",
        None).unwrap()
}

#[vertex_format]
#[deriving(Copy)]
struct Vertex {
    position: [f32, ..2],
}

#[test]
fn triangles_list_cpu() {
    let display = support::build_display();
    let program = build_program(&display);

    let vb = glium::VertexBuffer::new(&display, vec![
        Vertex { position: [-1.0,  1.0] }, Vertex { position: [1.0,  1.0] },
        Vertex { position: [-1.0, -1.0] }, Vertex { position: [1.0, -1.0] },
    ]);

    let indices = glium::index_buffer::TrianglesList(vec![0u8, 1, 2, 2, 1, 3]);

    let mut target = display.draw();
    target.clear_color(0.0, 0.0, 0.0, 0.0);
    target.draw(&vb, &indices, &program, &glium::uniforms::EmptyUniforms, &Default::default());
    target.finish();

    let data: Vec<Vec<(u8, u8, u8)>> = display.read_front_buffer();

    assert_eq!(data[0][0], (255, 0, 0));
    assert_eq!(data.last().unwrap().last().unwrap(), &(255, 0, 0));

    display.assert_no_error();
}

#[test]
fn triangle_strip_cpu() {
    let display = support::build_display();
    let program = build_program(&display);

    let vb = glium::VertexBuffer::new(&display, vec![
        Vertex { position: [-1.0,  1.0] }, Vertex { position: [1.0,  1.0] },
        Vertex { position: [-1.0, -1.0] }, Vertex { position: [1.0, -1.0] },
    ]);

    let indices = glium::index_buffer::TriangleStrip(vec![0u8, 1, 2, 3]);

    let mut target = display.draw();
    target.clear_color(0.0, 0.0, 0.0, 0.0);
    target.draw(&vb, &indices, &program, &glium::uniforms::EmptyUniforms, &Default::default());
    target.finish();

    let data: Vec<Vec<(u8, u8, u8)>> = display.read_front_buffer();

    assert_eq!(data[0][0], (255, 0, 0));
    assert_eq!(data.last().unwrap().last().unwrap(), &(255, 0, 0));

    display.assert_no_error();
}

#[test]
fn triangles_list_gpu() {
    let display = support::build_display();
    let program = build_program(&display);

    let vb = glium::VertexBuffer::new(&display, vec![
        Vertex { position: [-1.0,  1.0] }, Vertex { position: [1.0,  1.0] },
        Vertex { position: [-1.0, -1.0] }, Vertex { position: [1.0, -1.0] },
    ]);

    let indices = glium::index_buffer::TrianglesList(vec![0u8, 1, 2, 2, 1, 3]);
    let indices = glium::IndexBuffer::new(&display, indices);

    let mut target = display.draw();
    target.clear_color(0.0, 0.0, 0.0, 0.0);
    target.draw(&vb, &indices, &program, &glium::uniforms::EmptyUniforms, &Default::default());
    target.finish();

    let data: Vec<Vec<(u8, u8, u8)>> = display.read_front_buffer();

    assert_eq!(data[0][0], (255, 0, 0));
    assert_eq!(data.last().unwrap().last().unwrap(), &(255, 0, 0));

    display.assert_no_error();
}

#[test]
fn triangle_strip_gpu() {
    let display = support::build_display();
    let program = build_program(&display);

    let vb = glium::VertexBuffer::new(&display, vec![
        Vertex { position: [-1.0,  1.0] }, Vertex { position: [1.0,  1.0] },
        Vertex { position: [-1.0, -1.0] }, Vertex { position: [1.0, -1.0] },
    ]);

    let indices = glium::index_buffer::TriangleStrip(vec![0u8, 1, 2, 3]);
    let indices = glium::IndexBuffer::new(&display, indices);

    let mut target = display.draw();
    target.clear_color(0.0, 0.0, 0.0, 0.0);
    target.draw(&vb, &indices, &program, &glium::uniforms::EmptyUniforms, &Default::default());
    target.finish();

    let data: Vec<Vec<(u8, u8, u8)>> = display.read_front_buffer();

    assert_eq!(data[0][0], (255, 0, 0));
    assert_eq!(data.last().unwrap().last().unwrap(), &(255, 0, 0));

    display.assert_no_error();
}

#[test]
fn get_primitives_type() {
    let display = support::build_display();

    let indices = glium::index_buffer::TriangleStrip(vec![0u8, 1, 2, 3]);
    let indices = glium::IndexBuffer::new(&display, indices);

    assert_eq!(indices.get_primitives_type(), glium::index_buffer::PrimitiveType::TriangleStrip);

    display.assert_no_error();
}

#[test]
fn get_indices_type() {
    let display = support::build_display();

    let indices = glium::index_buffer::TriangleStrip(vec![0u8, 1, 2, 3]);
    let indices = glium::IndexBuffer::new(&display, indices);

    assert_eq!(indices.get_indices_type(), glium::index_buffer::IndexType::U8);

    display.assert_no_error();
}
<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/MD5/Implementation
/*
 * Ported from C - Simple MD5 implementation
* on Wikipedia https://en.wikipedia.org/wiki/MD5
*/
use std::iter::range_step;
use std::vec::Vec;
use std::fmt::{Show, Formatter, Result};

#[cfg(not(test))]
fn main() {
    let inputs= [bytes!("a"),
                bytes!("abc"),
                bytes!("message digest"),
                bytes!("abcdefghijklmnopqrstuvwxyz"),
                bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"),
                bytes!("12345678901234567890123456789012345678901234567890123456789012345678901234567890")];

    for &input in inputs.iter() {
        println!("{}", md5(input));
    }
}

// Constants are the integer part of the sines of integers (in radians) * 2^32.
static k:[u32,..64] = [
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee ,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501 ,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be ,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821 ,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa ,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8 ,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed ,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a ,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c ,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70 ,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05 ,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665 ,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039 ,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1 ,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1 ,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 ];

// r specifies the per-round shift amounts
static r:[u32,..64] = [7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
                      5,  9, 14, 20, 5,  9, 14, 20, 5,  9, 14, 20, 5,  9, 14, 20,
                      4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
                      6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21];

// "newtype" for [u8,..16] to specify it's a MD5 hash
struct MD5([u8,..16]);
impl Show for MD5 {
    fn fmt(&self, f: &mut Formatter) -> Result {
        let MD5(md5)=*self;
        for b in md5.iter() {
            try!(write!(f, "{:02x}", *b));
        }
        Ok(())
    }
}

// leftrotate function definition
#[inline]
fn left_rotate(x: u32, c: u32) -> u32 {
    (x << c) | (x >> (32 - c))
}

fn to_bytes(val: u64) -> [u8,..8]
{
    let mut tmp:[u8,..8] = [0u8,..8];
    for i in range (0u, 8) {
        tmp[i] = (val >> (8*i)) as u8;
    }
    tmp
}

fn md5(initial_msg: &[u8]) -> MD5
{
    let initial_len=initial_msg.len() as u64;

    // These vars will contain the hash
    let mut h:[u32,..4]=[0x67452301u32, 0xefcdab89, 0x98badcfe, 0x10325476];

     //Pre-processing:
    //append "1" bit to message
    //append "0" bits until message length in bits ≡ 448 (mod 512)
    //append length mod (2^64) to message
    let mut new_len=initial_len;
    while new_len % (512/8) != 448/8 {
        new_len+=1;
    }

    { // new block (so msg is freed as soon as not needed any longer)
        let mut msg = Vec::<u8>::from_slice(initial_msg);
        msg.push(0x80u8); // append the "1" bit; most significant bit is "first"

        for _ in range (initial_len + 1, new_len) {
            msg.push(0); // append "0" bits
        }

        // append the len in bits at the end of the buffer.
        let msg=msg.append(to_bytes(initial_len << 3));

        assert_eq!(msg.len() % 64, 0);

        let mut w:[u32,..16] = [0u32,..16];
        // Process the message in successive 512-bit chunks:
        //for each 512-bit chunk of message:
        for offset in range_step(0u64, new_len, (512/8)) {
            // break chunk into sixteen 32-bit words w[j], 0 ≤ j ≤ 15
            for i in range(0u32, 16) {
                let j = i as uint * 4 + offset as uint;
                w[i as uint] =
                        (*msg.get(j)   as u32)      |
                        (*msg.get(j+1) as u32) <<8  |
                        (*msg.get(j+2) as u32) <<16 |
                         *msg.get(j+3) as u32  <<24;
            }
            //println!("chunk {}", w);
            // Initialize hash value for this chunk:
            let (mut a, mut b, mut c, mut d) = (h[0], h[1], h[2], h[3]);

            // Main loop:
            for ind in range(0u, 64) {
                let (f,g) = match ind {
                    i @ 0..15   => ( (b & c) | ((!b) & d), //f
                                    i ),                   //g
                    i @ 16..31  => ( (d & b) | ((!d) & c),
                                    (5*i + 1) % 16 ),
                    i @ 32..47  => ( b ^ c ^ d,
                                    (3*i + 5) % 16 ),
                    i @ _       => ( c ^ (b | (!d)),
                                    (7*i) % 16 )
                };

                let temp = d;
                d = c;
                c = b;
                b = b + left_rotate((a + f + k[ind] + w[g]), r[ind]);
                a = temp;
            }

            // Add this chunk's hash to result so far:
            h[0] += a;
            h[1] += b;
            h[2] += c;
            h[3] += d;
        }
    } // cleanup (end block, msg is freed)

    //var char digest[16] := h0 append h1 append h2 append h3 //(Output is in little-endian)
    let mut digest: [u8,..16]=[0u8,..16];
    for (i, s) in h.iter().enumerate() {
        digest[i*4] = (*s ) as u8;
        digest[i*4+1] = (*s >> 8) as u8;
        digest[i*4+2] = (*s >> 16) as u8;
        digest[i*4+3] = (*s >> 24) as u8;
    }
    MD5(digest)
}

#[test]
fn helper_fns() {
    assert_eq!(64, left_rotate(8, 3));

    let exp:[u8,..8] = [64u8, 226, 1, 0, 0, 0, 0, 0];
    assert!(to_bytes(123456) == exp);
}

#[test]
fn known_hashes() {
    let in_out=[(bytes!(""),
        "d41d8cd98f00b204e9800998ecf8427e"),
    (bytes!("a"),
        "0cc175b9c0f1b6a831c399e269772661"),
    (bytes!("abc"),
        "900150983cd24fb0d6963f7d28e17f72"),
    (bytes!("message digest"),
        "f96b697d7cb7938d525a2f31aaf161d0"),
    (bytes!("abcdefghijklmnopqrstuvwxyz"),
        "c3fcd3d76192e4007dfb496cca67e13b"),
    (bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"),
        "d174ab98d277d9f5a5611c2c9f419d9f"),
    (bytes!("12345678901234567890123456789012345678901234567890123456789012345678901234567890"),
        "57edf4a22be3c955ac49da2e2107b67a")];

    for &(i,o) in in_out.iter() {
        let m=md5(i);
        assert_eq!(format!("{}", m), o.to_string());
    }
}<commit_msg>removed whitespace + long line warnings<commit_after>// Implements http://rosettacode.org/wiki/MD5/Implementation
/*
 * Ported from C - Simple MD5 implementation
* on Wikipedia https://en.wikipedia.org/wiki/MD5
*/
use std::iter::range_step;
use std::vec::Vec;
use std::fmt::{Show, Formatter, Result};

#[cfg(not(test))]
fn main() {
    let inputs=
    [bytes!("a"),
    bytes!("abc"),
    bytes!("message digest"),
    bytes!("abcdefghijklmnopqrstuvwxyz"),
    bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"),
    bytes!("12345678901234567890123456789012345678901234567890123456789012345678901234567890")];

    for &input in inputs.iter() {
        println!("{}", md5(input));
    }
}

// Constants are the integer part of the sines of integers (in radians) * 2^32.
static k:[u32,..64] = [
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee ,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501 ,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be ,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821 ,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa ,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8 ,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed ,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a ,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c ,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70 ,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05 ,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665 ,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039 ,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1 ,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1 ,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 ];

// r specifies the per-round shift amounts
static r:[u32,..64] = [7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
                      5,  9, 14, 20, 5,  9, 14, 20, 5,  9, 14, 20, 5,  9, 14, 20,
                      4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
                      6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21];

// "newtype" for [u8,..16] to specify it's a MD5 hash
struct MD5([u8,..16]);
impl Show for MD5 {
    fn fmt(&self, f: &mut Formatter) -> Result {
        let MD5(md5)=*self;
        for b in md5.iter() {
            try!(write!(f, "{:02x}", *b));
        }
        Ok(())
    }
}

// leftrotate function definition
#[inline]
fn left_rotate(x: u32, c: u32) -> u32 {
    (x << c) | (x >> (32 - c))
}

fn to_bytes(val: u64) -> [u8,..8]
{
    let mut tmp:[u8,..8] = [0u8,..8];
    for i in range (0u, 8) {
        tmp[i] = (val >> (8*i)) as u8;
    }
    tmp
}

fn md5(initial_msg: &[u8]) -> MD5
{
    let initial_len=initial_msg.len() as u64;

    // These vars will contain the hash
    let mut h:[u32,..4]=[0x67452301u32, 0xefcdab89, 0x98badcfe, 0x10325476];

     //Pre-processing:
    //append "1" bit to message
    //append "0" bits until message length in bits ≡ 448 (mod 512)
    //append length mod (2^64) to message
    let mut new_len=initial_len;
    while new_len % (512/8) != 448/8 {
        new_len+=1;
    }

    { // new block (so msg is freed as soon as not needed any longer)
        let mut msg = Vec::<u8>::from_slice(initial_msg);
        msg.push(0x80u8); // append the "1" bit; most significant bit is "first"

        for _ in range (initial_len + 1, new_len) {
            msg.push(0); // append "0" bits
        }

        // append the len in bits at the end of the buffer.
        let msg=msg.append(to_bytes(initial_len << 3));

        assert_eq!(msg.len() % 64, 0);

        let mut w:[u32,..16] = [0u32,..16];
        // Process the message in successive 512-bit chunks:
        //for each 512-bit chunk of message:
        for offset in range_step(0u64, new_len, (512/8)) {
            // break chunk into sixteen 32-bit words w[j], 0 ≤ j ≤ 15
            for i in range(0u32, 16) {
                let j = i as uint * 4 + offset as uint;
                w[i as uint] =
                        (*msg.get(j)   as u32)      |
                        (*msg.get(j+1) as u32) <<8  |
                        (*msg.get(j+2) as u32) <<16 |
                         *msg.get(j+3) as u32  <<24;
            }
            //println!("chunk {}", w);
            // Initialize hash value for this chunk:
            let (mut a, mut b, mut c, mut d) = (h[0], h[1], h[2], h[3]);

            // Main loop:
            for ind in range(0u, 64) {
                let (f,g) = match ind {
                    i @ 0..15   => ( (b & c) | ((!b) & d), //f
                                    i ),                   //g
                    i @ 16..31  => ( (d & b) | ((!d) & c),
                                    (5*i + 1) % 16 ),
                    i @ 32..47  => ( b ^ c ^ d,
                                    (3*i + 5) % 16 ),
                    i @ _       => ( c ^ (b | (!d)),
                                    (7*i) % 16 )
                };

                let temp = d;
                d = c;
                c = b;
                b = b + left_rotate((a + f + k[ind] + w[g]), r[ind]);
                a = temp;
            }

            // Add this chunk's hash to result so far:
            h[0] += a;
            h[1] += b;
            h[2] += c;
            h[3] += d;
        }
    } // cleanup (end block, msg is freed)

    //var char digest[16] := h0 append h1 append h2 append h3 //(Output is in little-endian)
    let mut digest: [u8,..16]=[0u8,..16];
    for (i, s) in h.iter().enumerate() {
        digest[i*4] = (*s ) as u8;
        digest[i*4+1] = (*s >> 8) as u8;
        digest[i*4+2] = (*s >> 16) as u8;
        digest[i*4+3] = (*s >> 24) as u8;
    }
    MD5(digest)
}

#[test]
fn helper_fns() {
    assert_eq!(64, left_rotate(8, 3));

    let exp:[u8,..8] = [64u8, 226, 1, 0, 0, 0, 0, 0];
    assert!(to_bytes(123456) == exp);
}

#[test]
fn known_hashes() {
    let in_out=
    [(bytes!(""),
        "d41d8cd98f00b204e9800998ecf8427e"),
    (bytes!("a"),
        "0cc175b9c0f1b6a831c399e269772661"),
    (bytes!("abc"),
        "900150983cd24fb0d6963f7d28e17f72"),
    (bytes!("message digest"),
        "f96b697d7cb7938d525a2f31aaf161d0"),
    (bytes!("abcdefghijklmnopqrstuvwxyz"),
        "c3fcd3d76192e4007dfb496cca67e13b"),
    (bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"),
        "d174ab98d277d9f5a5611c2c9f419d9f"),
    (bytes!("12345678901234567890123456789012345678901234567890123456789012345678901234567890"),
        "57edf4a22be3c955ac49da2e2107b67a")];

    for &(i,o) in in_out.iter() {
        let m=md5(i);
        assert_eq!(format!("{}", m), o.to_string());
    }
}<|endoftext|>


<commit_before>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use db::migration::Migrator;

use error::Result;

pub fn migrate(migrator: &mut Migrator) -> Result<()> {
    migrator
        .migrate("originsrv",
                 r#"CREATE SEQUENCE IF NOT EXISTS origin_package_id_seq;"#)?;
    migrator
        .migrate("originsrv",
                 r#"CREATE TABLE origin_packages (
                    id bigint PRIMARY KEY DEFAULT next_id_v1('origin_package_id_seq'),
                    origin_id bigint REFERENCES origins(id),
                    owner_id bigint,
                    name text,
                    ident text UNIQUE,
                    checksum text,
                    manifest text,
                    config text,
                    target text,
                    deps text,
                    tdeps text,
                    exposes text,
                    scheduler_sync bool DEFAULT false,
                    created_at timestamptz DEFAULT now(),
                    updated_at timestamptz
             )"#)?;
    migrator.migrate("originsrv",
                 r#"CREATE OR REPLACE FUNCTION insert_origin_package_v1 (
                    op_origin_id bigint,
                    op_owner_id bigint,
                    op_name text,
                    op_ident text,
                    op_checksum text,
                    op_manifest text,
                    op_config text,
                    op_target text,
                    op_deps text,
                    op_tdeps text,
                    op_exposes text
                 ) RETURNS SETOF origin_packages AS $$
                     DECLARE
                        inserted_package origin_packages;
                        channel_id bigint;
                     BEGIN
                         INSERT INTO origin_packages (origin_id, owner_id, name, ident, checksum, manifest, config, target, deps, tdeps, exposes)
                                VALUES (op_origin_id, op_owner_id, op_name, op_ident, op_checksum, op_manifest, op_config, op_target, op_deps, op_tdeps, op_exposes)
                                RETURNING * into inserted_package;

                         SELECT id FROM origin_channels WHERE origin_id = op_origin_id AND name = 'unstable' INTO channel_id;
                         PERFORM promote_origin_package_v1(channel_id, inserted_package.id);

                         RETURN NEXT inserted_package;
                         RETURN;
                     END
                 $$ LANGUAGE plpgsql VOLATILE"#)?;
    migrator
        .migrate("originsrv",
                 r#"CREATE OR REPLACE FUNCTION get_origin_package_v1 (
                    op_ident text
                 ) RETURNS SETOF origin_packages AS $$
                    BEGIN
                        RETURN QUERY SELECT * FROM origin_packages WHERE ident = op_ident;
                        RETURN;
                    END
                    $$ LANGUAGE plpgsql STABLE"#)?;
    migrator.migrate("originsrv",
                 r#"CREATE OR REPLACE FUNCTION get_origin_package_latest_v1 (
                    op_ident text,
                    op_target text
                 ) RETURNS SETOF origin_packages AS $$
                    BEGIN
                        RETURN QUERY SELECT * FROM origin_packages WHERE ident LIKE (op_ident  || '%') AND target = op_target;
                        RETURN;
                    END
                    $$ LANGUAGE plpgsql STABLE"#)?;
    migrator.migrate("originsrv",
                     r#"CREATE OR REPLACE FUNCTION get_origin_package_versions_for_origin_v1 (
                    op_origin text,
                    op_pkg text
                 ) RETURNS TABLE(version text, release_count bigint) AS $$
                    BEGIN
                        RETURN QUERY SELECT p.partial_ident[3] AS version, COUNT(p.partial_ident[4]) AS release_count FROM (SELECT regexp_split_to_array(op.ident, '/') AS partial_ident FROM origin_packages op INNER JOIN origins o ON o.id = op.origin_id WHERE o.name = op_origin AND op.name = op_pkg) AS p GROUP BY version;
                        RETURN;
                    END
                    $$ LANGUAGE plpgsql STABLE"#)?;
    migrator.migrate("originsrv",
                     r#"CREATE OR REPLACE FUNCTION get_origin_packages_for_origin_v1 (
                    op_ident text,
                    op_limit bigint,
                    op_offset bigint
                 ) RETURNS TABLE(total_count bigint, ident text) AS $$
                    BEGIN
                        RETURN QUERY SELECT COUNT(*) OVER () AS total_count, origin_packages.ident FROM origin_packages WHERE origin_packages.ident LIKE (op_ident  || '%')
                          ORDER BY ident ASC
                          LIMIT op_limit OFFSET op_offset;
                        RETURN;
                    END
                    $$ LANGUAGE plpgsql STABLE"#)?;
    migrator.migrate("originsrv",
                     r#"CREATE OR REPLACE FUNCTION get_origin_packages_for_origin_distinct_v1 (
                    op_ident text,
                    op_limit bigint,
                    op_offset bigint
                 ) RETURNS TABLE(total_count bigint, ident text) AS $$
                    BEGIN
                        RETURN QUERY SELECT COUNT(p.partial_ident[1] || '/' || p.partial_ident[2]) OVER () AS total_count, p.partial_ident[1] || '/' || p.partial_ident[2] AS ident
                        FROM (SELECT regexp_split_to_array(op.ident, '/') as partial_ident FROM origin_packages op WHERE op.ident LIKE ('%' || op_ident || '%')) AS p
                        GROUP BY (p.partial_ident[1] || '/' || p.partial_ident[2])
                        LIMIT op_limit OFFSET op_offset;
                        RETURN;
                    END
                    $$ LANGUAGE plpgsql STABLE"#)?;
    migrator.migrate("originsrv",
                     r#"CREATE OR REPLACE FUNCTION get_origin_packages_unique_for_origin_v1 (
                   op_origin text,
                   op_limit bigint,
                   op_offset bigint
                 ) RETURNS TABLE(total_count bigint, name text) AS $$
                    BEGIN
                        RETURN QUERY SELECT COUNT(*) OVER () AS total_count, origin_packages.name FROM origins INNER JOIN origin_packages ON origins.id = origin_packages.origin_id WHERE origins.name = op_origin
                          GROUP BY origin_packages.name
                          ORDER BY origin_packages.name ASC
                          LIMIT op_limit OFFSET op_offset;
                        RETURN;
                    END
                    $$ LANGUAGE plpgsql STABLE"#)?;
    migrator.migrate("originsrv",
                     r#"CREATE OR REPLACE FUNCTION search_origin_packages_for_origin_v1 (
                   op_origin text,
                   op_query text,
                   op_limit bigint,
                   op_offset bigint
                 ) RETURNS TABLE(total_count bigint, ident text) AS $$
                    BEGIN
                        RETURN QUERY SELECT COUNT(*) OVER () AS total_count, origin_packages.ident FROM origins INNER JOIN origin_packages ON origins.id = origin_packages.origin_id WHERE origins.name = op_origin and origin_packages.name LIKE ('%' || op_query || '%')
                          ORDER BY ident ASC
                          LIMIT op_limit OFFSET op_offset;
                        RETURN;
                    END
                    $$ LANGUAGE plpgsql STABLE"#)?;
    migrator.migrate("originsrv",
                     r#"CREATE OR REPLACE FUNCTION search_origin_packages_for_origin_distinct_v1 (
                   op_origin text,
                   op_query text,
                   op_limit bigint,
                   op_offset bigint
                 ) RETURNS TABLE(total_count bigint, ident text) AS $$
                    BEGIN
                        RETURN QUERY SELECT COUNT(p.partial_ident[1] || '/' || p.partial_ident[2]) OVER () AS total_count, p.partial_ident[1] || '/' || p.partial_ident[2] AS ident
                        FROM (SELECT regexp_split_to_array(op.ident, '/') as partial_ident FROM origins o INNER JOIN origin_packages op ON o.id = op.origin_id WHERE o.name = op_origin AND op.name LIKE ('%' || op_query || '%')) AS p
                        GROUP BY (p.partial_ident[1] || '/' || p.partial_ident[2])
                        LIMIT op_limit OFFSET op_offset;
                        RETURN;
                    END
                    $$ LANGUAGE plpgsql STABLE"#)?;
    migrator.migrate("originsrv",
                     r#"CREATE OR REPLACE FUNCTION search_all_origin_packages_dynamic_v1 (
                    op_query text,
                    op_limit bigint,
                    op_offset bigint
                    ) RETURNS TABLE(total_count bigint, ident text) AS $$
                    DECLARE
                      schema RECORD;
                    BEGIN
                      FOR schema IN EXECUTE
                        format(
                          'SELECT schema_name FROM information_schema.schemata WHERE left(schema_name, 6) = %L',
                          'shard_'
                        )
                      LOOP
                        RETURN QUERY EXECUTE
                        format('SELECT COUNT(p.partial_ident[1] || %L || p.partial_ident[2]) OVER () AS total_count, p.partial_ident[1] || %L || p.partial_ident[2] AS ident FROM (SELECT regexp_split_to_array(op.ident, %L) as partial_ident FROM %I.origins o INNER JOIN %I.origin_packages op ON o.id = op.origin_id WHERE o.name LIKE (%L || %L || %L) OR op.name LIKE (%L || %L || %L)) AS p GROUP BY (p.partial_ident[1] || %L || p.partial_ident[2]) LIMIT %L OFFSET %L', '/', '/', '/', schema.schema_name, schema.schema_name, '%', op_query, '%', '%', op_query, '%', '/', op_limit, op_offset);
                      END LOOP;
                    END;
                    $$ LANGUAGE plpgsql STABLE"#)?;
    migrator.migrate("originsrv",
                     r#"CREATE OR REPLACE FUNCTION sync_packages_v1() RETURNS TABLE(account_id bigint, package_id bigint, package_ident text, package_deps text) AS $$
                    BEGIN
                        RETURN QUERY SELECT origin_packages.owner_id, origin_packages.id, origin_packages.ident, origin_packages.deps FROM origin_packages WHERE origin_packages.scheduler_sync = false;
                        RETURN;
                    END
                    $$ LANGUAGE plpgsql STABLE"#)?;
    migrator.migrate("originsrv",
                     r#"CREATE OR REPLACE FUNCTION set_packages_sync_v1(in_package_id bigint) RETURNS VOID AS $$
                    BEGIN
                        UPDATE origin_packages SET scheduler_sync = true WHERE id = in_package_id;
                    END
                    $$ LANGUAGE plpgsql VOLATILE"#)?;
    migrator.migrate("originsrv",
                     r#"CREATE OR REPLACE FUNCTION get_origin_package_versions_for_origin_v2 (
                    op_origin text,
                    op_pkg text
                 ) RETURNS TABLE(version text, release_count bigint, latest text) AS $$
                    BEGIN
                        RETURN QUERY SELECT p.partial_ident[3] AS version, COUNT(p.partial_ident[4]) AS release_count, MAX(p.partial_ident[4]) as latest FROM (SELECT regexp_split_to_array(op.ident, '/') AS partial_ident FROM origin_packages op INNER JOIN origins o ON o.id = op.origin_id WHERE o.name = op_origin AND op.name = op_pkg) AS p GROUP BY version;
                        RETURN;
                    END
                    $$ LANGUAGE plpgsql STABLE"#)?;
    Ok(())
}
<commit_msg>Tweak the query for get_origin_package_latest_v1<commit_after>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use db::migration::Migrator;

use error::Result;

pub fn migrate(migrator: &mut Migrator) -> Result<()> {
    migrator
        .migrate("originsrv",
                 r#"CREATE SEQUENCE IF NOT EXISTS origin_package_id_seq;"#)?;
    migrator
        .migrate("originsrv",
                 r#"CREATE TABLE origin_packages (
                    id bigint PRIMARY KEY DEFAULT next_id_v1('origin_package_id_seq'),
                    origin_id bigint REFERENCES origins(id),
                    owner_id bigint,
                    name text,
                    ident text UNIQUE,
                    checksum text,
                    manifest text,
                    config text,
                    target text,
                    deps text,
                    tdeps text,
                    exposes text,
                    scheduler_sync bool DEFAULT false,
                    created_at timestamptz DEFAULT now(),
                    updated_at timestamptz
             )"#)?;
    migrator.migrate("originsrv",
                 r#"CREATE OR REPLACE FUNCTION insert_origin_package_v1 (
                    op_origin_id bigint,
                    op_owner_id bigint,
                    op_name text,
                    op_ident text,
                    op_checksum text,
                    op_manifest text,
                    op_config text,
                    op_target text,
                    op_deps text,
                    op_tdeps text,
                    op_exposes text
                 ) RETURNS SETOF origin_packages AS $$
                     DECLARE
                        inserted_package origin_packages;
                        channel_id bigint;
                     BEGIN
                         INSERT INTO origin_packages (origin_id, owner_id, name, ident, checksum, manifest, config, target, deps, tdeps, exposes)
                                VALUES (op_origin_id, op_owner_id, op_name, op_ident, op_checksum, op_manifest, op_config, op_target, op_deps, op_tdeps, op_exposes)
                                RETURNING * into inserted_package;

                         SELECT id FROM origin_channels WHERE origin_id = op_origin_id AND name = 'unstable' INTO channel_id;
                         PERFORM promote_origin_package_v1(channel_id, inserted_package.id);

                         RETURN NEXT inserted_package;
                         RETURN;
                     END
                 $$ LANGUAGE plpgsql VOLATILE"#)?;
    migrator
        .migrate("originsrv",
                 r#"CREATE OR REPLACE FUNCTION get_origin_package_v1 (
                    op_ident text
                 ) RETURNS SETOF origin_packages AS $$
                    BEGIN
                        RETURN QUERY SELECT * FROM origin_packages WHERE ident = op_ident;
                        RETURN;
                    END
                    $$ LANGUAGE plpgsql STABLE"#)?;
    migrator.migrate("originsrv",
                 r#"CREATE OR REPLACE FUNCTION get_origin_package_latest_v1 (
                    op_ident text,
                    op_target text
                 ) RETURNS SETOF origin_packages AS $$
                    BEGIN
                        RETURN QUERY SELECT * FROM origin_packages WHERE ident LIKE (op_ident  || '/%') AND target = op_target;
                        RETURN;
                    END
                    $$ LANGUAGE plpgsql STABLE"#)?;
    migrator.migrate("originsrv",
                     r#"CREATE OR REPLACE FUNCTION get_origin_package_versions_for_origin_v1 (
                    op_origin text,
                    op_pkg text
                 ) RETURNS TABLE(version text, release_count bigint) AS $$
                    BEGIN
                        RETURN QUERY SELECT p.partial_ident[3] AS version, COUNT(p.partial_ident[4]) AS release_count FROM (SELECT regexp_split_to_array(op.ident, '/') AS partial_ident FROM origin_packages op INNER JOIN origins o ON o.id = op.origin_id WHERE o.name = op_origin AND op.name = op_pkg) AS p GROUP BY version;
                        RETURN;
                    END
                    $$ LANGUAGE plpgsql STABLE"#)?;
    migrator.migrate("originsrv",
                     r#"CREATE OR REPLACE FUNCTION get_origin_packages_for_origin_v1 (
                    op_ident text,
                    op_limit bigint,
                    op_offset bigint
                 ) RETURNS TABLE(total_count bigint, ident text) AS $$
                    BEGIN
                        RETURN QUERY SELECT COUNT(*) OVER () AS total_count, origin_packages.ident FROM origin_packages WHERE origin_packages.ident LIKE (op_ident  || '%')
                          ORDER BY ident ASC
                          LIMIT op_limit OFFSET op_offset;
                        RETURN;
                    END
                    $$ LANGUAGE plpgsql STABLE"#)?;
    migrator.migrate("originsrv",
                     r#"CREATE OR REPLACE FUNCTION get_origin_packages_for_origin_distinct_v1 (
                    op_ident text,
                    op_limit bigint,
                    op_offset bigint
                 ) RETURNS TABLE(total_count bigint, ident text) AS $$
                    BEGIN
                        RETURN QUERY SELECT COUNT(p.partial_ident[1] || '/' || p.partial_ident[2]) OVER () AS total_count, p.partial_ident[1] || '/' || p.partial_ident[2] AS ident
                        FROM (SELECT regexp_split_to_array(op.ident, '/') as partial_ident FROM origin_packages op WHERE op.ident LIKE ('%' || op_ident || '%')) AS p
                        GROUP BY (p.partial_ident[1] || '/' || p.partial_ident[2])
                        LIMIT op_limit OFFSET op_offset;
                        RETURN;
                    END
                    $$ LANGUAGE plpgsql STABLE"#)?;
    migrator.migrate("originsrv",
                     r#"CREATE OR REPLACE FUNCTION get_origin_packages_unique_for_origin_v1 (
                   op_origin text,
                   op_limit bigint,
                   op_offset bigint
                 ) RETURNS TABLE(total_count bigint, name text) AS $$
                    BEGIN
                        RETURN QUERY SELECT COUNT(*) OVER () AS total_count, origin_packages.name FROM origins INNER JOIN origin_packages ON origins.id = origin_packages.origin_id WHERE origins.name = op_origin
                          GROUP BY origin_packages.name
                          ORDER BY origin_packages.name ASC
                          LIMIT op_limit OFFSET op_offset;
                        RETURN;
                    END
                    $$ LANGUAGE plpgsql STABLE"#)?;
    migrator.migrate("originsrv",
                     r#"CREATE OR REPLACE FUNCTION search_origin_packages_for_origin_v1 (
                   op_origin text,
                   op_query text,
                   op_limit bigint,
                   op_offset bigint
                 ) RETURNS TABLE(total_count bigint, ident text) AS $$
                    BEGIN
                        RETURN QUERY SELECT COUNT(*) OVER () AS total_count, origin_packages.ident FROM origins INNER JOIN origin_packages ON origins.id = origin_packages.origin_id WHERE origins.name = op_origin and origin_packages.name LIKE ('%' || op_query || '%')
                          ORDER BY ident ASC
                          LIMIT op_limit OFFSET op_offset;
                        RETURN;
                    END
                    $$ LANGUAGE plpgsql STABLE"#)?;
    migrator.migrate("originsrv",
                     r#"CREATE OR REPLACE FUNCTION search_origin_packages_for_origin_distinct_v1 (
                   op_origin text,
                   op_query text,
                   op_limit bigint,
                   op_offset bigint
                 ) RETURNS TABLE(total_count bigint, ident text) AS $$
                    BEGIN
                        RETURN QUERY SELECT COUNT(p.partial_ident[1] || '/' || p.partial_ident[2]) OVER () AS total_count, p.partial_ident[1] || '/' || p.partial_ident[2] AS ident
                        FROM (SELECT regexp_split_to_array(op.ident, '/') as partial_ident FROM origins o INNER JOIN origin_packages op ON o.id = op.origin_id WHERE o.name = op_origin AND op.name LIKE ('%' || op_query || '%')) AS p
                        GROUP BY (p.partial_ident[1] || '/' || p.partial_ident[2])
                        LIMIT op_limit OFFSET op_offset;
                        RETURN;
                    END
                    $$ LANGUAGE plpgsql STABLE"#)?;
    migrator.migrate("originsrv",
                     r#"CREATE OR REPLACE FUNCTION search_all_origin_packages_dynamic_v1 (
                    op_query text,
                    op_limit bigint,
                    op_offset bigint
                    ) RETURNS TABLE(total_count bigint, ident text) AS $$
                    DECLARE
                      schema RECORD;
                    BEGIN
                      FOR schema IN EXECUTE
                        format(
                          'SELECT schema_name FROM information_schema.schemata WHERE left(schema_name, 6) = %L',
                          'shard_'
                        )
                      LOOP
                        RETURN QUERY EXECUTE
                        format('SELECT COUNT(p.partial_ident[1] || %L || p.partial_ident[2]) OVER () AS total_count, p.partial_ident[1] || %L || p.partial_ident[2] AS ident FROM (SELECT regexp_split_to_array(op.ident, %L) as partial_ident FROM %I.origins o INNER JOIN %I.origin_packages op ON o.id = op.origin_id WHERE o.name LIKE (%L || %L || %L) OR op.name LIKE (%L || %L || %L)) AS p GROUP BY (p.partial_ident[1] || %L || p.partial_ident[2]) LIMIT %L OFFSET %L', '/', '/', '/', schema.schema_name, schema.schema_name, '%', op_query, '%', '%', op_query, '%', '/', op_limit, op_offset);
                      END LOOP;
                    END;
                    $$ LANGUAGE plpgsql STABLE"#)?;
    migrator.migrate("originsrv",
                     r#"CREATE OR REPLACE FUNCTION sync_packages_v1() RETURNS TABLE(account_id bigint, package_id bigint, package_ident text, package_deps text) AS $$
                    BEGIN
                        RETURN QUERY SELECT origin_packages.owner_id, origin_packages.id, origin_packages.ident, origin_packages.deps FROM origin_packages WHERE origin_packages.scheduler_sync = false;
                        RETURN;
                    END
                    $$ LANGUAGE plpgsql STABLE"#)?;
    migrator.migrate("originsrv",
                     r#"CREATE OR REPLACE FUNCTION set_packages_sync_v1(in_package_id bigint) RETURNS VOID AS $$
                    BEGIN
                        UPDATE origin_packages SET scheduler_sync = true WHERE id = in_package_id;
                    END
                    $$ LANGUAGE plpgsql VOLATILE"#)?;
    migrator.migrate("originsrv",
                     r#"CREATE OR REPLACE FUNCTION get_origin_package_versions_for_origin_v2 (
                    op_origin text,
                    op_pkg text
                 ) RETURNS TABLE(version text, release_count bigint, latest text) AS $$
                    BEGIN
                        RETURN QUERY SELECT p.partial_ident[3] AS version, COUNT(p.partial_ident[4]) AS release_count, MAX(p.partial_ident[4]) as latest FROM (SELECT regexp_split_to_array(op.ident, '/') AS partial_ident FROM origin_packages op INNER JOIN origins o ON o.id = op.origin_id WHERE o.name = op_origin AND op.name = op_pkg) AS p GROUP BY version;
                        RETURN;
                    END
                    $$ LANGUAGE plpgsql STABLE"#)?;
    Ok(())
}
<|endoftext|>


<commit_before>use std::iter::repeat;

use error::{RuntimeError, VoidResult};
use frame::GPUFrame;
use draw::RGB;

use super::super::ffi;
use super::super::{
   Texture, Framebuffer, Shader, Program, viewport, vertex_attrib_pointer,
   enable_vertex_attrib_array, uniform_value_1i, draw_arrays,
};

pub struct QuadFrame {
   pub texture: Texture,
   pub framebuffer: Framebuffer,
   pub program: Program,
   pub vertex_attrib: ffi::GLint,
   pub tex_coord_attrib: ffi::GLint,
   pub tex_sampler_uniform: ffi::GLint,
   pub data: Vec<u8>,
}

impl GPUFrame for QuadFrame {
   #[inline]
   fn new(width: u32, height: u32) -> Result<Self, RuntimeError> {
      let data = Self::create_data(width, height);

      let texture = try!(Texture::new(width, height));
      let framebuffer = try!(Framebuffer::new(&texture));

      try!(texture.bind());
      try!(framebuffer.bind());

      let program = try!(Self::create_program());

      let vertex_attrib = try!(program.get_attrib_location("vertex"));
      let tex_coord_attrib = try!(program.get_attrib_location("texCoord"));
      let tex_sampler_uniform = try!(program.get_uniform_location("texSampler"));

      Ok(QuadFrame {
         texture: texture,
         framebuffer: framebuffer,
         data: data,
         program: program,
         vertex_attrib: vertex_attrib,
         tex_coord_attrib: tex_coord_attrib,
         tex_sampler_uniform: tex_sampler_uniform,
      })
   }

   #[inline]
   fn clear(&mut self) {
      for item in self.data.iter_mut() {
         *item = 0;
      }
   }

   #[inline]
   fn put_pixel(&mut self, x: i32, y: i32, color: &RGB, width: u32, height: u32) {
      if x >= width as i32 || y >= height as i32 || x < 0 || y < 0 {
         return;
      }

      let i = 4 * (x + y * width as i32) as usize;
      self.data[i    ] = color.r;
      self.data[i + 1] = color.g;
      self.data[i + 2] = color.b;
   }

   #[inline]
   fn resize(&mut self, width: u32, height: u32) -> VoidResult {
      self.data.resize((width * height * 4) as usize, 0);
      self.texture.resize(width, height)
   }

   #[inline]
   fn pre_render(&mut self) -> VoidResult {
      Ok(())
   }

   #[inline]
   fn post_render(&mut self, width: u32, height: u32) -> VoidResult {
      let quad_vertices = [
         -1.0, -1.0, 0.0,
         1.0, -1.0, 0.0,
         -1.0, 1.0, 0.0,
         1.0, 1.0, 0.0,
      ];

      let quad_tex_coords = [
         0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0,
      ];

      try!(self.texture.update(width, height, &self.data));

      try!(viewport(width, height));

      try!(self.program.use_program());

      try!(vertex_attrib_pointer(
         self.vertex_attrib as ffi::GLuint,
         3,
         &quad_vertices
      ));

      try!(vertex_attrib_pointer(
         self.tex_coord_attrib as ffi::GLuint,
         2,
         &quad_tex_coords
      ));

      try!(enable_vertex_attrib_array(self.vertex_attrib as ffi::GLuint));

      try!(enable_vertex_attrib_array(self.tex_coord_attrib as ffi::GLuint));

      try!(uniform_value_1i(self.tex_sampler_uniform, 0));

      draw_arrays(4)
   }
}

impl QuadFrame {
   #[inline]
   pub fn create_data(width: u32, height: u32) -> Vec<u8> {
      repeat(0u8)
         .take((width * height * 4) as usize)
         .collect::<Vec<_>>()
   }

   fn create_program() -> Result<Program, RuntimeError> {
      let vertex_src = "
         attribute vec4 vertex;
         attribute vec2 texCoord;
         varying vec2 vTexCoord;
         void main()
         {
            gl_Position = vertex;
            vTexCoord = texCoord;
         }
      ";

      let fragment_src = "
         #ifdef GL_ES
            precision mediump float;
         #endif
         varying vec2 vTexCoord;
         uniform sampler2D texSampler;
         void main()
         {
            gl_FragColor = texture2D(texSampler, vTexCoord);
         }
      ";

      let vertex = try!(Shader::new(ffi::GL_VERTEX_SHADER));

      try!(vertex.shader_source(&vertex_src));

      try!(vertex.compile());

      let fragment = try!(Shader::new(ffi::GL_FRAGMENT_SHADER));

      try!(fragment.shader_source(&fragment_src));

      try!(fragment.compile());

      let program = try!(Program::new());

      try!(program.attach_shader(&vertex));
      try!(program.attach_shader(&fragment));

      try!(program.link());

      Ok(program)
   }
}
<commit_msg>Small reorganization of the QuadFrame code<commit_after>use std::iter::repeat;

use error::{RuntimeError, VoidResult};
use frame::GPUFrame;
use draw::RGB;

use super::super::ffi;
use super::super::{
   Texture, Framebuffer, Shader, Program, viewport, vertex_attrib_pointer,
   enable_vertex_attrib_array, uniform_value_1i, draw_arrays,
};

pub struct QuadFrame {
   pub texture: Texture,
   pub framebuffer: Framebuffer,
   pub program: Program,
   pub vertex_attrib: ffi::GLint,
   pub tex_coord_attrib: ffi::GLint,
   pub tex_sampler_uniform: ffi::GLint,
   pub data: Vec<u8>,
}

impl GPUFrame for QuadFrame {
   #[inline]
   fn new(width: u32, height: u32) -> Result<Self, RuntimeError> {
      let data = Self::create_data(width, height);

      let texture = try!(Texture::new(width, height));
      let framebuffer = try!(Framebuffer::new(&texture));

      try!(texture.bind());
      try!(framebuffer.bind());

      let (program, vertex_attrib, tex_coord_attrib, tex_sampler_uniform) = try!(Self::create_program());

      Ok(QuadFrame {
         texture: texture,
         framebuffer: framebuffer,
         data: data,
         program: program,
         vertex_attrib: vertex_attrib,
         tex_coord_attrib: tex_coord_attrib,
         tex_sampler_uniform: tex_sampler_uniform,
      })
   }

   #[inline]
   fn clear(&mut self) {
      for item in self.data.iter_mut() {
         *item = 0;
      }
   }

   #[inline]
   fn put_pixel(&mut self, x: i32, y: i32, color: &RGB, width: u32, height: u32) {
      if x >= width as i32 || y >= height as i32 || x < 0 || y < 0 {
         return;
      }

      let i = 4 * (x + y * width as i32) as usize;
      self.data[i    ] = color.r;
      self.data[i + 1] = color.g;
      self.data[i + 2] = color.b;
   }

   #[inline]
   fn resize(&mut self, width: u32, height: u32) -> VoidResult {
      self.data.resize((width * height * 4) as usize, 0);
      self.texture.resize(width, height)
   }

   #[inline]
   fn pre_render(&mut self) -> VoidResult {
      Ok(())
   }

   #[inline]
   fn post_render(&mut self, width: u32, height: u32) -> VoidResult {
      let quad_vertices = [
         -1.0, -1.0, 0.0,
         1.0, -1.0, 0.0,
         -1.0, 1.0, 0.0,
         1.0, 1.0, 0.0,
      ];

      let quad_tex_coords = [
         0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0,
      ];

      try!(self.texture.update(width, height, &self.data));

      try!(viewport(width, height));

      try!(self.program.use_program());

      try!(vertex_attrib_pointer(
         self.vertex_attrib as ffi::GLuint,
         3,
         &quad_vertices
      ));

      try!(vertex_attrib_pointer(
         self.tex_coord_attrib as ffi::GLuint,
         2,
         &quad_tex_coords
      ));

      try!(enable_vertex_attrib_array(self.vertex_attrib as ffi::GLuint));

      try!(enable_vertex_attrib_array(self.tex_coord_attrib as ffi::GLuint));

      try!(uniform_value_1i(self.tex_sampler_uniform, 0));

      draw_arrays(4)
   }
}

impl QuadFrame {
   #[inline]
   pub fn create_data(width: u32, height: u32) -> Vec<u8> {
      repeat(0u8)
         .take((width * height * 4) as usize)
         .collect::<Vec<_>>()
   }

   fn create_program() -> Result<(Program, ffi::GLint, ffi::GLint, ffi::GLint), RuntimeError> {
      let vertex_src = "
         attribute vec4 vertex;
         attribute vec2 texCoord;
         varying vec2 vTexCoord;
         void main()
         {
            gl_Position = vertex;
            vTexCoord = texCoord;
         }
      ";

      let fragment_src = "
         #ifdef GL_ES
            precision mediump float;
         #endif
         varying vec2 vTexCoord;
         uniform sampler2D texSampler;
         void main()
         {
            gl_FragColor = texture2D(texSampler, vTexCoord);
         }
      ";

      let vertex = try!(Shader::new(ffi::GL_VERTEX_SHADER));

      try!(vertex.shader_source(&vertex_src));

      try!(vertex.compile());

      let fragment = try!(Shader::new(ffi::GL_FRAGMENT_SHADER));

      try!(fragment.shader_source(&fragment_src));

      try!(fragment.compile());

      let program = try!(Program::new());

      try!(program.attach_shader(&vertex));
      try!(program.attach_shader(&fragment));

      try!(program.link());

      let vertex_attrib = try!(program.get_attrib_location("vertex"));

      let tex_coord_attrib = try!(program.get_attrib_location("texCoord"));

      let tex_sampler_uniform = try!(program.get_uniform_location("texSampler"));

      Ok((program, vertex_attrib, tex_coord_attrib, tex_sampler_uniform))
   }
}
<|endoftext|>


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

use proc_macro2::TokenStream;
use rustc_hash::FxHashSet;
use syn::spanned::Spanned;

use crate::{
    cpp::{fmt_write_err_map, map_any_err_to_our_err, CppForeignMethodSignature},
    error::{panic_on_syn_error, DiagnosticError},
    typemap::{ast::DisplayToTokens, CType, CTypes, TypeMap, FROM_VAR_TEMPLATE},
    types::{ForeignEnumInfo, ForeignerClassInfo},
};

pub(in crate::cpp) fn doc_comments_to_c_comments(
    doc_comments: &[String],
    class_comments: bool,
) -> String {
    use std::fmt::Write;
    let mut comments = String::new();
    for (i, comment) in doc_comments.iter().enumerate() {
        if i != 0 {
            comments.push('\n');
        }
        if !class_comments {
            comments.push_str("    ");
        }
        write!(&mut comments, "//{}", comment.trim()).unwrap();
    }
    comments
}

pub(in crate::cpp) fn c_generate_args_with_types(
    f_method: &CppForeignMethodSignature,
    append_comma_if_not_empty: bool,
) -> Result<String, String> {
    use std::fmt::Write;

    let mut buf = String::new();
    for (i, f_type_info) in f_method.input.iter().enumerate() {
        if i > 0 {
            write!(&mut buf, ", ").map_err(fmt_write_err_map)?;
        }
        write!(&mut buf, "{} a_{}", f_type_info.as_ref().name, i).map_err(fmt_write_err_map)?;
    }
    if !buf.is_empty() && append_comma_if_not_empty {
        write!(&mut buf, ", ").map_err(fmt_write_err_map)?;
    }
    Ok(buf)
}

pub(in crate::cpp) fn c_class_type(class: &ForeignerClassInfo) -> String {
    format!("{}Opaque", class.name)
}

pub(in crate::cpp) fn cpp_generate_args_with_types(
    f_method: &CppForeignMethodSignature,
) -> Result<String, String> {
    use std::fmt::Write;
    let mut ret = String::new();
    for (i, f_type_info) in f_method.input.iter().enumerate() {
        if i > 0 {
            write!(&mut ret, ", ").map_err(fmt_write_err_map)?;
        }

        write!(
            &mut ret,
            "{} a_{}",
            if let Some(conv) = f_type_info.cpp_converter.as_ref() {
                conv.typename.clone()
            } else {
                f_type_info.as_ref().name.clone()
            },
            i
        )
        .map_err(fmt_write_err_map)?;
    }
    Ok(ret)
}

pub(in crate::cpp) fn cpp_generate_args_to_call_c(
    f_method: &CppForeignMethodSignature,
) -> Result<String, String> {
    use std::fmt::Write;
    let mut ret = String::new();
    for (i, f_type_info) in f_method.input.iter().enumerate() {
        if i > 0 {
            write!(&mut ret, ", ").map_err(fmt_write_err_map)?;
        }
        if let Some(conv) = f_type_info.cpp_converter.as_ref() {
            let arg_name = format!("a_{}", i);
            let conv_arg = conv
                .converter
                .as_str()
                .replace(FROM_VAR_TEMPLATE, &arg_name);
            write!(&mut ret, "{}", conv_arg)
        } else {
            write!(&mut ret, "a_{}", i)
        }
        .map_err(fmt_write_err_map)?;
    }
    Ok(ret)
}

pub(in crate::cpp) fn cpp_header_name(class: &ForeignerClassInfo) -> String {
    format!("{}.hpp", class.name)
}

pub(in crate::cpp) fn cpp_header_name_for_enum(enum_info: &ForeignEnumInfo) -> String {
    format!("c_{}.h", enum_info.name)
}

pub(in crate::cpp) fn cpp_list_required_includes(
    methods: &mut [CppForeignMethodSignature],
) -> Vec<String> {
    let mut includes = FxHashSet::<String>::default();
    for m in methods {
        for p in &mut m.input {
            includes.extend(mem::replace(&mut p.provides_by_module, Vec::new()).into_iter());
        }
        includes.extend(mem::replace(&mut m.output.provides_by_module, Vec::new()).into_iter());
    }

    let mut ret: Vec<_> = includes.into_iter().collect();
    ret.sort();
    ret
}

pub(in crate::cpp) fn generate_c_type(
    tmap: &TypeMap,
    c_types: &CTypes,
    out: &mut io::Write,
) -> Result<Vec<TokenStream>, DiagnosticError> {
    let mut rust_code = vec![];

    for c_type in &c_types.types {
        match c_type {
            CType::Struct(ref s) => {
                let mut rust_layout_test = format!(
                    r#"
#[allow(non_snake_case)]
#[test]
fn test_{name}_layout() {{
#[repr(C)]
struct My{name} {{
"#,
                    name = s.ident,
                );
                writeln!(out, "struct {} {{", s.ident).map_err(map_any_err_to_our_err)?;
                let fields = match s.fields {
                    syn::Fields::Named(ref x) => x,
                    _ => {
                        return Err(DiagnosticError::new(
                            c_types.src_id,
                            s.fields.span(),
                            "only fields with names accepted in this context",
                        ))
                    }
                };
                for f in &fields.named {
                    let id = f.ident.as_ref().ok_or_else(|| {
                        DiagnosticError::new(
                            c_types.src_id,
                            f.span(),
                            "only fields with names accepted in this context",
                        )
                    })?;
                    let field_rty = tmap.ty_to_rust_type_checked(&f.ty).ok_or_else(|| {
                        DiagnosticError::new(c_types.src_id, f.ty.span(), "unknown Rust type")
                    })?;
                    let field_fty = tmap
                        .find_foreign_type_related_to_rust_ty(field_rty.to_idx())
                        .ok_or_else(|| {
                            DiagnosticError::new(
                                c_types.src_id,
                                f.ty.span(),
                                "no foreign type related to this type",
                            )
                        })?;
                    writeln!(out, "    {} {};", tmap[field_fty].name.as_str(), id)
                        .map_err(map_any_err_to_our_err)?;
                    writeln!(&mut rust_layout_test, "{}: {},", id, DisplayToTokens(&f.ty))
                        .map_err(map_any_err_to_our_err)?;
                }
                out.write_all(b"};\n").map_err(map_any_err_to_our_err)?;

                writeln!(
                    &mut rust_layout_test,
                    r#"}}
    assert_eq!(::std::mem::size_of::<My{name}>(), ::std::mem::size_of::<{name}>());
    assert_eq!(::std::mem::align_of::<My{name}>(), ::std::mem::align_of::<{name}>());
}}
"#,
                    name = s.ident
                )
                .map_err(map_any_err_to_our_err)?;
                let tt: TokenStream = syn::parse_str(&rust_layout_test).unwrap_or_else(|err| {
                    panic_on_syn_error("Internal: layout unit test", rust_layout_test, err)
                });
                rust_code.push(tt);
            }
            CType::Union(ref u) => {
                unimplemented!();
            }
        }
    }

    Ok(rust_code)
}
<commit_msg>feature: more detailed test for struct defined by define_c_struct<commit_after>use std::{fmt::Write, io, mem};

use proc_macro2::TokenStream;
use rustc_hash::FxHashSet;
use syn::spanned::Spanned;

use crate::{
    cpp::{fmt_write_err_map, map_any_err_to_our_err, CppForeignMethodSignature},
    error::{panic_on_syn_error, DiagnosticError},
    typemap::{ast::DisplayToTokens, CType, CTypes, TypeMap, FROM_VAR_TEMPLATE},
    types::{ForeignEnumInfo, ForeignerClassInfo},
};

pub(in crate::cpp) fn doc_comments_to_c_comments(
    doc_comments: &[String],
    class_comments: bool,
) -> String {
    use std::fmt::Write;
    let mut comments = String::new();
    for (i, comment) in doc_comments.iter().enumerate() {
        if i != 0 {
            comments.push('\n');
        }
        if !class_comments {
            comments.push_str("    ");
        }
        write!(&mut comments, "//{}", comment.trim()).unwrap();
    }
    comments
}

pub(in crate::cpp) fn c_generate_args_with_types(
    f_method: &CppForeignMethodSignature,
    append_comma_if_not_empty: bool,
) -> Result<String, String> {
    use std::fmt::Write;

    let mut buf = String::new();
    for (i, f_type_info) in f_method.input.iter().enumerate() {
        if i > 0 {
            write!(&mut buf, ", ").map_err(fmt_write_err_map)?;
        }
        write!(&mut buf, "{} a_{}", f_type_info.as_ref().name, i).map_err(fmt_write_err_map)?;
    }
    if !buf.is_empty() && append_comma_if_not_empty {
        write!(&mut buf, ", ").map_err(fmt_write_err_map)?;
    }
    Ok(buf)
}

pub(in crate::cpp) fn c_class_type(class: &ForeignerClassInfo) -> String {
    format!("{}Opaque", class.name)
}

pub(in crate::cpp) fn cpp_generate_args_with_types(
    f_method: &CppForeignMethodSignature,
) -> Result<String, String> {
    use std::fmt::Write;
    let mut ret = String::new();
    for (i, f_type_info) in f_method.input.iter().enumerate() {
        if i > 0 {
            write!(&mut ret, ", ").map_err(fmt_write_err_map)?;
        }

        write!(
            &mut ret,
            "{} a_{}",
            if let Some(conv) = f_type_info.cpp_converter.as_ref() {
                conv.typename.clone()
            } else {
                f_type_info.as_ref().name.clone()
            },
            i
        )
        .map_err(fmt_write_err_map)?;
    }
    Ok(ret)
}

pub(in crate::cpp) fn cpp_generate_args_to_call_c(
    f_method: &CppForeignMethodSignature,
) -> Result<String, String> {
    use std::fmt::Write;
    let mut ret = String::new();
    for (i, f_type_info) in f_method.input.iter().enumerate() {
        if i > 0 {
            write!(&mut ret, ", ").map_err(fmt_write_err_map)?;
        }
        if let Some(conv) = f_type_info.cpp_converter.as_ref() {
            let arg_name = format!("a_{}", i);
            let conv_arg = conv
                .converter
                .as_str()
                .replace(FROM_VAR_TEMPLATE, &arg_name);
            write!(&mut ret, "{}", conv_arg)
        } else {
            write!(&mut ret, "a_{}", i)
        }
        .map_err(fmt_write_err_map)?;
    }
    Ok(ret)
}

pub(in crate::cpp) fn cpp_header_name(class: &ForeignerClassInfo) -> String {
    format!("{}.hpp", class.name)
}

pub(in crate::cpp) fn cpp_header_name_for_enum(enum_info: &ForeignEnumInfo) -> String {
    format!("c_{}.h", enum_info.name)
}

pub(in crate::cpp) fn cpp_list_required_includes(
    methods: &mut [CppForeignMethodSignature],
) -> Vec<String> {
    let mut includes = FxHashSet::<String>::default();
    for m in methods {
        for p in &mut m.input {
            includes.extend(mem::replace(&mut p.provides_by_module, Vec::new()).into_iter());
        }
        includes.extend(mem::replace(&mut m.output.provides_by_module, Vec::new()).into_iter());
    }

    let mut ret: Vec<_> = includes.into_iter().collect();
    ret.sort();
    ret
}

pub(in crate::cpp) fn generate_c_type(
    tmap: &TypeMap,
    c_types: &CTypes,
    out: &mut io::Write,
) -> Result<Vec<TokenStream>, DiagnosticError> {
    let mut rust_code = vec![];

    for c_type in &c_types.types {
        match c_type {
            CType::Struct(ref s) => {
                let mut rust_layout_test = format!(
                    r#"
#[allow(non_snake_case)]
#[test]
fn test_{name}_layout() {{
#[repr(C)]
struct My{name} {{
"#,
                    name = s.ident,
                );
                writeln!(out, "struct {} {{", s.ident).map_err(map_any_err_to_our_err)?;
                let fields = match s.fields {
                    syn::Fields::Named(ref x) => x,
                    _ => {
                        return Err(DiagnosticError::new(
                            c_types.src_id,
                            s.fields.span(),
                            "only fields with names accepted in this context",
                        ))
                    }
                };
                let mut fields_asserts_code = String::new();
                for f in &fields.named {
                    let id = f.ident.as_ref().ok_or_else(|| {
                        DiagnosticError::new(
                            c_types.src_id,
                            f.span(),
                            "only fields with names accepted in this context",
                        )
                    })?;
                    let field_rty = tmap.ty_to_rust_type_checked(&f.ty).ok_or_else(|| {
                        DiagnosticError::new(c_types.src_id, f.ty.span(), "unknown Rust type")
                    })?;
                    let field_fty = tmap
                        .find_foreign_type_related_to_rust_ty(field_rty.to_idx())
                        .ok_or_else(|| {
                            DiagnosticError::new(
                                c_types.src_id,
                                f.ty.span(),
                                "no foreign type related to this type",
                            )
                        })?;
                    writeln!(out, "    {} {};", tmap[field_fty].name.as_str(), id)
                        .map_err(map_any_err_to_our_err)?;
                    writeln!(&mut rust_layout_test, "{}: {},", id, DisplayToTokens(&f.ty))
                        .map_err(map_any_err_to_our_err)?;

                    writeln!(
                        &mut fields_asserts_code,
                        r#"
#[allow(dead_code)]
fn check_{struct_name}_{field_name}_type_fn(s: &{struct_name}) -> &{field_type} {{
    &s.{field_name}
}}
    let offset_our = ((&our_s.{field_name} as *const {field_type}) as usize) - ((&our_s as *const My{struct_name}) as usize);
    let offset_user = ((&user_s.{field_name} as *const {field_type}) as usize) - ((&user_s as *const {struct_name}) as usize);
    assert_eq!(offset_our, offset_user);
"#,
                        struct_name = s.ident,
                        field_name = id,
                        field_type = DisplayToTokens(&f.ty),
                    )
                    .map_err(map_any_err_to_our_err)?;
                }
                out.write_all(b"};\n").map_err(map_any_err_to_our_err)?;

                writeln!(
                    &mut rust_layout_test,
                    r#"}}
    assert_eq!(::std::mem::size_of::<My{name}>(), ::std::mem::size_of::<{name}>());
    assert_eq!(::std::mem::align_of::<My{name}>(), ::std::mem::align_of::<{name}>());
    let our_s: My{name} = unsafe {{ ::std::mem::zeroed() }};
    let user_s: {name} = unsafe {{ ::std::mem::zeroed() }};

{fields_asserts}
}}
"#,
                    name = s.ident,
                    fields_asserts = fields_asserts_code,
                )
                .map_err(map_any_err_to_our_err)?;
                let tt: TokenStream = syn::parse_str(&rust_layout_test).unwrap_or_else(|err| {
                    panic_on_syn_error("Internal: layout unit test", rust_layout_test, err)
                });
                rust_code.push(tt);
            }
            CType::Union(ref u) => {
                unimplemented!();
            }
        }
    }

    Ok(rust_code)
}
<|endoftext|>