<commit_before>use std::convert::TryFrom;
use std::io::{BufRead, Write};

use capnp::message;
use capnp::serialize as capnp_serialize;

use crate::errors::FinchResult;
use crate::filtering::FilterParams;
use crate::format_err;
use crate::serialization::mash_capnp::min_hash;
use crate::serialization::Sketch;
use crate::sketch_schemes::{ItemHash, KmerCount, SketchParams};

pub fn write_mash_file(mut file: &mut dyn Write, sketches: &[Sketch]) -> FinchResult<()> {
    let params = SketchParams::from_sketches(&sketches)?;

    let mut message = message::Builder::new_default();
    {
        let mut mash_file: min_hash::Builder = message.init_root::<min_hash::Builder>();
        mash_file.set_kmer_size(u32::from(params.k()));
        mash_file.set_hash_seed(params.hash_info().2 as u32);
        mash_file.set_error(0.0); // TODO: from filters?
                                  // TODO: should we get these next 3 from a dummy method on SketchParams?
        mash_file.set_noncanonical(false);
        mash_file.set_preserve_case(false);
        mash_file.set_alphabet("ACGT");
        // not sure what these next 3 mean or if we have the right values?
        let largest_size = sketches.iter().map(|s| s.hashes.len()).max().unwrap_or(1);
        mash_file.set_window_size(u32::from(params.k()));
        mash_file.set_min_hashes_per_window(largest_size as u32);
        mash_file.set_concatenated(true);

        let mash_sketches_list = mash_file.init_reference_list();
        let mut mash_sketches = mash_sketches_list.init_references(sketches.len() as u32);

        for (i, sketch) in sketches.iter().enumerate() {
            let mut mash_sketch: min_hash::reference_list::reference::Builder =
                mash_sketches.reborrow().get(i as u32);
            mash_sketch.set_name(&sketch.name);
            mash_sketch.set_comment(&sketch.comment);
            mash_sketch.set_length64(sketch.seq_length);
            mash_sketch.set_num_valid_kmers(sketch.num_valid_kmers);
            {
                let mash_hashes = mash_sketch
                    .reborrow()
                    .init_hashes64(sketch.hashes.len() as u32);
                for (j, hash) in sketch.hashes.iter().enumerate() {
                    mash_hashes.reborrow().set(j as u32, hash.hash as u64);
                }
            }
            let mash_counts = mash_sketch.init_counts32(sketch.hashes.len() as u32);
            for (j, hash) in sketch.hashes.iter().enumerate() {
                mash_counts.reborrow().set(
                    j as u32,
                    TryFrom::try_from(hash.count).map_err(|_| {
                        format_err!("Counts greater than 32-bit not supported in mash files")
                    })?,
                );
            }
        }
    }

    capnp_serialize::write_message(&mut file, &message)?;
    Ok(())
}

pub fn read_mash_file(mut file: &mut dyn BufRead) -> FinchResult<Vec<Sketch>> {
    let options = *message::ReaderOptions::new().traversal_limit_in_words(Some(1024 * 1024 * 1024));
    let reader = capnp_serialize::read_message(&mut file, options)?;
    let mash_data: min_hash::Reader = reader.get_root::<min_hash::Reader>()?;

    let kmers_to_sketch = 0;

    let sketch_params = SketchParams::Mash {
        kmers_to_sketch,
        final_size: kmers_to_sketch,
        no_strict: true,
        hash_seed: u64::from(mash_data.get_hash_seed()),
        kmer_length: mash_data.get_kmer_size() as u8,
    };

    /*
        alphabet: String::from(mash_data.get_alphabet()?),
        preserve_case: mash_data.get_preserve_case(),
        canonical: !mash_data.get_noncanonical(),
    */

    let reference_list = mash_data.get_reference_list()?;
    let reference_list_old = mash_data.get_reference_list_old()?;

    let references = if reference_list.has_references() {
        reference_list.get_references()?
    } else {
        reference_list_old.get_references()?
    };

    let mut sketches = Vec::new();
    for reference in references {
        let hashes = reference.get_hashes64()?;
        let counts = reference.get_counts32()?;
        let kmercounts = if counts.len() == 0 {
            // reference_list_old doesn't seem to have counts?
            hashes
                .iter()
                .map(|h| KmerCount {
                    hash: h as ItemHash,
                    kmer: Vec::new(),
                    count: 1,
                    extra_count: 0,
                    label: None,
                })
                .collect()
        } else {
            hashes
                .iter()
                .zip(counts.iter())
                .map(|(h, c)| KmerCount {
                    hash: h as ItemHash,
                    kmer: Vec::new(),
                    count: c,
                    extra_count: c / 2,
                    label: None,
                })
                .collect()
        };

        sketches.push(Sketch {
            name: String::from(reference.get_name()?),
            seq_length: reference.get_length64(),
            num_valid_kmers: reference.get_num_valid_kmers(),
            comment: String::from(reference.get_comment()?),
            hashes: kmercounts,
            sketch_params: sketch_params.clone(),
            filter_params: FilterParams::default(),
        });
    }

    Ok(sketches)
}
<commit_msg>clippy<commit_after>use std::io::{BufRead, Write};

use capnp::message;
use capnp::serialize as capnp_serialize;

use crate::errors::FinchResult;
use crate::filtering::FilterParams;
use crate::serialization::mash_capnp::min_hash;
use crate::serialization::Sketch;
use crate::sketch_schemes::{ItemHash, KmerCount, SketchParams};

pub fn write_mash_file(mut file: &mut dyn Write, sketches: &[Sketch]) -> FinchResult<()> {
    let params = SketchParams::from_sketches(&sketches)?;

    let mut message = message::Builder::new_default();
    {
        let mut mash_file: min_hash::Builder = message.init_root::<min_hash::Builder>();
        mash_file.set_kmer_size(u32::from(params.k()));
        mash_file.set_hash_seed(params.hash_info().2 as u32);
        mash_file.set_error(0.0); // TODO: from filters?
                                  // TODO: should we get these next 3 from a dummy method on SketchParams?
        mash_file.set_noncanonical(false);
        mash_file.set_preserve_case(false);
        mash_file.set_alphabet("ACGT");
        // not sure what these next 3 mean or if we have the right values?
        let largest_size = sketches.iter().map(|s| s.hashes.len()).max().unwrap_or(1);
        mash_file.set_window_size(u32::from(params.k()));
        mash_file.set_min_hashes_per_window(largest_size as u32);
        mash_file.set_concatenated(true);

        let mash_sketches_list = mash_file.init_reference_list();
        let mut mash_sketches = mash_sketches_list.init_references(sketches.len() as u32);

        for (i, sketch) in sketches.iter().enumerate() {
            let mut mash_sketch: min_hash::reference_list::reference::Builder =
                mash_sketches.reborrow().get(i as u32);
            mash_sketch.set_name(&sketch.name);
            mash_sketch.set_comment(&sketch.comment);
            mash_sketch.set_length64(sketch.seq_length);
            mash_sketch.set_num_valid_kmers(sketch.num_valid_kmers);
            {
                let mash_hashes = mash_sketch
                    .reborrow()
                    .init_hashes64(sketch.hashes.len() as u32);
                for (j, hash) in sketch.hashes.iter().enumerate() {
                    mash_hashes.reborrow().set(j as u32, hash.hash as u64);
                }
            }
            let mash_counts = mash_sketch.init_counts32(sketch.hashes.len() as u32);
            for (j, hash) in sketch.hashes.iter().enumerate() {
                mash_counts.reborrow().set(j as u32, hash.count);
            }
        }
    }

    capnp_serialize::write_message(&mut file, &message)?;
    Ok(())
}

pub fn read_mash_file(mut file: &mut dyn BufRead) -> FinchResult<Vec<Sketch>> {
    let options = *message::ReaderOptions::new().traversal_limit_in_words(Some(1024 * 1024 * 1024));
    let reader = capnp_serialize::read_message(&mut file, options)?;
    let mash_data: min_hash::Reader = reader.get_root::<min_hash::Reader>()?;

    let kmers_to_sketch = 0;

    let sketch_params = SketchParams::Mash {
        kmers_to_sketch,
        final_size: kmers_to_sketch,
        no_strict: true,
        hash_seed: u64::from(mash_data.get_hash_seed()),
        kmer_length: mash_data.get_kmer_size() as u8,
    };

    /*
        alphabet: String::from(mash_data.get_alphabet()?),
        preserve_case: mash_data.get_preserve_case(),
        canonical: !mash_data.get_noncanonical(),
    */

    let reference_list = mash_data.get_reference_list()?;
    let reference_list_old = mash_data.get_reference_list_old()?;

    let references = if reference_list.has_references() {
        reference_list.get_references()?
    } else {
        reference_list_old.get_references()?
    };

    let mut sketches = Vec::new();
    for reference in references {
        let hashes = reference.get_hashes64()?;
        let counts = reference.get_counts32()?;
        let kmercounts = if counts.len() == 0 {
            // reference_list_old doesn't seem to have counts?
            hashes
                .iter()
                .map(|h| KmerCount {
                    hash: h as ItemHash,
                    kmer: Vec::new(),
                    count: 1,
                    extra_count: 0,
                    label: None,
                })
                .collect()
        } else {
            hashes
                .iter()
                .zip(counts.iter())
                .map(|(h, c)| KmerCount {
                    hash: h as ItemHash,
                    kmer: Vec::new(),
                    count: c,
                    extra_count: c / 2,
                    label: None,
                })
                .collect()
        };

        sketches.push(Sketch {
            name: String::from(reference.get_name()?),
            seq_length: reference.get_length64(),
            num_valid_kmers: reference.get_num_valid_kmers(),
            comment: String::from(reference.get_comment()?),
            hashes: kmercounts,
            sketch_params: sketch_params.clone(),
            filter_params: FilterParams::default(),
        });
    }

    Ok(sketches)
}
<|endoftext|>


<commit_before>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io
#![cfg_attr(feature = "serde_derive", feature(rustc_macro))]
#[cfg(feature = "serde_derive")]
#[macro_use]
extern crate serde_derive;

extern crate serde;
extern crate serde_json;

#[macro_use]
extern crate log;
extern crate env_logger;

extern crate chrono;
extern crate hyper;
extern crate rs_es;
extern crate regex;
extern crate geo;
extern crate geojson;

pub mod objects;
pub mod rubber;

pub use objects::*;

pub fn logger_init() -> Result<(), log::SetLoggerError> {
    let mut builder = env_logger::LogBuilder::new();
    builder.filter(None, log::LogLevelFilter::Info);
    if let Ok(s) = std::env::var("RUST_LOG") {
        builder.parse(&s);
    }
    builder.init()
}
<commit_msg>add the possibility to trace the time in log<commit_after>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io
#![cfg_attr(feature = "serde_derive", feature(rustc_macro))]
#[cfg(feature = "serde_derive")]
#[macro_use]
extern crate serde_derive;

extern crate serde;
extern crate serde_json;

#[macro_use]
extern crate log;
extern crate env_logger;

extern crate chrono;
extern crate hyper;
extern crate rs_es;
extern crate regex;
extern crate geo;
extern crate geojson;

pub mod objects;
pub mod rubber;
pub use objects::*;
use chrono::Local;

pub fn logger_init() -> Result<(), log::SetLoggerError> {
    let mut builder = env_logger::LogBuilder::new();

    if let Ok(s) = std::env::var("LOG_TIME") {
        if s == "1" {
            builder.format(|record| {
                format!("[{time}]{lvl}:{loc}: {msg}",
                        time = Local::now(),
                        lvl = record.level(),
                        loc = record.location().module_path(),
                        msg = record.args())
            });
        }
    }

    builder.filter(None, log::LogLevelFilter::Info);
    if let Ok(s) = std::env::var("RUST_LOG") {
        builder.parse(&s);
    }
    builder.init()
}
<|endoftext|>


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

#![crate_name = "snowmew-render"]
#![license = "ASL2"]
#![crate_type = "lib"]
#![comment = "A game engine in rust"]
#![allow(dead_code)]
#![feature(phase)]
#![feature(if_let)]

//extern crate debug;

extern crate collections;
extern crate time;
extern crate libc;
extern crate rustrt;

extern crate glfw;
extern crate cgmath;
extern crate cow;
extern crate gl;
extern crate opencl;
extern crate ovr;
extern crate collision;
extern crate gfx;
#[phase(plugin)]
extern crate gfx_macros;

extern crate gl_cl;

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

use std::task;
use std::comm::{Receiver, Sender};
use std::mem;
use std::sync::{TaskPool, Future, Arc};
use time::precise_time_s;

use opencl::hl::{CommandQueue, Context, Device};

use snowmew::common::Entity;
use snowmew::camera::Camera;
use snowmew::io::Window;
use position::Positions;

pub use config::Config;

use pipeline::Pipeline;
use drawlist::{Drawlist, create_drawlist};
use query::{ProfilerDummy, TimeQueryManager, Profiler};

use render_data::Renderable;

mod db;
mod shader;
mod vertex_buffer;
mod drawlist;
mod pipeline;
mod query;
//mod compute_accelerator;
mod config;
mod texture;
mod material;
mod light;
mod model;
mod matrix;
mod command;

enum RenderCommand {
    Update(Box<Renderable+Send>),
    Finish
}

fn render_thread(input: Receiver<(Box<Drawlist+Send>, Entity)>,
                 output: Sender<Box<Drawlist+Send>>,
                 window: Window,
                 size: (i32, i32),
                 config: Config,
                 cl: Option<(Arc<Context>, Arc<CommandQueue>, Arc<Device>)>) {

    window.make_context_current();
    let mut db = db::GlState::new();

    let mut pipeline = {
        if !window.is_hmd() {
            box pipeline::Swap::new(
                pipeline::Defered::new(pipeline::Forward::new()),
                window
            ) as Box<Pipeline>
        } else {
            box pipeline::Hmd::new(
                pipeline::Defered::new(pipeline::Forward::new()),
                window,
                &config
            ) as Box<Pipeline>
        }
    };

    let (width, height) = size;
    pipeline.resize(width as uint, height as uint);

    // todo move!
    unsafe {gl::Enable(gl::SCISSOR_TEST);}

    for _ in range(1, config.drawlist_count()) {
        let mut dl = create_drawlist(&config, cl.clone());
        dl.setup_begin();
        output.send(dl);
    }

    let mut next_dl = create_drawlist(&config, cl.clone());

    let mut qm = if config.profile() {
        box TimeQueryManager::new() as Box<Profiler>
    } else {
        box ProfilerDummy as Box<Profiler>
    };
    let mut last_frame = precise_time_s();
    for (mut dl, camera) in input.iter() {
        qm.time("setup complete".to_string());
        dl.setup_complete(&mut db, &config);

        let capture = precise_time_s();
        let camera_trans = dl.position(camera);
        let camera = Camera::new(camera_trans);

        let (w, h) = dl.io_state().size;
        pipeline.resize(w, h);
        pipeline.render(&mut *dl, &mut db, &camera, &mut *qm);
        // if the device is a hmd we need to stall the gpu
        // to make sure it actually flipped the buffers

        if config.fps() {
            let end = precise_time_s();
            println!("total: {:4.2}ms capture: {:4.2}ms {:4.1}fps",
                (end - dl.start_time()) * 1000., (end - capture) * 1000.,
                1. / (end - last_frame));
            last_frame = end;
        }

        qm.time("setup begin".to_string());
        mem::swap(&mut next_dl, &mut dl);
        dl.setup_begin();
        output.send(dl);

        qm.dump();
        qm.reset();
    }
}

fn render_server(command: Receiver<RenderCommand>,
                 window: Window,
                 size: (i32, i32),
                 dev: Option<Arc<Device>>) {

    let config = Config::new(window.get_context_version());

    let cl = if config.opencl() {
        setup_opencl(&window, dev)
    } else {
        None
    };

    let mut taskbuilder = task::TaskBuilder::new();
    taskbuilder = taskbuilder.named("render-thread".into_maybe_owned());

    let (send_drawlist_setup, receiver_drawlist_setup) = channel();
    let (send_drawlist_ready, receiver_drawlist_ready) = channel();
    taskbuilder.spawn(proc() {
        let window = window;
        render_thread(receiver_drawlist_setup,
                      send_drawlist_ready,
                      window,
                      size,
                      config,
                      cl
        );
    });

    let (send_drawlist_render, receiver_drawlist_render)
        : (Sender<Box<Drawlist+Send>>, Receiver<Box<Drawlist+Send>>) = channel();
    let mut taskpool = TaskPool::new(config.thread_pool_size());

    let mut drawlists_ready = Vec::new();

    let select = std::comm::Select::new();
    let mut receiver_drawlist_ready_handle = select.handle(&receiver_drawlist_ready);
    let mut receiver_drawlist_render_handle = select.handle(&receiver_drawlist_render);
    let mut command_handle = select.handle(&command);

    unsafe {
        receiver_drawlist_ready_handle.add();
        receiver_drawlist_render_handle.add();
        command_handle.add();
    }

    let mut db = None;

    'finished: loop {
        let id = select.wait();
        if id == receiver_drawlist_ready_handle.id() {
            let dl = receiver_drawlist_ready_handle.recv();
            drawlists_ready.push(dl);
        } else if id == receiver_drawlist_render_handle.id() {
            let dl = receiver_drawlist_render_handle.recv();
            let camera = dl.camera().expect("no camera found");
            send_drawlist_setup.send((dl, camera));
        } else if id == command_handle.id() {
            let command = command_handle.recv();
            match command {
                RenderCommand::Update(rd) => db = Some(rd),
                RenderCommand::Finish => break 'finished
            }
        }

        if drawlists_ready.len() > 0 {
            if let Some(mut db) = db {
                let dl = drawlists_ready.pop().unwrap();
                let scene = db.scene().expect("no scene set");
                dl.setup_compute(&mut *db, &mut taskpool, scene, send_drawlist_render.clone());
            }
            db = None;
        }
    }
}

fn setup_opencl(window: &Window, dev: Option<Arc<Device>>) -> Option<(Arc<Context>, Arc<CommandQueue>, Arc<Device>)> {
    window.make_context_current();
    let cl = match dev {
        Some(dev) => {
            let ctx = gl_cl::create_context(dev.deref());
            match ctx {
                Some(ctx) => {
                    let queue = ctx.create_command_queue(dev.deref());
                    Some((Arc::new(ctx), Arc::new(queue), dev))
                }
                None => None
            }
        },
        None => None
    };
    glfw::make_context_current(None);
    cl
}

pub struct RenderManager {
    ch: Sender<RenderCommand>,
    render_done: Future<rustrt::task::Result>
}

impl RenderManager {
    fn _new(window: Window, size: (i32, i32), dev: Option<Arc<Device>>) -> RenderManager {
        let mut taskbuilder = task::TaskBuilder::new();
        taskbuilder = taskbuilder.named("render-server".into_maybe_owned());

        let (sender, receiver) = channel();
        let render_main_result = taskbuilder.try_future(proc() {
            let window = window;

            render_server(receiver, window, size, dev.clone());
        });

        RenderManager {
            ch: sender,
            render_done: render_main_result
        }
    }

    pub fn new_cl(window: Window, size: (i32, i32), device: Arc<Device>) -> RenderManager {
        RenderManager::_new(window, size, Some(device))
    }

    pub fn new(window: Window, size: (i32, i32)) -> RenderManager {
        RenderManager::_new(window, size, None)
    }

    pub fn update(&mut self, db: Box<Renderable+Send>) {
        self.ch.send(RenderCommand::Update(db));
    }
}

impl Drop for RenderManager {
    fn drop(&mut self) {
        self.ch.send(RenderCommand::Finish);
        self.render_done.get_ref();
    }
}

impl<RD: Renderable+Send> snowmew::Render<RD> for RenderManager {
    fn update(&mut self, db: RD) {
        self.ch.send(RenderCommand::Update(box db));
    }
}

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

pub struct RenderFactory;

impl RenderFactory {
    pub fn new() -> RenderFactory { RenderFactory }
}<commit_msg>update to latest rustc<commit_after>//   Copyright 2014 Colin Sherratt
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

#![crate_name = "snowmew-render"]
#![license = "ASL2"]
#![crate_type = "lib"]
#![comment = "A game engine in rust"]
#![allow(dead_code)]
#![feature(phase)]
#![feature(if_let)]

//extern crate debug;

extern crate collections;
extern crate time;
extern crate libc;
extern crate rustrt;

extern crate glfw;
extern crate cgmath;
extern crate cow;
extern crate gl;
extern crate opencl;
extern crate ovr;
extern crate collision;
extern crate gfx;
#[phase(plugin)]
extern crate gfx_macros;

extern crate gl_cl;

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

use std::task;
use std::comm::{Receiver, Sender};
use std::mem;
use std::sync::{TaskPool, Future, Arc};
use time::precise_time_s;

use opencl::hl::{CommandQueue, Context, Device};

use snowmew::common::Entity;
use snowmew::camera::Camera;
use snowmew::io::Window;
use position::Positions;

pub use config::Config;

use pipeline::Pipeline;
use drawlist::{Drawlist, create_drawlist};
use query::{ProfilerDummy, TimeQueryManager, Profiler};

use render_data::Renderable;

mod db;
mod shader;
mod vertex_buffer;
mod drawlist;
mod pipeline;
mod query;
//mod compute_accelerator;
mod config;
mod texture;
mod material;
mod light;
mod model;
mod matrix;
mod command;

enum RenderCommand {
    Update(Box<Renderable+Send>),
    Finish
}

fn render_thread(input: Receiver<(Box<Drawlist+Send>, Entity)>,
                 output: Sender<Box<Drawlist+Send>>,
                 window: Window,
                 size: (i32, i32),
                 config: Config,
                 cl: Option<(Arc<Context>, Arc<CommandQueue>, Arc<Device>)>) {

    window.make_context_current();
    let mut db = db::GlState::new();

    let mut pipeline = {
        if !window.is_hmd() {
            box pipeline::Swap::new(
                pipeline::Defered::new(pipeline::Forward::new()),
                window
            ) as Box<Pipeline>
        } else {
            box pipeline::Hmd::new(
                pipeline::Defered::new(pipeline::Forward::new()),
                window,
                &config
            ) as Box<Pipeline>
        }
    };

    let (width, height) = size;
    pipeline.resize(width as uint, height as uint);

    // todo move!
    unsafe {gl::Enable(gl::SCISSOR_TEST);}

    for _ in range(1, config.drawlist_count()) {
        let mut dl = create_drawlist(&config, cl.clone());
        dl.setup_begin();
        output.send(dl);
    }

    let mut next_dl = create_drawlist(&config, cl.clone());

    let mut qm = if config.profile() {
        box TimeQueryManager::new() as Box<Profiler>
    } else {
        box ProfilerDummy as Box<Profiler>
    };
    let mut last_frame = precise_time_s();
    for (mut dl, camera) in input.iter() {
        qm.time("setup complete".to_string());
        dl.setup_complete(&mut db, &config);

        let capture = precise_time_s();
        let camera_trans = dl.position(camera);
        let camera = Camera::new(camera_trans);

        let (w, h) = dl.io_state().size;
        pipeline.resize(w, h);
        pipeline.render(&mut *dl, &mut db, &camera, &mut *qm);
        // if the device is a hmd we need to stall the gpu
        // to make sure it actually flipped the buffers

        if config.fps() {
            let end = precise_time_s();
            println!("total: {:4.2}ms capture: {:4.2}ms {:4.1}fps",
                (end - dl.start_time()) * 1000., (end - capture) * 1000.,
                1. / (end - last_frame));
            last_frame = end;
        }

        qm.time("setup begin".to_string());
        mem::swap(&mut next_dl, &mut dl);
        dl.setup_begin();
        output.send(dl);

        qm.dump();
        qm.reset();
    }
}

fn render_server(command: Receiver<RenderCommand>,
                 window: Window,
                 size: (i32, i32),
                 dev: Option<Arc<Device>>) {

    let config = Config::new(window.get_context_version());

    let cl = if config.opencl() {
        setup_opencl(&window, dev)
    } else {
        None
    };

    let mut taskbuilder = task::TaskBuilder::new();
    taskbuilder = taskbuilder.named("render-thread");

    let (send_drawlist_setup, receiver_drawlist_setup) = channel();
    let (send_drawlist_ready, receiver_drawlist_ready) = channel();
    taskbuilder.spawn(proc() {
        let window = window;
        render_thread(receiver_drawlist_setup,
                      send_drawlist_ready,
                      window,
                      size,
                      config,
                      cl
        );
    });

    let (send_drawlist_render, receiver_drawlist_render)
        : (Sender<Box<Drawlist+Send>>, Receiver<Box<Drawlist+Send>>) = channel();
    let mut taskpool = TaskPool::new(config.thread_pool_size());

    let mut drawlists_ready = Vec::new();

    let select = std::comm::Select::new();
    let mut receiver_drawlist_ready_handle = select.handle(&receiver_drawlist_ready);
    let mut receiver_drawlist_render_handle = select.handle(&receiver_drawlist_render);
    let mut command_handle = select.handle(&command);

    unsafe {
        receiver_drawlist_ready_handle.add();
        receiver_drawlist_render_handle.add();
        command_handle.add();
    }

    let mut db = None;

    'finished: loop {
        let id = select.wait();
        if id == receiver_drawlist_ready_handle.id() {
            let dl = receiver_drawlist_ready_handle.recv();
            drawlists_ready.push(dl);
        } else if id == receiver_drawlist_render_handle.id() {
            let dl = receiver_drawlist_render_handle.recv();
            let camera = dl.camera().expect("no camera found");
            send_drawlist_setup.send((dl, camera));
        } else if id == command_handle.id() {
            let command = command_handle.recv();
            match command {
                RenderCommand::Update(rd) => db = Some(rd),
                RenderCommand::Finish => break 'finished
            }
        }

        if drawlists_ready.len() > 0 {
            if let Some(mut db) = db {
                let dl = drawlists_ready.pop().unwrap();
                let scene = db.scene().expect("no scene set");
                dl.setup_compute(&mut *db, &mut taskpool, scene, send_drawlist_render.clone());
            }
            db = None;
        }
    }
}

fn setup_opencl(window: &Window, dev: Option<Arc<Device>>) -> Option<(Arc<Context>, Arc<CommandQueue>, Arc<Device>)> {
    window.make_context_current();
    let cl = match dev {
        Some(dev) => {
            let ctx = gl_cl::create_context(dev.deref());
            match ctx {
                Some(ctx) => {
                    let queue = ctx.create_command_queue(dev.deref());
                    Some((Arc::new(ctx), Arc::new(queue), dev))
                }
                None => None
            }
        },
        None => None
    };
    glfw::make_context_current(None);
    cl
}

pub struct RenderManager {
    ch: Sender<RenderCommand>,
    render_done: Future<rustrt::task::Result>
}

impl RenderManager {
    fn _new(window: Window, size: (i32, i32), dev: Option<Arc<Device>>) -> RenderManager {
        let mut taskbuilder = task::TaskBuilder::new();
        taskbuilder = taskbuilder.named("render-server");

        let (sender, receiver) = channel();
        let render_main_result = taskbuilder.try_future(proc() {
            let window = window;

            render_server(receiver, window, size, dev.clone());
        });

        RenderManager {
            ch: sender,
            render_done: render_main_result
        }
    }

    pub fn new_cl(window: Window, size: (i32, i32), device: Arc<Device>) -> RenderManager {
        RenderManager::_new(window, size, Some(device))
    }

    pub fn new(window: Window, size: (i32, i32)) -> RenderManager {
        RenderManager::_new(window, size, None)
    }

    pub fn update(&mut self, db: Box<Renderable+Send>) {
        self.ch.send(RenderCommand::Update(db));
    }
}

impl Drop for RenderManager {
    fn drop(&mut self) {
        self.ch.send(RenderCommand::Finish);
        self.render_done.get_ref();
    }
}

impl<RD: Renderable+Send> snowmew::Render<RD> for RenderManager {
    fn update(&mut self, db: RD) {
        self.ch.send(RenderCommand::Update(box db));
    }
}

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

pub struct RenderFactory;

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


<commit_before>use tensor::Tensor;
use blas;

macro_rules! add_impl {
    ($t:ty, $gemv:ident, $gemm:ident, $dot:ident) => (
        impl Tensor<$t> {
            /// Takes the product of two tensors. If the tensors are both matrices (2D), then a
            /// matrix multiplication is taken. If the tensors are both vectors (1D), the scalar
            /// product is taken.
            pub fn dot(&self, rhs: &Tensor<$t>) -> Tensor<$t> {
                if self.ndim() == 2 && rhs.ndim() == 1 {
                    assert_eq!(self.shape[1], rhs.shape[0]);
                    let mut t3 = Tensor::empty(&[self.shape[0]]);
                    if cfg!(noblas) {
                        // Naive implementation, BLAS will be much faster
                        for i in 0..self.shape[0] {
                            let mut v = 0.0;
                            for k in 0..self.shape[1] {
                                v += self.get(i, k) * rhs.data[k];
                            }
                            t3.data[i] = v;
                        }
                    } else {
                        blas::$gemv(b'T', self.shape[1], self.shape[0], 1.0, &self.data,
                                    self.shape[1], &rhs.data, 1, 0.0, &mut t3.data, 1);
                    }
                    t3
                } else if self.ndim() == 2 && rhs.ndim() == 2 {
                    assert_eq!(self.shape[1], rhs.shape[0]);
                    let mut t3 = Tensor::empty(&[self.shape[0], rhs.shape[1]]);
                    if cfg!(noblas) {
                        // Naive implementation, BLAS will be much faster
                        for i in 0..self.shape[0] {
                            for j in 0..rhs.shape[1] {
                                let mut v = 0.0;
                                for k in 0..self.shape[1] {
                                    v += self.get(i, k) * rhs.get(k, j);
                                }
                                t3.set2(i, j, v);
                            }
                        }
                    } else {
                        // Note: dgemm assumes column-major while we have row-major,
                        //       so we have to re-arrange things a bit
                        blas::$gemm(b'N', b'N', rhs.shape[1], self.shape[0], rhs.shape[0], 1.0,
                                    &rhs.data, rhs.shape[1], &self.data, rhs.shape[0], 0.0,
                                    &mut t3.data, rhs.shape[1]);
                    }
                    t3
                } else if self.ndim() == 1 && rhs.ndim() == 1 { // scalar product
                    assert_eq!(self.size(), rhs.size());
                    let mut v = 0.0;
                    if cfg!(noblas) {
                        // Naive implementation, BLAS will be much faster
                        for k in 0..self.shape[0] {
                            v += self.data[k] * rhs.data[k];
                        }
                    } else {
                        v = blas::$dot(self.size(), &self.data, 1, &rhs.data, 1);
                    }
                    Tensor::new(vec![v])
                } else {
                    panic!("Dot product is not supported for the matrix dimensions provided");
                }
            }
        }
    )
}

add_impl!(f32, sgemv, sgemm, sdot);
add_impl!(f64, dgemv, dgemm, ddot);
<commit_msg>Return proper scalar when dot operates on vectors<commit_after>use tensor::Tensor;
use blas;

macro_rules! add_impl {
    ($t:ty, $gemv:ident, $gemm:ident, $dot:ident) => (
        impl Tensor<$t> {
            /// Takes the product of two tensors. If the tensors are both matrices (2D), then a
            /// matrix multiplication is taken. If the tensors are both vectors (1D), the scalar
            /// product is taken.
            pub fn dot(&self, rhs: &Tensor<$t>) -> Tensor<$t> {
                if self.ndim() == 2 && rhs.ndim() == 1 {
                    assert_eq!(self.shape[1], rhs.shape[0]);
                    let mut t3 = Tensor::empty(&[self.shape[0]]);
                    if cfg!(noblas) {
                        // Naive implementation, BLAS will be much faster
                        for i in 0..self.shape[0] {
                            let mut v = 0.0;
                            for k in 0..self.shape[1] {
                                v += self.get(i, k) * rhs.data[k];
                            }
                            t3.data[i] = v;
                        }
                    } else {
                        blas::$gemv(b'T', self.shape[1], self.shape[0], 1.0, &self.data,
                                    self.shape[1], &rhs.data, 1, 0.0, &mut t3.data, 1);
                    }
                    t3
                } else if self.ndim() == 2 && rhs.ndim() == 2 {
                    assert_eq!(self.shape[1], rhs.shape[0]);
                    let mut t3 = Tensor::empty(&[self.shape[0], rhs.shape[1]]);
                    if cfg!(noblas) {
                        // Naive implementation, BLAS will be much faster
                        for i in 0..self.shape[0] {
                            for j in 0..rhs.shape[1] {
                                let mut v = 0.0;
                                for k in 0..self.shape[1] {
                                    v += self.get(i, k) * rhs.get(k, j);
                                }
                                t3.set2(i, j, v);
                            }
                        }
                    } else {
                        // Note: dgemm assumes column-major while we have row-major,
                        //       so we have to re-arrange things a bit
                        blas::$gemm(b'N', b'N', rhs.shape[1], self.shape[0], rhs.shape[0], 1.0,
                                    &rhs.data, rhs.shape[1], &self.data, rhs.shape[0], 0.0,
                                    &mut t3.data, rhs.shape[1]);
                    }
                    t3
                } else if self.ndim() == 1 && rhs.ndim() == 1 { // scalar product
                    assert_eq!(self.size(), rhs.size());
                    let mut v = 0.0;
                    if cfg!(noblas) {
                        // Naive implementation, BLAS will be much faster
                        for k in 0..self.shape[0] {
                            v += self.data[k] * rhs.data[k];
                        }
                    } else {
                        v = blas::$dot(self.size(), &self.data, 1, &rhs.data, 1);
                    }
                    Tensor::scalar(v)
                } else {
                    panic!("Dot product is not supported for the matrix dimensions provided");
                }
            }
        }
    )
}

add_impl!(f32, sgemv, sgemm, sdot);
add_impl!(f64, dgemv, dgemm, ddot);
<|endoftext|>


<commit_before>use std::collections::HashSet;
use chrono::Utc;
use serde::ser::Serialize;
use serde_json::map::Map;
use serde_json::{from_value, to_value, Value};

use crate::algorithms::Algorithm;
use crate::errors::{new_error, ErrorKind, Result};

/// Contains the various validations that are applied after decoding a token.
///
/// All time validation happen on UTC timestamps.
///
/// ```rust
/// use jsonwebtoken::Validation;
///
/// // Default value
/// let validation = Validation::default();
///
/// // Changing one parameter
/// let mut validation = Validation {leeway: 60, ..Default::default()};
///
/// // Setting audience
/// let mut validation = Validation::default();
/// validation.set_audience(&"Me"); // string
/// validation.set_audience(&["Me", "You"]); // array of strings
/// ```
#[derive(Debug, Clone, PartialEq)]
pub struct Validation {
    /// Add some leeway (in seconds) to the `exp`, `iat` and `nbf` validation to
    /// account for clock skew.
    ///
    /// Defaults to `0`.
    pub leeway: i64,
    /// Whether to validate the `exp` field.
    ///
    /// It will return an error if the time in the `exp` field is past.
    ///
    /// Defaults to `true`.
    pub validate_exp: bool,
    /// Whether to validate the `nbf` field.
    ///
    /// It will return an error if the current timestamp is before the time in the `nbf` field.
    ///
    /// Defaults to `false`.
    pub validate_nbf: bool,
    /// If it contains a value, the validation will check that the `aud` field is the same as the
    /// one provided and will error otherwise.
    /// Since `aud` can be either a String or a Vec<String> in the JWT spec, you will need to use
    /// the [set_audience](struct.Validation.html#method.set_audience) method to set it.
    ///
    /// Defaults to `None`.
    pub aud: Option<HashSet<String>>,
    /// If it contains a value, the validation will check that the `iss` field is the same as the
    /// one provided and will error otherwise.
    ///
    /// Defaults to `None`.
    pub iss: Option<String>,
    /// If it contains a value, the validation will check that the `sub` field is the same as the
    /// one provided and will error otherwise.
    ///
    /// Defaults to `None`.
    pub sub: Option<String>,
    /// If it contains a value, the validation will check that the `alg` of the header is contained
    /// in the ones provided and will error otherwise.
    ///
    /// Defaults to `vec![Algorithm::HS256]`.
    pub algorithms: Vec<Algorithm>,
}

impl Validation {
    /// Create a default validation setup allowing the given alg
    pub fn new(alg: Algorithm) -> Validation {
        let mut validation = Validation::default();
        validation.algorithms = vec![alg];
        validation
    }

    /// Since `aud` can be either a String or an array of String in the JWT spec, this method will take
    /// care of serializing the value.
    pub fn set_audience<T: Serialize>(&mut self, audience: &T) {
		let aud = to_value(audience)
				  .unwrap_or_else(|_| panic!("Failed to_value within set_audience)"));
		let aud = Validation::convert_aud(&aud)
				  .unwrap_or_else(|_| panic!("Failed convert_aud within set_audience"));
        self.aud = Some(aud);
    }

	/// Converts a Value, representing a String or collection of Strings, to a
    /// HashSet<String>, required for audience membership testing
	fn convert_aud(aud: &Value) -> Result<HashSet<String>> {
		let aud_from_claim: Vec<String> = match aud.is_array() {
			true => from_value(aud.clone()).unwrap(),
			false => {
				let aud_str: String = match from_value(aud.clone()) {
					Ok(val) => val,
					Err(_) => return Err(new_error(ErrorKind::InvalidAudience)),
				};
				vec![aud_str]
			}
		};

	   Ok(aud_from_claim.into_iter().collect())
	}
}

impl Default for Validation {
    fn default() -> Validation {
        Validation {
            leeway: 0,

            validate_exp: true,
            validate_nbf: false,

            iss: None,
            sub: None,
            aud: None,

            algorithms: vec![Algorithm::HS256],
        }
    }
}

pub fn validate(claims: &Map<String, Value>, options: &Validation) -> Result<()> {
    let now = Utc::now().timestamp();

    if options.validate_exp {
        if let Some(exp) = claims.get("exp") {
            if from_value::<i64>(exp.clone())? < now - options.leeway {
                return Err(new_error(ErrorKind::ExpiredSignature));
            }
        } else {
            return Err(new_error(ErrorKind::ExpiredSignature));
        }
    }

    if options.validate_nbf {
        if let Some(nbf) = claims.get("nbf") {
            if from_value::<i64>(nbf.clone())? > now + options.leeway {
                return Err(new_error(ErrorKind::ImmatureSignature));
            }
        } else {
            return Err(new_error(ErrorKind::ImmatureSignature));
        }
    }

    if let Some(ref correct_iss) = options.iss {
        if let Some(iss) = claims.get("iss") {
            if from_value::<String>(iss.clone())? != *correct_iss {
                return Err(new_error(ErrorKind::InvalidIssuer));
            }
        } else {
            return Err(new_error(ErrorKind::InvalidIssuer));
        }
    }

    if let Some(ref correct_sub) = options.sub {
        if let Some(sub) = claims.get("sub") {
            if from_value::<String>(sub.clone())? != *correct_sub {
                return Err(new_error(ErrorKind::InvalidSubject));
            }
        } else {
            return Err(new_error(ErrorKind::InvalidSubject));
        }
    }

    if let Some(ref correct_aud) = options.aud {
        if let Some(aud) = claims.get("aud") {
			let converted_aud = Validation::convert_aud(aud)?;
			if converted_aud.intersection(correct_aud).count() == 0 {
                return Err(new_error(ErrorKind::InvalidAudience));
            }
        } else {
            return Err(new_error(ErrorKind::InvalidAudience));
        }
    }

    Ok(())
}

#[cfg(test)]
mod tests {
    use chrono::Utc;
    use serde_json::map::Map;
    use serde_json::to_value;

    use super::{validate, Validation};

    use crate::errors::ErrorKind;

    #[test]
    fn exp_in_future_ok() {
        let mut claims = Map::new();
        claims.insert("exp".to_string(), to_value(Utc::now().timestamp() + 10000).unwrap());
        let res = validate(&claims, &Validation::default());
        assert!(res.is_ok());
    }

    #[test]
    fn exp_in_past_fails() {
        let mut claims = Map::new();
        claims.insert("exp".to_string(), to_value(Utc::now().timestamp() - 100000).unwrap());
        let res = validate(&claims, &Validation::default());
        assert!(res.is_err());

        match res.unwrap_err().kind() {
            &ErrorKind::ExpiredSignature => (),
            _ => assert!(false),
        };
    }

    #[test]
    fn exp_in_past_but_in_leeway_ok() {
        let mut claims = Map::new();
        claims.insert("exp".to_string(), to_value(Utc::now().timestamp() - 500).unwrap());
        let validation = Validation { leeway: 1000 * 60, ..Default::default() };
        let res = validate(&claims, &validation);
        assert!(res.is_ok());
    }

    // https://github.com/Keats/jsonwebtoken/issues/51
    #[test]
    fn validation_called_even_if_field_is_empty() {
        let claims = Map::new();
        let res = validate(&claims, &Validation::default());
        assert!(res.is_err());
        match res.unwrap_err().kind() {
            &ErrorKind::ExpiredSignature => (),
            _ => assert!(false),
        };
    }

    #[test]
    fn nbf_in_past_ok() {
        let mut claims = Map::new();
        claims.insert("nbf".to_string(), to_value(Utc::now().timestamp() - 10000).unwrap());
        let validation =
            Validation { validate_exp: false, validate_nbf: true, ..Validation::default() };
        let res = validate(&claims, &validation);
        assert!(res.is_ok());
    }

    #[test]
    fn nbf_in_future_fails() {
        let mut claims = Map::new();
        claims.insert("nbf".to_string(), to_value(Utc::now().timestamp() + 100000).unwrap());
        let validation =
            Validation { validate_exp: false, validate_nbf: true, ..Validation::default() };
        let res = validate(&claims, &validation);
        assert!(res.is_err());

        match res.unwrap_err().kind() {
            &ErrorKind::ImmatureSignature => (),
            _ => assert!(false),
        };
    }

    #[test]
    fn nbf_in_future_but_in_leeway_ok() {
        let mut claims = Map::new();
        claims.insert("nbf".to_string(), to_value(Utc::now().timestamp() + 500).unwrap());
        let validation = Validation {
            leeway: 1000 * 60,
            validate_nbf: true,
            validate_exp: false,
            ..Default::default()
        };
        let res = validate(&claims, &validation);
        assert!(res.is_ok());
    }

    #[test]
    fn iss_ok() {
        let mut claims = Map::new();
        claims.insert("iss".to_string(), to_value("Keats").unwrap());
        let validation = Validation {
            validate_exp: false,
            iss: Some("Keats".to_string()),
            ..Default::default()
        };
        let res = validate(&claims, &validation);
        assert!(res.is_ok());
    }

    #[test]
    fn iss_not_matching_fails() {
        let mut claims = Map::new();
        claims.insert("iss".to_string(), to_value("Hacked").unwrap());
        let validation = Validation {
            validate_exp: false,
            iss: Some("Keats".to_string()),
            ..Default::default()
        };
        let res = validate(&claims, &validation);
        assert!(res.is_err());

        match res.unwrap_err().kind() {
            &ErrorKind::InvalidIssuer => (),
            _ => assert!(false),
        };
    }

    #[test]
    fn iss_missing_fails() {
        let claims = Map::new();
        let validation = Validation {
            validate_exp: false,
            iss: Some("Keats".to_string()),
            ..Default::default()
        };
        let res = validate(&claims, &validation);
        assert!(res.is_err());

        match res.unwrap_err().kind() {
            &ErrorKind::InvalidIssuer => (),
            _ => assert!(false),
        };
    }

    #[test]
    fn sub_ok() {
        let mut claims = Map::new();
        claims.insert("sub".to_string(), to_value("Keats").unwrap());
        let validation = Validation {
            validate_exp: false,
            sub: Some("Keats".to_string()),
            ..Default::default()
        };
        let res = validate(&claims, &validation);
        assert!(res.is_ok());
    }

    #[test]
    fn sub_not_matching_fails() {
        let mut claims = Map::new();
        claims.insert("sub".to_string(), to_value("Hacked").unwrap());
        let validation = Validation {
            validate_exp: false,
            sub: Some("Keats".to_string()),
            ..Default::default()
        };
        let res = validate(&claims, &validation);
        assert!(res.is_err());

        match res.unwrap_err().kind() {
            &ErrorKind::InvalidSubject => (),
            _ => assert!(false),
        };
    }

    #[test]
    fn sub_missing_fails() {
        let claims = Map::new();
        let validation = Validation {
            validate_exp: false,
            sub: Some("Keats".to_string()),
            ..Default::default()
        };
        let res = validate(&claims, &validation);
        assert!(res.is_err());

        match res.unwrap_err().kind() {
            &ErrorKind::InvalidSubject => (),
            _ => assert!(false),
        };
    }

    #[test]
    fn aud_string_ok() {
        let mut claims = Map::new();
        claims.insert("aud".to_string(), to_value("Everyone").unwrap());
        let mut validation = Validation { validate_exp: false, ..Validation::default() };
        validation.set_audience(&"Everyone");
        let res = validate(&claims, &validation);
        assert!(res.is_ok());
    }

    #[test]
    fn aud_array_of_string_ok() {
        let mut claims = Map::new();
        claims.insert("aud".to_string(), to_value(["UserA", "UserB"]).unwrap());
        let mut validation = Validation { validate_exp: false, ..Validation::default() };
        validation.set_audience(&["UserA", "UserB"]);
        let res = validate(&claims, &validation);
        assert!(res.is_ok());
    }

    #[test]
    fn aud_type_mismatch_fails() {
        let mut claims = Map::new();
        claims.insert("aud".to_string(), to_value("Everyone").unwrap());
        let mut validation = Validation { validate_exp: false, ..Validation::default() };
        validation.set_audience(&["UserA", "UserB"]);
        let res = validate(&claims, &validation);
        assert!(res.is_err());

        match res.unwrap_err().kind() {
            &ErrorKind::InvalidAudience => (),
            _ => assert!(false),
        };
    }

    #[test]
    fn aud_correct_type_not_matching_fails() {
        let mut claims = Map::new();
        claims.insert("aud".to_string(), to_value("Everyone").unwrap());
        let mut validation = Validation { validate_exp: false, ..Validation::default() };
        validation.set_audience(&"None");
        let res = validate(&claims, &validation);
        assert!(res.is_err());

        match res.unwrap_err().kind() {
            &ErrorKind::InvalidAudience => (),
            _ => assert!(false),
        };
    }

    #[test]
    fn aud_missing_fails() {
        let claims = Map::new();
        let mut validation = Validation { validate_exp: false, ..Validation::default() };
        validation.set_audience(&"None");
        let res = validate(&claims, &validation);
        assert!(res.is_err());

        match res.unwrap_err().kind() {
            &ErrorKind::InvalidAudience => (),
            _ => assert!(false),
        };
    }
}
<commit_msg>revised set_audience, cleaned up validation, and cleared compiler warnings<commit_after>use std::collections::HashSet;
use chrono::Utc;
use serde_json::map::Map;
use serde_json::{from_value, Value};

use crypto::Algorithm;
use errors::{new_error, ErrorKind, Result};

/// Contains the various validations that are applied after decoding a token.
///
/// All time validation happen on UTC timestamps.
///
/// ```rust
/// use jsonwebtoken::Validation;
///
/// // Default value
/// let validation = Validation::default();
///
/// // Changing one parameter
/// let mut validation = Validation {leeway: 60, ..Default::default()};
///
/// // Setting audience
/// let mut validation = Validation::default();
/// validation.set_audience(&["Me"]); // a single string
/// validation.set_audience(&["Me", "You"]); // array of strings
/// ```
#[derive(Debug, Clone, PartialEq)]
pub struct Validation {
    /// Add some leeway (in seconds) to the `exp`, `iat` and `nbf` validation to
    /// account for clock skew.
    ///
    /// Defaults to `0`.
    pub leeway: i64,
    /// Whether to validate the `exp` field.
    ///
    /// It will return an error if the time in the `exp` field is past.
    ///
    /// Defaults to `true`.
    pub validate_exp: bool,
    /// Whether to validate the `nbf` field.
    ///
    /// It will return an error if the current timestamp is before the time in the `nbf` field.
    ///
    /// Defaults to `false`.
    pub validate_nbf: bool,
    /// If it contains a value, the validation will check that the `aud` field is a member of the
    /// audience provided and will error otherwise.
    ///
    /// Defaults to `None`.
    pub aud: Option<HashSet<String>>,
    /// If it contains a value, the validation will check that the `iss` field is the same as the
    /// one provided and will error otherwise.
    ///
    /// Defaults to `None`.
    pub iss: Option<String>,
    /// If it contains a value, the validation will check that the `sub` field is the same as the
    /// one provided and will error otherwise.
    ///
    /// Defaults to `None`.
    pub sub: Option<String>,
    /// If it contains a value, the validation will check that the `alg` of the header is contained
    /// in the ones provided and will error otherwise.
    ///
    /// Defaults to `vec![Algorithm::HS256]`.
    pub algorithms: Vec<Algorithm>,
}

impl Validation {
    /// Create a default validation setup allowing the given alg
    pub fn new(alg: Algorithm) -> Validation {
        let mut validation = Validation::default();
        validation.algorithms = vec![alg];
        validation
    }

    /// `aud` is a collection of one or more acceptable audience members
    pub fn set_audience<T: ToString>(&mut self, items: &[T]) {
        self.aud = Some(items.iter().map(|x| x.to_string()).collect())
    }
}

impl Default for Validation {
    fn default() -> Validation {
        Validation {
            leeway: 0,

            validate_exp: true,
            validate_nbf: false,

            iss: None,
            sub: None,
            aud: None,

            algorithms: vec![Algorithm::HS256],
        }
    }
}

pub fn validate(claims: &Map<String, Value>, options: &Validation) -> Result<()> {
    let now = Utc::now().timestamp();

    if options.validate_exp {
        if let Some(exp) = claims.get("exp") {
            if from_value::<i64>(exp.clone())? < now - options.leeway {
                return Err(new_error(ErrorKind::ExpiredSignature));
            }
        } else {
            return Err(new_error(ErrorKind::ExpiredSignature));
        }
    }

    if options.validate_nbf {
        if let Some(nbf) = claims.get("nbf") {
            if from_value::<i64>(nbf.clone())? > now + options.leeway {
                return Err(new_error(ErrorKind::ImmatureSignature));
            }
        } else {
            return Err(new_error(ErrorKind::ImmatureSignature));
        }
    }

    if let Some(ref correct_iss) = options.iss {
        if let Some(iss) = claims.get("iss") {
            if from_value::<String>(iss.clone())? != *correct_iss {
                return Err(new_error(ErrorKind::InvalidIssuer));
            }
        } else {
            return Err(new_error(ErrorKind::InvalidIssuer));
        }
    }

    if let Some(ref correct_sub) = options.sub {
        if let Some(sub) = claims.get("sub") {
            if from_value::<String>(sub.clone())? != *correct_sub {
                return Err(new_error(ErrorKind::InvalidSubject));
            }
        } else {
            return Err(new_error(ErrorKind::InvalidSubject));
        }
    }

    if let Some(ref correct_aud) = options.aud {
        if let Some(aud) = claims.get("aud") {
			let provided_aud: HashSet<String> = from_value(aud.clone())?;
			if provided_aud.intersection(correct_aud).count() == 0 {
                return Err(new_error(ErrorKind::InvalidAudience));
            }
        } else {
            return Err(new_error(ErrorKind::InvalidAudience));
        }
    }

    Ok(())
}

#[cfg(test)]
mod tests {
    use chrono::Utc;
    use serde_json::map::Map;
    use serde_json::to_value;

    use super::{validate, Validation};

    use errors::ErrorKind;

    #[test]
    fn exp_in_future_ok() {
        let mut claims = Map::new();
        claims.insert("exp".to_string(), to_value(Utc::now().timestamp() + 10000).unwrap());
        let res = validate(&claims, &Validation::default());
        assert!(res.is_ok());
    }

    #[test]
    fn exp_in_past_fails() {
        let mut claims = Map::new();
        claims.insert("exp".to_string(), to_value(Utc::now().timestamp() - 100000).unwrap());
        let res = validate(&claims, &Validation::default());
        assert!(res.is_err());

        match res.unwrap_err().kind() {
            &ErrorKind::ExpiredSignature => (),
            _ => assert!(false),
        };
    }

    #[test]
    fn exp_in_past_but_in_leeway_ok() {
        let mut claims = Map::new();
        claims.insert("exp".to_string(), to_value(Utc::now().timestamp() - 500).unwrap());
        let validation = Validation { leeway: 1000 * 60, ..Default::default() };
        let res = validate(&claims, &validation);
        assert!(res.is_ok());
    }

    // https://github.com/Keats/jsonwebtoken/issues/51
    #[test]
    fn validation_called_even_if_field_is_empty() {
        let claims = Map::new();
        let res = validate(&claims, &Validation::default());
        assert!(res.is_err());
        match res.unwrap_err().kind() {
            &ErrorKind::ExpiredSignature => (),
            _ => assert!(false),
        };
    }

    #[test]
    fn nbf_in_past_ok() {
        let mut claims = Map::new();
        claims.insert("nbf".to_string(), to_value(Utc::now().timestamp() - 10000).unwrap());
        let validation =
            Validation { validate_exp: false, validate_nbf: true, ..Validation::default() };
        let res = validate(&claims, &validation);
        assert!(res.is_ok());
    }

    #[test]
    fn nbf_in_future_fails() {
        let mut claims = Map::new();
        claims.insert("nbf".to_string(), to_value(Utc::now().timestamp() + 100000).unwrap());
        let validation =
            Validation { validate_exp: false, validate_nbf: true, ..Validation::default() };
        let res = validate(&claims, &validation);
        assert!(res.is_err());

        match res.unwrap_err().kind() {
            &ErrorKind::ImmatureSignature => (),
            _ => assert!(false),
        };
    }

    #[test]
    fn nbf_in_future_but_in_leeway_ok() {
        let mut claims = Map::new();
        claims.insert("nbf".to_string(), to_value(Utc::now().timestamp() + 500).unwrap());
        let validation = Validation {
            leeway: 1000 * 60,
            validate_nbf: true,
            validate_exp: false,
            ..Default::default()
        };
        let res = validate(&claims, &validation);
        assert!(res.is_ok());
    }

    #[test]
    fn iss_ok() {
        let mut claims = Map::new();
        claims.insert("iss".to_string(), to_value("Keats").unwrap());
        let validation = Validation {
            validate_exp: false,
            iss: Some("Keats".to_string()),
            ..Default::default()
        };
        let res = validate(&claims, &validation);
        assert!(res.is_ok());
    }

    #[test]
    fn iss_not_matching_fails() {
        let mut claims = Map::new();
        claims.insert("iss".to_string(), to_value("Hacked").unwrap());
        let validation = Validation {
            validate_exp: false,
            iss: Some("Keats".to_string()),
            ..Default::default()
        };
        let res = validate(&claims, &validation);
        assert!(res.is_err());

        match res.unwrap_err().kind() {
            &ErrorKind::InvalidIssuer => (),
            _ => assert!(false),
        };
    }

    #[test]
    fn iss_missing_fails() {
        let claims = Map::new();
        let validation = Validation {
            validate_exp: false,
            iss: Some("Keats".to_string()),
            ..Default::default()
        };
        let res = validate(&claims, &validation);
        assert!(res.is_err());

        match res.unwrap_err().kind() {
            &ErrorKind::InvalidIssuer => (),
            _ => assert!(false),
        };
    }

    #[test]
    fn sub_ok() {
        let mut claims = Map::new();
        claims.insert("sub".to_string(), to_value("Keats").unwrap());
        let validation = Validation {
            validate_exp: false,
            sub: Some("Keats".to_string()),
            ..Default::default()
        };
        let res = validate(&claims, &validation);
        assert!(res.is_ok());
    }

    #[test]
    fn sub_not_matching_fails() {
        let mut claims = Map::new();
        claims.insert("sub".to_string(), to_value("Hacked").unwrap());
        let validation = Validation {
            validate_exp: false,
            sub: Some("Keats".to_string()),
            ..Default::default()
        };
        let res = validate(&claims, &validation);
        assert!(res.is_err());

        match res.unwrap_err().kind() {
            &ErrorKind::InvalidSubject => (),
            _ => assert!(false),
        };
    }

    #[test]
    fn sub_missing_fails() {
        let claims = Map::new();
        let validation = Validation {
            validate_exp: false,
            sub: Some("Keats".to_string()),
            ..Default::default()
        };
        let res = validate(&claims, &validation);
        assert!(res.is_err());

        match res.unwrap_err().kind() {
            &ErrorKind::InvalidSubject => (),
            _ => assert!(false),
        };
    }

    #[test]
    fn aud_string_ok() {
        let mut claims = Map::new();
        claims.insert("aud".to_string(), to_value(["Everyone"]).unwrap());
        let mut validation = Validation { validate_exp: false, ..Validation::default() };
        validation.set_audience(&["Everyone"]);
        let res = validate(&claims, &validation);
        assert!(res.is_ok());
    }

    #[test]
    fn aud_array_of_string_ok() {
        let mut claims = Map::new();
        claims.insert("aud".to_string(), to_value(["UserA", "UserB"]).unwrap());
        let mut validation = Validation { validate_exp: false, ..Validation::default() };
        validation.set_audience(&["UserA", "UserB"]);
        let res = validate(&claims, &validation);
        assert!(res.is_ok());
    }

    #[test]
    fn aud_type_mismatch_fails() {
        let mut claims = Map::new();
        claims.insert("aud".to_string(), to_value(["Everyone"]).unwrap());
        let mut validation = Validation { validate_exp: false, ..Validation::default() };
        validation.set_audience(&["UserA", "UserB"]);
        let res = validate(&claims, &validation);
        assert!(res.is_err());

        match res.unwrap_err().kind() {
            &ErrorKind::InvalidAudience => (),
            _ => assert!(false),
        };
    }

    #[test]
    fn aud_correct_type_not_matching_fails() {
        let mut claims = Map::new();
        claims.insert("aud".to_string(), to_value(["Everyone"]).unwrap());
        let mut validation = Validation { validate_exp: false, ..Validation::default() };
        validation.set_audience(&["None"]);
        let res = validate(&claims, &validation);
        assert!(res.is_err());

        match res.unwrap_err().kind() {
            &ErrorKind::InvalidAudience => (),
            _ => assert!(false),
        };
    }

    #[test]
    fn aud_missing_fails() {
        let claims = Map::new();
        let mut validation = Validation { validate_exp: false, ..Validation::default() };
        validation.set_audience(&["None"]);
        let res = validate(&claims, &validation);
        assert!(res.is_err());

        match res.unwrap_err().kind() {
            &ErrorKind::InvalidAudience => (),
            _ => assert!(false),
        };
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

use std::raw::Repr;
use vector::ops::{Copy, Axpy, Scal, Dot, Nrm2, Asum, Iamax};

pub mod ll;
pub mod ops;

pub trait Vector<T> {
    fn inc(&self) -> i32;
    fn len(&self) -> i32;
    fn as_ptr(&self) -> *const T;
    fn as_mut_ptr(&mut self) -> *mut T;
}

pub trait VectorOperations<T>: Vector<T>
    where T: Copy + Axpy + Scal + Dot + Nrm2 + Asum + Iamax {

    #[inline]
    fn into_vec(&self) -> Vec<T> {
        let n = self.len() as uint;

        let mut x = Vec::with_capacity(n);
        Copy::copy(self, &mut x);
        unsafe { x.set_len(n); }

        x
    }

    #[inline]
    fn update(&mut self, alpha: &T, x: &Vector<T>) -> &mut Self {
        Axpy::axpy(alpha, x, self);
        self
    }

    #[inline]
    fn scale(&mut self, alpha: &T) -> &mut Self {
        Scal::scal(alpha, self);
        self
    }

    #[inline]
    fn dot(&self, x: &Vector<T>) -> T {
        Dot::dot(self, x)
    }

    #[inline]
    fn abs_sum(&self) -> T {
        Asum::asum(self)
    }

    #[inline]
    fn norm(&self) -> T {
        Nrm2::nrm2(self)
    }

    #[inline]
    fn max_index(&self) -> uint {
        Iamax::iamax(self)
    }
}

impl<T> Vector<T> for Vec<T> {
    #[inline]
    fn inc(&self) -> i32 { 1i32 }

    #[inline]
    fn len(&self) -> i32 {
        let l: Option<i32> = NumCast::from(self.len());
        match l {
            Some(l) => l,
            None => panic!(),
        }
    }

    #[inline]
    fn as_ptr(&self) -> *const T { self.as_slice().as_ptr() }

    #[inline]
    fn as_mut_ptr(&mut self) -> *mut T { self.as_mut_slice().as_mut_ptr() }
}

impl<'a, T> Vector<T> for &'a [T] {
    #[inline]
    fn inc(&self) -> i32 { 1i32 }

    #[inline]
    fn len(&self) -> i32 {
        let l: Option<i32> = NumCast::from(self.len());
        match l {
            Some(l) => l,
            None => panic!(),
        }
    }

    #[inline]
    fn as_ptr(&self) -> *const T { self.repr().data }

    #[inline]
    fn as_mut_ptr(&mut self) -> *mut T { self.repr().data as *mut T }
}
<commit_msg>Implement VectorOperations for vectors and slices<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

extern crate num;

use std::raw::Repr;
use self::num::complex::{Complex32, Complex64};
use vector::ops::{Copy, Axpy, Scal, Dot, Nrm2, Asum, Iamax};

pub mod ll;
pub mod ops;

pub trait Vector<T> {
    fn inc(&self) -> i32;
    fn len(&self) -> i32;
    fn as_ptr(&self) -> *const T;
    fn as_mut_ptr(&mut self) -> *mut T;
}

pub trait VectorOperations<T>: Vector<T>
    where T: Copy + Axpy + Scal + Dot + Nrm2 + Asum + Iamax {

    #[inline]
    fn into_vec(&self) -> Vec<T> {
        let n = self.len() as uint;

        let mut x = Vec::with_capacity(n);
        Copy::copy(self, &mut x);
        unsafe { x.set_len(n); }

        x
    }

    #[inline]
    fn update(&mut self, alpha: &T, x: &Vector<T>) -> &mut Self {
        Axpy::axpy(alpha, x, self);
        self
    }

    #[inline]
    fn scale(&mut self, alpha: &T) -> &mut Self {
        Scal::scal(alpha, self);
        self
    }

    #[inline]
    fn dot(&self, x: &Vector<T>) -> T {
        Dot::dot(self, x)
    }

    #[inline]
    fn abs_sum(&self) -> T {
        Asum::asum(self)
    }

    #[inline]
    fn norm(&self) -> T {
        Nrm2::nrm2(self)
    }

    #[inline]
    fn max_index(&self) -> uint {
        Iamax::iamax(self)
    }
}

impl<T> Vector<T> for Vec<T> {
    #[inline]
    fn inc(&self) -> i32 { 1i32 }

    #[inline]
    fn len(&self) -> i32 {
        let l: Option<i32> = NumCast::from(self.len());
        match l {
            Some(l) => l,
            None => panic!(),
        }
    }

    #[inline]
    fn as_ptr(&self) -> *const T { self.as_slice().as_ptr() }

    #[inline]
    fn as_mut_ptr(&mut self) -> *mut T { self.as_mut_slice().as_mut_ptr() }
}

impl<'a, T> Vector<T> for &'a [T] {
    #[inline]
    fn inc(&self) -> i32 { 1i32 }

    #[inline]
    fn len(&self) -> i32 {
        let l: Option<i32> = NumCast::from(self.len());
        match l {
            Some(l) => l,
            None => panic!(),
        }
    }

    #[inline]
    fn as_ptr(&self) -> *const T { self.repr().data }

    #[inline]
    fn as_mut_ptr(&mut self) -> *mut T { self.repr().data as *mut T }
}

macro_rules! operations_impl(
    ($v: ident, $($t: ty), +) => (
        $( impl VectorOperations<$t> for $v<$t> {} )+
    )
)

operations_impl!(Vec, f32, f64, Complex32, Complex64)
impl<'a> VectorOperations<f32> for &'a [f32] {}
impl<'a> VectorOperations<f64> for &'a [f64] {}
impl<'a> VectorOperations<Complex32> for &'a [Complex32] {}
impl<'a> VectorOperations<Complex64> for &'a [Complex64] {}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

extern crate glutin;
extern crate cgmath;
extern crate serialize;

use cgmath::{Vector2, Vector3};
use core_types::{Size2, ZInt, MapPos};
use visualizer_types::{ZFloat, Color3, Color4, ColorId, MatId, WorldPos, ScreenPos, VertexCoord};
use zgl::{Zgl, Mesh};
use camera::Camera;
use shader::{Shader};
use geom;
use core_map::{MapPosIter};

static VS_SRC: &'static str = "\
    #version 100\n\
    uniform mat4 mvp_mat;\n\
    attribute vec2 position;\n\
    void main() {\n\
        gl_Position = mvp_mat * vec4(position, 0.0, 1.0);\n\
    }\n\
";

static FS_SRC: &'static str = "\
    #version 100\n\
    precision mediump float;
    uniform vec4 col;\n\
    void main() {\n\
        gl_FragColor = col;\n\
    }\n\
";

fn get_win_size(window: &glutin::Window) -> Size2<ZInt> {
    let (w, h) = window.get_inner_size().expect("Can`t get window size");
    Size2{w: w as ZInt, h: h as ZInt}
}

fn get_max_camera_pos(map_size: &Size2<ZInt>) -> WorldPos {
    let pos = geom::map_pos_to_world_pos(
        MapPos{v: Vector2{x: map_size.w, y: map_size.h}});
    WorldPos{v: Vector3{x: -pos.v.x, y: -pos.v.y, z: 0.0}}
}

fn generate_mesh(map_size: &Size2<ZInt>, zgl: &Zgl) -> Mesh {
    let mut vertex_data = Vec::new();
    for tile_pos in MapPosIter::new(map_size) {
        let pos = geom::map_pos_to_world_pos(tile_pos);
        // TODO: range(0, 6) -> some dir iterator
        for num in range(0i32, 6) {
            let vertex = geom::index_to_hex_vertex(num);
            let next_vertex = geom::index_to_hex_vertex(num + 1);
            vertex_data.push(VertexCoord{v: pos.v + vertex.v});
            vertex_data.push(VertexCoord{v: pos.v + next_vertex.v});
            vertex_data.push(VertexCoord{v: pos.v});
        }
    }
    Mesh::new(zgl, vertex_data.as_slice())
}

pub struct Visualizer {
    zgl: Zgl,
    window: glutin::Window,
    should_close: bool,
    color_counter: i32, // TODO: remove
    test_color: Color4,
    shader: Shader,
    color_uniform_location: ColorId,
    mvp_uniform_location: MatId,
    camera: Camera,
    mouse_pos: ScreenPos,
    is_lmb_pressed: bool,
    win_size: Size2<ZInt>,
    mesh: Mesh,
}

impl Visualizer {
    pub fn new() -> Visualizer {
        let window_builder = glutin::WindowBuilder::new().with_gl_version((2, 0));
        let window = window_builder.build().ok().expect("Can`t create window");
        unsafe {
            window.make_current();
        };
        let win_size = get_win_size(&window);
        let mut zgl = Zgl::new(|s| window.get_proc_address(s));
        zgl.print_gl_info();
        let shader = Shader::new(&zgl, VS_SRC, FS_SRC);
        let color_uniform_location = shader.get_uniform_color(&zgl, "col");
        let mvp_uniform_location = shader.get_uniform_mat(&zgl, "mvp_mat");
        zgl.set_clear_color(Color3{r: 0.0, g: 0.0, b: 0.4});
        let mut camera = Camera::new(&win_size);
        let map_size = Size2{w: 5, h: 2};
        camera.set_max_pos(get_max_camera_pos(&map_size));
        let mesh = generate_mesh(&map_size, &zgl);
        Visualizer {
            zgl: zgl,
            window: window,
            should_close: false,
            color_counter: 0,
            test_color: Color4{r: 0.0, g: 0.0, b: 0.0, a: 0.0},
            shader: shader,
            color_uniform_location: color_uniform_location,
            mvp_uniform_location: mvp_uniform_location,
            camera: camera,
            mouse_pos: ScreenPos{v: Vector2::from_value(0)},
            is_lmb_pressed: false,
            win_size: win_size,
            mesh: mesh,
        }
    }

    pub fn is_running(&self) -> bool {
        !self.should_close
    }

    fn handle_event(&mut self, event: &glutin::Event) {
        match *event {
            glutin::Event::Closed => {
                self.should_close = true;
            },
            glutin::Event::Resized(w, h) => {
                self.win_size = Size2{w: w as ZInt, h: h as ZInt};
                self.zgl.set_viewport(&self.win_size);
            },
            glutin::Event::MouseMoved((x, y)) => {
                let new_pos = ScreenPos{v: Vector2{x: x as ZInt, y: y as ZInt}};
                if self.is_lmb_pressed {
                    let diff = new_pos.v - self.mouse_pos.v;
                    let win_w = self.win_size.w as ZFloat;
                    let win_h = self.win_size.h as ZFloat;
                    self.camera.add_z_angle(diff.x as ZFloat * (360.0 / win_w));
                    self.camera.add_x_angle(diff.y as ZFloat * (360.0 / win_h));
                }
                self.mouse_pos = new_pos;
            },
            glutin::Event::MouseInput(
                glutin::ElementState::Pressed,
                glutin::MouseButton::LeftMouseButton,
            ) => {
                self.is_lmb_pressed = true;
            },
            glutin::Event::MouseInput(
                glutin::ElementState::Released,
                glutin::MouseButton::LeftMouseButton,
            ) => {
                self.is_lmb_pressed = false;
                let (r, g, b, a) = self.zgl.read_pixel_bytes(
                    &self.win_size, &self.mouse_pos);
                println!("r: {}, g: {}, b: {}, a: {}", r, g, b, a);
            },
            glutin::Event::KeyboardInput(_, _, Some(key)) => match key {
                glutin::VirtualKeyCode::Q | glutin::VirtualKeyCode::Escape => {
                    self.should_close = true;
                },
                glutin::VirtualKeyCode::W => self.camera.move_camera(270.0, 0.1),
                glutin::VirtualKeyCode::S => self.camera.move_camera(90.0, 0.1),
                glutin::VirtualKeyCode::D => self.camera.move_camera(0.0, 0.1),
                glutin::VirtualKeyCode::A => self.camera.move_camera(180.0, 0.1),
                glutin::VirtualKeyCode::Minus => self.camera.change_zoom(1.3),
                glutin::VirtualKeyCode::Equals => self.camera.change_zoom(0.7),
                _ => {},
            },
            _ => {},
        }
    }

    fn handle_events(&mut self) {
        let events = self.window.poll_events().collect::<Vec<_>>();
        if events.is_empty() {
            return;
        }
        println!("{}", events);
        for event in events.iter() {
            self.handle_event(event);
        }
    }

    fn update_test_color(&mut self) {
        self.test_color = match self.color_counter {
            0 => Color4{r: 1.0, g: 0.0, b: 0.0, a: 1.0},
            30 => Color4{r: 0.0, g: 1.0, b: 0.0, a: 1.0},
            60 => Color4{r: 0.0, g: 0.0, b: 1.0, a: 1.0},
            _ => self.test_color,
        };
        self.color_counter += 1;
        if self.color_counter > 90 {
            self.color_counter = -1;
        }
    }

    fn draw(&mut self) {
        self.zgl.clear_screen();
        self.shader.activate(&self.zgl);
        self.shader.set_uniform_color(
            &self.zgl, self.color_uniform_location, &self.test_color);
        self.shader.set_uniform_mat4f(
            &self.zgl, self.mvp_uniform_location, &self.camera.mat(&self.zgl));
        self.mesh.draw(&self.zgl);
        self.window.swap_buffers();
    }

    pub fn tick(&mut self) {
        self.handle_events();
        // self.logic();
        self.update_test_color();
        self.draw();
        // self.update_time();
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>src/visualizer.rs: Commented-out 'println!({}, events)'<commit_after>// See LICENSE file for copyright and license details.

extern crate glutin;
extern crate cgmath;
extern crate serialize;

use cgmath::{Vector2, Vector3};
use core_types::{Size2, ZInt, MapPos};
use visualizer_types::{ZFloat, Color3, Color4, ColorId, MatId, WorldPos, ScreenPos, VertexCoord};
use zgl::{Zgl, Mesh};
use camera::Camera;
use shader::{Shader};
use geom;
use core_map::{MapPosIter};

static VS_SRC: &'static str = "\
    #version 100\n\
    uniform mat4 mvp_mat;\n\
    attribute vec2 position;\n\
    void main() {\n\
        gl_Position = mvp_mat * vec4(position, 0.0, 1.0);\n\
    }\n\
";

static FS_SRC: &'static str = "\
    #version 100\n\
    precision mediump float;
    uniform vec4 col;\n\
    void main() {\n\
        gl_FragColor = col;\n\
    }\n\
";

fn get_win_size(window: &glutin::Window) -> Size2<ZInt> {
    let (w, h) = window.get_inner_size().expect("Can`t get window size");
    Size2{w: w as ZInt, h: h as ZInt}
}

fn get_max_camera_pos(map_size: &Size2<ZInt>) -> WorldPos {
    let pos = geom::map_pos_to_world_pos(
        MapPos{v: Vector2{x: map_size.w, y: map_size.h}});
    WorldPos{v: Vector3{x: -pos.v.x, y: -pos.v.y, z: 0.0}}
}

fn generate_mesh(map_size: &Size2<ZInt>, zgl: &Zgl) -> Mesh {
    let mut vertex_data = Vec::new();
    for tile_pos in MapPosIter::new(map_size) {
        let pos = geom::map_pos_to_world_pos(tile_pos);
        // TODO: range(0, 6) -> some dir iterator
        for num in range(0i32, 6) {
            let vertex = geom::index_to_hex_vertex(num);
            let next_vertex = geom::index_to_hex_vertex(num + 1);
            vertex_data.push(VertexCoord{v: pos.v + vertex.v});
            vertex_data.push(VertexCoord{v: pos.v + next_vertex.v});
            vertex_data.push(VertexCoord{v: pos.v});
        }
    }
    Mesh::new(zgl, vertex_data.as_slice())
}

pub struct Visualizer {
    zgl: Zgl,
    window: glutin::Window,
    should_close: bool,
    color_counter: i32, // TODO: remove
    test_color: Color4,
    shader: Shader,
    color_uniform_location: ColorId,
    mvp_uniform_location: MatId,
    camera: Camera,
    mouse_pos: ScreenPos,
    is_lmb_pressed: bool,
    win_size: Size2<ZInt>,
    mesh: Mesh,
}

impl Visualizer {
    pub fn new() -> Visualizer {
        let window_builder = glutin::WindowBuilder::new().with_gl_version((2, 0));
        let window = window_builder.build().ok().expect("Can`t create window");
        unsafe {
            window.make_current();
        };
        let win_size = get_win_size(&window);
        let mut zgl = Zgl::new(|s| window.get_proc_address(s));
        zgl.print_gl_info();
        let shader = Shader::new(&zgl, VS_SRC, FS_SRC);
        let color_uniform_location = shader.get_uniform_color(&zgl, "col");
        let mvp_uniform_location = shader.get_uniform_mat(&zgl, "mvp_mat");
        zgl.set_clear_color(Color3{r: 0.0, g: 0.0, b: 0.4});
        let mut camera = Camera::new(&win_size);
        let map_size = Size2{w: 5, h: 2};
        camera.set_max_pos(get_max_camera_pos(&map_size));
        let mesh = generate_mesh(&map_size, &zgl);
        Visualizer {
            zgl: zgl,
            window: window,
            should_close: false,
            color_counter: 0,
            test_color: Color4{r: 0.0, g: 0.0, b: 0.0, a: 0.0},
            shader: shader,
            color_uniform_location: color_uniform_location,
            mvp_uniform_location: mvp_uniform_location,
            camera: camera,
            mouse_pos: ScreenPos{v: Vector2::from_value(0)},
            is_lmb_pressed: false,
            win_size: win_size,
            mesh: mesh,
        }
    }

    pub fn is_running(&self) -> bool {
        !self.should_close
    }

    fn handle_event(&mut self, event: &glutin::Event) {
        match *event {
            glutin::Event::Closed => {
                self.should_close = true;
            },
            glutin::Event::Resized(w, h) => {
                self.win_size = Size2{w: w as ZInt, h: h as ZInt};
                self.zgl.set_viewport(&self.win_size);
            },
            glutin::Event::MouseMoved((x, y)) => {
                let new_pos = ScreenPos{v: Vector2{x: x as ZInt, y: y as ZInt}};
                if self.is_lmb_pressed {
                    let diff = new_pos.v - self.mouse_pos.v;
                    let win_w = self.win_size.w as ZFloat;
                    let win_h = self.win_size.h as ZFloat;
                    self.camera.add_z_angle(diff.x as ZFloat * (360.0 / win_w));
                    self.camera.add_x_angle(diff.y as ZFloat * (360.0 / win_h));
                }
                self.mouse_pos = new_pos;
            },
            glutin::Event::MouseInput(
                glutin::ElementState::Pressed,
                glutin::MouseButton::LeftMouseButton,
            ) => {
                self.is_lmb_pressed = true;
            },
            glutin::Event::MouseInput(
                glutin::ElementState::Released,
                glutin::MouseButton::LeftMouseButton,
            ) => {
                self.is_lmb_pressed = false;
                let (r, g, b, a) = self.zgl.read_pixel_bytes(
                    &self.win_size, &self.mouse_pos);
                println!("r: {}, g: {}, b: {}, a: {}", r, g, b, a);
            },
            glutin::Event::KeyboardInput(_, _, Some(key)) => match key {
                glutin::VirtualKeyCode::Q | glutin::VirtualKeyCode::Escape => {
                    self.should_close = true;
                },
                glutin::VirtualKeyCode::W => self.camera.move_camera(270.0, 0.1),
                glutin::VirtualKeyCode::S => self.camera.move_camera(90.0, 0.1),
                glutin::VirtualKeyCode::D => self.camera.move_camera(0.0, 0.1),
                glutin::VirtualKeyCode::A => self.camera.move_camera(180.0, 0.1),
                glutin::VirtualKeyCode::Minus => self.camera.change_zoom(1.3),
                glutin::VirtualKeyCode::Equals => self.camera.change_zoom(0.7),
                _ => {},
            },
            _ => {},
        }
    }

    fn handle_events(&mut self) {
        let events = self.window.poll_events().collect::<Vec<_>>();
        if events.is_empty() {
            return;
        }
        // println!("{}", events);
        for event in events.iter() {
            self.handle_event(event);
        }
    }

    fn update_test_color(&mut self) {
        self.test_color = match self.color_counter {
            0 => Color4{r: 1.0, g: 0.0, b: 0.0, a: 1.0},
            30 => Color4{r: 0.0, g: 1.0, b: 0.0, a: 1.0},
            60 => Color4{r: 0.0, g: 0.0, b: 1.0, a: 1.0},
            _ => self.test_color,
        };
        self.color_counter += 1;
        if self.color_counter > 90 {
            self.color_counter = -1;
        }
    }

    fn draw(&mut self) {
        self.zgl.clear_screen();
        self.shader.activate(&self.zgl);
        self.shader.set_uniform_color(
            &self.zgl, self.color_uniform_location, &self.test_color);
        self.shader.set_uniform_mat4f(
            &self.zgl, self.mvp_uniform_location, &self.camera.mat(&self.zgl));
        self.mesh.draw(&self.zgl);
        self.window.swap_buffers();
    }

    pub fn tick(&mut self) {
        self.handle_events();
        // self.logic();
        self.update_test_color();
        self.draw();
        // self.update_time();
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>


<commit_before>// Copyright (C) 2020 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

use crate::{api, Error, Result};
use async_std::{fs, io};
use slog_scope::{debug, error};
use std::{
    convert::{TryFrom, TryInto},
    path::Path,
};
use surf::{
    http::headers,
    middleware::{self, Middleware},
    StatusCode,
};

struct API;

#[surf::utils::async_trait]
impl Middleware for API {
    async fn handle(
        &self,
        mut req: middleware::Request,
        client: std::sync::Arc<dyn middleware::HttpClient>,
        next: middleware::Next<'_>,
    ) -> surf::Result<middleware::Response> {
        req.insert_header(headers::USER_AGENT, "updatehub/next");
        req.insert_header(headers::CONTENT_TYPE, "application/json");
        req.insert_header("api-content-type", "application/vnd.updatehub-v1+json");
        Ok(next.run(req, client).await?)
    }
}

pub struct Client<'a> {
    client: surf::Client,
    server: &'a str,
}

pub async fn get<W>(url: &str, handle: &mut W) -> Result<()>
where
    W: io::Write + Unpin,
{
    let req = surf::get(url);
    save_body_to(req, handle).await
}

async fn save_body_to<W>(req: surf::Request, handle: &mut W) -> Result<()>
where
    W: io::Write + Unpin,
{
    use async_std::prelude::StreamExt;
    use io::prelude::{ReadExt, WriteExt};
    use std::str::FromStr;

    let rep = req.await?;
    if !rep.status().is_success() {
        return Err(Error::InvalidStatusResponse(rep.status()));
    }

    let mut written: f32 = 0.;
    let mut threshold = 10;
    let length = match rep.header(headers::CONTENT_LENGTH) {
        Some(v) => usize::from_str(v.as_str())?,
        None => 0,
    };

    let mut stream = rep.bytes();
    while let Some(byte) = stream.next().await {
        let byte = byte?;
        handle.write_all(&[byte]).await?;
        if length > 0 {
            written += 100. / length as f32;
            if written as usize >= threshold {
                threshold += 20;
                debug!("{}% of the file has been downloaded", std::cmp::min(written as usize, 100));
            }
        }
    }
    debug!("100% of the file has been downloaded");

    Ok(())
}

impl<'a> Client<'a> {
    pub fn new(server: &'a str) -> Self {
        Self { server, client: surf::Client::new() }
    }

    pub async fn probe(
        &self,
        num_retries: u64,
        firmware: api::FirmwareMetadata<'_>,
    ) -> Result<api::ProbeResponse> {
        let mut response = self
            .client
            .post(&format!("{}/upgrades", &self.server))
            .middleware(API)
            .set_header("api-retries", num_retries.to_string())
            .body_json(&firmware)?
            .await?;

        match response.status() {
            StatusCode::NotFound => Ok(api::ProbeResponse::NoUpdate),
            StatusCode::Ok => {
                match response
                    .header("add-extra-poll")
                    .map(|extra_poll| extra_poll.as_str())
                    .and_then(|extra_poll| extra_poll.parse().ok())
                {
                    Some(extra_poll) => Ok(api::ProbeResponse::ExtraPoll(extra_poll)),
                    None => {
                        let signature =
                            response.header("UH-Signature").map(TryInto::try_into).transpose()?;
                        Ok(api::ProbeResponse::Update(
                            api::UpdatePackage::parse(&response.body_bytes().await?)?,
                            signature,
                        ))
                    }
                }
            }
            s => Err(Error::InvalidStatusResponse(s)),
        }
    }

    pub async fn download_object(
        &self,
        product_uid: &str,
        package_uid: &str,
        download_dir: &Path,
        object: &str,
    ) -> Result<()> {
        // FIXME: Discuss the need of packages inside the route
        let mut request = self
            .client
            .get(&format!(
                "{}/products/{}/packages/{}/objects/{}",
                &self.server, product_uid, package_uid, object
            ))
            .middleware(API);

        if !download_dir.exists() {
            fs::create_dir_all(download_dir).await.map_err(|e| {
                error!("fail to create {:?} directory, error: {}", download_dir, e);
                e
            })?;
        }

        let file = download_dir.join(object);
        if file.exists() {
            request = request.set_header(
                "RANGE",
                format!("bytes={}-", file.metadata()?.len().saturating_sub(1)),
            );
        }

        let mut file = fs::OpenOptions::new().create(true).append(true).open(&file).await?;

        save_body_to(request, &mut file).await
    }

    pub async fn report(
        &self,
        state: &str,
        firmware: api::FirmwareMetadata<'_>,
        package_uid: &str,
        previous_state: Option<&str>,
        error_message: Option<String>,
        current_log: Option<String>,
    ) -> Result<()> {
        #[derive(serde::Serialize)]
        #[serde(rename_all = "kebab-case")]
        struct Payload<'a> {
            #[serde(rename = "status")]
            state: &'a str,
            #[serde(flatten)]
            firmware: api::FirmwareMetadata<'a>,
            package_uid: &'a str,
            #[serde(skip_serializing_if = "Option::is_none")]
            previous_state: Option<&'a str>,
            #[serde(skip_serializing_if = "Option::is_none")]
            error_message: Option<String>,
            #[serde(skip_serializing_if = "Option::is_none")]
            current_log: Option<String>,
        }

        let payload =
            Payload { state, firmware, package_uid, previous_state, error_message, current_log };

        self.client
            .post(&format!("{}/report", &self.server))
            .middleware(API)
            .body_json(&payload)?
            .await?;
        Ok(())
    }
}

impl TryFrom<&headers::HeaderValues> for api::Signature {
    type Error = Error;

    fn try_from(value: &headers::HeaderValues) -> Result<Self> {
        let value = value.as_str();

        // Workarround for https://github.com/sfackler/rust-openssl/issues/1325
        if value.is_empty() {
            return Ok(Self::from_base64_str("")?);
        }

        Ok(Self::from_base64_str(value)?)
    }
}
<commit_msg>updatehub-clod-sdk: Improve object download speed<commit_after>// Copyright (C) 2020 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

use crate::{api, Error, Result};
use async_std::{fs, io};
use slog_scope::{debug, error};
use std::{
    convert::{TryFrom, TryInto},
    path::Path,
};
use surf::{
    http::headers,
    middleware::{self, Middleware},
    StatusCode,
};

struct API;

#[surf::utils::async_trait]
impl Middleware for API {
    async fn handle(
        &self,
        mut req: middleware::Request,
        client: std::sync::Arc<dyn middleware::HttpClient>,
        next: middleware::Next<'_>,
    ) -> surf::Result<middleware::Response> {
        req.insert_header(headers::USER_AGENT, "updatehub/next");
        req.insert_header(headers::CONTENT_TYPE, "application/json");
        req.insert_header("api-content-type", "application/vnd.updatehub-v1+json");
        Ok(next.run(req, client).await?)
    }
}

pub struct Client<'a> {
    client: surf::Client,
    server: &'a str,
}

pub async fn get<W>(url: &str, handle: &mut W) -> Result<()>
where
    W: io::Write + Unpin,
{
    let req = surf::get(url);
    save_body_to(req, handle).await
}

async fn save_body_to<W>(req: surf::Request, handle: &mut W) -> Result<()>
where
    W: io::Write + Unpin,
{
    use io::prelude::{ReadExt, WriteExt};
    use std::str::FromStr;

    let mut rep = req.await?;
    if !rep.status().is_success() {
        return Err(Error::InvalidStatusResponse(rep.status()));
    }

    let mut written: f32 = 0.;
    let mut threshold = 10;
    let length = match rep.header(headers::CONTENT_LENGTH) {
        Some(v) => usize::from_str(v.as_str())?,
        None => 0,
    };

    loop {
        let mut buf = [0; 4096];
        let read = rep.read(&mut buf).await?;
        if read == 0 {
            break;
        }
        handle.write_all(&buf[..read]).await?;
        if length > 0 {
            written += read as f32 / (length as f32 / 100.);
            if written as usize >= threshold {
                threshold += 20;
                debug!("{}% of the file has been downloaded", std::cmp::min(written as usize, 100));
            }
        }
    }
    debug!("100% of the file has been downloaded");

    Ok(())
}

impl<'a> Client<'a> {
    pub fn new(server: &'a str) -> Self {
        Self { server, client: surf::Client::new() }
    }

    pub async fn probe(
        &self,
        num_retries: u64,
        firmware: api::FirmwareMetadata<'_>,
    ) -> Result<api::ProbeResponse> {
        let mut response = self
            .client
            .post(&format!("{}/upgrades", &self.server))
            .middleware(API)
            .set_header("api-retries", num_retries.to_string())
            .body_json(&firmware)?
            .await?;

        match response.status() {
            StatusCode::NotFound => Ok(api::ProbeResponse::NoUpdate),
            StatusCode::Ok => {
                match response
                    .header("add-extra-poll")
                    .map(|extra_poll| extra_poll.as_str())
                    .and_then(|extra_poll| extra_poll.parse().ok())
                {
                    Some(extra_poll) => Ok(api::ProbeResponse::ExtraPoll(extra_poll)),
                    None => {
                        let signature =
                            response.header("UH-Signature").map(TryInto::try_into).transpose()?;
                        Ok(api::ProbeResponse::Update(
                            api::UpdatePackage::parse(&response.body_bytes().await?)?,
                            signature,
                        ))
                    }
                }
            }
            s => Err(Error::InvalidStatusResponse(s)),
        }
    }

    pub async fn download_object(
        &self,
        product_uid: &str,
        package_uid: &str,
        download_dir: &Path,
        object: &str,
    ) -> Result<()> {
        // FIXME: Discuss the need of packages inside the route
        let mut request = self
            .client
            .get(&format!(
                "{}/products/{}/packages/{}/objects/{}",
                &self.server, product_uid, package_uid, object
            ))
            .middleware(API);

        if !download_dir.exists() {
            fs::create_dir_all(download_dir).await.map_err(|e| {
                error!("fail to create {:?} directory, error: {}", download_dir, e);
                e
            })?;
        }

        let file = download_dir.join(object);
        if file.exists() {
            request = request.set_header(
                "RANGE",
                format!("bytes={}-", file.metadata()?.len().saturating_sub(1)),
            );
        }

        let mut file = fs::OpenOptions::new().create(true).append(true).open(&file).await?;

        save_body_to(request, &mut file).await
    }

    pub async fn report(
        &self,
        state: &str,
        firmware: api::FirmwareMetadata<'_>,
        package_uid: &str,
        previous_state: Option<&str>,
        error_message: Option<String>,
        current_log: Option<String>,
    ) -> Result<()> {
        #[derive(serde::Serialize)]
        #[serde(rename_all = "kebab-case")]
        struct Payload<'a> {
            #[serde(rename = "status")]
            state: &'a str,
            #[serde(flatten)]
            firmware: api::FirmwareMetadata<'a>,
            package_uid: &'a str,
            #[serde(skip_serializing_if = "Option::is_none")]
            previous_state: Option<&'a str>,
            #[serde(skip_serializing_if = "Option::is_none")]
            error_message: Option<String>,
            #[serde(skip_serializing_if = "Option::is_none")]
            current_log: Option<String>,
        }

        let payload =
            Payload { state, firmware, package_uid, previous_state, error_message, current_log };

        self.client
            .post(&format!("{}/report", &self.server))
            .middleware(API)
            .body_json(&payload)?
            .await?;
        Ok(())
    }
}

impl TryFrom<&headers::HeaderValues> for api::Signature {
    type Error = Error;

    fn try_from(value: &headers::HeaderValues) -> Result<Self> {
        let value = value.as_str();

        // Workarround for https://github.com/sfackler/rust-openssl/issues/1325
        if value.is_empty() {
            return Ok(Self::from_base64_str("")?);
        }

        Ok(Self::from_base64_str(value)?)
    }
}
<|endoftext|>