<commit_before>extern crate base64;

use self::base64::encode;
use regex::Regex;
use url::{ParseError, Url};

lazy_static! {
    static ref HAS_PROTOCOL: Regex = Regex::new(r"^[a-z0-9]+:").unwrap();
    static ref REGEX_URL: Regex = Regex::new(r"^https?://").unwrap();
}

static MAGIC: [[&[u8]; 2]; 19] = [
    // Image
    [b"GIF87a", b"image/gif"],
    [b"GIF89a", b"image/gif"],
    [b"\xFF\xD8\xFF", b"image/jpeg"],
    [b"\x89PNG\x0D\x0A\x1A\x0A", b"image/png"],
    [b"<?xml ", b"image/svg+xml"],
    [b"<svg ", b"image/svg+xml"],
    [b"RIFF....WEBPVP8 ", b"image/webp"],
    [b"\x00\x00\x01\x00", b"image/x-icon"],
    // Audio
    [b"ID3", b"audio/mpeg"],
    [b"\xFF\x0E", b"audio/mpeg"],
    [b"\xFF\x0F", b"audio/mpeg"],
    [b"OggS", b"audio/ogg"],
    [b"RIFF....WAVEfmt ", b"audio/wav"],
    [b"fLaC", b"audio/x-flac"],
    // Video
    [b"RIFF....AVI LIST", b"video/avi"],
    [b"....ftyp", b"video/mp4"],
    [b"\x00\x00\x01\x0B", b"video/mpeg"],
    [b"....moov", b"video/quicktime"],
    [b"\x1A\x45\xDF\xA3", b"video/webm"],
];

pub fn data_to_dataurl(mime: &str, data: &[u8]) -> String {
    let mimetype = if mime == "" {
        detect_mimetype(data)
    } else {
        mime.to_string()
    };
    format!("data:{};base64,{}", mimetype, encode(data))
}

pub fn detect_mimetype(data: &[u8]) -> String {
    let mut re = String::new();

    for item in MAGIC.iter() {
        if data.starts_with(item[0]) {
            re = String::from_utf8(item[1].to_vec()).unwrap();
            break;
        }
    }

    re
}

pub fn url_has_protocol(url: &str) -> bool {
    HAS_PROTOCOL.is_match(&url.to_lowercase())
}

pub fn is_data_url(url: &str) -> Result<bool, ParseError> {
    match Url::parse(url) {
        Ok(parsed_url) => Ok(parsed_url.scheme() == "data"),
        Err(err) => Err(err),
    }
}

pub fn is_valid_url(path: &str) -> bool {
    REGEX_URL.is_match(path)
}

pub fn resolve_url(from: &str, to: &str) -> Result<String, ParseError> {
    let result = if is_valid_url(to) {
        to.to_string()
    } else {
        Url::parse(from)?.join(to)?.to_string()
    };

    Ok(result)
}
<commit_msg>refactor utils functions<commit_after>extern crate base64;

use self::base64::encode;
use regex::Regex;
use url::{ParseError, Url};

lazy_static! {
    static ref HAS_PROTOCOL: Regex = Regex::new(r"^[a-z0-9]+:").unwrap();
    static ref REGEX_URL: Regex = Regex::new(r"^https?://").unwrap();
}

const MAGIC: [[&[u8]; 2]; 19] = [
    // Image
    [b"GIF87a", b"image/gif"],
    [b"GIF89a", b"image/gif"],
    [b"\xFF\xD8\xFF", b"image/jpeg"],
    [b"\x89PNG\x0D\x0A\x1A\x0A", b"image/png"],
    [b"<?xml ", b"image/svg+xml"],
    [b"<svg ", b"image/svg+xml"],
    [b"RIFF....WEBPVP8 ", b"image/webp"],
    [b"\x00\x00\x01\x00", b"image/x-icon"],
    // Audio
    [b"ID3", b"audio/mpeg"],
    [b"\xFF\x0E", b"audio/mpeg"],
    [b"\xFF\x0F", b"audio/mpeg"],
    [b"OggS", b"audio/ogg"],
    [b"RIFF....WAVEfmt ", b"audio/wav"],
    [b"fLaC", b"audio/x-flac"],
    // Video
    [b"RIFF....AVI LIST", b"video/avi"],
    [b"....ftyp", b"video/mp4"],
    [b"\x00\x00\x01\x0B", b"video/mpeg"],
    [b"....moov", b"video/quicktime"],
    [b"\x1A\x45\xDF\xA3", b"video/webm"],
];

pub fn data_to_dataurl(mime: &str, data: &[u8]) -> String {
    let mimetype = if mime.is_empty() {
        detect_mimetype(data)
    } else {
        mime.to_string()
    };
    format!("data:{};base64,{}", mimetype, encode(data))
}

pub fn detect_mimetype(data: &[u8]) -> String {
    for item in MAGIC.iter() {
        if data.starts_with(item[0]) {
            return String::from_utf8(item[1].to_vec()).unwrap();
        }
    }
    "".to_owned()
}

pub fn url_has_protocol<T: AsRef<str>>(url: T) -> bool {
    HAS_PROTOCOL.is_match(url.as_ref().to_lowercase().as_str())
}

pub fn is_data_url<T: AsRef<str>>(url: T) -> Result<bool, ParseError> {
    Url::parse(url.as_ref()).and_then(|u| Ok(u.scheme() == "data"))
}

pub fn is_valid_url<T: AsRef<str>>(path: T) -> bool {
    REGEX_URL.is_match(path.as_ref())
}

pub fn resolve_url<T: AsRef<str>, U: AsRef<str>>(from: T, to: U) -> Result<String, ParseError> {
    let result = if is_valid_url(to.as_ref()) {
        to.as_ref().to_string()
    } else {
        Url::parse(from.as_ref())?
            .join(to.as_ref())?
            .as_ref()
            .to_string()
    };
    Ok(result)
}
<|endoftext|>


<commit_before>use core::nonzero::NonZero;
use ipc_channel::ipc::IpcSender;
use gleam::gl;
use offscreen_gl_context::{GLContext, GLContextAttributes, NativeGLContextMethods};

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct WebGLContextId(pub usize);

#[derive(Clone, Copy, PartialEq, Deserialize, Serialize, HeapSizeOf)]
pub enum WebGLError {
    InvalidEnum,
    InvalidOperation,
    InvalidValue,
    OutOfMemory,
    ContextLost,
}

pub type WebGLResult<T> = Result<T, WebGLError>;

#[derive(Clone, Deserialize, Serialize)]
pub enum WebGLFramebufferBindingRequest {
    Explicit(u32),
    Default,
}

#[derive(Clone, Deserialize, Serialize)]
pub enum WebGLShaderParameter {
    Int(i32),
    Bool(bool),
    Invalid,
}

#[derive(Clone, Deserialize, Serialize)]
pub enum WebGLCommand {
    GetContextAttributes(IpcSender<GLContextAttributes>),
    ActiveTexture(u32),
    BlendColor(f32, f32, f32, f32),
    BlendEquation(u32),
    BlendEquationSeparate(u32, u32),
    BlendFunc(u32, u32),
    BlendFuncSeparate(u32, u32, u32, u32),
    AttachShader(u32, u32),
    BufferData(u32, Vec<f32>, u32),
    Clear(u32),
    ClearColor(f32, f32, f32, f32),
    ClearDepth(f64),
    ClearStencil(i32),
    ColorMask(bool, bool, bool, bool),
    CullFace(u32),
    FrontFace(u32),
    DepthFunc(u32),
    DepthMask(bool),
    DepthRange(f64, f64),
    Enable(u32),
    Disable(u32),
    CompileShader(u32, String),
    CreateBuffer(IpcSender<Option<NonZero<u32>>>),
    CreateFramebuffer(IpcSender<Option<NonZero<u32>>>),
    CreateRenderbuffer(IpcSender<Option<NonZero<u32>>>),
    CreateTexture(IpcSender<Option<NonZero<u32>>>),
    CreateProgram(IpcSender<Option<NonZero<u32>>>),
    CreateShader(u32, IpcSender<Option<NonZero<u32>>>),
    DeleteBuffer(u32),
    DeleteFramebuffer(u32),
    DeleteRenderbuffer(u32),
    DeleteTexture(u32),
    DeleteProgram(u32),
    DeleteShader(u32),
    BindBuffer(u32, u32),
    BindFramebuffer(u32, WebGLFramebufferBindingRequest),
    BindRenderbuffer(u32, u32),
    BindTexture(u32, u32),
    DrawArrays(u32, i32, i32),
    EnableVertexAttribArray(u32),
    GetShaderParameter(u32, u32, IpcSender<WebGLShaderParameter>),
    GetAttribLocation(u32, String, IpcSender<Option<i32>>),
    GetUniformLocation(u32, String, IpcSender<Option<i32>>),
    PolygonOffset(f32, f32),
    Hint(u32, u32),
    LineWidth(f32),
    PixelStorei(u32, i32),
    LinkProgram(u32),
    Uniform4fv(i32, Vec<f32>),
    UseProgram(u32),
    VertexAttribPointer2f(u32, i32, bool, i32, u32),
    Viewport(i32, i32, i32, i32),
    TexImage2D(u32, i32, i32, i32, i32, u32, u32, Vec<u8>),
    TexParameteri(u32, u32, i32),
    TexParameterf(u32, u32, f32),
    DrawingBufferWidth(IpcSender<i32>),
    DrawingBufferHeight(IpcSender<i32>),
}

impl WebGLCommand {
    /// NOTE: This method consumes the command
    pub fn apply<Native: NativeGLContextMethods>(self, ctx: &GLContext<Native>) {
        match self {
            WebGLCommand::GetContextAttributes(sender) =>
                sender.send(*ctx.borrow_attributes()).unwrap(),
            WebGLCommand::ActiveTexture(target) =>
                gl::active_texture(target),
            WebGLCommand::BlendColor(r, g, b, a) =>
                gl::blend_color(r, g, b, a),
            WebGLCommand::BlendEquation(mode) =>
                gl::blend_equation(mode),
            WebGLCommand::BlendEquationSeparate(mode_rgb, mode_alpha) =>
                gl::blend_equation_separate(mode_rgb, mode_alpha),
            WebGLCommand::BlendFunc(src, dest) =>
                gl::blend_func(src, dest),
            WebGLCommand::BlendFuncSeparate(src_rgb, dest_rgb, src_alpha, dest_alpha) =>
                gl::blend_func_separate(src_rgb, dest_rgb, src_alpha, dest_alpha),
            WebGLCommand::AttachShader(program_id, shader_id) =>
                gl::attach_shader(program_id, shader_id),
            WebGLCommand::BufferData(buffer_type, data, usage) =>
                gl::buffer_data(buffer_type, &data, usage),
            WebGLCommand::Clear(mask) =>
                gl::clear(mask),
            WebGLCommand::ClearColor(r, g, b, a) =>
                gl::clear_color(r, g, b, a),
            WebGLCommand::ClearDepth(depth) =>
                gl::clear_depth(depth),
            WebGLCommand::ClearStencil(stencil) =>
                gl::clear_stencil(stencil),
            WebGLCommand::ColorMask(r, g, b, a) =>
                gl::color_mask(r, g, b, a),
            WebGLCommand::CullFace(mode) =>
                gl::cull_face(mode),
            WebGLCommand::DepthFunc(func) =>
                gl::depth_func(func),
            WebGLCommand::DepthMask(flag) =>
                gl::depth_mask(flag),
            WebGLCommand::DepthRange(near, far) =>
                gl::depth_range(near, far),
            WebGLCommand::Disable(cap) =>
                gl::disable(cap),
            WebGLCommand::Enable(cap) =>
                gl::enable(cap),
            WebGLCommand::FrontFace(mode) =>
                gl::front_face(mode),
            WebGLCommand::DrawArrays(mode, first, count) =>
                gl::draw_arrays(mode, first, count),
            WebGLCommand::Hint(name, val) =>
                gl::hint(name, val),
            WebGLCommand::LineWidth(width) =>
                gl::line_width(width),
            WebGLCommand::PixelStorei(name, val) =>
                gl::pixel_store_i(name, val),
            WebGLCommand::PolygonOffset(factor, units) =>
                gl::polygon_offset(factor, units),
            WebGLCommand::EnableVertexAttribArray(attrib_id) =>
                gl::enable_vertex_attrib_array(attrib_id),
            WebGLCommand::GetAttribLocation(program_id, name, chan) =>
                WebGLCommand::attrib_location(program_id, name, chan),
            WebGLCommand::GetShaderParameter(shader_id, param_id, chan) =>
                WebGLCommand::shader_parameter(shader_id, param_id, chan),
            WebGLCommand::GetUniformLocation(program_id, name, chan) =>
                WebGLCommand::uniform_location(program_id, name, chan),
            WebGLCommand::CompileShader(shader_id, source) =>
                WebGLCommand::compile_shader(shader_id, source),
            WebGLCommand::CreateBuffer(chan) =>
                WebGLCommand::create_buffer(chan),
            WebGLCommand::CreateFramebuffer(chan) =>
                WebGLCommand::create_framebuffer(chan),
            WebGLCommand::CreateRenderbuffer(chan) =>
                WebGLCommand::create_renderbuffer(chan),
            WebGLCommand::CreateTexture(chan) =>
                WebGLCommand::create_texture(chan),
            WebGLCommand::CreateProgram(chan) =>
                WebGLCommand::create_program(chan),
            WebGLCommand::CreateShader(shader_type, chan) =>
                WebGLCommand::create_shader(shader_type, chan),
            WebGLCommand::DeleteBuffer(id) =>
                gl::delete_buffers(&[id]),
            WebGLCommand::DeleteFramebuffer(id) =>
                gl::delete_framebuffers(&[id]),
            WebGLCommand::DeleteRenderbuffer(id) =>
                gl::delete_renderbuffers(&[id]),
            WebGLCommand::DeleteTexture(id) =>
                gl::delete_textures(&[id]),
            WebGLCommand::DeleteProgram(id) =>
                gl::delete_program(id),
            WebGLCommand::DeleteShader(id) =>
                gl::delete_shader(id),
            WebGLCommand::BindBuffer(target, id) =>
                gl::bind_buffer(target, id),
            WebGLCommand::BindFramebuffer(target, request) =>
                WebGLCommand::bind_framebuffer(target, request, ctx),
            WebGLCommand::BindRenderbuffer(target, id) =>
                gl::bind_renderbuffer(target, id),
            WebGLCommand::BindTexture(target, id) =>
                gl::bind_texture(target, id),
            WebGLCommand::LinkProgram(program_id) =>
                gl::link_program(program_id),
            WebGLCommand::Uniform4fv(uniform_id, data) =>
                gl::uniform_4f(uniform_id, data[0], data[1], data[2], data[3]),
            WebGLCommand::UseProgram(program_id) =>
                gl::use_program(program_id),
            WebGLCommand::VertexAttribPointer2f(attrib_id, size, normalized, stride, offset) =>
                gl::vertex_attrib_pointer_f32(attrib_id, size, normalized, stride, offset as u32),
            WebGLCommand::Viewport(x, y, width, height) =>
                gl::viewport(x, y, width, height),
            WebGLCommand::TexImage2D(target, level, internal, width, height, format, data_type, data) =>
                gl::tex_image_2d(target, level, internal, width, height, /*border*/0, format, data_type, Some(&data)),
            WebGLCommand::TexParameteri(target, name, value) =>
                gl::tex_parameter_i(target, name, value),
            WebGLCommand::TexParameterf(target, name, value) =>
                gl::tex_parameter_f(target, name, value),
            WebGLCommand::DrawingBufferWidth(sender) =>
                sender.send(ctx.borrow_draw_buffer().unwrap().size().width).unwrap(),
            WebGLCommand::DrawingBufferHeight(sender) =>
                sender.send(ctx.borrow_draw_buffer().unwrap().size().height).unwrap(),
        }
    }

    fn attrib_location(program_id: u32,
                       name: String,
                       chan: IpcSender<Option<i32>> ) {
        let attrib_location = gl::get_attrib_location(program_id, &name);

        let attrib_location = if attrib_location == -1 {
            None
        } else {
            Some(attrib_location)
        };

        chan.send(attrib_location).unwrap();
    }

    fn shader_parameter(shader_id: u32,
                        param_id: u32,
                        chan: IpcSender<WebGLShaderParameter>) {
        let result = match param_id {
            gl::SHADER_TYPE =>
                WebGLShaderParameter::Int(gl::get_shader_iv(shader_id, param_id)),
            gl::DELETE_STATUS | gl::COMPILE_STATUS =>
                WebGLShaderParameter::Bool(gl::get_shader_iv(shader_id, param_id) != 0),
            _ => panic!("Unexpected shader parameter type"),
        };

        chan.send(result).unwrap();
    }

    fn uniform_location(program_id: u32,
                        name: String,
                        chan: IpcSender<Option<i32>>) {
        let location = gl::get_uniform_location(program_id, &name);
        let location = if location == -1 {
            None
        } else {
            Some(location)
        };

        chan.send(location).unwrap();
    }

    fn create_buffer(chan: IpcSender<Option<NonZero<u32>>>) {
        let buffer = gl::gen_buffers(1)[0];
        let buffer = if buffer == 0 {
            None
        } else {
            Some(unsafe { NonZero::new(buffer) })
        };
        chan.send(buffer).unwrap();
    }

    fn create_framebuffer(chan: IpcSender<Option<NonZero<u32>>>) {
        let framebuffer = gl::gen_framebuffers(1)[0];
        let framebuffer = if framebuffer == 0 {
            None
        } else {
            Some(unsafe { NonZero::new(framebuffer) })
        };
        chan.send(framebuffer).unwrap();
    }

    fn create_renderbuffer(chan: IpcSender<Option<NonZero<u32>>>) {
        let renderbuffer = gl::gen_renderbuffers(1)[0];
        let renderbuffer = if renderbuffer == 0 {
            None
        } else {
            Some(unsafe { NonZero::new(renderbuffer) })
        };
        chan.send(renderbuffer).unwrap();
    }

    fn create_texture(chan: IpcSender<Option<NonZero<u32>>>) {
        let texture = gl::gen_textures(1)[0];
        let texture = if texture == 0 {
            None
        } else {
            Some(unsafe { NonZero::new(texture) })
        };
        chan.send(texture).unwrap();
    }

    fn create_program(chan: IpcSender<Option<NonZero<u32>>>) {
        let program = gl::create_program();
        let program = if program == 0 {
            None
        } else {
            Some(unsafe { NonZero::new(program) })
        };
        chan.send(program).unwrap();
    }

    fn create_shader(shader_type: u32, chan: IpcSender<Option<NonZero<u32>>>) {
        let shader = gl::create_shader(shader_type);
        let shader = if shader == 0 {
            None
        } else {
            Some(unsafe { NonZero::new(shader) })
        };
        chan.send(shader).unwrap();
    }

    #[inline]
    fn bind_framebuffer<Native: NativeGLContextMethods>(target: u32,
                                                        request: WebGLFramebufferBindingRequest,
                                                        ctx: &GLContext<Native>) {
        let id = match request {
            WebGLFramebufferBindingRequest::Explicit(id) => id,
            WebGLFramebufferBindingRequest::Default =>
                ctx.borrow_draw_buffer().unwrap().get_framebuffer(),
        };

        gl::bind_framebuffer(target, id);
    }

    #[inline]
    fn compile_shader(shader_id: u32, source: String) {
        gl::shader_source(shader_id, &[source.as_bytes()]);
        gl::compile_shader(shader_id);
    }
}
<commit_msg>webgl: Fix pending changes from rebase<commit_after>use core::nonzero::NonZero;
use ipc_channel::ipc::IpcSender;
use gleam::gl;
use offscreen_gl_context::{GLContext, GLContextAttributes, NativeGLContextMethods};

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct WebGLContextId(pub usize);

#[derive(Clone, Copy, PartialEq, Deserialize, Serialize, HeapSizeOf)]
pub enum WebGLError {
    InvalidEnum,
    InvalidOperation,
    InvalidValue,
    OutOfMemory,
    ContextLost,
}

pub type WebGLResult<T> = Result<T, WebGLError>;

#[derive(Clone, Deserialize, Serialize)]
pub enum WebGLFramebufferBindingRequest {
    Explicit(u32),
    Default,
}

#[derive(Clone, Deserialize, Serialize)]
pub enum WebGLShaderParameter {
    Int(i32),
    Bool(bool),
    Invalid,
}

#[derive(Clone, Deserialize, Serialize)]
pub enum WebGLCommand {
    GetContextAttributes(IpcSender<GLContextAttributes>),
    ActiveTexture(u32),
    BlendColor(f32, f32, f32, f32),
    BlendEquation(u32),
    BlendEquationSeparate(u32, u32),
    BlendFunc(u32, u32),
    BlendFuncSeparate(u32, u32, u32, u32),
    AttachShader(u32, u32),
    BufferData(u32, Vec<u8>, u32),
    BufferSubData(u32, isize, Vec<u8>),
    Clear(u32),
    ClearColor(f32, f32, f32, f32),
    ClearDepth(f64),
    ClearStencil(i32),
    ColorMask(bool, bool, bool, bool),
    CullFace(u32),
    FrontFace(u32),
    DepthFunc(u32),
    DepthMask(bool),
    DepthRange(f64, f64),
    Enable(u32),
    Disable(u32),
    CompileShader(u32, String),
    CreateBuffer(IpcSender<Option<NonZero<u32>>>),
    CreateFramebuffer(IpcSender<Option<NonZero<u32>>>),
    CreateRenderbuffer(IpcSender<Option<NonZero<u32>>>),
    CreateTexture(IpcSender<Option<NonZero<u32>>>),
    CreateProgram(IpcSender<Option<NonZero<u32>>>),
    CreateShader(u32, IpcSender<Option<NonZero<u32>>>),
    DeleteBuffer(u32),
    DeleteFramebuffer(u32),
    DeleteRenderbuffer(u32),
    DeleteTexture(u32),
    DeleteProgram(u32),
    DeleteShader(u32),
    BindBuffer(u32, u32),
    BindFramebuffer(u32, WebGLFramebufferBindingRequest),
    BindRenderbuffer(u32, u32),
    BindTexture(u32, u32),
    DrawArrays(u32, i32, i32),
    EnableVertexAttribArray(u32),
    GetShaderParameter(u32, u32, IpcSender<WebGLShaderParameter>),
    GetAttribLocation(u32, String, IpcSender<Option<i32>>),
    GetUniformLocation(u32, String, IpcSender<Option<i32>>),
    PolygonOffset(f32, f32),
    Hint(u32, u32),
    LineWidth(f32),
    PixelStorei(u32, i32),
    LinkProgram(u32),
    Uniform4fv(i32, Vec<f32>),
    UseProgram(u32),
    VertexAttribPointer2f(u32, i32, bool, i32, u32),
    Viewport(i32, i32, i32, i32),
    TexImage2D(u32, i32, i32, i32, i32, u32, u32, Vec<u8>),
    TexParameteri(u32, u32, i32),
    TexParameterf(u32, u32, f32),
    DrawingBufferWidth(IpcSender<i32>),
    DrawingBufferHeight(IpcSender<i32>),
}

impl WebGLCommand {
    /// NOTE: This method consumes the command
    pub fn apply<Native: NativeGLContextMethods>(self, ctx: &GLContext<Native>) {
        match self {
            WebGLCommand::GetContextAttributes(sender) =>
                sender.send(*ctx.borrow_attributes()).unwrap(),
            WebGLCommand::ActiveTexture(target) =>
                gl::active_texture(target),
            WebGLCommand::BlendColor(r, g, b, a) =>
                gl::blend_color(r, g, b, a),
            WebGLCommand::BlendEquation(mode) =>
                gl::blend_equation(mode),
            WebGLCommand::BlendEquationSeparate(mode_rgb, mode_alpha) =>
                gl::blend_equation_separate(mode_rgb, mode_alpha),
            WebGLCommand::BlendFunc(src, dest) =>
                gl::blend_func(src, dest),
            WebGLCommand::BlendFuncSeparate(src_rgb, dest_rgb, src_alpha, dest_alpha) =>
                gl::blend_func_separate(src_rgb, dest_rgb, src_alpha, dest_alpha),
            WebGLCommand::AttachShader(program_id, shader_id) =>
                gl::attach_shader(program_id, shader_id),
            WebGLCommand::BufferData(buffer_type, data, usage) =>
                gl::buffer_data(buffer_type, &data, usage),
            WebGLCommand::BufferSubData(buffer_type, offset, data) =>
                gl::buffer_sub_data(buffer_type, offset, &data),
            WebGLCommand::Clear(mask) =>
                gl::clear(mask),
            WebGLCommand::ClearColor(r, g, b, a) =>
                gl::clear_color(r, g, b, a),
            WebGLCommand::ClearDepth(depth) =>
                gl::clear_depth(depth),
            WebGLCommand::ClearStencil(stencil) =>
                gl::clear_stencil(stencil),
            WebGLCommand::ColorMask(r, g, b, a) =>
                gl::color_mask(r, g, b, a),
            WebGLCommand::CullFace(mode) =>
                gl::cull_face(mode),
            WebGLCommand::DepthFunc(func) =>
                gl::depth_func(func),
            WebGLCommand::DepthMask(flag) =>
                gl::depth_mask(flag),
            WebGLCommand::DepthRange(near, far) =>
                gl::depth_range(near, far),
            WebGLCommand::Disable(cap) =>
                gl::disable(cap),
            WebGLCommand::Enable(cap) =>
                gl::enable(cap),
            WebGLCommand::FrontFace(mode) =>
                gl::front_face(mode),
            WebGLCommand::DrawArrays(mode, first, count) =>
                gl::draw_arrays(mode, first, count),
            WebGLCommand::Hint(name, val) =>
                gl::hint(name, val),
            WebGLCommand::LineWidth(width) =>
                gl::line_width(width),
            WebGLCommand::PixelStorei(name, val) =>
                gl::pixel_store_i(name, val),
            WebGLCommand::PolygonOffset(factor, units) =>
                gl::polygon_offset(factor, units),
            WebGLCommand::EnableVertexAttribArray(attrib_id) =>
                gl::enable_vertex_attrib_array(attrib_id),
            WebGLCommand::GetAttribLocation(program_id, name, chan) =>
                WebGLCommand::attrib_location(program_id, name, chan),
            WebGLCommand::GetShaderParameter(shader_id, param_id, chan) =>
                WebGLCommand::shader_parameter(shader_id, param_id, chan),
            WebGLCommand::GetUniformLocation(program_id, name, chan) =>
                WebGLCommand::uniform_location(program_id, name, chan),
            WebGLCommand::CompileShader(shader_id, source) =>
                WebGLCommand::compile_shader(shader_id, source),
            WebGLCommand::CreateBuffer(chan) =>
                WebGLCommand::create_buffer(chan),
            WebGLCommand::CreateFramebuffer(chan) =>
                WebGLCommand::create_framebuffer(chan),
            WebGLCommand::CreateRenderbuffer(chan) =>
                WebGLCommand::create_renderbuffer(chan),
            WebGLCommand::CreateTexture(chan) =>
                WebGLCommand::create_texture(chan),
            WebGLCommand::CreateProgram(chan) =>
                WebGLCommand::create_program(chan),
            WebGLCommand::CreateShader(shader_type, chan) =>
                WebGLCommand::create_shader(shader_type, chan),
            WebGLCommand::DeleteBuffer(id) =>
                gl::delete_buffers(&[id]),
            WebGLCommand::DeleteFramebuffer(id) =>
                gl::delete_framebuffers(&[id]),
            WebGLCommand::DeleteRenderbuffer(id) =>
                gl::delete_renderbuffers(&[id]),
            WebGLCommand::DeleteTexture(id) =>
                gl::delete_textures(&[id]),
            WebGLCommand::DeleteProgram(id) =>
                gl::delete_program(id),
            WebGLCommand::DeleteShader(id) =>
                gl::delete_shader(id),
            WebGLCommand::BindBuffer(target, id) =>
                gl::bind_buffer(target, id),
            WebGLCommand::BindFramebuffer(target, request) =>
                WebGLCommand::bind_framebuffer(target, request, ctx),
            WebGLCommand::BindRenderbuffer(target, id) =>
                gl::bind_renderbuffer(target, id),
            WebGLCommand::BindTexture(target, id) =>
                gl::bind_texture(target, id),
            WebGLCommand::LinkProgram(program_id) =>
                gl::link_program(program_id),
            WebGLCommand::Uniform4fv(uniform_id, data) =>
                gl::uniform_4f(uniform_id, data[0], data[1], data[2], data[3]),
            WebGLCommand::UseProgram(program_id) =>
                gl::use_program(program_id),
            WebGLCommand::VertexAttribPointer2f(attrib_id, size, normalized, stride, offset) =>
                gl::vertex_attrib_pointer_f32(attrib_id, size, normalized, stride, offset as u32),
            WebGLCommand::Viewport(x, y, width, height) =>
                gl::viewport(x, y, width, height),
            WebGLCommand::TexImage2D(target, level, internal, width, height, format, data_type, data) =>
                gl::tex_image_2d(target, level, internal, width, height, /*border*/0, format, data_type, Some(&data)),
            WebGLCommand::TexParameteri(target, name, value) =>
                gl::tex_parameter_i(target, name, value),
            WebGLCommand::TexParameterf(target, name, value) =>
                gl::tex_parameter_f(target, name, value),
            WebGLCommand::DrawingBufferWidth(sender) =>
                sender.send(ctx.borrow_draw_buffer().unwrap().size().width).unwrap(),
            WebGLCommand::DrawingBufferHeight(sender) =>
                sender.send(ctx.borrow_draw_buffer().unwrap().size().height).unwrap(),
        }

        // FIXME: Convert to `debug_assert!` once tests are run with debug assertions
        assert!(gl::get_error() == gl::NO_ERROR);
    }

    fn attrib_location(program_id: u32,
                       name: String,
                       chan: IpcSender<Option<i32>> ) {
        let attrib_location = gl::get_attrib_location(program_id, &name);

        let attrib_location = if attrib_location == -1 {
            None
        } else {
            Some(attrib_location)
        };

        chan.send(attrib_location).unwrap();
    }

    fn shader_parameter(shader_id: u32,
                        param_id: u32,
                        chan: IpcSender<WebGLShaderParameter>) {
        let result = match param_id {
            gl::SHADER_TYPE =>
                WebGLShaderParameter::Int(gl::get_shader_iv(shader_id, param_id)),
            gl::DELETE_STATUS | gl::COMPILE_STATUS =>
                WebGLShaderParameter::Bool(gl::get_shader_iv(shader_id, param_id) != 0),
            _ => panic!("Unexpected shader parameter type"),
        };

        chan.send(result).unwrap();
    }

    fn uniform_location(program_id: u32,
                        name: String,
                        chan: IpcSender<Option<i32>>) {
        let location = gl::get_uniform_location(program_id, &name);
        let location = if location == -1 {
            None
        } else {
            Some(location)
        };

        chan.send(location).unwrap();
    }

    fn create_buffer(chan: IpcSender<Option<NonZero<u32>>>) {
        let buffer = gl::gen_buffers(1)[0];
        let buffer = if buffer == 0 {
            None
        } else {
            Some(unsafe { NonZero::new(buffer) })
        };
        chan.send(buffer).unwrap();
    }

    fn create_framebuffer(chan: IpcSender<Option<NonZero<u32>>>) {
        let framebuffer = gl::gen_framebuffers(1)[0];
        let framebuffer = if framebuffer == 0 {
            None
        } else {
            Some(unsafe { NonZero::new(framebuffer) })
        };
        chan.send(framebuffer).unwrap();
    }

    fn create_renderbuffer(chan: IpcSender<Option<NonZero<u32>>>) {
        let renderbuffer = gl::gen_renderbuffers(1)[0];
        let renderbuffer = if renderbuffer == 0 {
            None
        } else {
            Some(unsafe { NonZero::new(renderbuffer) })
        };
        chan.send(renderbuffer).unwrap();
    }

    fn create_texture(chan: IpcSender<Option<NonZero<u32>>>) {
        let texture = gl::gen_textures(1)[0];
        let texture = if texture == 0 {
            None
        } else {
            Some(unsafe { NonZero::new(texture) })
        };
        chan.send(texture).unwrap();
    }

    fn create_program(chan: IpcSender<Option<NonZero<u32>>>) {
        let program = gl::create_program();
        let program = if program == 0 {
            None
        } else {
            Some(unsafe { NonZero::new(program) })
        };
        chan.send(program).unwrap();
    }

    fn create_shader(shader_type: u32, chan: IpcSender<Option<NonZero<u32>>>) {
        let shader = gl::create_shader(shader_type);
        let shader = if shader == 0 {
            None
        } else {
            Some(unsafe { NonZero::new(shader) })
        };
        chan.send(shader).unwrap();
    }

    #[inline]
    fn bind_framebuffer<Native: NativeGLContextMethods>(target: u32,
                                                        request: WebGLFramebufferBindingRequest,
                                                        ctx: &GLContext<Native>) {
        let id = match request {
            WebGLFramebufferBindingRequest::Explicit(id) => id,
            WebGLFramebufferBindingRequest::Default =>
                ctx.borrow_draw_buffer().unwrap().get_framebuffer(),
        };

        gl::bind_framebuffer(target, id);
    }

    #[inline]
    fn compile_shader(shader_id: u32, source: String) {
        gl::shader_source(shader_id, &[source.as_bytes()]);
        gl::compile_shader(shader_id);
    }
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate persistent_vector;
extern crate test;

use persistent_vector::PVec;
use test::Bencher;

#[bench]
fn bench_push_get_pvec(b: &mut Bencher) {
    let n = (10 as usize).pow(4);
    b.iter(|| {
        let mut v = PVec::new();
        for i in 0..n {
            v = v.push(i);
        }
        for i in 0..n {
            assert_eq!(v.get(i), Some(&i));
        }
        assert_eq!(v.get(n), None);
    })
}

#[bench]
fn bench_push_get_vec(b: &mut Bencher) {
    let n = (10 as usize).pow(4);
    b.iter(|| {
        let mut v = Vec::new();
        for i in 0..n {
            v.push(i);
        }
        for i in 0..n {
            assert_eq!(v.get(i), Some(&i));
        }
        assert_eq!(v.get(n), None);
    })
}

#[bench]
fn bench_push_pvec(b: &mut Bencher) {
    let n = (10 as usize).pow(4);
    b.iter(|| {
        let mut v = PVec::new();
        for i in 0..n {
            v = v.push(i);
        }
        assert_eq!(v.get(n), None);
    })
}

#[bench]
fn bench_push_vec(b: &mut Bencher) {
    let n = (10 as usize).pow(4);
    b.iter(|| {
        let mut v = Vec::new();
        for i in 0..n {
            v.push(i);
        }
        assert_eq!(v.get(n), None);
    })
}

#[bench]
fn bench_get_pvec(b: &mut Bencher) {
    let n = (10 as usize).pow(4);
    let mut v = PVec::new();
    for i in 0..n {
        v = v.push(i);
    }
    b.iter(|| {
        for i in 0..n {
            assert_eq!(v.get(i), Some(&i));
        }
        assert_eq!(v.get(n), None);
    })
}

#[bench]
fn bench_get_vec(b: &mut Bencher) {
    let n = (10 as usize).pow(4);
    let mut v = Vec::new();
    for i in 0..n {
        v.push(i);
    }
    b.iter(|| {
        for i in 0..n {
            assert_eq!(v.get(i), Some(&i));
        }
        assert_eq!(v.get(n), None);
    })
}
<commit_msg>Refactor benchmarks for ease of changing number of elements<commit_after>#![feature(test)]

extern crate persistent_vector;
extern crate test;

use persistent_vector::PVec;
use test::Bencher;

const p: u32 = 5;

#[bench]
fn bench_push_get_pvec(b: &mut Bencher) {
    let n = (10 as usize).pow(p);
    b.iter(|| {
        let mut v = PVec::new();
        for i in 0..n {
            v = v.push(i);
        }
        for i in 0..n {
            assert_eq!(v.get(i), Some(&i));
        }
        assert_eq!(v.get(n), None);
    })
}

#[bench]
fn bench_push_get_vec(b: &mut Bencher) {
    let n = (10 as usize).pow(p);
    b.iter(|| {
        let mut v = Vec::new();
        for i in 0..n {
            v.push(i);
        }
        for i in 0..n {
            assert_eq!(v.get(i), Some(&i));
        }
        assert_eq!(v.get(n), None);
    })
}

#[bench]
fn bench_push_pvec(b: &mut Bencher) {
    let n = (10 as usize).pow(p);
    b.iter(|| {
        let mut v = PVec::new();
        for i in 0..n {
            v = v.push(i);
        }
        assert_eq!(v.get(n), None);
    })
}

#[bench]
fn bench_push_vec(b: &mut Bencher) {
    let n = (10 as usize).pow(p);
    b.iter(|| {
        let mut v = Vec::new();
        for i in 0..n {
            v.push(i);
        }
        assert_eq!(v.get(n), None);
    })
}

#[bench]
fn bench_get_pvec(b: &mut Bencher) {
    let n = (10 as usize).pow(p);
    let mut v = PVec::new();
    for i in 0..n {
        v = v.push(i);
    }
    b.iter(|| {
        for i in 0..n {
            assert_eq!(v.get(i), Some(&i));
        }
        assert_eq!(v.get(n), None);
    })
}

#[bench]
fn bench_get_vec(b: &mut Bencher) {
    let n = (10 as usize).pow(p);
    let mut v = Vec::new();
    for i in 0..n {
        v.push(i);
    }
    b.iter(|| {
        for i in 0..n {
            assert_eq!(v.get(i), Some(&i));
        }
        assert_eq!(v.get(n), None);
    })
}

#[bench]
fn bench_clone_pvec(b: &mut Bencher) {
    let n = (10 as usize).pow(p);
    let mut v = PVec::new();
    for i in 0..n {
        v = v.push(i);
    }
    b.iter(|| { let vs = v.clone(); })
}

#[bench]
fn bench_clone_vec(b: &mut Bencher) {
    let n = (10 as usize).pow(p);
    let mut v = Vec::new();
    for i in 0..n {
        v.push(i);
    }
    b.iter(|| { let vs = v.clone(); })
}
<|endoftext|>


<commit_before>//! Data structures and methods for parsing and applying Knuth-Liang
//! hyphenation patterns and exceptions.

#![cfg_attr(feature = "serde_derive", feature(proc_macro))]

#[cfg(feature = "serde_derive")]
#[macro_use]
extern crate serde_derive;

extern crate serde;
extern crate fnv;

use std::borrow::Cow;
use std::cmp::{max};
use std::collections::hash_map::{HashMap, Entry};
use std::hash::BuildHasherDefault;
use std::mem;

use fnv::FnvHasher;

/// A pair representing a Knuth-Liang hyphenation pattern. It comprises
/// alphabetical characters for subword matching and the score of each
/// hyphenation point.
pub type KLPair = (String, Vec<u8>);

#[cfg(feature = "serde_derive")]
include!("serde_types.in.rs");

#[cfg(feature = "serde_codegen")]
include!(concat!(env!("OUT_DIR"), "/serde_types.rs"));

pub trait KLPTrie<'a> {
    type Score;

    fn new() -> Self;

    fn insert(&mut self, KLPair) -> Option<Vec<u8>>;

    fn score(&'a self, &str) -> Self::Score;

    fn is_empty(&self) -> bool;

}

impl<'a> KLPTrie<'a> for Patterns {
    type Score = Vec<u8>;

    /// Creates an empty `Patterns` trie.
    fn new() -> Patterns {
        let fnv = BuildHasherDefault::<FnvHasher>::default();

        Patterns {
            tally: None,
            descendants: HashMap::with_hasher(fnv)
        }
    }

    /// Inserts a Knuth-Liang hyphenation pair into the trie.
    ///
    /// If the pattern already exists, the old tally is returned; if not, `None` is.
    fn insert(&mut self, (pattern, tally): KLPair) -> Option<Vec<u8>> {
        let node = pattern.bytes().fold(self, |t, b| {
            match t.descendants.entry(b) {
                Entry::Vacant(e) => e.insert(Patterns::new()),
                Entry::Occupied(e) => e.into_mut()
            }
        });

        let mut retv = None;
        match node.tally {
            Some(ref mut old) => retv = Some(mem::replace(old, tally)),
            None => node.tally = Some(tally)
        }

        retv
    }

    /// Assigns a score to each potential hyphenation point.
    ///
    /// All patterns matching a substring of `word` are compounded, and for
    /// each hyphenation point, the highest competing value is selected.
    fn score(&self, word: &str) -> Self::Score {
        let w = match word.chars().any(|c| c.is_uppercase()) {
            true => Cow::Owned(word.to_lowercase()),
            false => Cow::Borrowed(word)
        };
        let match_str = [".", w.as_ref(), "."].concat();
        let match_length = match_str.len();

        if match_length <= 3 {
            return vec![];
        }

        let hyphenable_length = match_length - 2;
        let mut points: Vec<u8> = vec![0; hyphenable_length - 1];

        for i in 0..match_length {
            let mut m = &self.descendants;
            for b in match_str.bytes().skip(i) {
                match m.get(&b) {
                    Some(&Patterns { tally: Some(ref t), descendants: ref m1 }) => {
                        m = m1;
                        for (j, &p) in t.iter().enumerate() {
                            let k = i + j;
                            if k > 1 && k <= hyphenable_length {
                                let p1 = points[k - 2];
                                points[k - 2] = max(p, p1)
                            }
                        }
                    },
                    Some(patterns) => m = &patterns.descendants,
                    _ => break
                }
            }
        }

        points
    }

    fn is_empty(&self) -> bool {
        self.descendants.is_empty()
    }
}

impl<'a> KLPTrie<'a> for Exceptions {
    type Score = Option<&'a Vec<u8>>;

    /// Creates an empty `Exceptions` map.
    fn new() -> Exceptions {
        Exceptions(HashMap::new())
    }

    /// Inserts a Knuth-Liang exception pair into the map.
    ///
    /// If the pattern already exists, the old score is returned; if not, `None` is.
    fn insert(&mut self, (pattern, score): KLPair) -> Option<Vec<u8>> {
        let Exceptions(ref mut m) = *self;

        m.insert(pattern, score)
    }

    /// Retrieves the score for each hyphenation point of `word`.
    fn score(&'a self, word: &str) -> Self::Score {
        let Exceptions(ref m) = *self;
        let w = match word.chars().any(|c| c.is_uppercase()) {
            true => Cow::Owned(word.to_lowercase()),
            false => Cow::Borrowed(word)
        };

        m.get(w.as_ref())
    }

    fn is_empty(&self) -> bool {
        self.0.is_empty()
    }
}
<commit_msg>Style minutia<commit_after>//! Data structures and methods for parsing and applying Knuth-Liang
//! hyphenation patterns and exceptions.

#![cfg_attr(feature = "serde_derive", feature(proc_macro))]

#[cfg(feature = "serde_derive")]
#[macro_use]
extern crate serde_derive;

extern crate serde;
extern crate fnv;

use std::borrow::Cow;
use std::cmp::{max};
use std::collections::hash_map::{HashMap, Entry};
use std::hash::BuildHasherDefault;
use std::mem;

use fnv::FnvHasher;

/// A pair representing a Knuth-Liang hyphenation pattern. It comprises
/// alphabetical characters for subword matching and the score of each
/// hyphenation point.
pub type KLPair = (String, Vec<u8>);

#[cfg(feature = "serde_derive")]
include!("serde_types.in.rs");

#[cfg(feature = "serde_codegen")]
include!(concat!(env!("OUT_DIR"), "/serde_types.rs"));

pub trait KLPTrie<'a> {
    type Score;

    fn new() -> Self;

    fn insert(&mut self, KLPair) -> Option<Vec<u8>>;

    fn score(&'a self, &str) -> Self::Score;

    fn is_empty(&self) -> bool;
}

impl<'a> KLPTrie<'a> for Patterns {
    type Score = Vec<u8>;

    /// Creates an empty `Patterns` trie.
    fn new() -> Patterns {
        let fnv = BuildHasherDefault::<FnvHasher>::default();

        Patterns {
            tally: None,
            descendants: HashMap::with_hasher(fnv)
        }
    }

    /// Inserts a Knuth-Liang hyphenation pair into the trie.
    ///
    /// If the pattern already exists, the old tally is returned; if not, `None` is.
    fn insert(&mut self, (pattern, tally): KLPair) -> Option<Vec<u8>> {
        let node = pattern.bytes().fold(self, |t, b| {
            match t.descendants.entry(b) {
                Entry::Vacant(e) => e.insert(Patterns::new()),
                Entry::Occupied(e) => e.into_mut()
            }
        });

        let mut retv = None;
        match node.tally {
            Some(ref mut old) => retv = Some(mem::replace(old, tally)),
            None => node.tally = Some(tally)
        }

        retv
    }

    /// Assigns a score to each potential hyphenation point.
    ///
    /// All patterns matching a substring of `word` are compounded, and for
    /// each hyphenation point, the highest competing value is selected.
    fn score(&self, word: &str) -> Self::Score {
        let w = match word.chars().any(|c| c.is_uppercase()) {
            true => Cow::Owned(word.to_lowercase()),
            false => Cow::Borrowed(word)
        };
        let match_str = [".", w.as_ref(), "."].concat();
        let match_length = match_str.len();

        if match_length <= 3 {
            return vec![];
        }

        let hyphenable_length = match_length - 2;
        let mut points: Vec<u8> = vec![0; hyphenable_length - 1];

        for i in 0..match_length {
            let mut m = &self.descendants;
            for b in match_str.bytes().skip(i) {
                match m.get(&b) {
                    Some(&Patterns { tally: Some(ref t), descendants: ref m1 }) => {
                        m = m1;
                        for (j, &p) in t.iter().enumerate() {
                            let k = i + j;
                            if k > 1 && k <= hyphenable_length {
                                let p1 = points[k - 2];
                                points[k - 2] = max(p, p1)
                            }
                        }
                    },
                    Some(patterns) => m = &patterns.descendants,
                    _ => break
                }
            }
        }

        points
    }

    fn is_empty(&self) -> bool {
        self.descendants.is_empty()
    }
}

impl<'a> KLPTrie<'a> for Exceptions {
    type Score = Option<&'a Vec<u8>>;

    /// Creates an empty `Exceptions` map.
    fn new() -> Exceptions {
        Exceptions(HashMap::new())
    }

    /// Inserts a Knuth-Liang exception pair into the map.
    ///
    /// If the pattern already exists, the old score is returned; if not, `None` is.
    fn insert(&mut self, (pattern, score): KLPair) -> Option<Vec<u8>> {
        let Exceptions(ref mut m) = *self;

        m.insert(pattern, score)
    }

    /// Retrieves the score for each hyphenation point of `word`.
    fn score(&'a self, word: &str) -> Self::Score {
        let Exceptions(ref m) = *self;
        let w = match word.chars().any(|c| c.is_uppercase()) {
            true => Cow::Owned(word.to_lowercase()),
            false => Cow::Borrowed(word)
        };

        m.get(w.as_ref())
    }

    fn is_empty(&self) -> bool {
        self.0.is_empty()
    }
}
<|endoftext|>


<commit_before>//! Package up unwind recovery. Note that if you are in some sensitive
//! place, you can use the `AbortIfPanic` helper to protect against
//! accidental panics in the rayon code itself.

#[cfg(any(not(target_arch = "wasm32"), target_os = "emscripten"))]
use libc;
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
use std::process;
use std::any::Any;
use std::panic::{self, AssertUnwindSafe};
use std::io::stderr;
use std::io::prelude::*;
use std::thread;

/// Executes `f` and captures any panic, translating that panic into a
/// `Err` result. The assumption is that any panic will be propagated
/// later with `resume_unwinding`, and hence `f` can be treated as
/// exception safe.
pub fn halt_unwinding<F, R>(func: F) -> thread::Result<R>
    where F: FnOnce() -> R
{
    panic::catch_unwind(AssertUnwindSafe(func))
}

pub fn resume_unwinding(payload: Box<Any + Send>) -> ! {
    panic::resume_unwind(payload)
}

pub struct AbortIfPanic;

impl Drop for AbortIfPanic {
    fn drop(&mut self) {
        let _ = writeln!(&mut stderr(), "Rayon: detected unexpected panic; aborting");
        #[cfg(any(not(target_arch = "wasm32"), target_os = "emscripten"))]
        unsafe {
            libc::abort();
        }
        #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
        process::abort();
    }
}
<commit_msg>Move wasm cfg to items for rust 1.12 compat<commit_after>//! Package up unwind recovery. Note that if you are in some sensitive
//! place, you can use the `AbortIfPanic` helper to protect against
//! accidental panics in the rayon code itself.

use std::any::Any;
use std::panic::{self, AssertUnwindSafe};
use std::io::stderr;
use std::io::prelude::*;
use std::thread;

/// Executes `f` and captures any panic, translating that panic into a
/// `Err` result. The assumption is that any panic will be propagated
/// later with `resume_unwinding`, and hence `f` can be treated as
/// exception safe.
pub fn halt_unwinding<F, R>(func: F) -> thread::Result<R>
    where F: FnOnce() -> R
{
    panic::catch_unwind(AssertUnwindSafe(func))
}

pub fn resume_unwinding(payload: Box<Any + Send>) -> ! {
    panic::resume_unwind(payload)
}

pub struct AbortIfPanic;

fn aborting() {
    let _ = writeln!(&mut stderr(), "Rayon: detected unexpected panic; aborting");
}

impl Drop for AbortIfPanic {
    #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
    fn drop(&mut self) {
        aborting();
        ::std::process::abort(); // stable in rust 1.17
    }

    #[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))]
    fn drop(&mut self) {
        aborting();
        unsafe {
            ::libc::abort(); // used for compat before 1.17
        }
    }
}
<|endoftext|>


<commit_before>extern crate diesel;
extern crate dotenv;
use self::diesel::*;
use self::dotenv::dotenv;
use std::{env, io};

#[cfg(not(any(feature = "mysql", feature = "sqlite", feature = "postgres")))]
compile_error!(
    "At least one backend must be used to test this crate.\n \
     Pass argument `--features \"<backend>\"` with one or more of the following backends, \
     'mysql', 'postgres', or 'sqlite'. \n\n \
     ex. cargo test --features \"mysql postgres sqlite\"\n"
);

#[cfg(feature = "postgres")]
fn connection() -> PgConnection {
    let database_url = database_url_from_env("PG_DATABASE_URL");
    PgConnection::establish(&database_url).unwrap()
}

#[cfg(feature = "sqlite")]
fn connection() -> SqliteConnection {
    let database_url = database_url_from_env("SQLITE_DATABASE_URL");
    SqliteConnection::establish(&database_url).unwrap()
}

#[cfg(feature = "mysql")]
fn connection() -> MysqlConnection {
    let database_url = database_url_from_env("MYSQL_DATABASE_URL");
    MysqlConnection::establish(&database_url).unwrap()
}

#[cfg(feature = "postgres")]
const MIGRATION_SUBDIR: &'static str = "postgresql";

#[cfg(feature = "sqlite")]
const MIGRATION_SUBDIR: &'static str = "sqlite";

#[cfg(feature = "mysql")]
const MIGRATION_SUBDIR: &'static str = "mysql";

fn database_url_from_env(backend_specific_env_var: &str) -> String {
    dotenv().ok();
    match env::var(backend_specific_env_var) {
        Ok(val) => {
            println!(r#"cargo:rustc-cfg=feature="backend_specific_database_url""#);
            val
        }
        _ => env::var("DATABASE_URL").expect("DATABASE_URL must be set in order to run tests"),
    }
}

fn main() {
    let migrations_dir = migrations::find_migrations_directory()
        .unwrap()
        .join(MIGRATION_SUBDIR);
    println!("cargo:rerun-if-changed={}", MIGRATION_SUBDIR);
    migrations::run_pending_migrations_in_directory(
        &connection(),
        &migrations_dir,
        &mut io::sink(),
    ).unwrap();
}
<commit_msg>Stop recompiling, I have shit to do<commit_after>extern crate diesel;
extern crate dotenv;
use self::diesel::*;
use self::dotenv::dotenv;
use std::{env, io};

#[cfg(not(any(feature = "mysql", feature = "sqlite", feature = "postgres")))]
compile_error!(
    "At least one backend must be used to test this crate.\n \
     Pass argument `--features \"<backend>\"` with one or more of the following backends, \
     'mysql', 'postgres', or 'sqlite'. \n\n \
     ex. cargo test --features \"mysql postgres sqlite\"\n"
);

#[cfg(feature = "postgres")]
fn connection() -> PgConnection {
    let database_url = database_url_from_env("PG_DATABASE_URL");
    PgConnection::establish(&database_url).unwrap()
}

#[cfg(feature = "sqlite")]
fn connection() -> SqliteConnection {
    let database_url = database_url_from_env("SQLITE_DATABASE_URL");
    SqliteConnection::establish(&database_url).unwrap()
}

#[cfg(feature = "mysql")]
fn connection() -> MysqlConnection {
    let database_url = database_url_from_env("MYSQL_DATABASE_URL");
    MysqlConnection::establish(&database_url).unwrap()
}

#[cfg(feature = "postgres")]
const MIGRATION_SUBDIR: &'static str = "postgresql";

#[cfg(feature = "sqlite")]
const MIGRATION_SUBDIR: &'static str = "sqlite";

#[cfg(feature = "mysql")]
const MIGRATION_SUBDIR: &'static str = "mysql";

fn database_url_from_env(backend_specific_env_var: &str) -> String {
    dotenv().ok();
    match env::var(backend_specific_env_var) {
        Ok(val) => {
            println!(r#"cargo:rustc-cfg=feature="backend_specific_database_url""#);
            val
        }
        _ => env::var("DATABASE_URL").expect("DATABASE_URL must be set in order to run tests"),
    }
}

fn main() {
    let migrations_dir = migrations::find_migrations_directory()
        .unwrap()
        .join(MIGRATION_SUBDIR);
    println!("cargo:rerun-if-changed={}", migrations_dir.display());
    migrations::run_pending_migrations_in_directory(
        &connection(),
        &migrations_dir,
        &mut io::sink(),
    ).unwrap();
}
<|endoftext|>


<commit_before>//! Private utility module for working with UIDs

use std::borrow::Cow;

pub(crate) fn trim_uid<'a>(uid: Cow<'a, str>) -> Cow<'a, str> {
    if uid.ends_with('\0') {
        Cow::Owned(uid.trim_end_matches(|c| c == '\0').to_string())
    } else {
        uid
    }
}

#[cfg(test)]
mod tests {
    use std::borrow::Cow;

    use super::trim_uid;

    #[test]
    fn test_trim_uid() {
        let uid = trim_uid(Cow::from("1.2.3.4"));
        assert_eq!(uid, "1.2.3.4");
        let uid = trim_uid(Cow::from("1.2.3.4\0"));
        assert_eq!(uid, "1.2.3.4");
        let uid = trim_uid(Cow::from("1.2.3.45\0"));
        assert_eq!(uid, "1.2.3.45");
    }
}<commit_msg>[ul] elide lifetime in uid::trim_uid<commit_after>//! Private utility module for working with UIDs

use std::borrow::Cow;

pub(crate) fn trim_uid(uid: Cow<str>) -> Cow<str> {
    if uid.ends_with('\0') {
        Cow::Owned(uid.trim_end_matches(|c| c == '\0').to_string())
    } else {
        uid
    }
}

#[cfg(test)]
mod tests {
    use std::borrow::Cow;

    use super::trim_uid;

    #[test]
    fn test_trim_uid() {
        let uid = trim_uid(Cow::from("1.2.3.4"));
        assert_eq!(uid, "1.2.3.4");
        let uid = trim_uid(Cow::from("1.2.3.4\0"));
        assert_eq!(uid, "1.2.3.4");
        let uid = trim_uid(Cow::from("1.2.3.45\0"));
        assert_eq!(uid, "1.2.3.45");
    }
}<|endoftext|>


<commit_before>use core::ptr;

#[lang="stack_exhausted"]
extern "C" fn stack_exhausted() {}

#[lang="eh_personality"]
extern "C" fn eh_personality() {}

#[no_mangle]
pub unsafe extern "C" fn memcmp(a: *mut i8, b: *const i8, len: usize) -> i32 {
    for i in 0..len {
        let c_a = ptr::read(a.offset(i as isize));
        let c_b = ptr::read(b.offset(i as isize));
        if c_a != c_b {
            return c_a as i32 - c_b as i32;
        }
    }
    return 0;
}

#[no_mangle]
pub unsafe extern "C" fn memmove(dst: *mut u8, src: *const u8, len: usize) {
    if src < dst {
        for i_reverse in 0..len as isize {
            let i = len as isize - i_reverse - 1;
            ptr::write(dst.offset(i), ptr::read(src.offset(i)));
        }
    } else {
        for i in 0..len as isize {
            ptr::write(dst.offset(i), ptr::read(src.offset(i)));
        }
    }
}

#[no_mangle]
pub unsafe extern "C" fn memcpy(dst: *mut u8, src: *const u8, len: usize) {
    for i in 0..len as isize {
        ptr::write(dst.offset(i), ptr::read(src.offset(i)));
    }
}

#[no_mangle]
pub unsafe extern "C" fn memset(dst: *mut u8, c: i32, len: usize) {
    for i in 0..len as isize {
        ptr::write(dst.offset(i), c as u8);
    }
}

#[no_mangle]
#[cfg(target_arch = "x86")]
/// 64 bit remainder on 32 bit arch
pub extern "C" fn __umoddi3(mut a: u64, mut b: u64) -> u64 {
    let mut hig = a >> 32; // The first 32 bits of a
    let mut d = 1;

    if hig >= b {
        hig /= b;
        a -= (hig * b) << 32;
    }

    while b > 0 && b < a {
        b *= 2;
        d *= 2;
    }

    loop {
        if a >= b {
            a -= b;
        }
        b >>= 1;
        d >>= 1;

        if d == 0 {
            break;
        }
    }

    a
}

#[no_mangle]
#[cfg(target_arch = "x86")]
/// 64 bit division on 32 bit arch
pub extern "C" fn __udivdi3(mut a: u64, mut b: u64) -> u64 {
    let mut res = 0;
    let mut hig = a >> 32; // The first 32 bits of a
    let mut d = 1;

    if hig >= b {
        hig /= b;
        res = hig << 32;
        a -= (hig * b) << 32;
    }

    while b > 0 && b < a {
        b *= 2;
        d *= 2;
    }

    loop {
        if a >= b {
            a -= b;
            res += d;
        }
        b >>= 1;
        d >>= 1;

        if d == 0 {
            break;
        }
    }

    res
}

#[no_mangle]
#[cfg(target_arch = "x86")]
/// 64 bit division and rem on 32 bit arch
pub extern "C" fn __udivremi3(mut a: u64, mut b: u64) -> (u64, u64) {
    let mut res = 0;
    let mut hig = a >> 32; // The first 32 bits of a
    let mut d = 1;

    if hig >= b {
        hig /= b;
        res = hig << 32;
        a -= (hig * b) << 32;
    }

    while b > 0 && b < a {
        b *= 2;
        d *= 2;
    }

    loop {
        if a >= b {
            a -= b;
            res += d;
        }
        b >>= 1;
        d >>= 1;

        if d == 0 {
            break;
        }
    }

    (res, a)
}
<commit_msg>Fix bugs and improve performance in memcmp, memset, memcpy, and memmove<commit_after>#[lang="stack_exhausted"]
extern "C" fn stack_exhausted() {}

#[lang="eh_personality"]
extern "C" fn eh_personality() {}

/// Memcpy
///
/// Copy N bytes of memory from one location to another.
#[no_mangle]
pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8,
                            n: usize) -> *mut u8 {
    let mut i = 0;
    while i < n {
        *dest.offset(i as isize) = *src.offset(i as isize);
        i += 1;
    }

    dest
}

/// Memmove
///
/// Copy N bytes of memory from src to dest. The memory areas may overlap.
#[no_mangle]
pub unsafe extern fn memmove(dest: *mut u8, src: *const u8,
                             n: usize) -> *mut u8 {
    if src < dest as *const u8 {
        let mut i = n;
        while i != 0 {
            i -= 1;
            *dest.offset(i as isize) = *src.offset(i as isize);
        }
    } else {
        let mut i = 0;
        while i < n {
            *dest.offset(i as isize) = *src.offset(i as isize);
            i += 1;
        }
    }

    dest
}

/// Memset
///
/// Fill a block of memory with a specified value.
#[no_mangle]
pub unsafe extern fn memset(s: *mut u8, c: i32, n: usize) -> *mut u8 {
    let mut i = 0;
    while i < n {
        *s.offset(i as isize) = c as u8;
        i += 1;
    }

    s
}

/// Memcmp
///
/// Compare two blocks of memory.
#[no_mangle]
pub unsafe extern fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 {
    let mut i = 0;

    while i < n {
        let a = *s1.offset(i as isize);
        let b = *s2.offset(i as isize);
        if a != b {
            return a as i32 - b as i32
        }
        i += 1;
    }

    0
}

/// 64 bit remainder on 32 bit arch
#[no_mangle]
#[cfg(target_arch = "x86")]
pub extern "C" fn __umoddi3(mut a: u64, mut b: u64) -> u64 {
    let mut hig = a >> 32; // The first 32 bits of a
    let mut d = 1;

    if hig >= b {
        hig /= b;
        a -= (hig * b) << 32;
    }

    while b > 0 && b < a {
        b *= 2;
        d *= 2;
    }

    loop {
        if a >= b {
            a -= b;
        }
        b >>= 1;
        d >>= 1;

        if d == 0 {
            break;
        }
    }

    a
}

/// 64 bit division on 32 bit arch
#[no_mangle]
#[cfg(target_arch = "x86")]
pub extern "C" fn __udivdi3(mut a: u64, mut b: u64) -> u64 {
    let mut res = 0;
    let mut hig = a >> 32; // The first 32 bits of a
    let mut d = 1;

    if hig >= b {
        hig /= b;
        res = hig << 32;
        a -= (hig * b) << 32;
    }

    while b > 0 && b < a {
        b *= 2;
        d *= 2;
    }

    loop {
        if a >= b {
            a -= b;
            res += d;
        }
        b >>= 1;
        d >>= 1;

        if d == 0 {
            break;
        }
    }

    res
}

#[no_mangle]
#[cfg(target_arch = "x86")]
/// 64 bit division and rem on 32 bit arch
pub extern "C" fn __udivremi3(mut a: u64, mut b: u64) -> (u64, u64) {
    let mut res = 0;
    let mut hig = a >> 32; // The first 32 bits of a
    let mut d = 1;

    if hig >= b {
        hig /= b;
        res = hig << 32;
        a -= (hig * b) << 32;
    }

    while b > 0 && b < a {
        b *= 2;
        d *= 2;
    }

    loop {
        if a >= b {
            a -= b;
            res += d;
        }
        b >>= 1;
        d >>= 1;

        if d == 0 {
            break;
        }
    }

    (res, a)
}
<|endoftext|>


<commit_before>//! Run-time feature detection for PowerPC on Linux.

use crate::detect::{Feature, cache};
use super::{auxvec, cpuinfo};

/// Performs run-time feature detection.
#[inline]
pub fn check_for(x: Feature) -> bool {
    cache::test(x as u32, detect_features)
}

/// Try to read the features from the auxiliary vector, and if that fails, try
/// to read them from /proc/cpuinfo.
fn detect_features() -> cache::Initializer {
    let mut value = cache::Initializer::default();
    let enable_feature = |value: &mut cache::Initializer, f, enable| {
        if enable {
            value.set(f as u32);
        }
    };

    // The values are part of the platform-specific [asm/cputable.h][cputable]
    //
    // [cputable]: https://github.com/torvalds/linux/blob/master/arch/powerpc/include/uapi/asm/cputable.h
    if let Ok(auxv) = auxvec::auxv() {
        // note: the PowerPC values are the mask to do the test (instead of the
        // index of the bit to test like in ARM and Aarch64)
        enable_feature(&mut value, Feature::altivec, auxv.hwcap & 0x10000000 != 0);
        enable_feature(&mut value, Feature::vsx, auxv.hwcap & 0x00000080 != 0);
        enable_feature(&mut value, Feature::power8, auxv.hwcap & 0x80000000 != 0);
        return value;
    }

    // PowerPC's /proc/cpuinfo lacks a proper Feature field,
    // but `altivec` support is indicated in the `cpu` field.
    if let Ok(c) = cpuinfo::CpuInfo::new() {
        enable_feature(&mut value, Feature::altivec, c.field("cpu").has("altivec"));
        return value;
    }
    value
}
<commit_msg>Fix detection of power8<commit_after>//! Run-time feature detection for PowerPC on Linux.

use crate::detect::{Feature, cache};
use super::{auxvec, cpuinfo};

/// Performs run-time feature detection.
#[inline]
pub fn check_for(x: Feature) -> bool {
    cache::test(x as u32, detect_features)
}

/// Try to read the features from the auxiliary vector, and if that fails, try
/// to read them from /proc/cpuinfo.
fn detect_features() -> cache::Initializer {
    let mut value = cache::Initializer::default();
    let enable_feature = |value: &mut cache::Initializer, f, enable| {
        if enable {
            value.set(f as u32);
        }
    };

    // The values are part of the platform-specific [asm/cputable.h][cputable]
    //
    // [cputable]: https://github.com/torvalds/linux/blob/master/arch/powerpc/include/uapi/asm/cputable.h
    if let Ok(auxv) = auxvec::auxv() {
        // note: the PowerPC values are the mask to do the test (instead of the
        // index of the bit to test like in ARM and Aarch64)
        enable_feature(&mut value, Feature::altivec, auxv.hwcap & 0x10000000 != 0);
        enable_feature(&mut value, Feature::vsx, auxv.hwcap & 0x00000080 != 0);
        enable_feature(&mut value, Feature::power8, auxv.hwcap2 & 0x80000000 != 0);
        return value;
    }

    // PowerPC's /proc/cpuinfo lacks a proper Feature field,
    // but `altivec` support is indicated in the `cpu` field.
    if let Ok(c) = cpuinfo::CpuInfo::new() {
        enable_feature(&mut value, Feature::altivec, c.field("cpu").has("altivec"));
        return value;
    }
    value
}
<|endoftext|>


<commit_before>extern crate rand;

use std::sync::mpsc::channel;
use std::thread::spawn;

static NTHREADS: i32 = 4;

// Description: Count how many of N uniform draws from a unit square fall
//              within a unit circle
// Input: number of trials to perform
// Output: number of trials that fell within the unit circle
fn monte_carlo_circle(n: i32) -> i32 {
    let mut num_in_circle = 0;
    for _ in 1..n {
        let x = rand::random::<f32>();
        let y = rand::random::<f32>();
        if x * x + y * y < 1. {
            num_in_circle += 1;
        }
    }
    num_in_circle
}

fn main() {
    let n = 10000000;

    // Spawn threads to split up the work. Communicate via a channel, which
    // is a thread-safe, multi-writer, single-reader FIFO.
    let (tx, rx) = channel();
    let chunk_size = n / NTHREADS;
    let mut threads = Vec::with_capacity(NTHREADS as usize);
    for _ in 0..NTHREADS {
        let tx_thread = tx.clone();
        let handle = spawn(move || tx_thread.send(monte_carlo_circle(chunk_size)));
        threads.push(handle);
    }

    // Grab results from the channel and sum them back up.
    let mut total_in_circle = 0;
    for _ in 0..NTHREADS {
        total_in_circle += rx.recv().unwrap();
    }

    // Destroy threads
    while let Some(thread) = threads.pop() {
        thread.join().ok();
    }
    let pi = 4. * total_in_circle as f32 / n as f32;

    println!("π is approximately {}", pi);
}
<commit_msg>monte_carlo_circle.rs: clarify what constitutes a trial<commit_after>extern crate rand;

use std::sync::mpsc::channel;
use std::thread::spawn;

static NTHREADS: i32 = 4;

// Description: Count how many of N uniform draws from a unit square fall
//              within a unit circle
// Input: number of trials to perform, drawing two floats from [0, 1)
// Output: number of trials that fell within the unit circle
fn monte_carlo_circle(n: i32) -> i32 {
    let mut num_in_circle = 0;
    for _ in 1..n {
        let x = rand::random::<f32>();
        let y = rand::random::<f32>();
        if x * x + y * y < 1. {
            num_in_circle += 1;
        }
    }
    num_in_circle
}

fn main() {
    let n = 10000000;

    // Spawn threads to split up the work. Communicate via a channel, which
    // is a thread-safe, multi-writer, single-reader FIFO.
    let (tx, rx) = channel();
    let chunk_size = n / NTHREADS;
    let mut threads = Vec::with_capacity(NTHREADS as usize);
    for _ in 0..NTHREADS {
        let tx_thread = tx.clone();
        let handle = spawn(move || tx_thread.send(monte_carlo_circle(chunk_size)));
        threads.push(handle);
    }

    // Grab results from the channel and sum them back up.
    let mut total_in_circle = 0;
    for _ in 0..NTHREADS {
        total_in_circle += rx.recv().unwrap();
    }

    // Destroy threads
    while let Some(thread) = threads.pop() {
        thread.join().ok();
    }
    let pi = 4. * total_in_circle as f32 / n as f32;

    println!("π is approximately {}", pi);
}
<|endoftext|>


<commit_before><commit_msg>Don't add a lifetime in `#[derive(asn1::Asn1Write)]` (#305)<commit_after><|endoftext|>


<commit_before>//! This module controls the RCC (Reset and Clock Controller), it handles enabling and disabling
//! clocks, setting clock configurations and the reset flags that are set on a reset.

use super::{Peripheral, Register};
use arm::dmb;
use volatile::Volatile;

mod clock_control;
mod config;

mod clock_rate {
  static mut clock_rate: u32 = 0;

  #[inline(never)]
  pub fn get_system_clock_rate() -> u32 {
    unsafe {
      clock_rate
    }
  }

  // For some reason, if we allow rust to inline this function (in the release build) it causes
  // some kind of bug where the clock rate will be seen as the old value even when it is running at
  // a higher frequency, so the timer gets thrown off... We'll have to look into this a bit more to
  // see if we can find another solution, though this one works for now.
  //#[inline(never)]
  pub fn update_system_clock_rate() {
    const HSI_VALUE: u32 = 8_000_000;
    const HSE_VALUE: u32 = 8_000_000;
    const HSI48_VALUE: u32 = 48_000_000;
    use super::Clock;
    use super::super::systick;

    let rcc = super::rcc();
    let rate = match rcc.get_system_clock_source() {
      Clock::HSI => HSI_VALUE,
      Clock::HSE => HSE_VALUE,
      Clock::HSI48 => HSI48_VALUE,
      Clock::PLL => {
        let multiplier = rcc.get_pll_multiplier() as u32;
        let source = rcc.get_pll_source();
        let prediv_factor = rcc.get_pll_prediv_factor() as u32;

        match source {
          Clock::HSE => (HSE_VALUE/prediv_factor) * multiplier,
          Clock::HSI48 => (HSI48_VALUE/prediv_factor) * multiplier,
          Clock::HSI => (HSI_VALUE/2) * multiplier,
          _ => panic!("CRR::update_system_core_clock - invalid clock driving the PLL!"),
        }
      },
      _ => panic!("CRR::update_system_core_clock - invalid clock for the system clock!"),
    };

    unsafe { clock_rate = rate; }
    let systick = systick::systick();
    // Interrupt every milisecond
    systick.set_reload_value(rate / 1000);
  }

}

pub fn rcc() -> RCC {
  RCC::rcc()
}

pub enum Clock {
  HSI,
  HSI48,
  HSI14,
  HSE,
  PLL,
}

/// Reset and Clock Controller
#[derive(Copy, Clone)]
pub struct RCC {
  mem_addr: u32,
  cr: clock_control::ClockControl,
  cfgr: config::ConfigControl,
}

impl Peripheral for RCC {
  unsafe fn mem_addr(&self) -> Volatile<u32> {
    Volatile::new(self.mem_addr as *const u32)
  }
}

impl RCC {
  fn rcc() -> Self {
    const RCC_ADDR: u32 = 0x4002_1000;
    RCC {
      mem_addr: RCC_ADDR,
      cr: clock_control::ClockControl::new(RCC_ADDR),
      cfgr: config::ConfigControl::new(RCC_ADDR),
    }
  }

  /// Enable the specified clock
  pub fn enable_clock(&self, clock: Clock) {
    self.cr.enable_clock(clock);
  }

  /// Disable the specified clock, if the clock cannot be disabled (if it is driving the PLL for
  /// example) then this method will return false, it returns true otherwise
  pub fn disable_clock(&self, clock: Clock) -> bool {
    self.cr.disable_clock(clock)
  }

  /// Return true if the specified clock is enabled
  pub fn clock_is_on(&self, clock: Clock) -> bool {
    self.cr.clock_is_on(clock)
  }

  /// Return true if the specified clock is ready to be used as the system clock
  pub fn clock_is_ready(&self, clock: Clock) -> bool {
    self.cr.clock_is_ready(clock)
  }

  /// Return the clock driving the system clock
  pub fn get_system_clock_source(&self) -> Clock {
    self.cfgr.get_system_clock_source()
  }

  /// Set the system clock source. The system clock can only be run off of the HSI, HSE, PLL or
  /// HSI48 clocks, if another clock is specified the kernel will panic
  pub fn set_system_clock_source(&self, clock: Clock) {
    self.cfgr.set_system_clock_source(clock);
    unsafe { dmb(); }
    clock_rate::update_system_clock_rate();
  }

  /// Get the clock driving the PLL
  pub fn get_pll_source(&self) -> Clock {
    self.cfgr.get_pll_source()
  }

  /// Set the specified clock to drive the PLL, only the HSI, HSE or HSI48 can drive the PLL, if
  /// another clock is specified the kernel will panic.
  pub fn set_pll_source(&self, clock: Clock) {
    self.cfgr.set_pll_source(clock);
  }

  /// Get the current multiplier for the PLL, the multiplier is in a range of [2..16].
  pub fn get_pll_multiplier(&self) -> u8 {
    self.cfgr.get_pll_multiplier()
  }

  /// Set the PLL multiplier, the multiplier specified MUST be within the range of [2..16], if it
  /// is outside of that range the kernel will panic.
  pub fn set_pll_multiplier(&self, mul: u8) {
    self.cfgr.set_pll_multiplier(mul);
  }

  /// Get the current prediv factor for the PLL, the factor is in a range of [1..16].
  pub fn get_pll_prediv_factor(&self) -> u8 {
    self.cfgr.get_pll_prediv_factor()
  }

  /// Set the PLL prediv factor, the factor specified MUST be within the range of [1..16], if it is
  /// outside that range the kernel will panic.
  pub fn set_pll_prediv_factor(&self, factor: u8) {
    self.cfgr.set_pll_prediv_factor(factor);
  }

  pub fn get_system_clock_rate(&self) -> u32 {
    clock_rate::get_system_clock_rate()
  }
}

<commit_msg>explain memory barrier in comments<commit_after>//! This module controls the RCC (Reset and Clock Controller), it handles enabling and disabling
//! clocks, setting clock configurations and the reset flags that are set on a reset.

use super::{Peripheral, Register};
use arm::dmb;
use volatile::Volatile;

mod clock_control;
mod config;

mod clock_rate {
  static mut clock_rate: u32 = 0;

  pub fn get_system_clock_rate() -> u32 {
    unsafe {
      clock_rate
    }
  }

  pub fn update_system_clock_rate() {
    const HSI_VALUE: u32 = 8_000_000;
    const HSE_VALUE: u32 = 8_000_000;
    const HSI48_VALUE: u32 = 48_000_000;
    use super::Clock;
    use super::super::systick;

    let rcc = super::rcc();
    let rate = match rcc.get_system_clock_source() {
      Clock::HSI => HSI_VALUE,
      Clock::HSE => HSE_VALUE,
      Clock::HSI48 => HSI48_VALUE,
      Clock::PLL => {
        let multiplier = rcc.get_pll_multiplier() as u32;
        let source = rcc.get_pll_source();
        let prediv_factor = rcc.get_pll_prediv_factor() as u32;

        match source {
          Clock::HSE => (HSE_VALUE/prediv_factor) * multiplier,
          Clock::HSI48 => (HSI48_VALUE/prediv_factor) * multiplier,
          Clock::HSI => (HSI_VALUE/2) * multiplier,
          _ => panic!("CRR::update_system_core_clock - invalid clock driving the PLL!"),
        }
      },
      _ => panic!("CRR::update_system_core_clock - invalid clock for the system clock!"),
    };

    unsafe { clock_rate = rate; }
    let systick = systick::systick();
    // Interrupt every milisecond
    systick.set_reload_value(rate / 1000);
  }

}

pub fn rcc() -> RCC {
  RCC::rcc()
}

pub enum Clock {
  HSI,
  HSI48,
  HSI14,
  HSE,
  PLL,
}

/// Reset and Clock Controller
#[derive(Copy, Clone)]
pub struct RCC {
  mem_addr: u32,
  cr: clock_control::ClockControl,
  cfgr: config::ConfigControl,
}

impl Peripheral for RCC {
  unsafe fn mem_addr(&self) -> Volatile<u32> {
    Volatile::new(self.mem_addr as *const u32)
  }
}

impl RCC {
  fn rcc() -> Self {
    const RCC_ADDR: u32 = 0x4002_1000;
    RCC {
      mem_addr: RCC_ADDR,
      cr: clock_control::ClockControl::new(RCC_ADDR),
      cfgr: config::ConfigControl::new(RCC_ADDR),
    }
  }

  /// Enable the specified clock
  pub fn enable_clock(&self, clock: Clock) {
    self.cr.enable_clock(clock);
  }

  /// Disable the specified clock, if the clock cannot be disabled (if it is driving the PLL for
  /// example) then this method will return false, it returns true otherwise
  pub fn disable_clock(&self, clock: Clock) -> bool {
    self.cr.disable_clock(clock)
  }

  /// Return true if the specified clock is enabled
  pub fn clock_is_on(&self, clock: Clock) -> bool {
    self.cr.clock_is_on(clock)
  }

  /// Return true if the specified clock is ready to be used as the system clock
  pub fn clock_is_ready(&self, clock: Clock) -> bool {
    self.cr.clock_is_ready(clock)
  }

  /// Return the clock driving the system clock
  pub fn get_system_clock_source(&self) -> Clock {
    self.cfgr.get_system_clock_source()
  }

  /// Set the system clock source. The system clock can only be run off of the HSI, HSE, PLL or
  /// HSI48 clocks, if another clock is specified the kernel will panic
  pub fn set_system_clock_source(&self, clock: Clock) {
    self.cfgr.set_system_clock_source(clock);
    // We need a memory barrier here since the hardware is writing to the system clock bit
    // If we access the register too fast the old value could still be in the cache un-updated,
    // and we could get the wrong system clock when we calculate the clock rate.
    unsafe { dmb(); }
    clock_rate::update_system_clock_rate();
  }

  /// Get the clock driving the PLL
  pub fn get_pll_source(&self) -> Clock {
    self.cfgr.get_pll_source()
  }

  /// Set the specified clock to drive the PLL, only the HSI, HSE or HSI48 can drive the PLL, if
  /// another clock is specified the kernel will panic.
  pub fn set_pll_source(&self, clock: Clock) {
    self.cfgr.set_pll_source(clock);
  }

  /// Get the current multiplier for the PLL, the multiplier is in a range of [2..16].
  pub fn get_pll_multiplier(&self) -> u8 {
    self.cfgr.get_pll_multiplier()
  }

  /// Set the PLL multiplier, the multiplier specified MUST be within the range of [2..16], if it
  /// is outside of that range the kernel will panic.
  pub fn set_pll_multiplier(&self, mul: u8) {
    self.cfgr.set_pll_multiplier(mul);
  }

  /// Get the current prediv factor for the PLL, the factor is in a range of [1..16].
  pub fn get_pll_prediv_factor(&self) -> u8 {
    self.cfgr.get_pll_prediv_factor()
  }

  /// Set the PLL prediv factor, the factor specified MUST be within the range of [1..16], if it is
  /// outside that range the kernel will panic.
  pub fn set_pll_prediv_factor(&self, factor: u8) {
    self.cfgr.set_pll_prediv_factor(factor);
  }

  pub fn get_system_clock_rate(&self) -> u32 {
    clock_rate::get_system_clock_rate()
  }
}

<|endoftext|>


<commit_before>
extern crate serial;

use std::env;
use std::io;
use std::time::Duration;
use std::process::exit;
use std::thread::sleep;

use std::io::prelude::*;
use serial::prelude::*;

fn main() {
    let args: Vec<String> = env::args().skip(1).collect();
    if args.len() != 1 {
        writeln!(io::stderr(), "Program takes exactly one argument. (The serial port)").unwrap();
        exit(1);
    }

    let level = read_level(&mut io::stdin());

    let mut port = serial::open(&args[0]).unwrap();
    let mut settings = serial::PortSettings::default();
    settings.set_char_size(serial::CharSize::Bits8);
    settings.set_parity(serial::Parity::ParityNone);
    settings.set_stop_bits(serial::StopBits::Stop1);
    if let Err(err) = settings.set_baud_rate(serial::BaudRate::Baud9600) {
        return;
    }

    if let Err(err) = port.configure(&settings) {
        return;
    }

    port.set_timeout(Duration::from_millis(10000)).unwrap();

    send_level(&mut port, &level);
}

// Reads level and prepares it to be sent
fn read_level(input: &mut Read) -> String {
    let mut buf = String::new();
    input.read_to_string(&mut buf).unwrap();

    let mut result = String::new();
    let mut width = 0u8;
    let mut height = 0u8;
    for line in buf.trim().lines() {
        result.push_str(line);
        height += 1;
        width = if line.len() as u8 > width {line.len() as u8} else {width};
    }
    format!("{}{}{}", width as char, height as char, result)
}

fn send_level(port: &mut SerialPort, level: &String) -> bool {
    let mut buf = String::new();
    let mut should_send = false;
    for b in port.bytes() {
        match std::char::from_u32(b.unwrap() as u32).unwrap()  {
            '\n' if buf.trim() == "ready" => {
                should_send = true;
                break;
            },
            '\n' => buf.clear(),
            character => buf.push(character),
        }
    }
    if should_send {
        write!(port, "{}", level).unwrap();
        return true;
    }
    return false;
}
<commit_msg>Improved level sender<commit_after>
extern crate serial;

use std::env;
use std::io;
use std::time::Duration;
use std::process::exit;
use std::thread::sleep;

use std::io::prelude::*;
use serial::prelude::*;

fn main() {
    let args: Vec<String> = env::args().skip(1).collect();
    if args.len() != 1 {
        writeln!(io::stderr(), "Program takes exactly one argument. (The serial port)").unwrap();
        exit(1);
    }

    let level = read_level(&mut io::stdin());

    let mut port = serial::open(&args[0]).unwrap();
    let mut settings = serial::PortSettings::default();
    settings.set_char_size(serial::CharSize::Bits8);
    settings.set_parity(serial::Parity::ParityNone);
    settings.set_stop_bits(serial::StopBits::Stop1);
    if let Err(err) = settings.set_baud_rate(serial::BaudRate::Baud9600) {
        return;
    }

    if let Err(err) = port.configure(&settings) {
        return;
    }

    port.set_timeout(Duration::from_millis(10000)).unwrap();

    println!("Level: {} {} {}", level.as_bytes()[0], level.as_bytes()[1], level.split_at(2).1);
    println!("Uploading...");
    if send_level(&mut port, &level) {
        println!("Finished.");
    } else {
        println!("Failed.");
    }

    for b in port.bytes() {
        print!("{}", std::char::from_u32(b.unwrap() as u32).unwrap());
    }
}

// Reads level and prepares it to be sent
fn read_level(input: &mut Read) -> String {
    let mut buf = String::new();
    input.read_to_string(&mut buf).unwrap();

    let mut lines = vec![];
    let mut width = 0u8;
    let mut height = 0u8;
    for line in buf.trim().lines() {
        lines.push(line);
        height += 1;
        width = if line.len() as u8 > width {line.len() as u8} else {width};
    }
    let mut result = String::new();
    for line in lines {
        result.push_str(line);
        let mut w = line.len() as u8;
        println!("Line short by {}", width - w);
        while w < width {
            w+=1;
            result.push('#');
        }
    }
    format!("{}{}{}", width as char, height as char, result)
}

fn send_level(port: &mut SerialPort, level: &String) -> bool {
    let mut buf = String::new();
    let mut should_send = false;
    for b in port.bytes() {
        match std::char::from_u32(b.unwrap() as u32).unwrap()  {
            '\n' if buf.trim() == "ready" => {
                should_send = true;
                break;
            },
            '\n' => buf.clear(),
            character => buf.push(character),
        }
    }
    if should_send {
        write!(port, "{}", level).unwrap();
        return true;
    }
    return false;
}
<|endoftext|>


<commit_before>/// Module to test equality between two AST Nodes.
pub mod eq;

/// Re-export AstEq publicly.
pub use eq::AstEq;

#[cfg(test)]
mod eq_tests;

/// Expression nodes in the AST.
pub mod expression;

/// Reexport expression nodes publicly.
pub use expression::*;

/// Nodes for literal in AST.
pub mod literal;

/// Reexport literal nodes publicly.
pub use literal::*;

/// Statement nodes in the AST.
pub mod statement;

/// Reexport statement nodes publicly.
pub use statement::*;

/// Type nodes in the AST.
pub mod types;

/// Reexport type nodes publicly.
pub use types::*;

/// Pattern matching AST nodes.
pub mod pattern;

/// Reexport pattern nodes publicly.
pub use pattern::*;
<commit_msg>typo<commit_after>/// Module to test equality between two AST Nodes.
pub mod eq;

/// Re-export AstEq publicly.
pub use eq::AstEq;

#[cfg(test)]
mod eq_tests;

/// Expression nodes in the AST.
pub mod expression;

/// Reexport expression nodes publicly.
pub use expression::*;

/// Nodes for literals in AST.
pub mod literal;

/// Reexport literal nodes publicly.
pub use literal::*;

/// Statement nodes in the AST.
pub mod statement;

/// Reexport statement nodes publicly.
pub use statement::*;

/// Type nodes in the AST.
pub mod types;

/// Reexport type nodes publicly.
pub use types::*;

/// Pattern matching AST nodes.
pub mod pattern;

/// Reexport pattern nodes publicly.
pub use pattern::*;
<|endoftext|>


<commit_before>extern crate plank_errors;
extern crate plank_syntax;
extern crate plank_frontend;
extern crate plank_ir;
extern crate plank_interpreter;

mod test_parser;

use std::fs;
use std::io;
use std::io::prelude::*;
use plank_errors::reporter::Diagnostic;

enum BuildError {
    Fail(Vec<Diagnostic>),
    BadIr(plank_ir::ir::Symbol, plank_ir::validation::Error),
}

fn build_code(source: &str) -> Result<plank_ir::Program, BuildError> {
    let reporter = plank_errors::Reporter::new();
    let tokens = plank_syntax::lex(source, reporter.clone());
    let program = plank_syntax::parse(tokens, reporter.clone());
    let ir = plank_frontend::compile(&program, reporter.clone()).map_err(|()| {
        BuildError::Fail(reporter.get_diagnostics())
    })?;
    if let Err((sym, err)) = plank_ir::validate_ir(&ir) {
        return Err(BuildError::BadIr(sym.clone(), err));
    }
    Ok(ir)
}

#[derive(Debug)]
enum TestResult {
    BuildFail(Vec<Diagnostic>),
    IrValidationFail(plank_ir::ir::Symbol, plank_ir::validation::Error),
    BadBuildPass(Vec<test_parser::Error>),
    BuildErrorMismatch(Vec<Diagnostic>, Vec<test_parser::Error>),
    IoMismatch { expected: Vec<u8>, got: Vec<u8> },
    MalformedTest(test_parser::ParseError),
    InterpreterExit(i32),
    InterpreterError(plank_interpreter::Error),
    Ok,
}

fn match_build_errors(expected: Vec<test_parser::Error>, got: Vec<Diagnostic>) -> TestResult {
    let mut unmatched = Vec::new();
    for err in expected {
        let mut matched = false;
        for actual in &got {
            if let Some(span) = actual.primary_span {
                if span.start.line == err.line && actual.message.contains(&err.message) {
                    matched = true;
                    break;
                }
            }
        }
        if !matched {
            unmatched.push(err);
        }
    }
    if unmatched.is_empty() {
        TestResult::Ok
    } else {
        TestResult::BuildErrorMismatch(got, unmatched)
    }
}

fn interpret_program(program: plank_ir::Program, input: Vec<u8>, output: Vec<u8>) -> TestResult {
    let mut input = ::std::io::Cursor::new(input);
    let mut actual_output = Vec::new();
    match plank_interpreter::run_program(&program, &mut input, &mut actual_output) {
        Ok(0) if actual_output == output => TestResult::Ok,
        Ok(0) => TestResult::IoMismatch { expected: output, got: actual_output },
        Ok(code) => TestResult::InterpreterExit(code),
        Err(e) => TestResult::InterpreterError(e),
    }
}

fn run_test(source: &str) -> TestResult {
    let expectation = match test_parser::parse_test(source) {
        Ok(e) => e,
        Err(e) => return TestResult::MalformedTest(e),
    };
    match expectation {
        test_parser::Expectation::BuildErrors(errors) => {
            match build_code(source) {
                Ok(_) => TestResult::BadBuildPass(errors),
                Err(BuildError::Fail(got)) => match_build_errors(errors, got),
                Err(BuildError::BadIr(sym, err)) => TestResult::IrValidationFail(sym, err),
            }
        }
        test_parser::Expectation::Io { input, output} => {
            match build_code(source) {
                Ok(program) => interpret_program(program, input, output),
                Err(BuildError::Fail(e)) => TestResult::BuildFail(e),
                Err(BuildError::BadIr(sym, err)) => TestResult::IrValidationFail(sym, err),
            }
        }
        test_parser::Expectation::BuildSuccess => {
            match build_code(source) {
                Ok(_) => TestResult::Ok,
                Err(BuildError::Fail(e)) => TestResult::BuildFail(e),
                Err(BuildError::BadIr(sym, err)) => TestResult::IrValidationFail(sym, err),
            }
        }
    }
}

fn run_tests() -> io::Result<Vec<(String, String, TestResult)>> {
    let mut test_results = Vec::new();
    for dir in TEST_DIRS {
        for entry in fs::read_dir(dir)? {
            let entry = entry?;
            if !entry.file_type()?.is_file() {
                continue;
            }
            let mut file = fs::File::open(entry.path())?;
            let mut source = String::new();
            file.read_to_string(&mut source)?;
            let test_result = run_test(&source);
            let test_name = entry.path().display().to_string();
            if let TestResult::Ok = test_result {
                println!("test {} ... ok", test_name);
            } else {
                println!("test {} ... FAIL", test_name);
            }
            test_results.push((test_name, source, test_result));
        }
    }
    Ok(test_results)
}

fn print_expected_errors(errors: &[test_parser::Error]) {
    for err in errors {
        println!("at line {}: {}", err.line + 1, err.message);
    }
}

fn print_output(out: &[u8]) {
    for &byte in out {
        if byte < 32 || byte >= 127 || byte == b'\\' {
            print!("\\x{:>02X}", byte);
        } else {
            print!("{}", byte as char);
        }
    }
    println!();
}

fn report_results(results: &[(String, String, TestResult)]) {
    let mut passed = 0;
    for &(ref name, ref source, ref result) in results {
        match *result {
            TestResult::Ok => passed += 1,
            TestResult::BuildFail(ref diagnostics) => {
                println!("========================================");
                println!("test {}", name);
                println!("unexpected build failure");
                plank_errors::printer::print_diagnostics(source, diagnostics);
                println!();
            }
            TestResult::BadBuildPass(ref expected) => {
                println!("========================================");
                println!("test {}", name);
                println!("build passed but expected failure");
                print_expected_errors(expected);
            }
            TestResult::BuildErrorMismatch(ref got, ref expected) => {
                println!("========================================");
                println!("test {}", name);
                println!("build error mismatch");
                println!(">> unmatched errors:");
                print_expected_errors(expected);
                println!(">> actual errors:");
                plank_errors::printer::print_diagnostics(source, got);
                println!();
            }
            TestResult::IoMismatch { ref expected, ref got } => {
                println!("========================================");
                println!("test {}", name);
                println!("wrong output");
                print!("Expected: ");
                print_output(expected);
                print!("Got:      ");
                print_output(got);
                println!();
            }
            TestResult::IrValidationFail(ref sym, ref err) => {
                println!("========================================");
                println!("test {}", name);
                println!("ir validation failed");
                println!("error in symbol {:?}: {:?}", sym, err);
                println!();
            }
            TestResult::MalformedTest(ref err) => {
                println!("========================================");
                println!("test {}", name);
                println!("malformed test");
                println!("{}", err);
                println!();
            }
            TestResult::InterpreterExit(code) => {
                println!("========================================");
                println!("test {}", name);
                println!("interpreted program exited with code {}", code);
                println!();
            }
            TestResult::InterpreterError(ref err) => {
                println!("========================================");
                println!("test {}", name);
                println!("interpreted program crashed");
                match *err {
                    plank_interpreter::Error::BadDeref => {
                        println!("invalid memory access");
                    }
                    plank_interpreter::Error::DivisionByZero => {
                        println!("division by zero");
                    }
                    plank_interpreter::Error::MissingSymbol(_) => {
                        println!("missing symbol definition");
                    }
                    plank_interpreter::Error::Io(ref err) => {
                        println!("io error: {}", err);
                    }
                }
                println!();
            }
        }
    }
    println!("========================================");
    println!("tests:  {}", results.len());
    println!("passed: {}", passed);
    println!("failed: {}", results.len() - passed);
}

fn main() {
    match run_tests() {
        Ok(results) => report_results(&results),
        Err(e) => println!("io error: {}", e),
    }
}

const TEST_DIRS: &'static [&'static str] = &[
    // test examples because obviously we want the
    // examples people come accross to build successfully
    "./examples",
    "./tests/compile-fail",
    "./tests/pass",
];
<commit_msg>fix test runner<commit_after>extern crate plank_errors;
extern crate plank_syntax;
extern crate plank_frontend;
extern crate plank_ir;
extern crate plank_interpreter;

mod test_parser;

use std::fs;
use std::io;
use std::io::prelude::*;
use plank_errors::reporter::Diagnostic;

enum BuildError {
    Fail(Vec<Diagnostic>),
    BadIr(plank_ir::ir::Symbol, plank_ir::validation::Error),
}

fn build_code(source: &str) -> Result<plank_ir::Program, BuildError> {
    let reporter = plank_errors::Reporter::new();
    let tokens = plank_syntax::lex(source, reporter.clone());
    let program = plank_syntax::parse(tokens, reporter.clone());
    let ir = plank_frontend::compile(&program, reporter.clone()).map_err(|()| {
        BuildError::Fail(reporter.get_diagnostics())
    })?;
    if let Err((sym, err)) = plank_ir::validate_ir(&ir) {
        return Err(BuildError::BadIr(sym.clone(), err));
    }
    Ok(ir)
}

#[derive(Debug)]
enum TestResult {
    BuildFail(Vec<Diagnostic>),
    IrValidationFail(plank_ir::ir::Symbol, plank_ir::validation::Error),
    BadBuildPass(Vec<test_parser::Error>),
    BuildErrorMismatch(Vec<Diagnostic>, Vec<test_parser::Error>),
    IoMismatch { expected: Vec<u8>, got: Vec<u8> },
    MalformedTest(test_parser::ParseError),
    InterpreterExit(i32),
    InterpreterError(plank_interpreter::Error),
    Ok,
}

fn match_build_errors(expected: Vec<test_parser::Error>, got: Vec<Diagnostic>) -> TestResult {
    let mut unmatched = Vec::new();
    for err in expected {
        let mut matched = false;
        for actual in &got {
            if let Some(span) = actual.primary_span {
                if span.start.line == err.line && actual.message.contains(&err.message) {
                    matched = true;
                    break;
                }
            }
        }
        if !matched {
            unmatched.push(err);
        }
    }
    if unmatched.is_empty() {
        TestResult::Ok
    } else {
        TestResult::BuildErrorMismatch(got, unmatched)
    }
}

fn interpret_program(program: plank_ir::Program, input: Vec<u8>, output: Vec<u8>) -> TestResult {
    let mut input = ::std::io::Cursor::new(input);
    let mut actual_output = Vec::new();
    match plank_interpreter::run_program(&program, &mut input, &mut actual_output) {
        Ok(0) if actual_output == output => TestResult::Ok,
        Ok(0) => TestResult::IoMismatch { expected: output, got: actual_output },
        Ok(code) => TestResult::InterpreterExit(code),
        Err(e) => TestResult::InterpreterError(e),
    }
}

fn run_test(source: &str) -> TestResult {
    let expectation = match test_parser::parse_test(source) {
        Ok(e) => e,
        Err(e) => return TestResult::MalformedTest(e),
    };
    match expectation {
        test_parser::Expectation::BuildErrors(errors) => {
            match build_code(source) {
                Ok(_) => TestResult::BadBuildPass(errors),
                Err(BuildError::Fail(got)) => match_build_errors(errors, got),
                Err(BuildError::BadIr(sym, err)) => TestResult::IrValidationFail(sym, err),
            }
        }
        test_parser::Expectation::Io { input, output} => {
            match build_code(source) {
                Ok(program) => interpret_program(program, input, output),
                Err(BuildError::Fail(e)) => TestResult::BuildFail(e),
                Err(BuildError::BadIr(sym, err)) => TestResult::IrValidationFail(sym, err),
            }
        }
        test_parser::Expectation::BuildSuccess => {
            match build_code(source) {
                Ok(_) => TestResult::Ok,
                Err(BuildError::Fail(e)) => TestResult::BuildFail(e),
                Err(BuildError::BadIr(sym, err)) => TestResult::IrValidationFail(sym, err),
            }
        }
    }
}

fn run_tests() -> io::Result<Vec<(String, String, TestResult)>> {
    let mut test_results = Vec::new();
    for dir in TEST_DIRS {
        for entry in fs::read_dir(dir)? {
            let entry = entry?;
            if !entry.file_type()?.is_file() {
                continue;
            }
            let mut file = fs::File::open(entry.path())?;
            let mut source = String::new();
            file.read_to_string(&mut source)?;
            let test_result = run_test(&source);
            let test_name = entry.path().display().to_string();
            if let TestResult::Ok = test_result {
                println!("test {} ... ok", test_name);
            } else {
                println!("test {} ... FAIL", test_name);
            }
            test_results.push((test_name, source, test_result));
        }
    }
    Ok(test_results)
}

fn print_expected_errors(errors: &[test_parser::Error]) {
    for err in errors {
        println!("at line {}: {}", err.line + 1, err.message);
    }
}

fn print_output(out: &[u8]) {
    for &byte in out {
        if byte < 32 || byte >= 127 || byte == b'\\' {
            print!("\\x{:>02X}", byte);
        } else {
            print!("{}", byte as char);
        }
    }
    println!();
}

fn report_results(results: &[(String, String, TestResult)]) {
    let mut passed = 0;
    for &(ref name, ref source, ref result) in results {
        match *result {
            TestResult::Ok => passed += 1,
            TestResult::BuildFail(ref diagnostics) => {
                println!("========================================");
                println!("test {}", name);
                println!("unexpected build failure");
                plank_errors::printer::print_diagnostics(source, diagnostics);
                println!();
            }
            TestResult::BadBuildPass(ref expected) => {
                println!("========================================");
                println!("test {}", name);
                println!("build passed but expected failure");
                print_expected_errors(expected);
            }
            TestResult::BuildErrorMismatch(ref got, ref expected) => {
                println!("========================================");
                println!("test {}", name);
                println!("build error mismatch");
                println!(">> unmatched errors:");
                print_expected_errors(expected);
                println!(">> actual errors:");
                plank_errors::printer::print_diagnostics(source, got);
                println!();
            }
            TestResult::IoMismatch { ref expected, ref got } => {
                println!("========================================");
                println!("test {}", name);
                println!("wrong output");
                print!("Expected: ");
                print_output(expected);
                print!("Got:      ");
                print_output(got);
                println!();
            }
            TestResult::IrValidationFail(ref sym, ref err) => {
                println!("========================================");
                println!("test {}", name);
                println!("ir validation failed");
                println!("error in symbol {:?}: {:?}", sym, err);
                println!();
            }
            TestResult::MalformedTest(ref err) => {
                println!("========================================");
                println!("test {}", name);
                println!("malformed test");
                println!("{}", err);
                println!();
            }
            TestResult::InterpreterExit(code) => {
                println!("========================================");
                println!("test {}", name);
                println!("interpreted program exited with code {}", code);
                println!();
            }
            TestResult::InterpreterError(ref err) => {
                println!("========================================");
                println!("test {}", name);
                println!("interpreted program crashed");
                println!("{}", err);
                println!();
            }
        }
    }
    println!("========================================");
    println!("tests:  {}", results.len());
    println!("passed: {}", passed);
    println!("failed: {}", results.len() - passed);
}

fn main() {
    match run_tests() {
        Ok(results) => report_results(&results),
        Err(e) => println!("io error: {}", e),
    }
}

const TEST_DIRS: &'static [&'static str] = &[
    // test examples because obviously we want the
    // examples people come accross to build successfully
    "./examples",
    "./tests/compile-fail",
    "./tests/pass",
];
<|endoftext|>