<commit_before>#![feature(unsafe_destructor,core,std_misc)]
#![unstable]

//! The purpose of this library is to provide an OpenGL context on as many
//!  platforms as possible.
//!
//! # Building a window
//!
//! There are two ways to create a window:
//!
//!  - Calling `Window::new()`.
//!  - Calling `let builder = WindowBuilder::new()` then `builder.build()`.
//!
//! The first way is the simpliest way and will give you default values.
//!
//! The second way allows you to customize the way your window and GL context
//!  will look and behave.
//!
//! # Features
//!
//! This crate has two Cargo features: `window` and `headless`.
//!
//!  - `window` allows you to create regular windows and enables the `WindowBuilder` object.
//!  - `headless` allows you to do headless rendering, and enables
//!     the `HeadlessRendererBuilder` object.
//!
//! By default only `window` is enabled.

extern crate gl_common;
extern crate libc;

#[cfg(target_os = "windows")]
extern crate winapi;
#[cfg(target_os = "windows")]
extern crate "kernel32-sys" as kernel32;
#[cfg(target_os = "windows")]
extern crate "gdi32-sys" as gdi32;
#[cfg(target_os = "windows")]
extern crate "user32-sys" as user32;
#[cfg(target_os = "macos")]
extern crate cocoa;
#[cfg(target_os = "macos")]
extern crate core_foundation;
#[cfg(target_os = "macos")]
extern crate core_graphics;

pub use events::*;
#[cfg(feature = "headless")]
pub use headless::{HeadlessRendererBuilder, HeadlessContext};
#[cfg(feature = "window")]
pub use window::{WindowBuilder, Window, WindowProxy, PollEventsIterator, WaitEventsIterator};
#[cfg(feature = "window")]
pub use window::{AvailableMonitorsIter, MonitorID, get_available_monitors, get_primary_monitor};

#[cfg(all(not(target_os = "windows"), not(target_os = "linux"), not(target_os = "macos"), not(target_os = "android")))]
use this_platform_is_not_supported;

#[cfg(target_os = "windows")]
#[path="win32/mod.rs"]
mod winimpl;
#[cfg(target_os = "linux")]
#[path="x11/mod.rs"]
mod winimpl;
#[cfg(target_os = "macos")]
#[path="cocoa/mod.rs"]
mod winimpl;
#[cfg(target_os = "android")]
#[path="android/mod.rs"]
mod winimpl;

mod events;
#[cfg(feature = "headless")]
mod headless;
#[cfg(feature = "window")]
mod window;

/// Error that can happen while creating a window or a headless renderer.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum CreationError {
    OsError(String),
    NotSupported,
}

impl CreationError {
    fn to_string(&self) -> &str {
        match *self {
            CreationError::OsError(ref text) => text.as_slice(),
            CreationError::NotSupported => "Some of the requested attributes are not supported",
        }
    }
}

impl std::fmt::Display for CreationError {
    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        formatter.write_str(self.to_string())
    }
}

impl std::error::Error for CreationError {
    fn description(&self) -> &str {
        self.to_string()
    }
}

/// All APIs related to OpenGL that you can possibly get while using glutin.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Api {
    /// The classical OpenGL. Available on Windows, Linux, OS/X.
    OpenGl,
    /// OpenGL embedded system. Available on Linux, Android.
    OpenGlEs,
    /// OpenGL for the web. Very similar to OpenGL ES.
    WebGl,
}

/// Describes the OpenGL API and version that are being requested when a context is created.
#[derive(Debug, Copy, Clone)]
pub enum GlRequest {
    /// Request the latest version of the "best" API of this platform.
    ///
    /// On desktop, will try OpenGL.
    Latest,

    /// Request a specific version of a specific API.
    ///
    /// Example: `GlRequest::Specific(Api::OpenGl, (3, 3))`.
    Specific(Api, (u8, u8)),

    /// If OpenGL is available, create an OpenGL context with the specified `opengl_version`.
    /// Else if OpenGL ES or WebGL is available, create a context with the
    /// specified `opengles_version`.
    GlThenGles {
        /// The version to use for OpenGL.
        opengl_version: (u8, u8),
        /// The version to use for OpenGL ES.
        opengles_version: (u8, u8),
    },
}

#[derive(Debug, Copy)]
pub enum MouseCursor {
    /// The platform-dependent default cursor.
    Default,
    /// A simple crosshair.
    Crosshair,
    /// A hand (often used to indicate links in web browsers).
    Hand,
    /// Self explanatory.
    Arrow,
    /// Indicates something is to be moved.
    Move,
    /// Indicates text that may be selected or edited.
    Text,
    /// Program busy indicator.
    Wait,
    /// Help indicator (often rendered as a "?")
    Help,
    /// Progress indicator. Shows that processing is being done. But in contrast
    /// with "Wait" the user may still interact with the program. Often rendered
    /// as a spinning beach ball, or an arrow with a watch or hourglass.
    Progress,

    /// Cursor showing that something cannot be done.
    NotAllowed,
    ContextMenu,
    NoneCursor,
    Cell,
    VerticalText,
    Alias,
    Copy,
    NoDrop,
    Grab,
    Grabbing,
    AllScroll,
    ZoomIn,
    ZoomOut,

    /// Indicate that some edge is to be moved. For example, the 'SeResize' cursor
    /// is used when the movement starts from the south-east corner of the box.
    EResize,
    NResize,
    NeResize,
    NwResize,
    SResize,
    SeResize,
    SwResize,
    WResize,
    EwResize,
    NsResize,
    NeswResize,
    NwseResize,
    ColResize,
    RowResize,
}

/// Describes a possible format. Unused.
#[allow(missing_docs)]
#[derive(Debug)]
pub struct PixelFormat {
    pub hardware_accelerated: bool,
    pub red_bits: u8,
    pub green_bits: u8,
    pub blue_bits: u8,
    pub alpha_bits: u8,
    pub depth_bits: u8,
    pub stencil_bits: u8,
    pub stereoscopy: bool,
    pub double_buffer: bool,
    pub multisampling: Option<u16>,
    pub srgb: bool,
}

/// Attributes
struct BuilderAttribs<'a> {
    #[allow(dead_code)]
    headless: bool,
    strict: bool,
    sharing: Option<&'a winimpl::Window>,
    dimensions: Option<(u32, u32)>,
    title: String,
    monitor: Option<winimpl::MonitorID>,
    gl_version: GlRequest,
    gl_debug: bool,
    vsync: bool,
    visible: bool,
    multisampling: Option<u16>,
    depth_bits: Option<u8>,
    stencil_bits: Option<u8>,
    color_bits: Option<u8>,
    alpha_bits: Option<u8>,
    stereoscopy: bool,
}

impl BuilderAttribs<'static> {
    fn new() -> BuilderAttribs<'static> {
        BuilderAttribs {
            headless: false,
            strict: false,
            sharing: None,
            dimensions: None,
            title: "glutin window".to_string(),
            monitor: None,
            gl_version: GlRequest::Latest,
            gl_debug: cfg!(ndebug),
            vsync: false,
            visible: true,
            multisampling: None,
            depth_bits: None,
            stencil_bits: None,
            color_bits: None,
            alpha_bits: None,
            stereoscopy: false,
        }
    }
}

impl<'a> BuilderAttribs<'a> {
    fn extract_non_static(mut self) -> (BuilderAttribs<'static>, Option<&'a winimpl::Window>) {
        let sharing = self.sharing.take();

        let new_attribs = BuilderAttribs {
            headless: self.headless,
            strict: self.strict,
            sharing: None,
            dimensions: self.dimensions,
            title: self.title,
            monitor: self.monitor,
            gl_version: self.gl_version,
            gl_debug: self.gl_debug,
            vsync: self.vsync,
            visible: self.visible,
            multisampling: self.multisampling,
            depth_bits: self.depth_bits,
            stencil_bits: self.stencil_bits,
            color_bits: self.color_bits,
            alpha_bits: self.alpha_bits,
            stereoscopy: self.stereoscopy,
        };

        (new_attribs, sharing)
    }

    fn choose_pixel_format<T, I>(&self, iter: I) -> (T, PixelFormat)
                                 where I: Iterator<Item=(T, PixelFormat)>, T: Clone
    {
        let mut current_result = None;

        // TODO: do this more properly
        for (id, format) in iter {
            if !format.hardware_accelerated {
                continue;
            }

            if format.red_bits + format.green_bits + format.blue_bits < self.color_bits.unwrap_or(0) {
                continue;
            }

            if format.alpha_bits < self.alpha_bits.unwrap_or(0) {
                continue;
            }

            if format.depth_bits < self.depth_bits.unwrap_or(0) {
                continue;
            }

            if format.stencil_bits < self.stencil_bits.unwrap_or(0) {
                continue;
            }

            if !format.stereoscopy && self.stereoscopy {
                continue;
            }

            if self.multisampling.is_some() && format.multisampling.is_none() {
                continue;
            }

            current_result = Some((id, format));
        }

        current_result.expect("Could not find compliant pixel format")
    }
}
<commit_msg>Allow using non-hardware-accelerated pixel formats<commit_after>#![feature(unsafe_destructor,core,std_misc)]
#![unstable]

//! The purpose of this library is to provide an OpenGL context on as many
//!  platforms as possible.
//!
//! # Building a window
//!
//! There are two ways to create a window:
//!
//!  - Calling `Window::new()`.
//!  - Calling `let builder = WindowBuilder::new()` then `builder.build()`.
//!
//! The first way is the simpliest way and will give you default values.
//!
//! The second way allows you to customize the way your window and GL context
//!  will look and behave.
//!
//! # Features
//!
//! This crate has two Cargo features: `window` and `headless`.
//!
//!  - `window` allows you to create regular windows and enables the `WindowBuilder` object.
//!  - `headless` allows you to do headless rendering, and enables
//!     the `HeadlessRendererBuilder` object.
//!
//! By default only `window` is enabled.

extern crate gl_common;
extern crate libc;

#[cfg(target_os = "windows")]
extern crate winapi;
#[cfg(target_os = "windows")]
extern crate "kernel32-sys" as kernel32;
#[cfg(target_os = "windows")]
extern crate "gdi32-sys" as gdi32;
#[cfg(target_os = "windows")]
extern crate "user32-sys" as user32;
#[cfg(target_os = "macos")]
extern crate cocoa;
#[cfg(target_os = "macos")]
extern crate core_foundation;
#[cfg(target_os = "macos")]
extern crate core_graphics;

pub use events::*;
#[cfg(feature = "headless")]
pub use headless::{HeadlessRendererBuilder, HeadlessContext};
#[cfg(feature = "window")]
pub use window::{WindowBuilder, Window, WindowProxy, PollEventsIterator, WaitEventsIterator};
#[cfg(feature = "window")]
pub use window::{AvailableMonitorsIter, MonitorID, get_available_monitors, get_primary_monitor};

#[cfg(all(not(target_os = "windows"), not(target_os = "linux"), not(target_os = "macos"), not(target_os = "android")))]
use this_platform_is_not_supported;

#[cfg(target_os = "windows")]
#[path="win32/mod.rs"]
mod winimpl;
#[cfg(target_os = "linux")]
#[path="x11/mod.rs"]
mod winimpl;
#[cfg(target_os = "macos")]
#[path="cocoa/mod.rs"]
mod winimpl;
#[cfg(target_os = "android")]
#[path="android/mod.rs"]
mod winimpl;

mod events;
#[cfg(feature = "headless")]
mod headless;
#[cfg(feature = "window")]
mod window;

/// Error that can happen while creating a window or a headless renderer.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum CreationError {
    OsError(String),
    NotSupported,
}

impl CreationError {
    fn to_string(&self) -> &str {
        match *self {
            CreationError::OsError(ref text) => text.as_slice(),
            CreationError::NotSupported => "Some of the requested attributes are not supported",
        }
    }
}

impl std::fmt::Display for CreationError {
    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        formatter.write_str(self.to_string())
    }
}

impl std::error::Error for CreationError {
    fn description(&self) -> &str {
        self.to_string()
    }
}

/// All APIs related to OpenGL that you can possibly get while using glutin.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Api {
    /// The classical OpenGL. Available on Windows, Linux, OS/X.
    OpenGl,
    /// OpenGL embedded system. Available on Linux, Android.
    OpenGlEs,
    /// OpenGL for the web. Very similar to OpenGL ES.
    WebGl,
}

/// Describes the OpenGL API and version that are being requested when a context is created.
#[derive(Debug, Copy, Clone)]
pub enum GlRequest {
    /// Request the latest version of the "best" API of this platform.
    ///
    /// On desktop, will try OpenGL.
    Latest,

    /// Request a specific version of a specific API.
    ///
    /// Example: `GlRequest::Specific(Api::OpenGl, (3, 3))`.
    Specific(Api, (u8, u8)),

    /// If OpenGL is available, create an OpenGL context with the specified `opengl_version`.
    /// Else if OpenGL ES or WebGL is available, create a context with the
    /// specified `opengles_version`.
    GlThenGles {
        /// The version to use for OpenGL.
        opengl_version: (u8, u8),
        /// The version to use for OpenGL ES.
        opengles_version: (u8, u8),
    },
}

#[derive(Debug, Copy)]
pub enum MouseCursor {
    /// The platform-dependent default cursor.
    Default,
    /// A simple crosshair.
    Crosshair,
    /// A hand (often used to indicate links in web browsers).
    Hand,
    /// Self explanatory.
    Arrow,
    /// Indicates something is to be moved.
    Move,
    /// Indicates text that may be selected or edited.
    Text,
    /// Program busy indicator.
    Wait,
    /// Help indicator (often rendered as a "?")
    Help,
    /// Progress indicator. Shows that processing is being done. But in contrast
    /// with "Wait" the user may still interact with the program. Often rendered
    /// as a spinning beach ball, or an arrow with a watch or hourglass.
    Progress,

    /// Cursor showing that something cannot be done.
    NotAllowed,
    ContextMenu,
    NoneCursor,
    Cell,
    VerticalText,
    Alias,
    Copy,
    NoDrop,
    Grab,
    Grabbing,
    AllScroll,
    ZoomIn,
    ZoomOut,

    /// Indicate that some edge is to be moved. For example, the 'SeResize' cursor
    /// is used when the movement starts from the south-east corner of the box.
    EResize,
    NResize,
    NeResize,
    NwResize,
    SResize,
    SeResize,
    SwResize,
    WResize,
    EwResize,
    NsResize,
    NeswResize,
    NwseResize,
    ColResize,
    RowResize,
}

/// Describes a possible format. Unused.
#[allow(missing_docs)]
#[derive(Debug, Clone)]
pub struct PixelFormat {
    pub hardware_accelerated: bool,
    pub red_bits: u8,
    pub green_bits: u8,
    pub blue_bits: u8,
    pub alpha_bits: u8,
    pub depth_bits: u8,
    pub stencil_bits: u8,
    pub stereoscopy: bool,
    pub double_buffer: bool,
    pub multisampling: Option<u16>,
    pub srgb: bool,
}

/// Attributes
struct BuilderAttribs<'a> {
    #[allow(dead_code)]
    headless: bool,
    strict: bool,
    sharing: Option<&'a winimpl::Window>,
    dimensions: Option<(u32, u32)>,
    title: String,
    monitor: Option<winimpl::MonitorID>,
    gl_version: GlRequest,
    gl_debug: bool,
    vsync: bool,
    visible: bool,
    multisampling: Option<u16>,
    depth_bits: Option<u8>,
    stencil_bits: Option<u8>,
    color_bits: Option<u8>,
    alpha_bits: Option<u8>,
    stereoscopy: bool,
}

impl BuilderAttribs<'static> {
    fn new() -> BuilderAttribs<'static> {
        BuilderAttribs {
            headless: false,
            strict: false,
            sharing: None,
            dimensions: None,
            title: "glutin window".to_string(),
            monitor: None,
            gl_version: GlRequest::Latest,
            gl_debug: cfg!(ndebug),
            vsync: false,
            visible: true,
            multisampling: None,
            depth_bits: None,
            stencil_bits: None,
            color_bits: None,
            alpha_bits: None,
            stereoscopy: false,
        }
    }
}

impl<'a> BuilderAttribs<'a> {
    fn extract_non_static(mut self) -> (BuilderAttribs<'static>, Option<&'a winimpl::Window>) {
        let sharing = self.sharing.take();

        let new_attribs = BuilderAttribs {
            headless: self.headless,
            strict: self.strict,
            sharing: None,
            dimensions: self.dimensions,
            title: self.title,
            monitor: self.monitor,
            gl_version: self.gl_version,
            gl_debug: self.gl_debug,
            vsync: self.vsync,
            visible: self.visible,
            multisampling: self.multisampling,
            depth_bits: self.depth_bits,
            stencil_bits: self.stencil_bits,
            color_bits: self.color_bits,
            alpha_bits: self.alpha_bits,
            stereoscopy: self.stereoscopy,
        };

        (new_attribs, sharing)
    }

    fn choose_pixel_format<T, I>(&self, iter: I) -> (T, PixelFormat)
                                 where I: Iterator<Item=(T, PixelFormat)>, T: Clone
    {
        let mut current_result = None;
        let mut current_software_result = None;

        // TODO: do this more properly
        for (id, format) in iter {
            if format.red_bits + format.green_bits + format.blue_bits < self.color_bits.unwrap_or(0) {
                continue;
            }

            if format.alpha_bits < self.alpha_bits.unwrap_or(0) {
                continue;
            }

            if format.depth_bits < self.depth_bits.unwrap_or(0) {
                continue;
            }

            if format.stencil_bits < self.stencil_bits.unwrap_or(0) {
                continue;
            }

            if !format.stereoscopy && self.stereoscopy {
                continue;
            }

            if self.multisampling.is_some() && format.multisampling.is_none() {
                continue;
            }

            current_software_result = Some((id.clone(), format.clone()));
            if format.hardware_accelerated {
                current_result = Some((id, format));
            }
        }

        current_result.or(current_software_result)
                      .expect("Could not find compliant pixel format")
    }
}
<|endoftext|>


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

extern crate gfx;
extern crate gfx_device_gl;
extern crate glutin;

use gfx::tex::Size;

pub struct Wrap<R: gfx::Resources> {
    pub window: glutin::Window,
    frame: gfx::FrameBufferHandle<R>,
    mask: gfx::Mask,
    srgb: bool,
}

impl<R: gfx::Resources> gfx::Output<R> for Wrap<R> {
    fn get_handle(&self) -> Option<&gfx::FrameBufferHandle<R>> {
        Some(&self.frame)
    }

    fn get_size(&self) -> (Size, Size) {
        let (w, h) = self.window.get_inner_size().unwrap_or((0, 0));
        (w as Size, h as Size)
    }

    fn get_mask(&self) -> gfx::Mask {
        self.mask
    }

    fn does_convert_gamma(&self) -> bool {
        self.srgb
    }
}

pub fn init<'a>(builder: glutin::WindowBuilder<'a>)
            -> Result<(Wrap<gfx_device_gl::Resources>, gfx_device_gl::Device, gfx_device_gl::Factory),
                      glutin::CreationError>
{
    let (mask, srgb) = {
        let attribs = builder.get_attributes();
        let mut mask = gfx::Mask::empty();
        match attribs.color_bits {
            Some(b) if b>0 => mask.insert(gfx::COLOR),
            _ => (),
        }
        match attribs.depth_bits {
            Some(b) if b>0 => mask.insert(gfx::DEPTH),
            _ => (),
        }
        match attribs.stencil_bits {
            Some(b) if b>0 => mask.insert(gfx::STENCIL),
            _ => (),
        }
        (mask, attribs.srgb == Some(true))
    };
    // create window
    builder.build().map(|window| {
        let (device, factory) = gfx_device_gl::create(|s| window.get_proc_address(s));
        let wrap = Wrap {
            window: window,
            frame: factory.get_main_frame_buffer(),
            mask: mask,
            srgb: srgb,
        };
        (wrap, device, factory)
    })
}
<commit_msg>Added Success type and init_titled()<commit_after>// Copyright 2015 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[deny(missing_docs)]

extern crate gfx;
extern crate gfx_device_gl;
extern crate glutin;

use gfx::tex::Size;

/// A wrapper around the window that implements `Output`.
pub struct Wrap<R: gfx::Resources> {
    /// Glutin window in the open.
    pub window: glutin::Window,
    frame: gfx::FrameBufferHandle<R>,
    mask: gfx::Mask,
    srgb: bool,
}

impl<R: gfx::Resources> gfx::Output<R> for Wrap<R> {
    fn get_handle(&self) -> Option<&gfx::FrameBufferHandle<R>> {
        Some(&self.frame)
    }

    fn get_size(&self) -> (Size, Size) {
        let (w, h) = self.window.get_inner_size().unwrap_or((0, 0));
        (w as Size, h as Size)
    }

    fn get_mask(&self) -> gfx::Mask {
        self.mask
    }

    fn does_convert_gamma(&self) -> bool {
        self.srgb
    }
}

/// Result of successful context initialization.
pub type Success = (
    Wrap<gfx_device_gl::Resources>,
    gfx_device_gl::Device,
    gfx_device_gl::Factory,
);

/// Initialize with a window builder.
pub fn init<'a>(builder: glutin::WindowBuilder<'a>)
            -> Result<Success, glutin::CreationError>
{
    let (mask, srgb) = {
        let attribs = builder.get_attributes();
        let mut mask = gfx::Mask::empty();
        match attribs.color_bits {
            Some(b) if b>0 => mask.insert(gfx::COLOR),
            _ => (),
        }
        match attribs.depth_bits {
            Some(b) if b>0 => mask.insert(gfx::DEPTH),
            _ => (),
        }
        match attribs.stencil_bits {
            Some(b) if b>0 => mask.insert(gfx::STENCIL),
            _ => (),
        }
        (mask, attribs.srgb == Some(true))
    };
    // create window
    builder.build().map(|window| {
        unsafe { window.make_current() };
        let (device, factory) = gfx_device_gl::create(|s| window.get_proc_address(s));
        let wrap = Wrap {
            window: window,
            frame: factory.get_main_frame_buffer(),
            mask: mask,
            srgb: srgb,
        };
        (wrap, device, factory)
    })
}

/// Initialize with just a title string.
pub fn init_titled(title: &str) -> Result<Success, glutin::CreationError>
{
    let builder = glutin::WindowBuilder::new()
        .with_title(title.to_string());
    init(builder)
}
<|endoftext|>


<commit_before>#![crate_name = "yaml"]
#![crate_type = "lib"]
#![feature(plugin)]
#![feature(box_syntax)]

#![feature(core)]
#![feature(libc)]
#![feature(slice_patterns)]

#![plugin(regex_macros)]

extern crate libc;

extern crate regex;

use std::str;
use std::ffi::CStr;
use std::io::Read;

use parser::YamlParser;
use constructor::{YamlStandardData, YamlStandardConstructor, YamlConstructor};
use error::YamlError;

pub mod ffi;
pub mod error;
pub mod event;
pub mod parser;
pub mod emitter;
pub mod document;
pub mod codecs;
pub mod constructor;

mod type_size;

pub fn version_string() -> String {
    unsafe {
        str::from_utf8(CStr::from_ptr(ffi::yaml_get_version_string()).to_bytes()).unwrap().to_string()
    }
}

pub fn version() -> (isize, isize, isize) {
    let mut c_major: libc::c_int = 0;
    let mut c_minor: libc::c_int = 0;
    let mut c_patch: libc::c_int = 0;

    unsafe {
        ffi::yaml_get_version(
            &mut c_major as *mut libc::c_int,
            &mut c_minor as *mut libc::c_int,
            &mut c_patch as *mut libc::c_int
        );
    }

    (c_major as isize, c_minor as isize, c_patch as isize)
}

pub fn parse_bytes_utf8(bytes: &[u8]) -> Result<Vec<YamlStandardData>, YamlError> {
    parse_bytes(bytes, ffi::YamlEncoding::YamlUtf8Encoding)
}

pub fn parse_bytes(bytes: &[u8], encoding: ffi::YamlEncoding) -> Result<Vec<YamlStandardData>, YamlError> {
    let parser = parser::YamlByteParser::init(bytes, encoding);
    let ctor = YamlStandardConstructor::new();

    parser.load().map(|doc_res|
        doc_res.and_then(|doc| ctor.construct(doc.root().unwrap()))
    ).collect()
}

pub fn parse_io_utf8(reader: &mut Read) -> Result<Vec<YamlStandardData>, YamlError> {
    parse_io(reader, ffi::YamlEncoding::YamlUtf8Encoding)
}

pub fn parse_io(reader: &mut Read, encoding: ffi::YamlEncoding) -> Result<Vec<YamlStandardData>, YamlError> {
    let parser = parser::YamlIoParser::init(reader, encoding);
    let ctor = YamlStandardConstructor::new();

    parser.load().map(|doc_res|
        doc_res.and_then(|doc| ctor.construct(doc.root().unwrap()))
    ).collect()
}

#[cfg(test)]
mod test {
    use std::mem;
    use std::io::BufReader;
    use constructor::YamlStandardData::*;

    #[test]
    fn test_version_string() {
        let vsn = super::version_string();
        assert!("0.1.4".to_string() <= vsn && vsn < "0.2".to_string())
    }

    #[test]
    fn test_version() {
        let vsn = super::version();
        assert!((0, 1, 4) <= vsn && vsn < (0, 2, 0))
    }

    #[test]
    fn test_event_size() {
        assert_eq!(super::type_size::YAML_EVENT_T_SIZE, mem::size_of::<super::ffi::yaml_event_t>())
    }

    #[test]
    fn test_parser_size() {
        assert_eq!(super::type_size::YAML_PARSER_T_SIZE, mem::size_of::<super::ffi::yaml_parser_t>())
    }

    #[test]
    fn test_emitter_size() {
        assert_eq!(super::type_size::YAML_EMITTER_T_SIZE, mem::size_of::<super::ffi::yaml_emitter_t>())
    }

    #[test]
    fn test_document_size() {
        assert_eq!(super::type_size::YAML_DOCUMENT_T_SIZE, mem::size_of::<super::ffi::yaml_document_t>())
    }

    #[test]
    fn test_node_size() {
        assert_eq!(super::type_size::YAML_NODE_T_SIZE, mem::size_of::<super::ffi::yaml_node_t>())
    }

    #[test]
    fn test_parse_bytes() {
        let data = "[1, 2, 3]";
        assert_eq!(Ok(vec![YamlSequence(vec![YamlInteger(1), YamlInteger(2), YamlInteger(3)])]), super::parse_bytes_utf8(data.as_bytes()))
    }

    #[test]
    fn test_parse_io() {
        let data = "[1, 2, 3]";
        let mut reader = BufReader::new(data.as_bytes());
        assert_eq!(Ok(vec![YamlSequence(vec![YamlInteger(1), YamlInteger(2), YamlInteger(3)])]), super::parse_io_utf8(&mut reader))
    }
}
<commit_msg>Rust changes: feature(core) stabilized<commit_after>#![crate_name = "yaml"]
#![crate_type = "lib"]
#![feature(plugin)]
#![feature(box_syntax)]

#![feature(libc)]
#![feature(slice_patterns)]

#![plugin(regex_macros)]

extern crate libc;

extern crate regex;

use std::str;
use std::ffi::CStr;
use std::io::Read;

use parser::YamlParser;
use constructor::{YamlStandardData, YamlStandardConstructor, YamlConstructor};
use error::YamlError;

pub mod ffi;
pub mod error;
pub mod event;
pub mod parser;
pub mod emitter;
pub mod document;
pub mod codecs;
pub mod constructor;

mod type_size;

pub fn version_string() -> String {
    unsafe {
        str::from_utf8(CStr::from_ptr(ffi::yaml_get_version_string()).to_bytes()).unwrap().to_string()
    }
}

pub fn version() -> (isize, isize, isize) {
    let mut c_major: libc::c_int = 0;
    let mut c_minor: libc::c_int = 0;
    let mut c_patch: libc::c_int = 0;

    unsafe {
        ffi::yaml_get_version(
            &mut c_major as *mut libc::c_int,
            &mut c_minor as *mut libc::c_int,
            &mut c_patch as *mut libc::c_int
        );
    }

    (c_major as isize, c_minor as isize, c_patch as isize)
}

pub fn parse_bytes_utf8(bytes: &[u8]) -> Result<Vec<YamlStandardData>, YamlError> {
    parse_bytes(bytes, ffi::YamlEncoding::YamlUtf8Encoding)
}

pub fn parse_bytes(bytes: &[u8], encoding: ffi::YamlEncoding) -> Result<Vec<YamlStandardData>, YamlError> {
    let parser = parser::YamlByteParser::init(bytes, encoding);
    let ctor = YamlStandardConstructor::new();

    parser.load().map(|doc_res|
        doc_res.and_then(|doc| ctor.construct(doc.root().unwrap()))
    ).collect()
}

pub fn parse_io_utf8(reader: &mut Read) -> Result<Vec<YamlStandardData>, YamlError> {
    parse_io(reader, ffi::YamlEncoding::YamlUtf8Encoding)
}

pub fn parse_io(reader: &mut Read, encoding: ffi::YamlEncoding) -> Result<Vec<YamlStandardData>, YamlError> {
    let parser = parser::YamlIoParser::init(reader, encoding);
    let ctor = YamlStandardConstructor::new();

    parser.load().map(|doc_res|
        doc_res.and_then(|doc| ctor.construct(doc.root().unwrap()))
    ).collect()
}

#[cfg(test)]
mod test {
    use std::mem;
    use std::io::BufReader;
    use constructor::YamlStandardData::*;

    #[test]
    fn test_version_string() {
        let vsn = super::version_string();
        assert!("0.1.4".to_string() <= vsn && vsn < "0.2".to_string())
    }

    #[test]
    fn test_version() {
        let vsn = super::version();
        assert!((0, 1, 4) <= vsn && vsn < (0, 2, 0))
    }

    #[test]
    fn test_event_size() {
        assert_eq!(super::type_size::YAML_EVENT_T_SIZE, mem::size_of::<super::ffi::yaml_event_t>())
    }

    #[test]
    fn test_parser_size() {
        assert_eq!(super::type_size::YAML_PARSER_T_SIZE, mem::size_of::<super::ffi::yaml_parser_t>())
    }

    #[test]
    fn test_emitter_size() {
        assert_eq!(super::type_size::YAML_EMITTER_T_SIZE, mem::size_of::<super::ffi::yaml_emitter_t>())
    }

    #[test]
    fn test_document_size() {
        assert_eq!(super::type_size::YAML_DOCUMENT_T_SIZE, mem::size_of::<super::ffi::yaml_document_t>())
    }

    #[test]
    fn test_node_size() {
        assert_eq!(super::type_size::YAML_NODE_T_SIZE, mem::size_of::<super::ffi::yaml_node_t>())
    }

    #[test]
    fn test_parse_bytes() {
        let data = "[1, 2, 3]";
        assert_eq!(Ok(vec![YamlSequence(vec![YamlInteger(1), YamlInteger(2), YamlInteger(3)])]), super::parse_bytes_utf8(data.as_bytes()))
    }

    #[test]
    fn test_parse_io() {
        let data = "[1, 2, 3]";
        let mut reader = BufReader::new(data.as_bytes());
        assert_eq!(Ok(vec![YamlSequence(vec![YamlInteger(1), YamlInteger(2), YamlInteger(3)])]), super::parse_io_utf8(&mut reader))
    }
}
<|endoftext|>


<commit_before>extern crate libc;

use std::os::raw;
use std::ffi::CString;
use std::mem::transmute;

#[link(name = "rust")]
extern {
  fn klee_make_symbolic(data: *const raw::c_void, length: libc::size_t, name: *const raw::c_char);
}

pub fn any(data: *const raw::c_void, length: usize, name: &str) {
  let name_cstr = CString::new(name).unwrap();
  unsafe {
    klee_make_symbolic(data, length as libc::size_t, name_cstr.as_ptr());
  }
}

pub fn i32(data: *const i32, name: &str) {
  let name_cstr = CString::new(name).unwrap();
  unsafe {
    klee_make_symbolic(transmute(data), 4, name_cstr.as_ptr());
  }
}

pub fn u32(data: *const u32, name: &str) {
  let name_cstr = CString::new(name).unwrap();
  unsafe {
    klee_make_symbolic(transmute(data), 4, name_cstr.as_ptr());
  }
}
<commit_msg>Update lib.rs<commit_after>extern crate libc;

use std::os::raw;
use std::ffi::CString;
use std::mem::transmute;

#[link(name = "rust")]
extern {
  fn klee_make_symbolic(data: *const raw::c_void, length: libc::size_t, name: *const raw::c_char);
}

pub fn any(data: *const raw::c_void, length: usize, name: &str) {
  let name_cstr = CString::new(name).unwrap();
  unsafe {
    klee_make_symbolic(data, length as libc::size_t, name_cstr.as_ptr());
  }
}

pub fn i32(data: *const i32, name: &str) {
  let name_cstr = CString::new(name).unwrap();
  unsafe {
    klee_make_symbolic(transmute(data), 4, name_cstr.as_ptr());
  }
}

pub fn u32(data: *const u32, name: &str) {
  let name_cstr = CString::new(name).unwrap();
  unsafe {
    klee_make_symbolic(transmute(data), 4, name_cstr.as_ptr());
  }
}

pub fn str(data: *const &str, name: &str) {
  let name_cstr = CString::new(name).unwrap();
  unsafe {
    klee_make_symbolic(transmute(data), data.len(), name_cstr.as_ptr());
  }
}
<|endoftext|>


<commit_before>#![feature(collections)]
#![feature(asm)]
#![feature(const_fn)]
#![feature(lang_items)]

#![feature(alloc, collections)]
#![allow(unknown_lints)]
#![no_std]

extern crate alloc;
#[cfg(not(test))]
extern crate allocator;
extern crate spin;
#[macro_use]
extern crate collections;

pub mod dispatch_table;
pub mod runtime;
pub mod hash_map;

pub mod vmx;

pub type CChar = u8;

macro_rules! cstring {
    ($e:expr) => (concat!($e, "\0").as_ptr() as *const CChar)
}

extern "C" {
    fn printk(format: *const CChar, ...);
}

#[no_mangle]
pub extern "C" fn entry(_heap: *mut CChar, _heap_size: u64, _: *mut CChar, _: u64) -> u32 {
    unsafe {
        printk(cstring!("Hello Linux!\n"));
    }

    #[cfg(not(test))]
    allocator::init_global_allocator(_heap_size, _heap);
    0
}
<commit_msg>Test loading GDT<commit_after>#![feature(collections)]
#![feature(asm)]
#![feature(const_fn)]
#![feature(lang_items)]

#![feature(alloc, collections)]
#![allow(unknown_lints)]
#![no_std]

extern crate alloc;
#[cfg(not(test))]
extern crate allocator;
extern crate spin;
#[macro_use]
extern crate collections;

pub mod dispatch_table;
pub mod runtime;
pub mod hash_map;
pub mod gdt;
pub mod cli;

pub mod vmx;

pub type CChar = u8;

macro_rules! cstring {
    ($e:expr) => (concat!($e, "\0").as_ptr() as *const CChar)
}

extern "C" {
    fn printk(format: *const CChar, ...);
}

#[no_mangle]
pub extern "C" fn entry(_heap: *mut CChar, _heap_size: u64, _: *mut CChar, _: u64) -> u32 {
    unsafe {
        printk(cstring!("Hello Linux!\n"));
    }

    gdt::test_load();

    #[cfg(not(test))]
    allocator::init_global_allocator(_heap_size, _heap);
    0
}
<|endoftext|>


<commit_before>#![crate_name = "shader_version"]
#![deny(missing_doc)]

//! A helper library for detecting and picking compatible shaders.

/// Models knowledge about version range.
pub enum VersionRange<T> {
    /// The version range is working from a version,
    /// up to but not included another version.
    ///
    /// With other words, from first time it works until it breaks.
    VersionFromTo(T, T),
    /// The version range is working from a version,
    /// and possibly for all newer versions unless
    /// the context it is used implies otherwise.
    VersionFrom(T)
}

#[allow(non_camel_case_types)]
#[allow(missing_doc)]
pub enum OpenGL {
    OpenGL_2_0,
    OpenGL_2_1,
    OpenGL_3_0,
    OpenGL_3_1,
    OpenGL_3_2,
    OpenGL_3_3,
    OpenGL_4_0,
    OpenGL_4_1,
    OpenGL_4_2,
    OpenGL_4_3,
    OpenGL_4_4
}

/// For OpenGL version 3.3 and above,
/// the GLSL version is the same as the OpenGL version.
///
/// Source: http://www.opengl.org/wiki/Core_Language_%28GLSL%29
#[allow(missing_doc)]
#[allow(non_camel_case_types)]
pub enum GLSL {
    GLSL_1_10,
    GLSL_1_20,
    GLSL_1_30,
    GLSL_1_40,
    GLSL_1_50,
    GLSL_3_30,
    GLSL_4_00,
    GLSL_4_10,
    GLSL_4_20,
    GLSL_4_30,
    GLSL_4_40
}

impl OpenGL {
    /// Gets the minor version of OpenGL.
    pub fn get_major_minor(&self) -> (int, int) {
        match *self {
            OpenGL_2_0 => (2, 0),
            OpenGL_2_1 => (2, 1),
            OpenGL_3_0 => (3, 0),
            OpenGL_3_1 => (3, 1),
            OpenGL_3_2 => (3, 2),
            OpenGL_3_3 => (3, 3),
            OpenGL_4_0 => (4, 0),
            OpenGL_4_1 => (4, 1),
            OpenGL_4_2 => (4, 2),
            OpenGL_4_3 => (4, 3),
            OpenGL_4_4 => (4, 4)
        }
    }

    /// Gets GLSL version associated with OpenGL.
    #[allow(non_snake_case_functions)]
    pub fn to_GLSL(&self) -> GLSL {
        match *self {
            OpenGL_2_0 => GLSL_1_10,
            OpenGL_2_1 => GLSL_1_20,
            OpenGL_3_0 => GLSL_1_30,
            OpenGL_3_1 => GLSL_1_40,
            OpenGL_3_2 => GLSL_1_50,
            OpenGL_3_3 => GLSL_3_30,
            OpenGL_4_0 => GLSL_4_00,
            OpenGL_4_1 => GLSL_4_10,
            OpenGL_4_2 => GLSL_4_20,
            OpenGL_4_3 => GLSL_4_30,
            OpenGL_4_4 => GLSL_4_40,
        }
    }
}

<commit_msg>Added `to_OpenGL`<commit_after>#![crate_name = "shader_version"]
#![deny(missing_doc)]

//! A helper library for detecting and picking compatible shaders.

/// Models knowledge about version range.
pub enum VersionRange<T> {
    /// The version range is working from a version,
    /// up to but not included another version.
    ///
    /// With other words, from first time it works until it breaks.
    VersionFromTo(T, T),
    /// The version range is working from a version,
    /// and possibly for all newer versions unless
    /// the context it is used implies otherwise.
    VersionFrom(T)
}

#[allow(non_camel_case_types)]
#[allow(missing_doc)]
pub enum OpenGL {
    OpenGL_2_0,
    OpenGL_2_1,
    OpenGL_3_0,
    OpenGL_3_1,
    OpenGL_3_2,
    OpenGL_3_3,
    OpenGL_4_0,
    OpenGL_4_1,
    OpenGL_4_2,
    OpenGL_4_3,
    OpenGL_4_4
}

/// For OpenGL version 3.3 and above,
/// the GLSL version is the same as the OpenGL version.
///
/// Source: http://www.opengl.org/wiki/Core_Language_%28GLSL%29
#[allow(missing_doc)]
#[allow(non_camel_case_types)]
pub enum GLSL {
    GLSL_1_10,
    GLSL_1_20,
    GLSL_1_30,
    GLSL_1_40,
    GLSL_1_50,
    GLSL_3_30,
    GLSL_4_00,
    GLSL_4_10,
    GLSL_4_20,
    GLSL_4_30,
    GLSL_4_40
}

impl OpenGL {
    /// Gets the minor version of OpenGL.
    pub fn get_major_minor(&self) -> (int, int) {
        match *self {
            OpenGL_2_0 => (2, 0),
            OpenGL_2_1 => (2, 1),
            OpenGL_3_0 => (3, 0),
            OpenGL_3_1 => (3, 1),
            OpenGL_3_2 => (3, 2),
            OpenGL_3_3 => (3, 3),
            OpenGL_4_0 => (4, 0),
            OpenGL_4_1 => (4, 1),
            OpenGL_4_2 => (4, 2),
            OpenGL_4_3 => (4, 3),
            OpenGL_4_4 => (4, 4)
        }
    }

    /// Gets GLSL version associated with OpenGL.
    #[allow(non_snake_case_functions)]
    pub fn to_GLSL(&self) -> GLSL {
        match *self {
            OpenGL_2_0 => GLSL_1_10,
            OpenGL_2_1 => GLSL_1_20,
            OpenGL_3_0 => GLSL_1_30,
            OpenGL_3_1 => GLSL_1_40,
            OpenGL_3_2 => GLSL_1_50,
            OpenGL_3_3 => GLSL_3_30,
            OpenGL_4_0 => GLSL_4_00,
            OpenGL_4_1 => GLSL_4_10,
            OpenGL_4_2 => GLSL_4_20,
            OpenGL_4_3 => GLSL_4_30,
            OpenGL_4_4 => GLSL_4_40,
        }
    }
}

impl GLSL {
    /// Gets OpenGL version associated with GLSL.
    #[allow(non_snake_case_functions)]
    pub fn to_OpenGL(&self) -> OpenGL {
        match *self {
            GLSL_1_10 => OpenGL_2_0,
            GLSL_1_20 => OpenGL_2_1,
            GLSL_1_30 => OpenGL_3_0,
            GLSL_1_40 => OpenGL_3_1,
            GLSL_1_50 => OpenGL_3_2,
            GLSL_3_30 => OpenGL_3_3,
            GLSL_4_00 => OpenGL_4_0,
            GLSL_4_10 => OpenGL_4_1,
            GLSL_4_20 => OpenGL_4_2,
            GLSL_4_30 => OpenGL_4_3,
            GLSL_4_40 => OpenGL_4_4,
        }
    }
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate openexr_sys;

mod cexr_type_aliases;
mod error;
mod frame_buffer;
mod input;
mod output;

use std::ffi::{CStr, CString};
use std::marker::PhantomData;

use openexr_sys::*;

pub use cexr_type_aliases::*;
pub use error::*;
pub use frame_buffer::*;
pub use input::*;
pub use output::*;

// TODO: move Header to its own module once we can use
// `pub(crate)` on struct fields (should be in Rust 1.18).

/// OpenEXR header.
pub struct Header {
    handle: *mut CEXR_Header,
    owned: bool,
    _phantom: PhantomData<CEXR_Header>,
}

impl Header {
    pub fn new() -> Self {
        // Create underlying C header
        let header = {
            let display_window = Box2i {
                min: CEXR_V2i { x: 0, y: 0 },
                max: CEXR_V2i { x: 1, y: 1 },
            };
            let data_window = display_window;
            let pixel_aspect_ratio = 1.0;
            let screen_window_center = CEXR_V2f { x: 0.0, y: 0.0 };
            let screen_window_width = 1.0;
            let line_order = LineOrder::INCREASING_Y;
            let compression = Compression::PIZ_COMPRESSION;
            let header = unsafe {
                CEXR_Header_new(&display_window,
                                &data_window,
                                pixel_aspect_ratio,
                                &screen_window_center,
                                screen_window_width,
                                line_order,
                                compression)
            };
            header
        };

        Self {
            handle: header,
            owned: true,
            _phantom: PhantomData,
        }
    }

    /// Sets the resolution.
    ///
    /// This is really just a shortcut for setting both the display window
    /// and data window to `(0, 0), (width-1, height-1)`.
    pub fn set_resolution(self, width: u32, height: u32) -> Self {
        let window = Box2i {
            min: CEXR_V2i { x: 0, y: 0 },
            max: CEXR_V2i {
                x: width as i32 - 1,
                y: height as i32 - 1,
            },
        };
        unsafe {
            CEXR_Header_set_display_window(self.handle, window);
        }
        unsafe {
            CEXR_Header_set_data_window(self.handle, window);
        }
        self
    }

    /// Sets the display window.
    pub fn set_display_window(self, window: Box2i) -> Self {
        unsafe {
            CEXR_Header_set_display_window(self.handle, window);
        }
        self
    }

    /// Sets the data window.
    pub fn set_data_window(self, window: Box2i) -> Self {
        unsafe {
            CEXR_Header_set_data_window(self.handle, window);
        }
        self
    }

    /// Sets the pixel aspect ratio.
    pub fn set_pixel_aspect_ratio(self, aspect_ratio: f32) -> Self {
        unsafe {
            CEXR_Header_set_pixel_aspect_ratio(self.handle, aspect_ratio);
        }
        self
    }

    /// Sets the screen window center.
    pub fn set_screen_window_center(self, center: (f32, f32)) -> Self {
        unsafe {
            CEXR_Header_set_screen_window_center(self.handle,
                                                 CEXR_V2f {
                                                     x: center.0,
                                                     y: center.1,
                                                 });
        }
        self
    }

    /// Sets the screen window width.
    pub fn set_screen_window_width(self, width: f32) -> Self {
        unsafe {
            CEXR_Header_set_screen_window_width(self.handle, width);
        }
        self
    }

    /// Sets the line order.
    pub fn set_line_order(self, line_order: LineOrder) -> Self {
        unsafe {
            CEXR_Header_set_line_order(self.handle, line_order);
        }
        self
    }

    /// Sets the compression mode.
    pub fn set_compression(self, compression: Compression) -> Self {
        unsafe {
            CEXR_Header_set_compression(self.handle, compression);
        }
        self
    }

    /// Adds a channel.
    ///
    /// This is a simplified version of `add_channel_detailed()`, using some sane
    /// defaults for the details.  Specifially: sampling is set to (1, 1)
    /// and p_linear is set to true.
    pub fn add_channel(self, name: &str, pixel_type: PixelType) -> Self {
        self.add_channel_detailed(name,
                                  Channel {
                                      pixel_type: pixel_type,
                                      x_sampling: 1,
                                      y_sampling: 1,
                                      p_linear: true,
                                  })
    }

    /// Adds a channel, specifying full details.
    pub fn add_channel_detailed(self, name: &str, channel: Channel) -> Self {
        let cname = CString::new(name.as_bytes()).unwrap();
        unsafe { CEXR_Header_insert_channel(self.handle, cname.as_ptr(), channel) };
        self
    }

    pub fn data_window(&self) -> &Box2i {
        unsafe { &*CEXR_Header_data_window(self.handle) }
    }

    pub fn display_window(&self) -> &Box2i {
        unsafe { &*CEXR_Header_display_window(self.handle) }
    }

    pub fn channels<'b>(&'b self) -> ChannelIter<'b> {
        ChannelIter {
            iterator: unsafe { CEXR_Header_channel_list_iter(self.handle) },
            _phantom_1: PhantomData,
            _phantom_2: PhantomData,
        }
    }
}

impl Drop for Header {
    fn drop(&mut self) {
        if self.owned {
            unsafe { CEXR_Header_delete(self.handle) };
        }
    }
}

pub struct ChannelIter<'a> {
    iterator: *mut CEXR_ChannelListIter,
    _phantom_1: PhantomData<CEXR_ChannelListIter>,
    _phantom_2: PhantomData<&'a InputFile<'a>>,
}

impl<'a> Drop for ChannelIter<'a> {
    fn drop(&mut self) {
        unsafe { CEXR_ChannelListIter_delete(self.iterator) };
    }
}

impl<'a> Iterator for ChannelIter<'a> {
    type Item = Result<(&'a str, Channel)>;
    fn next(&mut self) -> Option<Result<(&'a str, Channel)>> {
        let mut name = unsafe { std::mem::uninitialized() };
        let mut channel = unsafe { std::mem::uninitialized() };
        if unsafe { CEXR_ChannelListIter_next(self.iterator, &mut name, &mut channel) } {
            // TODO: use CStr::from_bytes_with_nul() instead to avoid memory unsafety
            // if the string is not nul terminated.
            let cname = unsafe { CStr::from_ptr(name) };
            let str_name = cname.to_str();
            if let Ok(n) = str_name {
                Some(Ok((n, channel)))
            } else {
                Some(Err(Error::Generic(format!("Invalid channel name: {:?}", cname))))
            }
        } else {
            None
        }
    }
}
<commit_msg>Made the Header builder methods use &mut self instead of self.<commit_after>extern crate libc;
extern crate openexr_sys;

mod cexr_type_aliases;
mod error;
mod frame_buffer;
mod input;
mod output;

use std::ffi::{CStr, CString};
use std::marker::PhantomData;

use openexr_sys::*;

pub use cexr_type_aliases::*;
pub use error::*;
pub use frame_buffer::*;
pub use input::*;
pub use output::*;

// TODO: move Header to its own module once we can use
// `pub(crate)` on struct fields (should be in Rust 1.18).

/// OpenEXR header.
pub struct Header {
    handle: *mut CEXR_Header,
    owned: bool,
    _phantom: PhantomData<CEXR_Header>,
}

impl Header {
    pub fn new() -> Self {
        // Create underlying C header
        let header = {
            let display_window = Box2i {
                min: CEXR_V2i { x: 0, y: 0 },
                max: CEXR_V2i { x: 1, y: 1 },
            };
            let data_window = display_window;
            let pixel_aspect_ratio = 1.0;
            let screen_window_center = CEXR_V2f { x: 0.0, y: 0.0 };
            let screen_window_width = 1.0;
            let line_order = LineOrder::INCREASING_Y;
            let compression = Compression::PIZ_COMPRESSION;
            let header = unsafe {
                CEXR_Header_new(&display_window,
                                &data_window,
                                pixel_aspect_ratio,
                                &screen_window_center,
                                screen_window_width,
                                line_order,
                                compression)
            };
            header
        };

        Self {
            handle: header,
            owned: true,
            _phantom: PhantomData,
        }
    }

    /// Sets the resolution.
    ///
    /// This is really just a shortcut for setting both the display window
    /// and data window to `(0, 0), (width-1, height-1)`.
    pub fn set_resolution(&mut self, width: u32, height: u32) -> &mut Self {
        let window = Box2i {
            min: CEXR_V2i { x: 0, y: 0 },
            max: CEXR_V2i {
                x: width as i32 - 1,
                y: height as i32 - 1,
            },
        };
        unsafe {
            CEXR_Header_set_display_window(self.handle, window);
        }
        unsafe {
            CEXR_Header_set_data_window(self.handle, window);
        }
        self
    }

    /// Sets the display window.
    pub fn set_display_window(&mut self, window: Box2i) -> &mut Self {
        unsafe {
            CEXR_Header_set_display_window(self.handle, window);
        }
        self
    }

    /// Sets the data window.
    pub fn set_data_window(&mut self, window: Box2i) -> &mut Self {
        unsafe {
            CEXR_Header_set_data_window(self.handle, window);
        }
        self
    }

    /// Sets the pixel aspect ratio.
    pub fn set_pixel_aspect_ratio(&mut self, aspect_ratio: f32) -> &mut Self {
        unsafe {
            CEXR_Header_set_pixel_aspect_ratio(self.handle, aspect_ratio);
        }
        self
    }

    /// Sets the screen window center.
    pub fn set_screen_window_center(&mut self, center: (f32, f32)) -> &mut Self {
        unsafe {
            CEXR_Header_set_screen_window_center(self.handle,
                                                 CEXR_V2f {
                                                     x: center.0,
                                                     y: center.1,
                                                 });
        }
        self
    }

    /// Sets the screen window width.
    pub fn set_screen_window_width(&mut self, width: f32) -> &mut Self {
        unsafe {
            CEXR_Header_set_screen_window_width(self.handle, width);
        }
        self
    }

    /// Sets the line order.
    pub fn set_line_order(&mut self, line_order: LineOrder) -> &mut Self {
        unsafe {
            CEXR_Header_set_line_order(self.handle, line_order);
        }
        self
    }

    /// Sets the compression mode.
    pub fn set_compression(&mut self, compression: Compression) -> &mut Self {
        unsafe {
            CEXR_Header_set_compression(self.handle, compression);
        }
        self
    }

    /// Adds a channel.
    ///
    /// This is a simplified version of `add_channel_detailed()`, using some sane
    /// defaults for the details.  Specifially: sampling is set to (1, 1)
    /// and p_linear is set to true.
    pub fn add_channel(&mut self, name: &str, pixel_type: PixelType) -> &mut Self {
        self.add_channel_detailed(name,
                                  Channel {
                                      pixel_type: pixel_type,
                                      x_sampling: 1,
                                      y_sampling: 1,
                                      p_linear: true,
                                  })
    }

    /// Adds a channel, specifying full details.
    pub fn add_channel_detailed(&mut self, name: &str, channel: Channel) -> &mut Self {
        let cname = CString::new(name.as_bytes()).unwrap();
        unsafe { CEXR_Header_insert_channel(self.handle, cname.as_ptr(), channel) };
        self
    }

    pub fn data_window(&self) -> &Box2i {
        unsafe { &*CEXR_Header_data_window(self.handle) }
    }

    pub fn display_window(&self) -> &Box2i {
        unsafe { &*CEXR_Header_display_window(self.handle) }
    }

    pub fn channels<'a>(&'a self) -> ChannelIter<'a> {
        ChannelIter {
            iterator: unsafe { CEXR_Header_channel_list_iter(self.handle) },
            _phantom_1: PhantomData,
            _phantom_2: PhantomData,
        }
    }
}

impl Drop for Header {
    fn drop(&mut self) {
        if self.owned {
            unsafe { CEXR_Header_delete(self.handle) };
        }
    }
}

pub struct ChannelIter<'a> {
    iterator: *mut CEXR_ChannelListIter,
    _phantom_1: PhantomData<CEXR_ChannelListIter>,
    _phantom_2: PhantomData<&'a Header>,
}

impl<'a> Drop for ChannelIter<'a> {
    fn drop(&mut self) {
        unsafe { CEXR_ChannelListIter_delete(self.iterator) };
    }
}

impl<'a> Iterator for ChannelIter<'a> {
    type Item = Result<(&'a str, Channel)>;
    fn next(&mut self) -> Option<Result<(&'a str, Channel)>> {
        let mut name = unsafe { std::mem::uninitialized() };
        let mut channel = unsafe { std::mem::uninitialized() };
        if unsafe { CEXR_ChannelListIter_next(self.iterator, &mut name, &mut channel) } {
            // TODO: use CStr::from_bytes_with_nul() instead to avoid memory unsafety
            // if the string is not nul terminated.
            let cname = unsafe { CStr::from_ptr(name) };
            let str_name = cname.to_str();
            if let Ok(n) = str_name {
                Some(Ok((n, channel)))
            } else {
                Some(Err(Error::Generic(format!("Invalid channel name: {:?}", cname))))
            }
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>extern crate iron;
extern crate unicase;

use unicase::UniCase;
use iron::prelude::*;
use iron::method::Method;
use iron::method::Method::*;
use iron::status;
use iron::headers::{Origin, AccessControlRequestMethod, AccessControlRequestHeaders,
                    AccessControlAllowOrigin, AccessControlAllowHeaders, AccessControlMaxAge,
                    AccessControlAllowMethods, AccessControlAllowCredentials};
use iron::middleware::{AroundMiddleware, Handler};
use std::collections::HashSet;
use std::iter::FromIterator;

// Using case-sensitive match of protocol://host:port
// For a formal definition, see
// https://tools.ietf.org/html/rfc6454#section-4
pub enum AllowedOrigins {
    Any{ prefer_wildcard: bool },
    Specific(HashSet<String>),
}

impl AllowedOrigins {
    fn allowed_for(&self, origin: &String, allow_credentials: bool) -> Option<String> {
        match self {
            &AllowedOrigins::Any{ prefer_wildcard } => {
                if allow_credentials {
                    // Allow credentials does not permit using wildcard
                    Some(origin.clone())
                } else {
                    // Use wildcard if preferred
                    Some(if prefer_wildcard { "*".to_owned() } else { origin.clone() })
                }
            }
            &AllowedOrigins::Specific(ref allowed) => {
                if allowed.contains(origin) {
                    Some(origin.clone())
                } else {
                    None
                }
            }
        }
    }
}

pub struct CorsMiddleware {
    pub allowed_origins: AllowedOrigins,
    // Having allowed methods "any" would not make much sense
    // since we need to enumerate all methods when returning
    // the allowed-methods header
    pub allowed_methods: Vec<Method>,
    pub allowed_headers: Vec<UniCase<String>>,
    pub exposed_headers: Vec<String>,
    pub allow_credentials: bool,
    pub max_age_seconds: u32,
}

impl CorsMiddleware {
    pub fn new() -> CorsMiddleware {
        let allowed_methods: Vec<Method> = vec![Options, Get, Post, Put, Delete, Head, Trace,
                                                Connect, Patch];
        let allowed_headers: Vec<unicase::UniCase<String>> =
            vec![// To allow application/json
                 UniCase("Content-Type".to_owned()),
                 // Set by some js libs
                 UniCase("X-Requested-With".to_owned())];
        let exposed_headers: Vec<String> = Vec::new();
        CorsMiddleware {
            allowed_origins: AllowedOrigins::Any { prefer_wildcard: false } ,
            allowed_methods: allowed_methods,
            allowed_headers: allowed_headers,
            exposed_headers: exposed_headers,
            allow_credentials: false,
            max_age_seconds: 60 * 60,
        }
    }

    fn handle(&self, req: &mut Request, handler: &Handler) -> IronResult<Response> {
        // http://stackoverflow.com/questions/14015118/
        // what-is-the-expected-response-to-an-invalid-cors-request
        // http://stackoverflow.com/questions/32331737/
        // how-can-i-identify-a-cors-preflight-request
        if req.method == Options && req.headers.get::<AccessControlRequestMethod>().is_some() {
            self.handle_preflight(req, handler)
        } else {
            self.handle_normal(req, handler)
        }
    }

    fn handle_preflight(&self, req: &mut Request, _: &Handler) -> IronResult<Response> {
        // Successful preflight status code is NoContent
        let mut res = Response::with((status::NoContent));

        // - Preflight request
        // - 1.If the Origin header is not present terminate this set of steps. The request is
        // - outside the scope of this specification.
        let maybe_origin = req.headers.get::<Origin>();
        if maybe_origin.is_none() {
            let resp = Response::with((status::BadRequest,
                                       "Preflight request without Origin header"));
            return Ok(resp);
        }
        let origin = maybe_origin.unwrap();
        //
        // - 2.If the value of the Origin header is not a case-sensitive match for any of the
        // - values in list of origins do not set any additional headers and terminate this
        // - set of steps.
        //
        // - Note: Always matching is acceptable since the list of origins can be unbounded.
        //
        // - Note: The Origin header can only contain a single origin as the user agent
        //       will not follow redirects.
        //
        let origin_str = origin.to_string();
        let allowed_origin = self.allowed_origins.allowed_for(&origin_str, self.allow_credentials);
        if allowed_origin.is_none() {
            let resp = Response::with((status::BadRequest,
                                       format!("Preflight request requesting \
                                       disallowed origin '{}'",
                                               origin_str)));
            return Ok(resp);
        }
        //
        // - 3. Let method be the value as result of parsing the Access-Control-Request-Method
        // - header.
        //
        // - If there is no Access-Control-Request-Method header or if parsing failed, do not
        // - set any additional headers and terminate this set of steps. The request is
        // - outside the scope of this specification.

        // We can assume that this header exists, since we already checked that before
        // classifying the request as preflight
        let requested_method = req.headers.get::<AccessControlRequestMethod>().unwrap();

        //
        // - 4. Let header field-names be the values as result of parsing the
        // - Access-Control-Request-Headers headers.
        let empty_vec: Vec<UniCase<String>> = vec![];
        let maybe_requested_headers = req.headers.get::<AccessControlRequestHeaders>();
        let requested_headers: &Vec<UniCase<String>> = if maybe_requested_headers.is_some() {
            &maybe_requested_headers.unwrap().0
        } else {
            &empty_vec
        };
        //
        // - If there are no Access-Control-Request-Headers headers let header field-names be
        // - the empty list.
        //
        // - If parsing failed do not set any additional headers and terminate this set of
        // - steps. The request is outside the scope of this specification.
        //
        // - 5.If method is not a case-sensitive match for any of the values in list of
        // -   methods do not set any additional headers and terminate this set of steps.
        //
        if !self.allowed_methods.contains(requested_method) {
            return Ok(Response::with((status::BadRequest,
                                      format!("Preflight request requesting disallowed method {}",
                                              requested_method))));
        }
        //
        // - Always matching is acceptable since the list of methods can be unbounded.
        //
        // - 6. If any of the header field-names is not a ASCII case-insensitive match for any
        // - of the values in list of headers do not set any additional headers and terminate
        // - this set of steps.
        let requested_headers_set: HashSet<UniCase<String>> =
            HashSet::from_iter(requested_headers.iter().cloned());
        let allowed_headers_set: HashSet<UniCase<String>> =
            HashSet::from_iter(self.allowed_headers.iter().cloned());
        let disallowed_headers: HashSet<UniCase<String>> =
            requested_headers_set.difference(&allowed_headers_set).cloned().collect();
        if !disallowed_headers.is_empty() {
            let a = disallowed_headers.iter()
                .map(|uh| uh.to_string())
                .collect::<Vec<_>>()
                .join(",");
            let msg = format!("Preflight request requesting disallowed header(s) {}", a);
            return Ok(Response::with((status::BadRequest, msg)));

        }
        //
        // - Always matching is acceptable since the list of headers can be unbounded.
        //
        // - 7. If the resource supports credentials add a single Access-Control-Allow-Origin
        // - header, with the value of the Origin header as value, and add a single
        // - Access-Control-Allow-Credentials header with the case-sensitive string "true" as
        // - value.
        if self.allow_credentials {
            res.headers.set(AccessControlAllowCredentials);
        }
        //
        // - Otherwise, add a single Access-Control-Allow-Origin header, with either the
        // - value of the Origin header or the string "*" as value.
        res.headers.set(AccessControlAllowOrigin::Value(allowed_origin.unwrap()));
        //
        // - The string "*" cannot be used for a resource that supports credentials.
        //
        // - 8. Optionally add a single Access-Control-Max-Age header with as value the amount
        // - of seconds the user agent is allowed to cache the result of the request.
        res.headers.set(AccessControlMaxAge(self.max_age_seconds));
        //
        // - 9. If method is a simple method this step may be skipped.
        //
        // - Add one or more Access-Control-Allow-Methods headers consisting of (a subset of)
        // - the list of methods.
        res.headers.set(AccessControlAllowMethods(self.allowed_methods.clone()));
        //
        // - If a method is a simple method it does not need to be listed, but this is not
        // - prohibited.
        //
        // - Since the list of methods can be unbounded, simply returning the method
        // - indicated by Access-Control-Request-Method (if supported) can be enough.
        //
        // - 10.If each of the header field-names is a simple header and none is Content-Type,
        // - this step may be skipped.
        //
        // - Add one or more Access-Control-Allow-Headers headers consisting of (a subset of)
        // - the list of headers.
        res.headers.set(AccessControlAllowHeaders(self.allowed_headers.clone()));
        //
        // - If a header field name is a simple header and is not Content-Type, it is not
        // - required to be listed. Content-Type is to be listed as only a subset of its
        // - values makes it qualify as simple header.
        //
        // - Since the list of headers can be unbounded, simply returning supported headers
        // - from Access-Control-Allow-Headers can be enough.
        Ok(res)
    }

    fn handle_normal(&self, req: &mut Request, handler: &Handler) -> IronResult<Response> {
        // Normal request
        // 1.If the Origin header is not present terminate this set of steps. The request is
        // outside the scope of this specification.
        let has_origin = req.headers.get::<Origin>().is_some();
        if !has_origin {
            return handler.handle(req);
        }
        //
        // 2.If the value of the Origin header is not a case-sensitive match for any of the
        // values in list of origins, do not set any additional headers and terminate this
        // set of steps.
        //
        // Note: Always matching is acceptable since the list of origins can be unbounded.
        //
        // 3. If the resource supports credentials add a single Access-Control-Allow-Origin
        // header, with the value of the Origin header as value, and add a single
        // Access-Control-Allow-Credentials header with the case-sensitive string "true" as
        // value.
        //
        // Otherwise, add a single Access-Control-Allow-Origin header, with either the
        // value of the Origin header or the string "*" as value.
        //
        // Note: The string "*" cannot be used for a resource that supports credentials.
        //
        // 4. If the list of exposed headers is not empty add one or more
        // Access-Control-Expose-Headers headers, with as values the header field names
        // given in the list of exposed headers.
        let result = handler.handle(req);
        match result {
            Ok(mut res) => {
                // And set CORS headers
                let origin = req.headers.get::<Origin>().unwrap();
                res.headers.set(AccessControlAllowOrigin::Value(format!("{}", origin)));
                Ok(res)
            }
            _ => result,
        }
    }
}

impl AroundMiddleware for CorsMiddleware {
    fn around(self, handler: Box<Handler>) -> Box<Handler> {
        Box::new(move |req: &mut Request| self.handle(req, &handler))
    }
}
<commit_msg>move doc<commit_after>extern crate iron;
extern crate unicase;

use unicase::UniCase;
use iron::prelude::*;
use iron::method::Method;
use iron::method::Method::*;
use iron::status;
use iron::headers::{Origin, AccessControlRequestMethod, AccessControlRequestHeaders,
                    AccessControlAllowOrigin, AccessControlAllowHeaders, AccessControlMaxAge,
                    AccessControlAllowMethods, AccessControlAllowCredentials};
use iron::middleware::{AroundMiddleware, Handler};
use std::collections::HashSet;
use std::iter::FromIterator;

// Using case-sensitive match of protocol://host:port
// For a formal definition, see
// https://tools.ietf.org/html/rfc6454#section-4
pub enum AllowedOrigins {
    Any{ prefer_wildcard: bool },
    Specific(HashSet<String>),
}

impl AllowedOrigins {
    fn allowed_for(&self, origin: &String, allow_credentials: bool) -> Option<String> {
        match self {
            &AllowedOrigins::Any{ prefer_wildcard } => {
                if allow_credentials {
                    // Allow credentials does not permit using wildcard
                    Some(origin.clone())
                } else {
                    // Use wildcard if preferred
                    Some(if prefer_wildcard { "*".to_owned() } else { origin.clone() })
                }
            }
            &AllowedOrigins::Specific(ref allowed) => {
                if allowed.contains(origin) {
                    Some(origin.clone())
                } else {
                    None
                }
            }
        }
    }
}

pub struct CorsMiddleware {
    pub allowed_origins: AllowedOrigins,
    // Having allowed methods "any" would not make much sense
    // since we need to enumerate all methods when returning
    // the allowed-methods header
    pub allowed_methods: Vec<Method>,
    pub allowed_headers: Vec<UniCase<String>>,
    pub exposed_headers: Vec<String>,
    pub allow_credentials: bool,
    pub max_age_seconds: u32,
}

impl CorsMiddleware {
    pub fn new() -> CorsMiddleware {
        let allowed_methods: Vec<Method> = vec![Options, Get, Post, Put, Delete, Head, Trace,
                                                Connect, Patch];
        let allowed_headers: Vec<unicase::UniCase<String>> =
            vec![// To allow application/json
                 UniCase("Content-Type".to_owned()),
                 // Set by some js libs
                 UniCase("X-Requested-With".to_owned())];
        let exposed_headers: Vec<String> = Vec::new();
        CorsMiddleware {
            allowed_origins: AllowedOrigins::Any { prefer_wildcard: false } ,
            allowed_methods: allowed_methods,
            allowed_headers: allowed_headers,
            exposed_headers: exposed_headers,
            allow_credentials: false,
            max_age_seconds: 60 * 60,
        }
    }

    fn handle(&self, req: &mut Request, handler: &Handler) -> IronResult<Response> {
        // http://stackoverflow.com/questions/14015118/
        // what-is-the-expected-response-to-an-invalid-cors-request
        // http://stackoverflow.com/questions/32331737/
        // how-can-i-identify-a-cors-preflight-request
        if req.method == Options && req.headers.get::<AccessControlRequestMethod>().is_some() {
            self.handle_preflight(req, handler)
        } else {
            self.handle_normal(req, handler)
        }
    }

    fn handle_preflight(&self, req: &mut Request, _: &Handler) -> IronResult<Response> {
        // Successful preflight status code is NoContent
        let mut res = Response::with((status::NoContent));

        // - Preflight request
        // - 1.If the Origin header is not present terminate this set of steps. The request is
        // - outside the scope of this specification.
        let maybe_origin = req.headers.get::<Origin>();
        if maybe_origin.is_none() {
            let resp = Response::with((status::BadRequest,
                                       "Preflight request without Origin header"));
            return Ok(resp);
        }
        let origin = maybe_origin.unwrap();
        //
        // - 2.If the value of the Origin header is not a case-sensitive match for any of the
        // - values in list of origins do not set any additional headers and terminate this
        // - set of steps.
        //
        // - Note: Always matching is acceptable since the list of origins can be unbounded.
        //
        // - Note: The Origin header can only contain a single origin as the user agent
        //       will not follow redirects.
        //
        let origin_str = origin.to_string();
        let allowed_origin = self.allowed_origins.allowed_for(&origin_str, self.allow_credentials);
        if allowed_origin.is_none() {
            let resp = Response::with((status::BadRequest,
                                       format!("Preflight request requesting \
                                       disallowed origin '{}'",
                                               origin_str)));
            return Ok(resp);
        }
        //
        // - 3. Let method be the value as result of parsing the Access-Control-Request-Method
        // - header.
        //
        // - If there is no Access-Control-Request-Method header or if parsing failed, do not
        // - set any additional headers and terminate this set of steps. The request is
        // - outside the scope of this specification.

        // We can assume that this header exists, since we already checked that before
        // classifying the request as preflight
        let requested_method = req.headers.get::<AccessControlRequestMethod>().unwrap();

        //
        // - 4. Let header field-names be the values as result of parsing the
        // - Access-Control-Request-Headers headers.
        //
        // - If there are no Access-Control-Request-Headers headers let header field-names be
        // - the empty list.
        //
        // - If parsing failed do not set any additional headers and terminate this set of
        // - steps. The request is outside the scope of this specification.
        //
        let empty_vec: Vec<UniCase<String>> = vec![];
        let maybe_requested_headers = req.headers.get::<AccessControlRequestHeaders>();
        let requested_headers: &Vec<UniCase<String>> = if maybe_requested_headers.is_some() {
            &maybe_requested_headers.unwrap().0
        } else {
            &empty_vec
        };
        // - 5.If method is not a case-sensitive match for any of the values in list of
        // -   methods do not set any additional headers and terminate this set of steps.
        //
        // - Always matching is acceptable since the list of methods can be unbounded.
        //
        if !self.allowed_methods.contains(requested_method) {
            return Ok(Response::with((status::BadRequest,
                                      format!("Preflight request requesting disallowed method {}",
                                              requested_method))));
        }
        // - 6. If any of the header field-names is not a ASCII case-insensitive match for any
        // - of the values in list of headers do not set any additional headers and terminate
        // - this set of steps.
        let requested_headers_set: HashSet<UniCase<String>> =
            HashSet::from_iter(requested_headers.iter().cloned());
        let allowed_headers_set: HashSet<UniCase<String>> =
            HashSet::from_iter(self.allowed_headers.iter().cloned());
        let disallowed_headers: HashSet<UniCase<String>> =
            requested_headers_set.difference(&allowed_headers_set).cloned().collect();
        if !disallowed_headers.is_empty() {
            let a = disallowed_headers.iter()
                .map(|uh| uh.to_string())
                .collect::<Vec<_>>()
                .join(",");
            let msg = format!("Preflight request requesting disallowed header(s) {}", a);
            return Ok(Response::with((status::BadRequest, msg)));

        }
        //
        // - Always matching is acceptable since the list of headers can be unbounded.
        //
        // - 7. If the resource supports credentials add a single Access-Control-Allow-Origin
        // - header, with the value of the Origin header as value, and add a single
        // - Access-Control-Allow-Credentials header with the case-sensitive string "true" as
        // - value.
        //
        // - Otherwise, add a single Access-Control-Allow-Origin header, with either the
        // - value of the Origin header or the string "*" as value.
        //
        // - The string "*" cannot be used for a resource that supports credentials.
        //
        if self.allow_credentials {
            res.headers.set(AccessControlAllowCredentials);
        }
        res.headers.set(AccessControlAllowOrigin::Value(allowed_origin.unwrap()));
        // - 8. Optionally add a single Access-Control-Max-Age header with as value the amount
        // - of seconds the user agent is allowed to cache the result of the request.
        res.headers.set(AccessControlMaxAge(self.max_age_seconds));
        //
        // - 9. If method is a simple method this step may be skipped.
        //
        // - Add one or more Access-Control-Allow-Methods headers consisting of (a subset of)
        // - the list of methods.
        //
        // - If a method is a simple method it does not need to be listed, but this is not
        // - prohibited.
        //
        // - Since the list of methods can be unbounded, simply returning the method
        // - indicated by Access-Control-Request-Method (if supported) can be enough.
        //
        res.headers.set(AccessControlAllowMethods(self.allowed_methods.clone()));
        // - 10.If each of the header field-names is a simple header and none is Content-Type,
        // - this step may be skipped.
        //
        // - Add one or more Access-Control-Allow-Headers headers consisting of (a subset of)
        // - the list of headers.
        //
        // - If a header field name is a simple header and is not Content-Type, it is not
        // - required to be listed. Content-Type is to be listed as only a subset of its
        // - values makes it qualify as simple header.
        //
        // - Since the list of headers can be unbounded, simply returning supported headers
        // - from Access-Control-Allow-Headers can be enough.
        res.headers.set(AccessControlAllowHeaders(self.allowed_headers.clone()));
        Ok(res)
    }

    fn handle_normal(&self, req: &mut Request, handler: &Handler) -> IronResult<Response> {
        // Normal request
        // 1.If the Origin header is not present terminate this set of steps. The request is
        // outside the scope of this specification.
        let has_origin = req.headers.get::<Origin>().is_some();
        if !has_origin {
            return handler.handle(req);
        }
        //
        // 2.If the value of the Origin header is not a case-sensitive match for any of the
        // values in list of origins, do not set any additional headers and terminate this
        // set of steps.
        //
        // Note: Always matching is acceptable since the list of origins can be unbounded.
        //
        // 3. If the resource supports credentials add a single Access-Control-Allow-Origin
        // header, with the value of the Origin header as value, and add a single
        // Access-Control-Allow-Credentials header with the case-sensitive string "true" as
        // value.
        //
        // Otherwise, add a single Access-Control-Allow-Origin header, with either the
        // value of the Origin header or the string "*" as value.
        //
        // Note: The string "*" cannot be used for a resource that supports credentials.
        //
        // 4. If the list of exposed headers is not empty add one or more
        // Access-Control-Expose-Headers headers, with as values the header field names
        // given in the list of exposed headers.
        let result = handler.handle(req);
        match result {
            Ok(mut res) => {
                // And set CORS headers
                let origin = req.headers.get::<Origin>().unwrap();
                res.headers.set(AccessControlAllowOrigin::Value(format!("{}", origin)));
                Ok(res)
            }
            _ => result,
        }
    }
}

impl AroundMiddleware for CorsMiddleware {
    fn around(self, handler: Box<Handler>) -> Box<Handler> {
        Box::new(move |req: &mut Request| self.handle(req, &handler))
    }
}
<|endoftext|>


<commit_before>//! # rowdy
//!
//! `rowdy` is a JSON Web token based authentication server based off Docker Registry's
//! [authtentication protocol](https://docs.docker.com/registry/spec/auth/).
//!
//! ## Features
//!
//! - `clippy`: Enable clippy lints during builds

#![feature(plugin, custom_derive)]
#![plugin(rocket_codegen)]
#![cfg_attr(feature="clippy", plugin(clippy))]

extern crate chrono;
extern crate hyper;
extern crate jwt;
#[macro_use]
extern crate log;
#[macro_use]
extern crate rocket; // we are using the "log_!" macros which are redefined from `log`'s
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate unicase;
extern crate uuid;

#[cfg(test)]
extern crate serde_test;

#[macro_use]
mod macros;
#[cfg(test)]
#[macro_use]
mod test;
pub mod header;
pub mod cors;
pub mod serde_custom;
pub mod token;

use std::error;
use std::fmt;
use std::io;
use std::str::FromStr;
use std::time::Duration;
use std::ops::Deref;

use jwt::jws;
use rocket::http::Status;
use rocket::response::{Response, Responder};
use serde::{Serialize, Serializer, Deserialize, Deserializer};
use serde::de;

#[derive(Debug)]
pub enum Error {
    GenericError(String),
    CORS(cors::Error),
    Token(token::Error),
    IOError(io::Error),
}

impl_from_error!(cors::Error, Error::CORS);
impl_from_error!(token::Error, Error::Token);
impl_from_error!(String, Error::GenericError);
impl_from_error!(io::Error, Error::IOError);

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::CORS(ref e) => e.description(),
            Error::Token(ref e) => e.description(),
            Error::IOError(ref e) => e.description(),
            Error::GenericError(ref e) => e,
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::CORS(ref e) => Some(e as &error::Error),
            Error::Token(ref e) => Some(e as &error::Error),
            Error::IOError(ref e) => Some(e as &error::Error),
            Error::GenericError(_) => Some(self as &error::Error),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::CORS(ref e) => fmt::Display::fmt(e, f),
            Error::Token(ref e) => fmt::Display::fmt(e, f),
            Error::IOError(ref e) => fmt::Display::fmt(e, f),
            Error::GenericError(ref e) => fmt::Display::fmt(e, f),
        }
    }
}

impl<'r> Responder<'r> for Error {
    fn respond(self) -> Result<Response<'r>, Status> {
        match self {
            Error::CORS(e) => e.respond(),
            Error::Token(e) => e.respond(),
            e => {
                error_!("{}", e);
                Err(Status::InternalServerError)
            }
        }
    }
}

/// Wrapper around `hyper::Url` with `Serialize` and `Deserialize` implemented
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct Url(hyper::Url);
impl_deref!(Url, hyper::Url);

impl FromStr for Url {
    type Err = hyper::error::ParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Url(hyper::Url::from_str(s)?))
    }
}

impl fmt::Display for Url {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0.as_str())
    }
}

impl Serialize for Url {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        serializer.serialize_str(self.0.as_str())
    }
}

impl Deserialize for Url {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer
    {
        struct UrlVisitor;
        impl de::Visitor for UrlVisitor {
            type Value = Url;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("a valid URL string")
            }

            fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
                where E: de::Error
            {
                Ok(Url(hyper::Url::from_str(&value).map_err(|e| E::custom(format!("{}", e)))?))
            }

            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
                where E: de::Error
            {
                Ok(Url(hyper::Url::from_str(value).map_err(|e| E::custom(format!("{}", e)))?))
            }
        }

        deserializer.deserialize_string(UrlVisitor)
    }
}

const DEFAULT_EXPIRY_DURATION: u64 = 86400;

/// Application configuration. Usually deserialized from JSON for use.
///
/// # Examples
/// This is a standard JSON serialized example.
///
/// ```json
/// {
///     "issuer": "https://www.acme.com",
///     "allowed_origins": ["https://www.example.com", "https://www.foobar.com"],
///     "audience": ["https://www.example.com", "https://www.foobar.com"],
///     "signature_algorithm": "RS256",
///     "secret": {
///                 "rsa_private": "test/fixtures/rsa_private_key.der",
///                 "rsa_public": "test/fixtures/rsa_public_key.der"
///                },
///     "expiry_duration": 86400
/// }
/// ```
///
/// ```
/// extern crate rowdy;
/// #[macro_use]
/// extern crate serde_derive;
/// extern crate serde_json;
///
/// use rowdy::Configuration;
///
/// # fn main() {
/// let json = r#"{
///     "issuer": "https://www.acme.com",
///     "allowed_origins": ["https://www.example.com", "https://www.foobar.com"],
///     "audience": ["https://www.example.com", "https://www.foobar.com"],
///     "signature_algorithm": "RS256",
///     "secret": {
///                 "rsa_private": "test/fixtures/rsa_private_key.der",
///                 "rsa_public": "test/fixtures/rsa_public_key.der"
///                },
///     "expiry_duration": 86400
/// }"#;
/// let deserialized: Configuration = serde_json::from_str(json).unwrap();
/// # }
/// ```
///
/// Variations for the fields `allowed_origins`, `audience` and `secret` exist. Refer to their type documentation for
/// examples.
#[derive(Serialize, Deserialize, Debug, Default)]
pub struct Configuration {
    /// The issuer of the token. Usually the URI of the authentication server.
    /// The issuer URI will also be used in the UUID generation of the tokens.
    pub issuer: String,
    /// Origins that are allowed to issue CORS request. This is needed for browser
    /// access to the authentication server, but tools like `curl` do not obey nor enforce the CORS convention.
    ///
    /// This enum (de)serialized as an [untagged](https://serde.rs/enum-representations.html) enum variant.
    ///
    /// See [`cors::AllowedOrigins`] for serialization examples.
    pub allowed_origins: cors::AllowedOrigins,
    /// The audience intended for your tokens.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub audience: Option<jwt::SingleOrMultipleStrings>,
    /// Defaults to `none`
    #[serde(skip_serializing_if = "Option::is_none")]
    pub signature_algorithm: Option<jws::Algorithm>,
    /// Secrets for use in signing and encrypting a JWT.
    /// This enum (de)serialized as an [untagged](https://serde.rs/enum-representations.html) enum variant.
    /// Defaults to `None`.
    ///
    /// See [`token::Secret`] for serialization examples
    #[serde(default)]
    pub secret: token::Secret,
    /// Expiry duration of tokens, in seconds. Defaults to 24 hours when deserialized and left unfilled
    #[serde(with = "::serde_custom::duration", default = "Configuration::default_expiry_duration")]
    pub expiry_duration: Duration,
}

impl Configuration {
    fn default_expiry_duration() -> Duration {
        Duration::from_secs(DEFAULT_EXPIRY_DURATION)
    }
}

/// Launches the Rocket server with the configuration. This function blocks and never returns.
pub fn launch(config: Configuration) {
    let token_getter_options = token::TokenGetterCorsOptions::new(&config);
    rocket::ignite()
        .mount("/",
               routes![token::token_getter, token::token_getter_options])
        .manage(config)
        .manage(token_getter_options)
        .launch();
}

#[cfg(test)]
mod tests {
    use std::default::Default;
    use std::str::FromStr;

    use serde_test::{Token, assert_tokens};

    use super::*;

    #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
    struct TestUrl {
        url: Url,
    }

    #[derive(Clone, Serialize, Deserialize, Debug, Eq, PartialEq)]
    struct TestClaims {
        company: String,
        department: String,
    }

    impl Default for TestClaims {
        fn default() -> Self {
            TestClaims {
                company: "ACME".to_string(),
                department: "Toilet Cleaning".to_string(),
            }
        }
    }

    #[test]
    fn url_serialization_token_round_trip() {
        let test = TestUrl { url: not_err!(Url::from_str("https://www.example.com/")) };

        assert_tokens(&test,
                      &[Token::StructStart("TestUrl", 1),
                        Token::StructSep,
                        Token::Str("url"),
                        Token::Str("https://www.example.com/"),
                        Token::StructEnd]);
    }
}
<commit_msg>Fix embarassing typo<commit_after>//! # rowdy
//!
//! `rowdy` is a JSON Web token based authentication server based off Docker Registry's
//! [authentication protocol](https://docs.docker.com/registry/spec/auth/).
//!
//! ## Features
//!
//! - `clippy`: Enable clippy lints during builds

#![feature(plugin, custom_derive)]
#![plugin(rocket_codegen)]
#![cfg_attr(feature="clippy", plugin(clippy))]

extern crate chrono;
extern crate hyper;
extern crate jwt;
#[macro_use]
extern crate log;
#[macro_use]
extern crate rocket; // we are using the "log_!" macros which are redefined from `log`'s
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate unicase;
extern crate uuid;

#[cfg(test)]
extern crate serde_test;

#[macro_use]
mod macros;
#[cfg(test)]
#[macro_use]
mod test;
pub mod header;
pub mod cors;
pub mod serde_custom;
pub mod token;

use std::error;
use std::fmt;
use std::io;
use std::str::FromStr;
use std::time::Duration;
use std::ops::Deref;

use jwt::jws;
use rocket::http::Status;
use rocket::response::{Response, Responder};
use serde::{Serialize, Serializer, Deserialize, Deserializer};
use serde::de;

#[derive(Debug)]
pub enum Error {
    GenericError(String),
    CORS(cors::Error),
    Token(token::Error),
    IOError(io::Error),
}

impl_from_error!(cors::Error, Error::CORS);
impl_from_error!(token::Error, Error::Token);
impl_from_error!(String, Error::GenericError);
impl_from_error!(io::Error, Error::IOError);

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::CORS(ref e) => e.description(),
            Error::Token(ref e) => e.description(),
            Error::IOError(ref e) => e.description(),
            Error::GenericError(ref e) => e,
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::CORS(ref e) => Some(e as &error::Error),
            Error::Token(ref e) => Some(e as &error::Error),
            Error::IOError(ref e) => Some(e as &error::Error),
            Error::GenericError(_) => Some(self as &error::Error),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::CORS(ref e) => fmt::Display::fmt(e, f),
            Error::Token(ref e) => fmt::Display::fmt(e, f),
            Error::IOError(ref e) => fmt::Display::fmt(e, f),
            Error::GenericError(ref e) => fmt::Display::fmt(e, f),
        }
    }
}

impl<'r> Responder<'r> for Error {
    fn respond(self) -> Result<Response<'r>, Status> {
        match self {
            Error::CORS(e) => e.respond(),
            Error::Token(e) => e.respond(),
            e => {
                error_!("{}", e);
                Err(Status::InternalServerError)
            }
        }
    }
}

/// Wrapper around `hyper::Url` with `Serialize` and `Deserialize` implemented
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct Url(hyper::Url);
impl_deref!(Url, hyper::Url);

impl FromStr for Url {
    type Err = hyper::error::ParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Url(hyper::Url::from_str(s)?))
    }
}

impl fmt::Display for Url {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0.as_str())
    }
}

impl Serialize for Url {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        serializer.serialize_str(self.0.as_str())
    }
}

impl Deserialize for Url {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer
    {
        struct UrlVisitor;
        impl de::Visitor for UrlVisitor {
            type Value = Url;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("a valid URL string")
            }

            fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
                where E: de::Error
            {
                Ok(Url(hyper::Url::from_str(&value).map_err(|e| E::custom(format!("{}", e)))?))
            }

            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
                where E: de::Error
            {
                Ok(Url(hyper::Url::from_str(value).map_err(|e| E::custom(format!("{}", e)))?))
            }
        }

        deserializer.deserialize_string(UrlVisitor)
    }
}

const DEFAULT_EXPIRY_DURATION: u64 = 86400;

/// Application configuration. Usually deserialized from JSON for use.
///
/// # Examples
/// This is a standard JSON serialized example.
///
/// ```json
/// {
///     "issuer": "https://www.acme.com",
///     "allowed_origins": ["https://www.example.com", "https://www.foobar.com"],
///     "audience": ["https://www.example.com", "https://www.foobar.com"],
///     "signature_algorithm": "RS256",
///     "secret": {
///                 "rsa_private": "test/fixtures/rsa_private_key.der",
///                 "rsa_public": "test/fixtures/rsa_public_key.der"
///                },
///     "expiry_duration": 86400
/// }
/// ```
///
/// ```
/// extern crate rowdy;
/// #[macro_use]
/// extern crate serde_derive;
/// extern crate serde_json;
///
/// use rowdy::Configuration;
///
/// # fn main() {
/// let json = r#"{
///     "issuer": "https://www.acme.com",
///     "allowed_origins": ["https://www.example.com", "https://www.foobar.com"],
///     "audience": ["https://www.example.com", "https://www.foobar.com"],
///     "signature_algorithm": "RS256",
///     "secret": {
///                 "rsa_private": "test/fixtures/rsa_private_key.der",
///                 "rsa_public": "test/fixtures/rsa_public_key.der"
///                },
///     "expiry_duration": 86400
/// }"#;
/// let deserialized: Configuration = serde_json::from_str(json).unwrap();
/// # }
/// ```
///
/// Variations for the fields `allowed_origins`, `audience` and `secret` exist. Refer to their type documentation for
/// examples.
#[derive(Serialize, Deserialize, Debug, Default)]
pub struct Configuration {
    /// The issuer of the token. Usually the URI of the authentication server.
    /// The issuer URI will also be used in the UUID generation of the tokens.
    pub issuer: String,
    /// Origins that are allowed to issue CORS request. This is needed for browser
    /// access to the authentication server, but tools like `curl` do not obey nor enforce the CORS convention.
    ///
    /// This enum (de)serialized as an [untagged](https://serde.rs/enum-representations.html) enum variant.
    ///
    /// See [`cors::AllowedOrigins`] for serialization examples.
    pub allowed_origins: cors::AllowedOrigins,
    /// The audience intended for your tokens.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub audience: Option<jwt::SingleOrMultipleStrings>,
    /// Defaults to `none`
    #[serde(skip_serializing_if = "Option::is_none")]
    pub signature_algorithm: Option<jws::Algorithm>,
    /// Secrets for use in signing and encrypting a JWT.
    /// This enum (de)serialized as an [untagged](https://serde.rs/enum-representations.html) enum variant.
    /// Defaults to `None`.
    ///
    /// See [`token::Secret`] for serialization examples
    #[serde(default)]
    pub secret: token::Secret,
    /// Expiry duration of tokens, in seconds. Defaults to 24 hours when deserialized and left unfilled
    #[serde(with = "::serde_custom::duration", default = "Configuration::default_expiry_duration")]
    pub expiry_duration: Duration,
}

impl Configuration {
    fn default_expiry_duration() -> Duration {
        Duration::from_secs(DEFAULT_EXPIRY_DURATION)
    }
}

/// Launches the Rocket server with the configuration. This function blocks and never returns.
pub fn launch(config: Configuration) {
    let token_getter_options = token::TokenGetterCorsOptions::new(&config);
    rocket::ignite()
        .mount("/",
               routes![token::token_getter, token::token_getter_options])
        .manage(config)
        .manage(token_getter_options)
        .launch();
}

#[cfg(test)]
mod tests {
    use std::default::Default;
    use std::str::FromStr;

    use serde_test::{Token, assert_tokens};

    use super::*;

    #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
    struct TestUrl {
        url: Url,
    }

    #[derive(Clone, Serialize, Deserialize, Debug, Eq, PartialEq)]
    struct TestClaims {
        company: String,
        department: String,
    }

    impl Default for TestClaims {
        fn default() -> Self {
            TestClaims {
                company: "ACME".to_string(),
                department: "Toilet Cleaning".to_string(),
            }
        }
    }

    #[test]
    fn url_serialization_token_round_trip() {
        let test = TestUrl { url: not_err!(Url::from_str("https://www.example.com/")) };

        assert_tokens(&test,
                      &[Token::StructStart("TestUrl", 1),
                        Token::StructSep,
                        Token::Str("url"),
                        Token::Str("https://www.example.com/"),
                        Token::StructEnd]);
    }
}
<|endoftext|>