<commit_before>// pub mod io;
// pub mod math;
// pub mod render;
// pub mod texture;
// pub mod ui;

// fn main() {
//     let v1 = math::vector::Vec3 {
//         x: 2.0f64,
//         y: 3.0f64,
//         z: 4.0f64,
//     };
//     let v2 = math::vector::Vec3 {
//         x: -3.0f64,
//         y: -1.0f64,
//         z:  1.0f64
//     };
//     let mut v3 = math::vector::Vec3 {
//         x: 0.0,
//         y: 0.0,
//         z: 0.0,
//     };
//     let sc1 = 45.0f64;
//     let ry1 = math::ray::Ray3 {
//         o:    v1.clone(),
//         d:    v2.clone(),
//         invd: v3.clone()
//     };
//     // println!("{:?}", ((v1 + v2) * 3.9).dot(v2));
//     v3 += v1 + v2;

//     println!("{:?}", v3 * sc1);
//     println!("{:?}", v3);
//     println!("{:?}", sc1);
//     println!("{:?}", v3.dot(&v1));
//     println!("{:?}", v1);
//     println!("{:?}", v3);
//     println!("{:?}", ry1);

//     let mut file = io::file::Stream::new(&("/home/thany/Temporary/1.gx3d".to_string()));

//     let mut textures_manager = texture::textures_manager::TexturesManager::new();
//     let mut scenes_manager = render::scenes_manager::ScenesManager::new();
//     textures_manager.read_table(&mut file);
//     scenes_manager.read_table(&mut file);
//     let mut scene = scenes_manager.get_scene(&"Scene".to_string(), &mut file);

//     let ui_manager = match ui::UiManager::new() {
//         Some(u) => u,
//         None    => return,
//     };
//     ui_manager.run();
// }
//! This example behaves the same as the `all_winit_glium` example while demonstrating how to run
//! the `conrod` loop on a separate thread.

#[macro_use]
extern crate conrod;
extern crate glium;
extern crate winit;
mod support {
    //! This module is used for sharing a few items between the `all_widgets.rs`, `glutin_glium.rs`
    //! and glutin_gfx.rs` examples.
    //!
    //! The module contains:
    //!
    //! - `pub struct DemoApp` as a demonstration of some state we want to change.
    //! - `pub fn gui` as a demonstration of all widgets, some of which mutate our `DemoApp`.
    //! - `pub struct Ids` - a set of all `widget::Id`s used in the `gui` fn.
    //!
    //! By sharing these items between these examples, we can test and ensure that the different
    //! events and drawing backends behave in the same manner.

    extern crate rand;

    use std;

    use conrod::backend::glium::glium;

    /// In most of the examples the `glutin` crate is used for providing the window context and
    /// events while the `glium` crate is used for displaying `conrod::render::Primitives` to the
    /// screen.
    ///
    /// This `Iterator`-like type simplifies some of the boilerplate involved in setting up a
    /// glutin+glium event loop that works efficiently with conrod.

    pub struct EventLoop {
        ui_needs_update: bool,
        last_update: std::time::Instant,
    }

    impl EventLoop {
        pub fn new() -> Self {
            EventLoop {
                last_update: std::time::Instant::now(),
                ui_needs_update: true,
            }
        }

        /// Produce an iterator yielding all available events.
        pub fn next(
            &mut self,
            events_loop: &mut glium::glutin::EventsLoop,
        ) -> Vec<glium::glutin::Event> {
            // We don't want to loop any faster than 60 FPS, so wait until it has been at least 16ms
            // since the last yield.
            let last_update = self.last_update;
            let sixteen_ms = std::time::Duration::from_millis(16);
            let duration_since_last_update = std::time::Instant::now().duration_since(last_update);
            if duration_since_last_update < sixteen_ms {
                std::thread::sleep(sixteen_ms - duration_since_last_update);
            }

            // Collect all pending events.
            let mut events = Vec::new();
            events_loop.poll_events(|event| events.push(event));

            // If there are no events and the `Ui` does not need updating, wait for the next event.
            if events.is_empty() && !self.ui_needs_update {
                events_loop.run_forever(|event| {
                    events.push(event);
                    glium::glutin::ControlFlow::Break
                });
            }

            self.ui_needs_update = false;
            self.last_update = std::time::Instant::now();

            events
        }
    }

}

extern crate find_folder;
extern crate image;
use conrod::{color, widget, Colorable, Positionable, Sizeable, Widget};
use conrod::backend::glium::glium::Surface;

pub fn main() {
    const WIDTH: u32 = 800;
    const HEIGHT: u32 = 600;

    // Build the window.
    let mut events_loop = glium::glutin::EventsLoop::new();
    let window = glium::glutin::WindowBuilder::new()
        .with_title("Image Widget Demonstration")
        .with_dimensions(WIDTH, HEIGHT);
    let context = glium::glutin::ContextBuilder::new()
        .with_vsync(true)
        .with_multisampling(4);
    let display = glium::Display::new(window, context, &events_loop).unwrap();

    // construct our `Ui`.
    let mut ui = conrod::UiBuilder::new([WIDTH as f64, HEIGHT as f64]).build();

    // A type used for converting `conrod::render::Primitives` into `Command`s that can be used
    // for drawing to the glium `Surface`.
    let mut renderer = conrod::backend::glium::Renderer::new(&display).unwrap();

    // The `WidgetId` for our background and `Image` widgets.
    widget_ids!(struct Ids { background, rust_logo });
    let ids = Ids::new(ui.widget_id_generator());

    // Create our `conrod::image::Map` which describes each of our widget->image mappings.
    // In our case we only have one image, however the macro may be used to list multiple.
    let rust_logo = load_rust_logo(&display);
    let (w, h) = (rust_logo.get_width(), rust_logo.get_height().unwrap());
    let mut image_map = conrod::image::Map::new();
    let rust_logo = image_map.insert(rust_logo);

    // Poll events from the window.
    let mut event_loop = support::EventLoop::new();
    'main: loop {
        // Handle all events.
        for event in event_loop.next(&mut events_loop) {
            // Use the `winit` backend feature to convert the winit event to a conrod one.
            if let Some(event) = conrod::backend::winit::convert_event(event.clone(), &display) {
                ui.handle_event(event);
            }

            match event {
                glium::glutin::Event::WindowEvent { event, .. } => match event {
                    // Break from the loop upon `Escape`.
                    glium::glutin::WindowEvent::Closed
                    | glium::glutin::WindowEvent::KeyboardInput {
                        input:
                            glium::glutin::KeyboardInput {
                                virtual_keycode: Some(glium::glutin::VirtualKeyCode::Escape),
                                ..
                            },
                        ..
                    } => break 'main,
                    _ => (),
                },
                _ => (),
            }
        }

        // Instantiate the widgets.
        {
            let ui = &mut ui.set_widgets();
            // Draw a light blue background.
            widget::Canvas::new()
                .color(color::DARK_CHARCOAL)
                .set(ids.background, ui);
            // Instantiate the `Image` at its full size in the middle of the window.
            widget::Image::new(rust_logo)
                .w_h(w as f64, h as f64)
                .middle()
                .set(ids.rust_logo, ui);
        }

        // Render the `Ui` and then display it on the screen.
        if let Some(primitives) = ui.draw_if_changed() {
            renderer.fill(&display, primitives, &image_map);
            let mut target = display.draw();
            target.clear_color(0.0, 0.0, 0.0, 1.0);
            renderer.draw(&display, &mut target, &image_map).unwrap();
            target.finish().unwrap();
        }
    }
}

fn load_rust_logo(display: &glium::Display) -> glium::texture::Texture2d {
    let image_dimensions = (128, 128);
    let mut image_data = [255u8; 128 * 128 * 4];
    for i in 0..128 {
        for j in 0..128 {
            if i > j {
                image_data[(i * 128 + j) * 4 + 2] = 0;
                image_data[(i * 128 + j) * 4 + 1] = 0;
            } else {
                image_data[(i * 128 + j) * 4] = 0;
                image_data[(i * 128 + j) * 4 + 1] = 0;
            }
        }
    }
    let raw_image =
        glium::texture::RawImage2d::from_raw_rgba_reversed(&image_data, image_dimensions);
    let texture = glium::texture::Texture2d::new(display, raw_image).unwrap();
    texture
}
<commit_msg>for cleaning code, some changes done<commit_after>#[macro_use]
extern crate conrod;
extern crate rand;
extern crate winit;
use conrod::backend::glium::glium;

pub struct EventLoop {
    ui_needs_update: bool,
    last_update: std::time::Instant,
}
impl EventLoop {
    pub fn new() -> Self {
        EventLoop {
            last_update: std::time::Instant::now(),
            ui_needs_update: true,
        }
    }

    /// Produce an iterator yielding all available events.
    pub fn next(
        &mut self,
        events_loop: &mut glium::glutin::EventsLoop,
    ) -> Vec<glium::glutin::Event> {
        // We don't want to loop any faster than 60 FPS, so wait until it has been at least 16ms
        // since the last yield.
        let last_update = self.last_update;
        let sixteen_ms = std::time::Duration::from_millis(16);
        let duration_since_last_update = std::time::Instant::now().duration_since(last_update);
        if duration_since_last_update < sixteen_ms {
            std::thread::sleep(sixteen_ms - duration_since_last_update);
        }

        // Collect all pending events.
        let mut events = Vec::new();
        events_loop.poll_events(|event| events.push(event));

        // If there are no events and the `Ui` does not need updating, wait for the next event.
        if events.is_empty() && !self.ui_needs_update {
            events_loop.run_forever(|event| {
                events.push(event);
                glium::glutin::ControlFlow::Break
            });
        }

        self.ui_needs_update = false;
        self.last_update = std::time::Instant::now();

        events
    }
}

extern crate find_folder;
extern crate image;
use conrod::{color, widget, Colorable, Positionable, Sizeable, Widget};
use conrod::backend::glium::glium::Surface;

pub fn main() {
    const WIDTH: u32 = 800;
    const HEIGHT: u32 = 600;

    // Build the window.
    let mut events_loop = glium::glutin::EventsLoop::new();
    let window = glium::glutin::WindowBuilder::new()
        .with_title("Image Widget Demonstration")
        .with_dimensions(WIDTH, HEIGHT);
    let context = glium::glutin::ContextBuilder::new()
        .with_vsync(true)
        .with_multisampling(4);
    let display = glium::Display::new(window, context, &events_loop).unwrap();

    // construct our `Ui`.
    let mut ui = conrod::UiBuilder::new([WIDTH as f64, HEIGHT as f64]).build();

    // A type used for converting `conrod::render::Primitives` into `Command`s that can be used
    // for drawing to the glium `Surface`.
    let mut renderer = conrod::backend::glium::Renderer::new(&display).unwrap();

    // The `WidgetId` for our background and `Image` widgets.
    widget_ids!(struct Ids { background, rust_logo });
    let ids = Ids::new(ui.widget_id_generator());

    // Create our `conrod::image::Map` which describes each of our widget->image mappings.
    // In our case we only have one image, however the macro may be used to list multiple.
    let rust_logo = load_rust_logo(&display);
    let (w, h) = (rust_logo.get_width(), rust_logo.get_height().unwrap());
    let mut image_map = conrod::image::Map::new();
    let rust_logo = image_map.insert(rust_logo);

    // Poll events from the window.
    let mut event_loop = EventLoop::new();
    'main: loop {
        // Handle all events.
        for event in event_loop.next(&mut events_loop) {
            // Use the `winit` backend feature to convert the winit event to a conrod one.
            if let Some(event) = conrod::backend::winit::convert_event(event.clone(), &display) {
                ui.handle_event(event);
            }

            match event {
                glium::glutin::Event::WindowEvent { event, .. } => match event {
                    // Break from the loop upon `Escape`.
                    glium::glutin::WindowEvent::Closed
                    | glium::glutin::WindowEvent::KeyboardInput {
                        input:
                            glium::glutin::KeyboardInput {
                                virtual_keycode: Some(glium::glutin::VirtualKeyCode::Escape),
                                ..
                            },
                        ..
                    } => break 'main,
                    _ => (),
                },
                _ => (),
            }
        }

        // Instantiate the widgets.
        {
            let ui = &mut ui.set_widgets();
            // Draw a light blue background.
            widget::Canvas::new()
                .color(color::DARK_CHARCOAL)
                .set(ids.background, ui);
            // Instantiate the `Image` at its full size in the middle of the window.
            widget::Image::new(rust_logo)
                .w_h(w as f64, h as f64)
                .middle()
                .set(ids.rust_logo, ui);
        }

        // Render the `Ui` and then display it on the screen.
        if let Some(primitives) = ui.draw_if_changed() {
            renderer.fill(&display, primitives, &image_map);
            let mut target = display.draw();
            target.clear_color(0.0, 0.0, 0.0, 1.0);
            renderer.draw(&display, &mut target, &image_map).unwrap();
            target.finish().unwrap();
        }
    }
}

fn load_rust_logo(display: &glium::Display) -> glium::texture::Texture2d {
    let image_dimensions = (128, 128);
    let mut image_data = [255u8; 128 * 128 * 4];
    for i in 0..128 {
        for j in 0..128 {
            if i > j {
                image_data[(i * 128 + j) * 4 + 2] = 0;
                image_data[(i * 128 + j) * 4 + 1] = 0;
            } else {
                image_data[(i * 128 + j) * 4] = 0;
                image_data[(i * 128 + j) * 4 + 1] = 0;
            }
        }
    }
    let raw_image =
        glium::texture::RawImage2d::from_raw_rgba_reversed(&image_data, image_dimensions);
    let texture = glium::texture::Texture2d::new(display, raw_image).unwrap();
    texture
}
<|endoftext|>


<commit_before>//#![feature(convert)]

#[macro_use] extern crate nickel;
extern crate rustc_serialize;
extern crate hyper;
extern crate nickel_postgres;
extern crate postgres;
extern crate r2d2_postgres;
extern crate r2d2;

use nickel::{Nickel, HttpRouter, QueryString};
use nickel::extensions::Redirect;
use rustc_serialize::json;
use hyper::Client;
use hyper::header::Connection;
use std::io::Read;
use std::env;
use r2d2::{NopErrorHandler, PooledConnection};
use r2d2_postgres::{SslMode, PostgresConnectionManager};
use nickel_postgres::{PostgresMiddleware, PostgresRequestExtensions};

#[derive(RustcDecodable, RustcEncodable, Debug)]
struct Data {
    data: User,
}

#[derive(RustcDecodable, RustcEncodable, Debug)]
struct User {
    id: i32,
    email: String,
    created_at: String,
    updated_at: String,
    first_name: String,
    last_name: String,
    graduation: String,
    major: String,
    shirt_size: String,
    dietary_restrictions: String,
    special_needs: Option<String>,
    date_of_birth: String,
    gender: String,
    phone_number: String,
    school: School,
}

#[derive(RustcDecodable, RustcEncodable, Debug)]
struct School {
    id: i32,
    name: String,
}

#[derive(RustcDecodable, RustcEncodable, Debug)]
struct TokenResp {
    access_token: String,
    token_type: String,
    scope: String,
    created_at: u64,
}

#[derive(RustcDecodable, RustcEncodable, Debug)]
struct Payload {
    channel: String,
    username: String,
    text: String,
    icon_emoji: String,
}

macro_rules! optry {
    ( $x:expr ) => {
        match $x {
            Some(v) => v,
            None => return None,
        }
    }
}

macro_rules! env_err {
    ( $var:expr, $error:expr ) => {
        env::var($var).expect($error)
    };
    ( $var:expr ) => {
        env_err!($var, &format!("Failed to get env var {}", $var))
    }
}

fn do_request(code: &str) -> Option<Data> {
    let id = env_err!("ID");
    let secret = env_err!("SECRET");
    let redirect = env_err!("REDIRECT");

    let url = format!("https://my.mlh.io/oauth/token?client_id={}&client_secret={}&code={}&redirect_uri={}&grant_type=authorization_code",
                      id, secret, code, redirect);

    let client = Client::new();
    let mut res = optry!(client.post(&url)
        .header(Connection::close())
        .send().ok());

    let mut body = String::new();
    optry!(res.read_to_string(&mut body).ok());

    let token: TokenResp = optry!(json::decode(&body).ok());
    let url2 = format!("https://my.mlh.io/api/v1/user?access_token={}",
                       token.access_token);

    res = optry!(client.get(&url2)
        .header(Connection::close())
        .send().ok());
    body = String::new();
    optry!(res.read_to_string(&mut body).ok());

    let person_data: Data = optry!(json::decode(&body).ok());

    let payload = Payload {
        channel: "#hackcwru".to_string(),
        username: "Signup bot".to_string(),
        icon_emoji: ":hackcwru:".to_string(),
        text: format!("{} from {} has signed up!",
                      person_data.data.first_name,
                      person_data.data.school.name),
    };

    let payload_str = json::encode(&payload).unwrap();

    let slackurl = env_err!("SLACKURL");

    let _res = optry!(client.post(&slackurl)
                 .body(&payload_str)
                 .send().ok());

    Some(person_data)
}

fn slack_send(user: User) {
//    let url = env
}

fn create_table(conn: PooledConnection<PostgresConnectionManager>) {
    let _r = conn.execute(
            "CREATE TABLE IF NOT EXISTS person (
                id SERIAL PRIMARY KEY,
                email VARCHAR NOT NULL,
                created_at VARCHAR NOT NULL,
                updated_at VARCHAR NOT NULL,
                first_name VARCHAR NOT NULL,
                last_name VARCHAR NOT NULL,
                graduation VARCHAR NOT NULL,
                major VARCHAR NOT NULL,
                shirt_size VARCHAR NOT NULL,
                dietary_restrictions VARCHAR NOT NULL,
                special_needs VARCHAR,
                date_of_birth VARCHAR NOT NULL,
                gender VARCHAR NOT NULL,
                phone_number VARCHAR NOT NULL,
                school_id integer,
                school_name VARCHAR
                )",
            &[]
        );
}

fn main() {
    let mut app = Nickel::new();

    let postgres_url = env_err!("DATABASE");
    let dbpool = PostgresMiddleware::new(&*postgres_url, SslMode::None, 5,
                                         Box::new(NopErrorHandler))
        .expect("Failed to start PostgresMiddleware");

    create_table(dbpool.pool.clone().get().unwrap());
    app.utilize(dbpool);

    app.get("/callback", middleware! { |request, response|
        let conn = request.db_conn();
        let user_data = match request.query().get("code") {
            Some(s) => do_request(s),
            None => None
        }.unwrap().data;

        let r = conn.execute(
                "INSERT INTO person (id, email, created_at, updated_at,
                first_name, last_name, graduation, major, shirt_size,
                dietary_restrictions, special_needs, date_of_birth, gender,
                phone_number, school_id, school_name) VALUES ($1, $2, $3, $4,
                $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)",
                &[&user_data.id, &user_data.email, &user_data.created_at,
                  &user_data.updated_at, &user_data.first_name,
                  &user_data.last_name, &user_data.graduation, &user_data.major,
                  &user_data.shirt_size, &user_data.dietary_restrictions,
                  &user_data.special_needs, &user_data.date_of_birth,
                  &user_data.gender, &user_data.phone_number,
                  &user_data.school.id, &user_data.school.name]
            );
        match r {
            Ok(v) => println!("{:?}", v),
            Err(e) => println!("{:?}", e)
        }

        return response.redirect("http://hack.cwru.edu/register.html")
    });

    app.get("/start", middleware! { |_req, response|
        let id = env_err!("ID");
        let redirect = env_err!("REDIRECT");
        return response.redirect(
            format!(
                    "http://my.mlh.io/oauth/authorize?client_id={}&redirect_uri={}&response_type=code",
                    id, redirect
                )
            );
    });

    let bind = match env::var("BIND") {
        Ok(v) => v,
        Err(_) => "127.0.0.1:8080".to_string(),
    };

    app.listen(&bind[..]);
}
<commit_msg>Better error handling<commit_after>//#![feature(convert)]

#[macro_use] extern crate nickel;
extern crate rustc_serialize;
extern crate hyper;
extern crate nickel_postgres;
extern crate postgres;
extern crate r2d2_postgres;
extern crate r2d2;

use nickel::{Nickel, HttpRouter, QueryString};
use nickel::extensions::Redirect;
use nickel::status::StatusCode;
use rustc_serialize::json;
use hyper::Client;
use hyper::header::Connection;
use hyper::status::StatusClass;
use hyper::client::response::Response;
use std::io::Read;
use std::env;
use r2d2::{NopErrorHandler, PooledConnection};
use r2d2_postgres::{SslMode, PostgresConnectionManager};
use nickel_postgres::{PostgresMiddleware, PostgresRequestExtensions};

#[derive(RustcDecodable, Debug)]
struct Data {
    data: User,
}

#[derive(RustcDecodable, Debug)]
struct User {
    id: i32,
    email: String,
    created_at: String,
    updated_at: String,
    first_name: String,
    last_name: String,
    graduation: String,
    major: String,
    shirt_size: String,
    dietary_restrictions: String,
    special_needs: Option<String>,
    date_of_birth: String,
    gender: String,
    phone_number: String,
    school: School,
}

#[derive(RustcDecodable, Debug)]
struct School {
    id: i32,
    name: String,
}

#[derive(RustcDecodable, Debug)]
struct TokenResp {
    access_token: String,
    token_type: String,
    scope: String,
    created_at: u64,
}

#[derive(RustcEncodable, Debug)]
struct Payload {
    channel: String,
    username: String,
    text: String,
    icon_emoji: String,
}

#[derive(Debug)]
enum ApiError {
    ClientError,
    ServerError,
}

#[derive(Debug)]
enum RequestError {
    Hyper(hyper::error::Error),
    Io(std::io::Error),
    JsonEnc(rustc_serialize::json::EncoderError),
    JsonDec(rustc_serialize::json::DecoderError),
    Api(ApiError),
}

macro_rules! env_err {
    ( $var:expr, $error:expr ) => {
        env::var($var).expect($error)
    };
    ( $var:expr ) => {
        env_err!($var, &format!("Failed to get env var {}", $var))
    }
}

macro_rules! impl_from {
    ( $from_t:path, $to_t:path, $enum_t:path ) => {
        impl From<$from_t> for $enum_t {
            fn from(err: $from_t) -> $enum_t {
                $to_t(err)
            }
        }
    }
}

impl_from!(hyper::error::Error, RequestError::Hyper, RequestError);
impl_from!(std::io::Error, RequestError::Io, RequestError);
impl_from!(rustc_serialize::json::DecoderError, RequestError::JsonDec,
           RequestError);
impl_from!(rustc_serialize::json::EncoderError, RequestError::JsonEnc,
           RequestError);
impl_from!(ApiError, RequestError::Api, RequestError);

fn check_http_error(res: &Response) -> Result<(), ApiError> {
    match res.status.class() {
        StatusClass::ClientError => Err(ApiError::ClientError),
        StatusClass::ServerError => Err(ApiError::ServerError),
        _ => Ok(())
    }
}

fn do_request(code: &str) -> Result<Data, RequestError> {
    let id = env_err!("ID");
    let secret = env_err!("SECRET");
    let redirect = env_err!("REDIRECT");

    let url = format!("https://my.mlh.io/oauth/token?client_id={}&client_secret={}&code={}&redirect_uri={}&grant_type=authorization_code",
                      id, secret, code, redirect);

    let client = Client::new();
    let mut res = try!(client.post(&url)
        .header(Connection::close())
        .send());

    try!(check_http_error(&res));

    let mut body = String::new();
    try!(res.read_to_string(&mut body));

    let token: TokenResp = try!(json::decode(&body));
    let url2 = format!("https://my.mlh.io/api/v1/user?access_token={}",
                       token.access_token);

    res = try!(client.get(&url2)
        .header(Connection::close())
        .send());

    try!(check_http_error(&res));

    body = String::new();
    try!(res.read_to_string(&mut body));

    let person_data: Data = try!(json::decode(&body));

    Ok(person_data)
}

fn slack_send(user: User) -> Result<(), RequestError> {
    let url = env_err!("SLACKURL");
    let client = Client::new();
    let payload = Payload {
        channel: "#hackcwru".to_string(),
        username: "Signup bot".to_string(),
        icon_emoji: ":hackcwru:".to_string(),
        text: format!("{} from {} has signed up!",
                      user.first_name,
                      user.school.name),
    };
    let payload_str = try!(json::encode(&payload));
    let res = try!(client.post(&url)
        .body(&payload_str)
        .send());

    try!(check_http_error(&res));

    Ok(())
}

fn create_table(conn: PooledConnection<PostgresConnectionManager>) {
    let _r = conn.execute(
            "CREATE TABLE IF NOT EXISTS person (
                id SERIAL PRIMARY KEY,
                email VARCHAR NOT NULL,
                created_at VARCHAR NOT NULL,
                updated_at VARCHAR NOT NULL,
                first_name VARCHAR NOT NULL,
                last_name VARCHAR NOT NULL,
                graduation VARCHAR NOT NULL,
                major VARCHAR NOT NULL,
                shirt_size VARCHAR NOT NULL,
                dietary_restrictions VARCHAR NOT NULL,
                special_needs VARCHAR,
                date_of_birth VARCHAR NOT NULL,
                gender VARCHAR NOT NULL,
                phone_number VARCHAR NOT NULL,
                school_id integer,
                school_name VARCHAR
                )",
            &[]
        );
}

fn main() {
    let mut app = Nickel::new();

    let postgres_url = env_err!("DATABASE");
    let dbpool = PostgresMiddleware::new(&*postgres_url, SslMode::None, 5,
                                         Box::new(NopErrorHandler))
        .expect("Failed to start PostgresMiddleware");

    create_table(dbpool.pool.clone().get().unwrap());
    app.utilize(dbpool);

    app.get("/callback", middleware! { |request, mut response|
        let conn = request.db_conn();
        let code = match request.query().get("code") {
            Some(s) => s,
            None => {
                println!("No code, quitting");
                return response.error(StatusCode::BadRequest, "Failed");
            }
        };
        let user_data = match do_request(code) {
            Ok(s) => s,
            Err(e) => {
                println!("Get user data failed with error: {:?}", e);
                return response
                    .error(StatusCode::InternalServerError, "Failed");
            }
        }.data;

        let r = conn.execute(
                "INSERT INTO person (id, email, created_at, updated_at,
                first_name, last_name, graduation, major, shirt_size,
                dietary_restrictions, special_needs, date_of_birth, gender,
                phone_number, school_id, school_name) VALUES ($1, $2, $3, $4,
                $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)",
                &[&user_data.id, &user_data.email, &user_data.created_at,
                  &user_data.updated_at, &user_data.first_name,
                  &user_data.last_name, &user_data.graduation, &user_data.major,
                  &user_data.shirt_size, &user_data.dietary_restrictions,
                  &user_data.special_needs, &user_data.date_of_birth,
                  &user_data.gender, &user_data.phone_number,
                  &user_data.school.id, &user_data.school.name]
            );
        match r {
            Ok(v) => {
                println!("Add to database succeeded with status {:?}", v);
                match slack_send(user_data) {
                    Ok(_) => println!("Slack send worked"),
                    Err(e) => println!("Slack send failed with error: {:?}", e)
                };
            },
            Err(e) => println!("Add to database failed: {:?}", e)
        }

        return response.redirect("http://hack.cwru.edu/register.html")
    });

    app.get("/start", middleware! { |_req, response|
        let id = env_err!("ID");
        let redirect = env_err!("REDIRECT");
        return response.redirect(
            format!(
                    "http://my.mlh.io/oauth/authorize?client_id={}&redirect_uri={}&response_type=code",
                    id, redirect
                )
            );
    });

    let bind = match env::var("BIND") {
        Ok(v) => v,
        Err(_) => "127.0.0.1:8080".to_string(),
    };

    app.listen(&bind[..]);
}
<|endoftext|>


<commit_before>
use std::int;
use std::num;

static phi: f64 = 0.77351f64;
static kappa: f64 = 1.75f64;

///
/// Implements the Probabilistic Counting with Stochastic Averaging
/// counter.  PCSA provides an approximate estimate of cardinality with
/// bounded error.
///
/// Relative error is 0.78 / sqrt(m)
///
/// See this [article](http://blog.aggregateknowledge.com/2013/04/02/sketch-of-the-day-probabilistic-counting-with-stochastic-averaging-pcsa/) for a layman's explanation of PCSA
///
/// Original paper can be found [here](http://www.mathcs.emory.edu/~cheung/papers/StreamDB/Probab/1985-Flajolet-Probabilistic-counting.pdf)
///
pub struct PCSA {
    m: u32,
    b: u32,
    buckets: Vec<u32>,
    indexMask: u64
}

impl PCSA {

    /// Construct a new PCSA counter
    ///
    /// b: number of bits to use as bucket index mask, larger
    ///    values means more buckets, better accuracy, more space
    ///    b must be between 4..16 inclusive
    ///
    ///    m = 2^b
    ///
    /// Complete PCSA Memory chart for reference (including per-object overhead, minus static overheads):
    ///
    ///

Precision	Size	Error on 1m Cardinality Test	Worst Case Estimate Error (+/-)
    ///
4	80 bytes	 0.09%	 39.00%

    ///
5	144 bytes	 4.14%	 34.88%

    ///
6	272 bytes	 1.18%	 31.84%

    ///
7	528 bytes	 3.62%	 29.48%

    ///
8	1040 bytes	 0.71%	 27.57%

    ///
9	2064 bytes	 1.51%	 26.00%

    ///
10	4112 bytes	 0.77%	 24.66%

    ///
11	8208 bytes	 1.15%	 23.51%

    ///
12	16400 bytes	 1.10%	 22.51%

    ///
13	32784 bytes	 0.96%	 21.63%

    ///
14	65552 bytes	 0.20%	 20.84%

    ///
15	131088 bytes	 0.18%	 20.13%

    ///

    ///
    /// ### Usage
    ///
    ///```
    ///let mut pcsa = PCSA::new(10);
    ///```
    #[experimental]
    pub fn new(b: u32) -> PCSA {

        let m: u32;

        match b {
            4..16 => {  m = num::pow(2, b as uint) },
            _ => fail!("b must be 4 <= b <= 16")
        }

        let mut buckets: Vec<u32> = Vec::from_elem(m as uint, 0u32);
        let indexMask: u64 = ((1u << b as uint) - 1) as u64;

        PCSA {m: m, b: b, buckets: buckets, indexMask: indexMask}
    }

    /// Offer a hashed u64 value to the PCSA algorithm.  If this is a new, distinct value, the PCSA algo will update it's
    /// internal buckets.
    ///
    ///### Usage
    ///
    ///```
    /// let mut pcsa = PCSA::new(10);
    ///
    /// // Hash the value with std::hash SipHash 2-4. Any 64-bit hash will work
    /// // You should probably use something *other* than SipHash, since it is cryptographic
    /// // and slow
    /// let hash: u64 = hash::hash(&19u);
    /// pcsa.offer_hashed(hash);
    ///
    ///```
    #[experimental]
    pub fn offer_hashed(&mut self, hash: &u64) {
        let index: u32 = (hash & self.indexMask) as u32;
        *self.buckets.get_mut(index as uint) |= 1 << (hash >> self.b as uint).trailing_zeros() as uint;
    }

    /// Returns the current cardinality estimate
    #[experimental]
    pub fn cardinality(&self) -> u32 {
        let mut counter = 0u;
        let mut sum = 0u;

        while counter < self.m as uint {
            // We want first "significant zero", so invert first
            sum += (!(self.buckets[counter])).trailing_zeros() as uint;
            counter += 1;
        }

        // pcsaCardinality: m / phi * Math.pow(2, sum / m)
        let m: f64 = self.m as f64;
        (m / phi * 2f64.powf(sum as f64 / m)) as u32
    }

    /// Returns the current cardinality estimatewith small-cardinality correction enabled
    #[experimental]
    pub fn smCardinality(&self) -> u32 {
        let mut counter = 0u;
        let mut sum = 0u;

        while counter < self.m as uint {
            // We want first "significant zero", so invert first
            sum += (!(self.buckets[counter])).trailing_zeros() as uint;
            counter += 1;
        }

        // pcsaCorCardinality: m / phi * (Math.pow(2, sum / m) - Math.pow(2, -kappa * sum / m)),
        let m: f64 = self.m as f64;
        ((m / phi * 2f64.powf(sum as f64 / m)) - 2f64.powf(-kappa * sum as f64 / m)) as u32
    }

    /// Returns the amount of memory (in bytes) used by this data structure
    #[experimental]
    pub fn ram_bytes_used(&self) -> u32 {
        16 + (self.m * 4)    // m + b + buckets[u32, ..m]
    }

    /// Merge another counter into this counter
    #[experimental]
    pub fn merge(&mut self, p2: &PCSA) {
        let mut counter = 0u;

        while counter < self.m as uint {
            *self.buckets.get_mut(counter) |= p2.buckets[counter];
            counter += 1;
        }

    }
}

#[cfg(test)]
mod test {

    use super::PCSA;
    use std::hash;
    use std::hash::Hash;
    use std::task;

    use time::precise_time_ns;

    #[test]
    pub fn test_pcsa_merge() {

        let mut count: int = 0;

        let mut p1 = PCSA::new(5);
        let mut p2 = PCSA::new(5);
        while count < 1000 {
            let hash = hash::hash(&count.to_string());
            p1.offer_hashed(&hash);

            let hash = hash::hash(&(count + 1000).to_string());
            p2.offer_hashed(&hash);
            count += 1;
        }

        error!("   P1: {}", p1.cardinality());
        error!("   P2: {}", p2.cardinality());

        p1.merge(&p2);
        error!("   P1 + P2: {}",  p1.cardinality());

        let estimate = p1.cardinality() as int;
        let error = (estimate - 2000i).abs() as f64 / 2000f64;
        let theoreticalError = 0.78 / 5f64.sqrt();

        error!("   Error: {}", error);
        error!("   Expected Error: {}", theoreticalError);

        assert!(error < theoreticalError);
    }

    #[test]
    pub fn test_pcsa_bad_constructor() {

        let mut m = 0;

        while m < 20u32 {
            let tm = m;
            let result = task::try(proc() {
                let mut pcsa = PCSA::new(tm);
            });

            match m {
                4..16 => {if result.is_err() {fail!("4..16 range threw error")}},
                _     => {if !result.is_err() {fail!("_ range did not throw error")}}
            }

            m += 1u32;
        }
    }

    #[test]
    pub fn test_pcsa_100000() {

        let mut m: f64 = 4f64;
        let iterations = 100000;

        while m < 16f64 {
            let mut pcsa = PCSA::new(m as u32);

            let mut count: int = 0;
            let start = precise_time_ns();

            while count < iterations {
                let hash = hash::hash(&count.to_string());  //TODO move this outside the loop, horrible for benchmarking

                pcsa.offer_hashed(&hash);
                count += 1;
            }
            let time = (precise_time_ns() - start) / 1000000;
            let qps = iterations as f64 / time as f64;

            let estimate = pcsa.cardinality() as int;
            let error = (estimate - count).abs() as f64 / count as f64;
            let theoreticalError: f64 = 0.78f64 / m.sqrt();

            error!("   m: {}", m);
            error!("   Milliseconds: {}", time);
            error!("   Counts/ms: {}", qps);
            error!("   Estimate: {}", estimate);
            error!("   Error: {}", error);
            error!("   Expected Error: {}", theoreticalError);
            error!("   Ram Usage: {}", pcsa.ram_bytes_used());

            assert!(error < theoreticalError);

            m += 1f64;
        }
    }

    #[test]
    pub fn test_pcsa_1000000() {

        let mut m: f64 = 4f64;
        let iterations = 1000000;

        while m < 16f64 {
            let mut pcsa = PCSA::new(m as u32);

            let mut count: int = 0;
            let start = precise_time_ns();

            while count < iterations {
                let hash = hash::hash(&count.to_string());   //TODO move this outside the loop, horrible for benchmarking

                pcsa.offer_hashed(&hash);
                count += 1;
            }
            let time = (precise_time_ns() - start) / 1000000;
            let qps = iterations as f64 / time as f64;

            let estimate = pcsa.cardinality() as int;
            let error = (estimate - count).abs() as f64 / count as f64;
            let theoreticalError = 0.78f64 / m.sqrt();

            error!("   m: {}",  m);
            error!("   Milliseconds: {}", time);
            error!("   Counts/ms: {}", qps);
            error!("   Estimate: {}", estimate);
            error!("   Error: {}", error);
            error!("   Expected Error: {}", theoreticalError);
            error!("   Ram Usage: {}", pcsa.ram_bytes_used());
            assert!(error < theoreticalError);

            m += 1f64;
        }
    }

}<commit_msg>[DOCS] formatting<commit_after>
use std::int;
use std::num;

static phi: f64 = 0.77351f64;
static kappa: f64 = 1.75f64;

///
/// Implements the Probabilistic Counting with Stochastic Averaging
/// counter.  PCSA provides an approximate estimate of cardinality with
/// bounded error.
///
/// Relative error is 0.78 / sqrt(m)
///
/// See this [article](http://blog.aggregateknowledge.com/2013/04/02/sketch-of-the-day-probabilistic-counting-with-stochastic-averaging-pcsa/) for a layman's explanation of PCSA
///
/// Original paper can be found [here](http://www.mathcs.emory.edu/~cheung/papers/StreamDB/Probab/1985-Flajolet-Probabilistic-counting.pdf)
///
pub struct PCSA {
    m: u32,
    b: u32,
    buckets: Vec<u32>,
    indexMask: u64
}

impl PCSA {

    /// Construct a new PCSA counter
    ///
    /// b: number of bits to use as bucket index mask, larger
    ///    values means more buckets, better accuracy, more space
    ///    b must be between 4..16 inclusive
    ///
    ///    m = 2^b
    ///
    /// Complete PCSA Memory chart for reference (including per-object overhead, minus static overheads):
    ///
    ///

Precision	Size	Error on 1m Cardinality Test	Worst Case Estimate Error (+/-)
    ///
4	80 bytes	 0.09%	 39.00%

    ///
5	144 bytes	 4.14%	 34.88%

    ///
6	272 bytes	 1.18%	 31.84%

    ///
7	528 bytes	 3.62%	 29.48%

    ///
8	1040 bytes	 0.71%	 27.57%

    ///
9	2064 bytes	 1.51%	 26.00%

    ///
10	4112 bytes	 0.77%	 24.66%

    ///
11	8208 bytes	 1.15%	 23.51%

    ///
12	16400 bytes	 1.10%	 22.51%

    ///
13	32784 bytes	 0.96%	 21.63%

    ///
14	65552 bytes	 0.20%	 20.84%

    ///
15	131088 bytes	 0.18%	 20.13%

    ///

    ///
    ///### Usage
    ///
    ///```
    ///let mut pcsa = PCSA::new(10);
    ///```
    #[experimental]
    pub fn new(b: u32) -> PCSA {

        let m: u32;

        match b {
            4..16 => {  m = num::pow(2, b as uint) },
            _ => fail!("b must be 4 <= b <= 16")
        }

        let mut buckets: Vec<u32> = Vec::from_elem(m as uint, 0u32);
        let indexMask: u64 = ((1u << b as uint) - 1) as u64;

        PCSA {m: m, b: b, buckets: buckets, indexMask: indexMask}
    }

    /// Offer a hashed u64 value to the PCSA algorithm.  If this is a new, distinct value, the PCSA algo will update it's
    /// internal buckets.
    ///
    ///### Usage
    ///
    ///```
    /// let mut pcsa = PCSA::new(10);
    ///
    /// // Hash the value with std::hash SipHash 2-4. Any 64-bit hash will work
    /// // You should probably use something *other* than SipHash, since it is cryptographic
    /// // and slow
    /// let hash: u64 = hash::hash(&19u);
    /// pcsa.offer_hashed(hash);
    ///
    ///```
    #[experimental]
    pub fn offer_hashed(&mut self, hash: &u64) {
        let index: u32 = (hash & self.indexMask) as u32;
        *self.buckets.get_mut(index as uint) |= 1 << (hash >> self.b as uint).trailing_zeros() as uint;
    }

    /// Returns the current cardinality estimate
    #[experimental]
    pub fn cardinality(&self) -> u32 {
        let mut counter = 0u;
        let mut sum = 0u;

        while counter < self.m as uint {
            // We want first "significant zero", so invert first
            sum += (!(self.buckets[counter])).trailing_zeros() as uint;
            counter += 1;
        }

        // pcsaCardinality: m / phi * Math.pow(2, sum / m)
        let m: f64 = self.m as f64;
        (m / phi * 2f64.powf(sum as f64 / m)) as u32
    }

    /// Returns the current cardinality estimatewith small-cardinality correction enabled
    #[experimental]
    pub fn smCardinality(&self) -> u32 {
        let mut counter = 0u;
        let mut sum = 0u;

        while counter < self.m as uint {
            // We want first "significant zero", so invert first
            sum += (!(self.buckets[counter])).trailing_zeros() as uint;
            counter += 1;
        }

        // pcsaCorCardinality: m / phi * (Math.pow(2, sum / m) - Math.pow(2, -kappa * sum / m)),
        let m: f64 = self.m as f64;
        ((m / phi * 2f64.powf(sum as f64 / m)) - 2f64.powf(-kappa * sum as f64 / m)) as u32
    }

    /// Returns the amount of memory (in bytes) used by this data structure
    #[experimental]
    pub fn ram_bytes_used(&self) -> u32 {
        16 + (self.m * 4)    // m + b + buckets[u32, ..m]
    }

    /// Merge another counter into this counter
    #[experimental]
    pub fn merge(&mut self, p2: &PCSA) {
        let mut counter = 0u;

        while counter < self.m as uint {
            *self.buckets.get_mut(counter) |= p2.buckets[counter];
            counter += 1;
        }

    }
}

#[cfg(test)]
mod test {

    use super::PCSA;
    use std::hash;
    use std::hash::Hash;
    use std::task;

    use time::precise_time_ns;

    #[test]
    pub fn test_pcsa_merge() {

        let mut count: int = 0;

        let mut p1 = PCSA::new(5);
        let mut p2 = PCSA::new(5);
        while count < 1000 {
            let hash = hash::hash(&count.to_string());
            p1.offer_hashed(&hash);

            let hash = hash::hash(&(count + 1000).to_string());
            p2.offer_hashed(&hash);
            count += 1;
        }

        error!("   P1: {}", p1.cardinality());
        error!("   P2: {}", p2.cardinality());

        p1.merge(&p2);
        error!("   P1 + P2: {}",  p1.cardinality());

        let estimate = p1.cardinality() as int;
        let error = (estimate - 2000i).abs() as f64 / 2000f64;
        let theoreticalError = 0.78 / 5f64.sqrt();

        error!("   Error: {}", error);
        error!("   Expected Error: {}", theoreticalError);

        assert!(error < theoreticalError);
    }

    #[test]
    pub fn test_pcsa_bad_constructor() {

        let mut m = 0;

        while m < 20u32 {
            let tm = m;
            let result = task::try(proc() {
                let mut pcsa = PCSA::new(tm);
            });

            match m {
                4..16 => {if result.is_err() {fail!("4..16 range threw error")}},
                _     => {if !result.is_err() {fail!("_ range did not throw error")}}
            }

            m += 1u32;
        }
    }

    #[test]
    pub fn test_pcsa_100000() {

        let mut m: f64 = 4f64;
        let iterations = 100000;

        while m < 16f64 {
            let mut pcsa = PCSA::new(m as u32);

            let mut count: int = 0;
            let start = precise_time_ns();

            while count < iterations {
                let hash = hash::hash(&count.to_string());  //TODO move this outside the loop, horrible for benchmarking

                pcsa.offer_hashed(&hash);
                count += 1;
            }
            let time = (precise_time_ns() - start) / 1000000;
            let qps = iterations as f64 / time as f64;

            let estimate = pcsa.cardinality() as int;
            let error = (estimate - count).abs() as f64 / count as f64;
            let theoreticalError: f64 = 0.78f64 / m.sqrt();

            error!("   m: {}", m);
            error!("   Milliseconds: {}", time);
            error!("   Counts/ms: {}", qps);
            error!("   Estimate: {}", estimate);
            error!("   Error: {}", error);
            error!("   Expected Error: {}", theoreticalError);
            error!("   Ram Usage: {}", pcsa.ram_bytes_used());

            assert!(error < theoreticalError);

            m += 1f64;
        }
    }

    #[test]
    pub fn test_pcsa_1000000() {

        let mut m: f64 = 4f64;
        let iterations = 1000000;

        while m < 16f64 {
            let mut pcsa = PCSA::new(m as u32);

            let mut count: int = 0;
            let start = precise_time_ns();

            while count < iterations {
                let hash = hash::hash(&count.to_string());   //TODO move this outside the loop, horrible for benchmarking

                pcsa.offer_hashed(&hash);
                count += 1;
            }
            let time = (precise_time_ns() - start) / 1000000;
            let qps = iterations as f64 / time as f64;

            let estimate = pcsa.cardinality() as int;
            let error = (estimate - count).abs() as f64 / count as f64;
            let theoreticalError = 0.78f64 / m.sqrt();

            error!("   m: {}",  m);
            error!("   Milliseconds: {}", time);
            error!("   Counts/ms: {}", qps);
            error!("   Estimate: {}", estimate);
            error!("   Error: {}", error);
            error!("   Expected Error: {}", theoreticalError);
            error!("   Ram Usage: {}", pcsa.ram_bytes_used());
            assert!(error < theoreticalError);

            m += 1f64;
        }
    }

}<|endoftext|>


<commit_before>//
// Copyright 2022 The Project Oak Authors
//
// 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.
//

#![no_std]
#![feature(never_type)]

extern crate alloc;

use alloc::{vec, vec::Vec};
use anyhow::{bail, Context};
use oak_remote_attestation_sessions::{SessionId, SESSION_ID_LENGTH};

pub mod framing;
mod logger;
mod remote_attestation;
mod wasm;

/// Basic hardware abstraction layer for sending data.
pub trait Channel {
    fn send(&mut self, data: &[u8]) -> anyhow::Result<()>;
    fn recv(&mut self, data: &mut [u8]) -> anyhow::Result<()>;
}

pub type FrameLength = u16;
// The frame length is a u16, which is two bytes encoded.
pub const FRAME_LENGTH_ENCODED_SIZE: usize = 2;

pub struct Frame {
    pub body: Vec<u8>,
}

pub struct Framed<T: Channel> {
    inner: T,
}

impl<T: Channel> Framed<T> {
    pub fn new(channel: T) -> Self {
        Self { inner: channel }
    }

    pub fn read_frame(&mut self) -> anyhow::Result<Frame> {
        let mut length_buf = [0; FRAME_LENGTH_ENCODED_SIZE];
        self.inner.recv(&mut length_buf)?;
        let length = FrameLength::from_be_bytes(length_buf);
        let mut body: Vec<u8> = vec![0; length.into()];
        self.inner.recv(&mut body)?;
        Ok(Frame { body })
    }

    pub fn write_frame(&mut self, frame: Frame) -> anyhow::Result<()> {
        let length: FrameLength = FrameLength::try_from(frame.body.len())
            .map_err(anyhow::Error::msg)
            .context("the frame body is too large")?;
        let encoded_length = length.to_be_bytes();
        let mut encoded_frame: Vec<u8> =
            Vec::with_capacity(encoded_length.len() + frame.body.len());
        encoded_frame.extend(encoded_length);
        encoded_frame.extend(frame.body);
        self.inner.send(&encoded_frame)?;
        Ok(())
    }
}

pub struct SerializeableRequest {
    pub session_id: SessionId,
    pub body: Vec<u8>,
}

impl From<SerializeableRequest> for Vec<u8> {
    fn from(serializeable_request: SerializeableRequest) -> Vec<u8> {
        // The payload is the request's body prepended with the 8 byte session_id.
        // This takes adavantage of the session_id's fixed size to avoid needing
        // to use a key/value pair binary serialization protocol.
        let mut serialized_request: Vec<u8> = Vec::with_capacity(
            serializeable_request.session_id.len() + serializeable_request.body.len(),
        );

        serialized_request.extend(serializeable_request.session_id);
        serialized_request.extend(serializeable_request.body);

        serialized_request
    }
}

impl TryFrom<&[u8]> for SerializeableRequest {
    type Error = anyhow::Error;

    fn try_from(serialized_request: &[u8]) -> Result<Self, Self::Error> {
        if serialized_request.len() < SESSION_ID_LENGTH {
            bail!(
                "Message too short to contain a SessionId. The length of a SessionId
                is {} bytes, the message received contained only {} bytes",
                SESSION_ID_LENGTH,
                serialized_request.len()
            );
        }

        let (session_id_slice, request_body_slice) = serialized_request.split_at(SESSION_ID_LENGTH);

        let mut session_id: SessionId = [0; SESSION_ID_LENGTH];
        session_id.copy_from_slice(session_id_slice);
        let body = request_body_slice.to_vec();

        Ok(Self { session_id, body })
    }
}
<commit_msg>Change frame length prefix to match planned framing (#2843)<commit_after>//
// Copyright 2022 The Project Oak Authors
//
// 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.
//

#![no_std]
#![feature(never_type)]

extern crate alloc;

use alloc::{vec, vec::Vec};
use anyhow::{bail, Context};
use oak_remote_attestation_sessions::{SessionId, SESSION_ID_LENGTH};

pub mod framing;
mod logger;
mod remote_attestation;
mod wasm;

/// Basic hardware abstraction layer for sending data.
pub trait Channel {
    fn send(&mut self, data: &[u8]) -> anyhow::Result<()>;
    fn recv(&mut self, data: &mut [u8]) -> anyhow::Result<()>;
}

/// Length of the entire frame, including the header.
pub type FrameLength = u32;
const FRAME_BYTES_SIZE: usize = 4;

pub struct Frame {
    pub body: Vec<u8>,
}

pub struct Framed<T: Channel> {
    inner: T,
}

impl<T: Channel> Framed<T> {
    pub fn new(channel: T) -> Self {
        Self { inner: channel }
    }

    pub fn read_frame(&mut self) -> anyhow::Result<Frame> {
        let length = {
            let mut length_bytes = [0; FRAME_BYTES_SIZE];
            self.inner.recv(&mut length_bytes)?;
            FrameLength::from_le_bytes(length_bytes)
        };

        let body = {
            let body_length: u32 = length - FRAME_BYTES_SIZE as u32;
            let mut body: Vec<u8> = vec![
                0;
                usize::try_from(body_length).expect(
                    "the supported pointer size is smaller than the frame length"
                )
            ];
            self.inner.recv(&mut body)?;
            body
        };

        Ok(Frame { body })
    }

    pub fn write_frame(&mut self, frame: Frame) -> anyhow::Result<()> {
        let length_bytes = {
            let length = FrameLength::try_from(FRAME_BYTES_SIZE + frame.body.len())
                .map_err(anyhow::Error::msg)
                .context("the frame is too large")?;
            length.to_le_bytes()
        };
        self.inner.send(&length_bytes)?;
        self.inner.send(&frame.body)?;
        Ok(())
    }
}

pub struct SerializeableRequest {
    pub session_id: SessionId,
    pub body: Vec<u8>,
}

impl From<SerializeableRequest> for Vec<u8> {
    fn from(serializeable_request: SerializeableRequest) -> Vec<u8> {
        // The payload is the request's body prepended with the 8 byte session_id.
        // This takes adavantage of the session_id's fixed size to avoid needing
        // to use a key/value pair binary serialization protocol.
        let mut serialized_request: Vec<u8> = Vec::with_capacity(
            serializeable_request.session_id.len() + serializeable_request.body.len(),
        );

        serialized_request.extend(serializeable_request.session_id);
        serialized_request.extend(serializeable_request.body);

        serialized_request
    }
}

impl TryFrom<&[u8]> for SerializeableRequest {
    type Error = anyhow::Error;

    fn try_from(serialized_request: &[u8]) -> Result<Self, Self::Error> {
        if serialized_request.len() < SESSION_ID_LENGTH {
            bail!(
                "Message too short to contain a SessionId. The length of a SessionId
                is {} bytes, the message received contained only {} bytes",
                SESSION_ID_LENGTH,
                serialized_request.len()
            );
        }

        let (session_id_slice, request_body_slice) = serialized_request.split_at(SESSION_ID_LENGTH);

        let mut session_id: SessionId = [0; SESSION_ID_LENGTH];
        session_id.copy_from_slice(session_id_slice);
        let body = request_body_slice.to_vec();

        Ok(Self { session_id, body })
    }
}
<|endoftext|>


<commit_before>use orbclient::Renderer;
use std::cell::{Cell, RefCell};
use std::sync::Arc;

use cell::{CloneCell, CheckSet};
use draw::draw_box;
use event::Event;
use point::Point;
use rect::Rect;
use theme::{Selector, Theme};
use traits::{Click, Place, Text};
use widgets::Widget;

pub struct Button {
    pub rect: Cell<Rect>,
    pub text: CloneCell<String>,
    pub text_offset: Cell<Point>,
    click_callback: RefCell<Option<Arc<Fn(&Button, Point)>>>,
    hover: Cell<bool>,
    pressed: Cell<bool>,
}

impl Button {
    pub fn new() -> Arc<Self> {
        Arc::new(Button {
            rect: Cell::new(Rect::default()),
            text: CloneCell::new(String::new()),
            text_offset: Cell::new(Point::default()),
            click_callback: RefCell::new(None),
            hover: Cell::new(false),
            pressed: Cell::new(false),
        })
    }
}

impl Click for Button {
    fn emit_click(&self, point: Point) {
        if let Some(ref click_callback) = *self.click_callback.borrow() {
            click_callback(self, point);
        }
    }

    fn on_click<T: Fn(&Self, Point) + 'static>(&self, func: T) -> &Self {
        *self.click_callback.borrow_mut() = Some(Arc::new(func));
        self
    }
}

impl Place for Button {}

impl Text for Button {
    fn text<S: Into<String>>(&self, text: S) -> &Self {
        self.text.set(text.into());
        self
    }

    fn text_offset(&self, x: i32, y: i32) -> &Self {
        self.text_offset.set(Point::new(x, y));
        self
    }
}

impl Widget for Button {
    fn name(&self) -> &str {
        "Button"
    }

    fn rect(&self) -> &Cell<Rect> {
        &self.rect
    }

    fn draw(&self, renderer: &mut Renderer, _focused: bool, theme: &Theme) {
        let mut selector = Selector::new(Some("button")).with_pseudo_class(
            if self.pressed.get() {
                "active"
            } else {
                "inactive"
            }
        );

        if self.hover.get() {
            selector = selector.with_pseudo_class("hover");
        }

        let rect = self.rect.get();

        let w = rect.width as i32;
        let h = rect.height as i32;

        draw_box(renderer, rect, theme, &selector);

        let text = self.text.borrow();

        let mut point = self.text_offset.get();
        for c in text.chars() {
            if c == '\n' {
                point.x = self.text_offset.get().x;
                point.y += 16;
            } else {
                if point.x + 8 <= w && point.y + 16 <= h {
                    renderer.char(point.x + rect.x, point.y + rect.y, c, theme.color("color", &selector));
                }
                point.x += 8;
            }
        }
    }

    fn event(&self, event: Event, focused: bool, redraw: &mut bool) -> bool {
        match event {
            Event::Mouse { point, left_button, .. } => {
                let mut click = false;

                let rect = self.rect.get();
                if rect.contains(point) {
                    if self.hover.check_set(true) {
                        *redraw = true;
                    }

                    if left_button {
                        if self.pressed.check_set(true) {
                            *redraw = true;
                        }
                    } else {
                        if self.pressed.check_set(false) {
                            click = true;
                            *redraw = true;
                        }
                    }
                } else {
                    if self.hover.check_set(false) {
                        *redraw = true;
                    }

                    if !left_button {
                        if self.pressed.check_set(false) {
                            *redraw = true;
                        }
                    }
                }

                if click {
                    let click_point: Point = point - rect.point();
                    self.emit_click(click_point);
                }
            }
            _ => (),
        }

        focused
    }
}
<commit_msg>Unpress buttons regardless of left_button state<commit_after>use orbclient::Renderer;
use std::cell::{Cell, RefCell};
use std::sync::Arc;

use cell::{CloneCell, CheckSet};
use draw::draw_box;
use event::Event;
use point::Point;
use rect::Rect;
use theme::{Selector, Theme};
use traits::{Click, Place, Text};
use widgets::Widget;

pub struct Button {
    pub rect: Cell<Rect>,
    pub text: CloneCell<String>,
    pub text_offset: Cell<Point>,
    click_callback: RefCell<Option<Arc<Fn(&Button, Point)>>>,
    hover: Cell<bool>,
    pressed: Cell<bool>,
}

impl Button {
    pub fn new() -> Arc<Self> {
        Arc::new(Button {
            rect: Cell::new(Rect::default()),
            text: CloneCell::new(String::new()),
            text_offset: Cell::new(Point::default()),
            click_callback: RefCell::new(None),
            hover: Cell::new(false),
            pressed: Cell::new(false),
        })
    }
}

impl Click for Button {
    fn emit_click(&self, point: Point) {
        if let Some(ref click_callback) = *self.click_callback.borrow() {
            click_callback(self, point);
        }
    }

    fn on_click<T: Fn(&Self, Point) + 'static>(&self, func: T) -> &Self {
        *self.click_callback.borrow_mut() = Some(Arc::new(func));
        self
    }
}

impl Place for Button {}

impl Text for Button {
    fn text<S: Into<String>>(&self, text: S) -> &Self {
        self.text.set(text.into());
        self
    }

    fn text_offset(&self, x: i32, y: i32) -> &Self {
        self.text_offset.set(Point::new(x, y));
        self
    }
}

impl Widget for Button {
    fn name(&self) -> &str {
        "Button"
    }

    fn rect(&self) -> &Cell<Rect> {
        &self.rect
    }

    fn draw(&self, renderer: &mut Renderer, _focused: bool, theme: &Theme) {
        let mut selector = Selector::new(Some("button")).with_pseudo_class(
            if self.pressed.get() {
                "active"
            } else {
                "inactive"
            }
        );

        if self.hover.get() {
            selector = selector.with_pseudo_class("hover");
        }

        let rect = self.rect.get();

        let w = rect.width as i32;
        let h = rect.height as i32;

        draw_box(renderer, rect, theme, &selector);

        let text = self.text.borrow();

        let mut point = self.text_offset.get();
        for c in text.chars() {
            if c == '\n' {
                point.x = self.text_offset.get().x;
                point.y += 16;
            } else {
                if point.x + 8 <= w && point.y + 16 <= h {
                    renderer.char(point.x + rect.x, point.y + rect.y, c, theme.color("color", &selector));
                }
                point.x += 8;
            }
        }
    }

    fn event(&self, event: Event, focused: bool, redraw: &mut bool) -> bool {
        match event {
            Event::Mouse { point, left_button, .. } => {
                let mut click = false;

                let rect = self.rect.get();
                if rect.contains(point) {
                    if self.hover.check_set(true) {
                        *redraw = true;
                    }

                    if left_button {
                        if self.pressed.check_set(true) {
                            *redraw = true;
                        }
                    } else {
                        if self.pressed.check_set(false) {
                            click = true;
                            *redraw = true;
                        }
                    }
                } else {
                    if self.hover.check_set(false) {
                        *redraw = true;
                    }

                    if self.pressed.check_set(false) {
                        *redraw = true;
                    }
                }

                if click {
                    let click_point: Point = point - rect.point();
                    self.emit_click(click_point);
                }
            }
            _ => (),
        }

        focused
    }
}
<|endoftext|>


<commit_before>use ::{Player, RED, BLUE};
use field::Field;
use unit::Unit;

pub trait WinCondition<T: Unit> {
    fn winner(&self, field: &Field<T>) -> Option<Player>;
}

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

impl<T: Unit> WinCondition<T> for EliminateCondition {
    fn winner(&self, field: &Field<T>) -> Option<Player> {
        let mut red_preseted = false;
        let mut blue_presented = false;
        for &row in field.rows.iter() {
            if red_preseted && blue_presented { break; }
            for &cell in row.iter() {
                if red_preseted && blue_presented { break; }
                if let Some(ref unit) = cell {
                    match unit.owner() {
                        RED => red_preseted = true,
                        BLUE => blue_presented = true,
                    }
                }
            }
        }
        match (red_preseted, blue_presented) {
            (true, false) => { Some(RED) },
            (false, true) => { Some(BLUE) },
            _ => None,
        }
    }
}
<commit_msg>Added another win condition<commit_after>use ::{Player, RED, BLUE, HEIGHT};
use field::Field;
use unit::Unit;

pub trait WinCondition<T: Unit> {
    fn winner(&self, field: &Field<T>) -> Option<Player>;
}

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

impl<T: Unit> WinCondition<T> for EliminateCondition {
    fn winner(&self, field: &Field<T>) -> Option<Player> {
        let mut red_preseted = false;
        let mut blue_presented = false;
        for &row in field.rows.iter() {
            if red_preseted && blue_presented { break; }
            for &cell in row.iter() {
                if red_preseted && blue_presented { break; }
                if let Some(ref unit) = cell {
                    match unit.owner() {
                        RED => red_preseted = true,
                        BLUE => blue_presented = true,
                    }
                }
            }
        }
        match (red_preseted, blue_presented) {
            (true, false) => { Some(RED) },
            (false, true) => { Some(BLUE) },
            _ => None,
        }
    }
}

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

impl<T: Unit> WinCondition<T> for GetToLastRowCondition {
    fn winner(&self, field: &Field<T>) -> Option<Player> {

        fn unit_check<T: Unit>(cell: &Option<T>, player: Player) -> bool {
            if let Some(ref u) = cell.as_ref() {
                u.owner() == player
            } else {
                false
            }
        };

        let blue_at_first = field.rows[0].iter().any(|&x| unit_check(&x, BLUE) );
        let red_at_last = field.rows[HEIGHT - 1].iter().any(|&x| unit_check(&x, RED) );

        match (red_at_last, blue_at_first) {
            (true, false) => Some(RED),
            (false, true) => Some(BLUE),
            _ => None
        }
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code, unused_variables)]
use alloc::alloc::{Global, Alloc, Layout};
use bytes::BytesMut;

use std::sync::Arc;

use audiosample::*;
use pixel::*;
use timeinfo::*;

use byte_slice_cast::*;

#[derive(Fail, Debug)]
pub enum FrameError {
    #[fail(display = "Invalid Index")]
    InvalidIndex,
    #[fail(display = "Invalid Conversion")]
    InvalidConversion,
}

use self::FrameError::*;

// TODO: Document
// TODO: Change it to provide Droppable/Seekable information or use a separate enum?
#[derive(Clone, Debug, PartialEq)]
pub enum PictureType {
    UNKNOWN,
    I,
    P,
    B,
    S,
    SI,
    SP,
    SB,
    BI,
}

#[derive(Clone, Debug, PartialEq)]
pub struct VideoInfo {
    pub pic_type: PictureType,
    pub width: usize,
    pub height: usize,
    pub format: Arc<Formaton>,
}

impl VideoInfo {
    fn size(&self, align: usize) -> usize {
        let mut size = 0;
        for &component in self.format.into_iter() {
            if let Some(c) = component {
                size += c.get_data_size(self.width, self.height, align);
            }
        }
        size
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct AudioInfo {
    pub samples: usize,
    pub rate: usize,
    pub map: ChannelMap,
    pub format: Arc<Soniton>,
}

impl AudioInfo {
    fn size(&self, align: usize) -> usize {
        self.format.get_audio_size(self.samples, align) * self.map.len()
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum MediaKind {
    Video(VideoInfo),
    Audio(AudioInfo),
}

use std::convert::From;

impl From<VideoInfo> for MediaKind {
    fn from(v: VideoInfo) -> Self {
        MediaKind::Video(v)
    }
}

impl From<AudioInfo> for MediaKind {
    fn from(a: AudioInfo) -> Self {
        MediaKind::Audio(a)
    }
}

use self::MediaKind::*;

pub trait FrameBuffer : Send + Sync {
    fn linesize(&self, idx: usize) -> Result<usize, FrameError>;
    fn count(&self) -> usize;
    fn as_slice_inner<'a>(&'a self, idx: usize) -> Result<&'a [u8], FrameError>;
    fn as_mut_slice_inner<'a>(&'a mut self, idx: usize) -> Result<&'a mut [u8], FrameError>;
}

mod private {
    use byte_slice_cast::*;

    pub trait Supported: FromByteSlice {}
    impl Supported for u8 {}
    impl Supported for i16 {}
    impl Supported for f32 {}
}

pub trait FrameBufferConv<T: private::Supported> : FrameBuffer {
    fn as_slice<'a>(&'a self, idx: usize) -> Result<&'a [T], FrameError> {
        self.as_slice_inner(idx)?.as_slice_of::<T>().map_err(|e| InvalidConversion)
    }
    fn as_mut_slice<'a>(&'a mut self, idx: usize) -> Result<&'a mut [T], FrameError> {
        self.as_mut_slice_inner(idx)?.as_mut_slice_of::<T>().map_err(|e| InvalidConversion)
    }
}

impl FrameBufferConv<u8> for FrameBuffer {}
impl FrameBufferConv<i16> for FrameBuffer {}
impl FrameBufferConv<f32> for FrameBuffer {}

use std::fmt;

impl fmt::Debug for FrameBuffer {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "FrameBuffer")
    }
}

#[derive(Debug)]
pub struct Frame {
    pub kind: MediaKind,
    pub buf: Box<FrameBuffer>,
    pub t: TimeInfo,
}

const ALIGNMENT: usize = 32;

struct Plane {
    buf: BytesMut,
    linesize: usize,
}

struct DefaultFrameBuffer {
    buf: BytesMut,
    planes: Vec<Plane>,
}

impl FrameBuffer for DefaultFrameBuffer {
    fn linesize(&self, idx: usize) -> Result<usize, FrameError> {
        match self.planes.get(idx) {
            None => Err(InvalidIndex),
            Some(plane) => Ok(plane.linesize),
        }
    }
    fn count(&self) -> usize {
        self.planes.len()
    }

    fn as_slice_inner<'a>(&'a self, idx: usize) -> Result<&'a [u8], FrameError> {
        match self.planes.get(idx) {
            None => Err(InvalidIndex),
            Some(plane) => Ok(&plane.buf),
        }
    }
    fn as_mut_slice_inner<'a>(&'a mut self, idx: usize) -> Result<&'a mut [u8], FrameError> {
        match self.planes.get_mut(idx) {
            None => Err(InvalidIndex),
            Some(plane) => Ok(&mut plane.buf),
        }
    }
}

impl DefaultFrameBuffer {
    pub fn new<'a>(kind: &'a MediaKind) -> DefaultFrameBuffer {
        match kind {
            &Video(ref video) => {
                let size = video.size(ALIGNMENT);
                let data = unsafe {
                    Global.alloc(Layout::from_size_align(size, ALIGNMENT).unwrap())
                        .unwrap()
                };
                let data = data.as_ptr() as *mut u8;
                //let data = unsafe { Heap.alloc_zeroed(Layout::from_size_align(size, ALIGNMENT)) };
                let buf = BytesMut::from(unsafe { Vec::from_raw_parts(data, size, size) });
                let mut buffer = DefaultFrameBuffer {
                    buf: buf,
                    planes: Vec::new(),
                };
                for &component in video.format.iter() {
                    if let Some(c) = component {
                        let planesize = c.get_data_size(video.width, video.height, ALIGNMENT);
                        let linesize = c.get_linesize(video.width, ALIGNMENT);
                        buffer.planes.push(Plane {
                            buf: buffer.buf.split_to(planesize),
                            linesize: linesize,
                        });
                    }
                }
                buffer
            },
            &Audio(ref audio) => {
                let size = audio.size(ALIGNMENT);
                let data = unsafe {
                    Global.alloc(Layout::from_size_align(size, ALIGNMENT).unwrap())
                        .unwrap()
                };
                let data = data.as_ptr() as *mut u8;
                let buf = BytesMut::from(unsafe { Vec::from_raw_parts(data, size, size) });
                let mut buffer = DefaultFrameBuffer {
                    buf: buf,
                    planes: Vec::new(),
                };
                for _ in 0..audio.map.len() {
                    let size = audio.format.get_audio_size(audio.samples, ALIGNMENT);
                    buffer.planes.push(Plane {
                        buf: buffer.buf.split_to(size),
                        linesize: size,
                    });
                }
                buffer
            },
        }
    }
}

pub type ArcFrame = Arc<Frame>;

pub fn new_default_frame<T>(kind: T, t: Option<TimeInfo>) -> Frame
where T: Into<MediaKind> + Clone
{
    let k = kind.into();
    let buf = DefaultFrameBuffer::new(&k);

    Frame {
        kind: k,
        buf: box buf,
        t: t.unwrap_or_default(),
    }
}

use std::ptr::copy_nonoverlapping;

fn copy_plane(
    dst: &mut [u8],
    dst_linesize: usize,
    src: &[u8],
    src_linesize: usize,
    w: usize,
    h: usize,
) {
    let dst_chunks = dst.chunks_mut(dst_linesize);
    let src_chunks = src.chunks(src_linesize);

    for (d, s) in dst_chunks.zip(src_chunks).take(h) {
        unsafe {
            copy_nonoverlapping(s.as_ptr(), d.as_mut_ptr(), w);
        }
    }
}

fn copy_image<'a, IM, IU, I>(
    dst: IM,
    dst_linesizes: IU,
    src: I,
    src_linesizes: IU,
    w: usize,
    h: usize,
    fmt: &Formaton,
) where
    IM: Iterator<Item = &'a mut [u8]>,
    I: Iterator<Item = &'a [u8]>,
    IU: Iterator<Item = usize>,
{
    let dst_iter = dst.zip(dst_linesizes);
    let src_iter = src.zip(src_linesizes);
    let iter = dst_iter.zip(src_iter).zip(fmt.iter());

    for (((d, d_linesize), (s, s_linesize)), c) in iter {
        copy_plane(
            d,
            d_linesize,
            s,
            s_linesize,
            c.unwrap().get_width(w),
            c.unwrap().get_height(h),
        );
    }
}

// TODO: Add proper tests
fn copy_to_frame<'a, I, IU>(dst: &mut Frame, mut src: I, mut src_linesize: IU, w: usize, h: usize)
where
    I: Iterator<Item = &'a [u8]>,
    IU: Iterator<Item = usize>,
{
    if let MediaKind::Video(ref fmt) = dst.kind {
        let mut f_iter = fmt.format.iter();
        let w = fmt.width;
        let h = fmt.height;
        for i in 0..dst.buf.count() {
            let d_linesize = dst.buf.linesize(i).unwrap();
            let s_linesize = src_linesize.next().unwrap();
            let d = dst.buf.as_mut_slice(i).unwrap();
            let s = src.next().unwrap();
            let c = f_iter.next().unwrap();
            copy_plane(
                d,
                d_linesize,
                s,
                s_linesize,
                c.unwrap().get_width(w),
                c.unwrap().get_height(h),
            );
        }
    } else {
        unimplemented!();
    }
}

use std::mem;
use std::slice;

// TODO make it a separate trait
impl Frame {
    pub fn copy_from_slice<'a, I, IU>(&mut self, mut src: I, mut src_linesize: IU)
    where
        I: Iterator<Item = &'a [u8]>,
        IU: Iterator<Item = usize>,
    {
        if let MediaKind::Video(ref fmt) = self.kind {
            let mut f_iter = fmt.format.iter();
            let w = fmt.width;
            let h = fmt.height;
            for i in 0..self.buf.count() {
                let d_linesize = self.buf.linesize(i).unwrap();
                let s_linesize = src_linesize.next().unwrap();
                let d = self.buf.as_mut_slice(i).unwrap();
                let s = src.next().unwrap();
                let c = f_iter.next().unwrap();
                copy_plane(
                    d,
                    d_linesize,
                    s,
                    s_linesize,
                    c.unwrap().get_width(w),
                    c.unwrap().get_height(h),
                );
            }
        } else {
            unimplemented!();
        }
    }

    pub fn copy_from_raw_parts<'a, I, IU>(&mut self, mut src: I, mut src_linesize: IU)
    where
        I: Iterator<Item = *const u8>,
        IU: Iterator<Item = usize>,
    {
        if let MediaKind::Video(ref fmt) = self.kind {
            let mut f_iter = fmt.format.iter();
            let w = fmt.width;
            let h = fmt.height;
            for i in 0..self.buf.count() {
                let d_linesize = self.buf.linesize(i).unwrap();
                let s_linesize = src_linesize.next().unwrap();
                let d = self.buf.as_mut_slice(i).unwrap();
                let c = f_iter.next().unwrap();
                let r = src.next().unwrap();
                let hb = c.unwrap().get_height(h);
                let s = unsafe { slice::from_raw_parts(r, hb * s_linesize) };
                copy_plane(d, d_linesize, s, s_linesize, c.unwrap().get_width(w), hb);
                mem::forget(s);
            }
        } else {
            unimplemented!();
        }
    }
}

<commit_msg>data: Compare AudioInfo without audio samples<commit_after>#![allow(dead_code, unused_variables)]
use alloc::alloc::{Global, Alloc, Layout};
use bytes::BytesMut;

use std::sync::Arc;

use audiosample::*;
use pixel::*;
use timeinfo::*;

use byte_slice_cast::*;

#[derive(Fail, Debug)]
pub enum FrameError {
    #[fail(display = "Invalid Index")]
    InvalidIndex,
    #[fail(display = "Invalid Conversion")]
    InvalidConversion,
}

use self::FrameError::*;

// TODO: Document
// TODO: Change it to provide Droppable/Seekable information or use a separate enum?
#[derive(Clone, Debug, PartialEq)]
pub enum PictureType {
    UNKNOWN,
    I,
    P,
    B,
    S,
    SI,
    SP,
    SB,
    BI,
}

#[derive(Clone, Debug, PartialEq)]
pub struct VideoInfo {
    pub pic_type: PictureType,
    pub width: usize,
    pub height: usize,
    pub format: Arc<Formaton>,
}

impl VideoInfo {
    fn size(&self, align: usize) -> usize {
        let mut size = 0;
        for &component in self.format.into_iter() {
            if let Some(c) = component {
                size += c.get_data_size(self.width, self.height, align);
            }
        }
        size
    }
}

#[derive(Clone, Debug)]
pub struct AudioInfo {
    pub samples: usize,
    pub rate: usize,
    pub map: ChannelMap,
    pub format: Arc<Soniton>,
}

impl AudioInfo {
    fn size(&self, align: usize) -> usize {
        self.format.get_audio_size(self.samples, align) * self.map.len()
    }
}

impl PartialEq for AudioInfo {

    fn eq(&self, info2: &AudioInfo) -> bool {
        self.rate == info2.rate && self.map == info2.map && self.format == info2.format
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum MediaKind {
    Video(VideoInfo),
    Audio(AudioInfo),
}

use std::convert::From;

impl From<VideoInfo> for MediaKind {
    fn from(v: VideoInfo) -> Self {
        MediaKind::Video(v)
    }
}

impl From<AudioInfo> for MediaKind {
    fn from(a: AudioInfo) -> Self {
        MediaKind::Audio(a)
    }
}

use self::MediaKind::*;

pub trait FrameBuffer : Send + Sync {
    fn linesize(&self, idx: usize) -> Result<usize, FrameError>;
    fn count(&self) -> usize;
    fn as_slice_inner<'a>(&'a self, idx: usize) -> Result<&'a [u8], FrameError>;
    fn as_mut_slice_inner<'a>(&'a mut self, idx: usize) -> Result<&'a mut [u8], FrameError>;
}

mod private {
    use byte_slice_cast::*;

    pub trait Supported: FromByteSlice {}
    impl Supported for u8 {}
    impl Supported for i16 {}
    impl Supported for f32 {}
}

pub trait FrameBufferConv<T: private::Supported> : FrameBuffer {
    fn as_slice<'a>(&'a self, idx: usize) -> Result<&'a [T], FrameError> {
        self.as_slice_inner(idx)?.as_slice_of::<T>().map_err(|e| InvalidConversion)
    }
    fn as_mut_slice<'a>(&'a mut self, idx: usize) -> Result<&'a mut [T], FrameError> {
        self.as_mut_slice_inner(idx)?.as_mut_slice_of::<T>().map_err(|e| InvalidConversion)
    }
}

impl FrameBufferConv<u8> for FrameBuffer {}
impl FrameBufferConv<i16> for FrameBuffer {}
impl FrameBufferConv<f32> for FrameBuffer {}

use std::fmt;

impl fmt::Debug for FrameBuffer {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "FrameBuffer")
    }
}

#[derive(Debug)]
pub struct Frame {
    pub kind: MediaKind,
    pub buf: Box<FrameBuffer>,
    pub t: TimeInfo,
}

const ALIGNMENT: usize = 32;

struct Plane {
    buf: BytesMut,
    linesize: usize,
}

struct DefaultFrameBuffer {
    buf: BytesMut,
    planes: Vec<Plane>,
}

impl FrameBuffer for DefaultFrameBuffer {
    fn linesize(&self, idx: usize) -> Result<usize, FrameError> {
        match self.planes.get(idx) {
            None => Err(InvalidIndex),
            Some(plane) => Ok(plane.linesize),
        }
    }
    fn count(&self) -> usize {
        self.planes.len()
    }

    fn as_slice_inner<'a>(&'a self, idx: usize) -> Result<&'a [u8], FrameError> {
        match self.planes.get(idx) {
            None => Err(InvalidIndex),
            Some(plane) => Ok(&plane.buf),
        }
    }
    fn as_mut_slice_inner<'a>(&'a mut self, idx: usize) -> Result<&'a mut [u8], FrameError> {
        match self.planes.get_mut(idx) {
            None => Err(InvalidIndex),
            Some(plane) => Ok(&mut plane.buf),
        }
    }
}

impl DefaultFrameBuffer {
    pub fn new<'a>(kind: &'a MediaKind) -> DefaultFrameBuffer {
        match kind {
            &Video(ref video) => {
                let size = video.size(ALIGNMENT);
                let data = unsafe {
                    Global.alloc(Layout::from_size_align(size, ALIGNMENT).unwrap())
                        .unwrap()
                };
                let data = data.as_ptr() as *mut u8;
                //let data = unsafe { Heap.alloc_zeroed(Layout::from_size_align(size, ALIGNMENT)) };
                let buf = BytesMut::from(unsafe { Vec::from_raw_parts(data, size, size) });
                let mut buffer = DefaultFrameBuffer {
                    buf: buf,
                    planes: Vec::new(),
                };
                for &component in video.format.iter() {
                    if let Some(c) = component {
                        let planesize = c.get_data_size(video.width, video.height, ALIGNMENT);
                        let linesize = c.get_linesize(video.width, ALIGNMENT);
                        buffer.planes.push(Plane {
                            buf: buffer.buf.split_to(planesize),
                            linesize: linesize,
                        });
                    }
                }
                buffer
            },
            &Audio(ref audio) => {
                let size = audio.size(ALIGNMENT);
                let data = unsafe {
                    Global.alloc(Layout::from_size_align(size, ALIGNMENT).unwrap())
                        .unwrap()
                };
                let data = data.as_ptr() as *mut u8;
                let buf = BytesMut::from(unsafe { Vec::from_raw_parts(data, size, size) });
                let mut buffer = DefaultFrameBuffer {
                    buf: buf,
                    planes: Vec::new(),
                };
                for _ in 0..audio.map.len() {
                    let size = audio.format.get_audio_size(audio.samples, ALIGNMENT);
                    buffer.planes.push(Plane {
                        buf: buffer.buf.split_to(size),
                        linesize: size,
                    });
                }
                buffer
            },
        }
    }
}

pub type ArcFrame = Arc<Frame>;

pub fn new_default_frame<T>(kind: T, t: Option<TimeInfo>) -> Frame
where T: Into<MediaKind> + Clone
{
    let k = kind.into();
    let buf = DefaultFrameBuffer::new(&k);

    Frame {
        kind: k,
        buf: box buf,
        t: t.unwrap_or_default(),
    }
}

use std::ptr::copy_nonoverlapping;

fn copy_plane(
    dst: &mut [u8],
    dst_linesize: usize,
    src: &[u8],
    src_linesize: usize,
    w: usize,
    h: usize,
) {
    let dst_chunks = dst.chunks_mut(dst_linesize);
    let src_chunks = src.chunks(src_linesize);

    for (d, s) in dst_chunks.zip(src_chunks).take(h) {
        unsafe {
            copy_nonoverlapping(s.as_ptr(), d.as_mut_ptr(), w);
        }
    }
}

fn copy_image<'a, IM, IU, I>(
    dst: IM,
    dst_linesizes: IU,
    src: I,
    src_linesizes: IU,
    w: usize,
    h: usize,
    fmt: &Formaton,
) where
    IM: Iterator<Item = &'a mut [u8]>,
    I: Iterator<Item = &'a [u8]>,
    IU: Iterator<Item = usize>,
{
    let dst_iter = dst.zip(dst_linesizes);
    let src_iter = src.zip(src_linesizes);
    let iter = dst_iter.zip(src_iter).zip(fmt.iter());

    for (((d, d_linesize), (s, s_linesize)), c) in iter {
        copy_plane(
            d,
            d_linesize,
            s,
            s_linesize,
            c.unwrap().get_width(w),
            c.unwrap().get_height(h),
        );
    }
}

// TODO: Add proper tests
fn copy_to_frame<'a, I, IU>(dst: &mut Frame, mut src: I, mut src_linesize: IU, w: usize, h: usize)
where
    I: Iterator<Item = &'a [u8]>,
    IU: Iterator<Item = usize>,
{
    if let MediaKind::Video(ref fmt) = dst.kind {
        let mut f_iter = fmt.format.iter();
        let w = fmt.width;
        let h = fmt.height;
        for i in 0..dst.buf.count() {
            let d_linesize = dst.buf.linesize(i).unwrap();
            let s_linesize = src_linesize.next().unwrap();
            let d = dst.buf.as_mut_slice(i).unwrap();
            let s = src.next().unwrap();
            let c = f_iter.next().unwrap();
            copy_plane(
                d,
                d_linesize,
                s,
                s_linesize,
                c.unwrap().get_width(w),
                c.unwrap().get_height(h),
            );
        }
    } else {
        unimplemented!();
    }
}

use std::mem;
use std::slice;

// TODO make it a separate trait
impl Frame {
    pub fn copy_from_slice<'a, I, IU>(&mut self, mut src: I, mut src_linesize: IU)
    where
        I: Iterator<Item = &'a [u8]>,
        IU: Iterator<Item = usize>,
    {
        if let MediaKind::Video(ref fmt) = self.kind {
            let mut f_iter = fmt.format.iter();
            let w = fmt.width;
            let h = fmt.height;
            for i in 0..self.buf.count() {
                let d_linesize = self.buf.linesize(i).unwrap();
                let s_linesize = src_linesize.next().unwrap();
                let d = self.buf.as_mut_slice(i).unwrap();
                let s = src.next().unwrap();
                let c = f_iter.next().unwrap();
                copy_plane(
                    d,
                    d_linesize,
                    s,
                    s_linesize,
                    c.unwrap().get_width(w),
                    c.unwrap().get_height(h),
                );
            }
        } else {
            unimplemented!();
        }
    }

    pub fn copy_from_raw_parts<'a, I, IU>(&mut self, mut src: I, mut src_linesize: IU)
    where
        I: Iterator<Item = *const u8>,
        IU: Iterator<Item = usize>,
    {
        if let MediaKind::Video(ref fmt) = self.kind {
            let mut f_iter = fmt.format.iter();
            let w = fmt.width;
            let h = fmt.height;
            for i in 0..self.buf.count() {
                let d_linesize = self.buf.linesize(i).unwrap();
                let s_linesize = src_linesize.next().unwrap();
                let d = self.buf.as_mut_slice(i).unwrap();
                let c = f_iter.next().unwrap();
                let r = src.next().unwrap();
                let hb = c.unwrap().get_height(h);
                let s = unsafe { slice::from_raw_parts(r, hb * s_linesize) };
                copy_plane(d, d_linesize, s, s_linesize, c.unwrap().get_width(w), hb);
                mem::forget(s);
            }
        } else {
            unimplemented!();
        }
    }
}

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

    #[test]
    fn test_format_cmp() {
        let mut map = ChannelMap::new();
        map.add_channel(ChannelType::C);
        let sn = Arc::new(formats::S16);
        let info1 = AudioInfo{samples: 42, rate: 48000, map: map.clone(), format: sn};
        let sn = Arc::new(formats::S16);
        let info2 = AudioInfo{samples: 4242, rate: 48000, map: map.clone(), format: sn};

        assert_eq!(info1 == info2, true);

        let mut map = ChannelMap::new();
        map.add_channel(ChannelType::C);
        let sn = Arc::new(formats::S16);
        let info1 = AudioInfo{samples: 42, rate: 48000, map: map.clone(), format: sn};
        let sn = Arc::new(formats::S32);
        let info2 = AudioInfo{samples: 42, rate: 48000, map: map.clone(), format: sn};

        assert_eq!(info1 == info2, false);
    }
}
<|endoftext|>