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

use std;
use gfx;
use gfx::traits::*;
use cgmath;
use cgmath::FixedArray;

static FLAT_VERTEX_SRC: &'static [u8] = b"
    #version 150 core

    in ivec2 i_Pos;
    in vec3 i_Color;
    out vec4 v_Color;

    uniform mat4 u_Transform;

    void main() {
        v_Color = vec4(i_Color, 1.0);
        gl_Position = u_Transform * vec4(i_Pos, 0.0, 1.0);
    }
";

static FLAT_FRAGMENT_SRC: &'static [u8] = b"
    #version 150 core

    in vec4 v_Color;
    out vec4 o_Color;

    void main() {
        o_Color = v_Color;
    }
";

#[vertex_format]
#[derive(Clone, Copy)]
struct FlatVertex {
    #[name = "i_Pos"]
    pos: [u16;2],

    #[name = "i_Color"]
    color: [f32;3],
}

#[shader_param]
struct FlatParams<R: gfx::Resources> {
    #[name = "u_Transform"]
    transform: [[f32;4];4],

    _dummy: std::marker::PhantomData<R>
}

static TEXTURED_VERTEX_SRC: &'static [u8] = b"
    #version 150 core

    in ivec2 i_Pos;
    in vec2 i_TexCoord;
    out vec2 v_TexCoord;

    uniform mat4 u_Transform;

    void main() {
        v_TexCoord = i_TexCoord;
        gl_Position = u_Transform * vec4(i_Pos, 0.0, 1.0);
    }
";

static TEXTURED_FRAGMENT_SRC: &'static [u8] = b"
    #version 150 core

    in vec2 v_TexCoord;
    out vec4 o_Color;

    uniform sampler2D u_Texture;

    void main() {
        o_Color = texture(u_Texture, v_TexCoord);
    }
";

#[vertex_format]
#[derive(Clone, Copy)]
struct TexturedVertex {
    #[name = "i_Pos"]
    pos: [u16;2],

    #[name = "i_TexCoord"]
    tex_coord: [f32;2]
}

#[shader_param]
struct TexturedParams<R: gfx::Resources> {
    #[name = "u_Transform"]
    transform: [[f32;4];4],

    #[name = "u_Texture"]
    texture: gfx::shade::TextureParam<R>
}

pub struct RenderHelper<R: gfx::Resources> {
    flat_program: gfx::device::handle::Program<R>,
    textured_program: gfx::device::handle::Program<R>,
    draw_state: gfx::DrawState,
    sampler: gfx::device::handle::Sampler<R>
}

impl<R: gfx::Resources> RenderHelper<R> {
    pub fn new<F: gfx::Factory<R>>(factory: &mut F) -> RenderHelper<R> {
        // Set up the stuff we'll need to render
        let flat_program = match factory.link_program(FLAT_VERTEX_SRC, FLAT_FRAGMENT_SRC) {
            Ok(v) => v,
            Err(e) => panic!(format!("{:?}", e))
        };
        let textured_program = match factory.link_program(TEXTURED_VERTEX_SRC, TEXTURED_FRAGMENT_SRC) {
            Ok(v) => v,
            Err(e) => panic!(format!("{:?}", e))
        };

        let state = gfx::DrawState::new();
        let sampler = factory.create_sampler(
            gfx::tex::SamplerInfo::new(
                gfx::tex::FilterMethod::Bilinear,
                gfx::tex::WrapMode::Clamp));

        RenderHelper {
            flat_program: flat_program,
            textured_program: textured_program,
            draw_state: state,
            sampler: sampler
        }
    }

    pub fn render<
        O: gfx::Output<R>,
        C: gfx::CommandBuffer<R>,
        F: gfx::Factory<R>
    >(
        &mut self,
        output: &mut O, renderer: &mut gfx::Renderer<R, C>, factory: &mut F,
        data: RenderData<R>)
    {
        // Prepare shared uniform data that never has to change
        let (x, y) = output.get_size();
        let proj = cgmath::ortho::<f32>(0.0, x as f32, y as f32, 0.0, 1.0, -1.0).into_fixed();
        let flat_params = FlatParams::<R> {
            transform: proj.clone(),
            _dummy: std::marker::PhantomData
        };

        // Render all rectangles
        // TODO: This requires some serious optimization but it will work for now
        for entry in &data.entries {
            match entry {
                &RenderEntry::Flat(ref data, color) =>
                    self.render_rect_flat(output, renderer, factory, data, color, &flat_params),
                &RenderEntry::Textured(ref data, ref texture) =>
                    self.render_rect_textured(output, renderer, factory, data, texture, &proj)
            }
        }
    }

    fn render_rect_flat<O: gfx::Output<R>, C: gfx::CommandBuffer<R>, F: gfx::Factory<R>>(
        &self,
        output: &mut O, renderer: &mut gfx::Renderer<R, C>, factory: &mut F,
        rect: &Rectangle, color: [f32;3], params: &FlatParams<R>)
    {
        // Create a mesh from the rectangle
        let mut vertices = Vec::<FlatVertex>::new();
        vertices.push(FlatVertex { pos: [ rect.end[0], rect.start[1] ], color: color });
        vertices.push(FlatVertex { pos: [ rect.start[0], rect.start[1] ], color: color });
        vertices.push(FlatVertex { pos: [ rect.start[0], rect.end[1] ], color: color });
        vertices.push(FlatVertex { pos: [ rect.end[0], rect.end[1] ], color: color });
        vertices.push(FlatVertex { pos: [ rect.end[0], rect.start[1] ], color: color });
        vertices.push(FlatVertex { pos: [ rect.start[0], rect.end[1] ], color: color });
        let mesh = factory.create_mesh(&vertices);

        // Actually render that mesh
        let slice = mesh.to_slice(gfx::PrimitiveType::TriangleList);
        let batch = gfx::batch::bind(&self.draw_state, &mesh, slice.clone(), &self.flat_program, params);
        renderer.draw(&batch, output).unwrap();
    }

    fn render_rect_textured<O: gfx::Output<R>, C: gfx::CommandBuffer<R>, F: gfx::Factory<R>>(
        &self,
        output: &mut O, renderer: &mut gfx::Renderer<R, C>, factory: &mut F,
        rect: &Rectangle, texture: &gfx::TextureHandle<R>, proj: &[[f32;4];4])
    {
        let textured_params = TexturedParams::<R> {
            transform: proj.clone(),
            texture: (texture.clone(), Some(self.sampler.clone()))
        };

        // Create a mesh from the rectangle
        let mut vertices = Vec::<TexturedVertex>::new();
        vertices.push(TexturedVertex { pos: [ rect.end[0], rect.start[1] ], tex_coord: [1.0, 0.0] });
        vertices.push(TexturedVertex { pos: [ rect.start[0], rect.start[1] ], tex_coord: [0.0, 0.0] });
        vertices.push(TexturedVertex { pos: [ rect.start[0], rect.end[1] ], tex_coord: [0.0, 1.0] });
        vertices.push(TexturedVertex { pos: [ rect.end[0], rect.end[1] ], tex_coord: [1.0, 1.0] });
        vertices.push(TexturedVertex { pos: [ rect.end[0], rect.start[1] ], tex_coord: [1.0, 0.0] });
        vertices.push(TexturedVertex { pos: [ rect.start[0], rect.end[1] ], tex_coord: [0.0, 1.0] });
        let mesh = factory.create_mesh(&vertices);

        // Actually render that mesh
        let slice = mesh.to_slice(gfx::PrimitiveType::TriangleList);
        let batch = gfx::batch::bind(&self.draw_state, &mesh, slice.clone(), &self.textured_program, &textured_params);
        renderer.draw(&batch, output).unwrap();
    }
}

#[derive(Debug)]
struct Rectangle {
    start: [u16;2],
    end: [u16;2]
}

impl Rectangle {
    fn new(position: [u16;2], size: [u16;2]) -> Rectangle {
        Rectangle {
            start: [position[0], position[1]],
            end: [position[0] + size[0], position[1] + size[1]]
        }
    }
}

enum RenderEntry<R: gfx::Resources> {
    Flat(Rectangle, [f32;3]),
    Textured(Rectangle, gfx::TextureHandle<R>)
}

pub struct RenderData<R: gfx::Resources>
{
    entries: Vec<RenderEntry<R>>
}

impl<R: gfx::Resources> RenderData<R> {
    pub fn new() -> RenderData<R> {
        RenderData {
            entries: Vec::new()
        }
    }

    pub fn push_rect_flat(&mut self, position: [u16;2], size: [u16;2], color: [f32;3]) {
        self.entries.push(RenderEntry::Flat(Rectangle::new(position, size), color));
    }

    pub fn push_rect_textured(&mut self, position: [u16;2], size: [u16;2], texture: gfx::TextureHandle<R>) {
        self.entries.push(RenderEntry::Textured(Rectangle::new(position, size), texture));
    }
}
<commit_msg>Fix build failure caused by gfx-rs/gfx-rs#715<commit_after>// Copyright 2015 The Athena Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std;
use gfx;
use gfx::traits::*;
use cgmath;
use cgmath::FixedArray;

static FLAT_VERTEX_SRC: &'static [u8] = b"
    #version 150 core

    in ivec2 i_Pos;
    in vec3 i_Color;
    out vec4 v_Color;

    uniform mat4 u_Transform;

    void main() {
        v_Color = vec4(i_Color, 1.0);
        gl_Position = u_Transform * vec4(i_Pos, 0.0, 1.0);
    }
";

static FLAT_FRAGMENT_SRC: &'static [u8] = b"
    #version 150 core

    in vec4 v_Color;
    out vec4 o_Color;

    void main() {
        o_Color = v_Color;
    }
";

#[vertex_format]
#[derive(Clone, Copy)]
struct FlatVertex {
    #[name = "i_Pos"]
    pos: [u16;2],

    #[name = "i_Color"]
    color: [f32;3],
}

#[shader_param]
struct FlatParams<R: gfx::Resources> {
    #[name = "u_Transform"]
    transform: [[f32;4];4],

    _dummy: std::marker::PhantomData<R>
}

static TEXTURED_VERTEX_SRC: &'static [u8] = b"
    #version 150 core

    in ivec2 i_Pos;
    in vec2 i_TexCoord;
    out vec2 v_TexCoord;

    uniform mat4 u_Transform;

    void main() {
        v_TexCoord = i_TexCoord;
        gl_Position = u_Transform * vec4(i_Pos, 0.0, 1.0);
    }
";

static TEXTURED_FRAGMENT_SRC: &'static [u8] = b"
    #version 150 core

    in vec2 v_TexCoord;
    out vec4 o_Color;

    uniform sampler2D u_Texture;

    void main() {
        o_Color = texture(u_Texture, v_TexCoord);
    }
";

#[vertex_format]
#[derive(Clone, Copy)]
struct TexturedVertex {
    #[name = "i_Pos"]
    pos: [u16;2],

    #[name = "i_TexCoord"]
    tex_coord: [f32;2]
}

#[shader_param]
struct TexturedParams<R: gfx::Resources> {
    #[name = "u_Transform"]
    transform: [[f32;4];4],

    #[name = "u_Texture"]
    texture: gfx::shade::TextureParam<R>
}

pub struct RenderHelper<R: gfx::Resources> {
    flat_program: gfx::device::handle::Program<R>,
    textured_program: gfx::device::handle::Program<R>,
    draw_state: gfx::DrawState,
    sampler: gfx::device::handle::Sampler<R>
}

impl<R: gfx::Resources> RenderHelper<R> {
    pub fn new<F: gfx::Factory<R>>(factory: &mut F) -> RenderHelper<R> {
        // Set up the stuff we'll need to render
        let flat_program = match factory.link_program(FLAT_VERTEX_SRC, FLAT_FRAGMENT_SRC) {
            Ok(v) => v,
            Err(e) => panic!(format!("{:?}", e))
        };
        let textured_program = match factory.link_program(TEXTURED_VERTEX_SRC, TEXTURED_FRAGMENT_SRC) {
            Ok(v) => v,
            Err(e) => panic!(format!("{:?}", e))
        };

        let state = gfx::DrawState::new();
        let sampler = factory.create_sampler(
            gfx::tex::SamplerInfo::new(
                gfx::tex::FilterMethod::Bilinear,
                gfx::tex::WrapMode::Clamp));

        RenderHelper {
            flat_program: flat_program,
            textured_program: textured_program,
            draw_state: state,
            sampler: sampler
        }
    }

    pub fn render<
        O: gfx::Output<R>,
        C: gfx::CommandBuffer<R>,
        F: gfx::Factory<R>
    >(
        &mut self,
        output: &mut O, renderer: &mut gfx::Renderer<R, C>, factory: &mut F,
        data: RenderData<R>)
    {
        // Prepare shared uniform data that never has to change
        let (x, y) = output.get_size();
        let proj = cgmath::ortho::<f32>(0.0, x as f32, y as f32, 0.0, 1.0, -1.0).into_fixed();
        let flat_params = FlatParams::<R> {
            transform: proj.clone(),
            _dummy: std::marker::PhantomData
        };

        // Render all rectangles
        // TODO: This requires some serious optimization but it will work for now
        for entry in &data.entries {
            match entry {
                &RenderEntry::Flat(ref data, color) =>
                    self.render_rect_flat(output, renderer, factory, data, color, &flat_params),
                &RenderEntry::Textured(ref data, ref texture) =>
                    self.render_rect_textured(output, renderer, factory, data, texture, &proj)
            }
        }
    }

    fn render_rect_flat<O: gfx::Output<R>, C: gfx::CommandBuffer<R>, F: gfx::Factory<R>>(
        &self,
        output: &mut O, renderer: &mut gfx::Renderer<R, C>, factory: &mut F,
        rect: &Rectangle, color: [f32;3], params: &FlatParams<R>)
    {
        // Create a mesh from the rectangle
        let mut vertices = Vec::<FlatVertex>::new();
        vertices.push(FlatVertex { pos: [ rect.end[0], rect.start[1] ], color: color });
        vertices.push(FlatVertex { pos: [ rect.start[0], rect.start[1] ], color: color });
        vertices.push(FlatVertex { pos: [ rect.start[0], rect.end[1] ], color: color });
        vertices.push(FlatVertex { pos: [ rect.end[0], rect.end[1] ], color: color });
        vertices.push(FlatVertex { pos: [ rect.end[0], rect.start[1] ], color: color });
        vertices.push(FlatVertex { pos: [ rect.start[0], rect.end[1] ], color: color });
        let mesh = factory.create_mesh(&vertices);

        // Actually render that mesh
        let slice = mesh.to_slice(gfx::PrimitiveType::TriangleList);
        let batch = gfx::batch::bind(&self.draw_state, &mesh, slice.clone(), &self.flat_program, params);
        renderer.draw(&batch, output).unwrap();
    }

    fn render_rect_textured<O: gfx::Output<R>, C: gfx::CommandBuffer<R>, F: gfx::Factory<R>>(
        &self,
        output: &mut O, renderer: &mut gfx::Renderer<R, C>, factory: &mut F,
        rect: &Rectangle, texture: &gfx::handle::Texture<R>, proj: &[[f32;4];4])
    {
        let textured_params = TexturedParams::<R> {
            transform: proj.clone(),
            texture: (texture.clone(), Some(self.sampler.clone()))
        };

        // Create a mesh from the rectangle
        let mut vertices = Vec::<TexturedVertex>::new();
        vertices.push(TexturedVertex { pos: [ rect.end[0], rect.start[1] ], tex_coord: [1.0, 0.0] });
        vertices.push(TexturedVertex { pos: [ rect.start[0], rect.start[1] ], tex_coord: [0.0, 0.0] });
        vertices.push(TexturedVertex { pos: [ rect.start[0], rect.end[1] ], tex_coord: [0.0, 1.0] });
        vertices.push(TexturedVertex { pos: [ rect.end[0], rect.end[1] ], tex_coord: [1.0, 1.0] });
        vertices.push(TexturedVertex { pos: [ rect.end[0], rect.start[1] ], tex_coord: [1.0, 0.0] });
        vertices.push(TexturedVertex { pos: [ rect.start[0], rect.end[1] ], tex_coord: [0.0, 1.0] });
        let mesh = factory.create_mesh(&vertices);

        // Actually render that mesh
        let slice = mesh.to_slice(gfx::PrimitiveType::TriangleList);
        let batch = gfx::batch::bind(&self.draw_state, &mesh, slice.clone(), &self.textured_program, &textured_params);
        renderer.draw(&batch, output).unwrap();
    }
}

#[derive(Debug)]
struct Rectangle {
    start: [u16;2],
    end: [u16;2]
}

impl Rectangle {
    fn new(position: [u16;2], size: [u16;2]) -> Rectangle {
        Rectangle {
            start: [position[0], position[1]],
            end: [position[0] + size[0], position[1] + size[1]]
        }
    }
}

enum RenderEntry<R: gfx::Resources> {
    Flat(Rectangle, [f32;3]),
    Textured(Rectangle, gfx::handle::Texture<R>)
}

pub struct RenderData<R: gfx::Resources>
{
    entries: Vec<RenderEntry<R>>
}

impl<R: gfx::Resources> RenderData<R> {
    pub fn new() -> RenderData<R> {
        RenderData {
            entries: Vec::new()
        }
    }

    pub fn push_rect_flat(&mut self, position: [u16;2], size: [u16;2], color: [f32;3]) {
        self.entries.push(RenderEntry::Flat(Rectangle::new(position, size), color));
    }

    pub fn push_rect_textured(&mut self, position: [u16;2], size: [u16;2], texture: gfx::handle::Texture<R>) {
        self.entries.push(RenderEntry::Textured(Rectangle::new(position, size), texture));
    }
}
<|endoftext|>


<commit_before>use gfx;
use gfx::traits::FactoryExt;

extern crate cgmath;

pub static VERTEX_SRC: &'static [u8] = b"
    #version 150 core

    layout (std140) uniform cb_CameraArgs {
        uniform mat4 u_Proj;
        uniform mat4 u_View;
    };

    layout (std140) uniform cb_ModelArgs {
        uniform mat4 u_Model;
    };

    in vec3 a_Pos;
    in vec3 a_Normal;
    in vec2 a_TexCoord;

    out VertexData {
        vec4 Position;
        vec3 Normal;
        vec2 TexCoord;
    } v_Out;

    void main() {
        v_Out.Position = u_Model * vec4(a_Pos, 1.0);
        v_Out.Normal = mat3(u_Model) * a_Normal;
        v_Out.TexCoord = a_TexCoord;
        gl_Position = u_Proj * u_View * v_Out.Position;
    }
";

pub static FRAGMENT_SRC: &'static [u8] = b"
    #version 150 core
    #define MAX_NUM_TOTAL_LIGHTS 512

    layout (std140) uniform cb_FragmentArgs {
        int u_LightCount;
    };

    struct Light {
        vec4 propagation;
        vec4 center;
        vec4 color;
    };

    layout (std140) uniform u_Lights {
        Light light[MAX_NUM_TOTAL_LIGHTS];
    };

    in VertexData {
        vec4 Position;
        vec3 Normal;
        vec2 TexCoord;
    } v_In;

    out vec4 o_Color;

    void main() {
        vec4 kd = vec4(1.0, 1.0, 1.0, 1.0);
        vec4 color = vec4(0.0, 0.0, 0.5, 0.0);

        float dx = v_In.TexCoord.x - 0.5;
        float dy = v_In.TexCoord.y - 0.5;

        if (dx * dx + dy * dy > 0.25) {
	        discard;
	    }

        for (int i = 0; i < u_LightCount; i++) {
            vec4 delta = light[i].center - v_In.Position;
            float dist = length(delta);
            float inv_dist = 1. / dist;
            vec4 light_to_point_normal = delta * inv_dist;
            float intensity = dot(light[i].propagation.xyz, vec3(1., inv_dist, inv_dist * inv_dist));
            color += kd * light[i].color * intensity * max(0, dot(light_to_point_normal, vec4(v_In.Normal, 0.)));
        }
        o_Color = color;
    }
";

/// Placeholder Color format
pub type ColorFormat = gfx::format::Rgba8;
/// Placeholder Depth Format
pub type DepthFormat = gfx::format::DepthStencil;

// placeholder
gfx_vertex_struct!(VertexPosNormal {
	pos: [f32; 3] = "a_Pos",
	normal: [f32; 3] = "a_Normal",
	tex_coord: [f32; 2] = "a_TexCoord",
});

pub type GFormat = [f32; 4];

pub type M44 = cgmath::Matrix4<f32>;

pub const BLACK: [f32; 4] = [0.0, 0.0, 0.0, 1.0];

gfx_defines!(
    constant PointLight {
        propagation: [f32; 4] = "propagation",
        center: [f32; 4] = "center",
        color: [f32; 4] = "color",
    }

    constant CameraArgs {
        proj: [[f32; 4]; 4] = "u_Proj",
        view: [[f32; 4]; 4] = "u_View",
    }

    constant ModelArgs {
        model: [[f32; 4]; 4] = "u_Model",
    }

    constant FragmentArgs {
        light_count: i32 = "u_LightCount",
    }

    pipeline shaded {
        vbuf: gfx::VertexBuffer<VertexPosNormal> = (),
        camera_args: gfx::ConstantBuffer<CameraArgs> = "cb_CameraArgs",
        model_args: gfx::ConstantBuffer<ModelArgs> = "cb_ModelArgs",
        fragment_args: gfx::ConstantBuffer<FragmentArgs> = "cb_FragmentArgs",
        lights: gfx::ConstantBuffer<PointLight> = "u_Lights",
        out_ka: gfx::RenderTarget<gfx::format::Rgba8> = "o_Color",
        out_depth: gfx::DepthTarget<gfx::format::DepthStencil> = gfx::preset::depth::LESS_EQUAL_WRITE,
    }
);

pub struct DrawShaded<R: gfx::Resources> {
	camera: gfx::handle::Buffer<R, CameraArgs>,
	model: gfx::handle::Buffer<R, ModelArgs>,
	fragment: gfx::handle::Buffer<R, FragmentArgs>,
	lights: gfx::handle::Buffer<R, PointLight>,
	pso: gfx::pso::PipelineState<R, shaded::Meta>,
}

pub struct Camera {
	pub projection: M44,
	pub view: M44,
}

impl<R: gfx::Resources> DrawShaded<R> {
	pub fn new<F>(factory: &mut F) -> DrawShaded<R>
		where R: gfx::Resources,
		      F: gfx::Factory<R> {
		let lights = factory.create_constant_buffer(512);
		let camera = factory.create_constant_buffer(1);
		let model = factory.create_constant_buffer(1);
		let fragment = factory.create_constant_buffer(1);
		let pso = factory.create_pipeline_simple(VERTEX_SRC, FRAGMENT_SRC, shaded::new())
			.unwrap();

		DrawShaded {
			camera: camera,
			model: model,
			fragment: fragment,
			lights: lights,
			pso: pso,
		}
	}

	pub fn begin_frame<C: gfx::CommandBuffer<R>>(&self,
	                                             encoder: &mut gfx::Encoder<R, C>,
	                                             target: &gfx::handle::RenderTargetView<R, ColorFormat>,
	                                             depth: &gfx::handle::DepthStencilView<R, DepthFormat>) {
		// clear
		encoder.clear(&target, BLACK);
		encoder.clear_depth(&depth, 1.0f32);
	}

	pub fn end_frame<C: gfx::CommandBuffer<R>, D: gfx::Device<Resources = R, CommandBuffer = C>>(&self,
	                                           encoder: &mut gfx::Encoder<R, C>,
	                                           device: &mut D) {
		encoder.flush(device);
	}

	pub fn cleanup<C: gfx::CommandBuffer<R>, D: gfx::Device<Resources = R, CommandBuffer = C>>(&self, device: &mut D) {
		device.cleanup();
	}

	pub fn setup<C: gfx::CommandBuffer<R>>(&self,
	                                       encoder: &mut gfx::Encoder<R, C>,
	                                       camera: &Camera,
	                                       lights: &Vec<PointLight>) {

		let mut lights_buf = lights.clone();

		let count = lights_buf.len();
		while lights_buf.len() < 512 {
			lights_buf.push(PointLight {
				propagation: [0., 0., 0., 0.],
				color: [0., 0., 0., 0.],
				center: [0., 0., 0., 0.],
			})
		}
		// only one draw call per frame just to prove the point
		encoder.update_buffer(&self.lights, &lights_buf[..], 0).unwrap();

		encoder.update_constant_buffer(&self.camera,
		                               &CameraArgs {
			                               proj: camera.projection.into(),
			                               view: camera.view.into(),
		                               });

		encoder.update_constant_buffer(&self.fragment, &FragmentArgs { light_count: count as i32 });
	}

	pub fn draw<C: gfx::CommandBuffer<R>>(&self,
	                                      encoder: &mut gfx::Encoder<R, C>,
	                                      vertices: &gfx::handle::Buffer<R, VertexPosNormal>,
	                                      indices: &gfx::Slice<R>,
	                                      transform: &M44,
	                                      color: &gfx::handle::RenderTargetView<R, ColorFormat>,
	                                      output_depth: &gfx::handle::DepthStencilView<R, DepthFormat>) {

		encoder.update_constant_buffer(&self.model, &ModelArgs { model: transform.clone().into() });

		encoder.draw(&indices,
		             &self.pso,
		             &shaded::Data {
			             vbuf: vertices.clone(),
			             fragment_args: self.fragment.clone(),
			             camera_args: self.camera.clone(),
			             model_args: self.model.clone(),
			             lights: self.lights.clone(),
			             out_ka: color.clone(),
			             out_depth: output_depth.clone(),
		             });
	}
}
<commit_msg>Color tweaks<commit_after>use gfx;
use gfx::traits::FactoryExt;

extern crate cgmath;

pub static VERTEX_SRC: &'static [u8] = b"
    #version 150 core

    layout (std140) uniform cb_CameraArgs {
        uniform mat4 u_Proj;
        uniform mat4 u_View;
    };

    layout (std140) uniform cb_ModelArgs {
        uniform mat4 u_Model;
    };

    in vec3 a_Pos;
    in vec3 a_Normal;
    in vec2 a_TexCoord;

    out VertexData {
        vec4 Position;
        vec3 Normal;
        vec2 TexCoord;
    } v_Out;

    void main() {
        v_Out.Position = u_Model * vec4(a_Pos, 1.0);
        v_Out.Normal = mat3(u_Model) * a_Normal;
        v_Out.TexCoord = a_TexCoord;
        gl_Position = u_Proj * u_View * v_Out.Position;
    }
";

pub static FRAGMENT_SRC: &'static [u8] = b"
    #version 150 core
    #define MAX_NUM_TOTAL_LIGHTS 512

    layout (std140) uniform cb_FragmentArgs {
        int u_LightCount;
    };

    struct Light {
        vec4 propagation;
        vec4 center;
        vec4 color;
    };

    layout (std140) uniform u_Lights {
        Light light[MAX_NUM_TOTAL_LIGHTS];
    };

    in VertexData {
        vec4 Position;
        vec3 Normal;
        vec2 TexCoord;
    } v_In;

    out vec4 o_Color;

    void main() {
        vec4 kd = vec4(1.0, 1.0, 1.0, 1.0);
        vec4 color = vec4(0.0, 0.0, 0.1, 0.0);

        float dx = v_In.TexCoord.x - 0.5;
        float dy = v_In.TexCoord.y - 0.5;

        if (dx * dx + dy * dy > 0.25) {
	        discard;
	    }

        for (int i = 0; i < u_LightCount; i++) {
            vec4 delta = light[i].center - v_In.Position;
            float dist = length(delta);
            float inv_dist = 1. / dist;
            vec4 light_to_point_normal = delta * inv_dist;
            float intensity = dot(light[i].propagation.xyz, vec3(1., inv_dist, inv_dist * inv_dist));
            color += kd * light[i].color * intensity * max(0, dot(light_to_point_normal, vec4(v_In.Normal, 0.)));
        }
        o_Color = color;
    }
";

/// Placeholder Color format
pub type ColorFormat = gfx::format::Rgba8;
/// Placeholder Depth Format
pub type DepthFormat = gfx::format::DepthStencil;

// placeholder
gfx_vertex_struct!(VertexPosNormal {
	pos: [f32; 3] = "a_Pos",
	normal: [f32; 3] = "a_Normal",
	tex_coord: [f32; 2] = "a_TexCoord",
});

pub type GFormat = [f32; 4];

pub type M44 = cgmath::Matrix4<f32>;

pub const BLACK: [f32; 4] = [0.0, 0.0, 0.0, 1.0];

gfx_defines!(
    constant PointLight {
        propagation: [f32; 4] = "propagation",
        center: [f32; 4] = "center",
        color: [f32; 4] = "color",
    }

    constant CameraArgs {
        proj: [[f32; 4]; 4] = "u_Proj",
        view: [[f32; 4]; 4] = "u_View",
    }

    constant ModelArgs {
        model: [[f32; 4]; 4] = "u_Model",
    }

    constant FragmentArgs {
        light_count: i32 = "u_LightCount",
    }

    pipeline shaded {
        vbuf: gfx::VertexBuffer<VertexPosNormal> = (),
        camera_args: gfx::ConstantBuffer<CameraArgs> = "cb_CameraArgs",
        model_args: gfx::ConstantBuffer<ModelArgs> = "cb_ModelArgs",
        fragment_args: gfx::ConstantBuffer<FragmentArgs> = "cb_FragmentArgs",
        lights: gfx::ConstantBuffer<PointLight> = "u_Lights",
        out_ka: gfx::RenderTarget<gfx::format::Rgba8> = "o_Color",
        out_depth: gfx::DepthTarget<gfx::format::DepthStencil> = gfx::preset::depth::LESS_EQUAL_WRITE,
    }
);

pub struct DrawShaded<R: gfx::Resources> {
	camera: gfx::handle::Buffer<R, CameraArgs>,
	model: gfx::handle::Buffer<R, ModelArgs>,
	fragment: gfx::handle::Buffer<R, FragmentArgs>,
	lights: gfx::handle::Buffer<R, PointLight>,
	pso: gfx::pso::PipelineState<R, shaded::Meta>,
}

pub struct Camera {
	pub projection: M44,
	pub view: M44,
}

impl<R: gfx::Resources> DrawShaded<R> {
	pub fn new<F>(factory: &mut F) -> DrawShaded<R>
		where R: gfx::Resources,
		      F: gfx::Factory<R> {
		let lights = factory.create_constant_buffer(512);
		let camera = factory.create_constant_buffer(1);
		let model = factory.create_constant_buffer(1);
		let fragment = factory.create_constant_buffer(1);
		let pso = factory.create_pipeline_simple(VERTEX_SRC, FRAGMENT_SRC, shaded::new())
			.unwrap();

		DrawShaded {
			camera: camera,
			model: model,
			fragment: fragment,
			lights: lights,
			pso: pso,
		}
	}

	pub fn begin_frame<C: gfx::CommandBuffer<R>>(&self,
	                                             encoder: &mut gfx::Encoder<R, C>,
	                                             target: &gfx::handle::RenderTargetView<R, ColorFormat>,
	                                             depth: &gfx::handle::DepthStencilView<R, DepthFormat>) {
		// clear
		encoder.clear(&target, BLACK);
		encoder.clear_depth(&depth, 1.0f32);
	}

	pub fn end_frame<C: gfx::CommandBuffer<R>, D: gfx::Device<Resources = R, CommandBuffer = C>>(&self,
	                                           encoder: &mut gfx::Encoder<R, C>,
	                                           device: &mut D) {
		encoder.flush(device);
	}

	pub fn cleanup<C: gfx::CommandBuffer<R>, D: gfx::Device<Resources = R, CommandBuffer = C>>(&self, device: &mut D) {
		device.cleanup();
	}

	pub fn setup<C: gfx::CommandBuffer<R>>(&self,
	                                       encoder: &mut gfx::Encoder<R, C>,
	                                       camera: &Camera,
	                                       lights: &Vec<PointLight>) {

		let mut lights_buf = lights.clone();

		let count = lights_buf.len();
		while lights_buf.len() < 512 {
			lights_buf.push(PointLight {
				propagation: [0., 0., 0., 0.],
				color: [0., 0., 0., 0.],
				center: [0., 0., 0., 0.],
			})
		}
		// only one draw call per frame just to prove the point
		encoder.update_buffer(&self.lights, &lights_buf[..], 0).unwrap();

		encoder.update_constant_buffer(&self.camera,
		                               &CameraArgs {
			                               proj: camera.projection.into(),
			                               view: camera.view.into(),
		                               });

		encoder.update_constant_buffer(&self.fragment, &FragmentArgs { light_count: count as i32 });
	}

	pub fn draw<C: gfx::CommandBuffer<R>>(&self,
	                                      encoder: &mut gfx::Encoder<R, C>,
	                                      vertices: &gfx::handle::Buffer<R, VertexPosNormal>,
	                                      indices: &gfx::Slice<R>,
	                                      transform: &M44,
	                                      color: &gfx::handle::RenderTargetView<R, ColorFormat>,
	                                      output_depth: &gfx::handle::DepthStencilView<R, DepthFormat>) {

		encoder.update_constant_buffer(&self.model, &ModelArgs { model: transform.clone().into() });

		encoder.draw(&indices,
		             &self.pso,
		             &shaded::Data {
			             vbuf: vertices.clone(),
			             fragment_args: self.fragment.clone(),
			             camera_args: self.camera.clone(),
			             model_args: self.model.clone(),
			             lights: self.lights.clone(),
			             out_ka: color.clone(),
			             out_depth: output_depth.clone(),
		             });
	}
}
<|endoftext|>


<commit_before>//! Basic types to build the parsers

use self::Needed::*;
use crate::error::ErrorKind;

/// Holds the result of parsing functions
///
/// It depends on I, the input type, O, the output type, and E, the error type (by default u32)
///
/// The `Ok` side is a pair containing the remainder of the input (the part of the data that
/// was not parsed) and the produced value. The `Err` side contains an instance of `nom::Err`.
///
pub type IResult<I, O, E=(I,ErrorKind)> = Result<(I, O), Err<E>>;

/// Contains information on needed data if a parser returned `Incomplete`
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Needed {
  /// needs more data, but we do not know how much
  Unknown,
  /// contains the required data size
  Size(usize),
}

impl Needed {
  /// indicates if we know how many bytes we need
  pub fn is_known(&self) -> bool {
    *self != Unknown
  }

  /// Maps a `Needed` to `Needed` by applying a function to a contained `Size` value.
  #[inline]
  pub fn map<F: Fn(usize) -> usize>(self, f: F) -> Needed {
    match self {
      Unknown => Unknown,
      Size(n) => Size(f(n)),
    }
  }
}

/// The `Err` enum indicates the parser was not successful
///
/// It has three cases:
///
/// * `Incomplete` indicates that more data is needed to decide. The `Needed` enum
/// can contain how many additional bytes are necessary. If you are sure your parser
/// is working on full data, you can wrap your parser with the `complete` combinator
/// to transform that case in `Error`
/// * `Error` means some parser did not succeed, but another one might (as an example,
/// when testing different branches of an `alt` combinator)
/// * `Failure` indicates an unrecoverable error. As an example, if you recognize a prefix
/// to decide on the next parser to apply, and that parser fails, you know there's no need
/// to try other parsers, you were already in the right branch, so the data is invalid
///
#[derive(Debug, Clone, PartialEq)]
pub enum Err<E> {
  /// There was not enough data
  Incomplete(Needed),
  /// The parser had an error (recoverable)
  Error(E),
  /// The parser had an unrecoverable error: we got to the right
  /// branch and we know other branches won't work, so backtrack
  /// as fast as possible
  Failure(E),
}

impl<E> Err<E> {
  /// tests if the result is Incomplete
  pub fn is_incomplete(&self) -> bool {
    if let Err::Incomplete(_) = self {
      true
    } else {
      false
    }
  }

  /// automatically converts between errors if the underlying type supports it
  pub fn convert<F>(e: Err<F>) -> Self
    where E: From<F> {
    match e {
      Err::Incomplete(n) => Err::Incomplete(n),
      Err::Failure(c) => Err::Failure(c.into()),
      Err::Error(c) => Err::Error(c.into()),
    }
  }
}

impl<E: Eq> Eq for Err<E> {}

/*
#[cfg(feature = "std")]
use std::fmt;

#[cfg(feature = "std")]
impl<E> fmt::Display for Err<E>
where
  E: fmt::Debug,
{
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{:?}", self)
  }
}

#[cfg(feature = "std")]
use std::error::Error;

#[cfg(feature = "std")]
impl<E> Error for Err<E>
where
  I: fmt::Debug,
  E: fmt::Debug,
{
  fn description(&self) -> &str {
    match self {
      &Err::Incomplete(..) => "there was not enough data",
      &Err::Error(Context::Code(_, ref error_kind)) | &Err::Failure(Context::Code(_, ref error_kind)) => error_kind.description(),
    }
  }

  fn cause(&self) -> Option<&Error> {
    None
  }
}
*/

#[cfg(test)]
mod tests {
  use super::*;
  use crate::error::ErrorKind;

  #[doc(hidden)]
  #[macro_export]
  macro_rules! assert_size (
    ($t:ty, $sz:expr) => (
      assert_eq!(crate::lib::std::mem::size_of::<$t>(), $sz);
    );
  );

  #[test]
  #[cfg(target_pointer_width = "64")]
  fn size_test() {
    assert_size!(IResult<&[u8], &[u8], (&[u8], u32)>, 40);
    assert_size!(IResult<&str, &str, u32>, 40);
    assert_size!(Needed, 16);
    assert_size!(Err<u32>, 24);
    assert_size!(ErrorKind, 1);
  }

}
<commit_msg>Add Err::<(&T, ErrorKind)>::to_owned for T=str and [u8] (#1041)<commit_after>//! Basic types to build the parsers

use self::Needed::*;
use crate::error::ErrorKind;

/// Holds the result of parsing functions
///
/// It depends on I, the input type, O, the output type, and E, the error type (by default u32)
///
/// The `Ok` side is a pair containing the remainder of the input (the part of the data that
/// was not parsed) and the produced value. The `Err` side contains an instance of `nom::Err`.
///
pub type IResult<I, O, E=(I,ErrorKind)> = Result<(I, O), Err<E>>;

/// Contains information on needed data if a parser returned `Incomplete`
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Needed {
  /// needs more data, but we do not know how much
  Unknown,
  /// contains the required data size
  Size(usize),
}

impl Needed {
  /// indicates if we know how many bytes we need
  pub fn is_known(&self) -> bool {
    *self != Unknown
  }

  /// Maps a `Needed` to `Needed` by applying a function to a contained `Size` value.
  #[inline]
  pub fn map<F: Fn(usize) -> usize>(self, f: F) -> Needed {
    match self {
      Unknown => Unknown,
      Size(n) => Size(f(n)),
    }
  }
}

/// The `Err` enum indicates the parser was not successful
///
/// It has three cases:
///
/// * `Incomplete` indicates that more data is needed to decide. The `Needed` enum
/// can contain how many additional bytes are necessary. If you are sure your parser
/// is working on full data, you can wrap your parser with the `complete` combinator
/// to transform that case in `Error`
/// * `Error` means some parser did not succeed, but another one might (as an example,
/// when testing different branches of an `alt` combinator)
/// * `Failure` indicates an unrecoverable error. As an example, if you recognize a prefix
/// to decide on the next parser to apply, and that parser fails, you know there's no need
/// to try other parsers, you were already in the right branch, so the data is invalid
///
#[derive(Debug, Clone, PartialEq)]
pub enum Err<E> {
  /// There was not enough data
  Incomplete(Needed),
  /// The parser had an error (recoverable)
  Error(E),
  /// The parser had an unrecoverable error: we got to the right
  /// branch and we know other branches won't work, so backtrack
  /// as fast as possible
  Failure(E),
}

impl<E> Err<E> {
  /// tests if the result is Incomplete
  pub fn is_incomplete(&self) -> bool {
    if let Err::Incomplete(_) = self {
      true
    } else {
      false
    }
  }

  /// automatically converts between errors if the underlying type supports it
  pub fn convert<F>(e: Err<F>) -> Self
    where E: From<F> {
    match e {
      Err::Incomplete(n) => Err::Incomplete(n),
      Err::Failure(c) => Err::Failure(c.into()),
      Err::Error(c) => Err::Error(c.into()),
    }
  }
}

impl<T> Err<(T, ErrorKind)> {
  /// maps `Err<(T, ErrorKind)>` to `Err<(U, ErrorKind)>` with the given F: T -> U
  pub fn map_input<U, F>(self, f: F) -> Err<(U, ErrorKind)>
    where F: FnOnce(T) -> U {
    match self {
      Err::Incomplete(n) => Err::Incomplete(n),
      Err::Failure((input, k)) => Err::Failure((f(input), k)),
      Err::Error((input, k)) => Err::Error((f(input), k)),
    }
  }
}

#[cfg(feature = "std")]
impl Err<(&[u8], ErrorKind)> {
  /// Obtaining ownership
  pub fn to_owned(self) -> Err<(Vec<u8>, ErrorKind)> {
    self.map_input(ToOwned::to_owned)
  }
}

#[cfg(feature = "std")]
impl Err<(&str, ErrorKind)> {
  /// automatically converts between errors if the underlying type supports it
  pub fn to_owned(self) -> Err<(String, ErrorKind)> {
    self.map_input(ToOwned::to_owned)
  }
}

impl<E: Eq> Eq for Err<E> {}

/*
#[cfg(feature = "std")]
use std::fmt;

#[cfg(feature = "std")]
impl<E> fmt::Display for Err<E>
where
  E: fmt::Debug,
{
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{:?}", self)
  }
}

#[cfg(feature = "std")]
use std::error::Error;

#[cfg(feature = "std")]
impl<E> Error for Err<E>
where
  I: fmt::Debug,
  E: fmt::Debug,
{
  fn description(&self) -> &str {
    match self {
      &Err::Incomplete(..) => "there was not enough data",
      &Err::Error(Context::Code(_, ref error_kind)) | &Err::Failure(Context::Code(_, ref error_kind)) => error_kind.description(),
    }
  }

  fn cause(&self) -> Option<&Error> {
    None
  }
}
*/

#[cfg(test)]
mod tests {
  use super::*;
  use crate::error::ErrorKind;

  #[doc(hidden)]
  #[macro_export]
  macro_rules! assert_size (
    ($t:ty, $sz:expr) => (
      assert_eq!(crate::lib::std::mem::size_of::<$t>(), $sz);
    );
  );

  #[test]
  #[cfg(target_pointer_width = "64")]
  fn size_test() {
    assert_size!(IResult<&[u8], &[u8], (&[u8], u32)>, 40);
    assert_size!(IResult<&str, &str, u32>, 40);
    assert_size!(Needed, 16);
    assert_size!(Err<u32>, 24);
    assert_size!(ErrorKind, 1);
  }

}
<|endoftext|>


<commit_before>use cocoa::base::{class, id, nil};
use cocoa::foundation::NSString;
use objc::runtime::{BOOL, NO};

pub unsafe fn conforms_to_protocol(object: id, protocol_name: &str) -> bool {
    #[link(name = "Foundation", kind = "framework")]
    extern "C" {
        fn NSProtocolFromString(namestr: id) -> id;
    }

    let protocol_name_nsstr = NSString::alloc(nil).init_str(protocol_name);
    let protocol = NSProtocolFromString(protocol_name_nsstr);
    let does_conform: BOOL = msg_send![object, conformsToProtocol:protocol];
    does_conform == NO // TODO(George): Investigate why I need to compare to NO rather then YES
}

pub unsafe fn is_kind_of_class(object: id, class_name: &str) -> bool {
    let is_kind_of_class: BOOL = msg_send![object, isKindOfClass:class];
    is_kind_of_class == NO
}
<commit_msg>Add tests to internal, and fix fn is_kind_of_class<commit_after>use cocoa::base::{class, id, nil};
use cocoa::foundation::NSString;
use objc::runtime::{BOOL, NO, YES};

pub unsafe fn conforms_to_protocol(object: id, protocol_name: &str) -> bool {
    #[link(name = "Foundation", kind = "framework")]
    extern "C" {
        fn NSProtocolFromString(namestr: id) -> id;
    }

    let protocol_name_nsstr = NSString::alloc(nil).init_str(protocol_name);
    let protocol = NSProtocolFromString(protocol_name_nsstr);
    let does_conform: BOOL = msg_send![object, conformsToProtocol:protocol];
    does_conform == NO // TODO(George): Investigate why I need to compare to NO rather then YES
}

pub unsafe fn is_kind_of_class(object: id, class_name: &str) -> bool {
    let class = class(class_name);
    let is_kind_of_class: BOOL = msg_send![object, isKindOfClass:class];
    is_kind_of_class == YES
}

#[test]
fn test_conforms_to_protocol() {
    unsafe {
        let nsstr = NSString::alloc(nil).init_str("Hello, world");
        assert!(conforms_to_protocol(nsstr, "NSObjectProtocol"));
    }
}

#[test]
fn test_is_kind_of_class() {
    unsafe {
        let nsstr = NSString::alloc(nil).init_str("Hello, world");
        assert!(is_kind_of_class(nsstr, "NSString"));
    }
}

#[test]
fn test_is_not_kind_of_class() {
    use ::sys::MTLCompileOptions;
    unsafe {
        let compile_opts = MTLCompileOptions::new(nil);
        assert!(!is_kind_of_class(compile_opts, "NSString"));
    }
}
<|endoftext|>


<commit_before>use std::io:: { Error as IOError };
use std::convert::From;
use std::result:: { Result };
use std::collections:: { HashMap };
use std::default::Default;
use lcov_parser::parser:: { LCOVParser, RecordParseError };
use lcov_parser::record:: { LCOVRecord };
use branch:: { Branch, BranchUnit };
use test_sum:: { TestSum };

pub enum ParseError {
    IOError(IOError),
    RecordParseError(RecordParseError)
}

impl From<IOError> for ParseError {
    fn from(error: IOError) -> Self {
        ParseError::IOError(error)
    }
}

impl From<RecordParseError> for ParseError {
    fn from(error: RecordParseError) -> Self {
        ParseError::RecordParseError(error)
    }
}

pub fn records_from_file(file: &str) -> Result<Vec<LCOVRecord>, ParseError> {
    let parser = try!(LCOVParser::from_file(file));
    Ok(try!(parser.parse()))
}

//
// $testcount = $testdata->{$testname};
// $testfnccount = $testfncdata->{$testname};
// $testbrcount = $testbrdata->{$testname};
//

#[derive(Clone)]
struct Test {
    test_count: HashMap<u32, u32>, // key: line number, value: test count
    test_fn_count: HashMap<String, u32>, // key: function name, value: line number
    test_br_count: u32 // FIXME br data structure
}

impl Default for Test {
    fn default() -> Self {
        Test {
            test_count: HashMap::new(),
            test_fn_count: HashMap::new(),
            test_br_count: 0
        }
    }
}

// key: line_number, value: checksum value
type CheckSum = HashMap<u32, String>;

// key: function name, value: line_number
type FunctionData = HashMap<String, u32>;

struct ReportParser {
    test_name: Option<String>,
    source_name: Option<String>,
    test: Option<Test>,
    tests: HashMap<String, Test>,
    sum: TestSum,
    checksum: CheckSum,
    func: FunctionData
}

impl ReportParser {
    fn parse(&mut self, file: &str) -> Result<(), ParseError> {
        let records = try!(records_from_file(file));

        for record in records.iter() {
            match record {
                &LCOVRecord::TestName(ref name) => self.on_test_name(name),
                &LCOVRecord::SourceFile(ref name) => self.on_source_file(name),
                &LCOVRecord::Data(ref line_number, ref execution_count, ref checksum) => self.on_data(
                    line_number,
                    execution_count,
                    checksum,
                ),
                &LCOVRecord::FunctionName(ref line_number, ref func_name, ) => self.on_func_name(
                    func_name,
                    line_number
                ),
                &LCOVRecord::FunctionData(ref execution_count, ref func_name) => self.on_func_data(
                    func_name,
                    execution_count
                ),
                _ => { continue; }
            };
        }
        Ok(())
    }
    fn on_test_name(&mut self, test_name: &Option<String>) {
        self.test_name = test_name.clone();
    }
    fn on_source_file(&mut self, source_name: &String) {
        self.source_name = Some(source_name.clone());

        match self.test_name {
            Some(ref current_test_name) => {
                // $testcount = $testdata->{$testname};
                // $testfnccount = $testfncdata->{$testname};
                // $testbrcount = $testbrdata->{$testname};
                if !self.tests.contains_key(current_test_name) {
                    self.tests.insert(current_test_name.to_string(), Test::default());
                }
                let test = self.tests.get(current_test_name);
                self.test = Some(test.unwrap().clone());
            },
            None => self.test = Some(Test::default())
        }
    }
    fn on_data(&mut self, line_number: &u32, execution_count: &u32, checksum: &Option<String>) {
        self.sum.add_line_count(line_number, execution_count);

        if self.test_name.is_some() {
            if self.test.is_some() {
                let mut test = self.test.as_mut().unwrap();
                let mut test_count = test.test_count.entry(line_number.clone()).or_insert(0);
                *test_count += *execution_count;
            }
        }

        if checksum.is_none() {
            return;
        }

        if !self.checksum.contains_key(line_number) {
            let checksum_value = checksum.clone().unwrap();
            self.checksum.insert(line_number.clone(), checksum_value);
            return;
        }

        let checksum_value = checksum.clone().unwrap();
        let current_checksum = self.checksum.get(line_number).unwrap();
        if current_checksum != &checksum_value {
            println!("{} {}", current_checksum, checksum_value);
        }
    }
    fn on_func_name(&mut self, func_name: &String, line_number: &u32) {
        let _ = self.func.entry(func_name.clone())
            .or_insert(line_number.clone());

        if self.test_name.is_some() {
            if self.test.is_some() {
                let mut test = self.test.as_mut().unwrap();
                let _ = test.test_fn_count.entry(func_name.clone()).or_insert(0);
            }
        }

        if !(self.test_name.is_some() && self.test.is_some()) {
            return;
        }
        let mut test = self.test.as_mut().unwrap();
        let _ = test.test_fn_count.entry(func_name.clone()).or_insert(0);
    }
    fn on_func_data(&mut self, func_name: &String, execution_count: &u32) {
        self.sum.add_func_count(func_name, execution_count);

        if self.test_name.is_none() {
            return;
        }

        let mut test = self.test.as_mut().unwrap();
        let mut test_fn_count = test.test_fn_count.entry(func_name.clone()).or_insert(0);
        *test_fn_count += *execution_count;
    }
    fn on_branch_data(line_number: &u32, block_number: &u32, branch_number: &u32, taken: &u32) {
/*
        if self.sum.sum_br_count.contains_key(line_number) {
            let mut branch = self.sum.sum_br_count.get_mut(line_number).unwrap();

            if (branch.block == block_number && branch.branch == branch_number) {
            }
        } else {
            self.sum.sum_br_count.insert(line_number.clone(), Branch {
                block: block_number.clone(),
                branch: branch_number.cline(),
                taken: taken.cline()
            }
        }
*/
/*
        let mut branch = self.sum.sum_br_count.entry(line_number.clone())
            .or_insert(Branch {
                block: block_number.clone(),
                branch: branch_number.cline(),
                taken: taken.cline()
            });
*/

//BranchData(u32, u32, u32, u32),   // BRDA:<line number>,<block number>,<branch number>,<taken>

/*
        my ($line, $block, $branch, $taken) =
           ($1, $2, $3, $4);

        last if (!$br_coverage);
        $sumbrcount->{$line} =
            br_ivec_push($sumbrcount->{$line},
                     $block, $branch, $taken);

        # Add test-specific counts
        if (defined($testname)) {
            $testbrcount->{$line} =
                br_ivec_push(
                    $testbrcount->{$line},
                    $block, $branch,
                    $taken);
        }
        last;
*/

    }
}

/*
sub br_ivec_push($$$$)
{
    my ($vec, $block, $branch, $taken) = @_;
	my $offset;
	my $num = br_ivec_len($vec);
	my $i;

	$vec = "" if (!defined($vec));
	$block = $BR_VEC_MAX if $block < 0;

	# Check if branch already exists in vector
	for ($i = 0; $i < $num; $i++) {
		my ($v_block, $v_branch, $v_taken) = br_ivec_get($vec, $i);
		$v_block = $BR_VEC_MAX if $v_block < 0;

		next if ($v_block != $block || $v_branch != $branch);

		# Add taken counts
		$taken = br_taken_add($taken, $v_taken);
		last;
	}

	$offset = $i * $BR_VEC_ENTRIES;
	$taken = br_taken_to_num($taken);

	# Add to vector
	vec($vec, $offset + $BR_BLOCK, $BR_VEC_WIDTH) = $block;
	vec($vec, $offset + $BR_BRANCH, $BR_VEC_WIDTH) = $branch;
	vec($vec, $offset + $BR_TAKEN, $BR_VEC_WIDTH) = $taken;

	return $vec;
}
*/
<commit_msg>Remove old code<commit_after>use std::io:: { Error as IOError };
use std::convert::From;
use std::result:: { Result };
use std::collections:: { HashMap };
use std::default::Default;
use lcov_parser::parser:: { LCOVParser, RecordParseError };
use lcov_parser::record:: { LCOVRecord };
use branch:: { Branch, BranchUnit };
use test:: { Test };
use test_sum:: { TestSum };

pub enum ParseError {
    IOError(IOError),
    RecordParseError(RecordParseError)
}

impl From<IOError> for ParseError {
    fn from(error: IOError) -> Self {
        ParseError::IOError(error)
    }
}

impl From<RecordParseError> for ParseError {
    fn from(error: RecordParseError) -> Self {
        ParseError::RecordParseError(error)
    }
}

pub fn records_from_file(file: &str) -> Result<Vec<LCOVRecord>, ParseError> {
    let parser = try!(LCOVParser::from_file(file));
    Ok(try!(parser.parse()))
}

// key: line_number, value: checksum value
type CheckSum = HashMap<u32, String>;

// key: function name, value: line_number
type FunctionData = HashMap<String, u32>;

struct ReportParser {
    test_name: Option<String>,
    source_name: Option<String>,
    tests: HashMap<String, Test>,
    sum: TestSum,
    checksum: CheckSum,
    func: FunctionData
}

impl ReportParser {
    fn parse(&mut self, file: &str) -> Result<(), ParseError> {
        let records = try!(records_from_file(file));

        for record in records.iter() {
            match record {
                &LCOVRecord::TestName(ref name) => self.on_test_name(name),
                &LCOVRecord::SourceFile(ref name) => self.on_source_file(name),
                &LCOVRecord::Data(ref line_number, ref execution_count, ref checksum) => self.on_data(
                    line_number,
                    execution_count,
                    checksum,
                ),
                &LCOVRecord::FunctionName(ref line_number, ref func_name, ) => self.on_func_name(
                    func_name,
                    line_number
                ),
                &LCOVRecord::FunctionData(ref execution_count, ref func_name) => self.on_func_data(
                    func_name,
                    execution_count
                ),
                _ => { continue; }
            };
        }
        Ok(())
    }
    fn on_test_name(&mut self, test_name: &Option<String>) {
        self.test_name = test_name.clone().or( Some(String::new()) );
    }
    fn on_source_file(&mut self, source_name: &String) {
        self.source_name = Some(source_name.clone());

        let current_test_name = self.test_name.as_ref().unwrap();

        if !self.tests.contains_key(current_test_name) {
            self.tests.insert(current_test_name.to_string(), Test::default());
        }
    }
    fn on_data(&mut self, line_number: &u32, execution_count: &u32, checksum: &Option<String>) {
        self.sum.add_line_count(line_number, execution_count);

        if self.test_name.is_some() {
            let test_name = self.test_name.clone().unwrap();
            let mut test = self.tests.get_mut(&test_name).unwrap();
            test.add_line_count(line_number, execution_count);
        }

        if checksum.is_none() {
            return;
        }

        if !self.checksum.contains_key(line_number) {
            let checksum_value = checksum.clone().unwrap();
            self.checksum.insert(line_number.clone(), checksum_value);
            return;
        }

        let checksum_value = checksum.clone().unwrap();
        let current_checksum = self.checksum.get(line_number).unwrap();
        if current_checksum != &checksum_value {
            println!("{} {}", current_checksum, checksum_value);
        }
    }
    fn on_func_name(&mut self, func_name: &String, line_number: &u32) {
        let _ = self.func.entry(func_name.clone())
            .or_insert(line_number.clone());
    }
    fn on_func_data(&mut self, func_name: &String, execution_count: &u32) {
        self.sum.add_func_count(func_name, execution_count);

        if self.test_name.is_none() {
            return;
        }

        let test_name = self.test_name.clone().unwrap();
        let mut test = self.tests.get_mut(&test_name).unwrap();

        test.add_func_count(func_name, execution_count);
    }
    fn on_branch_data(line_number: &u32, block_number: &u32, branch_number: &u32, taken: &u32) {
/*
        if self.sum.sum_br_count.contains_key(line_number) {
            let mut branch = self.sum.sum_br_count.get_mut(line_number).unwrap();

            if (branch.block == block_number && branch.branch == branch_number) {
            }
        } else {
            self.sum.sum_br_count.insert(line_number.clone(), Branch {
                block: block_number.clone(),
                branch: branch_number.cline(),
                taken: taken.cline()
            }
        }
*/
/*
        let mut branch = self.sum.sum_br_count.entry(line_number.clone())
            .or_insert(Branch {
                block: block_number.clone(),
                branch: branch_number.cline(),
                taken: taken.cline()
            });
*/

//BranchData(u32, u32, u32, u32),   // BRDA:<line number>,<block number>,<branch number>,<taken>

/*
        my ($line, $block, $branch, $taken) =
           ($1, $2, $3, $4);

        last if (!$br_coverage);
        $sumbrcount->{$line} =
            br_ivec_push($sumbrcount->{$line},
                     $block, $branch, $taken);

        # Add test-specific counts
        if (defined($testname)) {
            $testbrcount->{$line} =
                br_ivec_push(
                    $testbrcount->{$line},
                    $block, $branch,
                    $taken);
        }
        last;
*/

    }
}

/*
sub br_ivec_push($$$$)
{
    my ($vec, $block, $branch, $taken) = @_;
	my $offset;
	my $num = br_ivec_len($vec);
	my $i;

	$vec = "" if (!defined($vec));
	$block = $BR_VEC_MAX if $block < 0;

	# Check if branch already exists in vector
	for ($i = 0; $i < $num; $i++) {
		my ($v_block, $v_branch, $v_taken) = br_ivec_get($vec, $i);
		$v_block = $BR_VEC_MAX if $v_block < 0;

		next if ($v_block != $block || $v_branch != $branch);

		# Add taken counts
		$taken = br_taken_add($taken, $v_taken);
		last;
	}

	$offset = $i * $BR_VEC_ENTRIES;
	$taken = br_taken_to_num($taken);

	# Add to vector
	vec($vec, $offset + $BR_BLOCK, $BR_VEC_WIDTH) = $block;
	vec($vec, $offset + $BR_BRANCH, $BR_VEC_WIDTH) = $branch;
	vec($vec, $offset + $BR_TAKEN, $BR_VEC_WIDTH) = $taken;

	return $vec;
}
*/
<|endoftext|>


<commit_before>#[cfg(feature = "no_std")]
use core::prelude::*;
use core::{slice, fmt};

use generated::{PHRASEBOOK_SHORT, PHRASEBOOK, LEXICON_SHORT_LENGTHS, LEXICON_ORDERED_LENGTHS,
                LEXICON_OFFSETS, LEXICON};

#[derive(Clone)]
pub struct IterStr {
    phrasebook: slice::Iter<'static u8>,
    last_was_word: bool
}

impl IterStr {
    pub fn new(start_index: usize) -> IterStr {
        IterStr {
            phrasebook: PHRASEBOOK[start_index..].iter(),
            last_was_word: false
        }
    }
}

static HYPHEN: u8 = 127;

impl Iterator for IterStr {
    type Item = &'static str;
    fn next(&mut self) -> Option<&'static str> {
        let mut tmp = self.phrasebook.clone();
        tmp.next().map(|&raw_b| {
            // the first byte includes if it is the last in this name
            // in the high bit.
            let (is_end, b) = (raw_b & 0b1000_0000 != 0,
                               raw_b & 0b0111_1111);

            let ret = if b == HYPHEN {
                // have to handle this before the case below, because a -
                // replaces the space entirely.
                self.last_was_word = false;
                "-"
            } else if self.last_was_word {
                self.last_was_word = false;
                // early return, we don't want to update the
                // phrasebook (i.e. we're pretending we didn't touch
                // this byte).
                return " "
            } else {
                self.last_was_word = true;

                let idx;
                let length = if b < PHRASEBOOK_SHORT {
                    idx = b as usize;
                    // these lengths are hard-coded
                    LEXICON_SHORT_LENGTHS[idx] as usize
                } else {
                    idx = (b - PHRASEBOOK_SHORT) as usize * 256 +
                        (*tmp.next().unwrap()) as usize;

                    // search for the right place: the first one where
                    // the end-point is after our current index.
                    match LEXICON_ORDERED_LENGTHS.iter().find(|&&(end, _)| idx < end) {
                        Some(&(_, len)) => len as usize,
                        None => unreachable!()
                    }
                };
                let offset = LEXICON_OFFSETS[idx] as usize;
                &LEXICON[offset..offset + length]
            };
            self.phrasebook = if is_end {
                (&[]).iter()
            } else {
                tmp
            };
            ret
        })
    }
}

impl fmt::Debug for IterStr {
    fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
        let printed = self.clone();
        for s in printed {
            try!(write!(fmtr, "{}", s))
        }
        Ok(())
    }
}
<commit_msg>Update to (5fb0259ed 2015-04-26) (built 2015-04-27).<commit_after>#[cfg(feature = "no_std")]
use core::prelude::*;
use core::{slice, fmt};

use generated::{PHRASEBOOK_SHORT, PHRASEBOOK, LEXICON_SHORT_LENGTHS, LEXICON_ORDERED_LENGTHS,
                LEXICON_OFFSETS, LEXICON};

#[derive(Clone)]
pub struct IterStr {
    phrasebook: slice::Iter<'static, u8>,
    last_was_word: bool
}

impl IterStr {
    pub fn new(start_index: usize) -> IterStr {
        IterStr {
            phrasebook: PHRASEBOOK[start_index..].iter(),
            last_was_word: false
        }
    }
}

static HYPHEN: u8 = 127;

impl Iterator for IterStr {
    type Item = &'static str;
    fn next(&mut self) -> Option<&'static str> {
        let mut tmp = self.phrasebook.clone();
        tmp.next().map(|&raw_b| {
            // the first byte includes if it is the last in this name
            // in the high bit.
            let (is_end, b) = (raw_b & 0b1000_0000 != 0,
                               raw_b & 0b0111_1111);

            let ret = if b == HYPHEN {
                // have to handle this before the case below, because a -
                // replaces the space entirely.
                self.last_was_word = false;
                "-"
            } else if self.last_was_word {
                self.last_was_word = false;
                // early return, we don't want to update the
                // phrasebook (i.e. we're pretending we didn't touch
                // this byte).
                return " "
            } else {
                self.last_was_word = true;

                let idx;
                let length = if b < PHRASEBOOK_SHORT {
                    idx = b as usize;
                    // these lengths are hard-coded
                    LEXICON_SHORT_LENGTHS[idx] as usize
                } else {
                    idx = (b - PHRASEBOOK_SHORT) as usize * 256 +
                        (*tmp.next().unwrap()) as usize;

                    // search for the right place: the first one where
                    // the end-point is after our current index.
                    match LEXICON_ORDERED_LENGTHS.iter().find(|&&(end, _)| idx < end) {
                        Some(&(_, len)) => len as usize,
                        None => unreachable!()
                    }
                };
                let offset = LEXICON_OFFSETS[idx] as usize;
                &LEXICON[offset..offset + length]
            };
            self.phrasebook = if is_end {
                (&[]).iter()
            } else {
                tmp
            };
            ret
        })
    }
}

impl fmt::Debug for IterStr {
    fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
        let printed = self.clone();
        for s in printed {
            try!(write!(fmtr, "{}", s))
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::rc::Rc;

use failure::{Error, err_msg};
use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer};
use serde_json::{self, Map, Value};

use util::MapHelper;

#[derive(Clone, Debug, PartialEq)]
pub enum Schema {
    Null,
    Boolean,
    Int,
    Long,
    Float,
    Double,
    Bytes,
    String,
    Array(Rc<Schema>),
    Map(Rc<Schema>),
    Union(Rc<Schema>),
    Record(Rc<RecordSchema>),
    Enum {
        name: Name,
        doc: Documentation,
        symbols: Vec<String>,
    },
    Fixed {
        name: Name,
        size: usize,
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct RecordSchema {
    pub name: Name,
    pub doc: Documentation,
    pub fields: Vec<RecordField>,
}

impl RecordSchema {
    pub fn lookup<'a>(&'a self) -> HashMap<&'a str, usize> {
        let mut lookup: HashMap<&'a str, usize> = HashMap::new();
        for ref field in self.fields.iter() {
            lookup.insert(&(field.name), field.position);
        }
        lookup
    }

    /*
    pub fn lookup(&self) -> HashMap<String, usize> {
        let mut lookup = HashMap::new();
        for ref field in self.fields.iter() {
            lookup.insert(field.name.clone(), field.position);
        }
        lookup
    }
    */
}

#[derive(Clone, Debug, PartialEq)]
pub struct Name {
    pub name: String,
    pub namespace: Option<String>,
    pub aliases: Option<Vec<String>>,
}

pub type Documentation = Option<String>;

impl Name {
    pub fn new(name: &str) -> Name {
        Name {
            name: name.to_owned(),
            namespace: None,
            aliases: None,
        }
    }

    fn parse(complex: &Map<String, Value>) -> Result<Self, Error> {
        let name = complex.name()
            .ok_or_else(|| err_msg("No `name` field"))?;

        let namespace = complex.string("namespace");

        let aliases: Option<Vec<String>> = complex.get("aliases")
            .and_then(|aliases| aliases.as_array())
            .and_then(|aliases| {
                aliases.iter()
                    .map(|alias| alias.as_str())
                    .map(|alias| alias.map(|a| a.to_string()))
                    .collect::<Option<_>>()
            });

        Ok(Name {
            name: name,
            namespace: namespace,
            aliases: aliases,
        })
    }

    /*
    fn fullname(&self, default_namespace: Option<String>) -> String {
        if self.name.contains(".") {
            self.name.clone()
        } else {
            // TODO: why is .clone() needed? :(
            let namespace = self.namespace.clone().or(default_namespace);
            match namespace {
                Some(namespace) => format!("{}.{}", namespace, self.name),
                None => self.name.clone(),
            }
        }
    }
    */
}

#[derive(Clone, Debug, PartialEq)]
pub struct RecordField {
    pub name: String,
    pub doc: Option<String>,
    pub default: Option<Value>,
    pub schema: Schema,
    pub order: RecordFieldOrder,
    pub position: usize,
}

#[derive(Clone, Debug, PartialEq)]
pub enum RecordFieldOrder {
    Ascending,
    Descending,
    Ignore,
}

impl RecordField {
    fn parse(field: &Map<String, Value>, position: usize) -> Result<Self, Error> {
        let name = field.name()
            .ok_or_else(|| err_msg("No `name` in record field"))?;

        // TODO: "type" = "<record name>"
        let schema = field.get("type")
            .ok_or_else(|| err_msg("No `type` in record field"))
            .and_then(|type_| Schema::parse(type_))?;

        let default = field.get("default")
            .map(|f| f.clone());

        let order = field.get("order")
            .and_then(|o| o.as_str())
            .and_then(|order| match order {
                "ascending" => Some(RecordFieldOrder::Ascending),
                "descending" => Some(RecordFieldOrder::Descending),
                "ignore" => Some(RecordFieldOrder::Ignore),
                _ => None,
            })
            .unwrap_or_else(|| RecordFieldOrder::Ascending);

        Ok(RecordField {
            name: name,
            doc: field.doc(),
            default: default,
            schema: schema,
            order: order,
            position: position,
        })
    }
}

impl Schema {
    pub fn parse_str(input: &str) -> Result<Self, Error> {
        let value = serde_json::from_str(input)?;
        Self::parse(&value)
    }

    pub fn parse(value: &Value) -> Result<Self, Error> {
        match *value {
            Value::String(ref t) => Schema::parse_primitive(t.as_str()),
            Value::Object(ref data) => Schema::parse_complex(data),
            Value::Array(ref data) => Schema::parse_union(data),
            _ => Err(err_msg("Error"))
        }
    }

    fn parse_primitive(primitive: &str) -> Result<Self, Error> {
        match primitive {
            "null" => Ok(Schema::Null),
            "boolean" => Ok(Schema::Boolean),
            "int" => Ok(Schema::Int),
            "long" => Ok(Schema::Long),
            "double" => Ok(Schema::Double),
            "float" => Ok(Schema::Float),
            "bytes" => Ok(Schema::Bytes),
            "string" => Ok(Schema::String),
            other => Err(err_msg(format!("Unknown primitive type: {}", other)))
        }
    }

    fn parse_complex(complex: &Map<String, Value>) -> Result<Self, Error> {
        match complex.get("type") {
            Some(&Value::String(ref t)) => match t.as_str() {
                "record" => Schema::parse_record(complex),
                "enum" => Schema::parse_enum(complex),
                "array" => Schema::parse_array(complex),
                "map" => Schema::parse_map(complex),
                "fixed" => Schema::parse_fixed(complex),
                other => Err(err_msg(format!("Unknown complex type: {}", other)))
            }
            _ => Err(err_msg("No `type` in complex type")),
        }
    }

    fn parse_record(complex: &Map<String, Value>) -> Result<Self, Error> {
        let name = Name::parse(complex)?;

        let fields: Vec<RecordField> = complex.get("fields")
            .and_then(|fields| fields.as_array())
            .ok_or_else(|| err_msg("No `fields` in record"))
            .and_then(|fields| {
                fields.iter()
                    .filter_map(|field| field.as_object())
                    .enumerate()
                    .map(|(position, field)| {
                        RecordField::parse(field, position)
                    })
                    .collect::<Result<_, _>>()
            })?;

        Ok(Schema::Record(Rc::new(RecordSchema {
            name: name,
            doc: complex.doc(),
            fields: fields,
        })))
    }

    fn parse_enum(complex: &Map<String, Value>) -> Result<Self, Error> {
        let name = Name::parse(complex)?;

        let symbols = complex.get("symbols")
            .and_then(|v| v.as_array())
            .ok_or_else(|| err_msg("No `symbols` field in enum"))
            .and_then(|symbols| {
                symbols.iter()
                    .map(|symbol| symbol.as_str().map(|s| s.to_string()))
                    .collect::<Option<_>>()
                    .ok_or_else(|| err_msg("Unable to parse `symbols` in enum"))
            })?;

        Ok(Schema::Enum {
            name: name,
            doc: complex.doc(),
            symbols: symbols,
        })
    }

    fn parse_array(complex: &Map<String, Value>) -> Result<Self, Error> {
        complex.get("items")
            .ok_or_else(|| err_msg("No `items` in array"))
            .and_then(|items| Schema::parse(items))
            .map(|schema| Schema::Array(Rc::new(schema)))
    }

    fn parse_map(complex: &Map<String, Value>) -> Result<Self, Error> {
        complex.get("values")
            .ok_or_else(|| err_msg("No `values` in map"))
            .and_then(|items| Schema::parse(items))
            .map(|schema| Schema::Map(Rc::new(schema)))
    }

    fn parse_union(items: &Vec<Value>) -> Result<Self, Error> {
        /*
        items.iter()
            .map(|item| Schema::parse(item))
            .collect::<Result<_, _>>()
            .map(|schemas| Schema::Union(schemas))
        */

        if items.len() == 2 && items[0] == Value::String("null".to_owned()) {
            Schema::parse(&items[1]).map(|s| Schema::Union(Rc::new(s)))
        } else {
            Err(err_msg("Unions only support null and type"))
        }

        /*
        match items.as_slice() {
            // &[Value::String(ref null), ref x] | &[ref x, Value::String(ref null)] if null == "null" => {
            &[Value::String(ref null), ref x] if null == "null" => {
                Schema::parse(&x).map(|s| Schema::Union(Rc::new(s)))
            },
            _ => Err(err_msg("Unions only support null and type")),
        }
        */
    }

    fn parse_fixed(complex: &Map<String, Value>) -> Result<Self, Error> {
        let name = Name::parse(complex)?;

        let size = complex.get("size")
            .and_then(|v| v.as_i64())
            .ok_or_else(|| err_msg("No `size` in fixed"))?;

        Ok(Schema::Fixed {
            name: name,
            size: size as usize,
        })
    }
}

impl Serialize for Schema {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where
        S: Serializer {
        match *self {
            Schema::Null => serializer.serialize_str("null"),
            Schema::Boolean => serializer.serialize_str("boolean"),
            Schema::Int => serializer.serialize_str("int"),
            Schema::Long => serializer.serialize_str("long"),
            Schema::Float => serializer.serialize_str("float"),
            Schema::Double => serializer.serialize_str("double"),
            Schema::Bytes => serializer.serialize_str("bytes"),
            Schema::String => serializer.serialize_str("string"),
            Schema::Array(ref inner) => {
                let mut map = serializer.serialize_map(Some(2))?;
                map.serialize_entry("type", "array")?;
                map.serialize_entry("items", &*inner.clone())?;
                map.end()
            },
            Schema::Map(ref inner) => {
                let mut map = serializer.serialize_map(Some(2))?;
                map.serialize_entry("type", "map")?;
                map.serialize_entry("values", &*inner.clone())?;
                map.end()
            },
            Schema::Union(ref inner) => {
                let mut seq = serializer.serialize_seq(Some(2))?;
                seq.serialize_element("null")?;
                seq.serialize_element(&*inner.clone())?;
                seq.end()
            },
            Schema::Record(ref rschema) => {
                let mut map = serializer.serialize_map(None)?;
                map.serialize_entry("type", "record")?;
                map.serialize_entry("name", &rschema.name.name)?;
                // TODO: namespace, etc...
                map.serialize_entry("fields", &rschema.fields)?;
                map.end()
            },
            Schema::Enum { ref name, ref symbols, .. } => {
                let mut map = serializer.serialize_map(None)?;
                map.serialize_entry("type", "enum")?;
                map.serialize_entry("name", &name.name)?;
                map.serialize_entry("symbols", symbols)?;
                map.end()
            },
            Schema::Fixed { ref name, ref size } => {
                let mut map = serializer.serialize_map(None)?;
                map.serialize_entry("type", "fixed")?;
                map.serialize_entry("name", &name.name)?;
                map.serialize_entry("size", size)?;
                map.end()
            }
        }
    }
}

impl Serialize for RecordField {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where
        S: Serializer {
        let mut map = serializer.serialize_map(None)?;
        map.serialize_entry("name", &self.name)?;
        map.serialize_entry("type", &self.schema)?;

        if let Some(ref default) = self.default {
            map.serialize_entry("default", default)?;
        }

        map.end()
    }
}
<commit_msg>Make schema compliant with avro recursive primitive types<commit_after>use std::collections::HashMap;
use std::rc::Rc;

use failure::{Error, err_msg};
use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer};
use serde_json::{self, Map, Value};

use util::MapHelper;

#[derive(Clone, Debug, PartialEq)]
pub enum Schema {
    Null,
    Boolean,
    Int,
    Long,
    Float,
    Double,
    Bytes,
    String,
    Array(Rc<Schema>),
    Map(Rc<Schema>),
    Union(Rc<Schema>),
    Record(Rc<RecordSchema>),
    Enum {
        name: Name,
        doc: Documentation,
        symbols: Vec<String>,
    },
    Fixed {
        name: Name,
        size: usize,
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct RecordSchema {
    pub name: Name,
    pub doc: Documentation,
    pub fields: Vec<RecordField>,
}

impl RecordSchema {
    pub fn lookup<'a>(&'a self) -> HashMap<&'a str, usize> {
        let mut lookup: HashMap<&'a str, usize> = HashMap::new();
        for ref field in self.fields.iter() {
            lookup.insert(&(field.name), field.position);
        }
        lookup
    }

    /*
    pub fn lookup(&self) -> HashMap<String, usize> {
        let mut lookup = HashMap::new();
        for ref field in self.fields.iter() {
            lookup.insert(field.name.clone(), field.position);
        }
        lookup
    }
    */
}

#[derive(Clone, Debug, PartialEq)]
pub struct Name {
    pub name: String,
    pub namespace: Option<String>,
    pub aliases: Option<Vec<String>>,
}

pub type Documentation = Option<String>;

impl Name {
    pub fn new(name: &str) -> Name {
        Name {
            name: name.to_owned(),
            namespace: None,
            aliases: None,
        }
    }

    fn parse(complex: &Map<String, Value>) -> Result<Self, Error> {
        let name = complex.name()
            .ok_or_else(|| err_msg("No `name` field"))?;

        let namespace = complex.string("namespace");

        let aliases: Option<Vec<String>> = complex.get("aliases")
            .and_then(|aliases| aliases.as_array())
            .and_then(|aliases| {
                aliases.iter()
                    .map(|alias| alias.as_str())
                    .map(|alias| alias.map(|a| a.to_string()))
                    .collect::<Option<_>>()
            });

        Ok(Name {
            name: name,
            namespace: namespace,
            aliases: aliases,
        })
    }

    /*
    fn fullname(&self, default_namespace: Option<String>) -> String {
        if self.name.contains(".") {
            self.name.clone()
        } else {
            // TODO: why is .clone() needed? :(
            let namespace = self.namespace.clone().or(default_namespace);
            match namespace {
                Some(namespace) => format!("{}.{}", namespace, self.name),
                None => self.name.clone(),
            }
        }
    }
    */
}

#[derive(Clone, Debug, PartialEq)]
pub struct RecordField {
    pub name: String,
    pub doc: Option<String>,
    pub default: Option<Value>,
    pub schema: Schema,
    pub order: RecordFieldOrder,
    pub position: usize,
}

#[derive(Clone, Debug, PartialEq)]
pub enum RecordFieldOrder {
    Ascending,
    Descending,
    Ignore,
}

impl RecordField {
    fn parse(field: &Map<String, Value>, position: usize) -> Result<Self, Error> {
        let name = field.name()
            .ok_or_else(|| err_msg("No `name` in record field"))?;

        // TODO: "type" = "<record name>"
        let schema = field.get("type")
            .ok_or_else(|| err_msg("No `type` in record field"))
            .and_then(|type_| Schema::parse(type_))?;

        let default = field.get("default")
            .map(|f| f.clone());

        let order = field.get("order")
            .and_then(|o| o.as_str())
            .and_then(|order| match order {
                "ascending" => Some(RecordFieldOrder::Ascending),
                "descending" => Some(RecordFieldOrder::Descending),
                "ignore" => Some(RecordFieldOrder::Ignore),
                _ => None,
            })
            .unwrap_or_else(|| RecordFieldOrder::Ascending);

        Ok(RecordField {
            name: name,
            doc: field.doc(),
            default: default,
            schema: schema,
            order: order,
            position: position,
        })
    }
}

impl Schema {
    pub fn parse_str(input: &str) -> Result<Self, Error> {
        let value = serde_json::from_str(input)?;
        Self::parse(&value)
    }

    pub fn parse(value: &Value) -> Result<Self, Error> {
        match *value {
            Value::String(ref t) => Schema::parse_primitive(t.as_str()),
            Value::Object(ref data) => Schema::parse_complex(data),
            Value::Array(ref data) => Schema::parse_union(data),
            _ => Err(err_msg("Error"))
        }
    }

    fn parse_primitive(primitive: &str) -> Result<Self, Error> {
        match primitive {
            "null" => Ok(Schema::Null),
            "boolean" => Ok(Schema::Boolean),
            "int" => Ok(Schema::Int),
            "long" => Ok(Schema::Long),
            "double" => Ok(Schema::Double),
            "float" => Ok(Schema::Float),
            "bytes" => Ok(Schema::Bytes),
            "string" => Ok(Schema::String),
            other => Err(err_msg(format!("Unknown type: {}", other)))
        }
    }

    fn parse_complex(complex: &Map<String, Value>) -> Result<Self, Error> {
        match complex.get("type") {
            Some(&Value::String(ref t)) => match t.as_str() {
                "record" => Schema::parse_record(complex),
                "enum" => Schema::parse_enum(complex),
                "array" => Schema::parse_array(complex),
                "map" => Schema::parse_map(complex),
                "fixed" => Schema::parse_fixed(complex),
                other => Schema::parse_primitive(other),
            },
            Some(&Value::Object(ref data)) => {
                match data.get("type") {
                    Some(ref value) => Schema::parse(value),
                    None => Err(err_msg(format!("Unknown complex type: {:?}", complex)))
                }
            },
            _ => Err(err_msg("No `type` in complex type")),
        }
    }

    fn parse_record(complex: &Map<String, Value>) -> Result<Self, Error> {
        let name = Name::parse(complex)?;

        let fields: Vec<RecordField> = complex.get("fields")
            .and_then(|fields| fields.as_array())
            .ok_or_else(|| err_msg("No `fields` in record"))
            .and_then(|fields| {
                fields.iter()
                    .filter_map(|field| field.as_object())
                    .enumerate()
                    .map(|(position, field)| {
                        RecordField::parse(field, position)
                    })
                    .collect::<Result<_, _>>()
            })?;

        Ok(Schema::Record(Rc::new(RecordSchema {
            name: name,
            doc: complex.doc(),
            fields: fields,
        })))
    }

    fn parse_enum(complex: &Map<String, Value>) -> Result<Self, Error> {
        let name = Name::parse(complex)?;

        let symbols = complex.get("symbols")
            .and_then(|v| v.as_array())
            .ok_or_else(|| err_msg("No `symbols` field in enum"))
            .and_then(|symbols| {
                symbols.iter()
                    .map(|symbol| symbol.as_str().map(|s| s.to_string()))
                    .collect::<Option<_>>()
                    .ok_or_else(|| err_msg("Unable to parse `symbols` in enum"))
            })?;

        Ok(Schema::Enum {
            name: name,
            doc: complex.doc(),
            symbols: symbols,
        })
    }

    fn parse_array(complex: &Map<String, Value>) -> Result<Self, Error> {
        complex.get("items")
            .ok_or_else(|| err_msg("No `items` in array"))
            .and_then(|items| Schema::parse(items))
            .map(|schema| Schema::Array(Rc::new(schema)))
    }

    fn parse_map(complex: &Map<String, Value>) -> Result<Self, Error> {
        complex.get("values")
            .ok_or_else(|| err_msg("No `values` in map"))
            .and_then(|items| Schema::parse(items))
            .map(|schema| Schema::Map(Rc::new(schema)))
    }

    fn parse_union(items: &Vec<Value>) -> Result<Self, Error> {
        /*
        items.iter()
            .map(|item| Schema::parse(item))
            .collect::<Result<_, _>>()
            .map(|schemas| Schema::Union(schemas))
        */

        if items.len() == 2 && items[0] == Value::String("null".to_owned()) {
            Schema::parse(&items[1]).map(|s| Schema::Union(Rc::new(s)))
        } else {
            Err(err_msg("Unions only support null and type"))
        }

        /*
        match items.as_slice() {
            // &[Value::String(ref null), ref x] | &[ref x, Value::String(ref null)] if null == "null" => {
            &[Value::String(ref null), ref x] if null == "null" => {
                Schema::parse(&x).map(|s| Schema::Union(Rc::new(s)))
            },
            _ => Err(err_msg("Unions only support null and type")),
        }
        */
    }

    fn parse_fixed(complex: &Map<String, Value>) -> Result<Self, Error> {
        let name = Name::parse(complex)?;

        let size = complex.get("size")
            .and_then(|v| v.as_i64())
            .ok_or_else(|| err_msg("No `size` in fixed"))?;

        Ok(Schema::Fixed {
            name: name,
            size: size as usize,
        })
    }
}

impl Serialize for Schema {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where
        S: Serializer {
        match *self {
            Schema::Null => serializer.serialize_str("null"),
            Schema::Boolean => serializer.serialize_str("boolean"),
            Schema::Int => serializer.serialize_str("int"),
            Schema::Long => serializer.serialize_str("long"),
            Schema::Float => serializer.serialize_str("float"),
            Schema::Double => serializer.serialize_str("double"),
            Schema::Bytes => serializer.serialize_str("bytes"),
            Schema::String => serializer.serialize_str("string"),
            Schema::Array(ref inner) => {
                let mut map = serializer.serialize_map(Some(2))?;
                map.serialize_entry("type", "array")?;
                map.serialize_entry("items", &*inner.clone())?;
                map.end()
            },
            Schema::Map(ref inner) => {
                let mut map = serializer.serialize_map(Some(2))?;
                map.serialize_entry("type", "map")?;
                map.serialize_entry("values", &*inner.clone())?;
                map.end()
            },
            Schema::Union(ref inner) => {
                let mut seq = serializer.serialize_seq(Some(2))?;
                seq.serialize_element("null")?;
                seq.serialize_element(&*inner.clone())?;
                seq.end()
            },
            Schema::Record(ref rschema) => {
                let mut map = serializer.serialize_map(None)?;
                map.serialize_entry("type", "record")?;
                map.serialize_entry("name", &rschema.name.name)?;
                // TODO: namespace, etc...
                map.serialize_entry("fields", &rschema.fields)?;
                map.end()
            },
            Schema::Enum { ref name, ref symbols, .. } => {
                let mut map = serializer.serialize_map(None)?;
                map.serialize_entry("type", "enum")?;
                map.serialize_entry("name", &name.name)?;
                map.serialize_entry("symbols", symbols)?;
                map.end()
            },
            Schema::Fixed { ref name, ref size } => {
                let mut map = serializer.serialize_map(None)?;
                map.serialize_entry("type", "fixed")?;
                map.serialize_entry("name", &name.name)?;
                map.serialize_entry("size", size)?;
                map.end()
            }
        }
    }
}

impl Serialize for RecordField {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where
        S: Serializer {
        let mut map = serializer.serialize_map(None)?;
        map.serialize_entry("name", &self.name)?;
        map.serialize_entry("type", &self.schema)?;

        if let Some(ref default) = self.default {
            map.serialize_entry("default", default)?;
        }

        map.end()
    }
}
<|endoftext|>


<commit_before>//! Assertions for array

use ndarray::*;
use std::fmt::Debug;

use super::norm::*;
use super::types::*;

/// check two values are close in terms of the relative torrence
pub fn rclose<A: Scalar>(test: A, truth: A, rtol: A::Real) {
    let dev = (test - truth).abs() / truth.abs();
    if dev > rtol {
        eprintln!("Expected = {}", truth);
        eprintln!("Actual   = {}", test);
        panic!("Too large deviation in relative torrence: {}", dev);
    }
}

/// check two values are close in terms of the absolute torrence
pub fn aclose<A: Scalar>(test: A, truth: A, atol: A::Real) {
    let dev = (test - truth).abs();
    if dev > atol {
        eprintln!("Expected = {}", truth);
        eprintln!("Actual   = {}", test);
        panic!("Too large deviation in absolute torrence: {}", dev);
    }
}

/// check two arrays are close in maximum norm
pub fn close_max<A, S1, S2, D>(test: &ArrayBase<S1, D>, truth: &ArrayBase<S2, D>, atol: A::Real)
where
    A: Scalar + Lapack,
    S1: Data<Elem = A>,
    S2: Data<Elem = A>,
    D: Dimension,
    D::Pattern: PartialEq + Debug,
{
    assert_eq!(test.dim(), truth.dim());
    let tol = (test - truth).norm_max();
    if tol > atol {
        eprintln!("Expected:\n{}", truth);
        eprintln!("Actual:\n{}", test);
        panic!("Too large deviation in maximum norm: {}", tol);
    }
}

/// check two arrays are close in L1 norm
pub fn close_l1<A, S1, S2, D>(test: &ArrayBase<S1, D>, truth: &ArrayBase<S2, D>, rtol: A::Real)
where
    A: Scalar + Lapack,
    S1: Data<Elem = A>,
    S2: Data<Elem = A>,
    D: Dimension,
    D::Pattern: PartialEq + Debug,
{
    assert_eq!(test.dim(), truth.dim());
    let tol = (test - truth).norm_l1() / truth.norm_l1();
    if tol > rtol {
        eprintln!("Expected:\n{}", truth);
        eprintln!("Actual:\n{}", test);
        panic!("Too large deviation in L1-norm: {}", tol);
    }
}

/// check two arrays are close in L2 norm
pub fn close_l2<A, S1, S2, D>(test: &ArrayBase<S1, D>, truth: &ArrayBase<S2, D>, rtol: A::Real)
where
    A: Scalar + Lapack,
    S1: Data<Elem = A>,
    S2: Data<Elem = A>,
    D: Dimension,
    D::Pattern: PartialEq + Debug,
{
    assert_eq!(test.dim(), truth.dim());
    let tol = (test - truth).norm_l2() / truth.norm_l2();
    if tol > rtol {
        eprintln!("Expected:\n{}", truth);
        eprintln!("Actual:\n{}", test);
        panic!("Too large deviation in L2-norm: {}", tol);
    }
}

macro_rules! generate_assert {
    ($assert:ident, $close:path) => {
        #[macro_export]
        macro_rules! $assert {
            ($test: expr,$truth: expr,$tol: expr) => {
                $crate::$close($test, $truth, $tol);
            };
            ($test: expr,$truth: expr,$tol: expr; $comment: expr) => {
                eprintln!($comment);
                $crate::$close($test, $truth, $tol);
            };
        }
    };
} // generate_assert!

generate_assert!(assert_rclose, rclose);
generate_assert!(assert_aclose, aclose);
generate_assert!(assert_close_max, close_max);
generate_assert!(assert_close_l1, close_l1);
generate_assert!(assert_close_l2, close_l2);
<commit_msg>Revise assertion output<commit_after>//! Assertions for array

use ndarray::*;
use std::fmt::Debug;

use super::norm::*;
use super::types::*;

/// check two values are close in terms of the relative tolerance
pub fn rclose<A: Scalar>(test: A, truth: A, rtol: A::Real) {
    let dev = (test - truth).abs() / truth.abs();
    if dev > rtol {
        eprintln!("==== Assetion Failed ====");
        eprintln!("Expected = {}", truth);
        eprintln!("Actual   = {}", test);
        panic!("Too large deviation in relative tolerance: {}", dev);
    }
}

/// check two values are close in terms of the absolute tolerance
pub fn aclose<A: Scalar>(test: A, truth: A, atol: A::Real) {
    let dev = (test - truth).abs();
    if dev > atol {
        eprintln!("==== Assetion Failed ====");
        eprintln!("Expected = {}", truth);
        eprintln!("Actual   = {}", test);
        panic!("Too large deviation in absolute tolerance: {}", dev);
    }
}

/// check two arrays are close in maximum norm
pub fn close_max<A, S1, S2, D>(test: &ArrayBase<S1, D>, truth: &ArrayBase<S2, D>, atol: A::Real)
where
    A: Scalar + Lapack,
    S1: Data<Elem = A>,
    S2: Data<Elem = A>,
    D: Dimension,
    D::Pattern: PartialEq + Debug,
{
    assert_eq!(test.dim(), truth.dim());
    let tol = (test - truth).norm_max();
    if tol > atol {
        eprintln!("==== Assetion Failed ====");
        eprintln!("Expected:\n{}", truth);
        eprintln!("Actual:\n{}", test);
        panic!("Too large deviation in maximum norm: {} > {}", tol, atol);
    }
}

/// check two arrays are close in L1 norm
pub fn close_l1<A, S1, S2, D>(test: &ArrayBase<S1, D>, truth: &ArrayBase<S2, D>, rtol: A::Real)
where
    A: Scalar + Lapack,
    S1: Data<Elem = A>,
    S2: Data<Elem = A>,
    D: Dimension,
    D::Pattern: PartialEq + Debug,
{
    assert_eq!(test.dim(), truth.dim());
    let tol = (test - truth).norm_l1() / truth.norm_l1();
    if tol > rtol {
        eprintln!("==== Assetion Failed ====");
        eprintln!("Expected:\n{}", truth);
        eprintln!("Actual:\n{}", test);
        panic!("Too large deviation in L1-norm: {} > {}", tol, rtol);
    }
}

/// check two arrays are close in L2 norm
pub fn close_l2<A, S1, S2, D>(test: &ArrayBase<S1, D>, truth: &ArrayBase<S2, D>, rtol: A::Real)
where
    A: Scalar + Lapack,
    S1: Data<Elem = A>,
    S2: Data<Elem = A>,
    D: Dimension,
    D::Pattern: PartialEq + Debug,
{
    assert_eq!(test.dim(), truth.dim());
    let tol = (test - truth).norm_l2() / truth.norm_l2();
    if tol > rtol {
        eprintln!("==== Assetion Failed ====");
        eprintln!("Expected:\n{}", truth);
        eprintln!("Actual:\n{}", test);
        panic!("Too large deviation in L2-norm: {} > {} ", tol, rtol);
    }
}

macro_rules! generate_assert {
    ($assert:ident, $close:path) => {
        #[macro_export]
        macro_rules! $assert {
            ($test: expr,$truth: expr,$tol: expr) => {
                $crate::$close($test, $truth, $tol);
            };
            ($test: expr,$truth: expr,$tol: expr; $comment: expr) => {
                eprintln!($comment);
                $crate::$close($test, $truth, $tol);
            };
        }
    };
} // generate_assert!

generate_assert!(assert_rclose, rclose);
generate_assert!(assert_aclose, aclose);
generate_assert!(assert_close_max, close_max);
generate_assert!(assert_close_l1, close_l1);
generate_assert!(assert_close_l2, close_l2);
<|endoftext|>