<commit_before>/*!

A render buffer is similar to a texture, but is optimized for usage as a draw target.

Contrary to a texture, you can't sample nor modify the content of a render buffer.
You should prefer render buffers over textures when you know that you don't need to read or modify
the data of the render buffer.

*/
use std::rc::Rc;
use std::ops::{Deref, DerefMut};
use std::mem;

use framebuffer::{ColorAttachment, ToColorAttachment};
use framebuffer::{DepthAttachment, ToDepthAttachment};
use framebuffer::{StencilAttachment, ToStencilAttachment};
use framebuffer::{DepthStencilAttachment, ToDepthStencilAttachment};
use texture::{UncompressedFloatFormat, DepthFormat, StencilFormat, DepthStencilFormat, TextureKind};

use image_format;

use gl;
use GlObject;
use fbo::FramebuffersContainer;
use backend::Facade;
use context::Context;
use ContextExt;
use version::Version;
use version::Api;

/// Error while creating a render buffer.
#[derive(Copy, Clone, Debug)]
pub enum CreationError {
    /// The requested format is not supported.
    FormatNotSupported,
}

impl From<image_format::FormatNotSupportedError> for CreationError {
    fn from(_: image_format::FormatNotSupportedError) -> CreationError {
        CreationError::FormatNotSupported
    }
}

/// A render buffer is similar to a texture, but is optimized for usage as a draw target.
///
/// Contrary to a texture, you can't sample or modify the content of the `RenderBuffer`.
pub struct RenderBuffer {
    buffer: RenderBufferAny,
}

impl RenderBuffer {
    /// Builds a new render buffer.
    pub fn new<F>(facade: &F, format: UncompressedFloatFormat, width: u32, height: u32)
                  -> Result<RenderBuffer, CreationError> where F: Facade
    {
        let format = image_format::TextureFormatRequest::Specific(image_format::TextureFormat::UncompressedFloat(format));
        let format = try!(image_format::format_request_to_glenum(&facade.get_context(), format, image_format::RequestType::Renderbuffer));

        Ok(RenderBuffer {
            buffer: RenderBufferAny::new(facade, format, TextureKind::Float, width, height, None)
        })
    }
}

impl<'a> ToColorAttachment<'a> for &'a RenderBuffer {
    #[inline]
    fn to_color_attachment(self) -> ColorAttachment<'a> {
        ColorAttachment::RenderBuffer(self)
    }
}

impl Deref for RenderBuffer {
    type Target = RenderBufferAny;

    #[inline]
    fn deref(&self) -> &RenderBufferAny {
        &self.buffer
    }
}

impl DerefMut for RenderBuffer {
    #[inline]
    fn deref_mut(&mut self) -> &mut RenderBufferAny {
        &mut self.buffer
    }
}

impl GlObject for RenderBuffer {
    type Id = gl::types::GLuint;

    #[inline]
    fn get_id(&self) -> gl::types::GLuint {
        self.buffer.get_id()
    }
}

/// A render buffer is similar to a texture, but is optimized for usage as a draw target.
///
/// Contrary to a texture, you can't sample or modify the content of the `DepthRenderBuffer` directly.
pub struct DepthRenderBuffer {
    buffer: RenderBufferAny,
}

impl DepthRenderBuffer {
    /// Builds a new render buffer.
    pub fn new<F>(facade: &F, format: DepthFormat, width: u32, height: u32)
                  -> Result<DepthRenderBuffer, CreationError> where F: Facade
    {
        let format = image_format::TextureFormatRequest::Specific(image_format::TextureFormat::DepthFormat(format));
        let format = try!(image_format::format_request_to_glenum(&facade.get_context(), format, image_format::RequestType::Renderbuffer));

        Ok(DepthRenderBuffer {
            buffer: RenderBufferAny::new(facade, format, TextureKind::Depth, width, height, None)
        })
    }
}

impl<'a> ToDepthAttachment<'a> for &'a DepthRenderBuffer {
    fn to_depth_attachment(self) -> DepthAttachment<'a> {
        DepthAttachment::RenderBuffer(self)
    }
}

impl Deref for DepthRenderBuffer {
    type Target = RenderBufferAny;

    #[inline]
    fn deref(&self) -> &RenderBufferAny {
        &self.buffer
    }
}

impl DerefMut for DepthRenderBuffer {
    #[inline]
    fn deref_mut(&mut self) -> &mut RenderBufferAny {
        &mut self.buffer
    }
}

impl GlObject for DepthRenderBuffer {
    type Id = gl::types::GLuint;

    #[inline]
    fn get_id(&self) -> gl::types::GLuint {
        self.buffer.get_id()
    }
}

/// A render buffer is similar to a texture, but is optimized for usage as a draw target.
///
/// Contrary to a texture, you can't sample or modify the content of the `StencilRenderBuffer` directly.
pub struct StencilRenderBuffer {
    buffer: RenderBufferAny,
}

impl StencilRenderBuffer {
    /// Builds a new render buffer.
    pub fn new<F>(facade: &F, format: StencilFormat, width: u32, height: u32)
                  -> Result<StencilRenderBuffer, CreationError> where F: Facade
    {
        let format = image_format::TextureFormatRequest::Specific(image_format::TextureFormat::StencilFormat(format));
        let format = try!(image_format::format_request_to_glenum(&facade.get_context(), format, image_format::RequestType::Renderbuffer));

        Ok(StencilRenderBuffer {
            buffer: RenderBufferAny::new(facade, format, TextureKind::Stencil, width, height, None)
        })
    }
}

impl<'a> ToStencilAttachment<'a> for &'a StencilRenderBuffer {
    #[inline]
    fn to_stencil_attachment(self) -> StencilAttachment<'a> {
        StencilAttachment::RenderBuffer(self)
    }
}

impl Deref for StencilRenderBuffer {
    type Target = RenderBufferAny;

    #[inline]
    fn deref(&self) -> &RenderBufferAny {
        &self.buffer
    }
}

impl DerefMut for StencilRenderBuffer {
    #[inline]
    fn deref_mut(&mut self) -> &mut RenderBufferAny {
        &mut self.buffer
    }
}

impl GlObject for StencilRenderBuffer {
    type Id = gl::types::GLuint;

    #[inline]
    fn get_id(&self) -> gl::types::GLuint {
        self.buffer.get_id()
    }
}

/// A render buffer is similar to a texture, but is optimized for usage as a draw target.
///
/// Contrary to a texture, you can't sample or modify the content of the `DepthStencilRenderBuffer` directly.
pub struct DepthStencilRenderBuffer {
    buffer: RenderBufferAny,
}

impl DepthStencilRenderBuffer {
    /// Builds a new render buffer.
    pub fn new<F>(facade: &F, format: DepthStencilFormat, width: u32, height: u32)
                  -> Result<DepthStencilRenderBuffer, CreationError> where F: Facade
    {
        let format = image_format::TextureFormatRequest::Specific(image_format::TextureFormat::DepthStencilFormat(format));
        let format = try!(image_format::format_request_to_glenum(&facade.get_context(), format, image_format::RequestType::Renderbuffer));

        Ok(DepthStencilRenderBuffer {
            buffer: RenderBufferAny::new(facade, format, TextureKind::DepthStencil, width, height, None)
        })
    }
}

impl<'a> ToDepthStencilAttachment<'a> for &'a DepthStencilRenderBuffer {
    #[inline]
    fn to_depth_stencil_attachment(self) -> DepthStencilAttachment<'a> {
        DepthStencilAttachment::RenderBuffer(self)
    }
}

impl Deref for DepthStencilRenderBuffer {
    type Target = RenderBufferAny;

    #[inline]
    fn deref(&self) -> &RenderBufferAny {
        &self.buffer
    }
}

impl DerefMut for DepthStencilRenderBuffer {
    #[inline]
    fn deref_mut(&mut self) -> &mut RenderBufferAny {
        &mut self.buffer
    }
}

impl GlObject for DepthStencilRenderBuffer {
    type Id = gl::types::GLuint;

    #[inline]
    fn get_id(&self) -> gl::types::GLuint {
        self.buffer.get_id()
    }
}

/// A RenderBuffer of indeterminate type.
pub struct RenderBufferAny {
    context: Rc<Context>,
    id: gl::types::GLuint,
    width: u32,
    height: u32,
    samples: Option<u32>,
    kind: TextureKind,
}

impl RenderBufferAny {
    /// Builds a new render buffer.
    fn new<F>(facade: &F, format: gl::types::GLenum, kind: TextureKind, width: u32, height: u32,
              samples: Option<u32>) -> RenderBufferAny
        where F: Facade
    {
        unsafe {
            // TODO: check that dimensions don't exceed GL_MAX_RENDERBUFFER_SIZE
            // FIXME: gles2 only supports very few formats
            let mut ctxt = facade.get_context().make_current();
            let mut id = mem::uninitialized();

            if ctxt.version >= &Version(Api::Gl, 4, 5) ||
               ctxt.extensions.gl_arb_direct_state_access
            {
                ctxt.gl.CreateRenderbuffers(1, &mut id);
                if let Some(samples) = samples {
                    ctxt.gl.NamedRenderbufferStorageMultisample(id, samples as gl::types::GLsizei,
                                                                format, width as gl::types::GLsizei,
                                                                height as gl::types::GLsizei);
                } else {
                    ctxt.gl.NamedRenderbufferStorage(id, format, width as gl::types::GLsizei,
                                                     height as gl::types::GLsizei);
                }

            } else if samples.is_some() && (ctxt.version >= &Version(Api::Gl, 3, 0) ||
                                            ctxt.version >= &Version(Api::GlEs, 3, 0) ||
                                            ctxt.extensions.gl_apple_framebuffer_multisample ||
                                            ctxt.extensions.gl_angle_framebuffer_multisample ||
                                            ctxt.extensions.gl_ext_multisampled_render_to_texture ||
                                            ctxt.extensions.gl_nv_framebuffer_multisample)
            {
                ctxt.gl.GenRenderbuffers(1, &mut id);
                ctxt.gl.BindRenderbuffer(gl::RENDERBUFFER, id);
                ctxt.state.renderbuffer = id;

                let samples = samples.unwrap();

                if ctxt.version >= &Version(Api::Gl, 3, 0) ||
                   ctxt.version >= &Version(Api::GlEs, 3, 0)
                {
                    ctxt.gl.RenderbufferStorageMultisample(gl::RENDERBUFFER,
                                                           samples as gl::types::GLsizei,
                                                           format,
                                                           width as gl::types::GLsizei,
                                                           height as gl::types::GLsizei);

                } else if ctxt.extensions.gl_apple_framebuffer_multisample {
                    ctxt.gl.RenderbufferStorageMultisampleAPPLE(gl::RENDERBUFFER,
                                                                samples as gl::types::GLsizei,
                                                                format,
                                                                width as gl::types::GLsizei,
                                                                height as gl::types::GLsizei);

                } else if ctxt.extensions.gl_angle_framebuffer_multisample {
                    ctxt.gl.RenderbufferStorageMultisampleANGLE(gl::RENDERBUFFER,
                                                                samples as gl::types::GLsizei,
                                                                format,
                                                                width as gl::types::GLsizei,
                                                                height as gl::types::GLsizei);

                } else if ctxt.extensions.gl_ext_multisampled_render_to_texture {
                    ctxt.gl.RenderbufferStorageMultisampleEXT(gl::RENDERBUFFER,
                                                              samples as gl::types::GLsizei,
                                                              format,
                                                              width as gl::types::GLsizei,
                                                              height as gl::types::GLsizei);

                } else if ctxt.extensions.gl_nv_framebuffer_multisample {
                    ctxt.gl.RenderbufferStorageMultisampleNV(gl::RENDERBUFFER,
                                                             samples as gl::types::GLsizei,
                                                             format,
                                                             width as gl::types::GLsizei,
                                                             height as gl::types::GLsizei);

                } else {
                    unreachable!();
                }

            } else if samples.is_none() && (ctxt.version >= &Version(Api::Gl, 3, 0) ||
                                            ctxt.version >= &Version(Api::GlEs, 2, 0))
            {
                ctxt.gl.GenRenderbuffers(1, &mut id);
                ctxt.gl.BindRenderbuffer(gl::RENDERBUFFER, id);
                ctxt.state.renderbuffer = id;
                ctxt.gl.RenderbufferStorage(gl::RENDERBUFFER, format,
                                            width as gl::types::GLsizei,
                                            height as gl::types::GLsizei);

            } else if samples.is_some() && ctxt.extensions.gl_ext_framebuffer_object &&
                      ctxt.extensions.gl_ext_framebuffer_multisample
            {
                ctxt.gl.GenRenderbuffersEXT(1, &mut id);
                ctxt.gl.BindRenderbufferEXT(gl::RENDERBUFFER_EXT, id);
                ctxt.state.renderbuffer = id;

                let samples = samples.unwrap();
                ctxt.gl.RenderbufferStorageMultisampleEXT(gl::RENDERBUFFER_EXT,
                                                          samples as gl::types::GLsizei,
                                                          format,
                                                          width as gl::types::GLsizei,
                                                          height as gl::types::GLsizei);

            } else if samples.is_none() && ctxt.extensions.gl_ext_framebuffer_object {
                ctxt.gl.GenRenderbuffersEXT(1, &mut id);
                ctxt.gl.BindRenderbufferEXT(gl::RENDERBUFFER_EXT, id);
                ctxt.state.renderbuffer = id;
                ctxt.gl.RenderbufferStorageEXT(gl::RENDERBUFFER_EXT, format,
                                               width as gl::types::GLsizei,
                                               height as gl::types::GLsizei);

            } else {
                unreachable!();
            }

            RenderBufferAny {
                context: facade.get_context().clone(),
                id: id,
                width: width,
                height: height,
                samples: samples,
                kind: kind,
            }
        }
    }

    /// Returns the dimensions of the render buffer.
    #[inline]
    pub fn get_dimensions(&self) -> (u32, u32) {
        (self.width, self.height)
    }

    /// Returns the number of samples of the render buffer, or `None` if multisampling isn't
    /// enabled.
    #[inline]
    pub fn get_samples(&self) -> Option<u32> {
        self.samples
    }

    /// Returns the context used to create this renderbuffer.
    #[inline]
    pub fn get_context(&self) -> &Rc<Context> {
        &self.context
    }

    /// Returns the kind of renderbuffer.
    #[inline]
    pub fn kind(&self) -> TextureKind {
        self.kind
    }
}

impl Drop for RenderBufferAny {
    fn drop(&mut self) {
        unsafe {
            let mut ctxt = self.context.make_current();

            // removing FBOs which contain this buffer
            FramebuffersContainer::purge_renderbuffer(&mut ctxt, self.id);

            if ctxt.version >= &Version(Api::Gl, 3, 0) ||
               ctxt.version >= &Version(Api::GlEs, 2, 0)
            {
                if ctxt.state.renderbuffer == self.id {
                    ctxt.state.renderbuffer = 0;
                }

                ctxt.gl.DeleteRenderbuffers(1, [ self.id ].as_ptr());

            } else if ctxt.extensions.gl_ext_framebuffer_object {
                if ctxt.state.renderbuffer == self.id {
                    ctxt.state.renderbuffer = 0;
                }

                ctxt.gl.DeleteRenderbuffersEXT(1, [ self.id ].as_ptr());

            } else {
                unreachable!();
            }
        }
    }
}

impl GlObject for RenderBufferAny {
    type Id = gl::types::GLuint;

    #[inline]
    fn get_id(&self) -> gl::types::GLuint {
        self.id
    }
}
<commit_msg>fixed error handling in src/framebuffer/render_buffer.rs<commit_after>/*!

A render buffer is similar to a texture, but is optimized for usage as a draw target.

Contrary to a texture, you can't sample nor modify the content of a render buffer.
You should prefer render buffers over textures when you know that you don't need to read or modify
the data of the render buffer.

*/
use std::rc::Rc;
use std::ops::{Deref, DerefMut};
use std::{ mem, fmt };
use std::error::Error;

use framebuffer::{ColorAttachment, ToColorAttachment};
use framebuffer::{DepthAttachment, ToDepthAttachment};
use framebuffer::{StencilAttachment, ToStencilAttachment};
use framebuffer::{DepthStencilAttachment, ToDepthStencilAttachment};
use texture::{UncompressedFloatFormat, DepthFormat, StencilFormat, DepthStencilFormat, TextureKind};

use image_format;

use gl;
use GlObject;
use fbo::FramebuffersContainer;
use backend::Facade;
use context::Context;
use ContextExt;
use version::Version;
use version::Api;

/// Error while creating a render buffer.
#[derive(Copy, Clone, Debug)]
pub enum CreationError {
    /// The requested format is not supported.
    FormatNotSupported,
}

impl fmt::Display for CreationError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}", self.description())
    }
}

impl Error for CreationError {
    fn description(&self) -> &str {
        use self::CreationError::*;
        match *self {
            FormatNotSupported => "The requested format is not supported",
        }
    }
}

impl From<image_format::FormatNotSupportedError> for CreationError {
    fn from(_: image_format::FormatNotSupportedError) -> CreationError {
        CreationError::FormatNotSupported
    }
}

/// A render buffer is similar to a texture, but is optimized for usage as a draw target.
///
/// Contrary to a texture, you can't sample or modify the content of the `RenderBuffer`.
pub struct RenderBuffer {
    buffer: RenderBufferAny,
}

impl RenderBuffer {
    /// Builds a new render buffer.
    pub fn new<F>(facade: &F, format: UncompressedFloatFormat, width: u32, height: u32)
                  -> Result<RenderBuffer, CreationError> where F: Facade
    {
        let format = image_format::TextureFormatRequest::Specific(image_format::TextureFormat::UncompressedFloat(format));
        let format = try!(image_format::format_request_to_glenum(&facade.get_context(), format, image_format::RequestType::Renderbuffer));

        Ok(RenderBuffer {
            buffer: RenderBufferAny::new(facade, format, TextureKind::Float, width, height, None)
        })
    }
}

impl<'a> ToColorAttachment<'a> for &'a RenderBuffer {
    #[inline]
    fn to_color_attachment(self) -> ColorAttachment<'a> {
        ColorAttachment::RenderBuffer(self)
    }
}

impl Deref for RenderBuffer {
    type Target = RenderBufferAny;

    #[inline]
    fn deref(&self) -> &RenderBufferAny {
        &self.buffer
    }
}

impl DerefMut for RenderBuffer {
    #[inline]
    fn deref_mut(&mut self) -> &mut RenderBufferAny {
        &mut self.buffer
    }
}

impl GlObject for RenderBuffer {
    type Id = gl::types::GLuint;

    #[inline]
    fn get_id(&self) -> gl::types::GLuint {
        self.buffer.get_id()
    }
}

/// A render buffer is similar to a texture, but is optimized for usage as a draw target.
///
/// Contrary to a texture, you can't sample or modify the content of the `DepthRenderBuffer` directly.
pub struct DepthRenderBuffer {
    buffer: RenderBufferAny,
}

impl DepthRenderBuffer {
    /// Builds a new render buffer.
    pub fn new<F>(facade: &F, format: DepthFormat, width: u32, height: u32)
                  -> Result<DepthRenderBuffer, CreationError> where F: Facade
    {
        let format = image_format::TextureFormatRequest::Specific(image_format::TextureFormat::DepthFormat(format));
        let format = try!(image_format::format_request_to_glenum(&facade.get_context(), format, image_format::RequestType::Renderbuffer));

        Ok(DepthRenderBuffer {
            buffer: RenderBufferAny::new(facade, format, TextureKind::Depth, width, height, None)
        })
    }
}

impl<'a> ToDepthAttachment<'a> for &'a DepthRenderBuffer {
    fn to_depth_attachment(self) -> DepthAttachment<'a> {
        DepthAttachment::RenderBuffer(self)
    }
}

impl Deref for DepthRenderBuffer {
    type Target = RenderBufferAny;

    #[inline]
    fn deref(&self) -> &RenderBufferAny {
        &self.buffer
    }
}

impl DerefMut for DepthRenderBuffer {
    #[inline]
    fn deref_mut(&mut self) -> &mut RenderBufferAny {
        &mut self.buffer
    }
}

impl GlObject for DepthRenderBuffer {
    type Id = gl::types::GLuint;

    #[inline]
    fn get_id(&self) -> gl::types::GLuint {
        self.buffer.get_id()
    }
}

/// A render buffer is similar to a texture, but is optimized for usage as a draw target.
///
/// Contrary to a texture, you can't sample or modify the content of the `StencilRenderBuffer` directly.
pub struct StencilRenderBuffer {
    buffer: RenderBufferAny,
}

impl StencilRenderBuffer {
    /// Builds a new render buffer.
    pub fn new<F>(facade: &F, format: StencilFormat, width: u32, height: u32)
                  -> Result<StencilRenderBuffer, CreationError> where F: Facade
    {
        let format = image_format::TextureFormatRequest::Specific(image_format::TextureFormat::StencilFormat(format));
        let format = try!(image_format::format_request_to_glenum(&facade.get_context(), format, image_format::RequestType::Renderbuffer));

        Ok(StencilRenderBuffer {
            buffer: RenderBufferAny::new(facade, format, TextureKind::Stencil, width, height, None)
        })
    }
}

impl<'a> ToStencilAttachment<'a> for &'a StencilRenderBuffer {
    #[inline]
    fn to_stencil_attachment(self) -> StencilAttachment<'a> {
        StencilAttachment::RenderBuffer(self)
    }
}

impl Deref for StencilRenderBuffer {
    type Target = RenderBufferAny;

    #[inline]
    fn deref(&self) -> &RenderBufferAny {
        &self.buffer
    }
}

impl DerefMut for StencilRenderBuffer {
    #[inline]
    fn deref_mut(&mut self) -> &mut RenderBufferAny {
        &mut self.buffer
    }
}

impl GlObject for StencilRenderBuffer {
    type Id = gl::types::GLuint;

    #[inline]
    fn get_id(&self) -> gl::types::GLuint {
        self.buffer.get_id()
    }
}

/// A render buffer is similar to a texture, but is optimized for usage as a draw target.
///
/// Contrary to a texture, you can't sample or modify the content of the `DepthStencilRenderBuffer` directly.
pub struct DepthStencilRenderBuffer {
    buffer: RenderBufferAny,
}

impl DepthStencilRenderBuffer {
    /// Builds a new render buffer.
    pub fn new<F>(facade: &F, format: DepthStencilFormat, width: u32, height: u32)
                  -> Result<DepthStencilRenderBuffer, CreationError> where F: Facade
    {
        let format = image_format::TextureFormatRequest::Specific(image_format::TextureFormat::DepthStencilFormat(format));
        let format = try!(image_format::format_request_to_glenum(&facade.get_context(), format, image_format::RequestType::Renderbuffer));

        Ok(DepthStencilRenderBuffer {
            buffer: RenderBufferAny::new(facade, format, TextureKind::DepthStencil, width, height, None)
        })
    }
}

impl<'a> ToDepthStencilAttachment<'a> for &'a DepthStencilRenderBuffer {
    #[inline]
    fn to_depth_stencil_attachment(self) -> DepthStencilAttachment<'a> {
        DepthStencilAttachment::RenderBuffer(self)
    }
}

impl Deref for DepthStencilRenderBuffer {
    type Target = RenderBufferAny;

    #[inline]
    fn deref(&self) -> &RenderBufferAny {
        &self.buffer
    }
}

impl DerefMut for DepthStencilRenderBuffer {
    #[inline]
    fn deref_mut(&mut self) -> &mut RenderBufferAny {
        &mut self.buffer
    }
}

impl GlObject for DepthStencilRenderBuffer {
    type Id = gl::types::GLuint;

    #[inline]
    fn get_id(&self) -> gl::types::GLuint {
        self.buffer.get_id()
    }
}

/// A RenderBuffer of indeterminate type.
pub struct RenderBufferAny {
    context: Rc<Context>,
    id: gl::types::GLuint,
    width: u32,
    height: u32,
    samples: Option<u32>,
    kind: TextureKind,
}

impl RenderBufferAny {
    /// Builds a new render buffer.
    fn new<F>(facade: &F, format: gl::types::GLenum, kind: TextureKind, width: u32, height: u32,
              samples: Option<u32>) -> RenderBufferAny
        where F: Facade
    {
        unsafe {
            // TODO: check that dimensions don't exceed GL_MAX_RENDERBUFFER_SIZE
            // FIXME: gles2 only supports very few formats
            let mut ctxt = facade.get_context().make_current();
            let mut id = mem::uninitialized();

            if ctxt.version >= &Version(Api::Gl, 4, 5) ||
               ctxt.extensions.gl_arb_direct_state_access
            {
                ctxt.gl.CreateRenderbuffers(1, &mut id);
                if let Some(samples) = samples {
                    ctxt.gl.NamedRenderbufferStorageMultisample(id, samples as gl::types::GLsizei,
                                                                format, width as gl::types::GLsizei,
                                                                height as gl::types::GLsizei);
                } else {
                    ctxt.gl.NamedRenderbufferStorage(id, format, width as gl::types::GLsizei,
                                                     height as gl::types::GLsizei);
                }

            } else if samples.is_some() && (ctxt.version >= &Version(Api::Gl, 3, 0) ||
                                            ctxt.version >= &Version(Api::GlEs, 3, 0) ||
                                            ctxt.extensions.gl_apple_framebuffer_multisample ||
                                            ctxt.extensions.gl_angle_framebuffer_multisample ||
                                            ctxt.extensions.gl_ext_multisampled_render_to_texture ||
                                            ctxt.extensions.gl_nv_framebuffer_multisample)
            {
                ctxt.gl.GenRenderbuffers(1, &mut id);
                ctxt.gl.BindRenderbuffer(gl::RENDERBUFFER, id);
                ctxt.state.renderbuffer = id;

                let samples = samples.unwrap();

                if ctxt.version >= &Version(Api::Gl, 3, 0) ||
                   ctxt.version >= &Version(Api::GlEs, 3, 0)
                {
                    ctxt.gl.RenderbufferStorageMultisample(gl::RENDERBUFFER,
                                                           samples as gl::types::GLsizei,
                                                           format,
                                                           width as gl::types::GLsizei,
                                                           height as gl::types::GLsizei);

                } else if ctxt.extensions.gl_apple_framebuffer_multisample {
                    ctxt.gl.RenderbufferStorageMultisampleAPPLE(gl::RENDERBUFFER,
                                                                samples as gl::types::GLsizei,
                                                                format,
                                                                width as gl::types::GLsizei,
                                                                height as gl::types::GLsizei);

                } else if ctxt.extensions.gl_angle_framebuffer_multisample {
                    ctxt.gl.RenderbufferStorageMultisampleANGLE(gl::RENDERBUFFER,
                                                                samples as gl::types::GLsizei,
                                                                format,
                                                                width as gl::types::GLsizei,
                                                                height as gl::types::GLsizei);

                } else if ctxt.extensions.gl_ext_multisampled_render_to_texture {
                    ctxt.gl.RenderbufferStorageMultisampleEXT(gl::RENDERBUFFER,
                                                              samples as gl::types::GLsizei,
                                                              format,
                                                              width as gl::types::GLsizei,
                                                              height as gl::types::GLsizei);

                } else if ctxt.extensions.gl_nv_framebuffer_multisample {
                    ctxt.gl.RenderbufferStorageMultisampleNV(gl::RENDERBUFFER,
                                                             samples as gl::types::GLsizei,
                                                             format,
                                                             width as gl::types::GLsizei,
                                                             height as gl::types::GLsizei);

                } else {
                    unreachable!();
                }

            } else if samples.is_none() && (ctxt.version >= &Version(Api::Gl, 3, 0) ||
                                            ctxt.version >= &Version(Api::GlEs, 2, 0))
            {
                ctxt.gl.GenRenderbuffers(1, &mut id);
                ctxt.gl.BindRenderbuffer(gl::RENDERBUFFER, id);
                ctxt.state.renderbuffer = id;
                ctxt.gl.RenderbufferStorage(gl::RENDERBUFFER, format,
                                            width as gl::types::GLsizei,
                                            height as gl::types::GLsizei);

            } else if samples.is_some() && ctxt.extensions.gl_ext_framebuffer_object &&
                      ctxt.extensions.gl_ext_framebuffer_multisample
            {
                ctxt.gl.GenRenderbuffersEXT(1, &mut id);
                ctxt.gl.BindRenderbufferEXT(gl::RENDERBUFFER_EXT, id);
                ctxt.state.renderbuffer = id;

                let samples = samples.unwrap();
                ctxt.gl.RenderbufferStorageMultisampleEXT(gl::RENDERBUFFER_EXT,
                                                          samples as gl::types::GLsizei,
                                                          format,
                                                          width as gl::types::GLsizei,
                                                          height as gl::types::GLsizei);

            } else if samples.is_none() && ctxt.extensions.gl_ext_framebuffer_object {
                ctxt.gl.GenRenderbuffersEXT(1, &mut id);
                ctxt.gl.BindRenderbufferEXT(gl::RENDERBUFFER_EXT, id);
                ctxt.state.renderbuffer = id;
                ctxt.gl.RenderbufferStorageEXT(gl::RENDERBUFFER_EXT, format,
                                               width as gl::types::GLsizei,
                                               height as gl::types::GLsizei);

            } else {
                unreachable!();
            }

            RenderBufferAny {
                context: facade.get_context().clone(),
                id: id,
                width: width,
                height: height,
                samples: samples,
                kind: kind,
            }
        }
    }

    /// Returns the dimensions of the render buffer.
    #[inline]
    pub fn get_dimensions(&self) -> (u32, u32) {
        (self.width, self.height)
    }

    /// Returns the number of samples of the render buffer, or `None` if multisampling isn't
    /// enabled.
    #[inline]
    pub fn get_samples(&self) -> Option<u32> {
        self.samples
    }

    /// Returns the context used to create this renderbuffer.
    #[inline]
    pub fn get_context(&self) -> &Rc<Context> {
        &self.context
    }

    /// Returns the kind of renderbuffer.
    #[inline]
    pub fn kind(&self) -> TextureKind {
        self.kind
    }
}

impl Drop for RenderBufferAny {
    fn drop(&mut self) {
        unsafe {
            let mut ctxt = self.context.make_current();

            // removing FBOs which contain this buffer
            FramebuffersContainer::purge_renderbuffer(&mut ctxt, self.id);

            if ctxt.version >= &Version(Api::Gl, 3, 0) ||
               ctxt.version >= &Version(Api::GlEs, 2, 0)
            {
                if ctxt.state.renderbuffer == self.id {
                    ctxt.state.renderbuffer = 0;
                }

                ctxt.gl.DeleteRenderbuffers(1, [ self.id ].as_ptr());

            } else if ctxt.extensions.gl_ext_framebuffer_object {
                if ctxt.state.renderbuffer == self.id {
                    ctxt.state.renderbuffer = 0;
                }

                ctxt.gl.DeleteRenderbuffersEXT(1, [ self.id ].as_ptr());

            } else {
                unreachable!();
            }
        }
    }
}

impl GlObject for RenderBufferAny {
    type Id = gl::types::GLuint;

    #[inline]
    fn get_id(&self) -> gl::types::GLuint {
        self.id
    }
}
<|endoftext|>


<commit_before><commit_msg>Store location info in `LocatedTT`.<commit_after><|endoftext|>


<commit_before><commit_msg>Rollup merge of #36086 - apasel422:issue-35423, r=alexcrichton<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

fn main () {
    let x = 4;
    match x {
        ref r if *r < 0 => println!("got negative num {} < 0", r),
        e @ 1 ... 100 => println!("got number within range [1,100] {}", e),
        _ => println!("no"),
    }
}
<|endoftext|>


<commit_before>use codecleaner::{code_chunks, CodeIndicesIter};

pub struct StmtIndicesIter<'a> {
    src: &'a str,
    it: CodeIndicesIter<'a>,
    pos: usize,
    end: usize
}

impl<'a> Iterator for StmtIndicesIter<'a> {
    type Item = (usize, usize);

    #[inline]
    fn next(&mut self) -> Option<(usize, usize)> {
        let src_bytes = self.src.as_bytes();
        let mut enddelim = b';';
        let mut bracelevel = 0u16;
        let mut parenlevel = 0i32;
        let mut start = self.pos;

        // loop on all code_chunks until we find a relevant open/close pattern
        loop {
            // do we need the next chunk?
            if self.end == self.pos {
                // get the next chunk of code
                match self.it.next() {
                    Some((ch_start, ch_end)) => {
                        self.end = ch_end;
                        if start == self.pos { start = ch_start; }
                        self.pos = ch_start;
                    }
                    None => {
                        // no more chunks. finished
                        return if start < self.end { Some((start, self.end)) }
                               else { None }
                    }
                }
            }

            if start == self.pos {
                // if this is a new stmt block, skip the whitespace
                for &b in &src_bytes[self.pos..self.end] {
                    match b {
                        b' ' | b'\r' | b'\n' | b'\t' => { self.pos += 1; },
                        _ => { break; }
                    }
                }
                start = self.pos;

                // test attribute   #[foo = bar]
                if self.pos<self.end && src_bytes[self.pos] == b'#' {
                    enddelim = b']'
                };
            }

            // iterate through the chunk, looking for stmt end
            for &b in &src_bytes[self.pos..self.end] {
                self.pos += 1;

                match b {
                    b'(' => { parenlevel += 1; },
                    b')' => { parenlevel -= 1; },
                    b'{' => {
                        // if we are top level and stmt is not a 'use' then
                        // closebrace finishes the stmt
                        if bracelevel == 0 && parenlevel == 0
                            && !(is_a_use_stmt(self.src, start, self.pos)) {
                            enddelim = b'}';
                        }
                        bracelevel += 1;
                    },
                    b'}' => {
                        // have we reached the end of the scope?
                        if bracelevel == 0 { return None; }
                        bracelevel -= 1;
                    },
                    b'!' => {
                        // macro if followed by at least one space or (
                        // FIXME: test with boolean 'not' expression
                        if parenlevel == 0 && bracelevel == 0
                            && self.pos < self.end && (self.pos-start) > 1 {
                            match src_bytes[self.pos] {
                                b' ' | b'\r' | b'\n' | b'\t' | b'('  => {
                                    enddelim = b')';
                                },
                                _ => {}
                            }
                        }
                    }
                    _ => {}
                }

                if enddelim == b && bracelevel == 0 && parenlevel == 0 {
                    return Some((start, self.pos));
                }
            }
        }
    }
}

fn is_a_use_stmt(src: &str, start: usize, pos: usize) -> bool {
    let src_bytes = src.as_bytes();
    let whitespace = " {\t\r\n".as_bytes();
    (pos > 3 && &src_bytes[start..start+3] == b"use" &&
     whitespace.contains(&src_bytes[start+3])) ||
    (pos > 7 && &src_bytes[start..(start+7)] == b"pub use" &&
     whitespace.contains(&src_bytes[start+7]))
}

pub fn iter_stmts(src: &str) -> StmtIndicesIter {
    StmtIndicesIter{ src: src, it: code_chunks(src), pos: 0, end: 0 }
}

#[cfg(test)]
mod test {

    use testutils::{rejustify, slice};
    use super::*;

    #[test]
    fn iterates_single_use_stmts() {
        let src = &rejustify("
            use std::Foo; // a comment
            use std::Bar;
        ");

        let mut it = iter_stmts(src);
        assert_eq!("use std::Foo;", slice(src, it.next().unwrap()));
        assert_eq!("use std::Bar;", slice(src, it.next().unwrap()));
    }

    #[test]
    fn iterates_use_stmt_over_two_lines() {
        let src = &rejustify("
        use std::{Foo,
                  Bar}; // a comment
        ");
        let mut it = iter_stmts(src);
        assert_eq!("use std::{Foo,
              Bar};",slice(src, it.next().unwrap()));
    }

    #[test]
    fn iterates_use_stmt_without_the_prefix() {
        let src = &rejustify("
        pub use {Foo,
                 Bar}; // this is also legit apparently
        ");
        let mut it = iter_stmts(src);
        assert_eq!("pub use {Foo,
             Bar};", slice(src, it.next().unwrap())
        );
    }

    #[test]
    fn iterates_while_stmt() {
        let src = &rejustify("
            while self.pos < 3 { }
        ");
        let mut it = iter_stmts(src);
        assert_eq!("while self.pos < 3 { }", slice(src, it.next().unwrap()));
    }

    #[test]
    fn iterates_lambda_arg() {
        let src = &rejustify("
            myfn(|n|{});
        ");
        let mut it = iter_stmts(src);
        assert_eq!("myfn(|n|{});", slice(src, it.next().unwrap()));
    }

    #[test]
    fn iterates_macro() {
        let src = "
        mod foo;
        macro_rules! otry(
            ($e:expr) => (match $e { Some(e) => e, None => return })
        )
        mod bar;
        ";
        let mut it = iter_stmts(src);
        assert_eq!("mod foo;", slice(src, it.next().unwrap()));
        assert_eq!("macro_rules! otry(
            ($e:expr) => (match $e { Some(e) => e, None => return })
        )", slice(src, it.next().unwrap()));
        assert_eq!("mod bar;", slice(src, it.next().unwrap()));
    }

    #[test]
    fn iterates_macro_invocation() {
        let src = "
            mod foo;
            local_data_key!(local_stdout: Box<Writer + Send>)  // no ';'
            mod bar;
        ";
        let mut it = iter_stmts(src);
        assert_eq!("mod foo;", slice(src, it.next().unwrap()));
        assert_eq!("local_data_key!(local_stdout: Box<Writer + Send>)", slice(src, it.next().unwrap()));
        assert_eq!("mod bar;", slice(src, it.next().unwrap()));
    }

    #[test]
    fn iterates_if_else_stmt() {
        let src = "
            if self.pos < 3 { } else { }
        ";
        let mut it = iter_stmts(src);
        assert_eq!("if self.pos < 3 { }", slice(src, it.next().unwrap()));
        assert_eq!("else { }", slice(src, it.next().unwrap()));
    }

    #[test]
    fn iterates_inner_scope() {
        let src = "
        while self.pos < 3 {
            let a = 35;
            return a + 35;  // should iterate this
        }
        {
            b = foo;       // but not this
        }
        ";

        let scope = &src[29..];
        let mut it = iter_stmts(scope);

        assert_eq!("let a = 35;", slice(scope, it.next().unwrap()));
        assert_eq!("return a + 35;", slice(scope, it.next().unwrap()));
        assert_eq!(None, it.next());
    }

    #[test]
    fn iterates_module_attribute() {
        let src = &rejustify("
            #![license = \"BSD\"]
            #[test]
        ");
        let mut it = iter_stmts(src);
        assert_eq!("#![license = \"BSD\"]", slice(src, it.next().unwrap()));
        assert_eq!("#[test]", slice(src, it.next().unwrap()));
    }

    #[test]
    fn iterates_half_open_subscope_if_is_the_last_thing() {
        let src = "
            let something = 35;
            while self.pos < 3 {
            let a = 35;
            return a + 35;  // should iterate this
        ";

        let scope = src;
        let mut it = iter_stmts(scope);
        assert_eq!("let something = 35;", slice(scope, it.next().unwrap()));
        assert_eq!("while self.pos < 3 {
            let a = 35;
            return a + 35;  // should iterate this
        ", slice(scope, it.next().unwrap()));
    }

}
<commit_msg>codeiter: simplify is_a_use_stmt a little<commit_after>use codecleaner::{code_chunks, CodeIndicesIter};

pub struct StmtIndicesIter<'a> {
    src: &'a str,
    it: CodeIndicesIter<'a>,
    pos: usize,
    end: usize
}

impl<'a> Iterator for StmtIndicesIter<'a> {
    type Item = (usize, usize);

    #[inline]
    fn next(&mut self) -> Option<(usize, usize)> {
        let src_bytes = self.src.as_bytes();
        let mut enddelim = b';';
        let mut bracelevel = 0u16;
        let mut parenlevel = 0i32;
        let mut start = self.pos;

        // loop on all code_chunks until we find a relevant open/close pattern
        loop {
            // do we need the next chunk?
            if self.end == self.pos {
                // get the next chunk of code
                match self.it.next() {
                    Some((ch_start, ch_end)) => {
                        self.end = ch_end;
                        if start == self.pos { start = ch_start; }
                        self.pos = ch_start;
                    }
                    None => {
                        // no more chunks. finished
                        return if start < self.end { Some((start, self.end)) }
                               else { None }
                    }
                }
            }

            if start == self.pos {
                // if this is a new stmt block, skip the whitespace
                for &b in &src_bytes[self.pos..self.end] {
                    match b {
                        b' ' | b'\r' | b'\n' | b'\t' => { self.pos += 1; },
                        _ => { break; }
                    }
                }
                start = self.pos;

                // test attribute   #[foo = bar]
                if self.pos<self.end && src_bytes[self.pos] == b'#' {
                    enddelim = b']'
                };
            }

            // iterate through the chunk, looking for stmt end
            for &b in &src_bytes[self.pos..self.end] {
                self.pos += 1;

                match b {
                    b'(' => { parenlevel += 1; },
                    b')' => { parenlevel -= 1; },
                    b'{' => {
                        // if we are top level and stmt is not a 'use' then
                        // closebrace finishes the stmt
                        if bracelevel == 0 && parenlevel == 0
                            && !is_a_use_stmt(src_bytes, start, self.pos) {
                            enddelim = b'}';
                        }
                        bracelevel += 1;
                    },
                    b'}' => {
                        // have we reached the end of the scope?
                        if bracelevel == 0 { return None; }
                        bracelevel -= 1;
                    },
                    b'!' => {
                        // macro if followed by at least one space or (
                        // FIXME: test with boolean 'not' expression
                        if parenlevel == 0 && bracelevel == 0
                            && self.pos < self.end && (self.pos-start) > 1 {
                            match src_bytes[self.pos] {
                                b' ' | b'\r' | b'\n' | b'\t' | b'('  => {
                                    enddelim = b')';
                                },
                                _ => {}
                            }
                        }
                    }
                    _ => {}
                }

                if enddelim == b && bracelevel == 0 && parenlevel == 0 {
                    return Some((start, self.pos));
                }
            }
        }
    }
}

fn is_a_use_stmt(src_bytes: &[u8], start: usize, pos: usize) -> bool {
    let whitespace = b" {\t\r\n";
    (pos > 3 && &src_bytes[start..start+3] == b"use" &&
     whitespace.contains(&src_bytes[start+3])) ||
    (pos > 7 && &src_bytes[start..(start+7)] == b"pub use" &&
     whitespace.contains(&src_bytes[start+7]))
}

pub fn iter_stmts(src: &str) -> StmtIndicesIter {
    StmtIndicesIter{ src: src, it: code_chunks(src), pos: 0, end: 0 }
}

#[cfg(test)]
mod test {

    use testutils::{rejustify, slice};
    use super::*;

    #[test]
    fn iterates_single_use_stmts() {
        let src = &rejustify("
            use std::Foo; // a comment
            use std::Bar;
        ");

        let mut it = iter_stmts(src);
        assert_eq!("use std::Foo;", slice(src, it.next().unwrap()));
        assert_eq!("use std::Bar;", slice(src, it.next().unwrap()));
    }

    #[test]
    fn iterates_use_stmt_over_two_lines() {
        let src = &rejustify("
        use std::{Foo,
                  Bar}; // a comment
        ");
        let mut it = iter_stmts(src);
        assert_eq!("use std::{Foo,
              Bar};",slice(src, it.next().unwrap()));
    }

    #[test]
    fn iterates_use_stmt_without_the_prefix() {
        let src = &rejustify("
        pub use {Foo,
                 Bar}; // this is also legit apparently
        ");
        let mut it = iter_stmts(src);
        assert_eq!("pub use {Foo,
             Bar};", slice(src, it.next().unwrap())
        );
    }

    #[test]
    fn iterates_while_stmt() {
        let src = &rejustify("
            while self.pos < 3 { }
        ");
        let mut it = iter_stmts(src);
        assert_eq!("while self.pos < 3 { }", slice(src, it.next().unwrap()));
    }

    #[test]
    fn iterates_lambda_arg() {
        let src = &rejustify("
            myfn(|n|{});
        ");
        let mut it = iter_stmts(src);
        assert_eq!("myfn(|n|{});", slice(src, it.next().unwrap()));
    }

    #[test]
    fn iterates_macro() {
        let src = "
        mod foo;
        macro_rules! otry(
            ($e:expr) => (match $e { Some(e) => e, None => return })
        )
        mod bar;
        ";
        let mut it = iter_stmts(src);
        assert_eq!("mod foo;", slice(src, it.next().unwrap()));
        assert_eq!("macro_rules! otry(
            ($e:expr) => (match $e { Some(e) => e, None => return })
        )", slice(src, it.next().unwrap()));
        assert_eq!("mod bar;", slice(src, it.next().unwrap()));
    }

    #[test]
    fn iterates_macro_invocation() {
        let src = "
            mod foo;
            local_data_key!(local_stdout: Box<Writer + Send>)  // no ';'
            mod bar;
        ";
        let mut it = iter_stmts(src);
        assert_eq!("mod foo;", slice(src, it.next().unwrap()));
        assert_eq!("local_data_key!(local_stdout: Box<Writer + Send>)", slice(src, it.next().unwrap()));
        assert_eq!("mod bar;", slice(src, it.next().unwrap()));
    }

    #[test]
    fn iterates_if_else_stmt() {
        let src = "
            if self.pos < 3 { } else { }
        ";
        let mut it = iter_stmts(src);
        assert_eq!("if self.pos < 3 { }", slice(src, it.next().unwrap()));
        assert_eq!("else { }", slice(src, it.next().unwrap()));
    }

    #[test]
    fn iterates_inner_scope() {
        let src = "
        while self.pos < 3 {
            let a = 35;
            return a + 35;  // should iterate this
        }
        {
            b = foo;       // but not this
        }
        ";

        let scope = &src[29..];
        let mut it = iter_stmts(scope);

        assert_eq!("let a = 35;", slice(scope, it.next().unwrap()));
        assert_eq!("return a + 35;", slice(scope, it.next().unwrap()));
        assert_eq!(None, it.next());
    }

    #[test]
    fn iterates_module_attribute() {
        let src = &rejustify("
            #![license = \"BSD\"]
            #[test]
        ");
        let mut it = iter_stmts(src);
        assert_eq!("#![license = \"BSD\"]", slice(src, it.next().unwrap()));
        assert_eq!("#[test]", slice(src, it.next().unwrap()));
    }

    #[test]
    fn iterates_half_open_subscope_if_is_the_last_thing() {
        let src = "
            let something = 35;
            while self.pos < 3 {
            let a = 35;
            return a + 35;  // should iterate this
        ";

        let scope = src;
        let mut it = iter_stmts(scope);
        assert_eq!("let something = 35;", slice(scope, it.next().unwrap()));
        assert_eq!("while self.pos < 3 {
            let a = 35;
            return a + 35;  // should iterate this
        ", slice(scope, it.next().unwrap()));
    }

}
<|endoftext|>


<commit_before>use std::{run};
use std::io::fs::rmdir;

static exe: &'static str = "build/mkdir";
static test_dir1: &'static str = "mkdir_test1";
static test_dir2: &'static str = "mkdir_test2";
static test_dir3: &'static str = "mkdir_test3";
static test_dir4: &'static str = "mkdir_test4/mkdir_test4_1";
static test_dir5: &'static str = "mkdir_test5/mkdir_test5_1";

fn cleanup(dir: &'static str) {
    let d = dir.into_owned();
    let p = Path::new(d.into_owned());
    if p.exists() {
        rmdir(&p);
    }
}

#[test]
fn test_mkdir_mkdir() {
    cleanup(test_dir1);
    let prog = run::process_status(exe.into_owned(), [test_dir1.into_owned()]);
    let exit_success = prog.unwrap().success();
    cleanup(test_dir1);
    assert_eq!(exit_success, true);
}

#[test]
fn test_mkdir_dup_dir() {
    cleanup(test_dir2);
    let prog = run::process_status(exe.into_owned(), [test_dir2.into_owned()]);
    let exit_success = prog.unwrap().success();
    if !exit_success {
        cleanup(test_dir2);
        fail!();
    }
    let prog2 = run::process_status(exe.into_owned(), [test_dir2.into_owned()]);
    let exit_success2 = prog2.unwrap().success();
    cleanup(test_dir2);
    assert_eq!(exit_success2, false);
}

#[test]
fn test_mkdir_mode() {
    cleanup(test_dir3);
    let prog = run::process_status(exe.into_owned(), [~"-m", ~"755", test_dir3.into_owned()]);
    let exit_success = prog.unwrap().success();
    cleanup(test_dir3);
    assert_eq!(exit_success, true);
}

#[test]
fn test_mkdir_parent() {
    cleanup(test_dir4);
    let prog = run::process_status(exe.into_owned(), [~"-p", test_dir4.into_owned()]);
    let exit_success = prog.unwrap().success();
    cleanup(test_dir4);
    assert_eq!(exit_success, true);
}

#[test]
fn test_mkdir_no_parent() {
    cleanup(test_dir5);
    let prog = run::process_status(exe.into_owned(), [test_dir5.into_owned()]);
    let exit_success = prog.unwrap().success();
    cleanup(test_dir5);
    assert_eq!(exit_success, false);
}
<commit_msg>update test dir paths into tmp dir<commit_after>use std::{run};
use std::io::fs::rmdir;

static exe: &'static str = "build/mkdir";
static test_dir1: &'static str = "tmp/mkdir_test1";
static test_dir2: &'static str = "tmp/mkdir_test2";
static test_dir3: &'static str = "tmp/mkdir_test3";
static test_dir4: &'static str = "tmp/mkdir_test4/mkdir_test4_1";
static test_dir5: &'static str = "tmp/mkdir_test5/mkdir_test5_1";

fn cleanup(dir: &'static str) {
    let d = dir.into_owned();
    let p = Path::new(d.into_owned());
    if p.exists() {
        rmdir(&p);
    }
}

#[test]
fn test_mkdir_mkdir() {
    cleanup(test_dir1);
    let prog = run::process_status(exe.into_owned(), [test_dir1.into_owned()]);
    let exit_success = prog.unwrap().success();
    cleanup(test_dir1);
    assert_eq!(exit_success, true);
}

#[test]
fn test_mkdir_dup_dir() {
    cleanup(test_dir2);
    let prog = run::process_status(exe.into_owned(), [test_dir2.into_owned()]);
    let exit_success = prog.unwrap().success();
    if !exit_success {
        cleanup(test_dir2);
        fail!();
    }
    let prog2 = run::process_status(exe.into_owned(), [test_dir2.into_owned()]);
    let exit_success2 = prog2.unwrap().success();
    cleanup(test_dir2);
    assert_eq!(exit_success2, false);
}

#[test]
fn test_mkdir_mode() {
    cleanup(test_dir3);
    let prog = run::process_status(exe.into_owned(), [~"-m", ~"755", test_dir3.into_owned()]);
    let exit_success = prog.unwrap().success();
    cleanup(test_dir3);
    assert_eq!(exit_success, true);
}

#[test]
fn test_mkdir_parent() {
    cleanup(test_dir4);
    let prog = run::process_status(exe.into_owned(), [~"-p", test_dir4.into_owned()]);
    let exit_success = prog.unwrap().success();
    cleanup(test_dir4);
    assert_eq!(exit_success, true);
}

#[test]
fn test_mkdir_no_parent() {
    cleanup(test_dir5);
    let prog = run::process_status(exe.into_owned(), [test_dir5.into_owned()]);
    let exit_success = prog.unwrap().success();
    cleanup(test_dir5);
    assert_eq!(exit_success, false);
}
<|endoftext|>


<commit_before><commit_msg>[Auto] bin/core/git: Fix Clippy warnings<commit_after><|endoftext|>


<commit_before><commit_msg>Added text fields example.<commit_after>/*
 * Copyright (c) 2017 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

extern crate futures;
extern crate gtk;
#[macro_use]
extern crate relm;

use futures::Future;
use futures::future::ok;
use gtk::{ContainerExt, EditableSignals, Entry, EntryExt, Label, WidgetExt, Window, WindowType};
use gtk::Orientation::Vertical;
use relm::{QuitFuture, Relm, UnitFuture, Widget};

use self::Msg::*;

#[derive(Clone, Debug)]
struct Model {
    content: String,
}

#[derive(Clone)]
enum Msg {
    Change,
    Quit,
}

struct Widgets {
    input: Entry,
    label: Label,
    window: Window,
}

struct Win {
    model: Model,
    widgets: Widgets,
}

impl Win {
    fn view() -> Widgets {
        let vbox = gtk::Box::new(Vertical, 0);

        let input = Entry::new();
        vbox.add(&input);

        let label = Label::new(None);
        vbox.add(&label);

        let window = Window::new(WindowType::Toplevel);

        window.add(&vbox);

        window.show_all();

        Widgets {
            input: input,
            label: label,
            window: window,
        }
    }
}

impl Widget<Msg> for Win {
    fn connect_events(&self, relm: &Relm<Msg>) {
        connect!(relm, self.widgets.input, connect_changed(_), Change);
        connect_no_inhibit!(relm, self.widgets.window, connect_delete_event(_, _), Quit);
    }

    fn new() -> Self {
        Win {
            model: Model {
                content: String::new(),
            },
            widgets: Self::view(),
        }
    }

    fn update(&mut self, event: Msg) -> UnitFuture {
        match event {
            Change => {
                self.model.content = self.widgets.input.get_text().unwrap().chars().rev().collect();
                self.widgets.label.set_text(&self.model.content);
            },
            Quit => return QuitFuture.boxed(),
        }

        ok(()).boxed()
    }
}

fn main() {
    Relm::run::<Win>().unwrap();
}
<|endoftext|>


<commit_before>//! Server Requests
//!
//! These are requests that a `hyper::Server` receives, and include its method,
//! target URI, headers, and message body.
use std::io::IoResult;
use std::io::net::ip::SocketAddr;

use {HttpResult};
use version::{HttpVersion};
use method::Method::{self, Get, Head};
use header::Headers;
use header::common::{ContentLength, TransferEncoding};
use http::{read_request_line};
use http::HttpReader;
use http::HttpReader::{SizedReader, ChunkedReader, EmptyReader};
use uri::RequestUri;

/// A request bundles several parts of an incoming `NetworkStream`, given to a `Handler`.
pub struct Request<'a> {
    /// The IP address of the remote connection.
    pub remote_addr: SocketAddr,
    /// The `Method`, such as `Get`, `Post`, etc.
    pub method: Method,
    /// The headers of the incoming request.
    pub headers: Headers,
    /// The target request-uri for this request.
    pub uri: RequestUri,
    /// The version of HTTP for this request.
    pub version: HttpVersion,
    body: HttpReader<&'a mut (Reader + 'a)>
}

impl<'a> Request<'a> {

    /// Create a new Request, reading the StartLine and Headers so they are
    /// immediately useful.
    pub fn new(mut stream: &'a mut (Reader + 'a), addr: SocketAddr) -> HttpResult<Request<'a>> {
        let (method, uri, version) = try!(read_request_line(&mut stream));
        debug!("Request Line: {} {} {}", method, uri, version);
        let headers = try!(Headers::from_raw(&mut stream));
        debug!("Headers: [\n{}]", headers);

        let body = if method == Get || method == Head {
            EmptyReader(stream)
        } else if headers.has::<ContentLength>() {
            match headers.get::<ContentLength>() {
                Some(&ContentLength(len)) => SizedReader(stream, len),
                None => unreachable!()
            }
        } else if headers.has::<TransferEncoding>() {
            todo!("check for Transfer-Encoding: chunked");
            ChunkedReader(stream, None)
        } else {
            EmptyReader(stream)
        };

        Ok(Request {
            remote_addr: addr,
            method: method,
            uri: uri,
            headers: headers,
            version: version,
            body: body
        })
    }
}

impl<'a> Reader for Request<'a> {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        self.body.read(buf)
    }
}

#[cfg(test)]
mod tests {
    use mock::MockStream;
    use super::Request;

    use std::io::net::ip::SocketAddr;

    fn sock(s: &str) -> SocketAddr {
        s.parse().unwrap()
    }

    #[test]
    fn test_get_empty_body() {
        let mut stream = MockStream::with_input(b"\
            GET / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            \r\n\
            I'm a bad request.\r\n\
        ");

        let mut req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();
        assert_eq!(req.read_to_string(), Ok("".to_string()));
    }

    #[test]
    fn test_head_empty_body() {
        let mut stream = MockStream::with_input(b"\
            HEAD / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            \r\n\
            I'm a bad request.\r\n\
        ");

        let mut req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();
        assert_eq!(req.read_to_string(), Ok("".to_string()));
    }

    #[test]
    fn test_post_empty_body() {
        let mut stream = MockStream::with_input(b"\
            POST / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            \r\n\
            I'm a bad request.\r\n\
        ");

        let mut req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();
        assert_eq!(req.read_to_string(), Ok("".to_string()));
    }
}
<commit_msg>Add regression tests for chunked request parsing<commit_after>//! Server Requests
//!
//! These are requests that a `hyper::Server` receives, and include its method,
//! target URI, headers, and message body.
use std::io::IoResult;
use std::io::net::ip::SocketAddr;

use {HttpResult};
use version::{HttpVersion};
use method::Method::{self, Get, Head};
use header::Headers;
use header::common::{ContentLength, TransferEncoding};
use http::{read_request_line};
use http::HttpReader;
use http::HttpReader::{SizedReader, ChunkedReader, EmptyReader};
use uri::RequestUri;

/// A request bundles several parts of an incoming `NetworkStream`, given to a `Handler`.
pub struct Request<'a> {
    /// The IP address of the remote connection.
    pub remote_addr: SocketAddr,
    /// The `Method`, such as `Get`, `Post`, etc.
    pub method: Method,
    /// The headers of the incoming request.
    pub headers: Headers,
    /// The target request-uri for this request.
    pub uri: RequestUri,
    /// The version of HTTP for this request.
    pub version: HttpVersion,
    body: HttpReader<&'a mut (Reader + 'a)>
}

impl<'a> Request<'a> {

    /// Create a new Request, reading the StartLine and Headers so they are
    /// immediately useful.
    pub fn new(mut stream: &'a mut (Reader + 'a), addr: SocketAddr) -> HttpResult<Request<'a>> {
        let (method, uri, version) = try!(read_request_line(&mut stream));
        debug!("Request Line: {} {} {}", method, uri, version);
        let headers = try!(Headers::from_raw(&mut stream));
        debug!("Headers: [\n{}]", headers);

        let body = if method == Get || method == Head {
            EmptyReader(stream)
        } else if headers.has::<ContentLength>() {
            match headers.get::<ContentLength>() {
                Some(&ContentLength(len)) => SizedReader(stream, len),
                None => unreachable!()
            }
        } else if headers.has::<TransferEncoding>() {
            todo!("check for Transfer-Encoding: chunked");
            ChunkedReader(stream, None)
        } else {
            EmptyReader(stream)
        };

        Ok(Request {
            remote_addr: addr,
            method: method,
            uri: uri,
            headers: headers,
            version: version,
            body: body
        })
    }
}

impl<'a> Reader for Request<'a> {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        self.body.read(buf)
    }
}

#[cfg(test)]
mod tests {
    use header::common::{Host, TransferEncoding};
    use header::common::transfer_encoding::Encoding;
    use mock::MockStream;
    use super::Request;

    use std::io::net::ip::SocketAddr;

    fn sock(s: &str) -> SocketAddr {
        s.parse().unwrap()
    }

    #[test]
    fn test_get_empty_body() {
        let mut stream = MockStream::with_input(b"\
            GET / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            \r\n\
            I'm a bad request.\r\n\
        ");

        let mut req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();
        assert_eq!(req.read_to_string(), Ok("".to_string()));
    }

    #[test]
    fn test_head_empty_body() {
        let mut stream = MockStream::with_input(b"\
            HEAD / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            \r\n\
            I'm a bad request.\r\n\
        ");

        let mut req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();
        assert_eq!(req.read_to_string(), Ok("".to_string()));
    }

    #[test]
    fn test_post_empty_body() {
        let mut stream = MockStream::with_input(b"\
            POST / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            \r\n\
            I'm a bad request.\r\n\
        ");

        let mut req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();
        assert_eq!(req.read_to_string(), Ok("".to_string()));
    }

    #[test]
    fn test_parse_chunked_request() {
        let mut stream = MockStream::with_input(b"\
            POST / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            Transfer-Encoding: chunked\r\n\
            \r\n\
            1\r\n\
            q\r\n\
            2\r\n\
            we\r\n\
            2\r\n\
            rt\r\n\
            0\r\n\
            \r\n"
        );

        let mut req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();

        // The headers are correct?
        match req.headers.get::<Host>() {
            Some(host) => {
                assert_eq!("example.domain", host.hostname);
            },
            None => panic!("Host header expected!"),
        };
        match req.headers.get::<TransferEncoding>() {
            Some(encodings) => {
                assert_eq!(1, encodings.len());
                assert_eq!(Encoding::Chunked, encodings[0]);
            }
            None => panic!("Transfer-Encoding: chunked expected!"),
        };
        // The content is correctly read?
        let body = req.read_to_string().unwrap();
        assert_eq!("qwert", body);
    }

    /// Tests that when a chunk size is not a valid radix-16 number, an error
    /// is returned.
    #[test]
    fn test_invalid_chunk_size_not_hex_digit() {
        let mut stream = MockStream::with_input(b"\
            POST / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            Transfer-Encoding: chunked\r\n\
            \r\n\
            X\r\n\
            1\r\n\
            0\r\n\
            \r\n"
        );

        let mut req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();

        assert!(req.read_to_string().is_err());
    }

    /// Tests that when a chunk size contains an invalid extension, an error is
    /// returned.
    #[test]
    fn test_invalid_chunk_size_extension() {
        let mut stream = MockStream::with_input(b"\
            POST / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            Transfer-Encoding: chunked\r\n\
            \r\n\
            1 this is an invalid extension\r\n\
            1\r\n\
            0\r\n\
            \r\n"
        );

        let mut req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();

        assert!(req.read_to_string().is_err());
    }

    /// Tests that when a valid extension that contains a digit is appended to
    /// the chunk size, the chunk is correctly read.
    #[test]
    fn test_chunk_size_with_extension() {
        let mut stream = MockStream::with_input(b"\
            POST / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            Transfer-Encoding: chunked\r\n\
            \r\n\
            1;this is an extension with a digit 1\r\n\
            1\r\n\
            0\r\n\
            \r\n"
        );

        let mut req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();

        assert_eq!("1", req.read_to_string().unwrap())
    }

}
<|endoftext|>


<commit_before><commit_msg>Remove scope<commit_after><|endoftext|>


<commit_before>pub use self::fs::FileAbstraction;

// TODO:
// This whole thing can be written better with a trait based mechanism that is embedded into the
// store. However it would mean rewriting most things to be generic which can be a pain in the ass.

#[cfg(test)]
mod fs {
    use error::StoreError as SE;
    use error::StoreErrorKind as SEK;
    use std::io::Cursor;
    use std::path::PathBuf;

    use libimagerror::into::IntoError;

    use std::collections::HashMap;
    use std::sync::Mutex;

    lazy_static! {
        static ref MAP: Mutex<HashMap<PathBuf, Cursor<Vec<u8>>>> = {
            Mutex::new(HashMap::new())
        };
    }

    /// `FileAbstraction` type, this is the Test version!
    ///
    /// A lazy file is either absent, but a path to it is available, or it is present.
    #[derive(Debug)]
    pub enum FileAbstraction {
        Absent(PathBuf),
    }

    impl FileAbstraction {

        /**
         * Get the mutable file behind a FileAbstraction object
         */
        pub fn get_file_content(&mut self) -> Result<Cursor<Vec<u8>>, SE> {
            debug!("Getting lazy file: {:?}", self);
            match *self {
                FileAbstraction::Absent(ref f) => {
                    let map = MAP.lock().unwrap();
                    return map.get(f).cloned().ok_or(SEK::FileNotFound.into_error());
                },
            };
        }

        pub fn write_file_content(&mut self, buf: &[u8]) -> Result<(), SE> {
            match *self {
                FileAbstraction::Absent(ref f) => {
                    let mut map = MAP.lock().unwrap();
                    if let Some(ref mut cur) = map.get_mut(f) {
                        let mut vec = cur.get_mut();
                        vec.clear();
                        vec.extend_from_slice(buf);
                        return Ok(());
                    }
                    let vec = Vec::from(buf);
                    map.insert(f.clone(), Cursor::new(vec));
                    return Ok(());
                },
            };
        }

        pub fn remove_file(_: &PathBuf) -> Result<(), SE> {
            Ok(())
        }

        pub fn copy(from: &PathBuf, to: &PathBuf) -> Result<(), SE> {
            let mut map = MAP.lock().unwrap();
            let a = map.get(from).unwrap().clone();
            map.insert(to.clone(), a);
            Ok(())
        }

        pub fn rename(from: &PathBuf, to: &PathBuf) -> Result<(), SE> {
            let mut map = MAP.lock().unwrap();
            let a = map.get(from).unwrap().clone();
            map.insert(to.clone(), a);
            Ok(())
        }

        pub fn create_dir_all(_: &PathBuf) -> Result<(), SE> {
            Ok(())
        }
    }
}

#[cfg(not(test))]
mod fs {
    use error::{MapErrInto, StoreError as SE, StoreErrorKind as SEK};
    use std::io::{Seek, SeekFrom, Read};
    use std::path::{Path, PathBuf};
    use std::fs::{File, OpenOptions, create_dir_all, remove_file, copy, rename};

    /// `FileAbstraction` type
    ///
    /// A lazy file is either absent, but a path to it is available, or it is present.
    #[derive(Debug)]
    pub enum FileAbstraction {
        Absent(PathBuf),
        File(File, PathBuf)
    }

    fn open_file<A: AsRef<Path>>(p: A) -> ::std::io::Result<File> {
        OpenOptions::new().write(true).read(true).open(p)
    }

    fn create_file<A: AsRef<Path>>(p: A) -> ::std::io::Result<File> {
        if let Some(parent) = p.as_ref().parent() {
            debug!("Implicitely creating directory: {:?}", parent);
            if let Err(e) = create_dir_all(parent) {
                return Err(e);
            }
        }
        OpenOptions::new().write(true).read(true).create(true).open(p)
    }

    impl FileAbstraction {

        /**
         * Get the content behind this file
         */
        pub fn get_file_content(&mut self) -> Result<&mut Read, SE> {
            debug!("Getting lazy file: {:?}", self);
            let (file, path) = match *self {
                FileAbstraction::File(ref mut f, _) => return {
                    // We seek to the beginning of the file since we expect each
                    // access to the file to be in a different context
                    try!(f.seek(SeekFrom::Start(0))
                        .map_err_into(SEK::FileNotSeeked));
                    Ok(f)
                },
                FileAbstraction::Absent(ref p) => (try!(open_file(p).map_err_into(SEK::FileNotFound)),
                                            p.clone()),
            };
            *self = FileAbstraction::File(file, path);
            if let FileAbstraction::File(ref mut f, _) = *self {
                return Ok(f);
            }
            unreachable!()
        }

        /**
         * Write the content of this file
         */
        pub fn write_file_content(&mut self, buf: &[u8]) -> Result<(), SE> {
            use std::io::Write;
            let (file, path) = match *self {
                FileAbstraction::File(ref mut f, _) => return {
                    // We seek to the beginning of the file since we expect each
                    // access to the file to be in a different context
                    try!(f.seek(SeekFrom::Start(0))
                        .map_err_into(SEK::FileNotCreated));
                    f.write_all(buf).map_err_into(SEK::FileNotWritten)
                },
                FileAbstraction::Absent(ref p) => (try!(create_file(p).map_err_into(SEK::FileNotCreated)),
                                            p.clone()),
            };
            *self = FileAbstraction::File(file, path);
            if let FileAbstraction::File(ref mut f, _) = *self {
                return f.write_all(buf).map_err_into(SEK::FileNotWritten);
            }
            unreachable!();
        }

        pub fn remove_file(path: &PathBuf) -> Result<(), SE> {
            remove_file(path).map_err_into(SEK::FileNotRemoved)
        }

        pub fn copy(from: &PathBuf, to: &PathBuf) -> Result<(), SE> {
            copy(from, to).map_err_into(SEK::FileNotCopied).map(|_| ())
        }

        pub fn rename(from: &PathBuf, to: &PathBuf) -> Result<(), SE> {
            rename(from, to).map_err_into(SEK::FileNotRenamed)
        }

        pub fn create_dir_all(path: &PathBuf) -> Result<(), SE> {
            create_dir_all(path).map_err_into(SEK::DirNotCreated)
        }
    }
}

#[cfg(test)]
mod test {
    use super::FileAbstraction;
    use std::io::Read;
    use std::path::PathBuf;

    #[test]
    fn lazy_file() {
        let mut path = PathBuf::from("/tests");
        path.set_file_name("test1");
        let mut lf = FileAbstraction::Absent(path);
        lf.write_file_content(b"Hello World").unwrap();
        let mut bah = Vec::new();
        lf.get_file_content().unwrap().read_to_end(&mut bah).unwrap();
        assert_eq!(bah, b"Hello World");
    }

}
<commit_msg>Fix: FileAbstraction::remove_file(): Add implementation<commit_after>pub use self::fs::FileAbstraction;

// TODO:
// This whole thing can be written better with a trait based mechanism that is embedded into the
// store. However it would mean rewriting most things to be generic which can be a pain in the ass.

#[cfg(test)]
mod fs {
    use error::StoreError as SE;
    use error::StoreErrorKind as SEK;
    use std::io::Cursor;
    use std::path::PathBuf;

    use libimagerror::into::IntoError;

    use std::collections::HashMap;
    use std::sync::Mutex;

    lazy_static! {
        static ref MAP: Mutex<HashMap<PathBuf, Cursor<Vec<u8>>>> = {
            Mutex::new(HashMap::new())
        };
    }

    /// `FileAbstraction` type, this is the Test version!
    ///
    /// A lazy file is either absent, but a path to it is available, or it is present.
    #[derive(Debug)]
    pub enum FileAbstraction {
        Absent(PathBuf),
    }

    impl FileAbstraction {

        /**
         * Get the mutable file behind a FileAbstraction object
         */
        pub fn get_file_content(&mut self) -> Result<Cursor<Vec<u8>>, SE> {
            debug!("Getting lazy file: {:?}", self);
            match *self {
                FileAbstraction::Absent(ref f) => {
                    let map = MAP.lock().unwrap();
                    return map.get(f).cloned().ok_or(SEK::FileNotFound.into_error());
                },
            };
        }

        pub fn write_file_content(&mut self, buf: &[u8]) -> Result<(), SE> {
            match *self {
                FileAbstraction::Absent(ref f) => {
                    let mut map = MAP.lock().unwrap();
                    if let Some(ref mut cur) = map.get_mut(f) {
                        let mut vec = cur.get_mut();
                        vec.clear();
                        vec.extend_from_slice(buf);
                        return Ok(());
                    }
                    let vec = Vec::from(buf);
                    map.insert(f.clone(), Cursor::new(vec));
                    return Ok(());
                },
            };
        }

        pub fn remove_file(path: &PathBuf) -> Result<(), SE> {
            MAP.lock().unwrap().remove(path);
            Ok(())
        }

        pub fn copy(from: &PathBuf, to: &PathBuf) -> Result<(), SE> {
            let mut map = MAP.lock().unwrap();
            let a = map.get(from).unwrap().clone();
            map.insert(to.clone(), a);
            Ok(())
        }

        pub fn rename(from: &PathBuf, to: &PathBuf) -> Result<(), SE> {
            let mut map = MAP.lock().unwrap();
            let a = map.get(from).unwrap().clone();
            map.insert(to.clone(), a);
            Ok(())
        }

        pub fn create_dir_all(_: &PathBuf) -> Result<(), SE> {
            Ok(())
        }
    }
}

#[cfg(not(test))]
mod fs {
    use error::{MapErrInto, StoreError as SE, StoreErrorKind as SEK};
    use std::io::{Seek, SeekFrom, Read};
    use std::path::{Path, PathBuf};
    use std::fs::{File, OpenOptions, create_dir_all, remove_file, copy, rename};

    /// `FileAbstraction` type
    ///
    /// A lazy file is either absent, but a path to it is available, or it is present.
    #[derive(Debug)]
    pub enum FileAbstraction {
        Absent(PathBuf),
        File(File, PathBuf)
    }

    fn open_file<A: AsRef<Path>>(p: A) -> ::std::io::Result<File> {
        OpenOptions::new().write(true).read(true).open(p)
    }

    fn create_file<A: AsRef<Path>>(p: A) -> ::std::io::Result<File> {
        if let Some(parent) = p.as_ref().parent() {
            debug!("Implicitely creating directory: {:?}", parent);
            if let Err(e) = create_dir_all(parent) {
                return Err(e);
            }
        }
        OpenOptions::new().write(true).read(true).create(true).open(p)
    }

    impl FileAbstraction {

        /**
         * Get the content behind this file
         */
        pub fn get_file_content(&mut self) -> Result<&mut Read, SE> {
            debug!("Getting lazy file: {:?}", self);
            let (file, path) = match *self {
                FileAbstraction::File(ref mut f, _) => return {
                    // We seek to the beginning of the file since we expect each
                    // access to the file to be in a different context
                    try!(f.seek(SeekFrom::Start(0))
                        .map_err_into(SEK::FileNotSeeked));
                    Ok(f)
                },
                FileAbstraction::Absent(ref p) => (try!(open_file(p).map_err_into(SEK::FileNotFound)),
                                            p.clone()),
            };
            *self = FileAbstraction::File(file, path);
            if let FileAbstraction::File(ref mut f, _) = *self {
                return Ok(f);
            }
            unreachable!()
        }

        /**
         * Write the content of this file
         */
        pub fn write_file_content(&mut self, buf: &[u8]) -> Result<(), SE> {
            use std::io::Write;
            let (file, path) = match *self {
                FileAbstraction::File(ref mut f, _) => return {
                    // We seek to the beginning of the file since we expect each
                    // access to the file to be in a different context
                    try!(f.seek(SeekFrom::Start(0))
                        .map_err_into(SEK::FileNotCreated));
                    f.write_all(buf).map_err_into(SEK::FileNotWritten)
                },
                FileAbstraction::Absent(ref p) => (try!(create_file(p).map_err_into(SEK::FileNotCreated)),
                                            p.clone()),
            };
            *self = FileAbstraction::File(file, path);
            if let FileAbstraction::File(ref mut f, _) = *self {
                return f.write_all(buf).map_err_into(SEK::FileNotWritten);
            }
            unreachable!();
        }

        pub fn remove_file(path: &PathBuf) -> Result<(), SE> {
            remove_file(path).map_err_into(SEK::FileNotRemoved)
        }

        pub fn copy(from: &PathBuf, to: &PathBuf) -> Result<(), SE> {
            copy(from, to).map_err_into(SEK::FileNotCopied).map(|_| ())
        }

        pub fn rename(from: &PathBuf, to: &PathBuf) -> Result<(), SE> {
            rename(from, to).map_err_into(SEK::FileNotRenamed)
        }

        pub fn create_dir_all(path: &PathBuf) -> Result<(), SE> {
            create_dir_all(path).map_err_into(SEK::DirNotCreated)
        }
    }
}

#[cfg(test)]
mod test {
    use super::FileAbstraction;
    use std::io::Read;
    use std::path::PathBuf;

    #[test]
    fn lazy_file() {
        let mut path = PathBuf::from("/tests");
        path.set_file_name("test1");
        let mut lf = FileAbstraction::Absent(path);
        lf.write_file_content(b"Hello World").unwrap();
        let mut bah = Vec::new();
        lf.get_file_content().unwrap().read_to_end(&mut bah).unwrap();
        assert_eq!(bah, b"Hello World");
    }

}
<|endoftext|>


<commit_before><commit_msg>test: pass `--target` to `rustdoc` even if specified with host target<commit_after><|endoftext|>


<commit_before><commit_msg>Add a test for Pred<commit_after><|endoftext|>


<commit_before>use std::{fmt};
use os::token::Token;

#[deriving(Copy, PartialEq, Eq, Clone, PartialOrd, Ord)]
pub struct PollOpt(uint);

pub const EDGE: PollOpt    = PollOpt(0x020);
pub const LEVEL: PollOpt   = PollOpt(0x040);
pub const ONESHOT: PollOpt = PollOpt(0x080);

impl PollOpt {
    #[inline]
    pub fn edge() -> PollOpt {
        EDGE | ONESHOT
    }

    #[inline]
    pub fn empty() -> PollOpt {
        PollOpt(0)
    }

    #[inline]
    pub fn all() -> PollOpt {
        EDGE | LEVEL | ONESHOT
    }

    #[inline]
    pub fn bits(&self) -> uint {
        let PollOpt(bits) = *self;
        bits
    }

    #[inline]
    pub fn contains(&self, other: PollOpt) -> bool {
        (*self & other) == other
    }
}

impl BitOr<PollOpt, PollOpt> for PollOpt {
    #[inline]
    fn bitor(&self, other: &PollOpt) -> PollOpt {
        PollOpt(self.bits() | other.bits())
    }
}

impl BitXor<PollOpt, PollOpt> for PollOpt {
    #[inline]
    fn bitxor(&self, other: &PollOpt) -> PollOpt {
        PollOpt(self.bits() ^ other.bits())
    }
}

impl BitAnd<PollOpt, PollOpt> for PollOpt {
    #[inline]
    fn bitand(&self, other: &PollOpt) -> PollOpt {
        PollOpt(self.bits() & other.bits())
    }
}

impl Sub<PollOpt, PollOpt> for PollOpt {
    #[inline]
    fn sub(&self, other: &PollOpt) -> PollOpt {
        PollOpt(self.bits() & !other.bits())
    }
}

impl Not<PollOpt> for PollOpt {
    #[inline]
    fn not(&self) -> PollOpt {
        PollOpt(!self.bits() & PollOpt::all().bits())
    }
}

impl fmt::Show for PollOpt {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let mut one = false;
        let flags = [
            (EDGE, "Edge-Triggered"),
            (LEVEL, "Level-Triggered"),
            (ONESHOT, "OneShot")];

        for &(flag, msg) in flags.iter() {
            if self.contains(flag) {
                if one { try!(write!(fmt, " | ")) }
                try!(write!(fmt, "{}", msg));

                one = true
            }
        }

        Ok(())
    }
}

bitflags!(
    #[deriving(Copy)]
    flags Interest: uint {
        const READABLE = 0x001,
        const WRITABLE = 0x002,
        const ERROR    = 0x004,
        const HUP      = 0x008,
        const HINTED   = 0x010,
        const ALL      = 0x001 | 0x002 | 0x008  //epoll checks for ERROR no matter what
    }
)

impl fmt::Show for Interest {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let mut one = false;
        let flags = [
            (READABLE, "Readable"),
            (WRITABLE, "Writable"),
            (ERROR,    "Error"),
            (HUP,      "HupHint"),
            (HINTED,   "Hinted")];

        for &(flag, msg) in flags.iter() {
            if self.contains(flag) {
                if one { try!(write!(fmt, " | ")) }
                try!(write!(fmt, "{}", msg));

                one = true
            }
        }

        Ok(())
    }
}

bitflags!(
    #[deriving(Copy)]
    flags ReadHint: uint {
        const DATAHINT    = 0x001,
        const HUPHINT     = 0x002,
        const ERRORHINT   = 0x004
    }
)

impl fmt::Show for ReadHint {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let mut one = false;
        let flags = [
            (DATAHINT, "DataHint"),
            (HUPHINT, "HupHint"),
            (ERRORHINT, "ErrorHint")];

        for &(flag, msg) in flags.iter() {
            if self.contains(flag) {
                if one { try!(write!(fmt, " | ")) }
                try!(write!(fmt, "{}", msg));

                one = true
            }
        }

        Ok(())
    }
}

#[deriving(Copy, Show)]
pub struct IoEvent {
    kind: Interest,
    token: Token
}

/// IoEvent represents the raw event that the OS-specific selector
/// returned. An event can represent more than one kind (such as
/// readable or writable) at a time.
///
/// These IoEvent objects are created by the OS-specific concrete
/// Selector when they have events to report.
impl IoEvent {
    /// Create a new IoEvent.
    pub fn new(kind: Interest, token: uint) -> IoEvent {
        IoEvent {
            kind: kind,
            token: Token(token)
        }
    }

    pub fn token(&self) -> Token {
        self.token
    }

    /// Return an optional hint for a readable  handle. Currently,
    /// this method supports the HupHint, which indicates that the
    /// kernel reported that the remote side hung up. This allows a
    /// consumer to avoid reading in order to discover the hangup.
    pub fn read_hint(&self) -> ReadHint {
        let mut hint = ReadHint::empty();

        // The backend doesn't support hinting
        if !self.kind.contains(HINTED) {
            return hint;
        }

        if self.kind.contains(HUP) {
            hint = hint | HUPHINT
        }

        if self.kind.contains(READABLE) {
            hint = hint | DATAHINT
        }

        if self.kind.contains(ERROR) {
            hint = hint | ERRORHINT
        }

        hint
    }

    /// This event indicated that the  handle is now readable
    pub fn is_readable(&self) -> bool {
        self.kind.contains(READABLE) || self.kind.contains(HUP)
    }

    /// This event indicated that the  handle is now writable
    pub fn is_writable(&self) -> bool {
        self.kind.contains(WRITABLE)
    }

    /// This event indicated that the  handle had an error
    pub fn is_error(&self) -> bool {
        self.kind.contains(ERROR)
    }
}
<commit_msg>event: fix for ops reform.<commit_after>use std::{fmt};
use os::token::Token;

#[deriving(Copy, PartialEq, Eq, Clone, PartialOrd, Ord)]
pub struct PollOpt(uint);

pub const EDGE: PollOpt    = PollOpt(0x020);
pub const LEVEL: PollOpt   = PollOpt(0x040);
pub const ONESHOT: PollOpt = PollOpt(0x080);

impl PollOpt {
    #[inline]
    pub fn edge() -> PollOpt {
        EDGE | ONESHOT
    }

    #[inline]
    pub fn empty() -> PollOpt {
        PollOpt(0)
    }

    #[inline]
    pub fn all() -> PollOpt {
        EDGE | LEVEL | ONESHOT
    }

    #[inline]
    pub fn bits(&self) -> uint {
        let PollOpt(bits) = *self;
        bits
    }

    #[inline]
    pub fn contains(&self, other: PollOpt) -> bool {
        (*self & other) == other
    }
}

impl BitOr<PollOpt, PollOpt> for PollOpt {
    #[inline]
    fn bitor(self, other: PollOpt) -> PollOpt {
        PollOpt(self.bits() | other.bits())
    }
}

impl BitXor<PollOpt, PollOpt> for PollOpt {
    #[inline]
    fn bitxor(self, other: PollOpt) -> PollOpt {
        PollOpt(self.bits() ^ other.bits())
    }
}

impl BitAnd<PollOpt, PollOpt> for PollOpt {
    #[inline]
    fn bitand(self, other: PollOpt) -> PollOpt {
        PollOpt(self.bits() & other.bits())
    }
}

impl Sub<PollOpt, PollOpt> for PollOpt {
    #[inline]
    fn sub(self, other: PollOpt) -> PollOpt {
        PollOpt(self.bits() & !other.bits())
    }
}

impl Not<PollOpt> for PollOpt {
    #[inline]
    fn not(&self) -> PollOpt {
        PollOpt(!self.bits() & PollOpt::all().bits())
    }
}

impl fmt::Show for PollOpt {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let mut one = false;
        let flags = [
            (EDGE, "Edge-Triggered"),
            (LEVEL, "Level-Triggered"),
            (ONESHOT, "OneShot")];

        for &(flag, msg) in flags.iter() {
            if self.contains(flag) {
                if one { try!(write!(fmt, " | ")) }
                try!(write!(fmt, "{}", msg));

                one = true
            }
        }

        Ok(())
    }
}

bitflags!(
    #[deriving(Copy)]
    flags Interest: uint {
        const READABLE = 0x001,
        const WRITABLE = 0x002,
        const ERROR    = 0x004,
        const HUP      = 0x008,
        const HINTED   = 0x010,
        const ALL      = 0x001 | 0x002 | 0x008  //epoll checks for ERROR no matter what
    }
)

impl fmt::Show for Interest {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let mut one = false;
        let flags = [
            (READABLE, "Readable"),
            (WRITABLE, "Writable"),
            (ERROR,    "Error"),
            (HUP,      "HupHint"),
            (HINTED,   "Hinted")];

        for &(flag, msg) in flags.iter() {
            if self.contains(flag) {
                if one { try!(write!(fmt, " | ")) }
                try!(write!(fmt, "{}", msg));

                one = true
            }
        }

        Ok(())
    }
}

bitflags!(
    #[deriving(Copy)]
    flags ReadHint: uint {
        const DATAHINT    = 0x001,
        const HUPHINT     = 0x002,
        const ERRORHINT   = 0x004
    }
)

impl fmt::Show for ReadHint {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let mut one = false;
        let flags = [
            (DATAHINT, "DataHint"),
            (HUPHINT, "HupHint"),
            (ERRORHINT, "ErrorHint")];

        for &(flag, msg) in flags.iter() {
            if self.contains(flag) {
                if one { try!(write!(fmt, " | ")) }
                try!(write!(fmt, "{}", msg));

                one = true
            }
        }

        Ok(())
    }
}

#[deriving(Copy, Show)]
pub struct IoEvent {
    kind: Interest,
    token: Token
}

/// IoEvent represents the raw event that the OS-specific selector
/// returned. An event can represent more than one kind (such as
/// readable or writable) at a time.
///
/// These IoEvent objects are created by the OS-specific concrete
/// Selector when they have events to report.
impl IoEvent {
    /// Create a new IoEvent.
    pub fn new(kind: Interest, token: uint) -> IoEvent {
        IoEvent {
            kind: kind,
            token: Token(token)
        }
    }

    pub fn token(&self) -> Token {
        self.token
    }

    /// Return an optional hint for a readable  handle. Currently,
    /// this method supports the HupHint, which indicates that the
    /// kernel reported that the remote side hung up. This allows a
    /// consumer to avoid reading in order to discover the hangup.
    pub fn read_hint(&self) -> ReadHint {
        let mut hint = ReadHint::empty();

        // The backend doesn't support hinting
        if !self.kind.contains(HINTED) {
            return hint;
        }

        if self.kind.contains(HUP) {
            hint = hint | HUPHINT
        }

        if self.kind.contains(READABLE) {
            hint = hint | DATAHINT
        }

        if self.kind.contains(ERROR) {
            hint = hint | ERRORHINT
        }

        hint
    }

    /// This event indicated that the  handle is now readable
    pub fn is_readable(&self) -> bool {
        self.kind.contains(READABLE) || self.kind.contains(HUP)
    }

    /// This event indicated that the  handle is now writable
    pub fn is_writable(&self) -> bool {
        self.kind.contains(WRITABLE)
    }

    /// This event indicated that the  handle had an error
    pub fn is_error(&self) -> bool {
        self.kind.contains(ERROR)
    }
}
<|endoftext|>