<commit_before>use std::borrow::{Borrow, BorrowMut};
use gl;
use gl::types::*;
use types::{Color, Viewport, Capability, GLError};
use buffer::{BufferBinder, ContextBufferExt, BufferBinderRef, BufferBinderMut};
use framebuffer::{FramebufferBinder, ContextFramebufferExt};
use program::{ProgramBinder, ContextProgramExt, ProgramAttrib};
use renderbuffer::{RenderbufferBinder, ContextRenderbufferExt};
use shader::ContextShaderExt;
use texture::ContextTextureExt;
use texture_units::TextureUnits;

pub type Context = ContextOf<BufferBinder,
                             FramebufferBinder,
                             ProgramBinder,
                             RenderbufferBinder,
                             TextureUnits>;

pub type ContextRef<'a> = ContextOf<&'a BufferBinder,
                                    &'a FramebufferBinder,
                                    &'a ProgramBinder,
                                    &'a RenderbufferBinder,
                                    &'a TextureUnits>;

pub type ContextMut<'a> = ContextOf<&'a mut BufferBinder,
                                    &'a mut FramebufferBinder,
                                    &'a mut ProgramBinder,
                                    &'a mut RenderbufferBinder,
                                    &'a mut TextureUnits>;

pub type ContextSubRef<'a> = ContextOf<BufferBinderRef<'a>,
                                       &'a FramebufferBinder,
                                       &'a ProgramBinder,
                                       &'a RenderbufferBinder,
                                       &'a TextureUnits>;

pub type ContextSubMut<'a> = ContextOf<BufferBinderMut<'a>,
                                       &'a mut FramebufferBinder,
                                       &'a mut ProgramBinder,
                                       &'a mut RenderbufferBinder,
                                       &'a mut TextureUnits>;

pub struct ContextOf {
    pub buffers: B,
    pub framebuffer: F,
    pub program: P,
    pub renderbuffer: R,
    pub tex_units: T
}

impl ContextOf {
    pub unsafe fn current_context() -> Context {
        ContextOf {
            buffers: BufferBinder::current(),
            framebuffer: FramebufferBinder,
            program: ProgramBinder,
            renderbuffer: RenderbufferBinder,
            tex_units: TextureUnits::current()
        }
    }

    pub fn get_error() -> Option<GLError> {
        unsafe {
            match gl::GetError() {
                gl::INVALID_ENUM =>
                    Some(GLError::InvalidEnum),
                gl::INVALID_VALUE =>
                    Some(GLError::InvalidValue),
                gl::INVALID_OPERATION =>
                    Some(GLError::InvalidOperation),
                gl::INVALID_FRAMEBUFFER_OPERATION =>
                    Some(GLError::InvalidFramebufferOperation),
                gl::OUT_OF_MEMORY =>
                    Some(GLError::OutOfMemory),
                _ =>
                    None
            }
        }
    }

    pub fn borrowed<'a, BB = B, BF = F, BP = P, BR = R, BT = T>(&'a self)
        -> ContextOf<&'a BB, &'a BF, &'a BP, &'a BR, &'a BT>
        where B: Borrow<BB>,
              F: Borrow<BF>,
              P: Borrow<BP>,
              R: Borrow
,
              T: Borrow<BT>
    {
        ContextOf {
            buffers: self.buffers.borrow(),
            framebuffer: self.framebuffer.borrow(),
            program: self.program.borrow(),
            renderbuffer: self.renderbuffer.borrow(),
            tex_units: self.tex_units.borrow()
        }
    }

    pub fn borrowed_mut<'a, BB = B, BF = F, BP = P, BR = R, BT = T>
                       (&'a mut self)
        -> ContextOf<&'a mut BB,
                     &'a mut BF,
                     &'a mut BP,
                     &'a mut BR,
                     &'a mut BT>
        where B: BorrowMut<BB>,
              F: BorrowMut<BF>,
              P: BorrowMut<BP>,
              R: BorrowMut
,
              T: BorrowMut<BT>
    {
        ContextOf {
            buffers: self.buffers.borrow_mut(),
            framebuffer: self.framebuffer.borrow_mut(),
            program: self.program.borrow_mut(),
            renderbuffer: self.renderbuffer.borrow_mut(),
            tex_units: self.tex_units.borrow_mut()
        }
    }

    pub fn swap_buffers<NB>(self, new_buffer: NB)
        -> (B, ContextOf<NB, F, P, R, T>)
    {
        (
            self.buffers,
            ContextOf {
                buffers: new_buffer,
                framebuffer: self.framebuffer,
                program: self.program,
                renderbuffer: self.renderbuffer,
                tex_units: self.tex_units
            }
        )
    }

    pub fn swap_framebuffer<NF>(self, new_framebuffer: NF)
        -> (F, ContextOf)
    {
        (
            self.framebuffer,
            ContextOf {
                buffers: self.buffers,
                framebuffer: new_framebuffer,
                program: self.program,
                renderbuffer: self.renderbuffer,
                tex_units: self.tex_units
            }
        )
    }

    pub fn swap_program<NP>(self, new_program: NP)
        -> (P, ContextOf)
    {
        (
            self.program,
            ContextOf {
                buffers: self.buffers,
                framebuffer: self.framebuffer,
                program: new_program,
                renderbuffer: self.renderbuffer,
                tex_units: self.tex_units
            }
        )
    }

    pub fn swap_renderbuffer<NR>(self, new_renderbuffer: NR)
        -> (R, ContextOf)
    {
        (
            self.renderbuffer,
            ContextOf {
                buffers: self.buffers,
                framebuffer: self.framebuffer,
                program: self.program,
                renderbuffer: new_renderbuffer,
                tex_units: self.tex_units
            }
        )
    }

    pub fn swap_tex_units<NT>(self, new_tex_units: NT)
        -> (T, ContextOf)
    {
        (
            self.tex_units,
            ContextOf {
                buffers: self.buffers,
                framebuffer: self.framebuffer,
                program: self.program,
                renderbuffer: self.renderbuffer,
                tex_units: new_tex_units
            }
        )
    }
}

pub unsafe trait ContextExt {
    fn clear_color(&mut self, color: Color) {
        unsafe {
            gl::ClearColor(color.r, color.g, color.b, color.a);
        }
    }

    fn enable(&mut self, cap: Capability) {
        unsafe {
            gl::Enable(cap.gl_enum());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`cap` is not a valid OpenGL capability",
                _ => "Unknown error"
            }
        }
    }

    fn disable(&mut self, cap: Capability) {
        unsafe {
            gl::Disable(cap.gl_enum());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`cap` is not a valid OpenGL capability",
                _ => "Unknown error"
            }
        }
    }

    fn enable_vertex_attrib_array(&self, attrib: ProgramAttrib) {
        unsafe {
            gl::EnableVertexAttribArray(attrib.gl_index);
            dbg_gl_error! {
                GLError::InvalidValue => "`index` is >= GL_MAX_VERTEX_ATTRIBS",
                _ => "Unknown error"
            }
        }
    }

    fn viewport(&self, viewport: Viewport) {
        unsafe {
            gl::Viewport(viewport.x as GLint,
                         viewport.y as GLint,
                         viewport.width as GLsizei,
                         viewport.height as GLsizei);
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`width` or `height` is negative",
                _ => "Unknown error"
            }
        }
    }
}

unsafe impl ContextExt for ContextOf {

}

unsafe impl<'a, B, F, P, R, T> ContextExt for &'a mut ContextOf {

}

pub mod ext {
    pub use ContextExt;
    pub use ContextBufferExt;
    pub use ContextFramebufferExt;
    pub use ContextProgramExt;
    pub use ContextRenderbufferExt;
    pub use ContextShaderExt;
    pub use ContextTextureExt;
}

pub trait AContext: ContextExt +
                    ContextBufferExt +
                    ContextFramebufferExt +
                    ContextProgramExt +
                    ContextRenderbufferExt +
                    ContextShaderExt +
                    ContextTextureExt
{

}

impl AContext for ContextOf {

}

impl<'a, B, F, P, R, T> AContext for &'a mut ContextOf {

}

// HACK: Workaround for issue described here:
// https://www.reddit.com/r/rust/comments/339yj3/tuple_indexing_in_a_macro/cqiyv4n
#[macro_export]
macro_rules! _glitter_expr {
    ($x:expr) => ($x)
}

#[macro_export]
macro_rules! active_texture {
    ($gl:expr, $idx:tt) => {
        _glitter_expr!($gl.tex_units.$idx.active())
    }
}

#[macro_export]
macro_rules! active_texture_n {
    ($gl:expr, $idx:expr) => {
        $gl.tex_units.nth_unit($idx).active()
    }
}
<commit_msg>Add `ToRef` and `ToMut` impls for `ContextOf`<commit_after>use std::borrow::{Borrow, BorrowMut};
use gl;
use gl::types::*;
use types::{Color, Viewport, Capability, GLError};
use buffer::{BufferBinder, ContextBufferExt, BufferBinderRef, BufferBinderMut};
use framebuffer::{FramebufferBinder, ContextFramebufferExt};
use program::{ProgramBinder, ContextProgramExt, ProgramAttrib};
use renderbuffer::{RenderbufferBinder, ContextRenderbufferExt};
use shader::ContextShaderExt;
use texture::ContextTextureExt;
use texture_units::TextureUnits;
use to_ref::{ToRef, ToMut};

pub type Context = ContextOf<BufferBinder,
                             FramebufferBinder,
                             ProgramBinder,
                             RenderbufferBinder,
                             TextureUnits>;

pub type ContextRef<'a> = ContextOf<&'a BufferBinder,
                                    &'a FramebufferBinder,
                                    &'a ProgramBinder,
                                    &'a RenderbufferBinder,
                                    &'a TextureUnits>;

pub type ContextMut<'a> = ContextOf<&'a mut BufferBinder,
                                    &'a mut FramebufferBinder,
                                    &'a mut ProgramBinder,
                                    &'a mut RenderbufferBinder,
                                    &'a mut TextureUnits>;

pub type ContextSubRef<'a> = ContextOf<BufferBinderRef<'a>,
                                       &'a FramebufferBinder,
                                       &'a ProgramBinder,
                                       &'a RenderbufferBinder,
                                       &'a TextureUnits>;

pub type ContextSubMut<'a> = ContextOf<BufferBinderMut<'a>,
                                       &'a mut FramebufferBinder,
                                       &'a mut ProgramBinder,
                                       &'a mut RenderbufferBinder,
                                       &'a mut TextureUnits>;

pub struct ContextOf {
    pub buffers: B,
    pub framebuffer: F,
    pub program: P,
    pub renderbuffer: R,
    pub tex_units: T
}

impl ContextOf {
    pub unsafe fn current_context() -> Context {
        ContextOf {
            buffers: BufferBinder::current(),
            framebuffer: FramebufferBinder,
            program: ProgramBinder,
            renderbuffer: RenderbufferBinder,
            tex_units: TextureUnits::current()
        }
    }

    pub fn get_error() -> Option<GLError> {
        unsafe {
            match gl::GetError() {
                gl::INVALID_ENUM =>
                    Some(GLError::InvalidEnum),
                gl::INVALID_VALUE =>
                    Some(GLError::InvalidValue),
                gl::INVALID_OPERATION =>
                    Some(GLError::InvalidOperation),
                gl::INVALID_FRAMEBUFFER_OPERATION =>
                    Some(GLError::InvalidFramebufferOperation),
                gl::OUT_OF_MEMORY =>
                    Some(GLError::OutOfMemory),
                _ =>
                    None
            }
        }
    }

    pub fn borrowed<'a, BB = B, BF = F, BP = P, BR = R, BT = T>(&'a self)
        -> ContextOf<&'a BB, &'a BF, &'a BP, &'a BR, &'a BT>
        where B: Borrow<BB>,
              F: Borrow<BF>,
              P: Borrow<BP>,
              R: Borrow
,
              T: Borrow<BT>
    {
        ContextOf {
            buffers: self.buffers.borrow(),
            framebuffer: self.framebuffer.borrow(),
            program: self.program.borrow(),
            renderbuffer: self.renderbuffer.borrow(),
            tex_units: self.tex_units.borrow()
        }
    }

    pub fn borrowed_mut<'a, BB = B, BF = F, BP = P, BR = R, BT = T>
                       (&'a mut self)
        -> ContextOf<&'a mut BB,
                     &'a mut BF,
                     &'a mut BP,
                     &'a mut BR,
                     &'a mut BT>
        where B: BorrowMut<BB>,
              F: BorrowMut<BF>,
              P: BorrowMut<BP>,
              R: BorrowMut
,
              T: BorrowMut<BT>
    {
        ContextOf {
            buffers: self.buffers.borrow_mut(),
            framebuffer: self.framebuffer.borrow_mut(),
            program: self.program.borrow_mut(),
            renderbuffer: self.renderbuffer.borrow_mut(),
            tex_units: self.tex_units.borrow_mut()
        }
    }

    pub fn swap_buffers<NB>(self, new_buffer: NB)
        -> (B, ContextOf<NB, F, P, R, T>)
    {
        (
            self.buffers,
            ContextOf {
                buffers: new_buffer,
                framebuffer: self.framebuffer,
                program: self.program,
                renderbuffer: self.renderbuffer,
                tex_units: self.tex_units
            }
        )
    }

    pub fn swap_framebuffer<NF>(self, new_framebuffer: NF)
        -> (F, ContextOf)
    {
        (
            self.framebuffer,
            ContextOf {
                buffers: self.buffers,
                framebuffer: new_framebuffer,
                program: self.program,
                renderbuffer: self.renderbuffer,
                tex_units: self.tex_units
            }
        )
    }

    pub fn swap_program<NP>(self, new_program: NP)
        -> (P, ContextOf)
    {
        (
            self.program,
            ContextOf {
                buffers: self.buffers,
                framebuffer: self.framebuffer,
                program: new_program,
                renderbuffer: self.renderbuffer,
                tex_units: self.tex_units
            }
        )
    }

    pub fn swap_renderbuffer<NR>(self, new_renderbuffer: NR)
        -> (R, ContextOf)
    {
        (
            self.renderbuffer,
            ContextOf {
                buffers: self.buffers,
                framebuffer: self.framebuffer,
                program: self.program,
                renderbuffer: new_renderbuffer,
                tex_units: self.tex_units
            }
        )
    }

    pub fn swap_tex_units<NT>(self, new_tex_units: NT)
        -> (T, ContextOf)
    {
        (
            self.tex_units,
            ContextOf {
                buffers: self.buffers,
                framebuffer: self.framebuffer,
                program: self.program,
                renderbuffer: self.renderbuffer,
                tex_units: new_tex_units
            }
        )
    }
}

impl<'a, B, F, P, R, T> ToRef<'a> for ContextOf
    where B: 'a + ToRef<'a>,
          F: 'a + ToRef<'a>,
          P: 'a + ToRef<'a>,
          R: 'a + ToRef<'a>,
          T: 'a + ToRef<'a>
{
    type Ref = ContextOf;

    fn to_ref(&'a self) -> Self::Ref {
        ContextOf {
            buffers: self.buffers.to_ref(),
            framebuffer: self.framebuffer.to_ref(),
            program: self.program.to_ref(),
            renderbuffer: self.renderbuffer.to_ref(),
            tex_units: self.tex_units.to_ref()
        }
    }
}

impl<'a, B, F, P, R, T> ToMut<'a> for ContextOf
    where B: 'a + ToMut<'a>,
          F: 'a + ToMut<'a>,
          P: 'a + ToMut<'a>,
          R: 'a + ToMut<'a>,
          T: 'a + ToMut<'a>
{
    type Mut = ContextOf;

    fn to_mut(&'a mut self) -> Self::Mut {
        ContextOf {
            buffers: self.buffers.to_mut(),
            framebuffer: self.framebuffer.to_mut(),
            program: self.program.to_mut(),
            renderbuffer: self.renderbuffer.to_mut(),
            tex_units: self.tex_units.to_mut()
        }
    }
}

pub unsafe trait ContextExt {
    fn clear_color(&mut self, color: Color) {
        unsafe {
            gl::ClearColor(color.r, color.g, color.b, color.a);
        }
    }

    fn enable(&mut self, cap: Capability) {
        unsafe {
            gl::Enable(cap.gl_enum());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`cap` is not a valid OpenGL capability",
                _ => "Unknown error"
            }
        }
    }

    fn disable(&mut self, cap: Capability) {
        unsafe {
            gl::Disable(cap.gl_enum());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`cap` is not a valid OpenGL capability",
                _ => "Unknown error"
            }
        }
    }

    fn enable_vertex_attrib_array(&self, attrib: ProgramAttrib) {
        unsafe {
            gl::EnableVertexAttribArray(attrib.gl_index);
            dbg_gl_error! {
                GLError::InvalidValue => "`index` is >= GL_MAX_VERTEX_ATTRIBS",
                _ => "Unknown error"
            }
        }
    }

    fn viewport(&self, viewport: Viewport) {
        unsafe {
            gl::Viewport(viewport.x as GLint,
                         viewport.y as GLint,
                         viewport.width as GLsizei,
                         viewport.height as GLsizei);
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`width` or `height` is negative",
                _ => "Unknown error"
            }
        }
    }
}

unsafe impl ContextExt for ContextOf {

}

unsafe impl<'a, B, F, P, R, T> ContextExt for &'a mut ContextOf {

}

pub mod ext {
    pub use ContextExt;
    pub use ContextBufferExt;
    pub use ContextFramebufferExt;
    pub use ContextProgramExt;
    pub use ContextRenderbufferExt;
    pub use ContextShaderExt;
    pub use ContextTextureExt;
}

pub trait AContext: ContextExt +
                    ContextBufferExt +
                    ContextFramebufferExt +
                    ContextProgramExt +
                    ContextRenderbufferExt +
                    ContextShaderExt +
                    ContextTextureExt
{

}

impl AContext for ContextOf {

}

impl<'a, B, F, P, R, T> AContext for &'a mut ContextOf {

}

// HACK: Workaround for issue described here:
// https://www.reddit.com/r/rust/comments/339yj3/tuple_indexing_in_a_macro/cqiyv4n
#[macro_export]
macro_rules! _glitter_expr {
    ($x:expr) => ($x)
}

#[macro_export]
macro_rules! active_texture {
    ($gl:expr, $idx:tt) => {
        _glitter_expr!($gl.tex_units.$idx.active())
    }
}

#[macro_export]
macro_rules! active_texture_n {
    ($gl:expr, $idx:expr) => {
        $gl.tex_units.nth_unit($idx).active()
    }
}
<|endoftext|>


<commit_before>//! Transformation context

use draw_state::DrawState;
use vecmath::{
    identity,
    Matrix2d,
    Scalar
};

/// Transform property
#[derive(Copy)]
pub struct Transform(pub Matrix2d);

/// View transform property
#[derive(Copy)]
pub struct ViewTransform(pub Matrix2d);

/// Drawing 2d context.
#[derive(Copy, Clone)]
pub struct Context {
    /// View transformation.
    pub view: Matrix2d,
    /// Current transformation.
    pub transform: Matrix2d,
    /// Current draw state settings.
    pub draw_state: DrawState,
}

quack! {
    c: Context[]
    get:
        fn () -> Transform [] { Transform(c.transform) }
        fn () -> ViewTransform [] { ViewTransform(c.view) }
    set:
        fn (val: Transform) [] { c.transform = val.0 }
        fn (val: ViewTransform) [] { c.view = val.0 }
    action:
}

fn default_draw_state() -> DrawState {
    use draw_state::block::{ CullFace, RasterMethod };

    let mut draw_state = DrawState::new();
    draw_state.primitive.method = RasterMethod::Fill(CullFace::Nothing);
    draw_state
}

impl Context {
    /// Creates a new drawing context.
    #[inline(always)]
    pub fn new() -> Context {
        Context {
            view: identity(),
            transform: identity(),
            draw_state: default_draw_state(),
        }
    }

    /// Creates a new drawing context in absolute coordinates.
    ///
    /// This function assumes the default coordinate system
    /// being centered with x axis pointing to the right
    /// and y axis pointing up.
    ///
    /// Returns a drawing context
    /// with origin in the upper left corner
    /// and x axis pointing to the right
    /// and y axis pointing down.
    #[inline(always)]
    pub fn abs(w: Scalar, h: Scalar) -> Context {
        let sx = 2.0 / w;
        let sy = -2.0 / h;
        let mat = [[ sx, 0.0, -1.0 ],
                   [ 0.0,  sy, 1.0 ]];
        Context {
            view: mat,
            transform: mat,
            draw_state: default_draw_state(),
        }
    }
}

#[cfg(test)]
mod test {
    use super::Context;
    use std::num::Float;

    #[test]
    fn test_context() {
        use RelativeTransform;

        let c = Context::new();
        {
            let d = c.trans(20.0, 40.0);
            let d = d.trans(10.0, 10.0);
            let transform = d.transform;
            assert_eq!(transform[0][2], 30.0);
            assert_eq!(transform[1][2], 50.0);
        }

        let transform = c.transform;
        assert_eq!(transform[0][2], 0.0);
        assert_eq!(transform[1][2], 0.0);

        let c = c.rot_deg(90.0);
        let transform = c.transform;
        assert!((transform[0][0] - 0.0).abs() < 0.00001);
        assert!((transform[0][1] + 1.0).abs() < 0.00001);
    }

    #[test]
    fn test_scale() {
        use RelativeTransform;

        let c = Context::new();
        let c = c.scale(2.0, 3.0);
        let transform = c.transform;
        assert!((transform[0][0] - 2.0).abs() < 0.00001);
        assert!((transform[1][1] - 3.0).abs() < 0.00001);
    }
}
<commit_msg>Enable alpha blending by default<commit_after>//! Transformation context

use draw_state::DrawState;
use vecmath::{
    identity,
    Matrix2d,
    Scalar
};

/// Transform property
#[derive(Copy)]
pub struct Transform(pub Matrix2d);

/// View transform property
#[derive(Copy)]
pub struct ViewTransform(pub Matrix2d);

/// Drawing 2d context.
#[derive(Copy, Clone)]
pub struct Context {
    /// View transformation.
    pub view: Matrix2d,
    /// Current transformation.
    pub transform: Matrix2d,
    /// Current draw state settings.
    pub draw_state: DrawState,
}

quack! {
    c: Context[]
    get:
        fn () -> Transform [] { Transform(c.transform) }
        fn () -> ViewTransform [] { ViewTransform(c.view) }
    set:
        fn (val: Transform) [] { c.transform = val.0 }
        fn (val: ViewTransform) [] { c.view = val.0 }
    action:
}

fn default_draw_state() -> DrawState {
    use draw_state::block::{ CullFace, RasterMethod };
    use draw_state::BlendPreset;

    let mut draw_state = DrawState::new();
    draw_state.primitive.method = RasterMethod::Fill(CullFace::Nothing);
    draw_state.blend(BlendPreset::Alpha)
}

impl Context {
    /// Creates a new drawing context.
    #[inline(always)]
    pub fn new() -> Context {
        Context {
            view: identity(),
            transform: identity(),
            draw_state: default_draw_state(),
        }
    }

    /// Creates a new drawing context in absolute coordinates.
    ///
    /// This function assumes the default coordinate system
    /// being centered with x axis pointing to the right
    /// and y axis pointing up.
    ///
    /// Returns a drawing context
    /// with origin in the upper left corner
    /// and x axis pointing to the right
    /// and y axis pointing down.
    #[inline(always)]
    pub fn abs(w: Scalar, h: Scalar) -> Context {
        let sx = 2.0 / w;
        let sy = -2.0 / h;
        let mat = [[ sx, 0.0, -1.0 ],
                   [ 0.0,  sy, 1.0 ]];
        Context {
            view: mat,
            transform: mat,
            draw_state: default_draw_state(),
        }
    }
}

#[cfg(test)]
mod test {
    use super::Context;
    use std::num::Float;

    #[test]
    fn test_context() {
        use RelativeTransform;

        let c = Context::new();
        {
            let d = c.trans(20.0, 40.0);
            let d = d.trans(10.0, 10.0);
            let transform = d.transform;
            assert_eq!(transform[0][2], 30.0);
            assert_eq!(transform[1][2], 50.0);
        }

        let transform = c.transform;
        assert_eq!(transform[0][2], 0.0);
        assert_eq!(transform[1][2], 0.0);

        let c = c.rot_deg(90.0);
        let transform = c.transform;
        assert!((transform[0][0] - 0.0).abs() < 0.00001);
        assert!((transform[0][1] + 1.0).abs() < 0.00001);
    }

    #[test]
    fn test_scale() {
        use RelativeTransform;

        let c = Context::new();
        let c = c.scale(2.0, 3.0);
        let transform = c.transform;
        assert!((transform[0][0] - 2.0).abs() < 0.00001);
        assert!((transform[1][1] - 3.0).abs() < 0.00001);
    }
}
<|endoftext|>


<commit_before>//!Handler context and request body reading extensions.

use std::collections::HashMap;
use std::io::{self, Read};
use std::net::SocketAddr;

#[cfg(feature = "rustc_json_body")]
use rustc_serialize::json;
#[cfg(feature = "rustc_json_body")]
use rustc_serialize::Decodable;

use hyper::http::HttpReader;
use hyper::net::NetworkStream;
use hyper::buffer::BufReader;

use utils;

use HttpVersion;
use Method;
use header::Headers;
use log::Log;

use Global;

///A container for things like request data and cache.
///
///A `Context` can be dereferenced to a `BodyReader`, allowing direct access to
///the underlying read methods.
pub struct Context<'a, 'b: 'a, 's> {
    ///Headers from the HTTP request.
    pub headers: Headers,

    ///The HTTP version used in the request.
    pub http_version: HttpVersion,

    ///The client address
    pub address: SocketAddr,

    ///The HTTP method.
    pub method: Method,

    ///The requested path.
    pub path: String,

    ///Hypermedia from the current endpoint.
    pub hypermedia: Hypermedia<'s>,

    ///Route variables.
    pub variables: HashMap<String, String>,

    ///Query variables from the path.
    pub query: HashMap<String, String>,

    ///The fragment part of the URL (after #), if provided.
    pub fragment: Option<String>,

    ///Log for notes, errors and warnings.
    pub log: &'s (Log + 's),

    ///Globally accessible data.
    pub global: &'s Global,

    ///A reader for the request body.
    pub body: BodyReader<'a, 'b>,
}

///A reader for a request body.
pub struct BodyReader<'a, 'b: 'a> {
    request: HttpReader<&'a mut BufReader<&'b mut NetworkStream>>
}

impl<'a, 'b> BodyReader<'a, 'b> {
    pub fn from_reader(request: HttpReader<&'a mut BufReader<&'b mut NetworkStream>>) -> BodyReader<'a, 'b> {
        BodyReader {
            request: request
        }
    }
}

impl<'a, 'b> Read for BodyReader<'a, 'b> {
    ///Read the request body.
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.request.read(buf)
    }
}

///`BodyReader` extension for reading and parsing a query string.
pub trait ExtQueryBody {
    fn read_query_body(&mut self) -> io::Result<HashMap<String, String>>;
}

impl<'a, 'b> ExtQueryBody for BodyReader<'a, 'b> {
    ///Read and parse the request body as a query string.
    ///The body will be decoded as UTF-8 and plain '+' characters will be replaced with spaces.
    #[inline]
    fn read_query_body(&mut self) -> io::Result<HashMap<String, String>> {
        let mut buf = Vec::new();
        try!(self.read_to_end(&mut buf));
        Ok(utils::parse_parameters(&buf))
    }
}

///`BodyReader` extension for reading and parsing a JSON body.
///
///It is available by default and can be toggled using the `rustc_json_body`
///feature.
#[cfg(feature = "rustc_json_body")]
pub trait ExtJsonBody {
    ///Read the body into a JSON structure.
    fn read_json_body(&mut self) -> Result<json::Json, json::BuilderError>;

    ///Parse and decode the body as some type `T`.
    fn decode_json_body<T: Decodable>(&mut self) -> json::DecodeResult<T>;
}

#[cfg(feature = "rustc_json_body")]
impl<'a, 'b> ExtJsonBody for BodyReader<'a, 'b> {
    fn read_json_body(&mut self) -> Result<json::Json, json::BuilderError> {
        json::Json::from_reader(self)
    }

    fn decode_json_body<T: Decodable>(&mut self) -> json::DecodeResult<T> {
        let mut buf = String::new();
        try!(self.read_to_string(&mut buf).map_err(|e| {
            let parse_err = json::ParserError::IoError(e);
            json::DecoderError::ParseError(parse_err)
        }));
        json::decode(&buf)
    }
}

///Hypermedia connected to an API endpoint.
pub struct Hypermedia<'a> {
    ///Forward links from the current endpoint to other endpoints.
    pub links: Vec<Link<'a>>
}

impl<'a> Hypermedia<'a> {
    ///Create an empty `Hypermedia` structure.
    pub fn new() -> Hypermedia<'a> {
        Hypermedia {
            links: vec![]
        }
    }
}

///A hyperlink.
#[derive(PartialEq, Eq, Debug)]
pub struct Link<'a> {
    ///The HTTP method for which an endpoint is available. It can be left
    ///unspecified if the method doesn't matter.
    pub method: Option<Method>,
    ///A relative path from the current location.
    pub path: Vec<LinkSegment<'a>>
}

///A segment of a hyperlink path.
#[derive(PartialEq, Eq, Debug)]
pub enum LinkSegment<'a> {
    ///A static part of a path.
    Static(&'a str),
    ///A dynamic part of a path. Can be substituted with anything.
    Variable(&'a str),
    ///A recursive wildcard. Will recursively match anything.
    RecursiveWildcard
}
<commit_msg>Add examples and a little more information about body parsing<commit_after>//!Handler context and request body reading extensions.

use std::collections::HashMap;
use std::io::{self, Read};
use std::net::SocketAddr;

#[cfg(feature = "rustc_json_body")]
use rustc_serialize::json;
#[cfg(feature = "rustc_json_body")]
use rustc_serialize::Decodable;

use hyper::http::HttpReader;
use hyper::net::NetworkStream;
use hyper::buffer::BufReader;

use utils;

use HttpVersion;
use Method;
use header::Headers;
use log::Log;

use Global;

///A container for things like request data and cache.
///
///A `Context` can be dereferenced to a `BodyReader`, allowing direct access to
///the underlying read methods.
pub struct Context<'a, 'b: 'a, 's> {
    ///Headers from the HTTP request.
    pub headers: Headers,

    ///The HTTP version used in the request.
    pub http_version: HttpVersion,

    ///The client address
    pub address: SocketAddr,

    ///The HTTP method.
    pub method: Method,

    ///The requested path.
    pub path: String,

    ///Hypermedia from the current endpoint.
    pub hypermedia: Hypermedia<'s>,

    ///Route variables.
    pub variables: HashMap<String, String>,

    ///Query variables from the path.
    pub query: HashMap<String, String>,

    ///The fragment part of the URL (after #), if provided.
    pub fragment: Option<String>,

    ///Log for notes, errors and warnings.
    pub log: &'s (Log + 's),

    ///Globally accessible data.
    pub global: &'s Global,

    ///A reader for the request body.
    pub body: BodyReader<'a, 'b>,
}

///A reader for a request body.
pub struct BodyReader<'a, 'b: 'a> {
    request: HttpReader<&'a mut BufReader<&'b mut NetworkStream>>
}

impl<'a, 'b> BodyReader<'a, 'b> {
    pub fn from_reader(request: HttpReader<&'a mut BufReader<&'b mut NetworkStream>>) -> BodyReader<'a, 'b> {
        BodyReader {
            request: request
        }
    }
}

///`BodyReader` extension for reading and parsing a query string.
///
///Examples and more information can be found in [the documentation for
///`BodyReader`][body_reader].
///
///[body_reader]: struct.BodyReader.html
pub trait ExtQueryBody {
    fn read_query_body(&mut self) -> io::Result<HashMap<String, String>>;
}

impl<'a, 'b> ExtQueryBody for BodyReader<'a, 'b> {
    ///Read and parse the request body as a query string. The body will be
    ///decoded as UTF-8 and plain '+' characters will be replaced with spaces.
    ///
    ///A simplified example of how to parse `a=number&b=number`:
    ///
    ///```
    ///use rustful::{Context, Response};
    ///use rustful::context::ExtQueryBody;
    ///
    ///fn my_handler(mut context: Context, response: Response) {
    ///    //Parse the request body as a query string
    ///    let query = context.body.read_query_body().unwrap();
    ///
    ///    //Find "a" and "b" and assume that they are numbers
    ///    let a: f64 = query.get("a").and_then(|number| number.parse().ok()).unwrap();
    ///    let b: f64 = query.get("b").and_then(|number| number.parse().ok()).unwrap();
    ///
    ///    response.into_writer().send(format!("{} + {} = {}", a, b, a + b));
    ///}
    ///```
    #[inline]
    fn read_query_body(&mut self) -> io::Result<HashMap<String, String>> {
        let mut buf = Vec::new();
        try!(self.read_to_end(&mut buf));
        Ok(utils::parse_parameters(&buf))
    }
}

///`BodyReader` extension for reading and parsing a JSON body.
///
///It is available by default and can be toggled using the `rustc_json_body`
///feature. Examples and more information can be found in [the documentation
///for `BodyReader`][body_reader].
///
///[body_reader]: struct.BodyReader.html
#[cfg(feature = "rustc_json_body")]
pub trait ExtJsonBody {
    ///Read the request body into a JSON structure.
    fn read_json_body(&mut self) -> Result<json::Json, json::BuilderError>;

    ///Parse and decode the request body as some type `T`.
    fn decode_json_body<T: Decodable>(&mut self) -> json::DecodeResult<T>;
}

#[cfg(feature = "rustc_json_body")]
impl<'a, 'b> ExtJsonBody for BodyReader<'a, 'b> {
    ///Read the request body into a generic JSON structure. This structure can
    ///then be navigated and parsed freely.
    ///
    ///A simplified example of how to parse `{ "a": number, "b": number }`:
    ///
    ///```
    ///use rustful::{Context, Response};
    ///use rustful::context::ExtJsonBody;
    ///
    ///fn my_handler(mut context: Context, response: Response) {
    ///    //Parse the request body as JSON
    ///    let json = context.body.read_json_body().unwrap();
    ///
    ///    //Find "a" and "b" in the root object and assume that they are numbers
    ///    let a = json.find("a").and_then(|number| number.as_f64()).unwrap();
    ///    let b = json.find("b").and_then(|number| number.as_f64()).unwrap();
    ///
    ///    response.into_writer().send(format!("{} + {} = {}", a, b, a + b));
    ///}
    ///```
    fn read_json_body(&mut self) -> Result<json::Json, json::BuilderError> {
        json::Json::from_reader(self)
    }

    ///Read and decode a request body as a type `T`. The target type must
    ///implement `rustc_serialize::Decodable`.
    ///
    ///A simplified example of how to parse `{ "a": number, "b": number }`:
    ///
    ///```
    ///extern crate rustful;
    ///extern crate rustc_serialize;
    ///
    ///use rustful::{Context, Response};
    ///use rustful::context::ExtJsonBody;
    ///
    ///#[derive(RustcDecodable)]
    ///struct Foo {
    ///    a: f64,
    ///    b: f64
    ///}
    ///
    ///fn my_handler(mut context: Context, response: Response) {
    ///    //Decode a JSON formatted request body into Foo
    ///    let foo: Foo = context.body.decode_json_body().unwrap();
    ///
    ///    let res = format!("{} + {} = {}", foo.a, foo.b, foo.a + foo.b);
    ///    response.into_writer().send(res);
    ///}
    ///# fn main() {}
    ///```
    fn decode_json_body<T: Decodable>(&mut self) -> json::DecodeResult<T> {
        let mut buf = String::new();
        try!(self.read_to_string(&mut buf).map_err(|e| {
            let parse_err = json::ParserError::IoError(e);
            json::DecoderError::ParseError(parse_err)
        }));
        json::decode(&buf)
    }
}

impl<'a, 'b> Read for BodyReader<'a, 'b> {
    ///Read the request body.
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.request.read(buf)
    }
}

///Hypermedia connected to an API endpoint.
pub struct Hypermedia<'a> {
    ///Forward links from the current endpoint to other endpoints.
    pub links: Vec<Link<'a>>
}

impl<'a> Hypermedia<'a> {
    ///Create an empty `Hypermedia` structure.
    pub fn new() -> Hypermedia<'a> {
        Hypermedia {
            links: vec![]
        }
    }
}

///A hyperlink.
#[derive(PartialEq, Eq, Debug)]
pub struct Link<'a> {
    ///The HTTP method for which an endpoint is available. It can be left
    ///unspecified if the method doesn't matter.
    pub method: Option<Method>,
    ///A relative path from the current location.
    pub path: Vec<LinkSegment<'a>>
}

///A segment of a hyperlink path.
#[derive(PartialEq, Eq, Debug)]
pub enum LinkSegment<'a> {
    ///A static part of a path.
    Static(&'a str),
    ///A dynamic part of a path. Can be substituted with anything.
    Variable(&'a str),
    ///A recursive wildcard. Will recursively match anything.
    RecursiveWildcard
}
<|endoftext|>


<commit_before>use std::io::{self, Stdout, stdout, stdin, Write};
use termion::input::TermRead;
use termion::raw::{IntoRawMode, RawTerminal};

use super::*;

/// The default for `Context.word_fn`.
pub fn get_buffer_words(buf: &Buffer) -> Vec<(usize, usize)> {
    let mut res = Vec::new();

    let mut word_start = None;
    let mut just_had_backslash = false;

    for (i, &c) in buf.chars().enumerate() {
        if c == '\\' {
            just_had_backslash = true;
            continue;
        }

        if let Some(start) = word_start {
            if c == ' ' && !just_had_backslash {
                res.push((start, i));
                word_start = None;
            }
        } else {
            if c != ' ' {
                word_start = Some(i);
            }
        }

        just_had_backslash = false;
    }

    if let Some(start) = word_start {
        res.push((start, buf.num_chars()));
    }

    res
}

pub struct Context {
    pub history: History,
    pub completer: Option<Box<Completer>>,
    pub word_fn: Box<Fn(&Buffer) -> Vec<(usize, usize)>>,
}

impl Context {
    pub fn new() -> Self {
        Context {
            history: History::new(),
            completer: None,
            word_fn: Box::new(get_buffer_words),
        }
    }

    /// Creates an `Editor` and feeds it keypresses from stdin until the line is entered.
    /// The output is stdout.
    /// The returned line has the newline removed.
    /// Before returning, will revert all changes to the history buffers.
    pub fn read_line<P: Into<String>>(&mut self,
                                      prompt: P,
                                      mut handler: &mut EventHandler<RawTerminal<Stdout>>)
                                      -> io::Result<String> {
        let res = {
            let stdout = stdout().into_raw_mode().unwrap();
            let ed = try!(Editor::new(stdout, prompt.into(), self));
            Self::handle_keys(ed, handler)
        };

        self.revert_all_history();
        res
    }

    fn handle_keys<'a, T, W: Write, M: KeyMap<'a, W, T>>(
        mut keymap: M,
        mut handler: &mut EventHandler<W>)
    -> io::Result<String>
        where String: From<M>
    {
        let stdin = stdin();
        for c in stdin.keys() {
            if try!(keymap.handle_key(c.unwrap(), handler)) {
                break;
            }
        }

        Ok(keymap.into())
    }

    pub fn revert_all_history(&mut self) {
        for buf in &mut self.history.buffers {
            buf.revert();
        }
    }
}
<commit_msg>use Emacs key mapping in Context<commit_after>use std::io::{self, Stdout, stdout, stdin, Write};
use termion::input::TermRead;
use termion::raw::{IntoRawMode, RawTerminal};

use super::*;
use keymap;

/// The default for `Context.word_fn`.
pub fn get_buffer_words(buf: &Buffer) -> Vec<(usize, usize)> {
    let mut res = Vec::new();

    let mut word_start = None;
    let mut just_had_backslash = false;

    for (i, &c) in buf.chars().enumerate() {
        if c == '\\' {
            just_had_backslash = true;
            continue;
        }

        if let Some(start) = word_start {
            if c == ' ' && !just_had_backslash {
                res.push((start, i));
                word_start = None;
            }
        } else {
            if c != ' ' {
                word_start = Some(i);
            }
        }

        just_had_backslash = false;
    }

    if let Some(start) = word_start {
        res.push((start, buf.num_chars()));
    }

    res
}

pub struct Context {
    pub history: History,
    pub completer: Option<Box<Completer>>,
    pub word_fn: Box<Fn(&Buffer) -> Vec<(usize, usize)>>,
}

impl Context {
    pub fn new() -> Self {
        Context {
            history: History::new(),
            completer: None,
            word_fn: Box::new(get_buffer_words),
        }
    }

    /// Creates an `Editor` and feeds it keypresses from stdin until the line is entered.
    /// The output is stdout.
    /// The returned line has the newline removed.
    /// Before returning, will revert all changes to the history buffers.
    pub fn read_line<P: Into<String>>(&mut self,
                                      prompt: P,
                                      mut handler: &mut EventHandler<RawTerminal<Stdout>>)
                                      -> io::Result<String> {
        let res = {
            let stdout = stdout().into_raw_mode().unwrap();
            let ed = try!(Editor::new(stdout, prompt.into(), self));
            Self::handle_keys(keymap::Emacs::new(ed), handler)
        };

        self.revert_all_history();
        res
    }

    fn handle_keys<'a, T, W: Write, M: KeyMap<'a, W, T>>(
        mut keymap: M,
        mut handler: &mut EventHandler<W>)
    -> io::Result<String>
        where String: From<M>
    {
        let stdin = stdin();
        for c in stdin.keys() {
            if try!(keymap.handle_key(c.unwrap(), handler)) {
                break;
            }
        }

        Ok(keymap.into())
    }

    pub fn revert_all_history(&mut self) {
        for buf in &mut self.history.buffers {
            buf.revert();
        }
    }
}
<|endoftext|>


<commit_before>use std::io::{Result, BufReader, BufRead, Write};
use std::os::unix::fs::PermissionsExt;
use std::fs::{metadata, set_permissions, remove_file};
use std::sync::mpsc::TryRecvError;

use mioco;
use mioco::sync::mpsc::{channel, Sender, Receiver};
use mioco::unix::UnixListener;
use serde_json;

use resolver::{RcResolver};
use utils::{WithTimeout, JsonRpcRequest};

pub struct ControlServer {
    #[allow(dead_code)]
    live_token: Sender<()>,
    notifier: Option<Receiver<()>>,
}

impl ControlServer {
    pub fn new() -> Self {
        let (send, recv) = channel::<()>();
        ControlServer {
            live_token: send,
            notifier: Some(recv),
        }
    }
    pub fn run(&mut self, resolver: &RcResolver) -> Result<()> {
        let notifier = self.notifier.take().expect("run() can only be called once");
        ControlServer::serve(resolver, notifier)
    }
    fn serve(resolver: &RcResolver, live_notifier: Receiver<()>) -> Result<()> {
        let sock_path = &resolver.config.control.sock_path;
        // Clean up old socket
        remove_file(sock_path).is_ok();
        let listener = try!(UnixListener::bind(sock_path));
        let mut perm = try!(metadata(sock_path)).permissions();
        perm.set_mode(**resolver.config.control.sock_permission);
        try!(set_permissions(sock_path, perm));
        let weak = resolver.to_weak();
        mioco::spawn(move || {
            loop {
                select!(
                    r:listener => {
                        /* Fall below */
                    },
                    r:live_notifier => {
                        match live_notifier.try_recv() {
                            Ok(_) => panic!("Nothing should be sent over this channel"),
                            Err(TryRecvError::Disconnected) => {
                                debug!("Resolver is dropped, closing control channel");
                                return;
                            },
                            Err(e) => panic!("Unexpected error: {:?}", e),
                        };
                    },
                );
                let resolver = match weak.upgrade() {
                    Some(x) => x,
                    None => {
                        debug!("Resolver is dropped, closing control channel");
                        return;
                    },
                };
                let result = listener.try_accept()
                .expect("Unable to accept from control socket");
                let sock = match result {
                    Some(sock) => sock,
                    None => continue,
                };
                let sock = sock.with_resetting_timeout(5000);
                let mut reader = BufReader::new(sock);
                let mut buf = String::new();
                if let Err(e) = reader.read_line(&mut buf) {
                    warn!("Failed to read from control socket: {:?}", e);
                    continue;
                }
                let req: JsonRpcRequest = match serde_json::from_str(&buf) {
                    Ok(x) => x,
                    Err(e) => {
                        warn!(
                            "Control socket received an invalid request: {}, {:?}",
                            buf, e,
                        );
                        continue
                    },
                };
                info!("Command: {}", req.method);
                let resp = match req.method.as_str() {
                    "ping" => req.result("Pong".into()),
                    _ => req.error("Unknown command".into()),
                };
                let mut resp_str = serde_json::to_string(&resp).unwrap();
                resp_str.push_str("\n");
                let mut sock = reader.into_inner();
                if let Err(e) = sock.write_all(resp_str.as_bytes()) {
                    warn!("Failed to write to control socket: {:?}", e);
                }
            }
        });
        Ok(())
    }
}
<commit_msg>Better naming<commit_after>use std::io::{Result, BufReader, BufRead, Write};
use std::os::unix::fs::PermissionsExt;
use std::fs::{metadata, set_permissions, remove_file};
use std::sync::mpsc::TryRecvError;

use mioco;
use mioco::sync::mpsc::{channel, Sender, Receiver};
use mioco::unix::UnixListener;
use serde_json;

use resolver::{RcResolver};
use utils::{WithTimeout, JsonRpcRequest};

pub struct ControlServer {
    #[allow(dead_code)]
    live_keeper: Sender<()>,
    notifier: Option<Receiver<()>>,
}

impl ControlServer {
    pub fn new() -> Self {
        let (send, recv) = channel::<()>();
        ControlServer {
            live_keeper: send,
            notifier: Some(recv),
        }
    }
    pub fn run(&mut self, resolver: &RcResolver) -> Result<()> {
        let notifier = self.notifier.take().expect("run() can only be called once");
        ControlServer::serve(resolver, notifier)
    }
    fn serve(resolver: &RcResolver, live_notifier: Receiver<()>) -> Result<()> {
        let sock_path = &resolver.config.control.sock_path;
        // Clean up old socket
        remove_file(sock_path).is_ok();
        let listener = try!(UnixListener::bind(sock_path));
        let mut perm = try!(metadata(sock_path)).permissions();
        perm.set_mode(**resolver.config.control.sock_permission);
        try!(set_permissions(sock_path, perm));
        let weak = resolver.to_weak();
        mioco::spawn(move || {
            loop {
                select!(
                    r:listener => {
                        /* Fall below */
                    },
                    r:live_notifier => {
                        match live_notifier.try_recv() {
                            Ok(_) => panic!("Nothing should be sent over this channel"),
                            Err(TryRecvError::Disconnected) => {
                                debug!("Resolver is dropped, closing control channel");
                                return;
                            },
                            Err(e) => panic!("Unexpected error: {:?}", e),
                        };
                    },
                );
                let resolver = match weak.upgrade() {
                    Some(x) => x,
                    None => {
                        debug!("Resolver is dropped, closing control channel");
                        return;
                    },
                };
                let result = listener.try_accept()
                .expect("Unable to accept from control socket");
                let sock = match result {
                    Some(sock) => sock,
                    None => continue,
                };
                let sock = sock.with_resetting_timeout(5000);
                let mut reader = BufReader::new(sock);
                let mut buf = String::new();
                if let Err(e) = reader.read_line(&mut buf) {
                    warn!("Failed to read from control socket: {:?}", e);
                    continue;
                }
                let req: JsonRpcRequest = match serde_json::from_str(&buf) {
                    Ok(x) => x,
                    Err(e) => {
                        warn!(
                            "Control socket received an invalid request: {}, {:?}",
                            buf, e,
                        );
                        continue
                    },
                };
                info!("Command: {}", req.method);
                let resp = match req.method.as_str() {
                    "ping" => req.result("Pong".into()),
                    _ => req.error("Unknown command".into()),
                };
                let mut resp_str = serde_json::to_string(&resp).unwrap();
                resp_str.push_str("\n");
                let mut sock = reader.into_inner();
                if let Err(e) = sock.write_all(resp_str.as_bytes()) {
                    warn!("Failed to write to control socket: {:?}", e);
                }
            }
        });
        Ok(())
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use url::Url;
use hyper::method::Method;
use hyper::mime::{mod, Mime};
use hyper::header::Headers;
use hyper::header::common::ContentType;
use fetch::cors_cache::CORSCache;
use fetch::response::Response;

/// A [request context](http://fetch.spec.whatwg.org/#concept-request-context)
pub enum Context {
    Audio, Beacon, CSPreport, Download, Embed, Eventsource,
    Favicon, Fetch, Font, Form, Frame, Hyperlink, IFrame, Image,
    ImageSet, Import, Internal, Location, Manifest, Object, Ping,
    Plugin, Prefetch, Script, ServiceWorker, SharedWorker, Subresource,
    Style, Track, Video, Worker, XMLHttpRequest, XSLT
}

/// A [request context frame type](http://fetch.spec.whatwg.org/#concept-request-context-frame-type)
pub enum ContextFrameType {
    Auxiliary,
    TopLevel,
    Nested,
    ContextNone
}

/// A [referer](http://fetch.spec.whatwg.org/#concept-request-referrer)
pub enum Referer {
    RefererNone,
    Client,
    RefererUrl(Url)
}

/// A [request mode](http://fetch.spec.whatwg.org/#concept-request-mode)
pub enum RequestMode {
    SameOrigin,
    NoCORS,
    CORSMode,
    ForcedPreflightMode
}

/// Request [credentials mode](http://fetch.spec.whatwg.org/#concept-request-credentials-mode)
pub enum CredentialsMode {
    Omit,
    CredentialsSameOrigin,
    Include
}

/// [Response tainting](http://fetch.spec.whatwg.org/#concept-request-response-tainting)
pub enum ResponseTainting {
    Basic,
    CORSTainting,
    Opaque
}

/// A [Request](http://fetch.spec.whatwg.org/#requests) as defined by the Fetch spec
pub struct Request {
    pub method: Method,
    pub url: Url,
    pub headers: Headers,
    pub unsafe_request: bool,
    pub body: Option<Vec<u8>>,
    pub preserve_content_codings: bool,
    // pub client: GlobalRef, // XXXManishearth copy over only the relevant fields of the global scope,
                              // not the entire scope to avoid the libscript dependency
    pub skip_service_worker: bool,
    pub context: Context,
    pub context_frame_type: ContextFrameType,
    pub origin: Option<Url>,
    pub force_origin_header: bool,
    pub same_origin_data: bool,
    pub referer: Referer,
    pub authentication: bool,
    pub sync: bool,
    pub mode: RequestMode,
    pub credentials_mode: CredentialsMode,
    pub use_url_credentials: bool,
    pub manual_redirect: bool,
    pub redirect_count: uint,
    pub response_tainting: ResponseTainting,
    pub cache: Option<Box<CORSCache+'static>>
}

impl Request {
    pub fn new(url: Url, context: Context) -> Request {
         Request {
            method: Method::Get,
            url: url,
            headers: Headers::new(),
            unsafe_request: false,
            body: None,
            preserve_content_codings: false,
            skip_service_worker: false,
            context: context,
            context_frame_type: ContextFrameType::ContextNone,
            origin: None,
            force_origin_header: false,
            same_origin_data: false,
            referer: Referer::Client,
            authentication: false,
            sync: false,
            mode: RequestMode::NoCORS,
            credentials_mode: CredentialsMode::Omit,
            use_url_credentials: false,
            manual_redirect: false,
            redirect_count: 0,
            response_tainting: ResponseTainting::Basic,
            cache: None
        }
    }

    /// [Basic fetch](http://fetch.spec.whatwg.org#basic-fetch)
    pub fn basic_fetch(&mut self) -> Response {
        match self.url.scheme.as_slice() {
            "about" => match self.url.non_relative_scheme_data() {
                Some(s) if s.as_slice() == "blank" => {
                    let mut response = Response::new();
                    response.headers.set(ContentType(Mime(
                        mime::TopLevel::Text, mime::SubLevel::Html,
                        vec![(mime::Attr::Charset, mime::Value::Utf8)])));
                    response
                },
                _ => Response::network_error()
            },
            "http" | "https" => {
                self.http_fetch(false, false, false)
            },
            "blob" | "data" | "file" | "ftp" => {
                // XXXManishearth handle these
                panic!("Unimplemented scheme for Fetch")
            },

            _ => Response::network_error()
        }
    }

    // [HTTP fetch](http://fetch.spec.whatwg.org#http-fetch)
    pub fn http_fetch(&mut self, _cors_flag: bool, cors_preflight_flag: bool, _authentication_fetch_flag: bool) -> Response {
        let response = Response::new();
        // TODO: Service worker fetch
        // Step 3
        // Substep 1
        self.skip_service_worker = true;
        // Substep 2
        if cors_preflight_flag {
            // XXXManishearth stuff goes here
        }
        response
    }
}
<commit_msg>Import enums inside hyper::mime rather than the module.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use url::Url;
use hyper::method::Method;
use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};
use hyper::header::Headers;
use hyper::header::common::ContentType;
use fetch::cors_cache::CORSCache;
use fetch::response::Response;

/// A [request context](http://fetch.spec.whatwg.org/#concept-request-context)
pub enum Context {
    Audio, Beacon, CSPreport, Download, Embed, Eventsource,
    Favicon, Fetch, Font, Form, Frame, Hyperlink, IFrame, Image,
    ImageSet, Import, Internal, Location, Manifest, Object, Ping,
    Plugin, Prefetch, Script, ServiceWorker, SharedWorker, Subresource,
    Style, Track, Video, Worker, XMLHttpRequest, XSLT
}

/// A [request context frame type](http://fetch.spec.whatwg.org/#concept-request-context-frame-type)
pub enum ContextFrameType {
    Auxiliary,
    TopLevel,
    Nested,
    ContextNone
}

/// A [referer](http://fetch.spec.whatwg.org/#concept-request-referrer)
pub enum Referer {
    RefererNone,
    Client,
    RefererUrl(Url)
}

/// A [request mode](http://fetch.spec.whatwg.org/#concept-request-mode)
pub enum RequestMode {
    SameOrigin,
    NoCORS,
    CORSMode,
    ForcedPreflightMode
}

/// Request [credentials mode](http://fetch.spec.whatwg.org/#concept-request-credentials-mode)
pub enum CredentialsMode {
    Omit,
    CredentialsSameOrigin,
    Include
}

/// [Response tainting](http://fetch.spec.whatwg.org/#concept-request-response-tainting)
pub enum ResponseTainting {
    Basic,
    CORSTainting,
    Opaque
}

/// A [Request](http://fetch.spec.whatwg.org/#requests) as defined by the Fetch spec
pub struct Request {
    pub method: Method,
    pub url: Url,
    pub headers: Headers,
    pub unsafe_request: bool,
    pub body: Option<Vec<u8>>,
    pub preserve_content_codings: bool,
    // pub client: GlobalRef, // XXXManishearth copy over only the relevant fields of the global scope,
                              // not the entire scope to avoid the libscript dependency
    pub skip_service_worker: bool,
    pub context: Context,
    pub context_frame_type: ContextFrameType,
    pub origin: Option<Url>,
    pub force_origin_header: bool,
    pub same_origin_data: bool,
    pub referer: Referer,
    pub authentication: bool,
    pub sync: bool,
    pub mode: RequestMode,
    pub credentials_mode: CredentialsMode,
    pub use_url_credentials: bool,
    pub manual_redirect: bool,
    pub redirect_count: uint,
    pub response_tainting: ResponseTainting,
    pub cache: Option<Box<CORSCache+'static>>
}

impl Request {
    pub fn new(url: Url, context: Context) -> Request {
         Request {
            method: Method::Get,
            url: url,
            headers: Headers::new(),
            unsafe_request: false,
            body: None,
            preserve_content_codings: false,
            skip_service_worker: false,
            context: context,
            context_frame_type: ContextFrameType::ContextNone,
            origin: None,
            force_origin_header: false,
            same_origin_data: false,
            referer: Referer::Client,
            authentication: false,
            sync: false,
            mode: RequestMode::NoCORS,
            credentials_mode: CredentialsMode::Omit,
            use_url_credentials: false,
            manual_redirect: false,
            redirect_count: 0,
            response_tainting: ResponseTainting::Basic,
            cache: None
        }
    }

    /// [Basic fetch](http://fetch.spec.whatwg.org#basic-fetch)
    pub fn basic_fetch(&mut self) -> Response {
        match self.url.scheme.as_slice() {
            "about" => match self.url.non_relative_scheme_data() {
                Some(s) if s.as_slice() == "blank" => {
                    let mut response = Response::new();
                    response.headers.set(ContentType(Mime(
                        TopLevel::Text, SubLevel::Html,
                        vec![(Attr::Charset, Value::Utf8)])));
                    response
                },
                _ => Response::network_error()
            },
            "http" | "https" => {
                self.http_fetch(false, false, false)
            },
            "blob" | "data" | "file" | "ftp" => {
                // XXXManishearth handle these
                panic!("Unimplemented scheme for Fetch")
            },

            _ => Response::network_error()
        }
    }

    // [HTTP fetch](http://fetch.spec.whatwg.org#http-fetch)
    pub fn http_fetch(&mut self, _cors_flag: bool, cors_preflight_flag: bool, _authentication_fetch_flag: bool) -> Response {
        let response = Response::new();
        // TODO: Service worker fetch
        // Step 3
        // Substep 1
        self.skip_service_worker = true;
        // Substep 2
        if cors_preflight_flag {
            // XXXManishearth stuff goes here
        }
        response
    }
}
<|endoftext|>


<commit_before>//! The initializer module parses arguments and verfies commands are valid
//! The creator module handles creating the muxed directory and project files.
#![allow(experimental)]

use std::io::{File,fs};
use std::io::process::Command;
use std::path::posix::Path;
use std::os::homedir;
use libc::funcs::c95::stdlib::system;
#[cfg(test)] use std::rand::random;
#[cfg(test)] use std::finally::Finally;

static TEMPLATE: &'static str = include_str!("creator/template.yml");
static DEFAULT_MUXED_DIR: &'static str = "muxed";

pub fn new(name: &str) {
    let muxed_dir = match muxed_dir_exists(&DEFAULT_MUXED_DIR.to_string()) {
        true  => Path::new(format!("{}/.{}/", homedir_string(), &DEFAULT_MUXED_DIR.to_string())),
        false => create_muxed_dir(&DEFAULT_MUXED_DIR.to_string())
    };

    let path = &Path::new(format!("{}/{}", muxed_dir.display(), name));
    if !path.exists() {
        create_project_file(path);

        match default_editor_set() {
            true  => open_project_file(path),
            false => println!("Default editor is not set. Please define $EDITOR in your ~/.bashrc or similar file.")
        }
    } else {
        println!("Project already exists.");
    }
}

fn default_editor_set() -> bool {
  let output = match Command::new("which").arg("$EDITOR").output() {
      Ok(output) => output.output.to_string(),
      Err(e) => fail!("failed to execute process: {}", e),
  };

  !output.is_empty()
}

#[cfg(not(test))] fn open_project_file(path: &Path) {
    let method = format!("$EDITOR {}", path.display()).to_c_str();
    unsafe { system(method.unwrap()); };
}

#[cfg(test)] fn open_project_file(_path: &Path) { }

/// Copy and create the new project file from a template. Attempt to open the
/// users default editor to make changes.
fn create_project_file(path: &Path) {
    match File::create(path).write(TEMPLATE.as_bytes()) {
        Ok(()) => (),
        Err(_e) => println!("Failed to create project {}", path.filename()),
    }
}

/// Create the muxed directory and return the path if creation is successful.
fn create_muxed_dir(name: &String) -> Path {
    let path = &Path::new(format!("{}/.{}", homedir_string(), name));
    match fs::mkdir(path, ::std::io::UserRWX) {
        Ok(()) => (),
        Err(_e) => println!("Failed to create project {}", path.filename()),
    }

    path.clone()
}

/// Return a boolean if the ~/.muxed/ dir exists.
fn muxed_dir_exists(name: &String) -> bool {
    let path = &Path::new(format!("{}/.{}", homedir_string(), name));
    path.exists()
}

/// Return the users current homedir as a string.
fn homedir_string() -> String {
    let home_unwrap = homedir().unwrap();
    format!("{}", home_unwrap.display())
}

/// Test helper to standardize how random files and directories are generated.
#[cfg(test)]
fn random_name() -> String {
    format!("test_{}", random::<f64>())
}

#[test]
fn muxed_dir_exists_returns_false() {
    assert!(!muxed_dir_exists(&random_name()));
}

#[test]
fn muxed_dir_exists_returns_true() {
    let dir = random_name();
    create_muxed_dir(&dir);
    assert!(muxed_dir_exists(&dir));

    let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir));
    match fs::rmdir_recursive(muxed_path) {
        Ok(()) => (), // succeeded
        Err(e) => println!("Failed to remove the path {} with error {}", muxed_path.display(), e),
    }
}

#[test]
fn creates_muxed_dir() {
    let dir = random_name();
    let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir));
    create_muxed_dir(&dir);
    assert!(muxed_path.exists());
    match fs::rmdir_recursive(muxed_path) {
        Ok(()) => (), // succeeded
        Err(e) => println!("Failed to remove the path {} with error {}", muxed_path.display(), e),
    }
}

#[test]
fn new_writes_file_to_muxed_dir() {
    let name = random_name();
    let path = &Path::new(format!("{}/.muxed/{}", homedir_string(), name));
    new(name.as_slice());
    assert!(path.exists());
    match fs::unlink(path) {
        Ok(()) => (), // succeeded
        Err(e) => println!("Failed to unlink the path {} with error {}", path.display(), e),
    }
}

#[test]
// TODO: Fix this test so it verifies something better.
fn new_doesnt_overwrite_existing_file() {
    let name = random_name();
    let path = &Path::new(format!("{}/.muxed/{}", homedir_string(), name));
    new(name.as_slice());
    (|| {
        new(name.as_slice());
    }).finally(|| {
        match fs::unlink(path) {
            Ok(()) => (), // succeeded
            Err(e) => println!("Failed to unlink the path {} with error {}", path.display(), e),
        }
    })
}
<commit_msg>Add some comments/docs.<commit_after>//! The initializer module parses arguments and verfies commands are valid
//! The creator module handles creating the muxed directory and project files.
#![allow(experimental)]

use std::io::{File,fs};
use std::io::process::Command;
use std::path::posix::Path;
use std::os::homedir;
use libc::funcs::c95::stdlib::system;
#[cfg(test)] use std::rand::random;
#[cfg(test)] use std::finally::Finally;

static TEMPLATE: &'static str = include_str!("creator/template.yml");
static DEFAULT_MUXED_DIR: &'static str = "muxed";

pub fn new(name: &str) {
    let muxed_dir = match muxed_dir_exists(&DEFAULT_MUXED_DIR.to_string()) {
        true  => Path::new(format!("{}/.{}/", homedir_string(), &DEFAULT_MUXED_DIR.to_string())),
        false => create_muxed_dir(&DEFAULT_MUXED_DIR.to_string())
    };

    let path = &Path::new(format!("{}/{}", muxed_dir.display(), name));
    if !path.exists() {
        create_project_file(path);

        match default_editor_set() {
            true  => open_project_file(path),
            false => println!("Default editor is not set. Please define $EDITOR in your ~/.bashrc or similar file.")
        }
    } else {
        println!("Project already exists.");
    }
}

/// Run `which $EDITOR` to see if a default editor is defined on the system.
fn default_editor_set() -> bool {
  let output = match Command::new("which").arg("$EDITOR").output() {
      Ok(output) => output.output.to_string(),
      Err(e) => fail!("failed to execute process: {}", e),
  };

  !output.is_empty()
}

/// Open a project file with the default editor. Uses C directly to interact
/// with the system.
#[cfg(not(test))] fn open_project_file(path: &Path) {
    let method = format!("$EDITOR {}", path.display()).to_c_str();
    unsafe { system(method.unwrap()); };
}

#[cfg(test)] fn open_project_file(_path: &Path) { }

/// Copy and create the new project file from a template. Attempt to open the
/// users default editor to make changes.
fn create_project_file(path: &Path) {
    match File::create(path).write(TEMPLATE.as_bytes()) {
        Ok(()) => (),
        Err(_e) => println!("Failed to create project {}", path.filename()),
    }
}

/// Create the muxed directory and return the path if creation is successful.
fn create_muxed_dir(name: &String) -> Path {
    let path = &Path::new(format!("{}/.{}", homedir_string(), name));
    match fs::mkdir(path, ::std::io::UserRWX) {
        Ok(()) => (),
        Err(_e) => println!("Failed to create project {}", path.filename()),
    }

    path.clone()
}

/// Return a boolean if the ~/.muxed/ dir exists.
fn muxed_dir_exists(name: &String) -> bool {
    let path = &Path::new(format!("{}/.{}", homedir_string(), name));
    path.exists()
}

/// Return the users current homedir as a string.
fn homedir_string() -> String {
    let home_unwrap = homedir().unwrap();
    format!("{}", home_unwrap.display())
}

/// Test helper to standardize how random files and directories are generated.
#[cfg(test)]
fn random_name() -> String {
    format!("test_{}", random::<f64>())
}

#[test]
fn muxed_dir_exists_returns_false() {
    assert!(!muxed_dir_exists(&random_name()));
}

#[test]
fn muxed_dir_exists_returns_true() {
    let dir = random_name();
    create_muxed_dir(&dir);
    assert!(muxed_dir_exists(&dir));

    let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir));
    match fs::rmdir_recursive(muxed_path) {
        Ok(()) => (), // succeeded
        Err(e) => println!("Failed to remove the path {} with error {}", muxed_path.display(), e),
    }
}

#[test]
fn creates_muxed_dir() {
    let dir = random_name();
    let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir));
    create_muxed_dir(&dir);
    assert!(muxed_path.exists());
    match fs::rmdir_recursive(muxed_path) {
        Ok(()) => (), // succeeded
        Err(e) => println!("Failed to remove the path {} with error {}", muxed_path.display(), e),
    }
}

#[test]
fn new_writes_file_to_muxed_dir() {
    let name = random_name();
    let path = &Path::new(format!("{}/.muxed/{}", homedir_string(), name));
    new(name.as_slice());
    assert!(path.exists());
    match fs::unlink(path) {
        Ok(()) => (), // succeeded
        Err(e) => println!("Failed to unlink the path {} with error {}", path.display(), e),
    }
}

#[test]
// TODO: Fix this test so it verifies something better.
fn new_doesnt_overwrite_existing_file() {
    let name = random_name();
    let path = &Path::new(format!("{}/.muxed/{}", homedir_string(), name));
    new(name.as_slice());
    (|| {
        new(name.as_slice());
    }).finally(|| {
        match fs::unlink(path) {
            Ok(()) => (), // succeeded
            Err(e) => println!("Failed to unlink the path {} with error {}", path.display(), e),
        }
    })
}
<|endoftext|>


<commit_before>use av_format::error::*;
use std::io::SeekFrom;
use av_data::packet::Packet;
use av_format::stream::*;
use av_format::buffer::Buffered;
use av_format::demuxer::demux::{Demuxer, Event};
use av_format::demuxer::context::GlobalInfo;
use std::collections::VecDeque;
use rational::Rational32;

use ebml::{ebml_header, EBMLHeader};
use elements::{segment, segment_element, Cluster, SeekHead, Info, Tracks, TrackEntry,
               SegmentElement, simple_block};
use nom::{self, IResult, Offset};

#[derive(Debug, Clone, PartialEq)]
pub struct MkvDemuxer {
    pub header: Option<EBMLHeader>,
    pub seek_head: Option<SeekHead>,
    pub info: Option<Info>,
    pub tracks: Option<Tracks>,
    //pub clusters: Vec<Cluster>,
    pub queue: VecDeque<Event>,
    pub blockstream: Vec<u8>,
}

impl MkvDemuxer {
    pub fn new() -> MkvDemuxer {
        MkvDemuxer {
            header: None,
            seek_head: None,
            info: None,
            tracks: None,
            //clusters: Vec::new(),
            queue: VecDeque::new(),
            blockstream: Vec::new(),
        }
    }

    pub fn parse_until_tracks<'a>(&mut self, original_input: &'a [u8]) -> IResult<&'a [u8], ()> {
        let (i1, header) = try_parse!(original_input, ebml_header);

        self.header = Some(header);

        let (mut input, _) = try_parse!(i1, segment);

        loop {
            if self.seek_head.is_some() && self.info.is_some() && self.tracks.is_some() {
                return IResult::Done(input, ());
            }

            println!("offset: {}", original_input.offset(input));

            let (i3, element) = try_parse!(input, segment_element);

            match element {
                SegmentElement::SeekHead(s) => {
                    println!("got seek head: {:#?}", s);
                    if self.seek_head.is_some() {
                        return IResult::Error(nom::ErrorKind::Custom(1));
                    } else {
                        self.seek_head = Some(s);
                    }
                }
                SegmentElement::Info(i) => {
                    println!("got info: {:#?}", i);
                    if self.info.is_some() {
                        return IResult::Error(nom::ErrorKind::Custom(1));
                    } else {
                        self.info = Some(i);
                    }
                }
                SegmentElement::Tracks(t) => {
                    println!("got tracks: {:#?}", t);
                    if self.tracks.is_some() {
                        return IResult::Error(nom::ErrorKind::Custom(1));
                    } else {
                        self.tracks = Some(t);
                    }
                }
                SegmentElement::Cluster(c) => {
                    println!("got a cluster: {:#?}", c);
                    //self.clusters.push(c);
                }
                el => {
                    println!("got element: {:#?}", el);
                }
            }

            input = i3;
        }
    }
}

impl Demuxer for MkvDemuxer {
    fn open(&mut self) {}

    fn read_headers(&mut self, buf: &Box<Buffered>, info: &mut GlobalInfo) -> Result<SeekFrom> {
        match self.parse_until_tracks(buf.data()) {
            IResult::Done(i, _) => {
                info.duration = self.info.as_ref().and_then(|info| info.duration).map(|d| {
                    d as u64
                });
                if let Some(ref t) = self.tracks {
                    info.streams = t.tracks.iter().map(|tr| track_to_stream(tr)).collect();
                }
                Ok(SeekFrom::Current(buf.data().offset(i) as i64))
            }
            IResult::Incomplete(_) => Err(ErrorKind::MoreDataNeeded.into()),
            e => {
              println!("error reading headers: {:?}", e);
              Err(ErrorKind::InvalidData.into())
            },
        }
    }

    fn read_packet(&mut self, buf: &Box<Buffered>) -> Result<(SeekFrom, Event)> {
        match segment_element(buf.data()) {
            IResult::Done(i, element) => {
                let seek = SeekFrom::Current(buf.data().offset(i) as i64);
                match element {
                    SegmentElement::Cluster(c) => {
                        //self.clusters.push(c);
                        println!("got cluster element at timecode: {}", c.timecode);
                        for block in c.simple_block.iter() {
                          println!("got simple block of size {}", block.len());
                          if let IResult::Done(_,o) = simple_block(block) {
                            println!("parsing simple block: {:?}", o);
                          } else {
                            println!("error parsing simple block");
                          }
                          self.blockstream.extend(*block);
                        }

                        for block_group in c.block_group.iter() {
                          println!("got block group of size {}", block_group.block.len());
                          self.blockstream.extend(block_group.block);
                        }
                    }
                    el => {
                        println!("got element: {:#?}", el);
                    }
                }

                Ok((seek, Event::MoreDataNeeded))
            }
            IResult::Incomplete(_) => Ok((SeekFrom::Current(0), Event::MoreDataNeeded)),
            e => {
                println!("parsing issue: {:?}", e);
                Err(ErrorKind::InvalidData.into())
            }
        }
    }
}

fn track_entry_codec_id(t: &TrackEntry) -> Option<CodecID> {
    // TODO: Support V_QUICKTIME and V_MS/VFW/FOURCC
    match t.codec_id.as_ref() {
        "A_OPUS" => Some(CodecID::Opus),
        "V_VP9"  => Some(CodecID::VP9),
        _ => None
    }
}

fn track_entry_video_kind(t: &TrackEntry) -> Option<MediaKind> {
    // TODO: Validate that a track::video exists for track::type video before.
    if let Some(ref video) = t.video {
        let v = VideoInfo {
            width : video.pixel_width as usize,
            height : video.pixel_height as usize,
            // TODO parse Colour and/or CodecPrivate to extract the format
            format : None
        };
        Some(MediaKind::Video(v))
    } else {
        None
    }
}

fn track_entry_audio_kind(t: &TrackEntry) -> Option<MediaKind> {
    // TODO: Validate that a track::video exists for track::type video before.
    if let Some(ref audio) = t.audio {
        let rate = if let Some(r) = audio.output_sampling_frequency {
            r
        } else {
            audio.sampling_frequency
        };
        // TODO: complete it
        let a = AudioInfo {
            samples: 0,
            rate: rate as usize,
            map: None,
            format: None,
        };
        Some(MediaKind::Audio(a))
    } else {
        None
    }
}

fn track_entry_media_kind(t: &TrackEntry) -> Option<MediaKind> {
    // TODO: Use an enum for the track type
    match t.track_type {
        0x1 => track_entry_video_kind(t),
        0x2 => track_entry_audio_kind(t),
        _ => None
    }
}

pub fn track_to_stream(t: &TrackEntry) -> Stream {
    Stream {
    id: t.track_uid as usize,
    index: t.track_number as usize,
    start: None,
    duration: t.default_duration,
    timebase : Rational32::from_integer(1),
    // TODO: Extend CodecParams and fill it with the remaining information
    params : CodecParams {
        extradata: t.codec_private.clone(),
        bit_rate: 0,
        codec_id: track_entry_codec_id(t),
        kind: track_entry_media_kind(t)
    },
  }
}

impl<'a> Cluster<'a> {
  pub fn generate_packet(&mut self) -> Option<Event> {
    if self.simple_block.len() > 0 {
      let block_data = self.simple_block.remove(0);

      if let IResult::Done(i, block) = simple_block(block_data) {
        println!("parsing simple block: {:?}", block);
        let packet = Packet {
          data:         i.into(),
          pts:          Some(block.timecode as i64),
          dts:          None,
          pos:          None,
          stream_index: block.track_number as isize,
          is_key:       block.keyframe,
          is_corrupted: false,
        };

        Some(Event::NewPacket(packet))
      } else {
        println!("error parsing simple block");
        None
      }
    } else {
      None
    }
  }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Cursor;
    use nom::{IResult, Offset};
    use av_format::demuxer::context::DemuxerContext;

    const webm: &'static [u8] = include_bytes!("../assets/bbb-vp9-opus.webm");

    #[test]
    fn parse_headers() {
        let mut demuxer = MkvDemuxer::new();

        let res = demuxer.parse_until_tracks(webm);
        println!("got parsing res: {:?}", res);
        match res {
            IResult::Done(i, _) => {
                println!("offset: {} bytes", webm.offset(i));
            }
            e => {
                println!("could not parse: {:?}", e);
            }
        }

        println!("demuxer: {:#?}", demuxer);
        panic!();
    }

    #[test]
    fn context() {
        let mut context = DemuxerContext::new(Box::new(MkvDemuxer::new()),
                                              Box::new(Cursor::new(webm)));
        println!("DEMUXER CONTEXT read headers: {:?}", context.read_headers());
        println!("DEMUXER CONTEXT streams: {:?}", context.info.streams);
        println!("DEMUXER CONTEXT event: {:?}", context.read_packet());
        println!("DEMUXER CONTEXT event: {:?}", context.read_packet());
        println!("DEMUXER CONTEXT event: {:?}", context.read_packet());
        println!("DEMUXER CONTEXT event: {:?}", context.read_packet());
        panic!();
    }
}
<commit_msg>generate packets in the demuxer<commit_after>use av_format::error::*;
use std::io::SeekFrom;
use av_data::packet::Packet;
use av_format::stream::*;
use av_format::buffer::Buffered;
use av_format::demuxer::demux::{Demuxer, Event};
use av_format::demuxer::context::GlobalInfo;
use std::collections::VecDeque;
use rational::Rational32;

use ebml::{ebml_header, EBMLHeader};
use elements::{segment, segment_element, Cluster, SeekHead, Info, Tracks, TrackEntry,
               SegmentElement, simple_block};
use nom::{self, IResult, Offset};

#[derive(Debug, Clone, PartialEq)]
pub struct MkvDemuxer {
    pub header: Option<EBMLHeader>,
    pub seek_head: Option<SeekHead>,
    pub info: Option<Info>,
    pub tracks: Option<Tracks>,
    pub queue: VecDeque<Event>,
    pub blockstream: Vec<u8>,
}

impl MkvDemuxer {
    pub fn new() -> MkvDemuxer {
        MkvDemuxer {
            header: None,
            seek_head: None,
            info: None,
            tracks: None,
            queue: VecDeque::new(),
            blockstream: Vec::new(),
        }
    }

    pub fn parse_until_tracks<'a>(&mut self, original_input: &'a [u8]) -> IResult<&'a [u8], ()> {
        let (i1, header) = try_parse!(original_input, ebml_header);

        self.header = Some(header);

        let (mut input, _) = try_parse!(i1, segment);

        loop {
            if self.seek_head.is_some() && self.info.is_some() && self.tracks.is_some() {
                return IResult::Done(input, ());
            }

            println!("offset: {}", original_input.offset(input));

            let (i3, element) = try_parse!(input, segment_element);

            match element {
                SegmentElement::SeekHead(s) => {
                    println!("got seek head: {:#?}", s);
                    if self.seek_head.is_some() {
                        return IResult::Error(nom::ErrorKind::Custom(1));
                    } else {
                        self.seek_head = Some(s);
                    }
                }
                SegmentElement::Info(i) => {
                    println!("got info: {:#?}", i);
                    if self.info.is_some() {
                        return IResult::Error(nom::ErrorKind::Custom(1));
                    } else {
                        self.info = Some(i);
                    }
                }
                SegmentElement::Tracks(t) => {
                    println!("got tracks: {:#?}", t);
                    if self.tracks.is_some() {
                        return IResult::Error(nom::ErrorKind::Custom(1));
                    } else {
                        self.tracks = Some(t);
                    }
                }
                SegmentElement::Cluster(c) => {
                    println!("got a cluster: {:#?}", c);
                    //self.clusters.push(c);
                }
                el => {
                    println!("got element: {:#?}", el);
                }
            }

            input = i3;
        }
    }
}

impl Demuxer for MkvDemuxer {
    fn open(&mut self) {}

    fn read_headers(&mut self, buf: &Box<Buffered>, info: &mut GlobalInfo) -> Result<SeekFrom> {
        match self.parse_until_tracks(buf.data()) {
            IResult::Done(i, _) => {
                info.duration = self.info.as_ref().and_then(|info| info.duration).map(|d| {
                    d as u64
                });
                if let Some(ref t) = self.tracks {
                    info.streams = t.tracks.iter().map(|tr| track_to_stream(tr)).collect();
                }
                Ok(SeekFrom::Current(buf.data().offset(i) as i64))
            }
            IResult::Incomplete(_) => Err(ErrorKind::MoreDataNeeded.into()),
            e => {
              println!("error reading headers: {:?}", e);
              Err(ErrorKind::InvalidData.into())
            },
        }
    }

    fn read_packet(&mut self, buf: &Box<Buffered>) -> Result<(SeekFrom, Event)> {
        if let Some(event) = self.queue.pop_front() {
          Ok((SeekFrom::Current(0), event))
        } else {
          println!("no more stored packet, parsing a new one");
          match segment_element(buf.data()) {
              IResult::Done(i, element) => {
                  let seek = SeekFrom::Current(buf.data().offset(i) as i64);
                  match element {
                      SegmentElement::Cluster(c) => {
                        //self.clusters.push(c);
                        println!("got cluster element at timecode: {}", c.timecode);
                        let mut packets = c.generate_packets();
                        self.queue.extend(packets.drain(..));
                        /*
                        for block in c.simple_block.iter() {
                          println!("got simple block of size {}", block.len());
                          if let IResult::Done(_,o) = simple_block(block) {
                            println!("parsing simple block: {:?}", o);
                          } else {
                            println!("error parsing simple block");
                          }
                          self.blockstream.extend(*block);
                        }

                        for block_group in c.block_group.iter() {
                          println!("got block group of size {}", block_group.block.len());
                          self.blockstream.extend(block_group.block);
                        }
                        */
                        if let Some(event) = self.queue.pop_front() {
                          return Ok((seek, event))
                        }
                      }
                      el => {
                        println!("got element: {:#?}", el);
                      }
                  }

                  Ok((seek, Event::MoreDataNeeded))
              }
              IResult::Incomplete(_) => Ok((SeekFrom::Current(0), Event::MoreDataNeeded)),
              e => {
                  println!("parsing issue: {:?}", e);
                  Err(ErrorKind::InvalidData.into())
              }
          }
        }
    }
}

fn track_entry_codec_id(t: &TrackEntry) -> Option<CodecID> {
    // TODO: Support V_QUICKTIME and V_MS/VFW/FOURCC
    match t.codec_id.as_ref() {
        "A_OPUS" => Some(CodecID::Opus),
        "V_VP9"  => Some(CodecID::VP9),
        _ => None
    }
}

fn track_entry_video_kind(t: &TrackEntry) -> Option<MediaKind> {
    // TODO: Validate that a track::video exists for track::type video before.
    if let Some(ref video) = t.video {
        let v = VideoInfo {
            width : video.pixel_width as usize,
            height : video.pixel_height as usize,
            // TODO parse Colour and/or CodecPrivate to extract the format
            format : None
        };
        Some(MediaKind::Video(v))
    } else {
        None
    }
}

fn track_entry_audio_kind(t: &TrackEntry) -> Option<MediaKind> {
    // TODO: Validate that a track::video exists for track::type video before.
    if let Some(ref audio) = t.audio {
        let rate = if let Some(r) = audio.output_sampling_frequency {
            r
        } else {
            audio.sampling_frequency
        };
        // TODO: complete it
        let a = AudioInfo {
            samples: 0,
            rate: rate as usize,
            map: None,
            format: None,
        };
        Some(MediaKind::Audio(a))
    } else {
        None
    }
}

fn track_entry_media_kind(t: &TrackEntry) -> Option<MediaKind> {
    // TODO: Use an enum for the track type
    match t.track_type {
        0x1 => track_entry_video_kind(t),
        0x2 => track_entry_audio_kind(t),
        _ => None
    }
}

pub fn track_to_stream(t: &TrackEntry) -> Stream {
    Stream {
    id: t.track_uid as usize,
    index: t.track_number as usize,
    start: None,
    duration: t.default_duration,
    timebase : Rational32::from_integer(1),
    // TODO: Extend CodecParams and fill it with the remaining information
    params : CodecParams {
        extradata: t.codec_private.clone(),
        bit_rate: 0,
        codec_id: track_entry_codec_id(t),
        kind: track_entry_media_kind(t)
    },
  }
}

impl<'a> Cluster<'a> {
  pub fn generate_packets(&self) -> Vec<Event> {
    let mut v = Vec::new();

    for block_data in self.simple_block.iter() {
      if let IResult::Done(i, block) = simple_block(block_data) {
        //println!("parsing simple block: {:?}", block);
        let packet = Packet {
          data:         i.into(),
          pts:          Some(block.timecode as i64),
          dts:          None,
          pos:          None,
          stream_index: block.track_number as isize,
          is_key:       block.keyframe,
          is_corrupted: false,
        };

        v.push(Event::NewPacket(packet));
      } else {
        println!("error parsing simple block");
      }
    }

    v
  }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Cursor;
    use nom::{IResult, Offset};
    use av_format::demuxer::context::DemuxerContext;

    const webm: &'static [u8] = include_bytes!("../assets/bbb-vp9-opus.webm");

    #[test]
    fn parse_headers() {
        let mut demuxer = MkvDemuxer::new();

        let res = demuxer.parse_until_tracks(webm);
        println!("got parsing res: {:?}", res);
        match res {
            IResult::Done(i, _) => {
                println!("offset: {} bytes", webm.offset(i));
            }
            e => {
                println!("could not parse: {:?}", e);
            }
        }

        println!("demuxer: {:#?}", demuxer);
        panic!();
    }

    #[test]
    fn context() {
        let mut context = DemuxerContext::new(Box::new(MkvDemuxer::new()),
                                              Box::new(Cursor::new(webm)));
        println!("DEMUXER CONTEXT read headers: {:?}", context.read_headers());
        println!("DEMUXER CONTEXT streams: {:?}", context.info.streams);
        println!("DEMUXER CONTEXT event: {:?}", context.read_packet());
        println!("DEMUXER CONTEXT event: {:?}", context.read_packet());
        println!("DEMUXER CONTEXT event: {:?}", context.read_packet());
        println!("DEMUXER CONTEXT event: {:?}", context.read_packet());
        println!("DEMUXER CONTEXT event: {:?}", context.read_packet());
        println!("DEMUXER CONTEXT event: {:?}", context.read_packet());
        println!("DEMUXER CONTEXT event: {:?}", context.read_packet());
        println!("DEMUXER CONTEXT event: {:?}", context.read_packet());
        panic!();
    }
}
<|endoftext|>


<commit_before>use quote::Tokens;
use syn::{Data, DeriveInput, Field, Fields, Ident, Type};
use utils::{add_extra_ty_param_bound, named_to_vec, unnamed_to_vec};

/// Provides the hook to expand `#[derive(Display)]` into an implementation of `From`
pub fn expand(input: &DeriveInput, trait_name: &str) -> Tokens {
    let trait_path = &quote!(::std::fmt::Display);
    let generics = add_extra_ty_param_bound(&input.generics, trait_path);
    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
    let input_type = &input.ident;
    let member = match input.data {
        Data::Struct(ref data_struct) => match data_struct.fields {
            Fields::Unnamed(ref fields) => tuple_from_str(trait_name, unnamed_to_vec(fields)),
            Fields::Named(ref fields) => struct_from_str(trait_name, named_to_vec(fields)),
            Fields::Unit => panic_one_field(trait_name),
        },
        _ => panic_one_field(trait_name),
    };
    quote!{
        impl#impl_generics #trait_path for #input_type#ty_generics #where_clause
        {
            fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                return #member.fmt(formatter)
            }
        }
    }
}

fn panic_one_field(trait_name: &str) -> ! {
    panic!(format!(
        "Only structs with one field can derive({})",
        trait_name
    ))
}

fn tuple_from_str<'a>(trait_name: &str, fields: Vec<&'a Field>) -> Tokens {
    if fields.len() != 1 {
        panic_one_field(trait_name)
    };
    quote!(self.0)
}

fn struct_from_str<'a>(trait_name: &str, fields: Vec<&'a Field>) -> Tokens {
    if fields.len() != 1 {
        panic_one_field(trait_name)
    };
    let field = &fields[0];
    let field_ident = &field.ident;
    quote!(self.#field_ident)
}
<commit_msg>Fix warnings<commit_after>use quote::Tokens;
use syn::{Data, DeriveInput, Field, Fields};
use utils::{add_extra_ty_param_bound, named_to_vec, unnamed_to_vec};

/// Provides the hook to expand `#[derive(Display)]` into an implementation of `From`
pub fn expand(input: &DeriveInput, trait_name: &str) -> Tokens {
    let trait_path = &quote!(::std::fmt::Display);
    let generics = add_extra_ty_param_bound(&input.generics, trait_path);
    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
    let input_type = &input.ident;
    let member = match input.data {
        Data::Struct(ref data_struct) => match data_struct.fields {
            Fields::Unnamed(ref fields) => tuple_from_str(trait_name, unnamed_to_vec(fields)),
            Fields::Named(ref fields) => struct_from_str(trait_name, named_to_vec(fields)),
            Fields::Unit => panic_one_field(trait_name),
        },
        _ => panic_one_field(trait_name),
    };
    quote!{
        impl#impl_generics #trait_path for #input_type#ty_generics #where_clause
        {
            fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                return #member.fmt(formatter)
            }
        }
    }
}

fn panic_one_field(trait_name: &str) -> ! {
    panic!(format!(
        "Only structs with one field can derive({})",
        trait_name
    ))
}

fn tuple_from_str<'a>(trait_name: &str, fields: Vec<&'a Field>) -> Tokens {
    if fields.len() != 1 {
        panic_one_field(trait_name)
    };
    quote!(self.0)
}

fn struct_from_str<'a>(trait_name: &str, fields: Vec<&'a Field>) -> Tokens {
    if fields.len() != 1 {
        panic_one_field(trait_name)
    };
    let field = &fields[0];
    let field_ident = &field.ident;
    quote!(self.#field_ident)
}
<|endoftext|>


<commit_before>//! Draw ellipse

pub use rectangle::centered;
pub use rectangle::centered_square as circle;

use internal;
use triangulation;
use Graphics;
use Color;
use math::Matrix2d;
use DrawState;

/// Ellipse border
#[derive(Copy, Clone)]
pub struct Border {
    /// The border color
    pub color: internal::Color,
    /// The border radius
    pub radius: internal::Radius,
}

/// An ellipse with filled color
#[derive(Copy, Clone)]
pub struct Ellipse {
    /// The ellipse color
    pub color: internal::Color,
    /// The ellipse border
    pub border: Option<Border>,
}

impl Ellipse {
    /// Creates a new ellipse
    pub fn new(color: internal::Color) -> Ellipse {
        Ellipse {
            color: color,
            border: None
        }
    }

    /// Creates a new ellipse border
    pub fn new_border(
        color: internal::Color,
        radius: internal::Radius
    ) -> Ellipse {
        Ellipse {
            color: [0.0; 4],
            border: Some(Border {
                    color: color,
                    radius: radius,
                })
        }
    }

    /// Sets ellipse color.
    pub fn color(mut self, value: internal::Color) -> Self {
        self.color = value;
        self
    }

    /// Sets ellipse border.
    pub fn border(mut self, value: Border) -> Self {
        self.border = Some(value);
        self
    }

    /// Sets optional ellipse border.
    pub fn maybe_border(mut self, value: Option<Border>) -> Self {
        self.border = value;
        self
    }

    /// Draws the ellipse.
    pub fn draw<G>(
        &self,
        rectangle: internal::Rectangle,
        draw_state: &DrawState,
        transform: Matrix2d,
        g: &mut G
    )
        where G: Graphics
    {
        g.tri_list(
            draw_state,
            &self.color,
            |f|
        triangulation::with_ellipse_tri_list(
            128,
            transform,
            rectangle,
            |vertices| f(vertices)
        ));

        if let Some(Border { color, radius: border_radius }) = self.border {
            g.tri_list(
                &draw_state,
                &color,
                |f|
            triangulation::with_ellipse_border_tri_list(
                128,
                transform,
                rectangle,
                border_radius,
                |vertices| f(vertices)
            ));
        }
    }
}

#[cfg(test)]
mod test {
    use super::Ellipse;
    use super::Border;
    use Color;

    #[test]
    fn test_ellipse() {
        let _ellipse = Ellipse::new([1.0; 4])
            .set(Color([0.0; 4]))
            .set(Border { color: [1.0; 4], radius: 3.0 });
    }
}
<commit_msg>Fixed some unit test errors<commit_after>//! Draw ellipse

pub use rectangle::centered;
pub use rectangle::centered_square as circle;

use internal;
use triangulation;
use Graphics;
use Color;
use math::Matrix2d;
use DrawState;

/// Ellipse border
#[derive(Copy, Clone)]
pub struct Border {
    /// The border color
    pub color: internal::Color,
    /// The border radius
    pub radius: internal::Radius,
}

/// An ellipse with filled color
#[derive(Copy, Clone)]
pub struct Ellipse {
    /// The ellipse color
    pub color: internal::Color,
    /// The ellipse border
    pub border: Option<Border>,
}

impl Ellipse {
    /// Creates a new ellipse
    pub fn new(color: internal::Color) -> Ellipse {
        Ellipse {
            color: color,
            border: None
        }
    }

    /// Creates a new ellipse border
    pub fn new_border(
        color: internal::Color,
        radius: internal::Radius
    ) -> Ellipse {
        Ellipse {
            color: [0.0; 4],
            border: Some(Border {
                    color: color,
                    radius: radius,
                })
        }
    }

    /// Sets ellipse color.
    pub fn color(mut self, value: internal::Color) -> Self {
        self.color = value;
        self
    }

    /// Sets ellipse border.
    pub fn border(mut self, value: Border) -> Self {
        self.border = Some(value);
        self
    }

    /// Sets optional ellipse border.
    pub fn maybe_border(mut self, value: Option<Border>) -> Self {
        self.border = value;
        self
    }

    /// Draws the ellipse.
    pub fn draw<G>(
        &self,
        rectangle: internal::Rectangle,
        draw_state: &DrawState,
        transform: Matrix2d,
        g: &mut G
    )
        where G: Graphics
    {
        g.tri_list(
            draw_state,
            &self.color,
            |f|
        triangulation::with_ellipse_tri_list(
            128,
            transform,
            rectangle,
            |vertices| f(vertices)
        ));

        if let Some(Border { color, radius: border_radius }) = self.border {
            g.tri_list(
                &draw_state,
                &color,
                |f|
            triangulation::with_ellipse_border_tri_list(
                128,
                transform,
                rectangle,
                border_radius,
                |vertices| f(vertices)
            ));
        }
    }
}

#[cfg(test)]
mod test {
    use super::Ellipse;
    use super::Border;
    use Color;

    #[test]
    fn test_ellipse() {
        let _ellipse = Ellipse::new([1.0; 4])
            .color([0.0; 4])
            .border(Border { color: [1.0; 4], radius: 3.0 });
    }
}
<|endoftext|>