<commit_before>extern mod std;

use basics::*;
use std::hashmap::HashSet;

mod basics;

pub trait TimingPolicy {
    fn network_latency(&self, from: ServerID, to: ServerID) -> uint;
}

struct Uniform(uint, uint);
impl TimingPolicy for Uniform {
    fn network_latency(&self, _from: ServerID, _to: ServerID) -> uint {
        match *self {
          Uniform(min, max) => randrange(min, max)
        }
    }
}

struct Stochastic {
    afrac: f64,
    a: ~TimingPolicy,
    b: ~TimingPolicy,
}
impl TimingPolicy for Stochastic {
    fn network_latency(&self, from: ServerID, to: ServerID) -> uint {
        use std::rand::distributions::{IndependentSample, Range};
        let range = Range::new(0.0, 1.0);
        let sample = range.ind_sample(&mut std::rand::task_rng());
        if sample < self.afrac {
            self.a.network_latency(from, to)
        } else {
            self.b.network_latency(from, to)
        }
    }
}

struct Partitions(~[Partition]);

struct Partition {
    servers: HashSet<ServerID>,
    timing: ~TimingPolicy,
}

impl Partition {
    fn new(ids: &[ServerID], timing: ~TimingPolicy) -> Partition {
        Partition {
            servers: newHashSet(ids),
            timing: timing,
        }
    }
}

impl TimingPolicy for Partitions {
    fn network_latency(&self, from: ServerID, to: ServerID) -> uint {
        for partition in self.iter() {
            if partition.servers.contains(&from) &&
               partition.servers.contains(&to) {
                return partition.timing.network_latency(from, to);
            }
        }
        return INFINITY;
    }
}

struct Link {
    from: ServerID,
    to: ServerID,
    timing: ~TimingPolicy,
}
macro_rules! link(
    ($name:expr: $from:expr -> $to:expr) => (
        Link {
            from: ServerID($from),
            to: ServerID($to),
            timing: make(stringify!($name))
        }
    );
)

struct Links {
    links: ~[Link],
    other: ~TimingPolicy,
}

impl TimingPolicy for Links {
    fn network_latency(&self, from: ServerID, to: ServerID) -> uint {
        for link in self.links.iter() {
            if link.from == from && link.to == to {
                return link.timing.network_latency(from, to);
            }
        }
        return self.other.network_latency(from, to);
    }
}

macro_rules! partition(
    ($name:expr: $($id:expr) +) => (
        Partition::new([$(ServerID($id),)+], make(stringify!($name)))
    );
)

pub fn make(name: &str) -> ~TimingPolicy {
    return match name {
        "Delay1pct" => ~Stochastic {
            afrac: 0.99,
            a: ~Uniform(2000, 5000) as ~TimingPolicy,
            b: ~Uniform(5000, 100000) as ~TimingPolicy,
        } as ~TimingPolicy,
        "Down" => ~Uniform(INFINITY, INFINITY)
        as ~TimingPolicy,
        "LAN" => ~Uniform(2000, 5000)
        as ~TimingPolicy,
        "RAMCloud" => ~Uniform(5, 10)
        as ~TimingPolicy,
        "WAN" => ~Uniform(10000, 20000)
        as ~TimingPolicy,
        "P1" => ~Partitions(~[
                    partition!(Down: 1),
                    partition!(LAN:  2 3 4 5),
        ]) as ~TimingPolicy,
        "P1-RAMCloud" => ~Partitions(~[
                    partition!(Down: 1),
                    partition!(RAMCloud:  2 3 4 5),
        ]) as ~TimingPolicy,
        "P2" => ~Partitions(~[
                    partition!(Down: 1 2),
                    partition!(LAN:  3 4 5),
        ]) as ~TimingPolicy,
        "P2-RAMCloud" => ~Partitions(~[
                    partition!(Down: 1 2),
                    partition!(RAMCloud:  3 4 5),
        ]) as ~TimingPolicy,
        "L1" => ~Links {
            links: ~[link!(WAN: 1 -> 2)],
            other: make("LAN"),
        } as ~TimingPolicy,
        "Deian" => ~Partitions(~[
                    partition!(LAN: 1 2 3 4),
                    partition!(WAN: 1 2 3 4 5),
        ]) as ~TimingPolicy,
        "BadRecv" => ~Links {
            links: ~[
                link!(Down: 2 -> 1),
                link!(Down: 3 -> 1),
                link!(Down: 4 -> 1),
                link!(Down: 5 -> 1),
            ],
            other: make("LAN"),
        } as ~TimingPolicy,
        _ => fail!("Unknown timing policy name: {}", name),
    }
}

<commit_msg>Add P1-WAN policy<commit_after>extern mod std;

use basics::*;
use std::hashmap::HashSet;

mod basics;

pub trait TimingPolicy {
    fn network_latency(&self, from: ServerID, to: ServerID) -> uint;
}

struct Uniform(uint, uint);
impl TimingPolicy for Uniform {
    fn network_latency(&self, _from: ServerID, _to: ServerID) -> uint {
        match *self {
          Uniform(min, max) => randrange(min, max)
        }
    }
}

struct Stochastic {
    afrac: f64,
    a: ~TimingPolicy,
    b: ~TimingPolicy,
}
impl TimingPolicy for Stochastic {
    fn network_latency(&self, from: ServerID, to: ServerID) -> uint {
        use std::rand::distributions::{IndependentSample, Range};
        let range = Range::new(0.0, 1.0);
        let sample = range.ind_sample(&mut std::rand::task_rng());
        if sample < self.afrac {
            self.a.network_latency(from, to)
        } else {
            self.b.network_latency(from, to)
        }
    }
}

struct Partitions(~[Partition]);

struct Partition {
    servers: HashSet<ServerID>,
    timing: ~TimingPolicy,
}

impl Partition {
    fn new(ids: &[ServerID], timing: ~TimingPolicy) -> Partition {
        Partition {
            servers: newHashSet(ids),
            timing: timing,
        }
    }
}

impl TimingPolicy for Partitions {
    fn network_latency(&self, from: ServerID, to: ServerID) -> uint {
        for partition in self.iter() {
            if partition.servers.contains(&from) &&
               partition.servers.contains(&to) {
                return partition.timing.network_latency(from, to);
            }
        }
        return INFINITY;
    }
}

struct Link {
    from: ServerID,
    to: ServerID,
    timing: ~TimingPolicy,
}
macro_rules! link(
    ($name:expr: $from:expr -> $to:expr) => (
        Link {
            from: ServerID($from),
            to: ServerID($to),
            timing: make(stringify!($name))
        }
    );
)

struct Links {
    links: ~[Link],
    other: ~TimingPolicy,
}

impl TimingPolicy for Links {
    fn network_latency(&self, from: ServerID, to: ServerID) -> uint {
        for link in self.links.iter() {
            if link.from == from && link.to == to {
                return link.timing.network_latency(from, to);
            }
        }
        return self.other.network_latency(from, to);
    }
}

macro_rules! partition(
    ($name:expr: $($id:expr) +) => (
        Partition::new([$(ServerID($id),)+], make(stringify!($name)))
    );
)

pub fn make(name: &str) -> ~TimingPolicy {
    return match name {
        "Delay1pct" => ~Stochastic {
            afrac: 0.99,
            a: ~Uniform(2000, 5000) as ~TimingPolicy,
            b: ~Uniform(5000, 100000) as ~TimingPolicy,
        } as ~TimingPolicy,
        "Down" => ~Uniform(INFINITY, INFINITY)
        as ~TimingPolicy,
        "LAN" => ~Uniform(2000, 5000)
        as ~TimingPolicy,
        "RAMCloud" => ~Uniform(5, 10)
        as ~TimingPolicy,
        "WAN" => ~Uniform(10000, 20000)
        as ~TimingPolicy,
        "P1" => ~Partitions(~[
                    partition!(Down: 1),
                    partition!(LAN:  2 3 4 5),
        ]) as ~TimingPolicy,
        "P1-RAMCloud" => ~Partitions(~[
                    partition!(Down: 1),
                    partition!(RAMCloud:  2 3 4 5),
        ]) as ~TimingPolicy,
        "P1-WAN" => ~Partitions(~[
                    partition!(Down: 1),
                    partition!(WAN:  2 3 4 5),
        ]) as ~TimingPolicy,
        "P2" => ~Partitions(~[
                    partition!(Down: 1 2),
                    partition!(LAN:  3 4 5),
        ]) as ~TimingPolicy,
        "P2-RAMCloud" => ~Partitions(~[
                    partition!(Down: 1 2),
                    partition!(RAMCloud:  3 4 5),
        ]) as ~TimingPolicy,
        "L1" => ~Links {
            links: ~[link!(WAN: 1 -> 2)],
            other: make("LAN"),
        } as ~TimingPolicy,
        "Deian" => ~Partitions(~[
                    partition!(LAN: 1 2 3 4),
                    partition!(WAN: 1 2 3 4 5),
        ]) as ~TimingPolicy,
        "BadRecv" => ~Links {
            links: ~[
                link!(Down: 2 -> 1),
                link!(Down: 3 -> 1),
                link!(Down: 4 -> 1),
                link!(Down: 5 -> 1),
            ],
            other: make("LAN"),
        } as ~TimingPolicy,
        _ => fail!("Unknown timing policy name: {}", name),
    }
}

<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use layers::{ARGB32Format, ContainerLayerKind, Flip, NoFlip, RGB24Format, TextureLayerKind};
use layers::{VerticalFlip};
use layers;
use scene::Scene;
use texturegl::Texture;

use geom::matrix::{Matrix4, ortho};
use geom::point::Point2D;
use geom::size::Size2D;
use geom::rect::Rect;
use opengles::gl2::{ARRAY_BUFFER, COLOR_BUFFER_BIT, CLAMP_TO_EDGE, COMPILE_STATUS};
use opengles::gl2::{FRAGMENT_SHADER, LINK_STATUS, LINEAR, NO_ERROR, RGB, RGBA, BGRA, SCISSOR_BOX};
use opengles::gl2::{SCISSOR_TEST, STATIC_DRAW, TEXTURE_2D, TEXTURE_MAG_FILTER, TEXTURE_MIN_FILTER};
use opengles::gl2::{TEXTURE_WRAP_S, TEXTURE_WRAP_T, TEXTURE0};
use opengles::gl2::{TRIANGLE_STRIP, UNPACK_ALIGNMENT, UNPACK_CLIENT_STORAGE_APPLE};
use opengles::gl2::{UNPACK_ROW_LENGTH, UNSIGNED_BYTE, UNSIGNED_INT_8_8_8_8_REV, VERTEX_SHADER, VIEWPORT};
use opengles::gl2::{GLenum, GLint, GLsizei, GLuint, attach_shader, bind_buffer};
use opengles::gl2::{buffer_data, create_program, clear, clear_color};
use opengles::gl2::{compile_shader, create_shader, draw_arrays, disable, enable, is_enabled};
use opengles::gl2::{enable_vertex_attrib_array, gen_buffers, gen_textures};
use opengles::gl2::{get_attrib_location, get_error, get_integer_v, get_program_iv};
use opengles::gl2::{get_shader_info_log, get_shader_iv, active_texture};
use opengles::gl2::{get_uniform_location, link_program, pixel_store_i, scissor, shader_source};
use opengles::gl2::{tex_image_2d, tex_parameter_i, uniform_1i, uniform_matrix_4fv, use_program};
use opengles::gl2::{vertex_attrib_pointer_f32, viewport};

use std::libc::c_int;
use std::libc::c_uint;

pub fn FRAGMENT_SHADER_SOURCE() -> ~str {
    ~"
        #ifdef GL_ES
            precision mediump float;
        #endif

        varying vec2 vTextureCoord;

        uniform sampler2D uSampler;

        void main(void) {
            gl_FragColor = texture2D(uSampler, vTextureCoord);
        }
    "
}

pub fn VERTEX_SHADER_SOURCE() -> ~str {
    ~"
        attribute vec3 aVertexPosition;
        attribute vec2 aTextureCoord;

        uniform mat4 uMVMatrix;
        uniform mat4 uPMatrix;

        varying vec2 vTextureCoord;

        void main(void) {
            gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
            vTextureCoord = aTextureCoord;
        }
    "
}

pub fn load_shader(source_string: ~str, shader_type: GLenum) -> GLuint {
    let shader_id = create_shader(shader_type);
    shader_source(shader_id, [ source_string.as_bytes().to_owned() ]);
    compile_shader(shader_id);

    if get_error() != NO_ERROR {
        println(fmt!("error: %d", get_error() as int));
        fail!(~"failed to compile shader");
    }

    if get_shader_iv(shader_id, COMPILE_STATUS) == (0 as GLint) {
        println(fmt!("shader info log: %s", get_shader_info_log(shader_id)));
        fail!(~"failed to compile shader");
    }

    return shader_id;
}

pub struct RenderContext {
    program: GLuint,
    vertex_position_attr: c_int,
    texture_coord_attr: c_int,
    modelview_uniform: c_int,
    projection_uniform: c_int,
    sampler_uniform: c_int,
    vertex_buffer: GLuint,
    flipped_vertex_buffer: GLuint,
    texture_coord_buffer: GLuint,
}

pub fn RenderContext(program: GLuint) -> RenderContext {
    let (vertex_buffer, flipped_vertex_buffer, texture_coord_buffer) = init_buffers();
    let rc = RenderContext {
        program: program,
        vertex_position_attr: get_attrib_location(program, ~"aVertexPosition"),
        texture_coord_attr: get_attrib_location(program, ~"aTextureCoord"),
        modelview_uniform: get_uniform_location(program, ~"uMVMatrix"),
        projection_uniform: get_uniform_location(program, ~"uPMatrix"),
        sampler_uniform: get_uniform_location(program, ~"uSampler"),
        vertex_buffer: vertex_buffer,
        flipped_vertex_buffer: flipped_vertex_buffer,
        texture_coord_buffer: texture_coord_buffer,
    };

    enable_vertex_attrib_array(rc.vertex_position_attr as GLuint);
    enable_vertex_attrib_array(rc.texture_coord_attr as GLuint);

    rc
}

pub fn init_render_context() -> RenderContext {
    let vertex_shader = load_shader(VERTEX_SHADER_SOURCE(), VERTEX_SHADER);
    let fragment_shader = load_shader(FRAGMENT_SHADER_SOURCE(), FRAGMENT_SHADER);

    let program = create_program();
    attach_shader(program, vertex_shader);
    attach_shader(program, fragment_shader);
    link_program(program);

    if get_program_iv(program, LINK_STATUS) == (0 as GLint) {
        fail!(~"failed to initialize program");
    }

    use_program(program);
    enable(TEXTURE_2D);

    return RenderContext(program);
}

pub fn init_buffers() -> (GLuint, GLuint, GLuint) {
    let vertex_buffer = gen_buffers(1 as GLsizei)[0];
    bind_buffer(ARRAY_BUFFER, vertex_buffer);
    let vertices: [f32, ..8] = [
        0.0, 0.0,
        0.0, 1.0,
        1.0, 0.0,
        1.0, 1.0,
    ];
    buffer_data(ARRAY_BUFFER, vertices, STATIC_DRAW);

    let flipped_vertex_buffer = gen_buffers(1 as GLsizei)[0];
    bind_buffer(ARRAY_BUFFER, flipped_vertex_buffer);
    let flipped_vertices: [f32, ..8] = [
        0.0, 1.0,
        0.0, 0.0,
        1.0, 1.0,
        1.0, 0.0,
    ];
    buffer_data(ARRAY_BUFFER, flipped_vertices, STATIC_DRAW);

    let texture_coord_buffer = gen_buffers(1 as GLsizei)[0];
    bind_buffer(ARRAY_BUFFER, texture_coord_buffer);

    return (vertex_buffer, flipped_vertex_buffer, texture_coord_buffer);
}

pub fn bind_and_render_quad(render_context: RenderContext, texture: &Texture, flip: Flip) {
    active_texture(TEXTURE0);
    let _bound_texture = texture.bind();

    uniform_1i(render_context.sampler_uniform, 0);

    match flip {
        NoFlip => bind_buffer(ARRAY_BUFFER, render_context.vertex_buffer),
        VerticalFlip => bind_buffer(ARRAY_BUFFER, render_context.flipped_vertex_buffer),
    }

    vertex_attrib_pointer_f32(render_context.vertex_position_attr as GLuint, 3, false, 0, 0);

    // Create the texture coordinate array.
    bind_buffer(ARRAY_BUFFER, render_context.texture_coord_buffer);

    let vertices = [
        0.0f32, 1.0f32,
        0.0f32, 0.0f32,
        1.0f32, 1.0f32,
        1.0f32, 0.0f32,
    ];
    buffer_data(ARRAY_BUFFER, vertices, STATIC_DRAW);
    vertex_attrib_pointer_f32(render_context.texture_coord_attr as GLuint, 2, false, 0, 0);
    draw_arrays(TRIANGLE_STRIP, 0, 4);
}

// Layer rendering

pub trait Render {
    fn render(@mut self, render_context: RenderContext, transform: Matrix4<f32>);
}

impl Render for layers::ContainerLayer {
    fn render(@mut self, render_context: RenderContext, transform: Matrix4<f32>) {
        let old_rect_opt = if is_enabled(SCISSOR_TEST) {
            let mut old_rect = [0 as GLint, ..4];
            get_integer_v(SCISSOR_BOX, old_rect);
            Some(Rect(Point2D(old_rect[0], old_rect[1]), Size2D(old_rect[2], old_rect[3])))
        } else {
            None
        };

        match self.scissor {
            Some(rect) => {
                let size = Size2D((rect.size.width * transform.m11) as GLint,
                                  (rect.size.height * transform.m22) as GLint);

                // Get the viewport height so we can flip the origin horizontally
                // since glScissor measures from the bottom left of the viewport
                let mut viewport = [0 as GLint, ..4];
                get_integer_v(VIEWPORT, viewport);
                let w_height = viewport[3];
                let origin = Point2D((rect.origin.x * transform.m11 + transform.m41) as GLint,
                                     w_height
                                     - ((rect.origin.y * transform.m22 + transform.m42) as GLint)
                                     - size.height);
                let rect = Rect(origin, size);

                match old_rect_opt {
                    Some(old_rect) => {
                        // A parent ContainerLayer is already being scissored, so set the
                        // new scissor to the intersection of the two rects.
                        let intersection = rect.intersection(&old_rect);
                        match intersection {
                            Some(new_rect) => {
                                scissor(new_rect.origin.x,
                                        new_rect.origin.y,
                                        new_rect.size.width as GLsizei,
                                        new_rect.size.height as GLsizei);
                                maybe_get_error();
                            }
                            None => {
                                return; // Layer is occluded/offscreen
                            }
                        }
                    }
                    None => {
                        // We are the first ContainerLayer to be scissored.
                        // Check against the viewport to prevent invalid values
                        let w_rect = Rect(Point2D(0 as GLint, 0 as GLint),
                                          Size2D(viewport[2], viewport[3]));
                        let intersection = rect.intersection(&w_rect);
                        match intersection {
                            Some(new_rect) => {
                                enable(SCISSOR_TEST);
                                scissor(new_rect.origin.x,
                                        new_rect.origin.y,
                                        new_rect.size.width as GLsizei,
                                        new_rect.size.height as GLsizei);
                                maybe_get_error();
                            }
                            None => {
                                return; // Layer is offscreen
                            }
                        }
                    }
                }
            }
            None => {} // Nothing to do
        }

        let transform = transform.mul(&self.common.transform);
        for child in self.children() {
            render_layer(render_context, transform, child);
        }

        match (self.scissor, old_rect_opt) {
            (Some(_), Some(old_rect)) => {
                // Set scissor back to the parent's scissoring rect.
                scissor(old_rect.origin.x, old_rect.origin.y,
                        old_rect.size.width as GLsizei,
                        old_rect.size.height as GLsizei);
            }
            (Some(_), None) => {
                // Our parents are not being scissored, so disable scissoring for now
                disable(SCISSOR_TEST);
            }
            (None, _) => {} // Nothing to do
        }
    }
}

impl Render for layers::TextureLayer {
    fn render(@mut self, render_context: RenderContext, transform: Matrix4<f32>) {
        let transform = transform.mul(&self.common.transform);
        uniform_matrix_4fv(render_context.modelview_uniform, false, transform.to_array());
        bind_and_render_quad(render_context, self.texture.get(), self.flip);
    }
}

fn render_layer(render_context: RenderContext, transform: Matrix4<f32>, layer: layers::Layer) {
    match layer {
        ContainerLayerKind(container_layer) => {
            container_layer.render(render_context, transform);
        }
        TextureLayerKind(texture_layer) => {
            texture_layer.render(render_context, transform);
        }
    }
}

pub fn render_scene(render_context: RenderContext, scene: &Scene) {
    // Set the viewport.
    viewport(0 as GLint, 0 as GLint, scene.size.width as GLsizei, scene.size.height as GLsizei);

    // Clear the screen.
    clear_color(0.38f32, 0.36f32, 0.36f32, 1.0f32);
    clear(COLOR_BUFFER_BIT);

    // Set the projection matrix.
    let projection_matrix = ortho(0.0, scene.size.width, scene.size.height, 0.0, -10.0, 10.0);
    uniform_matrix_4fv(render_context.projection_uniform, false, projection_matrix.to_array());

    // Set up the initial modelview matrix.
    let transform = scene.transform;

    // Render the root layer.
    render_layer(render_context, transform, scene.root);
}

#[cfg(debug)]
fn maybe_get_error() {
    if get_error() != NO_ERROR {
        fail!("GL error: %d", get_error() as int);
    }
}

#[cfg(not(debug))]
fn maybe_get_error() {
    // do nothing
}
<commit_msg>Add flipping and modernize the codebase a bit<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use layers::{ARGB32Format, ContainerLayerKind, Flip, NoFlip, RGB24Format, TextureLayerKind};
use layers::{VerticalFlip};
use layers;
use scene::Scene;
use texturegl::Texture;

use geom::matrix::{Matrix4, ortho};
use geom::point::Point2D;
use geom::size::Size2D;
use geom::rect::Rect;
use opengles::gl2::{ARRAY_BUFFER, COLOR_BUFFER_BIT, CLAMP_TO_EDGE, COMPILE_STATUS};
use opengles::gl2::{FRAGMENT_SHADER, LINK_STATUS, LINEAR, NO_ERROR, RGB, RGBA, BGRA, SCISSOR_BOX};
use opengles::gl2::{SCISSOR_TEST, STATIC_DRAW, TEXTURE_2D, TEXTURE_MAG_FILTER, TEXTURE_MIN_FILTER};
use opengles::gl2::{TEXTURE_WRAP_S, TEXTURE_WRAP_T, TEXTURE0};
use opengles::gl2::{TRIANGLE_STRIP, UNPACK_ALIGNMENT, UNPACK_CLIENT_STORAGE_APPLE};
use opengles::gl2::{UNPACK_ROW_LENGTH, UNSIGNED_BYTE, UNSIGNED_INT_8_8_8_8_REV, VERTEX_SHADER, VIEWPORT};
use opengles::gl2::{GLenum, GLint, GLsizei, GLuint, attach_shader, bind_buffer};
use opengles::gl2::{buffer_data, create_program, clear, clear_color};
use opengles::gl2::{compile_shader, create_shader, draw_arrays, disable, enable, is_enabled};
use opengles::gl2::{enable_vertex_attrib_array, gen_buffers, gen_textures};
use opengles::gl2::{get_attrib_location, get_error, get_integer_v, get_program_iv};
use opengles::gl2::{get_shader_info_log, get_shader_iv, active_texture};
use opengles::gl2::{get_uniform_location, link_program, pixel_store_i, scissor, shader_source};
use opengles::gl2::{tex_image_2d, tex_parameter_i, uniform_1i, uniform_matrix_4fv, use_program};
use opengles::gl2::{vertex_attrib_pointer_f32, viewport};

use std::libc::c_int;
use std::libc::c_uint;

static FRAGMENT_SHADER_SOURCE: &'static str = "
    #ifdef GL_ES
        precision mediump float;
    #endif

    varying vec2 vTextureCoord;

    uniform sampler2D uSampler;

    void main(void) {
        gl_FragColor = texture2D(uSampler, vTextureCoord);
    }
";

static VERTEX_SHADER_SOURCE: &'static str = "
    attribute vec3 aVertexPosition;
    attribute vec2 aTextureCoord;

    uniform mat4 uMVMatrix;
    uniform mat4 uPMatrix;

    varying vec2 vTextureCoord;

    void main(void) {
        gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
        vTextureCoord = aTextureCoord;
    }
";

static VERTICES: [f32, ..12] = [
    0.0, 0.0, 0.0,
    0.0, 1.0, 0.0,
    1.0, 0.0, 0.0,
    1.0, 1.0, 0.0,
];

static TEXTURE_COORDINATES: [f32, ..8] = [
    0.0, 0.0,
    0.0, 1.0,
    1.0, 0.0,
    1.0, 1.0,
];

static FLIPPED_TEXTURE_COORDINATES: [f32, ..8] = [
    0.0, 1.0,
    0.0, 0.0,
    1.0, 1.0,
    1.0, 0.0,
];

pub fn load_shader(source_string: &str, shader_type: GLenum) -> GLuint {
    let shader_id = create_shader(shader_type);
    shader_source(shader_id, [ source_string.as_bytes().to_owned() ]);
    compile_shader(shader_id);

    if get_error() != NO_ERROR {
        println(fmt!("error: %d", get_error() as int));
        fail!("failed to compile shader");
    }

    if get_shader_iv(shader_id, COMPILE_STATUS) == (0 as GLint) {
        println(fmt!("shader info log: %s", get_shader_info_log(shader_id)));
        fail!("failed to compile shader");
    }

    return shader_id;
}

struct Buffers {
    vertex_buffer: GLuint,
    texture_coordinate_buffer: GLuint,
    flipped_texture_coordinate_buffer: GLuint,
}

pub struct RenderContext {
    program: GLuint,
    vertex_position_attr: c_int,
    texture_coord_attr: c_int,
    modelview_uniform: c_int,
    projection_uniform: c_int,
    sampler_uniform: c_int,
    buffers: Buffers,
}

impl RenderContext {
    fn new(program: GLuint) -> RenderContext {
        let render_context = RenderContext {
            program: program,
            vertex_position_attr: get_attrib_location(program, ~"aVertexPosition"),
            texture_coord_attr: get_attrib_location(program, ~"aTextureCoord"),
            modelview_uniform: get_uniform_location(program, ~"uMVMatrix"),
            projection_uniform: get_uniform_location(program, ~"uPMatrix"),
            sampler_uniform: get_uniform_location(program, ~"uSampler"),
            buffers: RenderContext::init_buffers(),
        };

        enable_vertex_attrib_array(render_context.vertex_position_attr as GLuint);
        enable_vertex_attrib_array(render_context.texture_coord_attr as GLuint);

        render_context
    }

    fn init_buffers() -> Buffers {
        let vertex_buffer = gen_buffers(1)[0];
        bind_buffer(ARRAY_BUFFER, vertex_buffer);
        buffer_data(ARRAY_BUFFER, VERTICES, STATIC_DRAW);

        let texture_coordinate_buffer = gen_buffers(1)[0];
        bind_buffer(ARRAY_BUFFER, texture_coordinate_buffer);
        buffer_data(ARRAY_BUFFER, TEXTURE_COORDINATES, STATIC_DRAW);

        let flipped_texture_coordinate_buffer = gen_buffers(1)[0];
        bind_buffer(ARRAY_BUFFER, flipped_texture_coordinate_buffer);
        buffer_data(ARRAY_BUFFER, FLIPPED_TEXTURE_COORDINATES, STATIC_DRAW);

        Buffers {
            vertex_buffer: vertex_buffer,
            texture_coordinate_buffer: texture_coordinate_buffer,
            flipped_texture_coordinate_buffer: flipped_texture_coordinate_buffer,
        }
    }
}

pub fn init_render_context() -> RenderContext {
    let vertex_shader = load_shader(VERTEX_SHADER_SOURCE, VERTEX_SHADER);
    let fragment_shader = load_shader(FRAGMENT_SHADER_SOURCE, FRAGMENT_SHADER);

    let program = create_program();
    attach_shader(program, vertex_shader);
    attach_shader(program, fragment_shader);
    link_program(program);

    if get_program_iv(program, LINK_STATUS) == (0 as GLint) {
        fail!("failed to initialize program");
    }

    use_program(program);
    enable(TEXTURE_2D);

    RenderContext::new(program)
}

pub fn bind_and_render_quad(render_context: RenderContext, texture: &Texture, flip: Flip) {
    active_texture(TEXTURE0);
    let _bound_texture = texture.bind();

    uniform_1i(render_context.sampler_uniform, 0);

    bind_buffer(ARRAY_BUFFER, render_context.buffers.vertex_buffer);
    vertex_attrib_pointer_f32(render_context.vertex_position_attr as GLuint, 3, false, 0, 0);

    match flip {
        NoFlip => bind_buffer(ARRAY_BUFFER, render_context.buffers.texture_coordinate_buffer),
        VerticalFlip => {
            bind_buffer(ARRAY_BUFFER, render_context.buffers.flipped_texture_coordinate_buffer)
        }
    }
    vertex_attrib_pointer_f32(render_context.texture_coord_attr as GLuint, 2, false, 0, 0);

    draw_arrays(TRIANGLE_STRIP, 0, 4);
}

// Layer rendering

pub trait Render {
    fn render(@mut self, render_context: RenderContext, transform: Matrix4<f32>);
}

impl Render for layers::ContainerLayer {
    fn render(@mut self, render_context: RenderContext, transform: Matrix4<f32>) {
        let old_rect_opt = if is_enabled(SCISSOR_TEST) {
            let mut old_rect = [0 as GLint, ..4];
            get_integer_v(SCISSOR_BOX, old_rect);
            Some(Rect(Point2D(old_rect[0], old_rect[1]), Size2D(old_rect[2], old_rect[3])))
        } else {
            None
        };

        match self.scissor {
            Some(rect) => {
                let size = Size2D((rect.size.width * transform.m11) as GLint,
                                  (rect.size.height * transform.m22) as GLint);

                // Get the viewport height so we can flip the origin horizontally
                // since glScissor measures from the bottom left of the viewport
                let mut viewport = [0 as GLint, ..4];
                get_integer_v(VIEWPORT, viewport);
                let w_height = viewport[3];
                let origin = Point2D((rect.origin.x * transform.m11 + transform.m41) as GLint,
                                     w_height
                                     - ((rect.origin.y * transform.m22 + transform.m42) as GLint)
                                     - size.height);
                let rect = Rect(origin, size);

                match old_rect_opt {
                    Some(old_rect) => {
                        // A parent ContainerLayer is already being scissored, so set the
                        // new scissor to the intersection of the two rects.
                        let intersection = rect.intersection(&old_rect);
                        match intersection {
                            Some(new_rect) => {
                                scissor(new_rect.origin.x,
                                        new_rect.origin.y,
                                        new_rect.size.width as GLsizei,
                                        new_rect.size.height as GLsizei);
                                maybe_get_error();
                            }
                            None => {
                                return; // Layer is occluded/offscreen
                            }
                        }
                    }
                    None => {
                        // We are the first ContainerLayer to be scissored.
                        // Check against the viewport to prevent invalid values
                        let w_rect = Rect(Point2D(0 as GLint, 0 as GLint),
                                          Size2D(viewport[2], viewport[3]));
                        let intersection = rect.intersection(&w_rect);
                        match intersection {
                            Some(new_rect) => {
                                enable(SCISSOR_TEST);
                                scissor(new_rect.origin.x,
                                        new_rect.origin.y,
                                        new_rect.size.width as GLsizei,
                                        new_rect.size.height as GLsizei);
                                maybe_get_error();
                            }
                            None => {
                                return; // Layer is offscreen
                            }
                        }
                    }
                }
            }
            None => {} // Nothing to do
        }

        let transform = transform.mul(&self.common.transform);
        for child in self.children() {
            render_layer(render_context, transform, child);
        }

        match (self.scissor, old_rect_opt) {
            (Some(_), Some(old_rect)) => {
                // Set scissor back to the parent's scissoring rect.
                scissor(old_rect.origin.x, old_rect.origin.y,
                        old_rect.size.width as GLsizei,
                        old_rect.size.height as GLsizei);
            }
            (Some(_), None) => {
                // Our parents are not being scissored, so disable scissoring for now
                disable(SCISSOR_TEST);
            }
            (None, _) => {} // Nothing to do
        }
    }
}

impl Render for layers::TextureLayer {
    fn render(@mut self, render_context: RenderContext, transform: Matrix4<f32>) {
        let transform = transform.mul(&self.common.transform);
        uniform_matrix_4fv(render_context.modelview_uniform, false, transform.to_array());
        bind_and_render_quad(render_context, self.texture.get(), self.flip);
    }
}

fn render_layer(render_context: RenderContext, transform: Matrix4<f32>, layer: layers::Layer) {
    match layer {
        ContainerLayerKind(container_layer) => {
            container_layer.render(render_context, transform);
        }
        TextureLayerKind(texture_layer) => {
            texture_layer.render(render_context, transform);
        }
    }
}

pub fn render_scene(render_context: RenderContext, scene: &Scene) {
    // Set the viewport.
    viewport(0 as GLint, 0 as GLint, scene.size.width as GLsizei, scene.size.height as GLsizei);

    // Clear the screen.
    clear_color(0.38f32, 0.36f32, 0.36f32, 1.0f32);
    clear(COLOR_BUFFER_BIT);

    // Set the projection matrix.
    let projection_matrix = ortho(0.0, scene.size.width, scene.size.height, 0.0, -10.0, 10.0);
    uniform_matrix_4fv(render_context.projection_uniform, false, projection_matrix.to_array());

    // Set up the initial modelview matrix.
    let transform = scene.transform;

    // Render the root layer.
    render_layer(render_context, transform, scene.root);
}

#[cfg(debug)]
fn maybe_get_error() {
    if get_error() != NO_ERROR {
        fail!("GL error: %d", get_error() as int);
    }
}

#[cfg(not(debug))]
fn maybe_get_error() {
    // do nothing
}
<|endoftext|>


<commit_before>/// Internal namespace.
mod internal
{
  use crate::exposed::*;

  // xxx : register graph_tools
  // xxx : no std
  // xxx : samples
  // qqq : paste generated code for each sample
  //
  // xxx : redo implements
  // xxx : add core::fmt to prelude
  // xxx : write article about the module

  ///
  /// Type constructor to define tuple wrapping a given type.
  ///
  /// Quite often you need to wrap a given type into new one.
  /// For example if orphan rule became and obstacle one should introduce a new type wrapping foreing one.
  /// Type constructr `types!` does exaclty that and auto-implement traits From, Into and Deref for the constructed type.
  ///
  /// ### Sample :: single line single.
  ///
  /// To define your own single use macro `types!`. Single-line definition looks like that.
  ///
  /// ```rust
  /// use type_constructor::prelude::*;
  /// types!( single MySingle : i32 );
  /// let x = MySingle( 13 );
  /// println!( "x : {}", x.0 );
  /// ```
  ///
  /// It gererates code:
  ///
  /// ```rust
  /// ```
  ///
  /// ### Sample :: single with derives and attributes.
  ///
  /// It's possible to define attributes as well as derives.
  ///
  /// ```rust
  /// use type_constructor::prelude::*;
  /// types!
  /// {
  ///   /// This is also attribute and macro understands it.
  ///   #[ derive( Debug ) ]
  ///   single MySingle : i32;
  /// }
  /// let x = MySingle( 13 );
  /// dbg!( x );
  /// ```
  ///
  /// It gererates code:
  ///
  /// ```rust
  /// ```
  ///
  /// ### Sample :: single with struct instead of macro.
  ///
  /// Sometimes it's sufficient to use common type instead of defining a brand new.
  /// You may use paramtetrized struct `Single< T >` instead of macro `types!` if that is the case.
  ///
  /// ```rust
  /// use type_constructor::prelude::*;
  /// let x = Single::< i32 >( 13 );
  /// dbg!( x );
  /// ```
  ///
  /// ### Sample :: single with parametrized element.
  ///
  /// Element of tuple could be parametrized.
  ///
  /// ```rust
  /// use type_constructor::prelude::*;
  /// types!
  /// {
  ///   #[ derive( Debug ) ]
  ///   single MySingle : std::sync::Arc< T : Copy >;
  /// }
  /// let x = MySingle( std::sync::Arc::new( 13 ) );
  /// dbg!( x );
  /// ```
  ///
  /// It gererates code:
  ///
  /// ```rust
  /// ```
  ///
  /// ### Sample :: single with parametrized tuple.
  ///
  /// Instead of parametrizing the element it's possible to define a parametrized tuple.
  ///
  ///
  /// ```rust
  /// use type_constructor::prelude::*;
  /// types!
  /// {
  ///   #[ derive( Debug ) ]
  ///   single MySingle : < T : Copy >;
  /// }
  /// let x = MySingle( 13 );
  /// dbg!( x );
  /// ```
  ///
  /// It gererates code:
  ///
  /// ```rust
  /// ```
  ///
  ///

  // #[ doc = include_str!( concat!( env!( "CARGO_MANIFEST_DIR" ), "/Readme.md" ) ) ]

  #[ macro_export ]
  macro_rules! types
  {

    // No more.

    (
    )
    =>
    {
    };

    // No more.

    (
      ;
    )
    =>
    {
    };

    // single

    (
      $( #[ $Meta : meta ] )*
      single
      $( $Rest : tt )*
    )
    =>
    {
      $crate::_single!
      {
        $( #[ $Meta ] )*
        single
        $( $Rest )*
      }
    };

    // pair

    (
      $( #[ $Meta : meta ] )*
      pair
      $( $Rest : tt )*
    )
    =>
    {
      $crate::_pair!
      {
        $( #[ $Meta ] )*
        pair
        $( $Rest )*
      }
    };

    // many

    (
      $( #[ $Meta : meta ] )*
      many
      $( $Rest : tt )*
    )
    =>
    {
      $crate::_many!
      {
        $( #[ $Meta ] )*
        many
        $( $Rest )*
      }
    };

    // bad syntax

    (
      $( $Rest : tt )*
    )
    =>
    {
      compile_error!
      (
        concat!
        (
          "Bad syntax.\n",
          "Expects : {kind} {name} : {type}.\n",
          "For example : `single MySingle : std::sync::Arc< T : Copy >`.\n",
          "But got:\n",
          stringify!
          (
            $( $Rest )*
          ),
        )
      );
    };

  }

  pub use types;
}

/// Protected namespace of the module.
pub mod protected
{
  pub use super::orphan::*;
}

pub use protected::*;

/// Orphan namespace of the module.
pub mod orphan
{
  pub use super::exposed::*;
}

/// Exposed namespace of the module.
pub mod exposed
{
  pub use super::prelude::*;
}

pub use exposed::*;

/// Prelude to use: `use wtools::prelude::*`.
pub mod prelude
{
  #[ doc( inline ) ]
  pub use super::internal::
  {
    types,
  };
}
<commit_msg>!build<commit_after>/// Internal namespace.
mod internal
{
  use crate::exposed::*;

  // xxx : register graph_tools
  // xxx : no std
  // xxx : samples
  // qqq : paste generated code for each sample
  //
  // xxx : redo implements
  // xxx : add core::fmt to prelude
  // xxx : write article about the module

  ///
  /// Type constructor to define tuple wrapping a given type.
  ///
  /// Quite often you need to wrap a given type into new one.
  /// For example if orphan rule became and obstacle one should introduce a new type wrapping foreing one.
  /// Type constructr `types!` does exaclty that and auto-implement traits From, Into and Deref for the constructed type.
  ///
  /// ### Sample :: single line single.
  ///
  /// To define your own single use macro `types!`. Single-line definition looks like that.
  ///
  /// ```rust
  /// use type_constructor::prelude::*;
  /// types!( single MySingle : i32 );
  /// let x = MySingle( 13 );
  /// println!( "x : {}", x.0 );
  /// ```
  ///
  /// It gererates code:
  ///
  /// ```rust
  /// ```
  ///
  /// ### Sample :: single with derives and attributes.
  ///
  /// It's possible to define attributes as well as derives.
  ///
  /// ```rust
  /// use type_constructor::prelude::*;
  /// types!
  /// {
  ///   /// This is also attribute and macro understands it.
  ///   #[ derive( Debug ) ]
  ///   single MySingle : i32;
  /// }
  /// let x = MySingle( 13 );
  /// dbg!( x );
  /// ```
  ///
  /// It gererates code:
  ///
  /// ```rust
  /// ```
  ///
  /// ### Sample :: single with struct instead of macro.
  ///
  /// Sometimes it's sufficient to use common type instead of defining a brand new.
  /// You may use paramtetrized struct `Single< T >` instead of macro `types!` if that is the case.
  ///
  /// ```rust
  /// use type_constructor::prelude::*;
  /// let x = Single::< i32 >( 13 );
  /// dbg!( x );
  /// ```
  ///
  /// ### Sample :: single with parametrized element.
  ///
  /// Element of tuple could be parametrized.
  ///
  /// ```rust
  /// use type_constructor::prelude::*;
  /// types!
  /// {
  ///   #[ derive( Debug ) ]
  ///   single MySingle : std::sync::Arc< T : Copy >;
  /// }
  /// let x = MySingle( std::sync::Arc::new( 13 ) );
  /// dbg!( x );
  /// ```
  ///
  /// It gererates code:
  ///
  /// ```rust
  /// ```
  ///
  /// ### Sample :: single with parametrized tuple.
  ///
  /// Instead of parametrizing the element it's possible to define a parametrized tuple.
  ///
  ///
  /// ```rust
  /// use type_constructor::prelude::*;
  /// types!
  /// {
  ///   #[ derive( Debug ) ]
  ///   single MySingle : < T : Copy >;
  /// }
  /// let x = MySingle( 13 );
  /// dbg!( x );
  /// ```
  ///
  /// It gererates code:
  ///
  /// ```rust
  /// ```
  ///
  ///

  // #[ doc = include_str!( concat!( env!( "CARGO_MANIFEST_DIR" ), "/Readme.md" ) ) ]

  #[ macro_export ]
  macro_rules! types
  {

    // No more.

    (
    )
    =>
    {
    };

    // No more.

    (
      ;
    )
    =>
    {
    };

    // single

    (
      $( #[ $Meta : meta ] )*
      single
      $( $Rest : tt )*
    )
    =>
    {
      $crate::_single!
      {
        $( #[ $Meta ] )*
        single
        $( $Rest )*
      }
    };

    // pair

    (
      $( #[ $Meta : meta ] )*
      pair
      $( $Rest : tt )*
    )
    =>
    {
      $crate::_pair!
      {
        $( #[ $Meta ] )*
        pair
        $( $Rest )*
      }
    };

    // many

    (
      $( #[ $Meta : meta ] )*
      many
      $( $Rest : tt )*
    )
    =>
    {
      $crate::_many!
      {
        $( #[ $Meta ] )*
        many
        $( $Rest )*
      }
    };

    // bad syntax

    (
      $( $Rest : tt )*
    )
    =>
    {
      compile_error!
      (
        concat!
        (
          "Bad syntax.\n",
          "Expects : {kind} {name} : {type}.\n",
          "For example : `single MySingle : std::sync::Arc< T : Copy >`.\n",
          "But got:\n",
          stringify!
          (
            $( $Rest )*
          ),
        )
      );
    };

  }

  pub use types;
}

/// Protected namespace of the module.
pub mod protected
{
  pub use super::orphan::*;
}

pub use protected::*;

/// Orphan namespace of the module.
pub mod orphan
{
  pub use super::exposed::*;
}

/// Exposed namespace of the module.
pub mod exposed
{
  pub use super::prelude::*;
}

pub use exposed::*;

/// Prelude to use: `use wtools::prelude::*`.
pub mod prelude
{
  #[ doc( inline ) ]
  pub use super::internal::
  {
    types,
  };
}

<|endoftext|>


<commit_before>use crate::{
    com_class, com_impl, com_interface, type_system::TypeSystemName, ComError, ComItf, ComRc,
    ComResult, ComStruct, GUID,
};

use std::borrow::Cow;

#[derive(Fail, Debug)]
pub enum TypeLibError
{
    #[fail(display = "COM error occurred: {}", _0)]
    ComError(ComError),
}

impl From<ComError> for TypeLibError
{
    fn from(s: ComError) -> Self
    {
        TypeLibError::ComError(s)
    }
}

mod from_impls;

// pub mod raw;
// use raw::*;

#[derive(Debug)]
pub struct InterfaceRef
{
    pub name: Cow<'static, str>,
    pub iid_automation: GUID,
    pub iid_raw: GUID,
}

// TypeLib

#[com_class(IIntercomTypeLib)]
#[derive(Debug)]
pub struct TypeLib
{
    pub name: Cow<'static, str>,
    pub libid: GUID,
    pub version: Cow<'static, str>,
    pub types: Vec<TypeInfo>,
}

#[com_interface]
#[allow(bare_trait_objects)]
pub trait IIntercomTypeLib
{
    fn get_info(&self) -> ComResult<(String, GUID, String)>;
    fn get_type_count(&self) -> ComResult<u32>;
    fn get_type(&self, idx: u32) -> ComResult<ComRc<IIntercomTypeInfo>>;
}

// TypeInfo

#[derive(Debug)]
pub enum TypeInfo
{
    Class(ComStruct<CoClass>),
    Interface(ComStruct<Interface>),
}

#[derive(intercom::ExternType, intercom::BidirectionalTypeInfo, Debug)]
#[repr(C)]
pub enum TypeInfoKind
{
    CoClass,
    Interface,
}

#[com_interface]
pub trait IIntercomTypeInfo
{
    fn get_name(&self) -> ComResult<String>;
    fn get_kind(&self) -> ComResult<TypeInfoKind>;
}

// TypeInfo::CoClass

#[com_class(IIntercomTypeInfo, IIntercomCoClass)]
#[derive(Debug)]
pub struct CoClass
{
    pub name: Cow<'static, str>,
    pub clsid: GUID,
    pub interfaces: Vec<InterfaceRef>,
}

#[com_interface]
pub trait IIntercomCoClass
{
    // FIXME: Support interface inheritance
    fn get_name(&self) -> ComResult<String>;

    fn get_clsid(&self) -> ComResult<GUID>;
    fn get_interface_count(&self) -> ComResult<u32>;
    fn get_interface_ref(&self, idx: u32, ts: TypeSystemName) -> ComResult<(String, GUID)>;
}

// TypeInfo::Interface

#[com_class(IIntercomTypeInfo, IIntercomInterface)]
#[derive(Debug)]
pub struct Interface
{
    pub name: Cow<'static, str>,
    pub variants: Vec<ComStruct<InterfaceVariant>>,
    pub options: InterfaceOptions,
}

#[derive(Debug, Clone, Default, intercom::ExternType, intercom::BidirectionalTypeInfo)]
#[repr(C)]
pub struct InterfaceOptions
{
    pub class_impl_interface: bool,
    pub __non_exhaustive: (),
}

#[com_class(IIntercomInterfaceVariant)]
#[derive(Debug)]
pub struct InterfaceVariant
{
    pub ts: TypeSystemName,
    pub iid: GUID,
    pub methods: Vec<ComStruct<Method>>,
}

#[com_interface]
#[allow(bare_trait_objects)]
pub trait IIntercomInterface
{
    // FIXME: Support interface inheritance
    fn get_name(&self) -> ComResult<String>;
    fn get_options(&self) -> ComResult<InterfaceOptions>;

    fn get_variant_count(&self) -> ComResult<u32>;
    fn get_variant(&self, idx: u32) -> ComResult<ComRc<IIntercomInterfaceVariant>>;
}

#[com_interface]
#[allow(bare_trait_objects)]
pub trait IIntercomInterfaceVariant
{
    fn get_type_system(&self) -> ComResult<TypeSystemName>;
    fn get_iid(&self) -> ComResult<GUID>;
    fn get_method_count(&self) -> ComResult<u32>;
    fn get_method(&self, idx: u32) -> ComResult<ComRc<IIntercomMethod>>;
}

// Method

#[com_class(IIntercomMethod)]
#[derive(Debug)]
pub struct Method
{
    pub name: Cow<'static, str>,
    pub return_type: Arg,
    pub parameters: Vec<Arg>,
}

#[derive(Debug)]
pub struct Arg
{
    pub name: Cow<'static, str>,
    pub ty: Cow<'static, str>,
    pub indirection_level: u32,
    pub direction: Direction,
}

#[derive(
    Debug, Clone, Copy, intercom::ExternType, intercom::BidirectionalTypeInfo, PartialEq, Eq,
)]
#[repr(C)]
pub enum Direction
{
    In,
    Out,
    Retval,
    Return,
}

#[com_interface]
pub trait IIntercomMethod
{
    fn get_name(&self) -> ComResult<String>;
    fn get_return_type(&self) -> ComResult<(String, u32)>;
    fn get_parameter_count(&self) -> ComResult<u32>;
    fn get_parameter(&self, idx: u32) -> ComResult<(String, String, u32, Direction)>;
}

// Impls

#[com_impl]
impl IIntercomTypeLib for TypeLib
{
    fn get_info(&self) -> ComResult<(String, GUID, String)>
    {
        Ok((
            self.name.to_string(),
            self.libid.clone(),
            self.version.to_string(),
        ))
    }

    fn get_type_count(&self) -> ComResult<u32>
    {
        Ok(self.types.len() as u32)
    }

    fn get_type(&self, idx: u32) -> ComResult<ComRc<dyn IIntercomTypeInfo>>
    {
        Ok(match &self.types[idx as usize] {
            TypeInfo::Class(cls) => ComRc::from(cls),
            TypeInfo::Interface(itf) => ComRc::from(itf),
        })
    }
}

#[com_impl]
impl IIntercomTypeInfo for CoClass
{
    fn get_name(&self) -> ComResult<String>
    {
        Ok(self.name.to_string())
    }

    fn get_kind(&self) -> ComResult<TypeInfoKind>
    {
        Ok(TypeInfoKind::CoClass)
    }
}

#[com_impl]
impl IIntercomCoClass for CoClass
{
    fn get_name(&self) -> ComResult<String>
    {
        Ok(self.name.to_string())
    }

    fn get_clsid(&self) -> ComResult<GUID>
    {
        Ok(self.clsid.clone())
    }
    fn get_interface_count(&self) -> ComResult<u32>
    {
        Ok(self.interfaces.len() as u32)
    }

    fn get_interface_ref(&self, idx: u32, ts: TypeSystemName) -> ComResult<(String, GUID)>
    {
        let itf = &self.interfaces[idx as usize];
        Ok((
            itf.name.to_string(),
            match ts {
                TypeSystemName::Automation => itf.iid_automation.clone(),
                TypeSystemName::Raw => itf.iid_raw.clone(),
            },
        ))
    }
}

#[com_impl]
impl IIntercomTypeInfo for Interface
{
    fn get_name(&self) -> ComResult<String>
    {
        Ok(self.name.to_string())
    }

    fn get_kind(&self) -> ComResult<TypeInfoKind>
    {
        Ok(TypeInfoKind::Interface)
    }
}

#[com_impl]
impl IIntercomInterface for Interface
{
    fn get_name(&self) -> ComResult<String>
    {
        Ok(self.name.to_string())
    }

    fn get_options(&self) -> ComResult<InterfaceOptions>
    {
        Ok(self.options.clone())
    }

    fn get_variant_count(&self) -> ComResult<u32>
    {
        Ok(self.variants.len() as u32)
    }

    fn get_variant(&self, idx: u32) -> ComResult<ComRc<dyn IIntercomInterfaceVariant>>
    {
        Ok(ComRc::from(&self.variants[idx as usize]))
    }
}

#[com_impl]
impl IIntercomInterfaceVariant for InterfaceVariant
{
    fn get_type_system(&self) -> ComResult<TypeSystemName>
    {
        Ok(self.ts)
    }

    fn get_iid(&self) -> ComResult<GUID>
    {
        Ok(self.iid.clone())
    }

    fn get_method_count(&self) -> ComResult<u32>
    {
        Ok(self.methods.len() as u32)
    }

    fn get_method(&self, idx: u32) -> ComResult<ComRc<dyn IIntercomMethod>>
    {
        Ok(ComRc::from(&self.methods[idx as usize]))
    }
}

#[com_impl]
impl IIntercomMethod for Method
{
    fn get_name(&self) -> ComResult<String>
    {
        Ok(self.name.to_string())
    }

    fn get_return_type(&self) -> ComResult<(String, u32)>
    {
        Ok((
            self.return_type.ty.to_string(),
            self.return_type.indirection_level,
        ))
    }

    fn get_parameter_count(&self) -> ComResult<u32>
    {
        Ok(self.parameters.len() as u32)
    }
    fn get_parameter(&self, idx: u32) -> ComResult<(String, String, u32, Direction)>
    {
        let arg = &self.parameters[idx as usize];
        Ok((
            arg.name.to_string(),
            arg.ty.to_string(),
            arg.indirection_level,
            arg.direction,
        ))
    }
}

impl CoClass
{
    pub fn __new(name: Cow<'static, str>, clsid: GUID, interfaces: Vec<InterfaceRef>) -> Self
    {
        Self {
            name,
            clsid,
            interfaces,
        }
    }
}

impl TypeLib
{
    pub fn __new(
        name: Cow<'static, str>,
        libid: GUID,
        version: Cow<'static, str>,
        mut types: Vec<TypeInfo>,
    ) -> TypeLib
    {
        types.sort_by_key(|item| match item {
            TypeInfo::Class(cls) => ("class", cls.as_ref().name.to_string()),
            TypeInfo::Interface(itf) => ("itf", itf.as_ref().name.to_string()),
        });
        types.dedup_by_key(|item| match item {
            TypeInfo::Class(cls) => ("class", cls.as_ref().name.to_string()),
            TypeInfo::Interface(itf) => ("itf", itf.as_ref().name.to_string()),
        });
        TypeLib {
            name,
            libid,
            version,
            types,
        }
    }
}
<commit_msg>Fix warnings in typelib<commit_after>use crate::{
    com_class, com_impl, com_interface, type_system::TypeSystemName, ComError, ComItf, ComRc,
    ComResult, ComStruct, GUID,
};

use std::borrow::Cow;

#[derive(Fail, Debug)]
pub enum TypeLibError
{
    #[fail(display = "COM error occurred: {}", _0)]
    ComError(ComError),
}

impl From<ComError> for TypeLibError
{
    fn from(s: ComError) -> Self
    {
        TypeLibError::ComError(s)
    }
}

mod from_impls;

// pub mod raw;
// use raw::*;

#[derive(Debug)]
pub struct InterfaceRef
{
    pub name: Cow<'static, str>,
    pub iid_automation: GUID,
    pub iid_raw: GUID,
}

// TypeLib

#[com_class(IIntercomTypeLib)]
#[derive(Debug)]
pub struct TypeLib
{
    pub name: Cow<'static, str>,
    pub libid: GUID,
    pub version: Cow<'static, str>,
    pub types: Vec<TypeInfo>,
}

#[com_interface]
pub trait IIntercomTypeLib
{
    fn get_info(&self) -> ComResult<(String, GUID, String)>;
    fn get_type_count(&self) -> ComResult<u32>;
    fn get_type(&self, idx: u32) -> ComResult<ComRc<dyn IIntercomTypeInfo>>;
}

// TypeInfo

#[derive(Debug)]
pub enum TypeInfo
{
    Class(ComStruct<CoClass>),
    Interface(ComStruct<Interface>),
}

#[derive(intercom::ExternType, intercom::BidirectionalTypeInfo, Debug)]
#[repr(C)]
pub enum TypeInfoKind
{
    CoClass,
    Interface,
}

#[com_interface]
pub trait IIntercomTypeInfo
{
    fn get_name(&self) -> ComResult<String>;
    fn get_kind(&self) -> ComResult<TypeInfoKind>;
}

// TypeInfo::CoClass

#[com_class(IIntercomTypeInfo, IIntercomCoClass)]
#[derive(Debug)]
pub struct CoClass
{
    pub name: Cow<'static, str>,
    pub clsid: GUID,
    pub interfaces: Vec<InterfaceRef>,
}

#[com_interface]
pub trait IIntercomCoClass
{
    // FIXME: Support interface inheritance
    fn get_name(&self) -> ComResult<String>;

    fn get_clsid(&self) -> ComResult<GUID>;
    fn get_interface_count(&self) -> ComResult<u32>;
    fn get_interface_ref(&self, idx: u32, ts: TypeSystemName) -> ComResult<(String, GUID)>;
}

// TypeInfo::Interface

#[com_class(IIntercomTypeInfo, IIntercomInterface)]
#[derive(Debug)]
pub struct Interface
{
    pub name: Cow<'static, str>,
    pub variants: Vec<ComStruct<InterfaceVariant>>,
    pub options: InterfaceOptions,
}

#[derive(Debug, Clone, Default, intercom::ExternType, intercom::BidirectionalTypeInfo)]
#[repr(C)]
pub struct InterfaceOptions
{
    pub class_impl_interface: bool,
    pub __non_exhaustive: (),
}

#[com_class(IIntercomInterfaceVariant)]
#[derive(Debug)]
pub struct InterfaceVariant
{
    pub ts: TypeSystemName,
    pub iid: GUID,
    pub methods: Vec<ComStruct<Method>>,
}

#[com_interface]
pub trait IIntercomInterface
{
    // FIXME: Support interface inheritance
    fn get_name(&self) -> ComResult<String>;
    fn get_options(&self) -> ComResult<InterfaceOptions>;

    fn get_variant_count(&self) -> ComResult<u32>;
    fn get_variant(&self, idx: u32) -> ComResult<ComRc<dyn IIntercomInterfaceVariant>>;
}

#[com_interface]
pub trait IIntercomInterfaceVariant
{
    fn get_type_system(&self) -> ComResult<TypeSystemName>;
    fn get_iid(&self) -> ComResult<GUID>;
    fn get_method_count(&self) -> ComResult<u32>;
    fn get_method(&self, idx: u32) -> ComResult<ComRc<dyn IIntercomMethod>>;
}

// Method

#[com_class(IIntercomMethod)]
#[derive(Debug)]
pub struct Method
{
    pub name: Cow<'static, str>,
    pub return_type: Arg,
    pub parameters: Vec<Arg>,
}

#[derive(Debug)]
pub struct Arg
{
    pub name: Cow<'static, str>,
    pub ty: Cow<'static, str>,
    pub indirection_level: u32,
    pub direction: Direction,
}

#[derive(
    Debug, Clone, Copy, intercom::ExternType, intercom::BidirectionalTypeInfo, PartialEq, Eq,
)]
#[repr(C)]
pub enum Direction
{
    In,
    Out,
    Retval,
    Return,
}

#[com_interface]
pub trait IIntercomMethod
{
    fn get_name(&self) -> ComResult<String>;
    fn get_return_type(&self) -> ComResult<(String, u32)>;
    fn get_parameter_count(&self) -> ComResult<u32>;
    fn get_parameter(&self, idx: u32) -> ComResult<(String, String, u32, Direction)>;
}

// Impls

#[com_impl]
impl IIntercomTypeLib for TypeLib
{
    fn get_info(&self) -> ComResult<(String, GUID, String)>
    {
        Ok((
            self.name.to_string(),
            self.libid.clone(),
            self.version.to_string(),
        ))
    }

    fn get_type_count(&self) -> ComResult<u32>
    {
        Ok(self.types.len() as u32)
    }

    fn get_type(&self, idx: u32) -> ComResult<ComRc<dyn IIntercomTypeInfo>>
    {
        Ok(match &self.types[idx as usize] {
            TypeInfo::Class(cls) => ComRc::from(cls),
            TypeInfo::Interface(itf) => ComRc::from(itf),
        })
    }
}

#[com_impl]
impl IIntercomTypeInfo for CoClass
{
    fn get_name(&self) -> ComResult<String>
    {
        Ok(self.name.to_string())
    }

    fn get_kind(&self) -> ComResult<TypeInfoKind>
    {
        Ok(TypeInfoKind::CoClass)
    }
}

#[com_impl]
impl IIntercomCoClass for CoClass
{
    fn get_name(&self) -> ComResult<String>
    {
        Ok(self.name.to_string())
    }

    fn get_clsid(&self) -> ComResult<GUID>
    {
        Ok(self.clsid.clone())
    }
    fn get_interface_count(&self) -> ComResult<u32>
    {
        Ok(self.interfaces.len() as u32)
    }

    fn get_interface_ref(&self, idx: u32, ts: TypeSystemName) -> ComResult<(String, GUID)>
    {
        let itf = &self.interfaces[idx as usize];
        Ok((
            itf.name.to_string(),
            match ts {
                TypeSystemName::Automation => itf.iid_automation.clone(),
                TypeSystemName::Raw => itf.iid_raw.clone(),
            },
        ))
    }
}

#[com_impl]
impl IIntercomTypeInfo for Interface
{
    fn get_name(&self) -> ComResult<String>
    {
        Ok(self.name.to_string())
    }

    fn get_kind(&self) -> ComResult<TypeInfoKind>
    {
        Ok(TypeInfoKind::Interface)
    }
}

#[com_impl]
impl IIntercomInterface for Interface
{
    fn get_name(&self) -> ComResult<String>
    {
        Ok(self.name.to_string())
    }

    fn get_options(&self) -> ComResult<InterfaceOptions>
    {
        Ok(self.options.clone())
    }

    fn get_variant_count(&self) -> ComResult<u32>
    {
        Ok(self.variants.len() as u32)
    }

    fn get_variant(&self, idx: u32) -> ComResult<ComRc<dyn IIntercomInterfaceVariant>>
    {
        Ok(ComRc::from(&self.variants[idx as usize]))
    }
}

#[com_impl]
impl IIntercomInterfaceVariant for InterfaceVariant
{
    fn get_type_system(&self) -> ComResult<TypeSystemName>
    {
        Ok(self.ts)
    }

    fn get_iid(&self) -> ComResult<GUID>
    {
        Ok(self.iid.clone())
    }

    fn get_method_count(&self) -> ComResult<u32>
    {
        Ok(self.methods.len() as u32)
    }

    fn get_method(&self, idx: u32) -> ComResult<ComRc<dyn IIntercomMethod>>
    {
        Ok(ComRc::from(&self.methods[idx as usize]))
    }
}

#[com_impl]
impl IIntercomMethod for Method
{
    fn get_name(&self) -> ComResult<String>
    {
        Ok(self.name.to_string())
    }

    fn get_return_type(&self) -> ComResult<(String, u32)>
    {
        Ok((
            self.return_type.ty.to_string(),
            self.return_type.indirection_level,
        ))
    }

    fn get_parameter_count(&self) -> ComResult<u32>
    {
        Ok(self.parameters.len() as u32)
    }
    fn get_parameter(&self, idx: u32) -> ComResult<(String, String, u32, Direction)>
    {
        let arg = &self.parameters[idx as usize];
        Ok((
            arg.name.to_string(),
            arg.ty.to_string(),
            arg.indirection_level,
            arg.direction,
        ))
    }
}

impl CoClass
{
    pub fn __new(name: Cow<'static, str>, clsid: GUID, interfaces: Vec<InterfaceRef>) -> Self
    {
        Self {
            name,
            clsid,
            interfaces,
        }
    }
}

impl TypeLib
{
    pub fn __new(
        name: Cow<'static, str>,
        libid: GUID,
        version: Cow<'static, str>,
        mut types: Vec<TypeInfo>,
    ) -> TypeLib
    {
        types.sort_by_key(|item| match item {
            TypeInfo::Class(cls) => ("class", cls.as_ref().name.to_string()),
            TypeInfo::Interface(itf) => ("itf", itf.as_ref().name.to_string()),
        });
        types.dedup_by_key(|item| match item {
            TypeInfo::Class(cls) => ("class", cls.as_ref().name.to_string()),
            TypeInfo::Interface(itf) => ("itf", itf.as_ref().name.to_string()),
        });
        TypeLib {
            name,
            libid,
            version,
            types,
        }
    }
}
<|endoftext|>


<commit_before>// Farbfeld filter that applies a cool blurring effect over images
// Usage: png2ff < greyscale.png | blur | ff2png > false-colored.png

use std::io;
use std::io::prelude::*;
use std::io::BufReader;
use std::io::BufWriter;

extern crate byteorder;
use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian, LittleEndian};

#[derive (Clone, Copy)]
struct FfPixel {
	pub r: u16,
	pub g: u16,
	pub b: u16,
	pub a: u16,
}

fn read_pixel <T> (reader: &mut T) -> FfPixel where T: ReadBytesExt {
	FfPixel {
		r: reader.read_u16::<BigEndian> ().unwrap (),
		g: reader.read_u16::<BigEndian> ().unwrap (),
		b: reader.read_u16::<BigEndian> ().unwrap (),
		a: reader.read_u16::<BigEndian> ().unwrap (),
	}
}

fn write_pixel <T> (writer: &mut T, pix: &FfPixel) where T: WriteBytesExt {
	writer.write_u16::<BigEndian> (pix.r).unwrap ();
	writer.write_u16::<BigEndian> (pix.g).unwrap ();
	writer.write_u16::<BigEndian> (pix.b).unwrap ();
	writer.write_u16::<BigEndian> (pix.a).unwrap ();
}

fn main () {
	let mut reader = BufReader::new (io::stdin ());

	let mut magic = [0; 8];
	reader.read (&mut magic [..]);

	// TODO: Assert that magic == 'farbfeld'
	//assert_eq! (magic, &"farbfeld");

	let width = reader.read_u32::<BigEndian>().unwrap();
	let height = reader.read_u32::<BigEndian>().unwrap();

	writeln!(&mut io::stderr(), "{} x {}", width, height).expect("failed printing to stderr");

	let mut pixels = Vec::new ();

	for i in 0..width * height {
		pixels.push (read_pixel (&mut reader).g);
	}

	{
		let mut writer = BufWriter::new (io::stdout ());

		writer.write ("farbfeld".as_bytes ()).expect ("printing farbfeld");

		writer.write_u32::<BigEndian> (width).unwrap ();
		writer.write_u32::<BigEndian> (height).unwrap ();

		for i in 0..(width * height) as usize {
			let val = pixels [i];

			write_pixel (&mut writer, &FfPixel {
				r: val,
				g: 0,
				b: val,
				a: 65535,
			});
		}
	}
}
<commit_msg>Working on a separable blur on CPU in Rust<commit_after>// Farbfeld filter that applies a cool blurring effect over images
// Usage: png2ff < greyscale.png | blur | ff2png > false-colored.png

use std::io;
use std::io::prelude::*;
use std::io::BufReader;
use std::io::BufWriter;

extern crate byteorder;
use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian};

#[derive (Clone, Copy)]
struct FfPixel {
	pub r: u16,
	pub g: u16,
	pub b: u16,
	pub a: u16,
}

#[derive (Clone, Copy)]
struct PlaneCoord {
	pub x: i32,
	pub y: i32,
}

impl PlaneCoord {
	pub fn contains (&self, x: i32, y: i32) -> bool {
		x >= 0 && x < self.x &&
		y >= 0 && y < self.y
	}

	pub fn clamp_x (&self, x: i32) -> i32 {
		return if x < 0 {
			0
		}
		else if x >= self.x {
			self.x - 1
		}
		else {
			x
		}
	}

	pub fn clamp_y (&self, y: i32) -> i32 {
		return if y < 0 {
			0
		}
		else if y >= self.y {
			self.y - 1
		}
		else {
			y
		}
	}

	pub fn clamp (&self, pc: &PlaneCoord) -> PlaneCoord {
		PlaneCoord {
			x: self.clamp_x (pc.x),
			y: self.clamp_y (pc.y),
		}
	}

	pub fn index (&self, pc: &PlaneCoord) -> i32 {
		let pc = self.clamp (pc);

		pc.y * self.x + pc.x
	}

	pub fn clamped_index (&self, pc: &PlaneCoord) -> i32 {
		self.index (&self.clamp (pc))
	}
}

struct HdrPlane {
	pub size: PlaneCoord,
	pub pixels: Vec <f64>,
}

fn read_pixel <T> (reader: &mut T) -> FfPixel where T: ReadBytesExt {
	FfPixel {
		r: reader.read_u16::<BigEndian> ().unwrap (),
		g: reader.read_u16::<BigEndian> ().unwrap (),
		b: reader.read_u16::<BigEndian> ().unwrap (),
		a: reader.read_u16::<BigEndian> ().unwrap (),
	}
}

fn write_pixel <T> (writer: &mut T, pix: &FfPixel) where T: WriteBytesExt {
	writer.write_u16::<BigEndian> (pix.r).unwrap ();
	writer.write_u16::<BigEndian> (pix.g).unwrap ();
	writer.write_u16::<BigEndian> (pix.b).unwrap ();
	writer.write_u16::<BigEndian> (pix.a).unwrap ();
}

fn pascal (n: u32) -> Vec <u32> {
	match n {
		0 => {
			vec! []
		}
		1 => {
			vec! [1]
		},
		2 => {
			vec! [1, 1]
		},
		3 => {
			vec! [1, 2, 1]
		},
		4 => {
			vec! [1, 3, 3, 1]
		}
		5 => {
			vec! [1, 4, 6, 4, 1]
		},
		_ => {
			let step = 5;
			let prev_row = pascal (n - step + 1);
			let step_row = pascal (step);

			let mut output = vec! [];
			for _ in 0..n {
				output.push (0);
			}

			for a in 0..prev_row.len () {
				for b in 0..step_row.len () {
					output [a + b] += prev_row [a] * step_row [b];
				}
			}

			output
		}
	}
}

fn blur_hor (input_plane: &HdrPlane, filter: &Vec <u32>) -> HdrPlane {
	let offset = -(filter.len () as i32 - 1) / 2;
	let filter_sum: u32 = filter.iter ().sum ();
	// Rust plz
	let filter_sum = filter_sum as f64;
	let filter_f: Vec <f64> = filter.iter ().map (|x| *x as f64 / filter_sum).collect ();

	let mut pixels = vec![];
	for y in 0..input_plane.size.y {
		for x in 0..input_plane.size.x {
			let dest_index = input_plane.size.clamped_index (&PlaneCoord {
				x: x,
				y: y
			});

			pixels.push (0.0f64);

			for i in 0..filter_f.len () {
				let src_index = input_plane.size.clamped_index (&PlaneCoord {
					x: x + i as i32 + offset,
					y: y
				});

				pixels [dest_index as usize] += filter_f [i] * input_plane.pixels [src_index as usize];
			}
		}
	}

	HdrPlane {
		size: input_plane.size,
		pixels: pixels,
	}
}

fn read_farbfeld_grey <T> (reader: &mut T) -> HdrPlane where T: ReadBytesExt {
	let mut magic = [0; 8];
	reader.read (&mut magic [..]).unwrap ();

	// TODO: Assert that magic == 'farbfeld'
	//assert_eq! (magic, &"farbfeld");

	let width = reader.read_u32::<BigEndian>().unwrap() as i32;
	let height = reader.read_u32::<BigEndian>().unwrap() as i32;

	writeln!(&mut io::stderr(), "{} x {}", width, height).expect("failed printing to stderr");

	let mut pixels = Vec::new ();

	for _ in 0 .. width * height {
		let gamma = read_pixel (reader).g as f64 / 65536.0;
		pixels.push (gamma * gamma);
	}

	HdrPlane {
		size: PlaneCoord {
			x: width,
			y: height,
		},
		pixels: pixels,
	}
}

fn write_farbfeld_plane <T> (writer: &mut T, plane: &HdrPlane) where T: WriteBytesExt
{
	writer.write ("farbfeld".as_bytes ()).expect ("printing farbfeld");

	writer.write_u32::<BigEndian> (plane.size.x as u32).unwrap ();
	writer.write_u32::<BigEndian> (plane.size.y as u32).unwrap ();

	for i in 0..plane.size.x * plane.size.y {
		let val = (plane.pixels [i as usize].sqrt () * 65535.0) as u16;

		write_pixel (writer, &FfPixel {
			r: val,
			g: val,
			b: val,
			a: 65535,
		});
	}
}

fn main () {
	// Reader
	let mut reader = BufReader::new (io::stdin ());

	let input_plane = read_farbfeld_grey (&mut reader);

	let filter = pascal (31);

	let input_plane = blur_hor (&input_plane, &filter);
	let input_plane = blur_hor (&input_plane, &filter);
	let input_plane = blur_hor (&input_plane, &filter);
	let input_plane = blur_hor (&input_plane, &filter);
	let input_plane = blur_hor (&input_plane, &filter);
	let input_plane = blur_hor (&input_plane, &filter);

	// Write
	{
		let mut writer = BufWriter::new (io::stdout ());

		write_farbfeld_plane (&mut writer, &input_plane);
	}

	writeln!(&mut io::stderr(), "filter {:?}", filter).expect("failed printing to stderr");
}
<|endoftext|>


<commit_before>use clap::{App, AppSettings, Arg, Shell, SubCommand};

pub fn build_cli() -> App<'static, 'static> {
    let database_arg = Arg::with_name("DATABASE_URL")
        .long("database-url")
        .help(
            "Specifies the database URL to connect to. Falls back to \
             the DATABASE_URL environment variable if unspecified.",
        )
        .global(true)
        .takes_value(true);

    let migration_subcommand = SubCommand::with_name("migration")
        .about(
            "A group of commands for generating, running, and reverting \
             migrations.",
        )
        .setting(AppSettings::VersionlessSubcommands)
        .arg(migration_dir_arg())
        .subcommand(SubCommand::with_name("run").about("Runs all pending migrations"))
        .subcommand(SubCommand::with_name("revert").about("Reverts the latest run migration"))
        .subcommand(SubCommand::with_name("redo").about(
            "Reverts and re-runs the latest migration. Useful \
             for testing that a migration can in fact be reverted.",
        ))
        .subcommand(
            SubCommand::with_name("list")
                .about("Lists all available migrations, marking those that have been applied."),
        )
        .subcommand(
            SubCommand::with_name("pending")
                .about("Returns true if there are any pending migrations."),
        )
        .subcommand(
            SubCommand::with_name("generate")
                .about(
                    "Generate a new migration with the given name, and \
                     the current timestamp as the version",
                )
                .arg(
                    Arg::with_name("MIGRATION_NAME")
                        .help("The name of the migration to create")
                        .required(true),
                )
                .arg(
                    Arg::with_name("MIGRATION_VERSION")
                        .long("version")
                        .help(
                            "The version number to use when generating the migration. \
                             Defaults to the current timestamp, which should suffice \
                             for most use cases.",
                        )
                        .takes_value(true),
                )
                .arg(
                    Arg::with_name("MIGRATION_FORMAT")
                        .long("format")
                        .possible_values(&["sql", "barrel"])
                        .default_value("sql")
                        .takes_value(true)
                        .help("The format of the migration to be generated."),
                ),
        )
        .setting(AppSettings::SubcommandRequiredElseHelp);

    let setup_subcommand = SubCommand::with_name("setup")
        .arg(migration_dir_arg())
        .about(
            "Creates the migrations directory, creates the database \
             specified in your DATABASE_URL, and runs existing migrations.",
        );

    let database_subcommand = SubCommand::with_name("database")
        .alias("db")
        .arg(migration_dir_arg())
        .about("A group of commands for setting up and resetting your database.")
        .setting(AppSettings::VersionlessSubcommands)
        .subcommand(SubCommand::with_name("setup").about(
            "Creates the database specified in your DATABASE_URL, \
             and then runs any existing migrations.",
        ))
        .subcommand(SubCommand::with_name("reset").about(
            "Resets your database by dropping the database specified \
             in your DATABASE_URL and then running `diesel database setup`.",
        ))
        .subcommand(
            SubCommand::with_name("drop")
                .about("Drops the database specified in your DATABASE_URL.")
                .setting(AppSettings::Hidden),
        )
        .setting(AppSettings::SubcommandRequiredElseHelp);

    let generate_bash_completion_subcommand = SubCommand::with_name("bash-completion")
        .about("DEPRECATED: Generate bash completion script for the diesel command.");

    let generate_completions_subcommand = SubCommand::with_name("completions")
        .about("Generate shell completion scripts for the diesel command.")
        .arg(
            Arg::with_name("SHELL")
                .index(1)
                .required(true)
                .possible_values(&Shell::variants()),
        );

    let infer_schema_subcommand = SubCommand::with_name("print-schema")
        .setting(AppSettings::VersionlessSubcommands)
        .about("Print table definitions for database schema.")
        .arg(
            Arg::with_name("schema")
                .long("schema")
                .short("s")
                .takes_value(true)
                .help("The name of the schema."),
        )
        .arg(
            Arg::with_name("table-name")
                .index(1)
                .takes_value(true)
                .multiple(true)
                .help("Table names to filter (default only-tables if not empty)"),
        )
        .arg(
            Arg::with_name("only-tables")
                .short("o")
                .long("only-tables")
                .help("Only include tables from table-name that matches regexp")
                .conflicts_with("except-tables"),
        )
        .arg(
            Arg::with_name("except-tables")
                .short("e")
                .long("except-tables")
                .help("Exclude tables from table-name that matches regex")
                .conflicts_with("only-tables"),
        )
        .arg(
            Arg::with_name("with-docs")
                .long("with-docs")
                .help("Render documentation comments for tables and columns"),
        )
        .arg(
            Arg::with_name("patch-file")
                .long("patch-file")
                .takes_value(true)
                .help("A unified diff file to be applied to the final schema"),
        )
        .arg(
            Arg::with_name("import-types")
                .long("import-types")
                .takes_value(true)
                .multiple(true)
                .number_of_values(1)
                .help("A list of types to import for every table, separated by commas"),
        );

    let config_arg = Arg::with_name("CONFIG_FILE")
        .long("config-file")
        .help(
            "The location of the configuration file to use. Falls back to the \
             `DIESEL_CONFIG_FILE` environment variable if unspecified. Defaults \
             to `diesel.toml` in your project root. See \
             diesel.rs/guides/configuring-diesel-cli for documentation on this file.",
        )
        .global(true)
        .takes_value(true);

    let locked_schema_arg = Arg::with_name("LOCKED_SCHEMA")
        .long("locked-schema")
        .help("Require that the schema file is up to date")
        .long_help(
            "When `print_schema.file` is specified in your config file, this \
             flag will cause Diesel CLI to error if any command would result in \
             changes to that file. It is recommended that you use this flag when \
             running migrations in CI or production.",
        )
        .global(true);

    App::new("diesel")
        .version(env!("CARGO_PKG_VERSION"))
        .setting(AppSettings::VersionlessSubcommands)
        .after_help(
            "You can also run `diesel SUBCOMMAND -h` to get more information about that subcommand.",
        )
        .arg(database_arg)
        .arg(config_arg)
        .arg(locked_schema_arg)
        .subcommand(migration_subcommand)
        .subcommand(setup_subcommand)
        .subcommand(database_subcommand)
        .subcommand(generate_bash_completion_subcommand)
        .subcommand(generate_completions_subcommand)
        .subcommand(infer_schema_subcommand)
        .setting(AppSettings::SubcommandRequiredElseHelp)
}

fn migration_dir_arg<'a, 'b>() -> Arg<'a, 'b> {
    Arg::with_name("MIGRATION_DIRECTORY")
        .long("migration-dir")
        .help(
            "The location of your migration directory. By default this \
             will look for a directory called `migrations` in the \
             current directory and its parents.",
        )
        .takes_value(true)
        .global(true)
}
<commit_msg>Add cli options to revert and redo all<commit_after>use clap::{App, AppSettings, Arg, Shell, SubCommand};

pub fn build_cli() -> App<'static, 'static> {
    let database_arg = Arg::with_name("DATABASE_URL")
        .long("database-url")
        .help(
            "Specifies the database URL to connect to. Falls back to \
             the DATABASE_URL environment variable if unspecified.",
        )
        .global(true)
        .takes_value(true);

    let migration_subcommand = SubCommand::with_name("migration")
        .about(
            "A group of commands for generating, running, and reverting \
             migrations.",
        )
        .setting(AppSettings::VersionlessSubcommands)
        .arg(migration_dir_arg())
        .subcommand(SubCommand::with_name("run").about("Runs all pending migrations"))
        .subcommand(
            SubCommand::with_name("revert")
                .about("Reverts the latest run migration")
                .arg(
                    Arg::with_name("REVERT_ALL")
                        .long("all")
                        .help("Reverts all migrations")
                        .long_help(
                            "When this option is specified all migrations \
                            will be reverted. Useful for testing your revert \
                            scripts only.",
                        )
                )
        )
        .subcommand(
            SubCommand::with_name("redo")
                .about(
                    "Reverts and re-runs the latest migration. Useful \
                    for testing that a migration can in fact be reverted.",
                )
                .arg(
                    Arg::with_name("REDO_ALL")
                        .long("all")
                        .help("Reverts and re-runs all migrations.")
                        .long_help(
                            "When this option is specified all migrations \
                            will be reverts and re-runs. Useful for testing \
                            that your migrations can be reverted and applied."
                        )
                )
            )
        .subcommand(
            SubCommand::with_name("list")
                .about("Lists all available migrations, marking those that have been applied."),
        )
        .subcommand(
            SubCommand::with_name("pending")
                .about("Returns true if there are any pending migrations."),
        )
        .subcommand(
            SubCommand::with_name("generate")
                .about(
                    "Generate a new migration with the given name, and \
                     the current timestamp as the version",
                )
                .arg(
                    Arg::with_name("MIGRATION_NAME")
                        .help("The name of the migration to create")
                        .required(true),
                )
                .arg(
                    Arg::with_name("MIGRATION_VERSION")
                        .long("version")
                        .help(
                            "The version number to use when generating the migration. \
                             Defaults to the current timestamp, which should suffice \
                             for most use cases.",
                        )
                        .takes_value(true),
                )
                .arg(
                    Arg::with_name("MIGRATION_FORMAT")
                        .long("format")
                        .possible_values(&["sql", "barrel"])
                        .default_value("sql")
                        .takes_value(true)
                        .help("The format of the migration to be generated."),
                ),
        )
        .setting(AppSettings::SubcommandRequiredElseHelp);

    let setup_subcommand = SubCommand::with_name("setup")
        .arg(migration_dir_arg())
        .about(
            "Creates the migrations directory, creates the database \
             specified in your DATABASE_URL, and runs existing migrations.",
        );

    let database_subcommand = SubCommand::with_name("database")
        .alias("db")
        .arg(migration_dir_arg())
        .about("A group of commands for setting up and resetting your database.")
        .setting(AppSettings::VersionlessSubcommands)
        .subcommand(SubCommand::with_name("setup").about(
            "Creates the database specified in your DATABASE_URL, \
             and then runs any existing migrations.",
        ))
        .subcommand(SubCommand::with_name("reset").about(
            "Resets your database by dropping the database specified \
             in your DATABASE_URL and then running `diesel database setup`.",
        ))
        .subcommand(
            SubCommand::with_name("drop")
                .about("Drops the database specified in your DATABASE_URL.")
                .setting(AppSettings::Hidden),
        )
        .setting(AppSettings::SubcommandRequiredElseHelp);

    let generate_bash_completion_subcommand = SubCommand::with_name("bash-completion")
        .about("DEPRECATED: Generate bash completion script for the diesel command.");

    let generate_completions_subcommand = SubCommand::with_name("completions")
        .about("Generate shell completion scripts for the diesel command.")
        .arg(
            Arg::with_name("SHELL")
                .index(1)
                .required(true)
                .possible_values(&Shell::variants()),
        );

    let infer_schema_subcommand = SubCommand::with_name("print-schema")
        .setting(AppSettings::VersionlessSubcommands)
        .about("Print table definitions for database schema.")
        .arg(
            Arg::with_name("schema")
                .long("schema")
                .short("s")
                .takes_value(true)
                .help("The name of the schema."),
        )
        .arg(
            Arg::with_name("table-name")
                .index(1)
                .takes_value(true)
                .multiple(true)
                .help("Table names to filter (default only-tables if not empty)"),
        )
        .arg(
            Arg::with_name("only-tables")
                .short("o")
                .long("only-tables")
                .help("Only include tables from table-name that matches regexp")
                .conflicts_with("except-tables"),
        )
        .arg(
            Arg::with_name("except-tables")
                .short("e")
                .long("except-tables")
                .help("Exclude tables from table-name that matches regex")
                .conflicts_with("only-tables"),
        )
        .arg(
            Arg::with_name("with-docs")
                .long("with-docs")
                .help("Render documentation comments for tables and columns"),
        )
        .arg(
            Arg::with_name("patch-file")
                .long("patch-file")
                .takes_value(true)
                .help("A unified diff file to be applied to the final schema"),
        )
        .arg(
            Arg::with_name("import-types")
                .long("import-types")
                .takes_value(true)
                .multiple(true)
                .number_of_values(1)
                .help("A list of types to import for every table, separated by commas"),
        );

    let config_arg = Arg::with_name("CONFIG_FILE")
        .long("config-file")
        .help(
            "The location of the configuration file to use. Falls back to the \
             `DIESEL_CONFIG_FILE` environment variable if unspecified. Defaults \
             to `diesel.toml` in your project root. See \
             diesel.rs/guides/configuring-diesel-cli for documentation on this file.",
        )
        .global(true)
        .takes_value(true);

    let locked_schema_arg = Arg::with_name("LOCKED_SCHEMA")
        .long("locked-schema")
        .help("Require that the schema file is up to date")
        .long_help(
            "When `print_schema.file` is specified in your config file, this \
             flag will cause Diesel CLI to error if any command would result in \
             changes to that file. It is recommended that you use this flag when \
             running migrations in CI or production.",
        )
        .global(true);

    App::new("diesel")
        .version(env!("CARGO_PKG_VERSION"))
        .setting(AppSettings::VersionlessSubcommands)
        .after_help(
            "You can also run `diesel SUBCOMMAND -h` to get more information about that subcommand.",
        )
        .arg(database_arg)
        .arg(config_arg)
        .arg(locked_schema_arg)
        .subcommand(migration_subcommand)
        .subcommand(setup_subcommand)
        .subcommand(database_subcommand)
        .subcommand(generate_bash_completion_subcommand)
        .subcommand(generate_completions_subcommand)
        .subcommand(infer_schema_subcommand)
        .setting(AppSettings::SubcommandRequiredElseHelp)
}

fn migration_dir_arg<'a, 'b>() -> Arg<'a, 'b> {
    Arg::with_name("MIGRATION_DIRECTORY")
        .long("migration-dir")
        .help(
            "The location of your migration directory. By default this \
             will look for a directory called `migrations` in the \
             current directory and its parents.",
        )
        .takes_value(true)
        .global(true)
}
<|endoftext|>


<commit_before>use std::error::Error;

use handlebars::{handlebars_helper, Handlebars};
use time::format_description::parse;
use time::OffsetDateTime;

// define a helper using helper
// a date format helper accept an `OffsetDateTime` as parameter
handlebars_helper!(date: |dt: OffsetDateTime| dt.format(&parse("[year]-[month]-[day]").unwrap()).unwrap());

// a helper returns number of provided parameters
handlebars_helper!(nargs: |*args| args.len());

// a helper provides format
handlebars_helper!(date2: |dt: OffsetDateTime, {fmt:str = "[year]-[month]-[day]"}|
    dt.format(&parse(fmt).unwrap()).unwrap()
);

fn main() -> Result<(), Box<dyn Error>> {
    // create the handlebars registry
    let mut handlebars = Handlebars::new();

    handlebars.register_helper("date", Box::new(date));
    handlebars.register_helper("date2", Box::new(date2));
    handlebars.register_helper("nargs", Box::new(nargs));

    let data = OffsetDateTime::now_utc();

    println!("{}", handlebars.render_template("{{date this}}", &data)?);
    println!("{}", handlebars.render_template("{{date2 this}}", &data)?);
    println!(
        "{}",
        handlebars.render_template("{{date2 this fmt=\"[day]/[month]/[year]\"}}", &data)?
    );

    println!("{}", handlebars.render_template("{{nargs 1 2 3 4}}", &())?);

    Ok(())
}
<commit_msg>chore: update example for helper macro<commit_after>use std::error::Error;

use handlebars::JsonRender;

use handlebars::{handlebars_helper, Handlebars};
use time::format_description::parse;
use time::OffsetDateTime;

// define a helper using helper
// a date format helper accept an `OffsetDateTime` as parameter
handlebars_helper!(date: |dt: OffsetDateTime| dt.format(&parse("[year]-[month]-[day]").unwrap()).unwrap());

// a helper returns number of provided parameters
handlebars_helper!(nargs: |*args| args.len());

// a helper joins all values, using both hash and parameters
handlebars_helper!(join: |{sep:str=","}, *args|
                   args.iter().map(|a| a.render()).collect::<Vec<String>>().join(sep)
);

// a helper provides format
handlebars_helper!(date2: |dt: OffsetDateTime, {fmt:str = "[year]-[month]-[day]"}|
    dt.format(&parse(fmt).unwrap()).unwrap()
);

fn main() -> Result<(), Box<dyn Error>> {
    // create the handlebars registry
    let mut handlebars = Handlebars::new();

    handlebars.register_helper("date", Box::new(date));
    handlebars.register_helper("date2", Box::new(date2));
    handlebars.register_helper("nargs", Box::new(nargs));
    handlebars.register_helper("join", Box::new(join));

    let data = OffsetDateTime::now_utc();

    println!("{}", handlebars.render_template("{{date this}}", &data)?);
    println!("{}", handlebars.render_template("{{date2 this}}", &data)?);
    println!(
        "{}",
        handlebars.render_template("{{date2 this fmt=\"[day]/[month]/[year]\"}}", &data)?
    );

    println!("{}", handlebars.render_template("{{nargs 1 2 3 4}}", &())?);

    println!(
        "{}",
        handlebars.render_template("{{join 1 2 3 4 sep=\"|\" }}", &())?
    );

    Ok(())
}
<|endoftext|>