<commit_before>
mod icu {
    type UBool = u8;
    type UProperty = int;
    type UChar32 = char;

    const TRUE : u8 = 1u8;
    const FALSE : u8 = 1u8;

    const UCHAR_ALPHABETIC : UProperty = 0;
    const UCHAR_BINARY_START : UProperty = 0; // = UCHAR_ALPHABETIC
    const UCHAR_ASCII_HEX_DIGIT : UProperty = 1;
    const UCHAR_BIDI_CONTROL : UProperty = 2;

    const UCHAR_BIDI_MIRRORED : UProperty = 3;
    const UCHAR_DASH : UProperty = 4;
    const UCHAR_DEFAULT_IGNORABLE_CODE_POINT : UProperty = 5;
    const UCHAR_DEPRECATED : UProperty = 6;

    const UCHAR_DIACRITIC : UProperty = 7;
    const UCHAR_EXTENDER : UProperty = 8;
    const UCHAR_FULL_COMPOSITION_EXCLUSION : UProperty = 9;
    const UCHAR_GRAPHEME_BASE : UProperty = 10;

    const UCHAR_GRAPHEME_EXTEND : UProperty = 11;
    const UCHAR_GRAPHEME_LINK : UProperty = 12;
    const UCHAR_HEX_DIGIT : UProperty = 13;
    const UCHAR_HYPHEN : UProperty = 14;

    const UCHAR_ID_CONTINUE : UProperty = 15;
    const UCHAR_ID_START : UProperty = 16;
    const UCHAR_IDEOGRAPHIC : UProperty = 17;
    const UCHAR_IDS_BINARY_OPERATOR : UProperty = 18;

    const UCHAR_IDS_TRINARY_OPERATOR : UProperty = 19;
    const UCHAR_JOIN_CONTROL : UProperty = 20;
    const UCHAR_LOGICAL_ORDER_EXCEPTION : UProperty = 21;
    const UCHAR_LOWERCASE : UProperty = 22;

    const UCHAR_MATH : UProperty = 23;
    const UCHAR_NONCHARACTER_CODE_POINT : UProperty = 24;
    const UCHAR_QUOTATION_MARK : UProperty = 25;
    const UCHAR_RADICAL : UProperty = 26;

    const UCHAR_SOFT_DOTTED : UProperty = 27;
    const UCHAR_TERMINAL_PUNCTUATION : UProperty = 28;
    const UCHAR_UNIFIED_IDEOGRAPH : UProperty = 29;
    const UCHAR_UPPERCASE : UProperty = 30;

    const UCHAR_WHITE_SPACE : UProperty = 31;
    const UCHAR_XID_CONTINUE : UProperty = 32;
    const UCHAR_XID_START : UProperty = 33;
    const UCHAR_CASE_SENSITIVE : UProperty = 34;

    const UCHAR_S_TERM : UProperty = 35;
    const UCHAR_VARIATION_SELECTOR : UProperty = 36;
    const UCHAR_NFD_INERT : UProperty = 37;
    const UCHAR_NFKD_INERT : UProperty = 38;

    const UCHAR_NFC_INERT : UProperty = 39;
    const UCHAR_NFKC_INERT : UProperty = 40;
    const UCHAR_SEGMENT_STARTER : UProperty = 41;
    const UCHAR_PATTERN_SYNTAX : UProperty = 42;

    const UCHAR_PATTERN_WHITE_SPACE : UProperty = 43;
    const UCHAR_POSIX_ALNUM : UProperty = 44;
    const UCHAR_POSIX_BLANK : UProperty = 45;
    const UCHAR_POSIX_GRAPH : UProperty = 46;

    const UCHAR_POSIX_PRINT : UProperty = 47;
    const UCHAR_POSIX_XDIGIT : UProperty = 48;
    const UCHAR_CASED : UProperty = 49;
    const UCHAR_CASE_IGNORABLE : UProperty = 50;

    const UCHAR_CHANGES_WHEN_LOWERCASED : UProperty = 51;
    const UCHAR_CHANGES_WHEN_UPPERCASED : UProperty = 52;
    const UCHAR_CHANGES_WHEN_TITLECASED : UProperty = 53;
    const UCHAR_CHANGES_WHEN_CASEFOLDED : UProperty = 54;

    const UCHAR_CHANGES_WHEN_CASEMAPPED : UProperty = 55;
    const UCHAR_CHANGES_WHEN_NFKC_CASEFOLDED : UProperty = 56;
    const UCHAR_BINARY_LIMIT : UProperty = 57;
    const UCHAR_BIDI_CLASS : UProperty = 0x1000;

    const UCHAR_INT_START : UProperty = 0x1000; // UCHAR_BIDI_CLASS
    const UCHAR_BLOCK : UProperty = 0x1001;
    const UCHAR_CANONICAL_COMBINING_CLASS : UProperty = 0x1002;
    const UCHAR_DECOMPOSITION_TYPE : UProperty = 0x1003;

    const UCHAR_EAST_ASIAN_WIDTH : UProperty = 0x1004;
    const UCHAR_GENERAL_CATEGORY : UProperty = 0x1005;
    const UCHAR_JOINING_GROUP : UProperty = 0x1006;
    const UCHAR_JOINING_TYPE : UProperty = 0x1007;

    const UCHAR_LINE_BREAK : UProperty = 0x1008;
    const UCHAR_NUMERIC_TYPE : UProperty = 0x1009;
    const UCHAR_SCRIPT : UProperty = 0x100A;
    const UCHAR_HANGUL_SYLLABLE_TYPE : UProperty = 0x100B;

    const UCHAR_NFD_QUICK_CHECK : UProperty = 0x100C;
    const UCHAR_NFKD_QUICK_CHECK : UProperty = 0x100D;
    const UCHAR_NFC_QUICK_CHECK : UProperty = 0x100E;
    const UCHAR_NFKC_QUICK_CHECK : UProperty = 0x100F;

    const UCHAR_LEAD_CANONICAL_COMBINING_CLASS : UProperty = 0x1010;
    const UCHAR_TRAIL_CANONICAL_COMBINING_CLASS : UProperty = 0x1011;
    const UCHAR_GRAPHEME_CLUSTER_BREAK : UProperty = 0x1012;
    const UCHAR_SENTENCE_BREAK : UProperty = 0x1013;

    const UCHAR_WORD_BREAK : UProperty = 0x1014;
    const UCHAR_INT_LIMIT : UProperty = 0x1015;

    const UCHAR_GENERAL_CATEGORY_MASK : UProperty = 0x2000;
    const UCHAR_MASK_START : UProperty = 0x2000;
    // = UCHAR_GENERAL_CATEGORY_MASK
    const UCHAR_MASK_LIMIT : UProperty = 0x2001;

    const UCHAR_NUMERIC_VALUE : UProperty = 0x3000;
    const UCHAR_DOUBLE_START : UProperty = 0x3000;
    // = UCHAR_NUMERIC_VALUE
    const UCHAR_DOUBLE_LIMIT : UProperty = 0x3001;

    const UCHAR_AGE : UProperty = 0x4000;
    const UCHAR_STRING_START : UProperty = 0x4000; // = UCHAR_AGE
    const UCHAR_BIDI_MIRRORING_GLYPH : UProperty = 0x4001;
    const UCHAR_CASE_FOLDING : UProperty = 0x4002;

    const UCHAR_ISO_COMMENT : UProperty = 0x4003;
    const UCHAR_LOWERCASE_MAPPING : UProperty = 0x4004;
    const UCHAR_NAME : UProperty = 0x4005;
    const UCHAR_SIMPLE_CASE_FOLDING : UProperty = 0x4006;

    const UCHAR_SIMPLE_LOWERCASE_MAPPING : UProperty = 0x4007;
    const UCHAR_SIMPLE_TITLECASE_MAPPING : UProperty = 0x4008;
    const UCHAR_SIMPLE_UPPERCASE_MAPPING : UProperty = 0x4009;
    const UCHAR_TITLECASE_MAPPING : UProperty = 0x400A;

    const UCHAR_UNICODE_1_NAME : UProperty = 0x400B;
    const UCHAR_UPPERCASE_MAPPING : UProperty = 0x400C;
    const UCHAR_STRING_LIMIT : UProperty = 0x400D;

    const UCHAR_SCRIPT_EXTENSIONS : UProperty = 0x7000;
    const UCHAR_OTHER_PROPERTY_START : UProperty = 0x7000;
    // = UCHAR_SCRIPT_EXTENSIONS;
    const UCHAR_OTHER_PROPERTY_LIMIT : UProperty = 0x7001;

    const UCHAR_INVALID_CODE : UProperty = 0xffffffff;
    // FIXME: should be -1, change when compiler supports negative
    // constants

    #[link_name = "icuuc"]
    #[abi = "cdecl"]
    native mod libicu {
        pure fn u_hasBinaryProperty(c: UChar32, which: UProperty) -> UBool;
        pure fn u_isdigit(c: UChar32) -> UBool;
        pure fn u_islower(c: UChar32) -> UBool;
        pure fn u_isspace(c: UChar32) -> UBool;
        pure fn u_isupper(c: UChar32) -> UBool;
        pure fn u_tolower(c: UChar32) -> UChar32;
        pure fn u_toupper(c: UChar32) -> UChar32;
    }
}

pure fn is_XID_start(c: char) -> bool {
    ret icu::libicu::u_hasBinaryProperty(c, icu::UCHAR_XID_START)
        == icu::TRUE;
}

pure fn is_XID_continue(c: char) -> bool {
    ret icu::libicu::u_hasBinaryProperty(c, icu::UCHAR_XID_START)
        == icu::TRUE;
}

/*
Function: is_digit

Returns true if a character is a digit.
*/
pure fn is_digit(c: char) -> bool {
    ret icu::libicu::u_isdigit(c) == icu::TRUE;
}

/*
Function: is_lower

Returns true if a character is a lowercase letter.
*/
pure fn is_lower(c: char) -> bool {
    ret icu::libicu::u_islower(c) == icu::TRUE;
}

/*
Function: is_space

Returns true if a character is space.
*/
pure fn is_space(c: char) -> bool {
    ret icu::libicu::u_isspace(c) == icu::TRUE;
}

/*
Function: is_upper

Returns true if a character is an uppercase letter.
*/
pure fn is_upper(c: char) -> bool {
    ret icu::libicu::u_isupper(c) == icu::TRUE;
}

#[cfg(test)]
mod tests {

    #[test]
    fn test_is_digit() {
        assert (unicode::icu::is_digit('0'));
        assert (!unicode::icu::is_digit('m'));
    }

    #[test]
    fn test_is_lower() {
        assert (unicode::icu::is_lower('m'));
        assert (!unicode::icu::is_lower('M'));
    }

    #[test]
    fn test_is_space() {
        assert (unicode::icu::is_space(' '));
        assert (!unicode::icu::is_space('m'));
    }

    #[test]
    fn test_is_upper() {
        assert (unicode::icu::is_upper('M'));
        assert (!unicode::icu::is_upper('m'));
    }
}<commit_msg>Write unicode::icu::UCHAR_INVALID_CODE as -1, removing a FIXME<commit_after>
mod icu {
    type UBool = u8;
    type UProperty = int;
    type UChar32 = char;

    const TRUE : u8 = 1u8;
    const FALSE : u8 = 1u8;

    const UCHAR_ALPHABETIC : UProperty = 0;
    const UCHAR_BINARY_START : UProperty = 0; // = UCHAR_ALPHABETIC
    const UCHAR_ASCII_HEX_DIGIT : UProperty = 1;
    const UCHAR_BIDI_CONTROL : UProperty = 2;

    const UCHAR_BIDI_MIRRORED : UProperty = 3;
    const UCHAR_DASH : UProperty = 4;
    const UCHAR_DEFAULT_IGNORABLE_CODE_POINT : UProperty = 5;
    const UCHAR_DEPRECATED : UProperty = 6;

    const UCHAR_DIACRITIC : UProperty = 7;
    const UCHAR_EXTENDER : UProperty = 8;
    const UCHAR_FULL_COMPOSITION_EXCLUSION : UProperty = 9;
    const UCHAR_GRAPHEME_BASE : UProperty = 10;

    const UCHAR_GRAPHEME_EXTEND : UProperty = 11;
    const UCHAR_GRAPHEME_LINK : UProperty = 12;
    const UCHAR_HEX_DIGIT : UProperty = 13;
    const UCHAR_HYPHEN : UProperty = 14;

    const UCHAR_ID_CONTINUE : UProperty = 15;
    const UCHAR_ID_START : UProperty = 16;
    const UCHAR_IDEOGRAPHIC : UProperty = 17;
    const UCHAR_IDS_BINARY_OPERATOR : UProperty = 18;

    const UCHAR_IDS_TRINARY_OPERATOR : UProperty = 19;
    const UCHAR_JOIN_CONTROL : UProperty = 20;
    const UCHAR_LOGICAL_ORDER_EXCEPTION : UProperty = 21;
    const UCHAR_LOWERCASE : UProperty = 22;

    const UCHAR_MATH : UProperty = 23;
    const UCHAR_NONCHARACTER_CODE_POINT : UProperty = 24;
    const UCHAR_QUOTATION_MARK : UProperty = 25;
    const UCHAR_RADICAL : UProperty = 26;

    const UCHAR_SOFT_DOTTED : UProperty = 27;
    const UCHAR_TERMINAL_PUNCTUATION : UProperty = 28;
    const UCHAR_UNIFIED_IDEOGRAPH : UProperty = 29;
    const UCHAR_UPPERCASE : UProperty = 30;

    const UCHAR_WHITE_SPACE : UProperty = 31;
    const UCHAR_XID_CONTINUE : UProperty = 32;
    const UCHAR_XID_START : UProperty = 33;
    const UCHAR_CASE_SENSITIVE : UProperty = 34;

    const UCHAR_S_TERM : UProperty = 35;
    const UCHAR_VARIATION_SELECTOR : UProperty = 36;
    const UCHAR_NFD_INERT : UProperty = 37;
    const UCHAR_NFKD_INERT : UProperty = 38;

    const UCHAR_NFC_INERT : UProperty = 39;
    const UCHAR_NFKC_INERT : UProperty = 40;
    const UCHAR_SEGMENT_STARTER : UProperty = 41;
    const UCHAR_PATTERN_SYNTAX : UProperty = 42;

    const UCHAR_PATTERN_WHITE_SPACE : UProperty = 43;
    const UCHAR_POSIX_ALNUM : UProperty = 44;
    const UCHAR_POSIX_BLANK : UProperty = 45;
    const UCHAR_POSIX_GRAPH : UProperty = 46;

    const UCHAR_POSIX_PRINT : UProperty = 47;
    const UCHAR_POSIX_XDIGIT : UProperty = 48;
    const UCHAR_CASED : UProperty = 49;
    const UCHAR_CASE_IGNORABLE : UProperty = 50;

    const UCHAR_CHANGES_WHEN_LOWERCASED : UProperty = 51;
    const UCHAR_CHANGES_WHEN_UPPERCASED : UProperty = 52;
    const UCHAR_CHANGES_WHEN_TITLECASED : UProperty = 53;
    const UCHAR_CHANGES_WHEN_CASEFOLDED : UProperty = 54;

    const UCHAR_CHANGES_WHEN_CASEMAPPED : UProperty = 55;
    const UCHAR_CHANGES_WHEN_NFKC_CASEFOLDED : UProperty = 56;
    const UCHAR_BINARY_LIMIT : UProperty = 57;
    const UCHAR_BIDI_CLASS : UProperty = 0x1000;

    const UCHAR_INT_START : UProperty = 0x1000; // UCHAR_BIDI_CLASS
    const UCHAR_BLOCK : UProperty = 0x1001;
    const UCHAR_CANONICAL_COMBINING_CLASS : UProperty = 0x1002;
    const UCHAR_DECOMPOSITION_TYPE : UProperty = 0x1003;

    const UCHAR_EAST_ASIAN_WIDTH : UProperty = 0x1004;
    const UCHAR_GENERAL_CATEGORY : UProperty = 0x1005;
    const UCHAR_JOINING_GROUP : UProperty = 0x1006;
    const UCHAR_JOINING_TYPE : UProperty = 0x1007;

    const UCHAR_LINE_BREAK : UProperty = 0x1008;
    const UCHAR_NUMERIC_TYPE : UProperty = 0x1009;
    const UCHAR_SCRIPT : UProperty = 0x100A;
    const UCHAR_HANGUL_SYLLABLE_TYPE : UProperty = 0x100B;

    const UCHAR_NFD_QUICK_CHECK : UProperty = 0x100C;
    const UCHAR_NFKD_QUICK_CHECK : UProperty = 0x100D;
    const UCHAR_NFC_QUICK_CHECK : UProperty = 0x100E;
    const UCHAR_NFKC_QUICK_CHECK : UProperty = 0x100F;

    const UCHAR_LEAD_CANONICAL_COMBINING_CLASS : UProperty = 0x1010;
    const UCHAR_TRAIL_CANONICAL_COMBINING_CLASS : UProperty = 0x1011;
    const UCHAR_GRAPHEME_CLUSTER_BREAK : UProperty = 0x1012;
    const UCHAR_SENTENCE_BREAK : UProperty = 0x1013;

    const UCHAR_WORD_BREAK : UProperty = 0x1014;
    const UCHAR_INT_LIMIT : UProperty = 0x1015;

    const UCHAR_GENERAL_CATEGORY_MASK : UProperty = 0x2000;
    const UCHAR_MASK_START : UProperty = 0x2000;
    // = UCHAR_GENERAL_CATEGORY_MASK
    const UCHAR_MASK_LIMIT : UProperty = 0x2001;

    const UCHAR_NUMERIC_VALUE : UProperty = 0x3000;
    const UCHAR_DOUBLE_START : UProperty = 0x3000;
    // = UCHAR_NUMERIC_VALUE
    const UCHAR_DOUBLE_LIMIT : UProperty = 0x3001;

    const UCHAR_AGE : UProperty = 0x4000;
    const UCHAR_STRING_START : UProperty = 0x4000; // = UCHAR_AGE
    const UCHAR_BIDI_MIRRORING_GLYPH : UProperty = 0x4001;
    const UCHAR_CASE_FOLDING : UProperty = 0x4002;

    const UCHAR_ISO_COMMENT : UProperty = 0x4003;
    const UCHAR_LOWERCASE_MAPPING : UProperty = 0x4004;
    const UCHAR_NAME : UProperty = 0x4005;
    const UCHAR_SIMPLE_CASE_FOLDING : UProperty = 0x4006;

    const UCHAR_SIMPLE_LOWERCASE_MAPPING : UProperty = 0x4007;
    const UCHAR_SIMPLE_TITLECASE_MAPPING : UProperty = 0x4008;
    const UCHAR_SIMPLE_UPPERCASE_MAPPING : UProperty = 0x4009;
    const UCHAR_TITLECASE_MAPPING : UProperty = 0x400A;

    const UCHAR_UNICODE_1_NAME : UProperty = 0x400B;
    const UCHAR_UPPERCASE_MAPPING : UProperty = 0x400C;
    const UCHAR_STRING_LIMIT : UProperty = 0x400D;

    const UCHAR_SCRIPT_EXTENSIONS : UProperty = 0x7000;
    const UCHAR_OTHER_PROPERTY_START : UProperty = 0x7000;
    // = UCHAR_SCRIPT_EXTENSIONS;
    const UCHAR_OTHER_PROPERTY_LIMIT : UProperty = 0x7001;

    const UCHAR_INVALID_CODE : UProperty = -1;

    #[link_name = "icuuc"]
    #[abi = "cdecl"]
    native mod libicu {
        pure fn u_hasBinaryProperty(c: UChar32, which: UProperty) -> UBool;
        pure fn u_isdigit(c: UChar32) -> UBool;
        pure fn u_islower(c: UChar32) -> UBool;
        pure fn u_isspace(c: UChar32) -> UBool;
        pure fn u_isupper(c: UChar32) -> UBool;
        pure fn u_tolower(c: UChar32) -> UChar32;
        pure fn u_toupper(c: UChar32) -> UChar32;
    }
}

pure fn is_XID_start(c: char) -> bool {
    ret icu::libicu::u_hasBinaryProperty(c, icu::UCHAR_XID_START)
        == icu::TRUE;
}

pure fn is_XID_continue(c: char) -> bool {
    ret icu::libicu::u_hasBinaryProperty(c, icu::UCHAR_XID_START)
        == icu::TRUE;
}

/*
Function: is_digit

Returns true if a character is a digit.
*/
pure fn is_digit(c: char) -> bool {
    ret icu::libicu::u_isdigit(c) == icu::TRUE;
}

/*
Function: is_lower

Returns true if a character is a lowercase letter.
*/
pure fn is_lower(c: char) -> bool {
    ret icu::libicu::u_islower(c) == icu::TRUE;
}

/*
Function: is_space

Returns true if a character is space.
*/
pure fn is_space(c: char) -> bool {
    ret icu::libicu::u_isspace(c) == icu::TRUE;
}

/*
Function: is_upper

Returns true if a character is an uppercase letter.
*/
pure fn is_upper(c: char) -> bool {
    ret icu::libicu::u_isupper(c) == icu::TRUE;
}

#[cfg(test)]
mod tests {

    #[test]
    fn test_is_digit() {
        assert (unicode::icu::is_digit('0'));
        assert (!unicode::icu::is_digit('m'));
    }

    #[test]
    fn test_is_lower() {
        assert (unicode::icu::is_lower('m'));
        assert (!unicode::icu::is_lower('M'));
    }

    #[test]
    fn test_is_space() {
        assert (unicode::icu::is_space(' '));
        assert (!unicode::icu::is_space('m'));
    }

    #[test]
    fn test_is_upper() {
        assert (unicode::icu::is_upper('M'));
        assert (!unicode::icu::is_upper('m'));
    }
}<|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-azdo"]

#![crate_type = "lib"]
#![allow(dead_code)]
#![feature(phase)]
#![feature(unsafe_destructor)]

//extern crate debug;

extern crate collections;
extern crate time;
extern crate libc;
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" as render_data;

use std::comm::{Receiver, Sender};
use std::mem;
use std::sync::{TaskPool, Arc};
use std::thread::{JoinGuard, Builder};
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<R> {
    Update(R),
    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 (w, h) = dl.io_state().size;

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

        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<R: Renderable+Send>(command: Receiver<RenderCommand<R>>,
                 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 thread = Builder::new().name("render-thread".to_string());

    let (send_drawlist_setup, receiver_drawlist_setup) = channel();
    let (send_drawlist_ready, receiver_drawlist_ready) = channel();
    thread.spawn(move || {
        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(db) = db {
                let dl = drawlists_ready.pop().unwrap();
                let scene = db.scene().expect("no scene set");
                dl.setup_compute(&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<R> {
    ch: Sender<RenderCommand<R>>,
    render_done: Option<JoinGuard<()>>
}

impl<R: Renderable+Send> RenderManager<R> {
    fn _new(window: Window, size: (i32, i32), dev: Option<Arc<Device>>) -> RenderManager<R> {
        let thread = Builder::new().name("render-server".to_string());

        let (sender, receiver) = channel();
        let render_main_result = thread.spawn(move || {
            let window = window;
            render_server(receiver, window, size, dev.clone());
        });

        RenderManager {
            ch: sender,
            render_done: Some(render_main_result)
        }
    }

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

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

    pub fn update(&mut self, db: R) {
        self.ch.send(RenderCommand::Update(db));
    }
}

#[unsafe_destructor]
impl<R: Renderable+Send> Drop for RenderManager<R> {
    fn drop(&mut self) {
        self.ch.send(RenderCommand::Finish);
        let _ = self.render_done.take().expect("no render_done").join();
    }
}

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

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

#[deriving(Copy)]
pub struct RenderFactory;

impl RenderFactory {
    pub fn new() -> RenderFactory { RenderFactory }
}<commit_msg>fix azdo render<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-azdo"]

#![crate_type = "lib"]
#![allow(dead_code)]
#![feature(phase)]
#![feature(unsafe_destructor)]

//extern crate debug;

extern crate collections;
extern crate time;
extern crate libc;
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" as render_data;

use std::comm::{Receiver, Sender};
use std::mem;
use std::sync::{TaskPool, Arc};
use std::thread::{JoinGuard, Builder};
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<R> {
    Update(R),
    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 (w, h) = dl.io_state().size;

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

        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<R: Renderable+Send>(command: Receiver<RenderCommand<R>>,
                 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 thread = Builder::new().name("render-thread".to_string());

    let (send_drawlist_setup, receiver_drawlist_setup) = channel();
    let (send_drawlist_ready, receiver_drawlist_ready) = channel();
    let guard = thread.spawn(move || {
        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(db) = db {
                let dl = drawlists_ready.pop().unwrap();
                let scene = db.scene().expect("no scene set");
                dl.setup_compute(&db, &mut taskpool, scene, send_drawlist_render.clone());
            }
            db = None;
        }
    }
    guard.join();
}

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<R> {
    ch: Sender<RenderCommand<R>>,
    render_done: Option<JoinGuard<()>>
}

impl<R: Renderable+Send> RenderManager<R> {
    fn _new(window: Window, size: (i32, i32), dev: Option<Arc<Device>>) -> RenderManager<R> {
        let thread = Builder::new().name("render-server".to_string());

        let (sender, receiver) = channel();
        let render_main_result = thread.spawn(move || {
            let window = window;
            render_server(receiver, window, size, dev.clone());
        });

        RenderManager {
            ch: sender,
            render_done: Some(render_main_result)
        }
    }

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

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

    pub fn update(&mut self, db: R) {
        self.ch.send(RenderCommand::Update(db));
    }
}

#[unsafe_destructor]
impl<R: Renderable+Send> Drop for RenderManager<R> {
    fn drop(&mut self) {
        self.ch.send(RenderCommand::Finish);
        let _ = self.render_done.take().expect("no render_done").join();
    }
}

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

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

#[deriving(Copy)]
pub struct RenderFactory;

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


<commit_before>//! A simple crate for executing work on a thread pool, and getting back a
//! future.
//!
//! This crate provides a simple thread pool abstraction for running work
//! externally from the current thread that's running. An instance of `Future`
//! is handed back to represent that the work may be done later, and further
//! computations can be chained along with it as well.
//!
//! ```rust
//! extern crate futures;
//! extern crate futures_cpupool;
//!
//! use futures::Future;
//! use futures_cpupool::CpuPool;
//!
//! # fn long_running_future(a: u32) -> futures::future::BoxFuture<u32, ()> {
//! #     futures::future::result(Ok(a)).boxed()
//! # }
//! # fn main() {
//!
//! // Create a worker thread pool with four threads
//! let pool = CpuPool::new(4);
//!
//! // Execute some work on the thread pool, optionally closing over data.
//! let a = pool.spawn(long_running_future(2));
//! let b = pool.spawn(long_running_future(100));
//!
//! // Express some further computation once the work is completed on the thread
//! // pool.
//! let c = a.join(b).map(|(a, b)| a + b).wait().unwrap();
//!
//! // Print out the result
//! println!("{:?}", c);
//! # }
//! ```

#![deny(missing_docs)]
#![deny(missing_debug_implementations)]

extern crate futures;
extern crate num_cpus;

use std::panic::{self, AssertUnwindSafe};
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::mpsc;
use std::thread;
use std::fmt;

use futures::{IntoFuture, Future, Poll, Async};
use futures::future::{lazy, Executor, ExecuteError};
use futures::sync::oneshot::{channel, Sender, Receiver};
use futures::executor::{self, Run, Executor as OldExecutor};

/// A thread pool intended to run CPU intensive work.
///
/// This thread pool will hand out futures representing the completed work
/// that happens on the thread pool itself, and the futures can then be later
/// composed with other work as part of an overall computation.
///
/// The worker threads associated with a thread pool are kept alive so long as
/// there is an open handle to the `CpuPool` or there is work running on them. Once
/// all work has been drained and all references have gone away the worker
/// threads will be shut down.
///
/// Currently `CpuPool` implements `Clone` which just clones a new reference to
/// the underlying thread pool.
///
/// **Note:** if you use CpuPool inside a library it's better accept a
/// `Builder` object for thread configuration rather than configuring just
/// pool size.  This not only future proof for other settings but also allows
/// user to attach monitoring tools to lifecycle hooks.
pub struct CpuPool {
    inner: Arc<Inner>,
}

/// Thread pool configuration object
///
/// Builder starts with a number of workers equal to the number
/// of CPUs on the host. But you can change it until you call `create()`.
pub struct Builder {
    pool_size: usize,
    name_prefix: Option<String>,
    after_start: Option<Arc<Fn() + Send + Sync>>,
    before_stop: Option<Arc<Fn() + Send + Sync>>,
}

struct MySender<F, T> {
    fut: F,
    tx: Option<Sender<T>>,
    keep_running_flag: Arc<AtomicBool>,
}

trait AssertSendSync: Send + Sync {}
impl AssertSendSync for CpuPool {}

struct Inner {
    tx: Mutex<mpsc::Sender<Message>>,
    rx: Mutex<mpsc::Receiver<Message>>,
    cnt: AtomicUsize,
    size: usize,
    after_start: Option<Arc<Fn() + Send + Sync>>,
    before_stop: Option<Arc<Fn() + Send + Sync>>,
}

impl fmt::Debug for CpuPool {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("CpuPool")
            .field("size", &self.inner.size)
            .finish()
    }
}

impl fmt::Debug for Builder {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Builder")
            .field("pool_size", &self.pool_size)
            .field("name_prefix", &self.name_prefix)
            .finish()
    }
}

/// The type of future returned from the `CpuPool::spawn` function, which
/// proxies the futures running on the thread pool.
///
/// This future will resolve in the same way as the underlying future, and it
/// will propagate panics.
#[must_use]
#[derive(Debug)]
pub struct CpuFuture<T, E> {
    inner: Receiver<thread::Result<Result<T, E>>>,
    keep_running_flag: Arc<AtomicBool>,
}

enum Message {
    Run(Run),
    Close,
}

impl CpuPool {
    /// Creates a new thread pool with `size` worker threads associated with it.
    ///
    /// The returned handle can use `execute` to run work on this thread pool,
    /// and clones can be made of it to get multiple references to the same
    /// thread pool.
    ///
    /// This is a shortcut for:
    ///
    /// ```rust
    /// # use futures_cpupool::{Builder, CpuPool};
    /// #
    /// # fn new(size: usize) -> CpuPool {
    /// Builder::new().pool_size(size).create()
    /// # }
    /// ```
    ///
    /// # Panics
    ///
    /// Panics if `size == 0`.
    pub fn new(size: usize) -> CpuPool {
        Builder::new().pool_size(size).create()
    }

    /// Creates a new thread pool with a number of workers equal to the number
    /// of CPUs on the host.
    ///
    /// This is a shortcut for:
    ///
    /// ```rust
    /// # use futures_cpupool::{Builder, CpuPool};
    /// #
    /// # fn new_num_cpus() -> CpuPool {
    /// Builder::new().create()
    /// # }
    /// ```
    pub fn new_num_cpus() -> CpuPool {
        Builder::new().create()
    }

    /// Spawns a future to run on this thread pool, returning a future
    /// representing the produced value.
    ///
    /// This function will execute the future `f` on the associated thread
    /// pool, and return a future representing the finished computation. The
    /// returned future serves as a proxy to the computation that `F` is
    /// running.
    ///
    /// To simply run an arbitrary closure on a thread pool and extract the
    /// result, you can use the `future::lazy` combinator to defer work to
    /// executing on the thread pool itself.
    ///
    /// Note that if the future `f` panics it will be caught by default and the
    /// returned future will propagate the panic. That is, panics will not tear
    /// down the thread pool and will be propagated to the returned future's
    /// `poll` method if queried.
    ///
    /// If the returned future is dropped then this `CpuPool` will attempt to
    /// cancel the computation, if possible. That is, if the computation is in
    /// the middle of working, it will be interrupted when possible.
    pub fn spawn<F>(&self, f: F) -> CpuFuture<F::Item, F::Error>
        where F: Future + Send + 'static,
              F::Item: Send + 'static,
              F::Error: Send + 'static,
    {
        let (tx, rx) = channel();
        let keep_running_flag = Arc::new(AtomicBool::new(false));
        // AssertUnwindSafe is used here because `Send + 'static` is basically
        // an alias for an implementation of the `UnwindSafe` trait but we can't
        // express that in the standard library right now.
        let sender = MySender {
            fut: AssertUnwindSafe(f).catch_unwind(),
            tx: Some(tx),
            keep_running_flag: keep_running_flag.clone(),
        };
        executor::spawn(sender).execute(self.inner.clone());
        CpuFuture { inner: rx , keep_running_flag: keep_running_flag.clone() }
    }

    /// Spawns a closure on this thread pool.
    ///
    /// This function is a convenience wrapper around the `spawn` function above
    /// for running a closure wrapped in `future::lazy`. It will spawn the
    /// function `f` provided onto the thread pool, and continue to run the
    /// future returned by `f` on the thread pool as well.
    ///
    /// The returned future will be a handle to the result produced by the
    /// future that `f` returns.
    pub fn spawn_fn<F, R>(&self, f: F) -> CpuFuture<R::Item, R::Error>
        where F: FnOnce() -> R + Send + 'static,
              R: IntoFuture + 'static,
              R::Future: Send + 'static,
              R::Item: Send + 'static,
              R::Error: Send + 'static,
    {
        self.spawn(lazy(f))
    }
}

impl<F> Executor<F> for CpuPool
    where F: Future<Item = (), Error = ()> + Send + 'static,
{
    fn execute(&self, future: F) -> Result<(), ExecuteError<F>> {
        executor::spawn(future).execute(self.inner.clone());
        Ok(())
    }
}

impl Inner {
    fn send(&self, msg: Message) {
        self.tx.lock().unwrap().send(msg).unwrap();
    }

    fn work(&self) {
        self.after_start.as_ref().map(|fun| fun());
        loop {
            let msg = self.rx.lock().unwrap().recv().unwrap();
            match msg {
                Message::Run(r) => r.run(),
                Message::Close => break,
            }
        }
        self.before_stop.as_ref().map(|fun| fun());
    }
}

impl Clone for CpuPool {
    fn clone(&self) -> CpuPool {
        self.inner.cnt.fetch_add(1, Ordering::Relaxed);
        CpuPool { inner: self.inner.clone() }
    }
}

impl Drop for CpuPool {
    fn drop(&mut self) {
        if self.inner.cnt.fetch_sub(1, Ordering::Relaxed) == 1 {
            for _ in 0..self.inner.size {
                self.inner.send(Message::Close);
            }
        }
    }
}

impl OldExecutor for Inner {
    fn execute(&self, run: Run) {
        self.send(Message::Run(run))
    }
}

impl<T, E> CpuFuture<T, E> {
    /// Drop this future without canceling the underlying future.
    ///
    /// When `CpuFuture` is dropped, `CpuPool` will try to abort the underlying
    /// future. This function can be used when user wants to drop but keep
    /// executing the underlying future.
    pub fn forget(self) {
        self.keep_running_flag.store(true, Ordering::SeqCst);
    }
}

impl<T: Send + 'static, E: Send + 'static> Future for CpuFuture<T, E> {
    type Item = T;
    type Error = E;

    fn poll(&mut self) -> Poll<T, E> {
        match self.inner.poll().expect("shouldn't be canceled") {
            Async::Ready(Ok(Ok(e))) => Ok(e.into()),
            Async::Ready(Ok(Err(e))) => Err(e),
            Async::Ready(Err(e)) => panic::resume_unwind(e),
            Async::NotReady => Ok(Async::NotReady),
        }
    }
}

impl<F: Future> Future for MySender<F, Result<F::Item, F::Error>> {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<(), ()> {
        if let Ok(Async::Ready(_)) = self.tx.as_mut().unwrap().poll_cancel() {
            if !self.keep_running_flag.load(Ordering::SeqCst) {
                // Cancelled, bail out
                return Ok(().into())
            }
        }

        let res = match self.fut.poll() {
            Ok(Async::Ready(e)) => Ok(e),
            Ok(Async::NotReady) => return Ok(Async::NotReady),
            Err(e) => Err(e),
        };

        // if the receiving end has gone away then that's ok, we just ignore the
        // send error here.
        drop(self.tx.take().unwrap().send(res));
        Ok(Async::Ready(()))
    }
}

impl Builder {
    /// Create a builder a number of workers equal to the number
    /// of CPUs on the host.
    pub fn new() -> Builder {
        Builder {
            pool_size: num_cpus::get(),
            name_prefix: None,
            after_start: None,
            before_stop: None,
        }
    }

    /// Set size of a future CpuPool
    ///
    /// The size of a thread pool is the number of worker threads spawned
    pub fn pool_size(&mut self, size: usize) -> &mut Self {
        self.pool_size = size;
        self
    }

    /// Set thread name prefix of a future CpuPool
    ///
    /// Thread name prefix is used for generating thread names. For example, if prefix is
    /// `my-pool-`, then threads in the pool will get names like `my-pool-1` etc.
    pub fn name_prefix<S: Into<String>>(&mut self, name_prefix: S) -> &mut Self {
        self.name_prefix = Some(name_prefix.into());
        self
    }

    /// Execute function `f` right after each thread is started but before
    /// running any jobs on it
    ///
    /// This is initially intended for bookkeeping and monitoring uses
    pub fn after_start<F>(&mut self, f: F) -> &mut Self
        where F: Fn() + Send + Sync + 'static
    {
        self.after_start = Some(Arc::new(f));
        self
    }

    /// Execute function `f` before each worker thread stops
    ///
    /// This is initially intended for bookkeeping and monitoring uses
    pub fn before_stop<F>(&mut self, f: F) -> &mut Self
        where F: Fn() + Send + Sync + 'static
    {
        self.before_stop = Some(Arc::new(f));
        self
    }

    /// Create CpuPool with configured parameters
    ///
    /// # Panics
    ///
    /// Panics if `pool_size == 0`.
    pub fn create(&mut self) -> CpuPool {
        let (tx, rx) = mpsc::channel();
        let pool = CpuPool {
            inner: Arc::new(Inner {
                tx: Mutex::new(tx),
                rx: Mutex::new(rx),
                cnt: AtomicUsize::new(1),
                size: self.pool_size,
                after_start: self.after_start.clone(),
                before_stop: self.before_stop.clone(),
            }),
        };
        assert!(self.pool_size > 0);

        for counter in 0..self.pool_size {
            let inner = pool.inner.clone();
            let mut thread_builder = thread::Builder::new();
            if let Some(ref name_prefix) = self.name_prefix {
                thread_builder = thread_builder.name(format!("{}{}", name_prefix, counter));
            }
            thread_builder.spawn(move || inner.work()).unwrap();
        }

        return pool
    }
}
<commit_msg>Drop `after_start` and `before_stop` after they are called.<commit_after>//! A simple crate for executing work on a thread pool, and getting back a
//! future.
//!
//! This crate provides a simple thread pool abstraction for running work
//! externally from the current thread that's running. An instance of `Future`
//! is handed back to represent that the work may be done later, and further
//! computations can be chained along with it as well.
//!
//! ```rust
//! extern crate futures;
//! extern crate futures_cpupool;
//!
//! use futures::Future;
//! use futures_cpupool::CpuPool;
//!
//! # fn long_running_future(a: u32) -> futures::future::BoxFuture<u32, ()> {
//! #     futures::future::result(Ok(a)).boxed()
//! # }
//! # fn main() {
//!
//! // Create a worker thread pool with four threads
//! let pool = CpuPool::new(4);
//!
//! // Execute some work on the thread pool, optionally closing over data.
//! let a = pool.spawn(long_running_future(2));
//! let b = pool.spawn(long_running_future(100));
//!
//! // Express some further computation once the work is completed on the thread
//! // pool.
//! let c = a.join(b).map(|(a, b)| a + b).wait().unwrap();
//!
//! // Print out the result
//! println!("{:?}", c);
//! # }
//! ```

#![deny(missing_docs)]
#![deny(missing_debug_implementations)]

extern crate futures;
extern crate num_cpus;

use std::panic::{self, AssertUnwindSafe};
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::mpsc;
use std::thread;
use std::fmt;

use futures::{IntoFuture, Future, Poll, Async};
use futures::future::{lazy, Executor, ExecuteError};
use futures::sync::oneshot::{channel, Sender, Receiver};
use futures::executor::{self, Run, Executor as OldExecutor};

/// A thread pool intended to run CPU intensive work.
///
/// This thread pool will hand out futures representing the completed work
/// that happens on the thread pool itself, and the futures can then be later
/// composed with other work as part of an overall computation.
///
/// The worker threads associated with a thread pool are kept alive so long as
/// there is an open handle to the `CpuPool` or there is work running on them. Once
/// all work has been drained and all references have gone away the worker
/// threads will be shut down.
///
/// Currently `CpuPool` implements `Clone` which just clones a new reference to
/// the underlying thread pool.
///
/// **Note:** if you use CpuPool inside a library it's better accept a
/// `Builder` object for thread configuration rather than configuring just
/// pool size.  This not only future proof for other settings but also allows
/// user to attach monitoring tools to lifecycle hooks.
pub struct CpuPool {
    inner: Arc<Inner>,
}

/// Thread pool configuration object
///
/// Builder starts with a number of workers equal to the number
/// of CPUs on the host. But you can change it until you call `create()`.
pub struct Builder {
    pool_size: usize,
    name_prefix: Option<String>,
    after_start: Option<Arc<Fn() + Send + Sync>>,
    before_stop: Option<Arc<Fn() + Send + Sync>>,
}

struct MySender<F, T> {
    fut: F,
    tx: Option<Sender<T>>,
    keep_running_flag: Arc<AtomicBool>,
}

trait AssertSendSync: Send + Sync {}
impl AssertSendSync for CpuPool {}

struct Inner {
    tx: Mutex<mpsc::Sender<Message>>,
    rx: Mutex<mpsc::Receiver<Message>>,
    cnt: AtomicUsize,
    size: usize,
}

impl fmt::Debug for CpuPool {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("CpuPool")
            .field("size", &self.inner.size)
            .finish()
    }
}

impl fmt::Debug for Builder {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Builder")
            .field("pool_size", &self.pool_size)
            .field("name_prefix", &self.name_prefix)
            .finish()
    }
}

/// The type of future returned from the `CpuPool::spawn` function, which
/// proxies the futures running on the thread pool.
///
/// This future will resolve in the same way as the underlying future, and it
/// will propagate panics.
#[must_use]
#[derive(Debug)]
pub struct CpuFuture<T, E> {
    inner: Receiver<thread::Result<Result<T, E>>>,
    keep_running_flag: Arc<AtomicBool>,
}

enum Message {
    Run(Run),
    Close,
}

impl CpuPool {
    /// Creates a new thread pool with `size` worker threads associated with it.
    ///
    /// The returned handle can use `execute` to run work on this thread pool,
    /// and clones can be made of it to get multiple references to the same
    /// thread pool.
    ///
    /// This is a shortcut for:
    ///
    /// ```rust
    /// # use futures_cpupool::{Builder, CpuPool};
    /// #
    /// # fn new(size: usize) -> CpuPool {
    /// Builder::new().pool_size(size).create()
    /// # }
    /// ```
    ///
    /// # Panics
    ///
    /// Panics if `size == 0`.
    pub fn new(size: usize) -> CpuPool {
        Builder::new().pool_size(size).create()
    }

    /// Creates a new thread pool with a number of workers equal to the number
    /// of CPUs on the host.
    ///
    /// This is a shortcut for:
    ///
    /// ```rust
    /// # use futures_cpupool::{Builder, CpuPool};
    /// #
    /// # fn new_num_cpus() -> CpuPool {
    /// Builder::new().create()
    /// # }
    /// ```
    pub fn new_num_cpus() -> CpuPool {
        Builder::new().create()
    }

    /// Spawns a future to run on this thread pool, returning a future
    /// representing the produced value.
    ///
    /// This function will execute the future `f` on the associated thread
    /// pool, and return a future representing the finished computation. The
    /// returned future serves as a proxy to the computation that `F` is
    /// running.
    ///
    /// To simply run an arbitrary closure on a thread pool and extract the
    /// result, you can use the `future::lazy` combinator to defer work to
    /// executing on the thread pool itself.
    ///
    /// Note that if the future `f` panics it will be caught by default and the
    /// returned future will propagate the panic. That is, panics will not tear
    /// down the thread pool and will be propagated to the returned future's
    /// `poll` method if queried.
    ///
    /// If the returned future is dropped then this `CpuPool` will attempt to
    /// cancel the computation, if possible. That is, if the computation is in
    /// the middle of working, it will be interrupted when possible.
    pub fn spawn<F>(&self, f: F) -> CpuFuture<F::Item, F::Error>
        where F: Future + Send + 'static,
              F::Item: Send + 'static,
              F::Error: Send + 'static,
    {
        let (tx, rx) = channel();
        let keep_running_flag = Arc::new(AtomicBool::new(false));
        // AssertUnwindSafe is used here because `Send + 'static` is basically
        // an alias for an implementation of the `UnwindSafe` trait but we can't
        // express that in the standard library right now.
        let sender = MySender {
            fut: AssertUnwindSafe(f).catch_unwind(),
            tx: Some(tx),
            keep_running_flag: keep_running_flag.clone(),
        };
        executor::spawn(sender).execute(self.inner.clone());
        CpuFuture { inner: rx , keep_running_flag: keep_running_flag.clone() }
    }

    /// Spawns a closure on this thread pool.
    ///
    /// This function is a convenience wrapper around the `spawn` function above
    /// for running a closure wrapped in `future::lazy`. It will spawn the
    /// function `f` provided onto the thread pool, and continue to run the
    /// future returned by `f` on the thread pool as well.
    ///
    /// The returned future will be a handle to the result produced by the
    /// future that `f` returns.
    pub fn spawn_fn<F, R>(&self, f: F) -> CpuFuture<R::Item, R::Error>
        where F: FnOnce() -> R + Send + 'static,
              R: IntoFuture + 'static,
              R::Future: Send + 'static,
              R::Item: Send + 'static,
              R::Error: Send + 'static,
    {
        self.spawn(lazy(f))
    }
}

impl<F> Executor<F> for CpuPool
    where F: Future<Item = (), Error = ()> + Send + 'static,
{
    fn execute(&self, future: F) -> Result<(), ExecuteError<F>> {
        executor::spawn(future).execute(self.inner.clone());
        Ok(())
    }
}

impl Inner {
    fn send(&self, msg: Message) {
        self.tx.lock().unwrap().send(msg).unwrap();
    }

    fn work(&self, after_start: Option<Arc<Fn() + Send + Sync>>, before_stop: Option<Arc<Fn() + Send + Sync>>) {
        after_start.map(|fun| fun());
        loop {
            let msg = self.rx.lock().unwrap().recv().unwrap();
            match msg {
                Message::Run(r) => r.run(),
                Message::Close => break,
            }
        }
        before_stop.map(|fun| fun());
    }
}

impl Clone for CpuPool {
    fn clone(&self) -> CpuPool {
        self.inner.cnt.fetch_add(1, Ordering::Relaxed);
        CpuPool { inner: self.inner.clone() }
    }
}

impl Drop for CpuPool {
    fn drop(&mut self) {
        if self.inner.cnt.fetch_sub(1, Ordering::Relaxed) == 1 {
            for _ in 0..self.inner.size {
                self.inner.send(Message::Close);
            }
        }
    }
}

impl OldExecutor for Inner {
    fn execute(&self, run: Run) {
        self.send(Message::Run(run))
    }
}

impl<T, E> CpuFuture<T, E> {
    /// Drop this future without canceling the underlying future.
    ///
    /// When `CpuFuture` is dropped, `CpuPool` will try to abort the underlying
    /// future. This function can be used when user wants to drop but keep
    /// executing the underlying future.
    pub fn forget(self) {
        self.keep_running_flag.store(true, Ordering::SeqCst);
    }
}

impl<T: Send + 'static, E: Send + 'static> Future for CpuFuture<T, E> {
    type Item = T;
    type Error = E;

    fn poll(&mut self) -> Poll<T, E> {
        match self.inner.poll().expect("shouldn't be canceled") {
            Async::Ready(Ok(Ok(e))) => Ok(e.into()),
            Async::Ready(Ok(Err(e))) => Err(e),
            Async::Ready(Err(e)) => panic::resume_unwind(e),
            Async::NotReady => Ok(Async::NotReady),
        }
    }
}

impl<F: Future> Future for MySender<F, Result<F::Item, F::Error>> {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<(), ()> {
        if let Ok(Async::Ready(_)) = self.tx.as_mut().unwrap().poll_cancel() {
            if !self.keep_running_flag.load(Ordering::SeqCst) {
                // Cancelled, bail out
                return Ok(().into())
            }
        }

        let res = match self.fut.poll() {
            Ok(Async::Ready(e)) => Ok(e),
            Ok(Async::NotReady) => return Ok(Async::NotReady),
            Err(e) => Err(e),
        };

        // if the receiving end has gone away then that's ok, we just ignore the
        // send error here.
        drop(self.tx.take().unwrap().send(res));
        Ok(Async::Ready(()))
    }
}

impl Builder {
    /// Create a builder a number of workers equal to the number
    /// of CPUs on the host.
    pub fn new() -> Builder {
        Builder {
            pool_size: num_cpus::get(),
            name_prefix: None,
            after_start: None,
            before_stop: None,
        }
    }

    /// Set size of a future CpuPool
    ///
    /// The size of a thread pool is the number of worker threads spawned
    pub fn pool_size(&mut self, size: usize) -> &mut Self {
        self.pool_size = size;
        self
    }

    /// Set thread name prefix of a future CpuPool
    ///
    /// Thread name prefix is used for generating thread names. For example, if prefix is
    /// `my-pool-`, then threads in the pool will get names like `my-pool-1` etc.
    pub fn name_prefix<S: Into<String>>(&mut self, name_prefix: S) -> &mut Self {
        self.name_prefix = Some(name_prefix.into());
        self
    }

    /// Execute function `f` right after each thread is started but before
    /// running any jobs on it
    ///
    /// This is initially intended for bookkeeping and monitoring uses
    pub fn after_start<F>(&mut self, f: F) -> &mut Self
        where F: Fn() + Send + Sync + 'static
    {
        self.after_start = Some(Arc::new(f));
        self
    }

    /// Execute function `f` before each worker thread stops
    ///
    /// This is initially intended for bookkeeping and monitoring uses
    pub fn before_stop<F>(&mut self, f: F) -> &mut Self
        where F: Fn() + Send + Sync + 'static
    {
        self.before_stop = Some(Arc::new(f));
        self
    }

    /// Create CpuPool with configured parameters
    ///
    /// # Panics
    ///
    /// Panics if `pool_size == 0`.
    pub fn create(&mut self) -> CpuPool {
        let (tx, rx) = mpsc::channel();
        let pool = CpuPool {
            inner: Arc::new(Inner {
                tx: Mutex::new(tx),
                rx: Mutex::new(rx),
                cnt: AtomicUsize::new(1),
                size: self.pool_size,
            }),
        };
        assert!(self.pool_size > 0);

        for counter in 0..self.pool_size {
            let inner = pool.inner.clone();
            let after_start = self.after_start.clone();
            let before_stop = self.before_stop.clone();
            let mut thread_builder = thread::Builder::new();
            if let Some(ref name_prefix) = self.name_prefix {
                thread_builder = thread_builder.name(format!("{}{}", name_prefix, counter));
            }
            thread_builder.spawn(move || inner.work(after_start, before_stop)).unwrap();
        }
        return pool
    }
}

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

    #[test]
    fn test_drop_after_start() {
        let (tx, rx) = mpsc::sync_channel(2);
        let cpu_pool = Builder::new()
            .pool_size(2)
            .after_start(move || tx.send(1).unwrap()).create();

        // After Builder is deconstructed, the tx should be droped
        // so that we can use rx as an iterator.
        let count = rx.into_iter().count();
        assert_eq!(count, 2);
    }
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::iter::IntoIterator;
use std::marker::PhantomData;

use math::{self, FScalar};
use super::primitive::{Polygon, Polygonal, Primitive, Triangle, Quad};

pub struct Decompose
where
    D: Copy,
    F: Fn(P, D) -> R,
    R: IntoIterator<Item = Q>,
{
    input: I,
    output: VecDeque<Q>,
    parameter: D,
    f: F,
    phantom: PhantomData<(P, R)>,
}

impl Decompose
where
    D: Copy,
    F: Fn(P, D) -> R,
    R: IntoIterator<Item = Q>,
{
    pub(super) fn new(input: I, parameter: D, f: F) -> Self {
        Decompose {
            input: input,
            output: VecDeque::new(),
            parameter: parameter,
            f: f,
            phantom: PhantomData,
        }
    }
}

impl Iterator for Decompose
where
    I: Iterator<Item = P>,
    D: Copy,
    F: Fn(P, D) -> R,
    R: IntoIterator<Item = Q>,
{
    type Item = Q;

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            if let Some(polygon) = self.output.pop_front() {
                return Some(polygon);
            }
            if let Some(polygon) = self.input.next() {
                self.output.extend((self.f)(polygon, self.parameter));
            }
            else {
                return None;
            }
        }
    }
}

pub trait Interpolate: math::Interpolate<FScalar> {}

impl<T> Interpolate for T
where
    T: math::Interpolate<FScalar>,
{
}

pub trait IntoSubdivisions: Polygonal
where
    Self::Point: Clone + Interpolate,
{
    fn into_subdivisions<F>(self, n: usize, f: F)
    where
        F: FnMut(Self);
}

pub trait IntoTetrahedrons: Polygonal
where
    Self::Point: Clone + Interpolate,
{
    fn into_tetrahedrons<F>(self, f: F)
    where
        F: FnMut(Triangle<Self::Point>);
}

impl<T> IntoSubdivisions for Triangle<T>
where
    T: Clone + Interpolate,
{
    fn into_subdivisions<F>(self, n: usize, mut f: F)
    where
        F: FnMut(Self),
    {
        for triangle in n_map_polygon(n, self, |triangle| {
            let Triangle { a, b, c } = triangle;
            let ac = a.midpoint(&c);
            vec![
                Triangle::new(b.clone(), ac.clone(), a),
                Triangle::new(c, ac, b),
            ]
        }) {
            f(triangle);
        }
    }
}

impl<T> IntoSubdivisions for Quad<T>
where
    T: Clone + Interpolate,
{
    fn into_subdivisions<F>(self, n: usize, mut f: F)
    where
        F: FnMut(Self),
    {
        for quad in n_map_polygon(n, self, |quad| {
            let Quad { a, b, c, d } = quad;
            let ab = a.midpoint(&b);
            let bc = b.midpoint(&c);
            let cd = c.midpoint(&d);
            let da = d.midpoint(&a);
            let ac = a.midpoint(&c); // Diagonal.
            vec![
                Quad::new(a, ab.clone(), ac.clone(), da.clone()),
                Quad::new(ab, b, bc.clone(), ac.clone()),
                Quad::new(ac.clone(), bc, c, cd.clone()),
                Quad::new(da, ac, cd, d),
            ]
        }) {
            f(quad);
        }
    }
}

impl<T> IntoTetrahedrons for Quad<T>
where
    T: Clone + Interpolate,
{
    fn into_tetrahedrons<F>(self, mut f: F)
    where
        F: FnMut(Triangle<Self::Point>),
    {
        let Quad { a, b, c, d } = self;
        let ac = a.midpoint(&c); // Diagonal.
        f(Triangle::new(a.clone(), b.clone(), ac.clone()));
        f(Triangle::new(b, c.clone(), ac.clone()));
        f(Triangle::new(c, d.clone(), ac.clone()));
        f(Triangle::new(d, a, ac));
    }
}

impl<T> IntoSubdivisions for Polygon<T>
where
    T: Clone + Interpolate,
{
    fn into_subdivisions<F>(self, n: usize, mut f: F)
    where
        F: FnMut(Self),
    {
        match self {
            Polygon::Triangle(triangle) => {
                triangle.into_subdivisions(n, |triangle| f(triangle.into()));
            }
            Polygon::Quad(quad) => {
                quad.into_subdivisions(n, |quad| f(quad.into()));
            }
        }
    }
}

pub trait Points
: Sized
where
    P: Primitive,
{
    fn points(self) -> Decompose<Self, P, P::Point, (), Vec
, fn(P, ()) -> Vec
>;
}

impl Points
 for I
where
    I: Iterator<Item = P>,
    P: Primitive<Point = T>,
    T: Clone,
{
    fn points(self) -> Decompose<Self, P, P::Point, (), Vec
, fn(P, ()) -> Vec
> {
        Decompose::new(self, (), into_points)
    }
}

pub trait Triangulate
: Sized
where
    P: Polygonal,
{
    fn triangulate(
        self,
    ) -> Decompose<
        Self,
        P,
        Triangle
,
        (),
        Vec<Triangle
>,
        fn(P, ()) -> Vec<Triangle
>,
    >;
}

impl Triangulate
 for I
where
    I: Iterator<Item = P>,
    P: Polygonal<Point = T>,
    T: Clone,
{
    fn triangulate(
        self,
    ) -> Decompose<
        Self,
        P,
        Triangle
,
        (),
        Vec<Triangle
>,
        fn(P, ()) -> Vec<Triangle
>,
    > {
        Decompose::new(self, (), into_triangles)
    }
}

pub trait Subdivide
: Sized
where
    P: Polygonal,
{
    fn subdivide(self, n: usize) -> Decompose<Self, P, P, usize, Vec
, fn(P, usize) -> Vec
>;
}

impl Subdivide
 for I
where
    I: Iterator<Item = P>,
    P: IntoSubdivisions<Point = T>,
    T: Clone + Interpolate,
{
    fn subdivide(self, n: usize) -> Decompose<Self, P, P, usize, Vec
, fn(P, usize) -> Vec
> {
        Decompose::new(self, n, into_subdivisions)
    }
}

pub trait Tetrahedrons<T>: Sized {
    fn tetrahedrons(
        self,
    ) -> Decompose<
        Self,
        Quad<T>,
        Triangle<T>,
        (),
        Vec<Triangle<T>>,
        fn(Quad<T>, ()) -> Vec<Triangle<T>>,
    >;
}

impl Tetrahedrons<T> for I
where
    I: Iterator<Item = Quad<T>>,
    T: Clone + Interpolate,
{
    fn tetrahedrons(
        self,
    ) -> Decompose<
        Self,
        Quad<T>,
        Triangle<T>,
        (),
        Vec<Triangle<T>>,
        fn(Quad<T>, ()) -> Vec<Triangle<T>>,
    > {
        Decompose::new(self, (), into_tetrahedrons)
    }
}

fn into_points
(primitive: P, _: ()) -> Vec<T>
where
    P: Primitive<Point = T>,
    T: Clone,
{
    let mut points = vec![];
    primitive.into_points(|point| points.push(point));
    points
}

fn into_triangles
(polygon: P, _: ()) -> Vec<Triangle<T>>
where
    P: Polygonal<Point = T>,
    T: Clone,
{
    let mut triangles = vec![];
    polygon.into_triangles(|triangle| triangles.push(triangle));
    triangles
}

fn into_subdivisions
(polygon: P, n: usize) -> Vec

where
    P: IntoSubdivisions<Point = T>,
    T: Clone + Interpolate,
{
    let mut polygons = vec![];
    polygon.into_subdivisions(n, |polygon| polygons.push(polygon));
    polygons
}

fn into_tetrahedrons<T>(quad: Quad<T>, _: ()) -> Vec<Triangle<T>>
where
    T: Clone + Interpolate,
{
    let mut triangles = vec![];
    quad.into_tetrahedrons(|triangle| triangles.push(triangle));
    triangles
}

fn n_map_polygon<T, P, F>(n: usize, polygon: P, f: F) -> Vec

where
    P: Polygonal<Point = T>,
    T: Clone,
    F: Fn(P) -> Vec
,
{
    let mut queued = vec![];
    let mut transformed = vec![polygon];
    for _ in 0..n {
        queued.extend(transformed.drain(..));
        while let Some(polygon) = queued.pop() {
            transformed.extend(f(polygon));
        }
    }
    transformed
}
<commit_msg>Remove type parameter `F` from `Decompose` iterator.<commit_after>use std::collections::VecDeque;
use std::iter::IntoIterator;

use math::{self, FScalar};
use super::primitive::{Polygon, Polygonal, Primitive, Triangle, Quad};

// A type `F` constrained to `Fn(P, D) -> R` could be used here, but it would
// not be possible to name that type for anything but functions (not closures).
// Instead of a limited and somewhat redundant type `F`, just use `fn(P, D) ->
// R` for the member `f`.
pub struct Decompose
where
    D: Copy,
    R: IntoIterator<Item = Q>,
{
    input: I,
    output: VecDeque<Q>,
    parameter: D,
    f: fn(P, D) -> R,
}

impl Decompose
where
    D: Copy,
    R: IntoIterator<Item = Q>,
{
    pub(super) fn new(input: I, parameter: D, f: fn(P, D) -> R) -> Self {
        Decompose {
            input: input,
            output: VecDeque::new(),
            parameter: parameter,
            f: f,
        }
    }
}

impl Iterator for Decompose
where
    I: Iterator<Item = P>,
    D: Copy,
    R: IntoIterator<Item = Q>,
{
    type Item = Q;

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            if let Some(polygon) = self.output.pop_front() {
                return Some(polygon);
            }
            if let Some(polygon) = self.input.next() {
                self.output.extend((self.f)(polygon, self.parameter));
            }
            else {
                return None;
            }
        }
    }
}

pub trait Interpolate: math::Interpolate<FScalar> {}

impl<T> Interpolate for T
where
    T: math::Interpolate<FScalar>,
{
}

pub trait IntoSubdivisions: Polygonal
where
    Self::Point: Clone + Interpolate,
{
    fn into_subdivisions<F>(self, n: usize, f: F)
    where
        F: FnMut(Self);
}

pub trait IntoTetrahedrons: Polygonal
where
    Self::Point: Clone + Interpolate,
{
    fn into_tetrahedrons<F>(self, f: F)
    where
        F: FnMut(Triangle<Self::Point>);
}

impl<T> IntoSubdivisions for Triangle<T>
where
    T: Clone + Interpolate,
{
    fn into_subdivisions<F>(self, n: usize, mut f: F)
    where
        F: FnMut(Self),
    {
        for triangle in n_map_polygon(n, self, |triangle| {
            let Triangle { a, b, c } = triangle;
            let ac = a.midpoint(&c);
            vec![
                Triangle::new(b.clone(), ac.clone(), a),
                Triangle::new(c, ac, b),
            ]
        }) {
            f(triangle);
        }
    }
}

impl<T> IntoSubdivisions for Quad<T>
where
    T: Clone + Interpolate,
{
    fn into_subdivisions<F>(self, n: usize, mut f: F)
    where
        F: FnMut(Self),
    {
        for quad in n_map_polygon(n, self, |quad| {
            let Quad { a, b, c, d } = quad;
            let ab = a.midpoint(&b);
            let bc = b.midpoint(&c);
            let cd = c.midpoint(&d);
            let da = d.midpoint(&a);
            let ac = a.midpoint(&c); // Diagonal.
            vec![
                Quad::new(a, ab.clone(), ac.clone(), da.clone()),
                Quad::new(ab, b, bc.clone(), ac.clone()),
                Quad::new(ac.clone(), bc, c, cd.clone()),
                Quad::new(da, ac, cd, d),
            ]
        }) {
            f(quad);
        }
    }
}

impl<T> IntoTetrahedrons for Quad<T>
where
    T: Clone + Interpolate,
{
    fn into_tetrahedrons<F>(self, mut f: F)
    where
        F: FnMut(Triangle<Self::Point>),
    {
        let Quad { a, b, c, d } = self;
        let ac = a.midpoint(&c); // Diagonal.
        f(Triangle::new(a.clone(), b.clone(), ac.clone()));
        f(Triangle::new(b, c.clone(), ac.clone()));
        f(Triangle::new(c, d.clone(), ac.clone()));
        f(Triangle::new(d, a, ac));
    }
}

impl<T> IntoSubdivisions for Polygon<T>
where
    T: Clone + Interpolate,
{
    fn into_subdivisions<F>(self, n: usize, mut f: F)
    where
        F: FnMut(Self),
    {
        match self {
            Polygon::Triangle(triangle) => {
                triangle.into_subdivisions(n, |triangle| f(triangle.into()));
            }
            Polygon::Quad(quad) => {
                quad.into_subdivisions(n, |quad| f(quad.into()));
            }
        }
    }
}

pub trait Points
: Sized
where
    P: Primitive,
{
    fn points(self) -> Decompose<Self, P, P::Point, (), Vec
>;
}

impl Points
 for I
where
    I: Iterator<Item = P>,
    P: Primitive<Point = T>,
    T: Clone,
{
    fn points(self) -> Decompose<Self, P, P::Point, (), Vec
> {
        Decompose::new(self, (), into_points)
    }
}

pub trait Triangulate
: Sized
where
    P: Polygonal,
{
    fn triangulate(self) -> Decompose<Self, P, Triangle
, (), Vec<Triangle
>>;
}

impl Triangulate
 for I
where
    I: Iterator<Item = P>,
    P: Polygonal<Point = T>,
    T: Clone,
{
    fn triangulate(self) -> Decompose<Self, P, Triangle
, (), Vec<Triangle
>> {
        Decompose::new(self, (), into_triangles)
    }
}

pub trait Subdivide
: Sized
where
    P: Polygonal,
{
    fn subdivide(self, n: usize) -> Decompose<Self, P, P, usize, Vec
>;
}

impl Subdivide
 for I
where
    I: Iterator<Item = P>,
    P: IntoSubdivisions<Point = T>,
    T: Clone + Interpolate,
{
    fn subdivide(self, n: usize) -> Decompose<Self, P, P, usize, Vec
> {
        Decompose::new(self, n, into_subdivisions)
    }
}

pub trait Tetrahedrons<T>: Sized {
    fn tetrahedrons(self) -> Decompose<Self, Quad<T>, Triangle<T>, (), Vec<Triangle<T>>>;
}

impl Tetrahedrons<T> for I
where
    I: Iterator<Item = Quad<T>>,
    T: Clone + Interpolate,
{
    fn tetrahedrons(self) -> Decompose<Self, Quad<T>, Triangle<T>, (), Vec<Triangle<T>>> {
        Decompose::new(self, (), into_tetrahedrons)
    }
}

fn into_points
(primitive: P, _: ()) -> Vec<T>
where
    P: Primitive<Point = T>,
    T: Clone,
{
    let mut points = vec![];
    primitive.into_points(|point| points.push(point));
    points
}

fn into_triangles
(polygon: P, _: ()) -> Vec<Triangle<T>>
where
    P: Polygonal<Point = T>,
    T: Clone,
{
    let mut triangles = vec![];
    polygon.into_triangles(|triangle| triangles.push(triangle));
    triangles
}

fn into_subdivisions
(polygon: P, n: usize) -> Vec

where
    P: IntoSubdivisions<Point = T>,
    T: Clone + Interpolate,
{
    let mut polygons = vec![];
    polygon.into_subdivisions(n, |polygon| polygons.push(polygon));
    polygons
}

fn into_tetrahedrons<T>(quad: Quad<T>, _: ()) -> Vec<Triangle<T>>
where
    T: Clone + Interpolate,
{
    let mut triangles = vec![];
    quad.into_tetrahedrons(|triangle| triangles.push(triangle));
    triangles
}

fn n_map_polygon<T, P, F>(n: usize, polygon: P, f: F) -> Vec

where
    P: Polygonal<Point = T>,
    T: Clone,
    F: Fn(P) -> Vec
,
{
    let mut queued = vec![];
    let mut transformed = vec![polygon];
    for _ in 0..n {
        queued.extend(transformed.drain(..));
        while let Some(polygon) = queued.pop() {
            transformed.extend(f(polygon));
        }
    }
    transformed
}
<|endoftext|>


<commit_before>use nom::{IResult, Consumer, ConsumerState};
use metadata::parser::{header, block_data};

use std::collections::HashMap;

/// Data associated with a single metadata block.
#[derive(Debug)]
pub struct Block {
  /// Marks whether the current metadata block is the last.
  pub is_last: bool,
  /// The length, in bytes, of the block being parsed. This does not include
  /// the metadata block header.
  pub length: u32,
  /// Block data containing on of the eight different types of metadata.
  pub data: BlockData,
}

/// General enum that hold all the different metadata block data.
#[derive(Debug, PartialEq, Eq)]
pub enum BlockData {
  /// Information regarding the entire audio stream.
  StreamInfo(StreamInfo),
  /// Block that represents a number of padded bytes.
  Padding(u32),
  /// Data used by third-party applications.
  Application(Application),
  /// Table of multiple points to seek, or skip, to within the FLAC file.
  SeekTable(Vec<SeekPoint>),
  /// Stores human-readable name/value pairs.
  VorbisComment(VorbisComment),
  /// Stores cue information
  CueSheet(CueSheet),
  /// Stores pictures associated with the FLAC file.
  Picture(Picture),
  /// A type of block data that isn't know or doesn't match the type above.
  Unknown(Vec<u8>),
}

/// Information regarding the entire audio stream.
#[derive(Debug, PartialEq, Eq)]
pub struct StreamInfo {
  /// Minimum block size, in samples, used in the stream.
  pub min_block_size: u16,
  /// Maximum block size, in samples, used in the stream.
  pub max_block_size: u16,
  /// Minimum frame size, in bytes, used in the stream. May be zero to imply
  /// the value isn't know.
  pub min_frame_size: u32,
  /// Maximum frame size, in bytes, used in the stream. May be zero to imply
  /// the value isn't know.
  pub max_frame_size: u32,
  /// Sample rate in hertz (Hz).
  pub sample_rate: u32,
  /// Number of channels. FLAC supports one to eight channel.
  pub channels: u8,
  /// Bits per sample. FLAC supports four to thirty-two bits per sample.
  pub bits_per_sample: u8,
  /// Total samples in the stream. A value of zero means the number is
  /// unknown.
  pub total_samples: u64,
  /// MD5 signature of the unencoded audio data.
  pub md5_sum: [u8; 16],
}

impl StreamInfo {
  pub fn new() -> StreamInfo {
    StreamInfo {
      min_block_size: 0,
      max_block_size: 0,
      min_frame_size: 0,
      max_frame_size: 0,
      sample_rate: 0,
      channels: 0,
      bits_per_sample: 0,
      total_samples: 0,
      md5_sum: [0; 16],
    }
  }
}

/// Data used by third-party applications.
#[derive(Debug, PartialEq, Eq)]
pub struct Application {
  /// Registered application ID.
  pub id: String,
  /// Data used by the third-party application.
  pub data: Vec<u8>,
}

/// Seek, or skip, to a point within the FLAC file.
#[derive(Debug, PartialEq, Eq)]
pub struct SeekPoint {
  /// Sample number of the first sample in the target frame.
  pub sample_number: u64,
  /// Byte offset of the target frame's header.
  pub stream_offset: u64,
  /// Number of samples in the target frame.
  pub frame_samples: u16,
}

/// Stores human-readable name/value pairs.
#[derive(Debug, PartialEq, Eq)]
pub struct VorbisComment {
  /// Vendor name.
  pub vendor_string: String,
  /// Comments associated with a name, or category, followed by it's
  /// contents.
  pub comments: HashMap<String, String>,
}

/// Stores cue information.
///
/// Generally for storing information from Compact Disk Digital Audio, but
/// can be used as a cueing mechanism for playback.
#[derive(Debug, PartialEq, Eq)]
pub struct CueSheet {
  /// Media catalog number.
  pub media_catalog_number: String,
  /// Number of lead-in samples.
  pub lead_in: u64,
  /// Whether or not this `CueSheet` corresponds to a Compact Disc.
  pub is_cd: bool,
  /// One or more tracks.
  pub tracks: Vec<CueSheetTrack>,
}

/// Track information inside a cue sheet.
#[derive(Debug, PartialEq, Eq)]
pub struct CueSheetTrack {
  /// Track offset, in samples, relative to the beginning of the FLAC audio
  /// stream.
  pub offset: u64,
  /// Track number.
  pub number: u8,
  /// Twelve digit alphanumeric code.
  pub isrc: String,
  /// Whether the cue sheet track is audio.
  pub is_audio: bool,
  /// Whether the cue sheet track is pre-emphasis.
  pub is_pre_emphasis: bool,
  /// For all tracks except the lead-out track.
  pub indices: Vec<CueSheetTrackIndex>,
}

/// An index point within a track, inside of a cue sheet.
#[derive(Debug, PartialEq, Eq)]
pub struct CueSheetTrackIndex {
  /// Offset, in samples, relative to the track offset of the index point.
  pub offset: u64,
  /// Index point number.
  pub number: u8,
}

/// Stores pictures associated with the FLAC file.
///
/// More than likely these pictures will be cover art, but you can have more
/// than one within a file, which are distinguished by `PictureType`and it's
/// mime type string.
#[derive(Debug, PartialEq, Eq)]
pub struct Picture {
  /// Picture type, based on the ID3v2 APIC frame.
  pub picture_type: PictureType,
  /// Multipurpose Internet Mail Extensions (MIME) type.
  pub mime_type: String,
  /// A string describing the picture.
  pub description: String,
  /// Width of the picture in pixels.
  pub width: u32,
  /// Height of the picture in pixels.
  pub height: u32,
  /// Color depth of the picture in bits-per-pixel.
  pub depth: u32,
  /// Number of colors used.
  pub colors: u32,
  /// Binary picture data.
  pub data: Vec<u8>,
}

/// The picture type according to the ID3v2 attached picture frame.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum PictureType {
  /// Other picture type not categorized in this enum.
  Other,
  /// 32x32 pixels 'file icon'.
  FileIconStandard,
  /// Other, or non-standard, file icon.
  FileIcon,
  /// Cover (front).
  FrontCover,
  /// Cover (back).
  BackCover,
  /// Leaflet page.
  LeafletPage,
  /// Media, like label side of a CD.
  Media,
  /// Lead artist, lead performer, or soloist.
  LeadArtist,
  /// Artist or performer.
  Artist,
  /// Conductor.
  Conductor,
  /// Band or orchestra.
  Band,
  /// Composer.
  Composer,
  /// Lyricist or text writer.
  Lyricist,
  /// Recording location.
  RecordingLocation,
  /// During recording.
  DuringRecording,
  /// During performance.
  DuringPerformace,
  /// Movie, or video, screen capture.
  VideoScreenCapture,
  /// A bright colored fish.
  Fish,
  /// Illustration.
  Illustration,
  /// Band, or artist, logotype.
  BandLogo,
  /// Publisher, or studio, logotype.
  PublisherLogo,
}

enum ParserState {
  FLAC,
  Header,
  MetaData,
}

pub struct MetaDataConsumer {
  state: ParserState,
  is_last: bool,
  block_type: u8,
  length: u32,
  pub data: Vec<Block>
}

impl MetaDataConsumer {
  pub fn new() -> MetaDataConsumer {
    MetaDataConsumer {
      state: ParserState::FLAC,
      is_last: false,
      block_type: 127,
      length: 0,
      data: Vec::new(),
    }
  }
}

impl Consumer for MetaDataConsumer {
  fn consume(&mut self, input: &[u8]) -> ConsumerState {
    match self.state {
      ParserState::FLAC     => {
        match tag!(input, "fLaC") {
          IResult::Done(_, _) => {
            self.state = ParserState::Header;
            ConsumerState::Await(4, 4)
          }
          IResult::Error(_)      => ConsumerState::ConsumerError(0),
          IResult::Incomplete(_) => ConsumerState::Await(0, 4),
        }
      }
      ParserState::Header   => {
        match header(input) {
          IResult::Done(_, data) => {
            let (is_last, block_type, length) = data;

            self.state      = ParserState::MetaData;
            self.is_last    = is_last;
            self.block_type = block_type;
            self.length     = length;

            ConsumerState::Await(4, length as usize)
          }
          IResult::Error(_)      => ConsumerState::ConsumerError(0),
          IResult::Incomplete(_) => ConsumerState::Await(0, 4),
        }
      },
      ParserState::MetaData => {
        let length = self.length as usize;

        match block_data(input, self.block_type, self.length) {
          IResult::Done(_, data) => {
            self.data.push(Block {
              is_last: self.is_last,
              length: self.length,
              data: data,
            });

            if self.is_last {
              ConsumerState::ConsumerDone
            } else {
              self.state = ParserState::Header;

              ConsumerState::Await(length, 4)
            }
          }
          IResult::Error(_)      => ConsumerState::ConsumerError(0),
          IResult::Incomplete(_) => ConsumerState::Await(0, length),
        }
      }
    }
  }

  fn failed(&mut self, error_code: u32) {
    println!("Failed with error code: {}", error_code);
  }

  fn end(&mut self) {}
}
<commit_msg>Rename `ParserState` variants for clearer meaning<commit_after>use nom::{IResult, Consumer, ConsumerState};
use metadata::parser::{header, block_data};

use std::collections::HashMap;

/// Data associated with a single metadata block.
#[derive(Debug)]
pub struct Block {
  /// Marks whether the current metadata block is the last.
  pub is_last: bool,
  /// The length, in bytes, of the block being parsed. This does not include
  /// the metadata block header.
  pub length: u32,
  /// Block data containing on of the eight different types of metadata.
  pub data: BlockData,
}

/// General enum that hold all the different metadata block data.
#[derive(Debug, PartialEq, Eq)]
pub enum BlockData {
  /// Information regarding the entire audio stream.
  StreamInfo(StreamInfo),
  /// Block that represents a number of padded bytes.
  Padding(u32),
  /// Data used by third-party applications.
  Application(Application),
  /// Table of multiple points to seek, or skip, to within the FLAC file.
  SeekTable(Vec<SeekPoint>),
  /// Stores human-readable name/value pairs.
  VorbisComment(VorbisComment),
  /// Stores cue information
  CueSheet(CueSheet),
  /// Stores pictures associated with the FLAC file.
  Picture(Picture),
  /// A type of block data that isn't know or doesn't match the type above.
  Unknown(Vec<u8>),
}

/// Information regarding the entire audio stream.
#[derive(Debug, PartialEq, Eq)]
pub struct StreamInfo {
  /// Minimum block size, in samples, used in the stream.
  pub min_block_size: u16,
  /// Maximum block size, in samples, used in the stream.
  pub max_block_size: u16,
  /// Minimum frame size, in bytes, used in the stream. May be zero to imply
  /// the value isn't know.
  pub min_frame_size: u32,
  /// Maximum frame size, in bytes, used in the stream. May be zero to imply
  /// the value isn't know.
  pub max_frame_size: u32,
  /// Sample rate in hertz (Hz).
  pub sample_rate: u32,
  /// Number of channels. FLAC supports one to eight channel.
  pub channels: u8,
  /// Bits per sample. FLAC supports four to thirty-two bits per sample.
  pub bits_per_sample: u8,
  /// Total samples in the stream. A value of zero means the number is
  /// unknown.
  pub total_samples: u64,
  /// MD5 signature of the unencoded audio data.
  pub md5_sum: [u8; 16],
}

impl StreamInfo {
  pub fn new() -> StreamInfo {
    StreamInfo {
      min_block_size: 0,
      max_block_size: 0,
      min_frame_size: 0,
      max_frame_size: 0,
      sample_rate: 0,
      channels: 0,
      bits_per_sample: 0,
      total_samples: 0,
      md5_sum: [0; 16],
    }
  }
}

/// Data used by third-party applications.
#[derive(Debug, PartialEq, Eq)]
pub struct Application {
  /// Registered application ID.
  pub id: String,
  /// Data used by the third-party application.
  pub data: Vec<u8>,
}

/// Seek, or skip, to a point within the FLAC file.
#[derive(Debug, PartialEq, Eq)]
pub struct SeekPoint {
  /// Sample number of the first sample in the target frame.
  pub sample_number: u64,
  /// Byte offset of the target frame's header.
  pub stream_offset: u64,
  /// Number of samples in the target frame.
  pub frame_samples: u16,
}

/// Stores human-readable name/value pairs.
#[derive(Debug, PartialEq, Eq)]
pub struct VorbisComment {
  /// Vendor name.
  pub vendor_string: String,
  /// Comments associated with a name, or category, followed by it's
  /// contents.
  pub comments: HashMap<String, String>,
}

/// Stores cue information.
///
/// Generally for storing information from Compact Disk Digital Audio, but
/// can be used as a cueing mechanism for playback.
#[derive(Debug, PartialEq, Eq)]
pub struct CueSheet {
  /// Media catalog number.
  pub media_catalog_number: String,
  /// Number of lead-in samples.
  pub lead_in: u64,
  /// Whether or not this `CueSheet` corresponds to a Compact Disc.
  pub is_cd: bool,
  /// One or more tracks.
  pub tracks: Vec<CueSheetTrack>,
}

/// Track information inside a cue sheet.
#[derive(Debug, PartialEq, Eq)]
pub struct CueSheetTrack {
  /// Track offset, in samples, relative to the beginning of the FLAC audio
  /// stream.
  pub offset: u64,
  /// Track number.
  pub number: u8,
  /// Twelve digit alphanumeric code.
  pub isrc: String,
  /// Whether the cue sheet track is audio.
  pub is_audio: bool,
  /// Whether the cue sheet track is pre-emphasis.
  pub is_pre_emphasis: bool,
  /// For all tracks except the lead-out track.
  pub indices: Vec<CueSheetTrackIndex>,
}

/// An index point within a track, inside of a cue sheet.
#[derive(Debug, PartialEq, Eq)]
pub struct CueSheetTrackIndex {
  /// Offset, in samples, relative to the track offset of the index point.
  pub offset: u64,
  /// Index point number.
  pub number: u8,
}

/// Stores pictures associated with the FLAC file.
///
/// More than likely these pictures will be cover art, but you can have more
/// than one within a file, which are distinguished by `PictureType`and it's
/// mime type string.
#[derive(Debug, PartialEq, Eq)]
pub struct Picture {
  /// Picture type, based on the ID3v2 APIC frame.
  pub picture_type: PictureType,
  /// Multipurpose Internet Mail Extensions (MIME) type.
  pub mime_type: String,
  /// A string describing the picture.
  pub description: String,
  /// Width of the picture in pixels.
  pub width: u32,
  /// Height of the picture in pixels.
  pub height: u32,
  /// Color depth of the picture in bits-per-pixel.
  pub depth: u32,
  /// Number of colors used.
  pub colors: u32,
  /// Binary picture data.
  pub data: Vec<u8>,
}

/// The picture type according to the ID3v2 attached picture frame.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum PictureType {
  /// Other picture type not categorized in this enum.
  Other,
  /// 32x32 pixels 'file icon'.
  FileIconStandard,
  /// Other, or non-standard, file icon.
  FileIcon,
  /// Cover (front).
  FrontCover,
  /// Cover (back).
  BackCover,
  /// Leaflet page.
  LeafletPage,
  /// Media, like label side of a CD.
  Media,
  /// Lead artist, lead performer, or soloist.
  LeadArtist,
  /// Artist or performer.
  Artist,
  /// Conductor.
  Conductor,
  /// Band or orchestra.
  Band,
  /// Composer.
  Composer,
  /// Lyricist or text writer.
  Lyricist,
  /// Recording location.
  RecordingLocation,
  /// During recording.
  DuringRecording,
  /// During performance.
  DuringPerformace,
  /// Movie, or video, screen capture.
  VideoScreenCapture,
  /// A bright colored fish.
  Fish,
  /// Illustration.
  Illustration,
  /// Band, or artist, logotype.
  BandLogo,
  /// Publisher, or studio, logotype.
  PublisherLogo,
}

enum ParserState {
  Marker,
  Header,
  Block((bool, u8, u32)),
}

pub struct MetaDataConsumer {
  state: ParserState,
  is_last: bool,
  block_type: u8,
  length: u32,
  pub data: Vec<Block>
}

impl MetaDataConsumer {
  pub fn new() -> MetaDataConsumer {
    MetaDataConsumer {
      state: ParserState::FLAC,
      is_last: false,
      block_type: 127,
      length: 0,
      data: Vec::new(),
    }
  }
}

impl Consumer for MetaDataConsumer {
  fn consume(&mut self, input: &[u8]) -> ConsumerState {
    match self.state {
      ParserState::FLAC     => {
        match tag!(input, "fLaC") {
          IResult::Done(_, _) => {
            self.state = ParserState::Header;
            ConsumerState::Await(4, 4)
          }
          IResult::Error(_)      => ConsumerState::ConsumerError(0),
          IResult::Incomplete(_) => ConsumerState::Await(0, 4),
        }
      }
      ParserState::Header   => {
        match header(input) {
          IResult::Done(_, data) => {
            let (is_last, block_type, length) = data;

            self.state      = ParserState::MetaData;
            self.is_last    = is_last;
            self.block_type = block_type;
            self.length     = length;

            ConsumerState::Await(4, length as usize)
          }
          IResult::Error(_)      => ConsumerState::ConsumerError(0),
          IResult::Incomplete(_) => ConsumerState::Await(0, 4),
        }
      },
      ParserState::MetaData => {
        let length = self.length as usize;

        match block_data(input, self.block_type, self.length) {
          IResult::Done(_, data) => {
            self.data.push(Block {
              is_last: self.is_last,
              length: self.length,
              data: data,
            });

            if self.is_last {
              ConsumerState::ConsumerDone
            } else {
              self.state = ParserState::Header;

              ConsumerState::Await(length, 4)
            }
          }
          IResult::Error(_)      => ConsumerState::ConsumerError(0),
          IResult::Incomplete(_) => ConsumerState::Await(0, length),
        }
      }
    }
  }

  fn failed(&mut self, error_code: u32) {
    println!("Failed with error code: {}", error_code);
  }

  fn end(&mut self) {}
}
<|endoftext|>


<commit_before>// compile-flags: -C no-prepopulate-passes

#![crate_type = "lib"]
#![feature(c_variadic)]
#![feature(unwind_attributes)]
#![no_std]
use core::ffi::VaList;

extern "C" {
    fn foreign_c_variadic_0(_: i32, ...);
    fn foreign_c_variadic_1(_: VaList, ...);
}

#[unwind(aborts)] // FIXME(#58794)
pub unsafe extern "C" fn use_foreign_c_variadic_0() {
    // Ensure that we correctly call foreign C-variadic functions.
    // CHECK: invoke void (i32, ...) @foreign_c_variadic_0(i32 0)
    foreign_c_variadic_0(0);
    // CHECK: invoke void (i32, ...) @foreign_c_variadic_0(i32 0, i32 42)
    foreign_c_variadic_0(0, 42i32);
    // CHECK: invoke void (i32, ...) @foreign_c_variadic_0(i32 0, i32 42, i32 1024)
    foreign_c_variadic_0(0, 42i32, 1024i32);
    // CHECK: invoke void (i32, ...) @foreign_c_variadic_0(i32 0, i32 42, i32 1024, i32 0)
    foreign_c_variadic_0(0, 42i32, 1024i32, 0i32);
}

// Ensure that we do not remove the `va_list` passed to the foreign function when
// removing the "spoofed" `VaListImpl` that is used by Rust defined C-variadics.
#[unwind(aborts)] // FIXME(#58794)
pub unsafe extern "C" fn use_foreign_c_variadic_1_0(ap: VaList) {
    // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap)
    foreign_c_variadic_1(ap);
}

#[unwind(aborts)] // FIXME(#58794)
pub unsafe extern "C" fn use_foreign_c_variadic_1_1(ap: VaList) {
    // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, i32 42)
    foreign_c_variadic_1(ap, 42i32);
}
#[unwind(aborts)] // FIXME(#58794)
pub unsafe extern "C" fn use_foreign_c_variadic_1_2(ap: VaList) {
    // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, i32 2, i32 42)
    foreign_c_variadic_1(ap, 2i32, 42i32);
}

#[unwind(aborts)] // FIXME(#58794)
pub unsafe extern "C" fn use_foreign_c_variadic_1_3(ap: VaList) {
    // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, i32 2, i32 42, i32 0)
    foreign_c_variadic_1(ap, 2i32, 42i32, 0i32);
}

// Ensure that `va_start` and `va_end` are properly injected.
#[no_mangle]
pub unsafe extern "C" fn c_variadic(n: i32, mut ap: ...) -> i32 {
    // CHECK: call void @llvm.va_start
    let mut sum = 0;
    for _ in 0..n {
        sum += ap.arg::<i32>();
    }
    sum
    // CHECK: call void @llvm.va_end
}

// Ensure that we generate the correct `call` signature when calling a Rust
// defined C-variadic.
pub unsafe fn test_c_variadic_call() {
    // CHECK: call i32 (i32, ...) @c_variadic(i32 0)
    c_variadic(0);
    // CHECK: call i32 (i32, ...) @c_variadic(i32 0, i32 42)
    c_variadic(0, 42i32);
    // CHECK: call i32 (i32, ...) @c_variadic(i32 0, i32 42, i32 1024)
    c_variadic(0, 42i32, 1024i32);
    // CHECK: call i32 (i32, ...) @c_variadic(i32 0, i32 42, i32 1024, i32 0)
    c_variadic(0, 42i32, 1024i32, 0i32);
}
<commit_msg>test/c-variadic: Fix patterns on powerpc64<commit_after>// compile-flags: -C no-prepopulate-passes
// ignore-tidy-linelength

#![crate_type = "lib"]
#![feature(c_variadic)]
#![feature(unwind_attributes)]
#![no_std]
use core::ffi::VaList;

extern "C" {
    fn foreign_c_variadic_0(_: i32, ...);
    fn foreign_c_variadic_1(_: VaList, ...);
}

#[unwind(aborts)] // FIXME(#58794)
pub unsafe extern "C" fn use_foreign_c_variadic_0() {
    // Ensure that we correctly call foreign C-variadic functions.
    // CHECK: invoke void (i32, ...) @foreign_c_variadic_0([[PARAM:i32( signext)?]] 0)
    foreign_c_variadic_0(0);
    // CHECK: invoke void (i32, ...) @foreign_c_variadic_0([[PARAM]] 0, [[PARAM]] 42)
    foreign_c_variadic_0(0, 42i32);
    // CHECK: invoke void (i32, ...) @foreign_c_variadic_0([[PARAM]] 0, [[PARAM]] 42, [[PARAM]] 1024)
    foreign_c_variadic_0(0, 42i32, 1024i32);
    // CHECK: invoke void (i32, ...) @foreign_c_variadic_0([[PARAM]] 0, [[PARAM]] 42, [[PARAM]] 1024, [[PARAM]] 0)
    foreign_c_variadic_0(0, 42i32, 1024i32, 0i32);
}

// Ensure that we do not remove the `va_list` passed to the foreign function when
// removing the "spoofed" `VaListImpl` that is used by Rust defined C-variadics.
#[unwind(aborts)] // FIXME(#58794)
pub unsafe extern "C" fn use_foreign_c_variadic_1_0(ap: VaList) {
    // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap)
    foreign_c_variadic_1(ap);
}

#[unwind(aborts)] // FIXME(#58794)
pub unsafe extern "C" fn use_foreign_c_variadic_1_1(ap: VaList) {
    // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, [[PARAM]] 42)
    foreign_c_variadic_1(ap, 42i32);
}
#[unwind(aborts)] // FIXME(#58794)
pub unsafe extern "C" fn use_foreign_c_variadic_1_2(ap: VaList) {
    // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, [[PARAM]] 2, [[PARAM]] 42)
    foreign_c_variadic_1(ap, 2i32, 42i32);
}

#[unwind(aborts)] // FIXME(#58794)
pub unsafe extern "C" fn use_foreign_c_variadic_1_3(ap: VaList) {
    // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, [[PARAM]] 2, [[PARAM]] 42, [[PARAM]] 0)
    foreign_c_variadic_1(ap, 2i32, 42i32, 0i32);
}

// Ensure that `va_start` and `va_end` are properly injected.
#[no_mangle]
pub unsafe extern "C" fn c_variadic(n: i32, mut ap: ...) -> i32 {
    // CHECK: call void @llvm.va_start
    let mut sum = 0;
    for _ in 0..n {
        sum += ap.arg::<i32>();
    }
    sum
    // CHECK: call void @llvm.va_end
}

// Ensure that we generate the correct `call` signature when calling a Rust
// defined C-variadic.
pub unsafe fn test_c_variadic_call() {
    // CHECK: call [[RET:(signext )?i32]] (i32, ...) @c_variadic([[PARAM]] 0)
    c_variadic(0);
    // CHECK: call [[RET]] (i32, ...) @c_variadic([[PARAM]] 0, [[PARAM]] 42)
    c_variadic(0, 42i32);
    // CHECK: call [[RET]] (i32, ...) @c_variadic([[PARAM]] 0, [[PARAM]] 42, [[PARAM]] 1024)
    c_variadic(0, 42i32, 1024i32);
    // CHECK: call [[RET]] (i32, ...) @c_variadic([[PARAM]] 0, [[PARAM]] 42, [[PARAM]] 1024, [[PARAM]] 0)
    c_variadic(0, 42i32, 1024i32, 0i32);
}
<|endoftext|>