<commit_before>//! Methods for reading font data out of fonts.mul
//!
//! Fonts are represented in a continuous, unindexed file as groups
//! `|header: u8|characters: [Character..224]`
//!
//! Individual Characters are defined as
//! `|width: u8|height: u8|unknown: u8|pixels: [Color16..width*height]`
//!
use std::fs::{File};
use std::io::{Cursor, Result, SeekFrom, Seek, Read, Write};
use color::{Color16, Color};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use std::path::Path;
use image::{Rgba, RgbaImage};

#[derive(Clone)]
pub struct Character {
    pub width: u8,
    pub height: u8,
    pub unknown: u8,
    pub data: Vec<Color16>
}

impl Character {
    pub fn to_image(&self) -> RgbaImage {
        let mut buffer = RgbaImage::new(self.width as u32, self.height as u32);
        for y in 0..self.height {
            for x in 0..self.width {
                let pixel = self.data[(y as usize * self.width as usize) + x as usize];
                let (r, g, b, a) = pixel.to_rgba();
                // Black is transparent
                if r != 0 || g != 0 || b != 0 {
                    buffer.put_pixel(x as u32, y as u32, Rgba([r, g, b, a]));
                }
            }
        }
        buffer
    }
}

#[derive(Clone)]
pub struct Font {
    pub header: u8,
    pub characters: Vec<Character>
}

pub struct FontReader<T: Read + Seek> {
    data_reader: T
}

impl FontReader<File> {
    pub fn new(font_path: &Path) -> Result<FontReader<File>> {
        let data_reader = File::open(font_path)?;

        Ok(FontReader {
            data_reader: data_reader
        })
    }
}

impl<T: Read + Seek> FontReader<T> {
    /**
     * If we've already got a file-like object, wrap it
     * */
    pub fn from_readable(data_reader: T) -> FontReader<T> {
        FontReader {
            data_reader: data_reader
        }
    }

    pub fn read_fonts(&mut self) -> Result<Vec<Font>> {
        let mut out = vec![];
        loop {
            let header = self.data_reader.read_u8()?;
            // A 0 in the header means it's not a valid font
            if header == 0 {
                break;
            }
            let current = self.data_reader.seek(SeekFrom::Current(-1))?;
            out.push(self.read_font()?);
        }
        Ok(out)
    }

    fn read_font(&mut self) -> Result<Font> {
        let header = self.data_reader.read_u8()?;
        let mut chars = vec![];
        for _ in 0..224 {
            chars.push(self.read_character()?);
        }
        Ok(Font {
            header,
            characters: chars
        })
    }

    fn read_character(&mut self) -> Result<Character> {
        let width = self.data_reader.read_u8()?;
        let height = self.data_reader.read_u8()?;
        let unknown = self.data_reader.read_u8()?;
        let mut pixels = vec![];
        for _ in 0..(width as u32 * height as u32) {
            pixels.push(self.data_reader.read_u16::<LittleEndian>()?);
        }
        Ok(Character {
            width,
            height,
            unknown,
            data: pixels
        })
    }
}
<commit_msg>Cleanup<commit_after>//! Methods for reading font data out of fonts.mul
//!
//! Fonts are represented in a continuous, unindexed file as groups
//! `|header: u8|characters: [Character..224]`
//!
//! Individual Characters are defined as
//! `|width: u8|height: u8|unknown: u8|pixels: [Color16..width*height]`
//!
use std::fs::{File};
use std::io::{Result, Seek, Read};
use color::{Color16, Color};
use byteorder::{LittleEndian, ReadBytesExt};
use std::path::Path;
use image::{Rgba, RgbaImage};

#[derive(Clone)]
pub struct Character {
    pub width: u8,
    pub height: u8,
    pub unknown: u8,
    pub data: Vec<Color16>
}

impl Character {
    pub fn to_image(&self) -> RgbaImage {
        let mut buffer = RgbaImage::new(self.width as u32, self.height as u32);
        for y in 0..self.height {
            for x in 0..self.width {
                let pixel = self.data[(y as usize * self.width as usize) + x as usize];
                let (r, g, b, a) = pixel.to_rgba();
                // Black is transparent
                if r != 0 || g != 0 || b != 0 {
                    buffer.put_pixel(x as u32, y as u32, Rgba([r, g, b, a]));
                }
            }
        }
        buffer
    }
}

#[derive(Clone)]
pub struct Font {
    pub header: u8,
    pub characters: Vec<Character>
}

pub struct FontReader<T: Read + Seek> {
    data_reader: T
}

impl FontReader<File> {
    pub fn new(font_path: &Path) -> Result<FontReader<File>> {
        let data_reader = File::open(font_path)?;

        Ok(FontReader {
            data_reader: data_reader
        })
    }
}

impl<T: Read + Seek> FontReader<T> {
    /**
     * If we've already got a file-like object, wrap it
     * */
    pub fn from_readable(data_reader: T) -> FontReader<T> {
        FontReader {
            data_reader: data_reader
        }
    }

    pub fn read_fonts(&mut self) -> Result<Vec<Font>> {
        let mut out = vec![];
        loop {
            let header = self.data_reader.read_u8()?;
            // A 0 in the header means it's not a valid font
            if header == 0 {
                break;
            }
            out.push(self.read_font()?);
        }
        Ok(out)
    }

    fn read_font(&mut self) -> Result<Font> {
        let header = self.data_reader.read_u8()?;
        let mut chars = vec![];
        for _ in 0..224 {
            chars.push(self.read_character()?);
        }
        Ok(Font {
            header,
            characters: chars
        })
    }

    fn read_character(&mut self) -> Result<Character> {
        let width = self.data_reader.read_u8()?;
        let height = self.data_reader.read_u8()?;
        let unknown = self.data_reader.read_u8()?;
        let mut pixels = vec![];
        for _ in 0..(width as u32 * height as u32) {
            pixels.push(self.data_reader.read_u16::<LittleEndian>()?);
        }
        Ok(Character {
            width,
            height,
            unknown,
            data: pixels
        })
    }
}
<|endoftext|>


<commit_before>//! Methods for reading font data out of fonts.mul
//!
//! Fonts are represented in a continuous, unindexed file as groups
//! `|header: u8|characters: [Character..224]`
//!
//! Individual Characters are defined as
//! `|width: u8|height: u8|unknown: u8|pixels: [Color16..width*height]`
//!
use byteorder::{LittleEndian, ReadBytesExt};
use color::{Color, Color16};
use image::{Rgba, RgbaImage};
use std::fs::File;
use std::io::{Read, Result, Seek};
use std::path::Path;

#[derive(Clone)]
pub struct Character {
    pub width: u8,
    pub height: u8,
    pub unknown: u8,
    pub data: Vec<Color16>,
}

impl Character {
    pub fn to_image(&self) -> RgbaImage {
        let mut buffer = RgbaImage::new(self.width as u32, self.height as u32);
        for y in 0..self.height {
            for x in 0..self.width {
                let pixel = self.data[(y as usize * self.width as usize) + x as usize];
                let (r, g, b, a) = pixel.to_rgba();
                // Black is transparent
                if r != 0 || g != 0 || b != 0 {
                    buffer.put_pixel(x as u32, y as u32, Rgba([r, g, b, a]));
                }
            }
        }
        buffer
    }
}

#[derive(Clone)]
pub struct Font {
    pub header: u8,
    pub characters: Vec<Character>,
}

pub struct FontReader<T: Read + Seek> {
    data_reader: T,
}

impl FontReader<File> {
    pub fn new(font_path: &Path) -> Result<FontReader<File>> {
        let data_reader = File::open(font_path)?;

        Ok(FontReader {
            data_reader: data_reader,
        })
    }
}

impl<T: Read + Seek> FontReader<T> {
    /**
     * If we've already got a file-like object, wrap it
     * */
    pub fn from_readable(data_reader: T) -> FontReader<T> {
        FontReader {
            data_reader: data_reader,
        }
    }

    pub fn read_fonts(&mut self) -> Result<Vec<Font>> {
        let mut out = vec![];
        loop {
            let header = self.data_reader.read_u8()?;
            // A 0 in the header means it's not a valid font
            if header == 0 {
                break;
            }
            out.push(self.read_font()?);
        }
        Ok(out)
    }

    fn read_font(&mut self) -> Result<Font> {
        let header = self.data_reader.read_u8()?;
        let mut chars = vec![];
        for _ in 0..224 {
            chars.push(self.read_character()?);
        }
        Ok(Font {
            header,
            characters: chars,
        })
    }

    fn read_character(&mut self) -> Result<Character> {
        let width = self.data_reader.read_u8()?;
        let height = self.data_reader.read_u8()?;
        let unknown = self.data_reader.read_u8()?;
        let mut pixels = vec![];
        for _ in 0..(width as u32 * height as u32) {
            pixels.push(self.data_reader.read_u16::<LittleEndian>()?);
        }
        Ok(Character {
            width,
            height,
            unknown,
            data: pixels,
        })
    }
}
<commit_msg>Correct font reading<commit_after>//! Methods for reading font data out of fonts.mul
//!
//! Fonts are represented in a continuous, unindexed file as groups
//! `|header: u8|characters: [Character..224]`
//!
//! Individual Characters are defined as
//! `|width: u8|height: u8|unknown: u8|pixels: [Color16..width*height]`
//!
use byteorder::{LittleEndian, ReadBytesExt};
use color::{Color, Color16};
use image::{Rgba, RgbaImage};
use std::fs::File;
use std::io::{Read, Result, Seek};
use std::path::Path;

#[derive(Clone)]
pub struct Character {
    pub width: u8,
    pub height: u8,
    pub unknown: u8,
    pub data: Vec<Color16>,
}

impl Character {
    pub fn to_image(&self) -> RgbaImage {
        let mut buffer = RgbaImage::new(self.width as u32, self.height as u32);
        for y in 0..self.height {
            for x in 0..self.width {
                let pixel = self.data[(y as usize * self.width as usize) + x as usize];
                let (r, g, b, a) = pixel.to_rgba();
                // Black is transparent
                if r != 0 || g != 0 || b != 0 {
                    buffer.put_pixel(x as u32, y as u32, Rgba([r, g, b, a]));
                }
            }
        }
        buffer
    }
}

#[derive(Clone)]
pub struct Font {
    pub header: u8,
    pub characters: Vec<Character>,
}

pub struct FontReader<T: Read + Seek> {
    data_reader: T,
}

impl FontReader<File> {
    pub fn new(font_path: &Path) -> Result<FontReader<File>> {
        let data_reader = File::open(font_path)?;

        Ok(FontReader {
            data_reader: data_reader,
        })
    }
}

impl<T: Read + Seek> FontReader<T> {
    /**
     * If we've already got a file-like object, wrap it
     * */
    pub fn from_readable(data_reader: T) -> FontReader<T> {
        FontReader {
            data_reader: data_reader,
        }
    }

    pub fn read_fonts(&mut self) -> Result<Vec<Font>> {
        let mut out = vec![];
        for _ in 0..10 {
            out.push(self.read_font()?);
        }
        Ok(out)
    }

    fn read_font(&mut self) -> Result<Font> {
        let header = self.data_reader.read_u8()?;
        let mut chars = vec![];
        for _ in 0..224 {
            chars.push(self.read_character()?);
        }
        Ok(Font {
            header,
            characters: chars,
        })
    }

    fn read_character(&mut self) -> Result<Character> {
        let width = self.data_reader.read_u8()?;
        let height = self.data_reader.read_u8()?;
        let unknown = self.data_reader.read_u8()?;
        let mut pixels = vec![];
        for _ in 0..(width as u32 * height as u32) {
            pixels.push(self.data_reader.read_u16::<LittleEndian>()?);
        }
        Ok(Character {
            width,
            height,
            unknown,
            data: pixels,
        })
    }
}
<|endoftext|>


<commit_before>
use gfx;
use gfx::DeviceHelper;
use graphics::BackEnd;
use graphics::BACK_END_MAX_VERTEX_COUNT as BUFFER_SIZE;

use Texture;

static VERTEX_SHADER: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
attribute vec2 pos;
attribute vec4 color;
varying vec4 v_Color;
void main() {
    v_Color = color;
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
    GLSL_150: b"
#version 150 core
in vec2 pos;
in vec4 color;
out vec4 v_Color;
void main() {
    v_Color = color;
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
};

static FRAGMENT_SHADER: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
varying vec4 v_Color;
void main() {
    gl_FragColor = v_Color;
}
"
    GLSL_150: b"
#version 150 core
in vec4 v_Color;
out vec4 o_Color;
void main() {
    o_Color = v_Color;
}
"
};

static VERTEX_SHADER_UV: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
attribute vec2 pos;
attribute vec4 color;
attribute vec2 uv;
uniform sampler2D s_texture;
varying vec4 v_Color;
varying vec2 v_UV;
void main() {
    v_UV = uv;
    v_Color = color;
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
    GLSL_150: b"
#version 150 core
in vec2 pos;
in vec4 color;
in vec2 uv;
uniform sampler2D s_texture;
out vec4 v_Color;
out vec2 v_UV;
void main() {
    v_UV = uv;
    v_Color = color;
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
};

static FRAGMENT_SHADER_UV: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
uniform sampler2D s_texture;
varying vec2 v_UV;
varying vec4 v_Color;
void main()
{
    gl_FragColor = texture2D(s_texture, v_UV) * v_Color;
}
"
    GLSL_150: b"
#version 150 core
out vec4 o_Color;
uniform sampler2D s_texture;
in vec2 v_UV;
in vec4 v_Color;
void main()
{
    o_Color = texture(s_texture, v_UV) * v_Color;
}
"
};

#[vertex_format]
struct Vertex {
    pos: [f32, ..2],
    color: [f32, ..4],
}

impl Vertex {
    fn new(pos: [f32, ..2], color: [f32, ..4]) -> Vertex {
        Vertex {
            pos: pos,
            color: color,
        }
    }
}

#[vertex_format]
struct VertexUV {
    pos: [f32, ..2],
    color: [f32, ..4],
    uv: [f32, ..2],
}

impl VertexUV {
    fn new(pos: [f32, ..2], color: [f32, ..4], uv: [f32, ..2]) -> VertexUV {
        VertexUV {
            pos: pos,
            color: color,
            uv: uv,
        }
    }
}

#[allow(unused_imports)]
#[shader_param(BatchUV, OwnedBatchUV)]
struct ParamsUV {
    s_texture: gfx::shade::TextureParam,
}

/// The graphics back-end.
pub struct Gfx2d {
    buffer: gfx::BufferHandle<Vertex>,
    buffer_uv: gfx::BufferHandle<VertexUV>,
    batch: gfx::batch::OwnedBatch<(), ()>,
    batch_uv: OwnedBatchUV,
}

impl Gfx2d {
    /// Creates a new Gfx2d object.
    pub fn new<D: gfx::Device<C>,
               C: gfx::CommandBuffer>(device: &mut D) -> Gfx2d {
        let program = device.link_program(
                VERTEX_SHADER.clone(),
                FRAGMENT_SHADER.clone()
            ).unwrap();
        let program_uv = device.link_program(
                VERTEX_SHADER_UV.clone(),
                FRAGMENT_SHADER_UV.clone()
            ).unwrap();
        let buffer = device.create_buffer(BUFFER_SIZE, gfx::UsageDynamic);
        let buffer_uv = device.create_buffer(BUFFER_SIZE, gfx::UsageDynamic);
        let mesh = gfx::Mesh::from_format(buffer, BUFFER_SIZE as u32);
        let mesh_uv = gfx::Mesh::from_format(buffer_uv, BUFFER_SIZE as u32);
        let batch = gfx::batch::OwnedBatch::new(mesh, program, ()).unwrap();

        let sampler = device.create_sampler(
                gfx::tex::SamplerInfo::new(gfx::tex::Trilinear,
                                           gfx::tex::Clamp)
            );

        // Create a dummy texture
        let texture_info = gfx::tex::TextureInfo {
            width: 1,
            height: 1,
            depth: 1,
            levels: 1,
            kind: gfx::tex::Texture2D,
            format: gfx::tex::RGBA8,
        };
        let image_info = texture_info.to_image_info();
        let texture = device.create_texture(texture_info).unwrap();
        device.update_texture(&texture, &image_info,
                [0x20u8, 0xA0u8, 0xC0u8, 0x00u8])
            .unwrap();
        let params_uv = ParamsUV {
            s_texture: (texture, Some(sampler))
        };

        let batch_uv = gfx::batch::OwnedBatch::new(
            mesh_uv, program_uv, params_uv).unwrap();

        Gfx2d {
            buffer: buffer,
            buffer_uv: buffer_uv,
            batch: batch,
            batch_uv: batch_uv,
        }
    }
}

/// Used for rendering 2D graphics.
pub struct RenderContext<'a, C: 'a + gfx::CommandBuffer> {
    renderer: &'a mut gfx::Renderer<C>,
    frame: &'a gfx::Frame,
    gfx2d: &'a mut Gfx2d,
    data_vertex: Vec<Vertex>,
    data_vertex_uv: Vec<VertexUV>,
}

impl<'a, C: gfx::CommandBuffer> RenderContext<'a, C> {
    /// Creates a new object for rendering 2D graphics.
    pub fn new(renderer: &'a mut gfx::Renderer<C>,
               frame: &'a gfx::Frame,
               gfx2d: &'a mut Gfx2d) -> RenderContext<'a, C> {
        RenderContext {
            renderer: renderer,
            frame: frame,
            gfx2d: gfx2d,
            data_vertex: Vec::new(),
            data_vertex_uv: Vec::new(),
        }
    }
}

impl<'a, C: gfx::CommandBuffer> BackEnd<Texture>
for RenderContext<'a, C> {
    fn supports_clear_rgba(&self) -> bool { true }

    fn clear_rgba(&mut self, r: f32, g: f32, b: f32, a: f32) {
        let &RenderContext {
            ref mut renderer,
            frame,
            ..
        } = self;
        renderer.clear(
                gfx::ClearData {
                    color: [r, g, b, a],
                    depth: 0.0,
                    stencil: 0,
                },
                gfx::Color,
                frame
            );
    }

    fn enable_alpha_blend(&mut self) {
        use std::default::Default;
        use gfx::state::{Normal, Inverse, Factor};

        self.gfx2d.batch.state.blend = Some(gfx::state::Blend {
                value: [1.0, 1.0, 1.0, 1.0],
                color: gfx::state::BlendChannel {
                        equation: gfx::state::FuncAdd,
                        source: Factor(Normal, gfx::state::SourceAlpha),
                        destination: Factor(Inverse, gfx::state::SourceAlpha)
                    },
                alpha: Default::default()
            })
    }

    fn disable_alpha_blend(&mut self) {
        self.gfx2d.batch.state.blend = None;
    }

    fn supports_tri_list_xy_f32_rgba_f32(&self) -> bool { true }

    fn tri_list_xy_f32_rgba_f32(
        &mut self,
        vertices: &[f32],
        colors: &[f32]
    ) {
        let &RenderContext {
            ref mut renderer,
            ref frame,
            gfx2d: &Gfx2d {
                ref mut buffer,
                ref mut batch,
                ..
            },
            ref mut data_vertex,
            ..
        } = self;

        data_vertex.truncate(0);
        for i in range(0, vertices.len() / 2) {
            data_vertex.push(
                Vertex::new(
                    [vertices[2 * i], vertices[2 * i + 1]],
                    [
                        colors[4 * i],
                        colors[4 * i + 1],
                        colors[4 * i + 2],
                        colors[4 * i + 3]
                    ]
                )
            );
        }

        let n = data_vertex.len();
        renderer.update_buffer_vec(*buffer, data_vertex.as_slice(), 0);
        batch.slice = gfx::VertexSlice(gfx::TriangleList, 0, n as u32);
        renderer.draw(&*batch, *frame);
    }

    fn supports_single_texture(&self) -> bool { true }

    fn enable_single_texture(&mut self, texture: &Texture) {
        let ParamsUV {
            s_texture: (ref mut s_texture, _)
        } = self.gfx2d.batch_uv.param;
        *s_texture = texture.handle;
    }

    fn disable_single_texture(&mut self) {}

    // Assume all textures has alpha channel for now.
    fn has_texture_alpha(&self, _texture: &Texture) -> bool { true }

    fn supports_tri_list_xy_f32_rgba_f32_uv_f32(&self) -> bool { true }

    fn tri_list_xy_f32_rgba_f32_uv_f32(
        &mut self,
        vertices: &[f32],
        colors: &[f32],
        texture_coords: &[f32]
    ) {
        let &RenderContext {
            ref mut renderer,
            ref frame,
            gfx2d: &Gfx2d {
                ref mut buffer_uv,
                ref mut batch_uv,
                ..
            },
            ref mut data_vertex_uv,
            ..
        } = self;

        data_vertex_uv.truncate(0);
        for i in range(0, vertices.len() / 2) {
            data_vertex_uv.push(
                VertexUV::new(
                    [vertices[2 * i], vertices[2 * i + 1]],
                    [
                        colors[4 * i],
                        colors[4 * i + 1],
                        colors[4 * i + 2],
                        colors[4 * i + 3]
                    ],
                    [
                        texture_coords[2 * i],
                        texture_coords[2 * i + 1]
                    ]
                )
            );
        }

        let n = data_vertex_uv.len();
        renderer.update_buffer_vec(*buffer_uv, data_vertex_uv.as_slice(), 0);
        batch_uv.slice = gfx::VertexSlice(gfx::TriangleList, 0, n as u32);
        renderer.draw(&*batch_uv, *frame);
    }
}
<commit_msg>Switched to buffer per attribute scheme.<commit_after>
use gfx;
use gfx::DeviceHelper;
use graphics::BackEnd;
use graphics::BACK_END_MAX_VERTEX_COUNT as BUFFER_SIZE;

use Texture;

static VERTEX_SHADER: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
attribute vec2 pos;
attribute vec4 color;
varying vec4 v_Color;
void main() {
    v_Color = color;
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
    GLSL_150: b"
#version 150 core
in vec2 pos;
in vec4 color;
out vec4 v_Color;
void main() {
    v_Color = color;
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
};

static FRAGMENT_SHADER: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
varying vec4 v_Color;
void main() {
    gl_FragColor = v_Color;
}
"
    GLSL_150: b"
#version 150 core
in vec4 v_Color;
out vec4 o_Color;
void main() {
    o_Color = v_Color;
}
"
};

static VERTEX_SHADER_UV: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
attribute vec2 pos;
attribute vec4 color;
attribute vec2 uv;
uniform sampler2D s_texture;
varying vec4 v_Color;
varying vec2 v_UV;
void main() {
    v_UV = uv;
    v_Color = color;
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
    GLSL_150: b"
#version 150 core
in vec2 pos;
in vec4 color;
in vec2 uv;
uniform sampler2D s_texture;
out vec4 v_Color;
out vec2 v_UV;
void main() {
    v_UV = uv;
    v_Color = color;
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
};

static FRAGMENT_SHADER_UV: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
uniform sampler2D s_texture;
varying vec2 v_UV;
varying vec4 v_Color;
void main()
{
    gl_FragColor = texture2D(s_texture, v_UV) * v_Color;
}
"
    GLSL_150: b"
#version 150 core
out vec4 o_Color;
uniform sampler2D s_texture;
in vec2 v_UV;
in vec4 v_Color;
void main()
{
    o_Color = texture(s_texture, v_UV) * v_Color;
}
"
};

static POS_COMPONENTS: uint = 2;
static COLOR_COMPONENTS: uint = 4;
static UV_COMPONENTS: uint = 2;

// Boiler plate for automatic attribute construction.
// Needs to be improved on gfx-rs side.
// For some reason, using ``*_COMPONENT` triggers some macros errors.

#[vertex_format]
struct PositionFormat { v: [f32, ..2] }

#[vertex_format]
struct ColorFormat { v: [f32, ..4] }

#[vertex_format]
struct TexCoordsFormat { v: [f32, ..2] }

#[allow(unused_imports)]
#[shader_param(BatchUV, OwnedBatchUV)]
struct ParamsUV {
    s_texture: gfx::shade::TextureParam,
}

/// The graphics back-end.
pub struct Gfx2d {
    buffer_pos: gfx::BufferHandle<f32>,
    buffer_color: gfx::BufferHandle<f32>,
    buffer_uv: gfx::BufferHandle<f32>,
    batch: gfx::batch::OwnedBatch<(), ()>,
    batch_uv: OwnedBatchUV,
}

impl Gfx2d {
    /// Creates a new Gfx2d object.
    pub fn new<D: gfx::Device<C>,
               C: gfx::CommandBuffer>(device: &mut D) -> Gfx2d {
        let program = device.link_program(
                VERTEX_SHADER.clone(),
                FRAGMENT_SHADER.clone()
            ).unwrap();
        let program_uv = device.link_program(
                VERTEX_SHADER_UV.clone(),
                FRAGMENT_SHADER_UV.clone()
            ).unwrap();

        let buffer_pos = device.create_buffer(
            POS_COMPONENTS * BUFFER_SIZE,
            gfx::UsageDynamic);
        let buffer_color = device.create_buffer(
            COLOR_COMPONENTS * BUFFER_SIZE,
            gfx::UsageDynamic);
        let buffer_uv = device.create_buffer(
            UV_COMPONENTS * BUFFER_SIZE,
            gfx::UsageDynamic);

        let mut mesh = gfx::Mesh::new(BUFFER_SIZE as u32);
        mesh.attributes.push_all_move(gfx::VertexFormat::generate(
            None::<PositionFormat>,
            buffer_pos.raw()
        ));
        mesh.attributes.push_all_move(gfx::VertexFormat::generate(
            None::<ColorFormat>,
            buffer_color.raw()
        ));

        let mut mesh_uv = mesh.clone();
        mesh_uv.attributes.push_all_move(gfx::VertexFormat::generate(
            None::<TexCoordsFormat>,
            buffer_uv.raw()
        ));

        let batch = gfx::batch::OwnedBatch::new(mesh, program, ()).unwrap();

        let sampler = device.create_sampler(
                gfx::tex::SamplerInfo::new(gfx::tex::Trilinear,
                                           gfx::tex::Clamp)
            );

        // Create a dummy texture
        let texture_info = gfx::tex::TextureInfo {
            width: 1,
            height: 1,
            depth: 1,
            levels: 1,
            kind: gfx::tex::Texture2D,
            format: gfx::tex::RGBA8,
        };
        let image_info = texture_info.to_image_info();
        let texture = device.create_texture(texture_info).unwrap();
        device.update_texture(&texture, &image_info,
                [0x20u8, 0xA0u8, 0xC0u8, 0x00u8])
            .unwrap();
        let params_uv = ParamsUV {
            s_texture: (texture, Some(sampler))
        };

        let batch_uv = gfx::batch::OwnedBatch::new(
            mesh_uv, program_uv, params_uv).unwrap();

        Gfx2d {
            buffer_pos: buffer_pos,
            buffer_color: buffer_color,
            buffer_uv: buffer_uv,
            batch: batch,
            batch_uv: batch_uv,
        }
    }
}

/// Used for rendering 2D graphics.
pub struct RenderContext<'a, C: 'a + gfx::CommandBuffer> {
    renderer: &'a mut gfx::Renderer<C>,
    frame: &'a gfx::Frame,
    gfx2d: &'a mut Gfx2d,
}

impl<'a, C: gfx::CommandBuffer> RenderContext<'a, C> {
    /// Creates a new object for rendering 2D graphics.
    pub fn new(renderer: &'a mut gfx::Renderer<C>,
               frame: &'a gfx::Frame,
               gfx2d: &'a mut Gfx2d) -> RenderContext<'a, C> {
        RenderContext {
            renderer: renderer,
            frame: frame,
            gfx2d: gfx2d,
        }
    }
}

impl<'a, C: gfx::CommandBuffer> BackEnd<Texture>
for RenderContext<'a, C> {
    fn supports_clear_rgba(&self) -> bool { true }

    fn clear_rgba(&mut self, r: f32, g: f32, b: f32, a: f32) {
        let &RenderContext {
            ref mut renderer,
            frame,
            ..
        } = self;
        renderer.clear(
                gfx::ClearData {
                    color: [r, g, b, a],
                    depth: 0.0,
                    stencil: 0,
                },
                gfx::Color,
                frame
            );
    }

    fn enable_alpha_blend(&mut self) {
        use std::default::Default;
        use gfx::state::{Normal, Inverse, Factor};

        self.gfx2d.batch.state.blend = Some(gfx::state::Blend {
                value: [1.0, 1.0, 1.0, 1.0],
                color: gfx::state::BlendChannel {
                        equation: gfx::state::FuncAdd,
                        source: Factor(Normal, gfx::state::SourceAlpha),
                        destination: Factor(Inverse, gfx::state::SourceAlpha)
                    },
                alpha: Default::default()
            })
    }

    fn disable_alpha_blend(&mut self) {
        self.gfx2d.batch.state.blend = None;
    }

    fn supports_tri_list_xy_f32_rgba_f32(&self) -> bool { true }

    fn tri_list_xy_f32_rgba_f32(
        &mut self,
        vertices: &[f32],
        colors: &[f32]
    ) {
        let &RenderContext {
            ref mut renderer,
            ref frame,
            gfx2d: &Gfx2d {
                ref mut buffer_pos,
                ref mut buffer_color,
                ref mut batch,
                ..
            },
        } = self;

        assert_eq!(
            vertices.len() * COLOR_COMPONENTS,
            colors.len() * POS_COMPONENTS
        );
        renderer.update_buffer_vec(*buffer_pos, vertices, 0);
        renderer.update_buffer_vec(*buffer_color, colors, 0);

        let n = vertices.len() / POS_COMPONENTS;
        batch.slice = gfx::VertexSlice(gfx::TriangleList, 0, n as u32);
        renderer.draw(&*batch, *frame);
    }

    fn supports_single_texture(&self) -> bool { true }

    fn enable_single_texture(&mut self, texture: &Texture) {
        let ParamsUV {
            s_texture: (ref mut s_texture, _)
        } = self.gfx2d.batch_uv.param;
        *s_texture = texture.handle;
    }

    fn disable_single_texture(&mut self) {}

    // Assume all textures has alpha channel for now.
    fn has_texture_alpha(&self, _texture: &Texture) -> bool { true }

    fn supports_tri_list_xy_f32_rgba_f32_uv_f32(&self) -> bool { true }

    fn tri_list_xy_f32_rgba_f32_uv_f32(
        &mut self,
        vertices: &[f32],
        colors: &[f32],
        texture_coords: &[f32]
    ) {
        let &RenderContext {
            ref mut renderer,
            ref frame,
            gfx2d: &Gfx2d {
                ref mut buffer_pos,
                ref mut buffer_color,
                ref mut buffer_uv,
                ref mut batch_uv,
                ..
            },
        } = self;

        assert_eq!(
            vertices.len() * COLOR_COMPONENTS,
            colors.len() * POS_COMPONENTS
        );
        assert_eq!(
            vertices.len() * UV_COMPONENTS,
            texture_coords.len() * POS_COMPONENTS
        );
        renderer.update_buffer_vec(*buffer_pos, vertices, 0);
        renderer.update_buffer_vec(*buffer_color, colors, 0);
        renderer.update_buffer_vec(*buffer_uv, texture_coords, 0);

        let n = vertices.len() / POS_COMPONENTS;
        batch_uv.slice = gfx::VertexSlice(gfx::TriangleList, 0, n as u32);
        renderer.draw(&*batch_uv, *frame);
    }
}
<|endoftext|>


<commit_before>//! The `image` element.

use markup5ever::{expanded_name, local_name, namespace_url, ns};

use crate::aspect_ratio::AspectRatio;
use crate::bbox::BoundingBox;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{Draw, ElementResult, SetAttributes};
use crate::error::*;
use crate::href::{is_href, set_href};
use crate::length::*;
use crate::node::{CascadedValues, Node};
use crate::parsers::ParseValue;
use crate::rect::Rect;
use crate::xml::Attributes;

#[derive(Default)]
pub struct Image {
    x: Length<Horizontal>,
    y: Length<Vertical>,
    width: ULength<Horizontal>,
    height: ULength<Vertical>,
    aspect: AspectRatio,
    href: Option<String>,
}

impl SetAttributes for Image {
    fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
        for (attr, value) in attrs.iter() {
            match attr.expanded() {
                expanded_name!("", "x") => self.x = attr.parse(value)?,
                expanded_name!("", "y") => self.y = attr.parse(value)?,
                expanded_name!("", "width") => self.width = attr.parse(value)?,
                expanded_name!("", "height") => self.height = attr.parse(value)?,
                expanded_name!("", "preserveAspectRatio") => self.aspect = attr.parse(value)?,

                // "path" is used by some older Adobe Illustrator versions
                ref a if is_href(a) || *a == expanded_name!("", "path") => {
                    set_href(a, &mut self.href, value.to_string())
                }

                _ => (),
            }
        }

        Ok(())
    }
}

impl Draw for Image {
    fn draw(
        &self,
        node: &Node,
        acquired_nodes: &mut AcquiredNodes<'_>,
        cascaded: &CascadedValues<'_>,
        draw_ctx: &mut DrawingCtx,
        clipping: bool,
    ) -> Result<BoundingBox, RenderingError> {
        let surface = match self.href {
            Some(ref url) => match acquired_nodes.lookup_image(url) {
                Ok(surf) => surf,
                Err(e) => {
                    rsvg_log!("could not load image \"{}\": {}", url, e);
                    return Ok(draw_ctx.empty_bbox());
                }
            },
            None => return Ok(draw_ctx.empty_bbox()),
        };

        let values = cascaded.get();

        let params = draw_ctx.get_view_params();
        let x = self.x.normalize(&values, &params);
        let y = self.y.normalize(&values, &params);
        let w = self.width.normalize(&values, &params);
        let h = self.height.normalize(&values, &params);

        draw_ctx.draw_image(
            &surface,
            Rect::new(x, y, x + w, y + h),
            self.aspect,
            node,
            acquired_nodes,
            values,
            clipping,
        )
    }
}
<commit_msg>image.rs: use NormalizeParams<commit_after>//! The `image` element.

use markup5ever::{expanded_name, local_name, namespace_url, ns};

use crate::aspect_ratio::AspectRatio;
use crate::bbox::BoundingBox;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{Draw, ElementResult, SetAttributes};
use crate::error::*;
use crate::href::{is_href, set_href};
use crate::length::*;
use crate::node::{CascadedValues, Node};
use crate::parsers::ParseValue;
use crate::rect::Rect;
use crate::xml::Attributes;

#[derive(Default)]
pub struct Image {
    x: Length<Horizontal>,
    y: Length<Vertical>,
    width: ULength<Horizontal>,
    height: ULength<Vertical>,
    aspect: AspectRatio,
    href: Option<String>,
}

impl SetAttributes for Image {
    fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
        for (attr, value) in attrs.iter() {
            match attr.expanded() {
                expanded_name!("", "x") => self.x = attr.parse(value)?,
                expanded_name!("", "y") => self.y = attr.parse(value)?,
                expanded_name!("", "width") => self.width = attr.parse(value)?,
                expanded_name!("", "height") => self.height = attr.parse(value)?,
                expanded_name!("", "preserveAspectRatio") => self.aspect = attr.parse(value)?,

                // "path" is used by some older Adobe Illustrator versions
                ref a if is_href(a) || *a == expanded_name!("", "path") => {
                    set_href(a, &mut self.href, value.to_string())
                }

                _ => (),
            }
        }

        Ok(())
    }
}

impl Draw for Image {
    fn draw(
        &self,
        node: &Node,
        acquired_nodes: &mut AcquiredNodes<'_>,
        cascaded: &CascadedValues<'_>,
        draw_ctx: &mut DrawingCtx,
        clipping: bool,
    ) -> Result<BoundingBox, RenderingError> {
        let surface = match self.href {
            Some(ref url) => match acquired_nodes.lookup_image(url) {
                Ok(surf) => surf,
                Err(e) => {
                    rsvg_log!("could not load image \"{}\": {}", url, e);
                    return Ok(draw_ctx.empty_bbox());
                }
            },
            None => return Ok(draw_ctx.empty_bbox()),
        };

        let values = cascaded.get();

        let view_params = draw_ctx.get_view_params();
        let params = NormalizeParams::new(values, &view_params);

        let x = self.x.to_user(&params);
        let y = self.y.to_user(&params);
        let w = self.width.to_user(&params);
        let h = self.height.to_user(&params);

        draw_ctx.draw_image(
            &surface,
            Rect::new(x, y, x + w, y + h),
            self.aspect,
            node,
            acquired_nodes,
            values,
            clipping,
        )
    }
}
<|endoftext|>


<commit_before>// Bloom
//
// HTTP REST API caching middleware
// Copyright: 2017, Valerian Saliou <valerian@valeriansaliou.name>
// License: Mozilla Public License v2.0 (MPL v2.0)

use futures::future::{self, Future};
use httparse;
use hyper::{Error, Method, StatusCode, Headers};
use hyper::header::{Origin, IfNoneMatch, ETag, EntityTag};
use hyper::server::{Request, Response};

use super::header::ProxyHeader;
use super::tunnel::ProxyTunnel;
use header::janitor::HeaderJanitor;
use header::request_shard::HeaderRequestBloomRequestShard;
use header::status::{HeaderBloomStatus, HeaderBloomStatusValue};
use cache::read::CacheRead;
use cache::write::CacheWrite;
use cache::route::CacheRoute;
use LINE_FEED;

pub struct ProxyServe;

const CACHED_PARSE_MAX_HEADERS: usize = 100;

pub type ProxyServeFuture = Box<Future<Item = Response, Error = Error>>;

impl ProxyServe {
    pub fn handle(req: Request) -> ProxyServeFuture {
        info!("handled request: {} on {}", req.method(), req.path());

        if req.headers().has::<HeaderRequestBloomRequestShard>() == true {
            match *req.method() {
                Method::Options | Method::Head | Method::Get | Method::Post | Method::Patch |
                Method::Put | Method::Delete => Self::accept(req),
                _ => Self::reject(req, StatusCode::MethodNotAllowed),
            }
        } else {
            Self::reject(req, StatusCode::NotExtended)
        }
    }

    fn accept(req: Request) -> ProxyServeFuture {
        Self::tunnel(req)
    }

    fn reject(req: Request, status: StatusCode) -> ProxyServeFuture {
        let mut headers = Headers::new();

        headers.set::<HeaderBloomStatus>(HeaderBloomStatus(HeaderBloomStatusValue::Reject));

        Self::respond(&req.method(), status, headers, format!("{}", status))
    }

    fn tunnel(req: Request) -> ProxyServeFuture {
        let (method, uri, version, headers, body) = req.deconstruct();
        let (headers, auth, shard) = ProxyHeader::parse_from_request(headers);

        let auth_hash = CacheRoute::hash(&auth);

        let (ns, ns_mask) = CacheRoute::gen_key_cache(
            shard,
            &auth_hash,
            version,
            &method,
            uri.path(),
            uri.query(),
            headers.get::<Origin>(),
        );

        info!("tunneling for ns = {}", ns);

        Box::new(
            CacheRead::acquire(&ns, &method)
                .or_else(|_| Err(Error::Incomplete))
                .and_then(move |result| {
                    match result {
                        Ok(value) => Self::dispatch_cached(&method, &headers, &value.0, value.1),
                        Err(_) => {
                            // Clone method value for closures. Sadly, it looks like Rust borrow \
                            //   checker doesnt discriminate properly on this check.
                            let method_success = method.to_owned();
                            let method_failure = method.to_owned();

                            Box::new(
                                ProxyTunnel::run(&method, &uri, &headers, body, shard)
                                    .and_then(move |tunnel_res| {
                                        CacheWrite::save(
                                            ns,
                                            ns_mask,
                                            auth_hash,
                                            shard,
                                            method,
                                            version,
                                            tunnel_res.status(),
                                            tunnel_res.headers().to_owned(),
                                            tunnel_res.body(),
                                        )
                                    })
                                    .and_then(move |mut result| match result.body {
                                        Ok(body_string) => {
                                            Self::dispatch_fetched(
                                                &method_success,
                                                &result.status,
                                                result.headers,
                                                HeaderBloomStatusValue::Miss,
                                                body_string,
                                                result.fingerprint,
                                            )
                                        }
                                        Err(body_string_values) => {
                                            match body_string_values {
                                                Some(body_string) => {
                                                    // Enforce clean headers, has usually they get \
                                                    //   cleaned from cache writer
                                                    HeaderJanitor::clean(&mut result.headers);

                                                    Self::dispatch_fetched(
                                                        &method_success,
                                                        &result.status,
                                                        result.headers,
                                                        HeaderBloomStatusValue::Direct,
                                                        body_string,
                                                        result.fingerprint,
                                                    )
                                                }
                                                _ => Self::dispatch_failure(&method_success),
                                            }
                                        }
                                    })
                                    .or_else(move |_| Self::dispatch_failure(&method_failure)),
                            )
                        }
                    }
                }),
        )
    }

    fn dispatch_cached(
        method: &Method,
        headers: &Headers,
        res_body: &str,
        res_fingerprint: String,
    ) -> ProxyServeFuture {
        // Check if not modified?
        let isnt_modified = match headers.get::<IfNoneMatch>() {
            Some(req_if_none_match) => {
                match *req_if_none_match {
                    IfNoneMatch::Any => true,
                    IfNoneMatch::Items(ref req_etags) => {
                        if let Some(req_etag) = req_etags.first() {
                            req_etag.weak_eq(&EntityTag::new(false, res_fingerprint.to_owned()))
                        } else {
                            false
                        }
                    }
                }
            }
            _ => false,
        };

        // Response not modified for client?
        if isnt_modified == true {
            // Process non-modified + cached headers
            let mut headers = Headers::new();

            ProxyHeader::set_etag(&mut headers, Self::fingerprint_etag(res_fingerprint));
            headers.set::<HeaderBloomStatus>(HeaderBloomStatus(HeaderBloomStatusValue::Hit));

            // Serve non-modified response
            return Self::respond(method, StatusCode::NotModified, headers, String::from(""));
        }

        // Response modified
        let mut headers = [httparse::EMPTY_HEADER; CACHED_PARSE_MAX_HEADERS];
        let mut res = httparse::Response::new(&mut headers);

        // Split headers from body
        let mut res_body_string = String::new();
        let mut is_last_line_empty = false;

        for res_line in res_body.lines() {
            if res_body_string.is_empty() == false || is_last_line_empty == true {
                // Write to body
                res_body_string.push_str(res_line.as_ref());
                res_body_string.push_str(LINE_FEED);
            }

            is_last_line_empty = res_line.is_empty();
        }

        match res.parse(res_body.as_bytes()) {
            Ok(_) => {
                // Process cached status
                let code = res.code.unwrap_or(500u16);
                let status = StatusCode::try_from(code).unwrap_or(StatusCode::Unregistered(code));

                // Process cached headers
                let mut headers = Headers::new();

                for header in res.headers {
                    if let (Ok(header_name), Ok(header_value)) =
                        (
                            String::from_utf8(Vec::from(header.name)),
                            String::from_utf8(Vec::from(header.value)),
                        )
                    {
                        headers.set_raw(header_name, header_value);
                    }
                }

                ProxyHeader::set_etag(&mut headers, Self::fingerprint_etag(res_fingerprint));
                headers.set::<HeaderBloomStatus>(HeaderBloomStatus(HeaderBloomStatusValue::Hit));

                // Serve cached response
                Self::respond(method, status, headers, res_body_string)
            }
            Err(err) => {
                error!("failed parsing cached response: {}", err);

                Self::dispatch_failure(method)
            }
        }
    }

    fn dispatch_fetched(
        method: &Method,
        status: &StatusCode,
        mut headers: Headers,
        bloom_status: HeaderBloomStatusValue,
        body_string: String,
        fingerprint: Option<String>,
    ) -> ProxyServeFuture {
        // Process ETag for content?
        if let Some(fingerprint_value) = fingerprint {
            ProxyHeader::set_etag(&mut headers, Self::fingerprint_etag(fingerprint_value));
        }

        headers.set(HeaderBloomStatus(bloom_status));

        Self::respond(method, *status, headers, body_string)
    }

    fn dispatch_failure(method: &Method) -> ProxyServeFuture {
        let status = StatusCode::BadGateway;

        let mut headers = Headers::new();

        headers.set::<HeaderBloomStatus>(HeaderBloomStatus(HeaderBloomStatusValue::Offline));

        Self::respond(method, status, headers, format!("{}", status))
    }

    fn fingerprint_etag(fingerprint: String) -> ETag {
        ETag(EntityTag::new(false, fingerprint))
    }

    fn respond(
        method: &Method,
        status: StatusCode,
        headers: Headers,
        body_string: String,
    ) -> ProxyServeFuture {
        Box::new(future::ok(match method {
            &Method::Get | &Method::Post | &Method::Patch | &Method::Put | &Method::Delete => {
                Response::new()
                    .with_status(status)
                    .with_headers(headers)
                    .with_body(body_string)
            }
            _ => Response::new().with_status(status).with_headers(headers),
        }))
    }
}
<commit_msg>RB<commit_after>// Bloom
//
// HTTP REST API caching middleware
// Copyright: 2017, Valerian Saliou <valerian@valeriansaliou.name>
// License: Mozilla Public License v2.0 (MPL v2.0)

use futures::future::{self, Future};
use httparse;
use hyper::{Error, Method, StatusCode, Headers};
use hyper::header::{Origin, IfNoneMatch, ETag, EntityTag};
use hyper::server::{Request, Response};

use super::header::ProxyHeader;
use super::tunnel::ProxyTunnel;
use header::janitor::HeaderJanitor;
use header::request_shard::HeaderRequestBloomRequestShard;
use header::status::{HeaderBloomStatus, HeaderBloomStatusValue};
use cache::read::CacheRead;
use cache::write::CacheWrite;
use cache::route::CacheRoute;
use LINE_FEED;

pub struct ProxyServe;

const CACHED_PARSE_MAX_HEADERS: usize = 100;

pub type ProxyServeFuture = Box<Future<Item = Response, Error = Error>>;

impl ProxyServe {
    pub fn handle(req: Request) -> ProxyServeFuture {
        info!("handled request: {} on {}", req.method(), req.path());

        if req.headers().has::<HeaderRequestBloomRequestShard>() == true {
            match *req.method() {
                Method::Options | Method::Head | Method::Get | Method::Post | Method::Patch |
                Method::Put | Method::Delete => Self::accept(req),
                _ => Self::reject(req, StatusCode::MethodNotAllowed),
            }
        } else {
            Self::reject(req, StatusCode::NotExtended)
        }
    }

    fn accept(req: Request) -> ProxyServeFuture {
        Self::tunnel(req)
    }

    fn reject(req: Request, status: StatusCode) -> ProxyServeFuture {
        let mut headers = Headers::new();

        headers.set::<HeaderBloomStatus>(HeaderBloomStatus(HeaderBloomStatusValue::Reject));

        Self::respond(&req.method(), status, headers, format!("{}", status))
    }

    fn tunnel(req: Request) -> ProxyServeFuture {
        let (method, uri, version, headers, body) = req.deconstruct();
        let (headers, auth, shard) = ProxyHeader::parse_from_request(headers);

        let auth_hash = CacheRoute::hash(&auth);

        let (ns, ns_mask) = CacheRoute::gen_key_cache(
            shard,
            &auth_hash,
            version,
            &method,
            uri.path(),
            uri.query(),
            headers.get::<Origin>(),
        );

        info!("tunneling for ns = {}", ns);

        Box::new(
            CacheRead::acquire(&ns, &method)
                .or_else(|_| Err(Error::Incomplete))
                .and_then(move |result| {
                    match result {
                        Ok(value) => Self::dispatch_cached(&method, &headers, &value.0, value.1),
                        Err(_) => {
                            // Clone method value for closures. Sadly, it looks like Rust borrow \
                            //   checker doesnt discriminate properly on this check.
                            let method_success = method.to_owned();
                            let method_failure = method.to_owned();

                            Box::new(
                                ProxyTunnel::run(&method, &uri, &headers, body, shard)
                                    .and_then(move |tunnel_res| {
                                        CacheWrite::save(
                                            ns,
                                            ns_mask,
                                            auth_hash,
                                            shard,
                                            method,
                                            version,
                                            tunnel_res.status(),
                                            tunnel_res.headers().to_owned(),
                                            tunnel_res.body(),
                                        )
                                    })
                                    .and_then(move |mut result| match result.body {
                                        Ok(body_string) => {
                                            Self::dispatch_fetched(
                                                &method_success,
                                                &result.status,
                                                result.headers,
                                                HeaderBloomStatusValue::Miss,
                                                body_string,
                                                result.fingerprint,
                                            )
                                        }
                                        Err(body_string_values) => {
                                            match body_string_values {
                                                Some(body_string) => {
                                                    // Enforce clean headers, has usually they get \
                                                    //   cleaned from cache writer
                                                    HeaderJanitor::clean(&mut result.headers);

                                                    Self::dispatch_fetched(
                                                        &method_success,
                                                        &result.status,
                                                        result.headers,
                                                        HeaderBloomStatusValue::Direct,
                                                        body_string,
                                                        result.fingerprint,
                                                    )
                                                }
                                                _ => Self::dispatch_failure(&method_success),
                                            }
                                        }
                                    })
                                    .or_else(move |_| Self::dispatch_failure(&method_failure)),
                            )
                        }
                    }
                }),
        )
    }

    fn dispatch_cached(
        method: &Method,
        headers: &Headers,
        res_string: &str,
        res_fingerprint: String,
    ) -> ProxyServeFuture {
        // Check if not modified?
        let isnt_modified = match headers.get::<IfNoneMatch>() {
            Some(req_if_none_match) => {
                match *req_if_none_match {
                    IfNoneMatch::Any => true,
                    IfNoneMatch::Items(ref req_etags) => {
                        if let Some(req_etag) = req_etags.first() {
                            req_etag.weak_eq(&EntityTag::new(false, res_fingerprint.to_owned()))
                        } else {
                            false
                        }
                    }
                }
            }
            _ => false,
        };

        // Response not modified for client?
        if isnt_modified == true {
            // Process non-modified + cached headers
            let mut headers = Headers::new();

            ProxyHeader::set_etag(&mut headers, Self::fingerprint_etag(res_fingerprint));
            headers.set::<HeaderBloomStatus>(HeaderBloomStatus(HeaderBloomStatusValue::Hit));

            // Serve non-modified response
            return Self::respond(method, StatusCode::NotModified, headers, String::from(""));
        }

        // Response modified
        let mut headers = [httparse::EMPTY_HEADER; CACHED_PARSE_MAX_HEADERS];
        let mut res = httparse::Response::new(&mut headers);

        // Split headers from body
        let mut res_body_string = String::new();
        let mut is_last_line_empty = false;

        for res_line in res_string.lines() {
            if res_body_string.is_empty() == false || is_last_line_empty == true {
                // Write to body
                res_body_string.push_str(res_line.as_ref());
                res_body_string.push_str(LINE_FEED);
            }

            is_last_line_empty = res_line.is_empty();
        }

        match res.parse(res_string.as_bytes()) {
            Ok(_) => {
                // Process cached status
                let code = res.code.unwrap_or(500u16);
                let status = StatusCode::try_from(code).unwrap_or(StatusCode::Unregistered(code));

                // Process cached headers
                let mut headers = Headers::new();

                for header in res.headers {
                    if let (Ok(header_name), Ok(header_value)) =
                        (
                            String::from_utf8(Vec::from(header.name)),
                            String::from_utf8(Vec::from(header.value)),
                        )
                    {
                        headers.set_raw(header_name, header_value);
                    }
                }

                ProxyHeader::set_etag(&mut headers, Self::fingerprint_etag(res_fingerprint));
                headers.set::<HeaderBloomStatus>(HeaderBloomStatus(HeaderBloomStatusValue::Hit));

                // Serve cached response
                Self::respond(method, status, headers, res_body_string)
            }
            Err(err) => {
                error!("failed parsing cached response: {}", err);

                Self::dispatch_failure(method)
            }
        }
    }

    fn dispatch_fetched(
        method: &Method,
        status: &StatusCode,
        mut headers: Headers,
        bloom_status: HeaderBloomStatusValue,
        body_string: String,
        fingerprint: Option<String>,
    ) -> ProxyServeFuture {
        // Process ETag for content?
        if let Some(fingerprint_value) = fingerprint {
            ProxyHeader::set_etag(&mut headers, Self::fingerprint_etag(fingerprint_value));
        }

        headers.set(HeaderBloomStatus(bloom_status));

        Self::respond(method, *status, headers, body_string)
    }

    fn dispatch_failure(method: &Method) -> ProxyServeFuture {
        let status = StatusCode::BadGateway;

        let mut headers = Headers::new();

        headers.set::<HeaderBloomStatus>(HeaderBloomStatus(HeaderBloomStatusValue::Offline));

        Self::respond(method, status, headers, format!("{}", status))
    }

    fn fingerprint_etag(fingerprint: String) -> ETag {
        ETag(EntityTag::new(false, fingerprint))
    }

    fn respond(
        method: &Method,
        status: StatusCode,
        headers: Headers,
        body_string: String,
    ) -> ProxyServeFuture {
        Box::new(future::ok(match method {
            &Method::Get | &Method::Post | &Method::Patch | &Method::Put | &Method::Delete => {
                Response::new()
                    .with_status(status)
                    .with_headers(headers)
                    .with_body(body_string)
            }
            _ => Response::new().with_status(status).with_headers(headers),
        }))
    }
}
<|endoftext|>


<commit_before>extern crate anagram;

#[test]
fn test_no_matches() {
    let inputs = ["hello", "world", "zombies", "pants"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for("diaper", &inputs), outputs);
}

#[test]
#[ignore]
fn test_detect_simple_anagram() {
    let inputs = ["tan", "stand", "at"];
    let outputs: Vec<&str> = vec!["tan"];
    assert_eq!(anagram::anagrams_for("ant", &inputs), outputs);
}

#[test]
#[ignore]
fn test_does_not_confuse_different_duplicates() {
    let inputs = ["eagle"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for("galea", &inputs), outputs);
}

#[test]
#[ignore]
fn test_eliminate_anagram_subsets() {
    let inputs = ["dog", "goody"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for("good", &inputs), outputs);
}

#[test]
#[ignore]
fn test_detect_anagram() {
    let inputs = ["enlists", "google", "inlets", "banana"];
    let outputs: Vec<&str> = vec!["inlets"];
    assert_eq!(anagram::anagrams_for("listen", &inputs), outputs);
}

#[test]
#[ignore]
fn test_multiple_anagrams() {
    let inputs = ["gallery", "ballerina", "regally", "clergy", "largely", "leading"];
    let mut outputs: Vec<&str> = vec!["gallery", "regally", "largely"];
    outputs.sort();
    let mut result = anagram::anagrams_for("allergy", &inputs);
    result.sort();
    assert_eq!(result, outputs);
}

#[test]
#[ignore]
fn test_case_insensitive_anagrams() {
    let inputs = ["cashregister", "Carthorse", "radishes"];
    let outputs: Vec<&str> = vec!["Carthorse"];
    assert_eq!(anagram::anagrams_for("Orchestra", &inputs), outputs);
}

#[test]
#[ignore]
fn test_unicode_anagrams() {
    // These words don't make sense, they're just greek letters cobbled together.
    let inputs = ["ΒΓΑ", "ΒΓΔ", "γβα"];
    let outputs: Vec<&str> = vec!["ΒΓΑ", "γβα"];
    assert_eq!(anagram::anagrams_for("ΑΒΓ", &inputs), outputs);
}

#[test]
#[ignore]
fn test_misleading_unicode_anagrams() {
    // Despite what a human might think these words different letters, the input uses Greek A and B
    // while the list of potential anagrams uses Latin A and B.
    let inputs = ["ABΓ"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for("ΑΒΓ", &inputs), outputs);
}

#[test]
#[ignore]
fn test_does_not_detect_a_word_as_its_own_anagram() {
    let inputs = ["banana"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for("banana", &inputs), outputs);
}

#[test]
#[ignore]
fn test_does_not_detect_a_differently_cased_word_as_its_own_anagram() {
    let inputs = ["bAnana"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for("banana", &inputs), outputs);
}

#[test]
#[ignore]
fn test_does_not_detect_a_differently_cased_unicode_word_as_its_own_anagram() {
    let inputs = ["ΑΒγ"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for("ΑΒΓ", &inputs), outputs);
}
<commit_msg>Test anagram for same bytes but different chars<commit_after>extern crate anagram;

#[test]
fn test_no_matches() {
    let inputs = ["hello", "world", "zombies", "pants"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for("diaper", &inputs), outputs);
}

#[test]
#[ignore]
fn test_detect_simple_anagram() {
    let inputs = ["tan", "stand", "at"];
    let outputs: Vec<&str> = vec!["tan"];
    assert_eq!(anagram::anagrams_for("ant", &inputs), outputs);
}

#[test]
#[ignore]
fn test_does_not_confuse_different_duplicates() {
    let inputs = ["eagle"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for("galea", &inputs), outputs);
}

#[test]
#[ignore]
fn test_eliminate_anagram_subsets() {
    let inputs = ["dog", "goody"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for("good", &inputs), outputs);
}

#[test]
#[ignore]
fn test_detect_anagram() {
    let inputs = ["enlists", "google", "inlets", "banana"];
    let outputs: Vec<&str> = vec!["inlets"];
    assert_eq!(anagram::anagrams_for("listen", &inputs), outputs);
}

#[test]
#[ignore]
fn test_multiple_anagrams() {
    let inputs = ["gallery", "ballerina", "regally", "clergy", "largely", "leading"];
    let mut outputs: Vec<&str> = vec!["gallery", "regally", "largely"];
    outputs.sort();
    let mut result = anagram::anagrams_for("allergy", &inputs);
    result.sort();
    assert_eq!(result, outputs);
}

#[test]
#[ignore]
fn test_case_insensitive_anagrams() {
    let inputs = ["cashregister", "Carthorse", "radishes"];
    let outputs: Vec<&str> = vec!["Carthorse"];
    assert_eq!(anagram::anagrams_for("Orchestra", &inputs), outputs);
}

#[test]
#[ignore]
fn test_unicode_anagrams() {
    // These words don't make sense, they're just greek letters cobbled together.
    let inputs = ["ΒΓΑ", "ΒΓΔ", "γβα"];
    let outputs: Vec<&str> = vec!["ΒΓΑ", "γβα"];
    assert_eq!(anagram::anagrams_for("ΑΒΓ", &inputs), outputs);
}

#[test]
#[ignore]
fn test_misleading_unicode_anagrams() {
    // Despite what a human might think these words different letters, the input uses Greek A and B
    // while the list of potential anagrams uses Latin A and B.
    let inputs = ["ABΓ"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for("ΑΒΓ", &inputs), outputs);
}

#[test]
#[ignore]
fn test_does_not_detect_a_word_as_its_own_anagram() {
    let inputs = ["banana"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for("banana", &inputs), outputs);
}

#[test]
#[ignore]
fn test_does_not_detect_a_differently_cased_word_as_its_own_anagram() {
    let inputs = ["bAnana"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for("banana", &inputs), outputs);
}

#[test]
#[ignore]
fn test_does_not_detect_a_differently_cased_unicode_word_as_its_own_anagram() {
    let inputs = ["ΑΒγ"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for("ΑΒΓ", &inputs), outputs);
}

#[test]
#[ignore]
fn test_same_bytes_different_chars() {
    let inputs = ["€a"]; // E2 82 AC 61
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for(
        "a⬂", // 61 E2 AC 82
        &inputs), outputs);
}
<|endoftext|>


<commit_before>extern crate getopts;
extern crate markovpass;

use markovpass::PassphraseMarkovChain;
use std::io::Write;

fn build_opts() -> getopts::Options {
    let mut opts = getopts::Options::new();
    opts.optopt("n", "", "Number of passphrases to generate (default 1)", "NUM");
    opts.optopt("e", "", "Minimum entropy (default 60)", "MINENTROPY");
    opts.optopt("l", "", "NGram length (default 3)", "LENGTH");
    opts.optopt("w", "", "Minimum word length for corpus (default 5)", "LENGTH");
    opts.optflag("h", "help", "display this help and exit");

    opts
}

fn parse_flag<T: std::str::FromStr>(matches: &getopts::Matches, flag: &str, default: T)
        -> Result<T, &'static str> {
    matches.opt_str(flag)
        .map(|c| c.parse::<T>())
        .unwrap_or(Ok(default))
        .map_err(|_| "Failed to parse flag.")
}

fn parse_args(opts: &getopts::Options, args: &Vec<String>)
        -> Result<(String, usize, f64, usize, usize), &'static str> {
    let matches = try!(opts.parse(&args[1..]).map_err(|_| "Failed to parse arguments."));

    if matches.opt_present("h") || matches.free.len() > 1 {
        return Err("Failed to parse arguments.");
    };

    let number = try!(parse_flag(&matches, "n", 1));
    let min_entropy = try!(parse_flag(&matches, "e", 60.0));
    let ngram_length = try!(parse_flag(&matches, "l", 3));
    let min_word_length = try!(parse_flag(&matches, "w", 5));

    let filename = if matches.free.is_empty() {
        "-".to_string()
    } else {
        matches.free[0].clone()
    };

    Ok((filename, number, min_entropy, ngram_length, min_word_length))
}

fn get_corpus(filename: &str) -> Result<String, std::io::Error> {
    let mut input: Box<std::io::Read> = if filename == "-" {
        Box::new(std::io::stdin())
    } else {
        let file = try!(std::fs::File::open(&filename));
        Box::new(file)
    };
    let mut corpus = String::new();
    try!(input.read_to_string(&mut corpus));

    Ok(corpus)
}

fn clean_word(word: &str, min_length: usize) -> Option<&str> {
    let word = word.trim_matches(|c: char| !c.is_alphabetic());

    if word.chars().all(|c: char| c.is_alphabetic()) && word.len() >= min_length {
        Some(word)
    } else {
        None
    }
}

fn get_ngrams(corpus: &str, ngram_length: usize, min_word_length: usize) -> Vec<String> {
    let words = corpus.split_whitespace()
      .filter_map(|word| clean_word(word, min_word_length));
    let cleaned_corpus = Some("").into_iter().chain(words).collect::<Vec<&str>>().join(" ");
    let char_count = cleaned_corpus.chars().count();
    if char_count < ngram_length { return vec![]; };
    let count = char_count - ngram_length + 1;

    let mut chars = cleaned_corpus.chars();
    let mut ngrams = Vec::with_capacity(count);
    for _ in 0..count {
        let ngram: String = chars.clone().take(ngram_length).collect();
        ngrams.push(ngram.to_lowercase());
        chars.next();
    };

    ngrams
}

fn gen_passphrases(ngrams: Vec<String>, number: usize, min_entropy: f64)
        -> Result<Vec<(String, f64)>, &'static str> {
    if ngrams.is_empty() { return Err("No NGrams found."); };
    let chain = try!(PassphraseMarkovChain::new(ngrams.iter().cloned()));
    let mut passphrases = Vec::with_capacity(number);
    for _ in 0..number {
        passphrases.push(chain.passphrase(min_entropy));
    };

    Ok(passphrases)
}

fn print_usage(program: &str, opts: &getopts::Options) {
    let brief = format!("Usage: {} [FILE] [options]", program);
    print!("{}", opts.usage(&brief));
}

fn write_error(message: &str) {
    writeln!(&mut std::io::stderr(), "{}", &message).expect("Failed to write to stderr.");
}

fn main() {
    let args: Vec<String> = std::env::args().collect();
    let program = args[0].clone();
    let opts = build_opts();

    let (filename, number, min_entropy, ngram_length, min_word_length) =
            match parse_args(&opts, &args) {
        Ok(parsed_args) => { parsed_args },
        Err(_) => {
            print_usage(&program, &opts);
            return;
        }
    };
    if ngram_length < 2 {
        write_error("Ngram length must be greater than one.");
    };
    let corpus = match get_corpus(&filename) {
        Ok(corpus) => { corpus },
        Err(_) => {
            write_error(&format!("{}: {}: {}", &program, &filename, "Failed to read input."));
            return;
        },
    };
    let ngrams = get_ngrams(&corpus, ngram_length, min_word_length);
    let passphrases = match gen_passphrases(ngrams, number, min_entropy) {
        Ok(passphrases) => { passphrases },
        Err(e) => {
            write_error(&format!("{}: {}: {}", &program, &filename, e));
            return;
        },
    };

    for (passphrase, entropy) in passphrases {
        println!("{} <{}>", passphrase, entropy);
    };
}
<commit_msg>Use Option<String> for filename<commit_after>extern crate getopts;
extern crate markovpass;

use markovpass::PassphraseMarkovChain;
use std::io::Write;

fn build_opts() -> getopts::Options {
    let mut opts = getopts::Options::new();
    opts.optopt("n", "", "Number of passphrases to generate (default 1)", "NUM");
    opts.optopt("e", "", "Minimum entropy (default 60)", "MINENTROPY");
    opts.optopt("l", "", "NGram length (default 3)", "LENGTH");
    opts.optopt("w", "", "Minimum word length for corpus (default 5)", "LENGTH");
    opts.optflag("h", "help", "display this help and exit");

    opts
}

fn parse_flag<T: std::str::FromStr>(matches: &getopts::Matches, flag: &str, default: T)
        -> Result<T, &'static str> {
    matches.opt_str(flag)
        .map(|c| c.parse::<T>())
        .unwrap_or(Ok(default))
        .map_err(|_| "Failed to parse flag.")
}

fn parse_args(opts: &getopts::Options, args: &Vec<String>)
        -> Result<(Option<String>, usize, f64, usize, usize), &'static str> {
    let matches = try!(opts.parse(&args[1..]).map_err(|_| "Failed to parse arguments."));

    if matches.opt_present("h") || matches.free.len() > 1 {
        return Err("Failed to parse arguments.");
    };

    let number = try!(parse_flag(&matches, "n", 1));
    let min_entropy = try!(parse_flag(&matches, "e", 60.0));
    let ngram_length = try!(parse_flag(&matches, "l", 3));
    let min_word_length = try!(parse_flag(&matches, "w", 5));

    let filename = if matches.free.is_empty() || matches.free[0] == "-" {
        None
    } else {
        Some(matches.free[0].clone())
    };

    Ok((filename, number, min_entropy, ngram_length, min_word_length))
}

fn get_corpus(filename: Option<&str>) -> Result<String, std::io::Error> {
    let mut input: Box<std::io::Read> = match filename {
        Some(filename) => Box::new(try!(std::fs::File::open(&filename))),
        None => Box::new(std::io::stdin()),
    };
    let mut corpus = String::new();
    try!(input.read_to_string(&mut corpus));

    Ok(corpus)
}

fn clean_word(word: &str, min_length: usize) -> Option<&str> {
    let word = word.trim_matches(|c: char| !c.is_alphabetic());

    if word.chars().all(|c: char| c.is_alphabetic()) && word.len() >= min_length {
        Some(word)
    } else {
        None
    }
}

fn get_ngrams(corpus: &str, ngram_length: usize, min_word_length: usize) -> Vec<String> {
    let words = corpus.split_whitespace()
      .filter_map(|word| clean_word(word, min_word_length));
    let cleaned_corpus = Some("").into_iter().chain(words).collect::<Vec<&str>>().join(" ");
    let char_count = cleaned_corpus.chars().count();
    if char_count < ngram_length { return vec![]; };
    let count = char_count - ngram_length + 1;

    let mut chars = cleaned_corpus.chars();
    let mut ngrams = Vec::with_capacity(count);
    for _ in 0..count {
        let ngram: String = chars.clone().take(ngram_length).collect();
        ngrams.push(ngram.to_lowercase());
        chars.next();
    };

    ngrams
}

fn gen_passphrases(ngrams: Vec<String>, number: usize, min_entropy: f64)
        -> Result<Vec<(String, f64)>, &'static str> {
    if ngrams.is_empty() { return Err("No NGrams found."); };
    let chain = try!(PassphraseMarkovChain::new(ngrams.iter().cloned()));
    let mut passphrases = Vec::with_capacity(number);
    for _ in 0..number {
        passphrases.push(chain.passphrase(min_entropy));
    };

    Ok(passphrases)
}

fn print_usage(program: &str, opts: &getopts::Options) {
    let brief = format!("Usage: {} [FILE] [options]", program);
    print!("{}", opts.usage(&brief));
}

fn write_error(message: &str) {
    writeln!(&mut std::io::stderr(), "{}", &message).expect("Failed to write to stderr.");
}

fn main() {
    let args: Vec<String> = std::env::args().collect();
    let program = args[0].clone();
    let opts = build_opts();

    let (filename, number, min_entropy, ngram_length, min_word_length) =
            match parse_args(&opts, &args) {
        Ok(parsed_args) => { parsed_args },
        Err(_) => {
            print_usage(&program, &opts);
            return;
        }
    };
    if ngram_length < 2 {
        write_error("Ngram length must be greater than one.");
    };
    let corpus = match get_corpus(filename.as_ref().map(String::as_ref)) {
        Ok(corpus) => { corpus },
        Err(_) => {
            let filename_str = filename.unwrap_or("-".to_string());
            write_error(&format!("{}: {}: {}", &program, &filename_str, "Failed to read input."));
            return;
        },
    };
    let ngrams = get_ngrams(&corpus, ngram_length, min_word_length);
    let passphrases = match gen_passphrases(ngrams, number, min_entropy) {
        Ok(passphrases) => { passphrases },
        Err(e) => {
            write_error(&format!("{}: {}", &program, e));
            return;
        },
    };

    for (passphrase, entropy) in passphrases {
        println!("{} <{}>", passphrase, entropy);
    };
}
<|endoftext|>