<commit_before>use cocoa::base::{id, nil};
use cocoa::foundation::{NSString, NSUInteger};
use objc::runtime::YES;
use sys::{MTLCopyAllDevices, MTLCreateSystemDefaultDevice, MTLDevice};
use std::borrow::Cow;
use std::convert::{AsRef, From};
use std::error::Error;
use std::ffi::CStr;
use std::fmt::{self, Display, Formatter};
use std::path::Path;
use {CommandQueue, CommandQueueError, CompileOptions, FromRaw, FromRawError, Library,
     LibraryError, Size};

pub struct Device(id);

impl Device {
    pub fn system_default_device() -> Result<Self, DeviceError> {
        let device = unsafe { MTLCreateSystemDefaultDevice() };
        if device != nil { Ok(Device(device)) } else { Err(DeviceError::ConstructionFailed) }
    }

    #[allow(unused_mut, unused_variables, unreachable_code)]
    pub fn enumerate_all_system_devices() -> Vec<Result<Self, DeviceError>> {
        let all_devices = unsafe { MTLCopyAllDevices() };
        let mut devices_vec = vec![];

        unimplemented!();

        devices_vec
    }

    pub fn new_command_queue(&mut self) -> Result<CommandQueue, CommandQueueError> {
        let command_queue = unsafe { self.0.newCommandQueue() };
        Ok(try!(FromRaw::from_raw(command_queue)))
    }

    pub fn new_command_queue_with_max_buffer_count(&mut self, max_command_buffer_count: usize)
                                                   -> Result<CommandQueue, CommandQueueError> {
        let command_queue = unsafe {
            self.0.newCommandQueueWithMaxCommandBufferCount(max_command_buffer_count as NSUInteger)
        };
        Ok(try!(FromRaw::from_raw(command_queue)))
    }

    #[allow(unused_variables)]
    pub fn new_default_library(&mut self) -> Result<Library, LibraryError> {
        unimplemented!();
    }

    #[allow(unused_variables)]
    pub fn new_library_with_file<P: AsRef<Path>>(&mut self, file_path: P)
                                                 -> Result<Library, LibraryError> {
        unimplemented!();
    }

    pub fn new_library_with_source<S: AsRef<str>>(&mut self, source: S,
                                                  compile_options: &CompileOptions)
                                                  -> Result<Library, LibraryError> {
        unsafe {
            let source = NSString::alloc(nil).init_str(source.as_ref());
            let options = compile_options.mtl_compile_options();
            let error = nil;
            let library = self.0.newLibraryWithSource_options_error(source, options, error);
            if error != nil {
                // Todo(George): Should use the `error` variable to get more info
                Err(LibraryError::SourceError)
            } else {
                Ok(try!(FromRaw::from_raw(library)))
            }
        }
    }

    #[allow(unused_variables)]
    // Todo(George): `data` parameter should be of the correct type
    pub fn new_library_with_data(&mut self, data: ()) -> Result<Library, LibraryError> {
        unimplemented!();
    }

    pub fn is_depth24_stencil8_pixel_format_supported(&self) -> bool {
        unsafe { self.0.depth24Stencil8PixelFormatSupported() == YES }
    }

    pub fn is_headless(&self) -> bool {
        unsafe { self.0.headless() == YES }
    }

    pub fn is_low_power(&self) -> bool {
        unsafe { self.0.lowPower() == YES }
    }

    pub fn max_threads_per_group(&self) -> Size {
        unsafe { self.0.maxThreadsPerGroup().into() }
    }

    pub fn get_name(&self) -> Cow<str> {
        unsafe { CStr::from_ptr(self.0.name().UTF8String()).to_string_lossy() }
    }

    pub fn supports_texture_sample_count(&self, sample_count: usize) -> bool {
        unsafe { self.0.supportsTextureSampleCount(sample_count as NSUInteger) == YES }
    }
}

impl_from_into_raw!(Device, "MTLDevice");

/// Internal utility function to get a Device's id without consuming it.
/// Not exported publicly from this crate.
#[doc(hidden)]
pub unsafe fn _device_get_raw(device: &Device) -> id {
    device.0
}

#[derive(Clone, Debug)]
pub enum DeviceError {
    ConstructionFailed,
    RawError(FromRawError)
}

impl From<FromRawError> for DeviceError {
    fn from(error: FromRawError) -> Self {
        DeviceError::RawError(error)
    }
}

impl Display for DeviceError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let descr = match *self {
            DeviceError::ConstructionFailed => "DeviceError::ConstructionFailed",
            DeviceError::RawError(_) => "DeviceError::ConstructionFailed",
        };
        write!(f, "{}", descr)
    }
}

impl Error for DeviceError {
    fn description(&self) -> &str {
        match *self {
            DeviceError::ConstructionFailed => {
                "Could not create a default device. Please ensure that you are using at least OSX \
                 10.11 or iOS 8.0"
            }
            DeviceError::RawError(_) => "There was an error with the device pointer",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match self {
            &DeviceError::ConstructionFailed => None,
            &DeviceError::RawError(ref raw_err) => Some(raw_err),
        }
    }
}
<commit_msg>Implement Device::new_default_library<commit_after>use cocoa::base::{id, nil};
use cocoa::foundation::{NSString, NSUInteger};
use objc::runtime::YES;
use sys::{MTLCopyAllDevices, MTLCreateSystemDefaultDevice, MTLDevice};
use std::borrow::Cow;
use std::convert::{AsRef, From};
use std::error::Error;
use std::ffi::CStr;
use std::fmt::{self, Display, Formatter};
use std::path::Path;
use {CommandQueue, CommandQueueError, CompileOptions, FromRaw, FromRawError, Library,
     LibraryError, Size};

pub struct Device(id);

impl Device {
    pub fn system_default_device() -> Result<Self, DeviceError> {
        let device = unsafe { MTLCreateSystemDefaultDevice() };
        if device != nil { Ok(Device(device)) } else { Err(DeviceError::ConstructionFailed) }
    }

    #[allow(unused_mut, unused_variables, unreachable_code)]
    pub fn enumerate_all_system_devices() -> Vec<Result<Self, DeviceError>> {
        let all_devices = unsafe { MTLCopyAllDevices() };
        let mut devices_vec = vec![];

        unimplemented!();

        devices_vec
    }

    pub fn new_command_queue(&mut self) -> Result<CommandQueue, CommandQueueError> {
        let command_queue = unsafe { self.0.newCommandQueue() };
        Ok(try!(FromRaw::from_raw(command_queue)))
    }

    pub fn new_command_queue_with_max_buffer_count(&mut self, max_command_buffer_count: usize)
                                                   -> Result<CommandQueue, CommandQueueError> {
        let command_queue = unsafe {
            self.0.newCommandQueueWithMaxCommandBufferCount(max_command_buffer_count as NSUInteger)
        };
        Ok(try!(FromRaw::from_raw(command_queue)))
    }

    #[allow(unused_variables)]
    pub fn new_default_library(&mut self) -> Result<Library, LibraryError> {
        unsafe {
            let library = self.0.newDefaultLibrary();
            Ok(try!(FromRaw::from_raw(library)))
        }
    }

    #[allow(unused_variables)]
    pub fn new_library_with_file<P: AsRef<Path>>(&mut self, file_path: P)
                                                 -> Result<Library, LibraryError> {
        unimplemented!();
    }

    pub fn new_library_with_source<S: AsRef<str>>(&mut self, source: S,
                                                  compile_options: &CompileOptions)
                                                  -> Result<Library, LibraryError> {
        unsafe {
            let source = NSString::alloc(nil).init_str(source.as_ref());
            let options = compile_options.mtl_compile_options();
            let error = nil;
            let library = self.0.newLibraryWithSource_options_error(source, options, error);
            if error != nil {
                // Todo(George): Should use the `error` variable to get more info
                Err(LibraryError::SourceError)
            } else {
                Ok(try!(FromRaw::from_raw(library)))
            }
        }
    }

    #[allow(unused_variables)]
    // Todo(George): `data` parameter should be of the correct type
    pub fn new_library_with_data(&mut self, data: ()) -> Result<Library, LibraryError> {
        unimplemented!();
    }

    pub fn is_depth24_stencil8_pixel_format_supported(&self) -> bool {
        unsafe { self.0.depth24Stencil8PixelFormatSupported() == YES }
    }

    pub fn is_headless(&self) -> bool {
        unsafe { self.0.headless() == YES }
    }

    pub fn is_low_power(&self) -> bool {
        unsafe { self.0.lowPower() == YES }
    }

    pub fn max_threads_per_group(&self) -> Size {
        unsafe { self.0.maxThreadsPerGroup().into() }
    }

    pub fn get_name(&self) -> Cow<str> {
        unsafe { CStr::from_ptr(self.0.name().UTF8String()).to_string_lossy() }
    }

    pub fn supports_texture_sample_count(&self, sample_count: usize) -> bool {
        unsafe { self.0.supportsTextureSampleCount(sample_count as NSUInteger) == YES }
    }
}

impl_from_into_raw!(Device, "MTLDevice");

/// Internal utility function to get a Device's id without consuming it.
/// Not exported publicly from this crate.
#[doc(hidden)]
pub unsafe fn _device_get_raw(device: &Device) -> id {
    device.0
}

#[derive(Clone, Debug)]
pub enum DeviceError {
    ConstructionFailed,
    RawError(FromRawError)
}

impl From<FromRawError> for DeviceError {
    fn from(error: FromRawError) -> Self {
        DeviceError::RawError(error)
    }
}

impl Display for DeviceError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let descr = match *self {
            DeviceError::ConstructionFailed => "DeviceError::ConstructionFailed",
            DeviceError::RawError(_) => "DeviceError::ConstructionFailed",
        };
        write!(f, "{}", descr)
    }
}

impl Error for DeviceError {
    fn description(&self) -> &str {
        match *self {
            DeviceError::ConstructionFailed => {
                "Could not create a default device. Please ensure that you are using at least OSX \
                 10.11 or iOS 8.0"
            }
            DeviceError::RawError(_) => "There was an error with the device pointer",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match self {
            &DeviceError::ConstructionFailed => None,
            &DeviceError::RawError(ref raw_err) => Some(raw_err),
        }
    }
}
<|endoftext|>


<commit_before>// error-pattern:yummy
#![feature(box_syntax)]
#![feature(rustc_private)]
#![allow(unknown_lints, missing_docs_in_private_items)]

extern crate clippy_lints;
extern crate getopts;
extern crate rustc;
extern crate rustc_driver;
extern crate rustc_errors;
extern crate rustc_plugin;
extern crate syntax;

use rustc_driver::{driver, Compilation, CompilerCalls, RustcDefaultCalls};
use rustc::session::{config, CompileIncomplete, Session};
use rustc::session::config::{ErrorOutputType, Input};
use std::path::PathBuf;
use std::process::Command;
use syntax::ast;

struct ClippyCompilerCalls {
    default: RustcDefaultCalls,
    run_lints: bool,
}

impl ClippyCompilerCalls {
    fn new(run_lints: bool) -> Self {
        Self {
            default: RustcDefaultCalls,
            run_lints: run_lints,
        }
    }
}

impl<'a> CompilerCalls<'a> for ClippyCompilerCalls {
    fn early_callback(
        &mut self,
        matches: &getopts::Matches,
        sopts: &config::Options,
        cfg: &ast::CrateConfig,
        descriptions: &rustc_errors::registry::Registry,
        output: ErrorOutputType,
    ) -> Compilation {
        self.default
            .early_callback(matches, sopts, cfg, descriptions, output)
    }
    fn no_input(
        &mut self,
        matches: &getopts::Matches,
        sopts: &config::Options,
        cfg: &ast::CrateConfig,
        odir: &Option<PathBuf>,
        ofile: &Option<PathBuf>,
        descriptions: &rustc_errors::registry::Registry,
    ) -> Option<(Input, Option<PathBuf>)> {
        self.default
            .no_input(matches, sopts, cfg, odir, ofile, descriptions)
    }
    fn late_callback(
        &mut self,
        matches: &getopts::Matches,
        sess: &Session,
        crate_stores: &rustc::middle::cstore::CrateStore,
        input: &Input,
        odir: &Option<PathBuf>,
        ofile: &Option<PathBuf>,
    ) -> Compilation {
        self.default
            .late_callback(matches, sess, crate_stores, input, odir, ofile)
    }
    fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> driver::CompileController<'a> {
        let mut control = self.default.build_controller(sess, matches);

        if self.run_lints {
            let old = std::mem::replace(&mut control.after_parse.callback, box |_| {});
            control.after_parse.callback = Box::new(move |state| {
                {
                    let mut registry = rustc_plugin::registry::Registry::new(
                        state.session,
                        state
                            .krate
                            .as_ref()
                            .expect(
                                "at this compilation stage \
                                 the krate must be parsed",
                            )
                            .span,
                    );
                    registry.args_hidden = Some(Vec::new());
                    clippy_lints::register_plugins(&mut registry);

                    let rustc_plugin::registry::Registry {
                        early_lint_passes,
                        late_lint_passes,
                        lint_groups,
                        llvm_passes,
                        attributes,
                        ..
                    } = registry;
                    let sess = &state.session;
                    let mut ls = sess.lint_store.borrow_mut();
                    for pass in early_lint_passes {
                        ls.register_early_pass(Some(sess), true, pass);
                    }
                    for pass in late_lint_passes {
                        ls.register_late_pass(Some(sess), true, pass);
                    }

                    for (name, to) in lint_groups {
                        ls.register_group(Some(sess), true, name, to);
                    }

                    sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes);
                    sess.plugin_attributes.borrow_mut().extend(attributes);
                }
                old(state);
            });
        }

        control
    }
}

#[allow(print_stdout)]
fn show_version() {
    println!("{}", env!("CARGO_PKG_VERSION"));
}

pub fn main() {
    use std::env;

    if env::var("CLIPPY_DOGFOOD").is_ok() {
        panic!("yummy");
    }

    if std::env::args().any(|a| a == "--version" || a == "-V") {
        show_version();
        return;
    }

    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
    let sys_root = if let (Some(home), Some(toolchain)) = (home, toolchain) {
        format!("{}/toolchains/{}", home, toolchain)
    } else {
        option_env!("SYSROOT")
            .map(|s| s.to_owned())
            .or_else(|| {
                Command::new("rustc")
                    .arg("--print")
                    .arg("sysroot")
                    .output()
                    .ok()
                    .and_then(|out| String::from_utf8(out.stdout).ok())
                    .map(|s| s.trim().to_owned())
            })
            .expect(
                "need to specify SYSROOT env var during clippy compilation, or use rustup or multirust",
            )
    };

    rustc_driver::in_rustc_thread(|| {
        // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument.
        // We're invoking the compiler programatically, so we ignore this/
        let mut orig_args: Vec<String> = env::args().collect();
        if orig_args.len() <= 1 {
            std::process::exit(1);
        }
        if orig_args[1] == "rustc" {
            // we still want to be able to invoke it normally though
            orig_args.remove(1);
        }
        // this conditional check for the --sysroot flag is there so users can call
        // `clippy_driver` directly
        // without having to pass --sysroot or anything
        let mut args: Vec<String> = if orig_args.iter().any(|s| s == "--sysroot") {
            orig_args.clone()
        } else {
            orig_args.clone().into_iter()
                .chain(Some("--sysroot".to_owned()))
                .chain(Some(sys_root))
                .collect()
        };

        // this check ensures that dependencies are built but not linted and the final
        // crate is
        // linted but not built
        let clippy_enabled = env::var("CLIPPY_TESTS").ok().map_or(false, |val| val == "true") ||
            orig_args.iter().any(|s| s == "--emit=metadata");

        if clippy_enabled {
            args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]);
        }

        let mut ccc = ClippyCompilerCalls::new(clippy_enabled);
        let (result, _) = rustc_driver::run_compiler(&args, &mut ccc, None, None);
        if let Err(CompileIncomplete::Errored(_)) = result {
            std::process::exit(1);
        }
    }).expect("rustc_thread failed");
}
<commit_msg>Fix a typo<commit_after>// error-pattern:yummy
#![feature(box_syntax)]
#![feature(rustc_private)]
#![allow(unknown_lints, missing_docs_in_private_items)]

extern crate clippy_lints;
extern crate getopts;
extern crate rustc;
extern crate rustc_driver;
extern crate rustc_errors;
extern crate rustc_plugin;
extern crate syntax;

use rustc_driver::{driver, Compilation, CompilerCalls, RustcDefaultCalls};
use rustc::session::{config, CompileIncomplete, Session};
use rustc::session::config::{ErrorOutputType, Input};
use std::path::PathBuf;
use std::process::Command;
use syntax::ast;

struct ClippyCompilerCalls {
    default: RustcDefaultCalls,
    run_lints: bool,
}

impl ClippyCompilerCalls {
    fn new(run_lints: bool) -> Self {
        Self {
            default: RustcDefaultCalls,
            run_lints: run_lints,
        }
    }
}

impl<'a> CompilerCalls<'a> for ClippyCompilerCalls {
    fn early_callback(
        &mut self,
        matches: &getopts::Matches,
        sopts: &config::Options,
        cfg: &ast::CrateConfig,
        descriptions: &rustc_errors::registry::Registry,
        output: ErrorOutputType,
    ) -> Compilation {
        self.default
            .early_callback(matches, sopts, cfg, descriptions, output)
    }
    fn no_input(
        &mut self,
        matches: &getopts::Matches,
        sopts: &config::Options,
        cfg: &ast::CrateConfig,
        odir: &Option<PathBuf>,
        ofile: &Option<PathBuf>,
        descriptions: &rustc_errors::registry::Registry,
    ) -> Option<(Input, Option<PathBuf>)> {
        self.default
            .no_input(matches, sopts, cfg, odir, ofile, descriptions)
    }
    fn late_callback(
        &mut self,
        matches: &getopts::Matches,
        sess: &Session,
        crate_stores: &rustc::middle::cstore::CrateStore,
        input: &Input,
        odir: &Option<PathBuf>,
        ofile: &Option<PathBuf>,
    ) -> Compilation {
        self.default
            .late_callback(matches, sess, crate_stores, input, odir, ofile)
    }
    fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> driver::CompileController<'a> {
        let mut control = self.default.build_controller(sess, matches);

        if self.run_lints {
            let old = std::mem::replace(&mut control.after_parse.callback, box |_| {});
            control.after_parse.callback = Box::new(move |state| {
                {
                    let mut registry = rustc_plugin::registry::Registry::new(
                        state.session,
                        state
                            .krate
                            .as_ref()
                            .expect(
                                "at this compilation stage \
                                 the krate must be parsed",
                            )
                            .span,
                    );
                    registry.args_hidden = Some(Vec::new());
                    clippy_lints::register_plugins(&mut registry);

                    let rustc_plugin::registry::Registry {
                        early_lint_passes,
                        late_lint_passes,
                        lint_groups,
                        llvm_passes,
                        attributes,
                        ..
                    } = registry;
                    let sess = &state.session;
                    let mut ls = sess.lint_store.borrow_mut();
                    for pass in early_lint_passes {
                        ls.register_early_pass(Some(sess), true, pass);
                    }
                    for pass in late_lint_passes {
                        ls.register_late_pass(Some(sess), true, pass);
                    }

                    for (name, to) in lint_groups {
                        ls.register_group(Some(sess), true, name, to);
                    }

                    sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes);
                    sess.plugin_attributes.borrow_mut().extend(attributes);
                }
                old(state);
            });
        }

        control
    }
}

#[allow(print_stdout)]
fn show_version() {
    println!("{}", env!("CARGO_PKG_VERSION"));
}

pub fn main() {
    use std::env;

    if env::var("CLIPPY_DOGFOOD").is_ok() {
        panic!("yummy");
    }

    if std::env::args().any(|a| a == "--version" || a == "-V") {
        show_version();
        return;
    }

    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
    let sys_root = if let (Some(home), Some(toolchain)) = (home, toolchain) {
        format!("{}/toolchains/{}", home, toolchain)
    } else {
        option_env!("SYSROOT")
            .map(|s| s.to_owned())
            .or_else(|| {
                Command::new("rustc")
                    .arg("--print")
                    .arg("sysroot")
                    .output()
                    .ok()
                    .and_then(|out| String::from_utf8(out.stdout).ok())
                    .map(|s| s.trim().to_owned())
            })
            .expect(
                "need to specify SYSROOT env var during clippy compilation, or use rustup or multirust",
            )
    };

    rustc_driver::in_rustc_thread(|| {
        // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument.
        // We're invoking the compiler programmatically, so we ignore this/
        let mut orig_args: Vec<String> = env::args().collect();
        if orig_args.len() <= 1 {
            std::process::exit(1);
        }
        if orig_args[1] == "rustc" {
            // we still want to be able to invoke it normally though
            orig_args.remove(1);
        }
        // this conditional check for the --sysroot flag is there so users can call
        // `clippy_driver` directly
        // without having to pass --sysroot or anything
        let mut args: Vec<String> = if orig_args.iter().any(|s| s == "--sysroot") {
            orig_args.clone()
        } else {
            orig_args.clone().into_iter()
                .chain(Some("--sysroot".to_owned()))
                .chain(Some(sys_root))
                .collect()
        };

        // this check ensures that dependencies are built but not linted and the final
        // crate is
        // linted but not built
        let clippy_enabled = env::var("CLIPPY_TESTS").ok().map_or(false, |val| val == "true") ||
            orig_args.iter().any(|s| s == "--emit=metadata");

        if clippy_enabled {
            args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]);
        }

        let mut ccc = ClippyCompilerCalls::new(clippy_enabled);
        let (result, _) = rustc_driver::run_compiler(&args, &mut ccc, None, None);
        if let Err(CompileIncomplete::Errored(_)) = result {
            std::process::exit(1);
        }
    }).expect("rustc_thread failed");
}
<|endoftext|>


<commit_before>use error_chain::ChainedError;
use ffmpeg;
use std::sync::{Mutex, ONCE_INIT, Once};

use errors::*;

lazy_static! {
    static ref VIDEO_ENCODER: Mutex<Option<ffmpeg::codec::Video>> = Mutex::new(None);
}

/// An encoder used to encode a video to a file.
///
/// Call `Encoder::start()` to start the encoding, then encode some frames with `Encoder::encode()`.
/// The encoder will flush and save the output file automatically upon being dropped.
pub struct Encoder {
    converter: ffmpeg::software::scaling::Context,
    context: ffmpeg::format::context::Output,
    encoder: ffmpeg::codec::encoder::Video,
    output_frame: ffmpeg::util::frame::Video,
    packet: ffmpeg::Packet,

    time_base: ffmpeg::Rational,
    stream_time_base: ffmpeg::Rational,

    pts: i64,

    /// Difference, in video frames, between how much time passed in-game and how much video we
    /// output.
    remainder: f64,
}

unsafe impl Send for Encoder {}

impl Encoder {
    pub fn start(filename: &str,
                 (width, height): (u32, u32),
                 time_base: ffmpeg::Rational,
                 crf: &str,
                 preset: &str)
                 -> Result<Self> {
        let codec = VIDEO_ENCODER.lock().unwrap();
        ensure!(codec.is_some(), "video encoder was not set");
        let codec = codec.unwrap();

        let mut context = ffmpeg::format::output(&filename)
            .chain_err(|| "could not create the output context")?;

        let encoder = {
            let mut stream =
                context.add_stream(codec)
                       .chain_err(|| "could not add the video stream")?;

            let mut encoder =
                stream.codec()
                      .encoder()
                      .video()
                      .chain_err(|| "could not retrieve the video encoder")?;

            encoder.set_width(width);
            encoder.set_height(height);
            encoder.set_time_base(time_base);

            if let Some(mut formats) = codec.formats() {
                encoder.set_format(formats.next().unwrap());
            } else {
                encoder.set_format(ffmpeg::format::Pixel::YUV420P);
            }

            let encoder = encoder.open_as_with(codec,
                                               dict!("crf" => &crf,
                                                     "preset" => &preset))
                                 .chain_err(|| "could not open the video encoder",)?;
            stream.set_parameters(&encoder);

            stream.set_time_base(time_base);

            encoder
        };

        context.write_header()
               .chain_err(|| "could not write the header")?;

        let stream_time_base = context.stream(0).unwrap().time_base();

        let converter = ffmpeg::software::converter((width, height),
                                                    ffmpeg::format::Pixel::RGB24,
                                                    encoder.format())
            .chain_err(|| "could not get the color conversion context")?;

        let output_frame = ffmpeg::frame::Video::new(encoder.format(), width, height);

        let packet = ffmpeg::Packet::empty();

        Ok(Self {
               converter,
               context,
               encoder,
               output_frame,
               packet,

               time_base,
               stream_time_base,

               pts: 0,
               remainder: 0f64,
           })
    }

    fn push_frame(&mut self) -> Result<()> {
        self.output_frame.set_pts(Some(self.pts));
        self.pts += 1;

        if self.encoder
               .encode(&self.output_frame, &mut self.packet)
               .chain_err(|| "could not encode the frame")? {
            self.packet
                .rescale_ts(self.time_base, self.stream_time_base);

            self.packet
                .write_interleaved(&mut self.context)
                .chain_err(|| "could not write the packet")?;
        }

        Ok(())
    }

    pub fn take(&mut self, frame: &ffmpeg::frame::Video, frametime: f64) -> Result<()> {
        self.converter
            .run(frame, &mut self.output_frame)
            .chain_err(|| "could not convert the frame to the correct format")?;

        let time_base: f64 = self.time_base.into();
        self.remainder += frametime / time_base;

        loop {
            // Push this frame as long as it takes up the most of the video frame.
            if self.remainder <= 0.5f64 {
                break;
            }

            self.push_frame()?;
            self.remainder -= 1f64;
        }

        Ok(())
    }

    fn flush(&mut self) -> Result<()> {
        while self.encoder
                  .flush(&mut self.packet)
                  .chain_err(|| "could not get the packet")? {
            self.packet
                .rescale_ts(self.time_base, self.stream_time_base);

            self.packet
                .write_interleaved(&mut self.context)
                .chain_err(|| "could not write the packet")?;
        }

        Ok(())
    }

    pub fn width(&self) -> u32 {
        self.encoder.width()
    }

    pub fn height(&self) -> u32 {
        self.encoder.height()
    }
}

impl Drop for Encoder {
    fn drop(&mut self) {
        #![allow(unused_must_use)]
        self.flush();
        self.context.write_trailer();
    }
}

/// Initialize the encoding stuff.
pub fn initialize() {
    static INIT: Once = ONCE_INIT;

    INIT.call_once(|| {
        if let Err(ref e) = ffmpeg::init().chain_err(|| "error initializing ffmpeg") {
            panic!("{}", e.display());
        }

        *VIDEO_ENCODER.lock().unwrap() = ffmpeg::encoder::find_by_name("libx264")
            .and_then(|e| e.video().ok());
    });
}

command!(cap_set_video_encoder, |engine| {
    let mut args = engine.args();

    if args.len() != 2 {
        let mut buf = String::new();

        buf.push_str("Usage:\n");
        buf.push_str("    cap_set_video_encoder <encoder>\n");
        buf.push_str("     - Set the video encoder by name.\n");
        buf.push_str("Example:\n");
        buf.push_str("    cap_set_video_encoder libx264\n");

        engine.con_print(&buf);
        return;
    }

    let encoder_name = args.nth(1).unwrap();

    if let Some(encoder) = ffmpeg::encoder::find_by_name(&encoder_name) {
        if let Ok(video) = encoder.video() {
            let mut buf = String::new();

            buf.push_str(&format!("Selected encoder: {}\n", encoder_name));
            buf.push_str(&format!("Description: {}\n", encoder.description()));
            buf.push_str("Pixel formats: ");

            if let Some(formats) = video.formats() {
                buf.push_str(&format!("{:?}\n", formats.collect::<Vec<_>>()));
            } else {
                buf.push_str("any\n");
            }

            engine.con_print(&buf);

            *VIDEO_ENCODER.lock().unwrap() = Some(video);
        } else {
            engine.con_print(&format!("Invalid encoder type '{}'\n", encoder_name));
        }
    } else {
        engine.con_print(&format!("Unknown encoder '{}'\n", encoder_name));
    }
});

// command!(cap_test_video_output, |engine| {
//     if VIDEO_ENCODER.lock().unwrap().is_none() {
//         engine.con_print("Please set the video encoder with cap_set_video_encoder.\n");
//         return;
//     }
//
//     if let Err(ref e) = test_video_output().chain_err(|| "error in test_video_output()") {
//         engine.con_print(&format!("{}", e.display()));
//         return;
//     }
//
//     engine.con_print("Done!\n");
// });
//
// fn test_video_output() -> Result<()> {
//     let mut encoder = Encoder::start("/home/yalter/test.mkv",
//                                      (1680, 1050),
//                                      (1, 60).into())
//         .chain_err(|| "could not create the encoder")?;
//
//     let mut frame = ffmpeg::frame::Video::new(ffmpeg::format::Pixel::RGB24, 1680, 1050);
//
//     {
//         let mut data = frame.plane_mut::<(u8, u8, u8)>(0);
//         for pixel in data.iter_mut() {
//             *pixel = (0, 255, 0);
//         }
//     }
//
//     let linesize = unsafe {
//         (*frame.as_ptr()).linesize[0] / 3
//     };
//
//     for f in 0..240 {
//         {
//             let mut data = frame.plane_mut::<(u8, u8, u8)>(0);
//             for y in 0..1050 {
//                 data[y * linesize as usize + f * 2] = (255, 0, 0);
//                 data[y * linesize as usize + f * 2 + 1] = (255, 0, 0);
//             }
//         }
//
//         encoder.encode(&frame)
//             .chain_err(|| "could not encode a frame")?;
//     }
//
//     Ok(())
// }
<commit_msg>Add important performance comment<commit_after>use error_chain::ChainedError;
use ffmpeg;
use std::sync::{Mutex, ONCE_INIT, Once};

use errors::*;

lazy_static! {
    static ref VIDEO_ENCODER: Mutex<Option<ffmpeg::codec::Video>> = Mutex::new(None);
}

/// An encoder used to encode a video to a file.
///
/// Call `Encoder::start()` to start the encoding, then encode some frames with `Encoder::encode()`.
/// The encoder will flush and save the output file automatically upon being dropped.
pub struct Encoder {
    converter: ffmpeg::software::scaling::Context,
    context: ffmpeg::format::context::Output,
    encoder: ffmpeg::codec::encoder::Video,
    output_frame: ffmpeg::util::frame::Video,
    packet: ffmpeg::Packet,

    time_base: ffmpeg::Rational,
    stream_time_base: ffmpeg::Rational,

    pts: i64,

    /// Difference, in video frames, between how much time passed in-game and how much video we
    /// output.
    remainder: f64,
}

unsafe impl Send for Encoder {}

impl Encoder {
    pub fn start(filename: &str,
                 (width, height): (u32, u32),
                 time_base: ffmpeg::Rational,
                 crf: &str,
                 preset: &str)
                 -> Result<Self> {
        let codec = VIDEO_ENCODER.lock().unwrap();
        ensure!(codec.is_some(), "video encoder was not set");
        let codec = codec.unwrap();

        let mut context = ffmpeg::format::output(&filename)
            .chain_err(|| "could not create the output context")?;

        let encoder = {
            let mut stream =
                context.add_stream(codec)
                       .chain_err(|| "could not add the video stream")?;

            let mut encoder =
                stream.codec()
                      .encoder()
                      .video()
                      .chain_err(|| "could not retrieve the video encoder")?;

            encoder.set_width(width);
            encoder.set_height(height);
            encoder.set_time_base(time_base);

            if let Some(mut formats) = codec.formats() {
                encoder.set_format(formats.next().unwrap());
            } else {
                encoder.set_format(ffmpeg::format::Pixel::YUV420P);
            }

            let encoder = encoder.open_as_with(codec,
                                               dict!("crf" => &crf,
                                                     "preset" => &preset))
                                 .chain_err(|| "could not open the video encoder",)?;
            stream.set_parameters(&encoder);

            stream.set_time_base(time_base);

            encoder
        };

        context.write_header()
               .chain_err(|| "could not write the header")?;

        let stream_time_base = context.stream(0).unwrap().time_base();

        let converter = ffmpeg::software::converter((width, height),
                                                    ffmpeg::format::Pixel::RGB24,
                                                    encoder.format())
            .chain_err(|| "could not get the color conversion context")?;

        let output_frame = ffmpeg::frame::Video::new(encoder.format(), width, height);

        let packet = ffmpeg::Packet::empty();

        Ok(Self {
               converter,
               context,
               encoder,
               output_frame,
               packet,

               time_base,
               stream_time_base,

               pts: 0,
               remainder: 0f64,
           })
    }

    fn push_frame(&mut self) -> Result<()> {
        self.output_frame.set_pts(Some(self.pts));
        self.pts += 1;

        if self.encoder
               .encode(&self.output_frame, &mut self.packet)
               .chain_err(|| "could not encode the frame")? {
            self.packet
                .rescale_ts(self.time_base, self.stream_time_base);

            self.packet
                .write_interleaved(&mut self.context)
                .chain_err(|| "could not write the packet")?;
        }

        Ok(())
    }

    pub fn take(&mut self, frame: &ffmpeg::frame::Video, frametime: f64) -> Result<()> {
        self.converter
            .run(frame, &mut self.output_frame)
            .chain_err(|| "could not convert the frame to the correct format")?;

        let time_base: f64 = self.time_base.into();
        self.remainder += frametime / time_base;

        loop {
            // Push this frame as long as it takes up the most of the video frame.
            // TODO: move this logic somewhere to skip glReadPixels and other stuff
            // altogether if we're gonna drop this frame anyway.
            if self.remainder <= 0.5f64 {
                break;
            }

            self.push_frame()?;
            self.remainder -= 1f64;
        }

        Ok(())
    }

    fn flush(&mut self) -> Result<()> {
        while self.encoder
                  .flush(&mut self.packet)
                  .chain_err(|| "could not get the packet")? {
            self.packet
                .rescale_ts(self.time_base, self.stream_time_base);

            self.packet
                .write_interleaved(&mut self.context)
                .chain_err(|| "could not write the packet")?;
        }

        Ok(())
    }

    pub fn width(&self) -> u32 {
        self.encoder.width()
    }

    pub fn height(&self) -> u32 {
        self.encoder.height()
    }
}

impl Drop for Encoder {
    fn drop(&mut self) {
        #![allow(unused_must_use)]
        self.flush();
        self.context.write_trailer();
    }
}

/// Initialize the encoding stuff.
pub fn initialize() {
    static INIT: Once = ONCE_INIT;

    INIT.call_once(|| {
        if let Err(ref e) = ffmpeg::init().chain_err(|| "error initializing ffmpeg") {
            panic!("{}", e.display());
        }

        *VIDEO_ENCODER.lock().unwrap() = ffmpeg::encoder::find_by_name("libx264")
            .and_then(|e| e.video().ok());
    });
}

command!(cap_set_video_encoder, |engine| {
    let mut args = engine.args();

    if args.len() != 2 {
        let mut buf = String::new();

        buf.push_str("Usage:\n");
        buf.push_str("    cap_set_video_encoder <encoder>\n");
        buf.push_str("     - Set the video encoder by name.\n");
        buf.push_str("Example:\n");
        buf.push_str("    cap_set_video_encoder libx264\n");

        engine.con_print(&buf);
        return;
    }

    let encoder_name = args.nth(1).unwrap();

    if let Some(encoder) = ffmpeg::encoder::find_by_name(&encoder_name) {
        if let Ok(video) = encoder.video() {
            let mut buf = String::new();

            buf.push_str(&format!("Selected encoder: {}\n", encoder_name));
            buf.push_str(&format!("Description: {}\n", encoder.description()));
            buf.push_str("Pixel formats: ");

            if let Some(formats) = video.formats() {
                buf.push_str(&format!("{:?}\n", formats.collect::<Vec<_>>()));
            } else {
                buf.push_str("any\n");
            }

            engine.con_print(&buf);

            *VIDEO_ENCODER.lock().unwrap() = Some(video);
        } else {
            engine.con_print(&format!("Invalid encoder type '{}'\n", encoder_name));
        }
    } else {
        engine.con_print(&format!("Unknown encoder '{}'\n", encoder_name));
    }
});

// command!(cap_test_video_output, |engine| {
//     if VIDEO_ENCODER.lock().unwrap().is_none() {
//         engine.con_print("Please set the video encoder with cap_set_video_encoder.\n");
//         return;
//     }
//
//     if let Err(ref e) = test_video_output().chain_err(|| "error in test_video_output()") {
//         engine.con_print(&format!("{}", e.display()));
//         return;
//     }
//
//     engine.con_print("Done!\n");
// });
//
// fn test_video_output() -> Result<()> {
//     let mut encoder = Encoder::start("/home/yalter/test.mkv",
//                                      (1680, 1050),
//                                      (1, 60).into())
//         .chain_err(|| "could not create the encoder")?;
//
//     let mut frame = ffmpeg::frame::Video::new(ffmpeg::format::Pixel::RGB24, 1680, 1050);
//
//     {
//         let mut data = frame.plane_mut::<(u8, u8, u8)>(0);
//         for pixel in data.iter_mut() {
//             *pixel = (0, 255, 0);
//         }
//     }
//
//     let linesize = unsafe {
//         (*frame.as_ptr()).linesize[0] / 3
//     };
//
//     for f in 0..240 {
//         {
//             let mut data = frame.plane_mut::<(u8, u8, u8)>(0);
//             for y in 0..1050 {
//                 data[y * linesize as usize + f * 2] = (255, 0, 0);
//                 data[y * linesize as usize + f * 2 + 1] = (255, 0, 0);
//             }
//         }
//
//         encoder.encode(&frame)
//             .chain_err(|| "could not encode a frame")?;
//     }
//
//     Ok(())
// }
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::cell::RefCell;
use std::thread;
use std::ops::Deref;

use bootstrap;
use bootstrap::window::Window;
use bootstrap::window::Message::*;
use bootstrap::time::Timer;
use bootstrap::gl_utils;

use bs_audio;

use polygon::gl_render::{self, GLRender};

use scene::Scene;
use resource::ResourceManager;
use ecs::System;
use component::*;

pub const TARGET_FRAME_TIME_SECONDS: f32 = 1.0 / 60.0;
pub const TARGET_FRAME_TIME_MS: f32 = TARGET_FRAME_TIME_SECONDS * 1000.0;

pub struct Engine {
    window: Rc<RefCell<Window>>, // TODO: This doesn't need to be an Rc<RefCell<>> when we're not doing hotloading.
    renderer: GLRender,
    resource_manager: Rc<RefCell<ResourceManager>>,
    systems: Vec<Box<System>>,
    transform_update: Box<System>,
    light_update: Box<System>,
    audio_update: Box<System>,
    scene: Scene,

    close: bool,
}

impl Engine {
    pub fn new() -> Engine {
        let instance = bootstrap::init();
        let window = Window::new("Rust Window", instance);
        let renderer = gl_render::init(window.borrow().deref());
        let resource_manager = Rc::new(RefCell::new(ResourceManager::new(renderer)));

        let audio_source = match bs_audio::init() {
            Ok(audio_source) => {
                println!("Audio subsystem successfully initialized");
                audio_source
            },
            Err(error) => {
                panic!("Error while initialzing audio subsystem: {}", error)
            },
        };

        Engine {
            window: window.clone(),
            renderer: renderer,
            resource_manager: resource_manager.clone(),
            systems: Vec::new(),
            transform_update: Box::new(TransformUpdateSystem),
            light_update: Box::new(LightUpdateSystem),
            audio_update: Box::new(AudioSystem),
            scene: Scene::new(&resource_manager, audio_source),

            close: false,
        }
    }

    pub fn update(&mut self) {
        let scene = &mut self.scene;

        scene.input.clear();
        let mut window = self.window.borrow_mut();
        window.handle_messages();
        loop {
            let message = window.next_message(); // TODO: Make this an iterator to simplify this loop.
            match message {
                Some(message) => {
                    match message {
                        Activate => (),
                        Close => self.close = true,
                        Destroy => (),
                        Paint => (),

                        // Handle inputs.
                        KeyDown(_)
                      | KeyUp(_)
                      | MouseMove(_, _)
                      | MousePos(_, _)
                      | MouseButtonPressed(_)
                      | MouseButtonReleased(_)
                      | MouseWheel(_) => scene.input.push_input(message),
                    }
                },
                None => break
            }
        }

        // Update systems.
        for system in self.systems.iter_mut() {
            system.update(scene, TARGET_FRAME_TIME_SECONDS);
        }

        self.transform_update.update(scene, TARGET_FRAME_TIME_SECONDS);
        self.light_update.update(scene, TARGET_FRAME_TIME_SECONDS);
        self.audio_update.update(scene, TARGET_FRAME_TIME_SECONDS);
    }

    pub fn draw(&mut self) {
        self.renderer.clear();

        let scene = &mut self.scene;
        let camera_manager = scene.get_manager::<CameraManager>();
        let transform_manager = scene.get_manager::<TransformManager>();
        let mesh_manager = scene.get_manager::<MeshManager>();
        let light_manager = scene.get_manager::<LightManager>();

        // Handle rendering for each camera.
        for (mut camera, entity) in camera_manager.iter_mut() {

            // TODO: Update the camera's bounds in a separate system.
            {
                let transform = transform_manager.get(entity);

                camera.position = transform.position_derived();
                camera.rotation = transform.rotation_derived();
            }

            // Draw all of the meshes.
            for (mesh, entity) in mesh_manager.iter() {
                let transform = transform_manager.get(entity);

                self.renderer.draw_mesh(
                    &mesh,
                    transform.derived_matrix(),
                    transform.derived_normal_matrix(),
                    &camera,
                    &mut light_manager.components().iter().map(|ref_cell| *ref_cell.borrow()));
            }
        }

        self.renderer.swap_buffers();
    }

    pub fn main_loop(&mut self) {
        let timer = Timer::new();

        loop {
            let start_time = timer.now();

            self.update();
            self.draw();

            if self.close {
                break;
            }

            // Wait for target frame time.
            let mut remaining_time_ms = TARGET_FRAME_TIME_MS - timer.elapsed_ms(start_time);
            while remaining_time_ms > 1.0 {
                remaining_time_ms = TARGET_FRAME_TIME_MS - timer.elapsed_ms(start_time);
                thread::sleep_ms(remaining_time_ms as u32);
            }

            while remaining_time_ms > 0.0 {
                remaining_time_ms = TARGET_FRAME_TIME_MS - timer.elapsed_ms(start_time);
            }

            // TODO: Don't flip buffers until end of frame time?
        };
    }

    pub fn register_system(&mut self, system: Box<System>) {
        self.systems.push(system);
    }

    pub fn scene(&self) -> &Scene {
        &self.scene
    }

    pub fn scene_mut(&mut self) -> &mut Scene {
        &mut self.scene
    }

    pub fn close(&self) -> bool {
        self.close
    }
}

impl Clone for Engine {
    fn clone(&self) -> Engine {
        let resource_manager = Rc::new(RefCell::new(self.resource_manager.borrow().deref().clone()));

        let engine = Engine {
            window: self.window.clone(),
            renderer: self.renderer.clone(),
            resource_manager: resource_manager.clone(),
            systems: Vec::new(),
            transform_update: Box::new(TransformUpdateSystem),
            light_update: Box::new(LightUpdateSystem),
            audio_update: Box::new(AudioSystem),
            scene: self.scene.clone(&resource_manager),

            close: false,
        };

        // TODO: Reload game systems.

        engine
    }
}

#[no_mangle]
pub fn engine_init(window: Rc<RefCell<Window>>) -> Box<Engine> {
    let renderer = gl_render::init(window.borrow().deref());
    let resource_manager = Rc::new(RefCell::new(ResourceManager::new(renderer)));

    let audio_source = match bs_audio::init() {
        Ok(audio_source) => {
            println!("Audio subsystem successfully initialized");
            audio_source
        },
        Err(error) => {
            panic!("Error while initialzing audio subsystem: {}", error)
        },
    };

    Box::new(Engine {
        window: window,
        renderer: renderer,
        resource_manager: resource_manager.clone(),
        systems: Vec::new(),
        transform_update: Box::new(TransformUpdateSystem),
        light_update: Box::new(LightUpdateSystem),
        audio_update: Box::new(AudioSystem),
        scene: Scene::new(&resource_manager, audio_source),

        close: false,
    })
}

#[no_mangle]
pub fn engine_reload(engine: &Engine) -> Box<Engine> {
    let new_engine = engine.clone();

    // The proc loader needs to be set from within the DLL otherwise we don't
    // correctly bind to OpenGL on Windows.
    gl_utils::set_proc_loader();

    Box::new(new_engine)
}

#[no_mangle]
pub fn engine_update_and_render(engine: &mut Engine) {
    engine.update();
    engine.draw();
}

#[no_mangle]
pub fn engine_close(engine: &Engine) -> bool {
    engine.close()
}

#[no_mangle]
pub fn engine_drop(engine: Box<Engine>) {
    drop(engine);
}
<commit_msg>Game Freeze Bug Fix<commit_after>use std::rc::Rc;
use std::cell::RefCell;
use std::thread;
use std::ops::Deref;
use std::any::Any;

use bootstrap;
use bootstrap::window::Window;
use bootstrap::window::Message::*;
use bootstrap::time::Timer;
use bootstrap::gl_utils;

use bs_audio;

use polygon::gl_render::{self, GLRender};

use scene::Scene;
use resource::ResourceManager;
use ecs::System;
use component::*;

pub const TARGET_FRAME_TIME_SECONDS: f32 = 1.0 / 60.0;
pub const TARGET_FRAME_TIME_MS: f32 = TARGET_FRAME_TIME_SECONDS * 1000.0;

pub struct Engine {
    window: Rc<RefCell<Window>>, // TODO: This doesn't need to be an Rc<RefCell<>> when we're not doing hotloading.
    renderer: GLRender,
    resource_manager: Rc<RefCell<ResourceManager>>,
    systems: Vec<Box<System>>,
    transform_update: Box<System>,
    light_update: Box<System>,
    audio_update: Box<System>,
    scene: Scene,

    close: bool,
}

impl Engine {
    pub fn new() -> Engine {
        let instance = bootstrap::init();
        let window = Window::new("Rust Window", instance);
        let renderer = gl_render::init(window.borrow().deref());
        let resource_manager = Rc::new(RefCell::new(ResourceManager::new(renderer)));

        let audio_source = match bs_audio::init() {
            Ok(audio_source) => {
                println!("Audio subsystem successfully initialized");
                audio_source
            },
            Err(error) => {
                panic!("Error while initialzing audio subsystem: {}", error)
            },
        };

        Engine {
            window: window.clone(),
            renderer: renderer,
            resource_manager: resource_manager.clone(),
            systems: Vec::new(),
            transform_update: Box::new(TransformUpdateSystem),
            light_update: Box::new(LightUpdateSystem),
            audio_update: Box::new(AudioSystem),
            scene: Scene::new(&resource_manager, audio_source),

            close: false,
        }
    }

    pub fn update(&mut self) {
        let scene = &mut self.scene;

        scene.input.clear();
        let mut window = self.window.borrow_mut();
        window.handle_messages();
        loop {
            let message = window.next_message(); // TODO: Make this an iterator to simplify this loop.
            match message {
                Some(message) => {
                    match message {
                        Activate => (),
                        Close => self.close = true,
                        Destroy => (),
                        Paint => (),

                        // Handle inputs.
                        KeyDown(_)
                      | KeyUp(_)
                      | MouseMove(_, _)
                      | MousePos(_, _)
                      | MouseButtonPressed(_)
                      | MouseButtonReleased(_)
                      | MouseWheel(_) => scene.input.push_input(message),
                    }
                },
                None => break
            }
        }

        // Update systems.
        for system in self.systems.iter_mut() {
            system.update(scene, TARGET_FRAME_TIME_SECONDS);
        }

        self.transform_update.update(scene, TARGET_FRAME_TIME_SECONDS);
        self.light_update.update(scene, TARGET_FRAME_TIME_SECONDS);
        self.audio_update.update(scene, TARGET_FRAME_TIME_SECONDS);
    }

    pub fn draw(&mut self) {
        self.renderer.clear();

        let scene = &mut self.scene;
        let camera_manager = scene.get_manager::<CameraManager>();
        let transform_manager = scene.get_manager::<TransformManager>();
        let mesh_manager = scene.get_manager::<MeshManager>();
        let light_manager = scene.get_manager::<LightManager>();

        // Handle rendering for each camera.
        for (mut camera, entity) in camera_manager.iter_mut() {

            // TODO: Update the camera's bounds in a separate system.
            {
                let transform = transform_manager.get(entity);

                camera.position = transform.position_derived();
                camera.rotation = transform.rotation_derived();
            }

            // Draw all of the meshes.
            for (mesh, entity) in mesh_manager.iter() {
                let transform = transform_manager.get(entity);

                self.renderer.draw_mesh(
                    &mesh,
                    transform.derived_matrix(),
                    transform.derived_normal_matrix(),
                    &camera,
                    &mut light_manager.components().iter().map(|ref_cell| *ref_cell.borrow()));
            }
        }

        self.renderer.swap_buffers();
    }

    pub fn main_loop(&mut self) {
        let timer = Timer::new();

        loop {
            let start_time = timer.now();

            self.update();
            self.draw();

            if self.close {
                break;
            }

            // Wait for target frame time.
            let mut remaining_time_ms = TARGET_FRAME_TIME_MS - timer.elapsed_ms(start_time);
            while remaining_time_ms > 1.0 {
                thread::sleep_ms(remaining_time_ms as u32);
                remaining_time_ms = TARGET_FRAME_TIME_MS - timer.elapsed_ms(start_time);
            }

            while remaining_time_ms > 0.0 {
                remaining_time_ms = TARGET_FRAME_TIME_MS - timer.elapsed_ms(start_time);
            }

            // TODO: Don't flip buffers until end of frame time?
        };
    }

    pub fn register_system<T: Any + System>(&mut self, system: T) {
        self.systems.push(Box::new(system));
    }

    pub fn scene(&self) -> &Scene {
        &self.scene
    }

    pub fn scene_mut(&mut self) -> &mut Scene {
        &mut self.scene
    }

    pub fn close(&self) -> bool {
        self.close
    }
}

impl Clone for Engine {
    fn clone(&self) -> Engine {
        let resource_manager = Rc::new(RefCell::new(self.resource_manager.borrow().deref().clone()));

        let engine = Engine {
            window: self.window.clone(),
            renderer: self.renderer.clone(),
            resource_manager: resource_manager.clone(),
            systems: Vec::new(),
            transform_update: Box::new(TransformUpdateSystem),
            light_update: Box::new(LightUpdateSystem),
            audio_update: Box::new(AudioSystem),
            scene: self.scene.clone(&resource_manager),

            close: false,
        };

        // TODO: Reload game systems.

        engine
    }
}

#[no_mangle]
pub fn engine_init(window: Rc<RefCell<Window>>) -> Box<Engine> {
    let renderer = gl_render::init(window.borrow().deref());
    let resource_manager = Rc::new(RefCell::new(ResourceManager::new(renderer)));

    let audio_source = match bs_audio::init() {
        Ok(audio_source) => {
            println!("Audio subsystem successfully initialized");
            audio_source
        },
        Err(error) => {
            panic!("Error while initialzing audio subsystem: {}", error)
        },
    };

    Box::new(Engine {
        window: window,
        renderer: renderer,
        resource_manager: resource_manager.clone(),
        systems: Vec::new(),
        transform_update: Box::new(TransformUpdateSystem),
        light_update: Box::new(LightUpdateSystem),
        audio_update: Box::new(AudioSystem),
        scene: Scene::new(&resource_manager, audio_source),

        close: false,
    })
}

#[no_mangle]
pub fn engine_reload(engine: &Engine) -> Box<Engine> {
    let new_engine = engine.clone();

    // The proc loader needs to be set from within the DLL otherwise we don't
    // correctly bind to OpenGL on Windows.
    gl_utils::set_proc_loader();

    Box::new(new_engine)
}

#[no_mangle]
pub fn engine_update_and_render(engine: &mut Engine) {
    engine.update();
    engine.draw();
}

#[no_mangle]
pub fn engine_close(engine: &Engine) -> bool {
    engine.close()
}

#[no_mangle]
pub fn engine_drop(engine: Box<Engine>) {
    drop(engine);
}
<|endoftext|>


<commit_before>use serde::{Serialize, Deserialize};
use serde;
use serde_json;
use algorithm::*;
use std::collections::HashMap;

#[derive(Debug, PartialEq)]
/// A basic JWT header part, the alg defaults to HS256 and typ is automatically
/// set to `JWT`. All the other fields are optional
pub struct Header {
    typ: String,
    pub alg: Algorithm,
    pub jku: Option<String>,
    pub kid: Option<String>,
    pub x5u: Option<String>,
    pub x5t: Option<String>,
    pub custom_params: HashMap<String, serde_json::value::Value>,
}

impl Header {
    pub fn new(algorithm: Algorithm) -> Header {
        Header {
            typ: "JWT".to_owned(),
            alg: algorithm,
            jku: None,
            kid: None,
            x5u: None,
            x5t: None,
            custom_params: HashMap::new(),
        }
    }
}

impl Default for Header {
    fn default() -> Header {
        Header::new(Algorithm::HS256)
    }
}

impl Serialize for Header {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer,
    {
        serializer.serialize_map(HeaderSerVisitor(&self))
    }
}

struct HeaderSerVisitor<'a>(&'a Header);

impl<'a> serde::ser::MapVisitor for HeaderSerVisitor<'a> {
    fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
        where S: serde::Serializer
    {
        try!(serializer.serialize_struct_elt("typ", &self.0.typ));
        try!(serializer.serialize_struct_elt("alg", &self.0.alg));

        if self.0.jku.is_some() {
            try!(serializer.serialize_struct_elt("jku", &self.0.jku));
        }

        if self.0.kid.is_some() {
            try!(serializer.serialize_struct_elt("kid", &self.0.kid));
        }

        if self.0.x5u.is_some() {
            try!(serializer.serialize_struct_elt("x5u", &self.0.x5u));
        }

        if self.0.x5t.is_some() {
            try!(serializer.serialize_struct_elt("x5t", &self.0.x5t));
        }

        for (k,v) in &self.0.custom_params {
            try!(serializer.serialize_map_elt(k, v));
        }

        Ok(None)
    }
}

impl Deserialize for Header {
    fn deserialize<D>(deserializer: &mut D) -> Result<Header, D::Error>
        where D: serde::Deserializer,
    {
        deserializer.deserialize(HeaderDeVisitor)
    }
}

struct HeaderDeVisitor;

impl serde::de::Visitor for HeaderDeVisitor {
    type Value = Header;

    fn visit_map<V>(&mut self, mut visitor: V) -> Result<Header, V::Error>
        where V: serde::de::MapVisitor,
    {
        let mut alg = None;
        let mut typ = None;
        let mut jku = None;
        let mut kid = None;
        let mut x5u = None;
        let mut x5t = None;
        let mut custom_params = HashMap::<String, serde_json::value::Value>::new();

        loop {
            if let Some(key) = try!(visitor.visit_key::<String>()) {
                match &key[..] {
                    "alg" => { alg = Some(try!(visitor.visit_value())); }
                    "typ" => { typ = Some(try!(visitor.visit_value())); }
                    "kid" => { kid = Some(try!(visitor.visit_value())); }
                    "jku" => { jku = Some(try!(visitor.visit_value())); }
                    "x5u" => { x5u = Some(try!(visitor.visit_value())); }
                    "x5t" => { x5t = Some(try!(visitor.visit_value())); }
                    k => {
                        let v = try!(visitor.visit_value());

                        custom_params.entry(k.to_owned()).or_insert(v);
                    }
                }
            } else {
                break;
            }
        }

        let alg = match alg {
            Some(alg) => alg,
            None => try!(visitor.missing_field("alg")),
        };

        let typ = match typ {
            Some(typ) => typ,
            None => try!(visitor.missing_field("typ")),
        };

        try!(visitor.end());

        Ok(Header{
            alg: alg,
            typ: typ,
            kid: kid,
            jku: jku,
            x5u: x5u,
            x5t: x5t,
            custom_params: custom_params,
        })
    }
}
<commit_msg>add known header params<commit_after>use serde::{Serialize, Deserialize};
use serde;
use serde_json;
use algorithm::*;
use std::collections::HashMap;

#[derive(Debug, PartialEq)]
/// A basic JWT header part, the alg defaults to HS256 and typ is automatically
/// set to `JWT`. All the other fields are optional
pub struct Header {
    typ: String,
    pub alg: Algorithm,
    pub jku: Option<String>, // jwk key set url
    pub jwk: Option<String>, // json web key
    pub kid: Option<String>, // key id
    pub x5u: Option<String>, // x509 url
    pub x5c: Option<Vec<String>>, // x509 cert chain
    pub x5t: Option<String>, // x509 cert sha1 thumbprint
    pub x5t_s256: Option<String>, // x509 cert sha256 thumbprint
    pub cty: Option<String>, // payload media type
    pub crit: Option<Vec<String>>, // critical extension params list
    pub custom_params: HashMap<String, serde_json::value::Value>,
}

impl Header {
    pub fn new(algorithm: Algorithm) -> Header {
        Header {
            typ: "JWT".to_owned(),
            alg: algorithm,
            jku: None,
            jwk: None,
            kid: None,
            x5u: None,
            x5c: None,
            x5t: None,
            x5t_s256: None,
            cty: None,
            crit: None,
            custom_params: HashMap::new(),
        }
    }
}

impl Default for Header {
    fn default() -> Header {
        Header::new(Algorithm::HS256)
    }
}

impl Serialize for Header {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer,
    {
        serializer.serialize_map(HeaderSerVisitor(&self))
    }
}

struct HeaderSerVisitor<'a>(&'a Header);

impl<'a> serde::ser::MapVisitor for HeaderSerVisitor<'a> {
    fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
        where S: serde::Serializer
    {
        try!(serializer.serialize_struct_elt("typ", &self.0.typ));
        try!(serializer.serialize_struct_elt("alg", &self.0.alg));

        if self.0.jku.is_some() {
            try!(serializer.serialize_struct_elt("jku", &self.0.jku));
        }

        if self.0.jwk.is_some() {
            try!(serializer.serialize_struct_elt("jwk", &self.0.jwk));
        }

        if self.0.kid.is_some() {
            try!(serializer.serialize_struct_elt("kid", &self.0.kid));
        }

        if self.0.x5u.is_some() {
            try!(serializer.serialize_struct_elt("x5u", &self.0.x5u));
        }

        if self.0.x5c.is_some() {
            try!(serializer.serialize_struct_elt("x5c", &self.0.x5c));
        }

        if self.0.x5t.is_some() {
            try!(serializer.serialize_struct_elt("x5t", &self.0.x5t));
        }

        if self.0.x5t_s256.is_some() {
            try!(serializer.serialize_struct_elt("x5t#s256", &self.0.x5t_s256));
        }

        if self.0.cty.is_some() {
            try!(serializer.serialize_struct_elt("cty", &self.0.cty));
        }

        if let Some(crit) = self.0.crit.as_ref() {
            if crit.len() != 0 {
                try!(serializer.serialize_struct_elt("crit", &self.0.crit));
            }
        }

        for (k,v) in &self.0.custom_params {
            try!(serializer.serialize_map_elt(k, v));
        }

        Ok(None)
    }
}

impl Deserialize for Header {
    fn deserialize<D>(deserializer: &mut D) -> Result<Header, D::Error>
        where D: serde::Deserializer,
    {
        deserializer.deserialize(HeaderDeVisitor)
    }
}

struct HeaderDeVisitor;

impl serde::de::Visitor for HeaderDeVisitor {
    type Value = Header;

    fn visit_map<V>(&mut self, mut visitor: V) -> Result<Header, V::Error>
        where V: serde::de::MapVisitor,
    {
        let mut alg = None;
        let mut typ = None;
        let mut jku = None;
        let mut jwk = None;
        let mut kid = None;
        let mut x5u = None;
        let mut x5c = None;
        let mut x5t = None;
        let mut x5t_s256 = None;
        let mut cty = None;
        let mut crit = None;
        let mut custom_params = HashMap::<String, serde_json::value::Value>::new();

        loop {
            if let Some(key) = try!(visitor.visit_key::<String>()) {
                match &key[..] {
                    "alg" => { alg = Some(try!(visitor.visit_value())); }
                    "typ" => { typ = Some(try!(visitor.visit_value())); }
                    "kid" => { kid = Some(try!(visitor.visit_value())); }
                    "jku" => { jku = Some(try!(visitor.visit_value())); }
                    "jwk" => { jwk = Some(try!(visitor.visit_value())); }
                    "x5u" => { x5u = Some(try!(visitor.visit_value())); }
                    "x5c" => { x5c = Some(try!(visitor.visit_value())); }
                    "x5t" => { x5t = Some(try!(visitor.visit_value())); }
                    "x5t#s256" => { x5t_s256 = Some(try!(visitor.visit_value())); }
                    "cty" => { cty = Some(try!(visitor.visit_value())); }
                    "crit" => { crit = Some(try!(visitor.visit_value())); }

                    k => {
                        let v = try!(visitor.visit_value());

                        custom_params.entry(k.to_owned()).or_insert(v);
                    }
                }
            } else {
                break;
            }
        }

        let alg = match alg {
            Some(alg) => alg,
            None => try!(visitor.missing_field("alg")),
        };

        let typ = match typ {
            Some(typ) => typ,
            None => try!(visitor.missing_field("typ")),
        };

        try!(visitor.end());

        Ok(Header{
            alg: alg,
            typ: typ,
            kid: kid,
            jku: jku,
            jwk: jwk,
            x5u: x5u,
            x5c: x5c,
            x5t: x5t,
            x5t_s256: x5t_s256,
            cty: cty,
            crit: crit,
            custom_params: custom_params,
        })
    }
}

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

    #[test]
    fn test_header_serde() {
        let mut h = Header::default();
        h.jku = Some("https://example.com/jwk".to_owned());
        h.jwk = Some("".to_owned());
        h.kid = Some("one".to_owned());
        h.x5u = Some("https://example.com/x509cert".to_owned());
        h.x5c = Some(vec!["b64 jws cert".to_owned(), "b64 jws cert's CA etc".to_owned()]);
        h.x5t = Some("blah".to_owned());
        h.x5t_s256 = Some("blah256".to_owned());
        h.cty = Some("example".to_owned());
        h.crit = Some(vec!["exp".to_owned()]);
        h.custom_params.insert("exp".to_owned(), serde_json::to_value("soon"));

        let h_js = serde_json::to_string(&h).unwrap();

        let h2: Header = serde_json::from_str(&h_js).unwrap();

        assert_eq!(h, h2);
    }
}<|endoftext|>


<commit_before>use consts;

use errors::*;

use std::fmt;

use lib_futures::stream;
use lib_futures::{
    Async,
    Future,
    Poll,
};

pub use self::io_futures::{
    ConnectingStream,
    WritePacket,
};
use self::io_futures::{
    new_connecting_stream,
    new_write_packet,
};

use proto::{
    NewPacket,
    Packet,
    ParseResult,
};

use std::cmp;
use std::collections::vec_deque::VecDeque;
use std::io;
use std::io::Read;
use std::net::ToSocketAddrs;

use tokio::net::TcpStream;
use tokio::io::write_all;
use tokio::reactor::Handle;

mod io_futures;

pub struct Stream {
    endpoint: Option<TcpStream>,
    closed: bool,
    next_packet: Option<ParseResult>,
    buf: Option<VecDeque<u8>>,
}

impl fmt::Debug for Stream {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Stream (endpoint={:?})", self.endpoint)
    }
}

impl Drop for Stream {
    fn drop(&mut self) {
        let endpoint = self.endpoint.take().unwrap();
        let data = vec![1, 0, 0, 0, consts::Command::COM_QUIT as u8];
        let _ = write_all(endpoint, data).map(|_| ()).map_err(|_| ()).wait();
    }
}

impl Stream {
    pub fn connect<S>(addr: S, handle: &Handle) -> ConnectingStream
        where S: ToSocketAddrs,
    {
        new_connecting_stream(addr, handle)
    }

    pub fn write_packet(self, data: Vec<u8>, seq_id: u8) -> WritePacket {
        new_write_packet(self, data, seq_id)
    }
}

impl io::Read for Stream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.endpoint.as_mut().unwrap().read(buf)
    }
}

impl io::Write for Stream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.endpoint.as_mut().unwrap().write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.endpoint.as_mut().unwrap().flush()
    }
}

impl stream::Stream for Stream {
    type Item = (Packet, u8);
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<(Packet, u8)>, Error> {
        // should read everything from self.endpoint
        if ! self.closed {
            let mut buf = [0u8; 4096];
            loop {
                match self.endpoint.as_mut().unwrap().read(&mut buf[..]) {
                    Ok(0) => {
                        break;
                    },
                    Ok(size) => {
                        let buf_handle = self.buf.as_mut().unwrap();
                        buf_handle.extend(&buf[..size]);
                    },
                    Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
                        break;
                    },
                    Err(error) => {
                        self.closed = true;
                        return Err(Error::from(error))
                    },
                };
            }
        } else {
            return Ok(Async::Ready(None))
        }

        // need to call again if there is a data in self.buf
        // or data was written to packet parser
        let mut should_poll = false;

        let next_packet = self.next_packet.take().expect("Stream.next_packet should not be None");
        let next_packet = match next_packet {
            ParseResult::Done(packet, seq_id) => {
                self.next_packet = Some(NewPacket::empty().parse());
                return Ok(Async::Ready(Some((packet, seq_id))));
            },
            ParseResult::NeedHeader(mut new_packet, needed) => {
                {
                    let buf_handle = self.buf.as_mut().unwrap();
                    let buf_len = buf_handle.len();
                    for byte in buf_handle.drain(..cmp::min(needed, buf_len)) {
                        new_packet.push_header(byte);
                    }
                    if buf_len != 0 {
                        should_poll = true;
                    }

                    new_packet
                }
            }
            ParseResult::Incomplete(mut new_packet, needed) => {
                {
                    let buf_handle = self.buf.as_mut().unwrap();
                    let buf_len = buf_handle.len();
                    for byte in buf_handle.drain(..cmp::min(needed, buf_len)) {
                        new_packet.push(byte);
                    }
                    if buf_len != 0 {
                        should_poll = true;
                    }

                    new_packet
                }
            }
        };

        self.next_packet = Some(next_packet.parse());

        if should_poll {
            self.poll()
        } else {
            Ok(Async::NotReady)
        }
    }
}

#[cfg(test)]
mod tests {
    use io::Stream;

    use Opts;

    use proto::{HandshakePacket, HandshakeResponse};

    use lib_futures::Future;
    use lib_futures::stream::Stream as FuturesStream;

    use test_misc::DATABASE_URL;

    use tokio::reactor::Core;

    #[test]
    fn should_connect_stream() {
        let mut lp = Core::new().unwrap();

        let opts: Opts = (&**DATABASE_URL).into();
        let ip = opts.get_ip_or_hostname();
        let port = opts.get_tcp_port();

        let stream = Stream::connect((ip, port), &lp.handle()).and_then(|stream: Stream| {
            stream.into_future().map_err(|(err, _)| err)
        }).and_then(|(maybe_packet, stream)| {
            let (packet, _) = maybe_packet.expect("no handshake!?");
            let handshake = HandshakePacket::new(packet);
            let user = "root";
            let pass = "password";
            let handshake_response = HandshakeResponse::new(&handshake,
                                                            Some(user.as_bytes()),
                                                            Some(pass.as_bytes()),
                                                            None::<Vec<u8>>);
            stream.write_packet(handshake_response.as_ref().to_vec(), 1)
        }).and_then(|(stream, _)| {
            stream.into_future().map_err(|(err, _)| err)
        }).map(|(maybe_packet, _)| {
            let (_, _) = maybe_packet.expect("Should be here");
        });

        lp.run(stream).unwrap();
    }
}
<commit_msg>Remove Drop impl for io::stream<commit_after>use errors::*;

use std::fmt;

use lib_futures::stream;
use lib_futures::{
    Async,
    Poll,
};

pub use self::io_futures::{
    ConnectingStream,
    WritePacket,
};
use self::io_futures::{
    new_connecting_stream,
    new_write_packet,
};

use proto::{
    NewPacket,
    Packet,
    ParseResult,
};

use std::cmp;
use std::collections::vec_deque::VecDeque;
use std::io;
use std::io::Read;
use std::net::ToSocketAddrs;

use tokio::net::TcpStream;
use tokio::reactor::Handle;

mod io_futures;

pub struct Stream {
    endpoint: Option<TcpStream>,
    closed: bool,
    next_packet: Option<ParseResult>,
    buf: Option<VecDeque<u8>>,
}

impl fmt::Debug for Stream {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Stream (endpoint={:?})", self.endpoint)
    }
}

impl Stream {
    pub fn connect<S>(addr: S, handle: &Handle) -> ConnectingStream
        where S: ToSocketAddrs,
    {
        new_connecting_stream(addr, handle)
    }

    pub fn write_packet(self, data: Vec<u8>, seq_id: u8) -> WritePacket {
        new_write_packet(self, data, seq_id)
    }
}

impl io::Read for Stream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.endpoint.as_mut().unwrap().read(buf)
    }
}

impl io::Write for Stream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.endpoint.as_mut().unwrap().write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.endpoint.as_mut().unwrap().flush()
    }
}

impl stream::Stream for Stream {
    type Item = (Packet, u8);
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<(Packet, u8)>, Error> {
        // should read everything from self.endpoint
        if ! self.closed {
            let mut buf = [0u8; 4096];
            loop {
                match self.endpoint.as_mut().unwrap().read(&mut buf[..]) {
                    Ok(0) => {
                        break;
                    },
                    Ok(size) => {
                        let buf_handle = self.buf.as_mut().unwrap();
                        buf_handle.extend(&buf[..size]);
                    },
                    Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
                        break;
                    },
                    Err(error) => {
                        self.closed = true;
                        return Err(Error::from(error))
                    },
                };
            }
        } else {
            return Ok(Async::Ready(None))
        }

        // need to call again if there is a data in self.buf
        // or data was written to packet parser
        let mut should_poll = false;

        let next_packet = self.next_packet.take().expect("Stream.next_packet should not be None");
        let next_packet = match next_packet {
            ParseResult::Done(packet, seq_id) => {
                self.next_packet = Some(NewPacket::empty().parse());
                return Ok(Async::Ready(Some((packet, seq_id))));
            },
            ParseResult::NeedHeader(mut new_packet, needed) => {
                {
                    let buf_handle = self.buf.as_mut().unwrap();
                    let buf_len = buf_handle.len();
                    for byte in buf_handle.drain(..cmp::min(needed, buf_len)) {
                        new_packet.push_header(byte);
                    }
                    if buf_len != 0 {
                        should_poll = true;
                    }

                    new_packet
                }
            }
            ParseResult::Incomplete(mut new_packet, needed) => {
                {
                    let buf_handle = self.buf.as_mut().unwrap();
                    let buf_len = buf_handle.len();
                    for byte in buf_handle.drain(..cmp::min(needed, buf_len)) {
                        new_packet.push(byte);
                    }
                    if buf_len != 0 {
                        should_poll = true;
                    }

                    new_packet
                }
            }
        };

        self.next_packet = Some(next_packet.parse());

        if should_poll {
            self.poll()
        } else {
            Ok(Async::NotReady)
        }
    }
}

#[cfg(test)]
mod tests {
    use io::Stream;

    use Opts;

    use proto::{HandshakePacket, HandshakeResponse};

    use lib_futures::Future;
    use lib_futures::stream::Stream as FuturesStream;

    use test_misc::DATABASE_URL;

    use tokio::reactor::Core;

    #[test]
    fn should_connect_stream() {
        let mut lp = Core::new().unwrap();

        let opts: Opts = (&**DATABASE_URL).into();
        let ip = opts.get_ip_or_hostname();
        let port = opts.get_tcp_port();

        let stream = Stream::connect((ip, port), &lp.handle()).and_then(|stream: Stream| {
            stream.into_future().map_err(|(err, _)| err)
        }).and_then(|(maybe_packet, stream)| {
            let (packet, _) = maybe_packet.expect("no handshake!?");
            let handshake = HandshakePacket::new(packet);
            let user = "root";
            let pass = "password";
            let handshake_response = HandshakeResponse::new(&handshake,
                                                            Some(user.as_bytes()),
                                                            Some(pass.as_bytes()),
                                                            None::<Vec<u8>>);
            stream.write_packet(handshake_response.as_ref().to_vec(), 1)
        }).and_then(|(stream, _)| {
            stream.into_future().map_err(|(err, _)| err)
        }).map(|(maybe_packet, _)| {
            let (_, _) = maybe_packet.expect("Should be here");
        });

        lp.run(stream).unwrap();
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::sync::Arc;
use command_buffer::cb::AddCommand;
use command_buffer::cb::CommandBufferBuild;
use command_buffer::CommandBufferBuilder;
use command_buffer::commands_raw;
use device::Device;
use device::DeviceOwned;

/// Layer around a command buffer builder that checks whether the commands can be executed in the
/// given context related to render passes.
///
/// What is checked exactly:
///
/// - When adding a command that can only be executed within a render pass or outside of a render
///   pass, checks that we are within or outside of a render pass.
/// - When leaving the render pass or going to the next subpass, makes sure that the number of
///   subpasses of the current render pass is respected.
/// - When binding a graphics pipeline or drawing, makes sure that the pipeline is valid for the
///   current render pass.
///
pub struct ContextCheckLayer<I> {
    // Inner command buffer builder.
    inner: I,
    // True if we are currently inside a render pass.
    inside_render_pass: bool,
    // True if entering/leaving a render pass or going to the next subpass is allowed.
    allow_render_pass_ops: bool,
}

impl<I> ContextCheckLayer<I> {
    /// Builds a new `ContextCheckLayer`.
    ///
    /// If `allow_render_pass_ops` is true, then entering/leaving a render pass or going to the
    /// next subpass is allowed by the layer.
    ///
    /// If `inside_render_pass` is true, then the builder is currently inside a render pass.
    ///
    /// Note that this layer will only protect you if you pass correct values in this constructor.
    /// It is not unsafe to pass wrong values, but if you do so then the layer will be inefficient
    /// as a safety tool.
    #[inline]
    pub fn new(inner: I, inside_render_pass: bool, allow_render_pass_ops: bool)
               -> ContextCheckLayer<I>
    {
        ContextCheckLayer {
            inner: inner,
            inside_render_pass: inside_render_pass,
            allow_render_pass_ops: allow_render_pass_ops,
        }
    }

    /// Destroys the layer and returns the underlying command buffer.
    #[inline]
    pub fn into_inner(self) -> I {
        self.inner
    }
}

unsafe impl<I, O, E> CommandBufferBuild for ContextCheckLayer<I>
    where I: CommandBufferBuild<Out = O, Err = E>
{
    type Out = O;
    type Err = E;

    #[inline]
    fn build(self) -> Result<O, E> {
        self.inner.build()
    }
}

unsafe impl<I> DeviceOwned for ContextCheckLayer<I>
    where I: DeviceOwned
{
    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.inner.device()
    }
}

unsafe impl<I> CommandBufferBuilder for ContextCheckLayer<I>
    where I: CommandBufferBuilder
{
    #[inline]
    fn supports_graphics(&self) -> bool {
        self.inner.supports_graphics()
    }

    #[inline]
    fn supports_compute(&self) -> bool {
        self.inner.supports_compute()
    }
}

// TODO:
// impl!((C), commands_raw::CmdExecuteCommands<C>);

// FIXME: must also check that a pipeline's render pass matches the render pass

// FIXME:
// > If the variable multisample rate feature is not supported, pipeline is a graphics pipeline,
// > the current subpass has no attachments, and this is not the first call to this function with
// > a graphics pipeline after transitioning to the current subpass, then the sample count
// > specified by this pipeline must match that set in the previous pipeline

macro_rules! impl_always {
    (($($param:ident),*), $cmd:ty) => {
        unsafe impl<'a, I, O $(, $param)*> AddCommand<$cmd> for ContextCheckLayer<I>
            where I: AddCommand<$cmd, Out = O>
        {
            type Out = ContextCheckLayer<O>;

            #[inline]
            fn add(self, command: $cmd) -> Self::Out {
                ContextCheckLayer {
                    inner: self.inner.add(command),
                    inside_render_pass: self.inside_render_pass,
                    allow_render_pass_ops: self.allow_render_pass_ops,
                }
            }
        }
    }
}

impl_always!((S, Pl), commands_raw::CmdBindDescriptorSets<S, Pl>);
impl_always!((B), commands_raw::CmdBindIndexBuffer<B>);
impl_always!((Pl), commands_raw::CmdBindPipeline<Pl>);
impl_always!((V), commands_raw::CmdBindVertexBuffers<V>);
impl_always!((Pc, Pl), commands_raw::CmdPushConstants<Pc, Pl>);

macro_rules! impl_inside_only {
    (($($param:ident),*), $cmd:ty) => {
        unsafe impl<'a, I, O $(, $param)*> AddCommand<$cmd> for ContextCheckLayer<I>
            where I: AddCommand<$cmd, Out = O>
        {
            type Out = ContextCheckLayer<O>;

            #[inline]
            fn add(self, command: $cmd) -> Self::Out {
                assert!(self.inside_render_pass);       // TODO: proper error

                ContextCheckLayer {
                    inner: self.inner.add(command),
                    inside_render_pass: self.inside_render_pass,
                    allow_render_pass_ops: self.allow_render_pass_ops,
                }
            }
        }
    }
}

impl_inside_only!((), commands_raw::CmdClearAttachments);
impl_inside_only!((), commands_raw::CmdDrawIndexedRaw);
impl_inside_only!((B), commands_raw::CmdDrawIndirectRaw<B>);
impl_inside_only!((), commands_raw::CmdDrawRaw);

macro_rules! impl_outside_only {
    (($($param:ident),*), $cmd:ty) => {
        unsafe impl<'a, I, O $(, $param)*> AddCommand<$cmd> for ContextCheckLayer<I>
            where I: AddCommand<$cmd, Out = O>
        {
            type Out = ContextCheckLayer<O>;

            #[inline]
            fn add(self, command: $cmd) -> Self::Out {
                assert!(!self.inside_render_pass);       // TODO: proper error

                ContextCheckLayer {
                    inner: self.inner.add(command),
                    inside_render_pass: self.inside_render_pass,
                    allow_render_pass_ops: self.allow_render_pass_ops,
                }
            }
        }
    }
}

impl_outside_only!((S, D), commands_raw::CmdBlitImage<S, D>);
impl_outside_only!((S, D), commands_raw::CmdCopyBuffer<S, D>);
impl_outside_only!((S, D), commands_raw::CmdCopyBufferToImage<S, D>);
impl_outside_only!((S, D), commands_raw::CmdCopyImage<S, D>);
impl_outside_only!((), commands_raw::CmdDispatchRaw);
impl_outside_only!((B), commands_raw::CmdFillBuffer<B>);
impl_outside_only!((S, D), commands_raw::CmdResolveImage<S, D>);
impl_outside_only!((), commands_raw::CmdSetEvent);
impl_outside_only!((), commands_raw::CmdSetState);
impl_outside_only!((B, D), commands_raw::CmdUpdateBuffer<B, D>);

unsafe impl<'a, I, O, Rp, F> AddCommand<commands_raw::CmdBeginRenderPass<Rp, F>> for ContextCheckLayer<I>
    where I: AddCommand<commands_raw::CmdBeginRenderPass<Rp, F>, Out = O>
{
    type Out = ContextCheckLayer<O>;

    #[inline]
    fn add(self, command: commands_raw::CmdBeginRenderPass<Rp, F>) -> Self::Out {
        assert!(!self.inside_render_pass);       // TODO: proper error
        assert!(self.allow_render_pass_ops);     // TODO: proper error

        ContextCheckLayer {
            inner: self.inner.add(command),
            inside_render_pass: true,
            allow_render_pass_ops: true,
        }
    }
}

unsafe impl<'a, I, O> AddCommand<commands_raw::CmdNextSubpass> for ContextCheckLayer<I>
    where I: AddCommand<commands_raw::CmdNextSubpass, Out = O>
{
    type Out = ContextCheckLayer<O>;

    #[inline]
    fn add(self, command: commands_raw::CmdNextSubpass) -> Self::Out {
        assert!(self.inside_render_pass);       // TODO: proper error
        assert!(self.allow_render_pass_ops);    // TODO: proper error
        // FIXME: check number of subpasses

        ContextCheckLayer {
            inner: self.inner.add(command),
            inside_render_pass: true,
            allow_render_pass_ops: true,
        }
    }
}

unsafe impl<'a, I, O> AddCommand<commands_raw::CmdEndRenderPass> for ContextCheckLayer<I>
    where I: AddCommand<commands_raw::CmdEndRenderPass, Out = O>
{
    type Out = ContextCheckLayer<O>;

    #[inline]
    fn add(self, command: commands_raw::CmdEndRenderPass) -> Self::Out {
        assert!(self.inside_render_pass);       // TODO: proper error
        assert!(self.allow_render_pass_ops);    // TODO: proper error
        // FIXME: check number of subpasses

        ContextCheckLayer {
            inner: self.inner.add(command),
            inside_render_pass: false,
            allow_render_pass_ops: true,
        }
    }
}
<commit_msg>Fix CmdSetState only outside render pass<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::sync::Arc;
use command_buffer::cb::AddCommand;
use command_buffer::cb::CommandBufferBuild;
use command_buffer::CommandBufferBuilder;
use command_buffer::commands_raw;
use device::Device;
use device::DeviceOwned;

/// Layer around a command buffer builder that checks whether the commands can be executed in the
/// given context related to render passes.
///
/// What is checked exactly:
///
/// - When adding a command that can only be executed within a render pass or outside of a render
///   pass, checks that we are within or outside of a render pass.
/// - When leaving the render pass or going to the next subpass, makes sure that the number of
///   subpasses of the current render pass is respected.
/// - When binding a graphics pipeline or drawing, makes sure that the pipeline is valid for the
///   current render pass.
///
pub struct ContextCheckLayer<I> {
    // Inner command buffer builder.
    inner: I,
    // True if we are currently inside a render pass.
    inside_render_pass: bool,
    // True if entering/leaving a render pass or going to the next subpass is allowed.
    allow_render_pass_ops: bool,
}

impl<I> ContextCheckLayer<I> {
    /// Builds a new `ContextCheckLayer`.
    ///
    /// If `allow_render_pass_ops` is true, then entering/leaving a render pass or going to the
    /// next subpass is allowed by the layer.
    ///
    /// If `inside_render_pass` is true, then the builder is currently inside a render pass.
    ///
    /// Note that this layer will only protect you if you pass correct values in this constructor.
    /// It is not unsafe to pass wrong values, but if you do so then the layer will be inefficient
    /// as a safety tool.
    #[inline]
    pub fn new(inner: I, inside_render_pass: bool, allow_render_pass_ops: bool)
               -> ContextCheckLayer<I>
    {
        ContextCheckLayer {
            inner: inner,
            inside_render_pass: inside_render_pass,
            allow_render_pass_ops: allow_render_pass_ops,
        }
    }

    /// Destroys the layer and returns the underlying command buffer.
    #[inline]
    pub fn into_inner(self) -> I {
        self.inner
    }
}

unsafe impl<I, O, E> CommandBufferBuild for ContextCheckLayer<I>
    where I: CommandBufferBuild<Out = O, Err = E>
{
    type Out = O;
    type Err = E;

    #[inline]
    fn build(self) -> Result<O, E> {
        self.inner.build()
    }
}

unsafe impl<I> DeviceOwned for ContextCheckLayer<I>
    where I: DeviceOwned
{
    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.inner.device()
    }
}

unsafe impl<I> CommandBufferBuilder for ContextCheckLayer<I>
    where I: CommandBufferBuilder
{
    #[inline]
    fn supports_graphics(&self) -> bool {
        self.inner.supports_graphics()
    }

    #[inline]
    fn supports_compute(&self) -> bool {
        self.inner.supports_compute()
    }
}

// TODO:
// impl!((C), commands_raw::CmdExecuteCommands<C>);

// FIXME: must also check that a pipeline's render pass matches the render pass

// FIXME:
// > If the variable multisample rate feature is not supported, pipeline is a graphics pipeline,
// > the current subpass has no attachments, and this is not the first call to this function with
// > a graphics pipeline after transitioning to the current subpass, then the sample count
// > specified by this pipeline must match that set in the previous pipeline

macro_rules! impl_always {
    (($($param:ident),*), $cmd:ty) => {
        unsafe impl<'a, I, O $(, $param)*> AddCommand<$cmd> for ContextCheckLayer<I>
            where I: AddCommand<$cmd, Out = O>
        {
            type Out = ContextCheckLayer<O>;

            #[inline]
            fn add(self, command: $cmd) -> Self::Out {
                ContextCheckLayer {
                    inner: self.inner.add(command),
                    inside_render_pass: self.inside_render_pass,
                    allow_render_pass_ops: self.allow_render_pass_ops,
                }
            }
        }
    }
}

impl_always!((S, Pl), commands_raw::CmdBindDescriptorSets<S, Pl>);
impl_always!((B), commands_raw::CmdBindIndexBuffer<B>);
impl_always!((Pl), commands_raw::CmdBindPipeline<Pl>);
impl_always!((V), commands_raw::CmdBindVertexBuffers<V>);
impl_always!((Pc, Pl), commands_raw::CmdPushConstants<Pc, Pl>);
impl_always!((), commands_raw::CmdSetState);

macro_rules! impl_inside_only {
    (($($param:ident),*), $cmd:ty) => {
        unsafe impl<'a, I, O $(, $param)*> AddCommand<$cmd> for ContextCheckLayer<I>
            where I: AddCommand<$cmd, Out = O>
        {
            type Out = ContextCheckLayer<O>;

            #[inline]
            fn add(self, command: $cmd) -> Self::Out {
                assert!(self.inside_render_pass);       // TODO: proper error

                ContextCheckLayer {
                    inner: self.inner.add(command),
                    inside_render_pass: self.inside_render_pass,
                    allow_render_pass_ops: self.allow_render_pass_ops,
                }
            }
        }
    }
}

impl_inside_only!((), commands_raw::CmdClearAttachments);
impl_inside_only!((), commands_raw::CmdDrawIndexedRaw);
impl_inside_only!((B), commands_raw::CmdDrawIndirectRaw<B>);
impl_inside_only!((), commands_raw::CmdDrawRaw);

macro_rules! impl_outside_only {
    (($($param:ident),*), $cmd:ty) => {
        unsafe impl<'a, I, O $(, $param)*> AddCommand<$cmd> for ContextCheckLayer<I>
            where I: AddCommand<$cmd, Out = O>
        {
            type Out = ContextCheckLayer<O>;

            #[inline]
            fn add(self, command: $cmd) -> Self::Out {
                assert!(!self.inside_render_pass);       // TODO: proper error

                ContextCheckLayer {
                    inner: self.inner.add(command),
                    inside_render_pass: self.inside_render_pass,
                    allow_render_pass_ops: self.allow_render_pass_ops,
                }
            }
        }
    }
}

impl_outside_only!((S, D), commands_raw::CmdBlitImage<S, D>);
impl_outside_only!((S, D), commands_raw::CmdCopyBuffer<S, D>);
impl_outside_only!((S, D), commands_raw::CmdCopyBufferToImage<S, D>);
impl_outside_only!((S, D), commands_raw::CmdCopyImage<S, D>);
impl_outside_only!((), commands_raw::CmdDispatchRaw);
impl_outside_only!((B), commands_raw::CmdFillBuffer<B>);
impl_outside_only!((S, D), commands_raw::CmdResolveImage<S, D>);
impl_outside_only!((), commands_raw::CmdSetEvent);
impl_outside_only!((B, D), commands_raw::CmdUpdateBuffer<B, D>);

unsafe impl<'a, I, O, Rp, F> AddCommand<commands_raw::CmdBeginRenderPass<Rp, F>> for ContextCheckLayer<I>
    where I: AddCommand<commands_raw::CmdBeginRenderPass<Rp, F>, Out = O>
{
    type Out = ContextCheckLayer<O>;

    #[inline]
    fn add(self, command: commands_raw::CmdBeginRenderPass<Rp, F>) -> Self::Out {
        assert!(!self.inside_render_pass);       // TODO: proper error
        assert!(self.allow_render_pass_ops);     // TODO: proper error

        ContextCheckLayer {
            inner: self.inner.add(command),
            inside_render_pass: true,
            allow_render_pass_ops: true,
        }
    }
}

unsafe impl<'a, I, O> AddCommand<commands_raw::CmdNextSubpass> for ContextCheckLayer<I>
    where I: AddCommand<commands_raw::CmdNextSubpass, Out = O>
{
    type Out = ContextCheckLayer<O>;

    #[inline]
    fn add(self, command: commands_raw::CmdNextSubpass) -> Self::Out {
        assert!(self.inside_render_pass);       // TODO: proper error
        assert!(self.allow_render_pass_ops);    // TODO: proper error
        // FIXME: check number of subpasses

        ContextCheckLayer {
            inner: self.inner.add(command),
            inside_render_pass: true,
            allow_render_pass_ops: true,
        }
    }
}

unsafe impl<'a, I, O> AddCommand<commands_raw::CmdEndRenderPass> for ContextCheckLayer<I>
    where I: AddCommand<commands_raw::CmdEndRenderPass, Out = O>
{
    type Out = ContextCheckLayer<O>;

    #[inline]
    fn add(self, command: commands_raw::CmdEndRenderPass) -> Self::Out {
        assert!(self.inside_render_pass);       // TODO: proper error
        assert!(self.allow_render_pass_ops);    // TODO: proper error
        // FIXME: check number of subpasses

        ContextCheckLayer {
            inner: self.inner.add(command),
            inside_render_pass: false,
            allow_render_pass_ops: true,
        }
    }
}
<|endoftext|>