<commit_before>extern crate glutin;
#[macro_use]
extern crate glium;
#[cfg(feature = "cgmath")]
extern crate cgmath;
#[cfg(feature = "image")]
extern crate image;

use glium::Surface;
use glium::DisplayBuild;
#[cfg(feature = "cgmath")]
use cgmath::FixedArray;
use std::old_io::BufReader;

mod support;

#[cfg(not(all(feature = "cgmath", feature = "image")))]
fn main() {
    println!("This example requires the `cgmath` and `image` features to be enabled");
}

#[cfg(all(feature = "cgmath", feature = "image"))]
fn main() {
    use glium::DisplayBuild;

    // building the display, ie. the main object
    let display = glutin::WindowBuilder::new()
        .with_dimensions(800, 500)
        .with_title(format!("Glium Deferred Example"))
        .build_glium()
        .unwrap();

    let image = image::load(BufReader::new(include_bytes!("../tests/fixture/opengl.png")), image::PNG).unwrap();
    let opengl_texture = glium::texture::Texture2d::new(&display, image);

    let floor_vertex_buffer = {
        #[derive(Copy)]
        struct Vertex {
            position: [f32; 4],
            normal: [f32; 4],
            texcoord: [f32; 2]
        }

        implement_vertex!(Vertex, position, normal, texcoord);

        glium::VertexBuffer::new(&display,
            vec![
                Vertex { position: [-1.0, 0.0, -1.0, 1.0], normal: [0.0, 1.0, 0.0, 1.0], texcoord: [0.0, 0.0] },
                Vertex { position: [1.0, 0.0, -1.0, 1.0], normal: [0.0, 1.0, 0.0, 1.0], texcoord: [1.0, 0.0] },
                Vertex { position: [1.0, 0.0, 1.0, 1.0], normal: [0.0, 1.0, 0.0, 1.0], texcoord: [1.0, 1.0] },
                Vertex { position: [-1.0, 0.0, 1.0, 1.0], normal: [0.0, 1.0, 0.0, 1.0], texcoord: [0.0, 1.0] },
            ]
        )
    };

    let floor_index_buffer = glium::IndexBuffer::new(&display,
        glium::index::TrianglesList(vec![0u16, 1, 2, 0, 2, 3]));

    let quad_vertex_buffer = {
        #[derive(Copy)]
        struct Vertex {
            position: [f32; 4],
            texcoord: [f32; 2]
        }

        implement_vertex!(Vertex, position, texcoord);

        glium::VertexBuffer::new(&display,
            vec![
                Vertex { position: [0.0, 0.0, 0.0, 1.0], texcoord: [0.0, 0.0] },
                Vertex { position: [800.0, 0.0, 0.0, 1.0], texcoord: [1.0, 0.0] },
                Vertex { position: [800.0, 500.0, 0.0, 1.0], texcoord: [1.0, 1.0] },
                Vertex { position: [0.0, 500.0, 0.0, 1.0], texcoord: [0.0, 1.0] },
            ]
        )
    };

    let quad_index_buffer = glium::IndexBuffer::new(&display,
        glium::index::TrianglesList(vec![0u16, 1, 2, 0, 2, 3]));

    // compiling shaders and linking them together
    let prepass_program = glium::Program::from_source(&display,
        // vertex shader
        "
            #version 130

            uniform mat4 perspective_matrix;
            uniform mat4 view_matrix;
            uniform mat4 model_matrix;

            in vec4 position;
            in vec4 normal;
            in vec2 texcoord;

            smooth out vec4 frag_position;
            smooth out vec4 frag_normal;
            smooth out vec2 frag_texcoord;

            void main() {
                frag_position = model_matrix * position;
                frag_normal = model_matrix * normal;
                frag_texcoord = texcoord;
                gl_Position = perspective_matrix * view_matrix * frag_position;
            }
        ",

        // fragment shader
        "
            #version 130

            uniform sampler2D texture;

            smooth in vec4 frag_position;
            smooth in vec4 frag_normal;
            smooth in vec2 frag_texcoord;

            out vec4 output1;
            out vec4 output2;
            out vec4 output3;
            out vec4 output4;

            void main() {
                output1 = vec4(frag_position);
                output2 = vec4(frag_normal);
                output3 = texture2D(texture, frag_texcoord);
                output4 = vec4(1.0, 0.0, 1.0, 1.0);
            }
        ",

        // geometry shader
        None)
        .unwrap();

    let lighting_program = glium::Program::from_source(&display,
        // vertex shader
        "
            #version 130

            uniform mat4 matrix;

            in vec4 position;
            in vec2 texcoord;

            smooth out vec2 frag_texcoord;

            void main() {
                gl_Position = matrix * position;
                frag_texcoord = texcoord;
            }
        ",

        // fragment shader
        "
            #version 130

            uniform sampler2D position_texture;
            uniform sampler2D normal_texture;
            uniform vec4 light_position;
            uniform vec3 light_color;
            uniform vec3 light_attenuation;
            uniform float light_radius;

            smooth in vec2 frag_texcoord;

            out vec4 frag_output;

            void main() {
                vec4 position = texture2D(position_texture, frag_texcoord);
                vec4 normal = texture2D(normal_texture, frag_texcoord);
                vec3 light_vector = light_position.xyz - position.xyz;
                float light_distance = abs(length(light_vector));
                vec3 normal_vector = normalize(normal.xyz);
                float diffuse = max(dot(normal_vector, light_vector), 0.0);
                if (diffuse > 0.0) {
                    float attenuation_factor = 1.0 / (
                        light_attenuation.x +
                        (light_attenuation.y * light_distance) +
                        (light_attenuation.z * light_distance * light_distance)
                    );
                    attenuation_factor *= (1.0 - pow((light_distance / light_radius), 2.0));
                    diffuse *= attenuation_factor;

                }
                frag_output = vec4(light_color * diffuse, 1.0);
            }
        ",

        // geometry shader
        None)
        .unwrap();

    // compiling shaders and linking them together
    let composition_program = glium::Program::from_source(&display,
        // vertex shader
        "
            #version 130

            uniform mat4 matrix;

            in vec4 position;
            in vec2 texcoord;

            smooth out vec2 frag_texcoord;

            void main() {
                frag_texcoord = texcoord;
                gl_Position = matrix * position;
            }
        ",

        // fragment shader
        "
            #version 130

            uniform sampler2D decal_texture;
            uniform sampler2D lighting_texture;

            smooth in vec2 frag_texcoord;

            out vec4 frag_output;

            void main() {
                vec4 lighting_value = texture2D(lighting_texture, frag_texcoord);
                frag_output = vec4(texture2D(decal_texture, frag_texcoord).rgb * lighting_value.rgb, 1.0);
            }
        ",

        // geometry shader
        None)
        .unwrap();

    /*// creating the uniforms structure
    #[uniforms]
    #[derive(Copy)]
    struct PrepassUniforms<'a> {
        perspective_matrix: [[f32; 4]; 4],
        view_matrix: [[f32; 4]; 4],
        model_matrix: [[f32; 4]; 4],
        texture: &'a glium::texture::Texture2d
    }

    #[uniforms]
    #[derive(Copy)]
    struct LightingUniforms<'a> {
        matrix: [[f32; 4]; 4],
        position_texture: &'a glium::texture::Texture2d,
        normal_texture: &'a glium::texture::Texture2d,
        light_position: [f32; 4],
        light_color: [f32; 3],
        light_attenuation: [f32; 3],
        light_radius: f32
    }

    #[uniforms]
    #[derive(Copy)]
    struct CompositionUniforms<'a> {
        matrix: [[f32; 4]; 4],
        decal_texture: &'a glium::texture::Texture2d,
        lighting_texture: &'a glium::texture::Texture2d
    }*/

    struct Light {
        position: [f32; 4],
        color: [f32; 3],
        attenuation: [f32; 3],
        radius: f32
    }

    let texture1 = glium::texture::Texture2d::new_empty(&display, glium::texture::UncompressedFloatFormat::F32F32F32F32, 800, 500);
    let texture2 = glium::texture::Texture2d::new_empty(&display, glium::texture::UncompressedFloatFormat::F32F32F32F32, 800, 500);
    let texture3 = glium::texture::Texture2d::new_empty(&display, glium::texture::UncompressedFloatFormat::F32F32F32F32, 800, 500);
    let texture4 = glium::texture::Texture2d::new_empty(&display, glium::texture::UncompressedFloatFormat::F32F32F32F32, 800, 500);
    let depthtexture = glium::texture::DepthTexture2d::new_empty(&display, glium::texture::DepthFormat::F32, 800, 500);
    let output = &[("output1", &texture1), ("output2", &texture2), ("output3", &texture3), ("output4", &texture4)];
    let mut framebuffer = glium::framebuffer::MultiOutputFrameBuffer::with_depth_buffer(&display, output, &depthtexture);

    let light_texture = glium::texture::Texture2d::new_empty(&display, glium::texture::UncompressedFloatFormat::F32F32F32F32, 800, 500);
    let mut light_buffer = glium::framebuffer::SimpleFrameBuffer::with_depth_buffer(&display, &light_texture, &depthtexture);

    let ortho_matrix: cgmath::Matrix4<f32> = cgmath::ortho(0.0, 800.0, 0.0, 500.0, -1.0, 1.0);
    let fixed_ortho_matrix = ortho_matrix.as_fixed();

    let perspective_matrix: cgmath::Matrix4<f32> = cgmath::perspective(cgmath::deg(45.0), 1.333, 0.0001, 100.0);
    let fixed_perspective_matrix = perspective_matrix.as_fixed();
    let view_eye: cgmath::Point3<f32> = cgmath::Point3::new(0.0, 2.0, -2.0);
    let view_center: cgmath::Point3<f32> = cgmath::Point3::new(0.0, 0.0, 0.0);
    let view_up: cgmath::Vector3<f32> = cgmath::Vector3::new(0.0, 1.0, 0.0);
    let view_matrix: cgmath::Matrix4<f32> = cgmath::Matrix4::look_at(&view_eye, &view_center, &view_up);
    let fixed_view_matrix = view_matrix.as_fixed();
    let model_matrix: cgmath::Matrix4<f32> = cgmath::Matrix4::identity();
    let fixed_model_matrix = model_matrix.as_fixed();

    let lights = [
        Light {
            position: [1.0, 1.0, 1.0, 1.0],
            attenuation: [0.8, 0.00125, 0.0000001],
            color: [1.0, 0.0, 0.0],
            radius: 1.5
        },
        Light {
            position: [0.0, 1.0, 0.0, 1.0],
            attenuation: [0.8, 0.00125, 0.0000001],
            color: [0.0, 1.0, 0.0],
            radius: 1.5
        },
        Light {
            position: [0.0, 1.0, 1.0, 1.0],
            attenuation: [0.8, 0.00125, 0.0000001],
            color: [0.0, 0.0, 1.0],
            radius: 1.5
        },
        Light {
            position: [1.0, 1.0, 0.0, 1.0],
            attenuation: [0.8, 0.00125, 0.0000001],
            color: [1.0, 1.0, 0.0],
            radius: 1.5
        }
    ];

    // the main loop
    support::start_loop(|| {
        // prepass
        let uniforms = uniform! {
            perspective_matrix: *fixed_perspective_matrix,
            view_matrix: *fixed_view_matrix,
            model_matrix: *fixed_model_matrix,
            texture: &opengl_texture
        };
        framebuffer.clear_color(0.0, 0.0, 0.0, 0.0);
        framebuffer.draw(&floor_vertex_buffer, &floor_index_buffer, &prepass_program, &uniforms, &std::default::Default::default()).unwrap();

        // lighting
        let draw_params = glium::DrawParameters {
            //depth_function: glium::DepthFunction::IfLessOrEqual,
            blending_function: Some(glium::BlendingFunction::Addition{
                source: glium::LinearBlendingFactor::One,
                destination: glium::LinearBlendingFactor::One
            }),
            .. std::default::Default::default()
        };
        light_buffer.clear_color(0.0, 0.0, 0.0, 0.0);
        for light in lights.iter() {
            let uniforms = uniform! {
                matrix: *fixed_ortho_matrix,
                position_texture: &texture1,
                normal_texture: &texture2,
                light_position: light.position,
                light_attenuation: light.attenuation,
                light_color: light.color,
                light_radius: light.radius
            };
            light_buffer.draw(&quad_vertex_buffer, &quad_index_buffer, &lighting_program, &uniforms, &draw_params).unwrap();
        }

        // composition
        let uniforms = uniform! {
            matrix: *fixed_ortho_matrix,
            decal_texture: &texture3,
            lighting_texture: &light_texture
        };
        let mut target = display.draw();
        target.clear_color(0.0, 0.0, 0.0, 0.0);
        target.draw(&quad_vertex_buffer, &quad_index_buffer, &composition_program, &uniforms, &std::default::Default::default()).unwrap();
        target.finish();

        // polling and handling the events received by the window
        for event in display.poll_events() {
            match event {
                glutin::Event::Closed => return support::Action::Stop,
                _ => ()
            }
        }

        support::Action::Continue
    });
}
<commit_msg>Fix the OpenGL logo being in the wrong direction in the deferred example<commit_after>extern crate glutin;
#[macro_use]
extern crate glium;
#[cfg(feature = "cgmath")]
extern crate cgmath;
#[cfg(feature = "image")]
extern crate image;

use glium::Surface;
use glium::DisplayBuild;
#[cfg(feature = "cgmath")]
use cgmath::FixedArray;
use std::old_io::BufReader;

mod support;

#[cfg(not(all(feature = "cgmath", feature = "image")))]
fn main() {
    println!("This example requires the `cgmath` and `image` features to be enabled");
}

#[cfg(all(feature = "cgmath", feature = "image"))]
fn main() {
    use glium::DisplayBuild;

    // building the display, ie. the main object
    let display = glutin::WindowBuilder::new()
        .with_dimensions(800, 500)
        .with_title(format!("Glium Deferred Example"))
        .build_glium()
        .unwrap();

    let image = image::load(BufReader::new(include_bytes!("../tests/fixture/opengl.png")), image::PNG).unwrap();
    let opengl_texture = glium::texture::Texture2d::new(&display, image);

    let floor_vertex_buffer = {
        #[derive(Copy)]
        struct Vertex {
            position: [f32; 4],
            normal: [f32; 4],
            texcoord: [f32; 2]
        }

        implement_vertex!(Vertex, position, normal, texcoord);

        glium::VertexBuffer::new(&display,
            vec![
                Vertex { position: [-1.0, 0.0, -1.0, 1.0], normal: [0.0, 1.0, 0.0, 1.0], texcoord: [1.0, 0.0] },
                Vertex { position: [1.0, 0.0, -1.0, 1.0], normal: [0.0, 1.0, 0.0, 1.0], texcoord: [0.0, 0.0] },
                Vertex { position: [1.0, 0.0, 1.0, 1.0], normal: [0.0, 1.0, 0.0, 1.0], texcoord: [0.0, 1.0] },
                Vertex { position: [-1.0, 0.0, 1.0, 1.0], normal: [0.0, 1.0, 0.0, 1.0], texcoord: [1.0, 1.0] },
            ]
        )
    };

    let floor_index_buffer = glium::IndexBuffer::new(&display,
        glium::index::TrianglesList(vec![0u16, 1, 2, 0, 2, 3]));

    let quad_vertex_buffer = {
        #[derive(Copy)]
        struct Vertex {
            position: [f32; 4],
            texcoord: [f32; 2]
        }

        implement_vertex!(Vertex, position, texcoord);

        glium::VertexBuffer::new(&display,
            vec![
                Vertex { position: [0.0, 0.0, 0.0, 1.0], texcoord: [0.0, 0.0] },
                Vertex { position: [800.0, 0.0, 0.0, 1.0], texcoord: [1.0, 0.0] },
                Vertex { position: [800.0, 500.0, 0.0, 1.0], texcoord: [1.0, 1.0] },
                Vertex { position: [0.0, 500.0, 0.0, 1.0], texcoord: [0.0, 1.0] },
            ]
        )
    };

    let quad_index_buffer = glium::IndexBuffer::new(&display,
        glium::index::TrianglesList(vec![0u16, 1, 2, 0, 2, 3]));

    // compiling shaders and linking them together
    let prepass_program = glium::Program::from_source(&display,
        // vertex shader
        "
            #version 130

            uniform mat4 perspective_matrix;
            uniform mat4 view_matrix;
            uniform mat4 model_matrix;

            in vec4 position;
            in vec4 normal;
            in vec2 texcoord;

            smooth out vec4 frag_position;
            smooth out vec4 frag_normal;
            smooth out vec2 frag_texcoord;

            void main() {
                frag_position = model_matrix * position;
                frag_normal = model_matrix * normal;
                frag_texcoord = texcoord;
                gl_Position = perspective_matrix * view_matrix * frag_position;
            }
        ",

        // fragment shader
        "
            #version 130

            uniform sampler2D texture;

            smooth in vec4 frag_position;
            smooth in vec4 frag_normal;
            smooth in vec2 frag_texcoord;

            out vec4 output1;
            out vec4 output2;
            out vec4 output3;
            out vec4 output4;

            void main() {
                output1 = vec4(frag_position);
                output2 = vec4(frag_normal);
                output3 = texture2D(texture, frag_texcoord);
                output4 = vec4(1.0, 0.0, 1.0, 1.0);
            }
        ",

        // geometry shader
        None)
        .unwrap();

    let lighting_program = glium::Program::from_source(&display,
        // vertex shader
        "
            #version 130

            uniform mat4 matrix;

            in vec4 position;
            in vec2 texcoord;

            smooth out vec2 frag_texcoord;

            void main() {
                gl_Position = matrix * position;
                frag_texcoord = texcoord;
            }
        ",

        // fragment shader
        "
            #version 130

            uniform sampler2D position_texture;
            uniform sampler2D normal_texture;
            uniform vec4 light_position;
            uniform vec3 light_color;
            uniform vec3 light_attenuation;
            uniform float light_radius;

            smooth in vec2 frag_texcoord;

            out vec4 frag_output;

            void main() {
                vec4 position = texture2D(position_texture, frag_texcoord);
                vec4 normal = texture2D(normal_texture, frag_texcoord);
                vec3 light_vector = light_position.xyz - position.xyz;
                float light_distance = abs(length(light_vector));
                vec3 normal_vector = normalize(normal.xyz);
                float diffuse = max(dot(normal_vector, light_vector), 0.0);
                if (diffuse > 0.0) {
                    float attenuation_factor = 1.0 / (
                        light_attenuation.x +
                        (light_attenuation.y * light_distance) +
                        (light_attenuation.z * light_distance * light_distance)
                    );
                    attenuation_factor *= (1.0 - pow((light_distance / light_radius), 2.0));
                    diffuse *= attenuation_factor;

                }
                frag_output = vec4(light_color * diffuse, 1.0);
            }
        ",

        // geometry shader
        None)
        .unwrap();

    // compiling shaders and linking them together
    let composition_program = glium::Program::from_source(&display,
        // vertex shader
        "
            #version 130

            uniform mat4 matrix;

            in vec4 position;
            in vec2 texcoord;

            smooth out vec2 frag_texcoord;

            void main() {
                frag_texcoord = texcoord;
                gl_Position = matrix * position;
            }
        ",

        // fragment shader
        "
            #version 130

            uniform sampler2D decal_texture;
            uniform sampler2D lighting_texture;

            smooth in vec2 frag_texcoord;

            out vec4 frag_output;

            void main() {
                vec4 lighting_value = texture2D(lighting_texture, frag_texcoord);
                frag_output = vec4(texture2D(decal_texture, frag_texcoord).rgb * lighting_value.rgb, 1.0);
            }
        ",

        // geometry shader
        None)
        .unwrap();

    /*// creating the uniforms structure
    #[uniforms]
    #[derive(Copy)]
    struct PrepassUniforms<'a> {
        perspective_matrix: [[f32; 4]; 4],
        view_matrix: [[f32; 4]; 4],
        model_matrix: [[f32; 4]; 4],
        texture: &'a glium::texture::Texture2d
    }

    #[uniforms]
    #[derive(Copy)]
    struct LightingUniforms<'a> {
        matrix: [[f32; 4]; 4],
        position_texture: &'a glium::texture::Texture2d,
        normal_texture: &'a glium::texture::Texture2d,
        light_position: [f32; 4],
        light_color: [f32; 3],
        light_attenuation: [f32; 3],
        light_radius: f32
    }

    #[uniforms]
    #[derive(Copy)]
    struct CompositionUniforms<'a> {
        matrix: [[f32; 4]; 4],
        decal_texture: &'a glium::texture::Texture2d,
        lighting_texture: &'a glium::texture::Texture2d
    }*/

    struct Light {
        position: [f32; 4],
        color: [f32; 3],
        attenuation: [f32; 3],
        radius: f32
    }

    let texture1 = glium::texture::Texture2d::new_empty(&display, glium::texture::UncompressedFloatFormat::F32F32F32F32, 800, 500);
    let texture2 = glium::texture::Texture2d::new_empty(&display, glium::texture::UncompressedFloatFormat::F32F32F32F32, 800, 500);
    let texture3 = glium::texture::Texture2d::new_empty(&display, glium::texture::UncompressedFloatFormat::F32F32F32F32, 800, 500);
    let texture4 = glium::texture::Texture2d::new_empty(&display, glium::texture::UncompressedFloatFormat::F32F32F32F32, 800, 500);
    let depthtexture = glium::texture::DepthTexture2d::new_empty(&display, glium::texture::DepthFormat::F32, 800, 500);
    let output = &[("output1", &texture1), ("output2", &texture2), ("output3", &texture3), ("output4", &texture4)];
    let mut framebuffer = glium::framebuffer::MultiOutputFrameBuffer::with_depth_buffer(&display, output, &depthtexture);

    let light_texture = glium::texture::Texture2d::new_empty(&display, glium::texture::UncompressedFloatFormat::F32F32F32F32, 800, 500);
    let mut light_buffer = glium::framebuffer::SimpleFrameBuffer::with_depth_buffer(&display, &light_texture, &depthtexture);

    let ortho_matrix: cgmath::Matrix4<f32> = cgmath::ortho(0.0, 800.0, 0.0, 500.0, -1.0, 1.0);
    let fixed_ortho_matrix = ortho_matrix.as_fixed();

    let perspective_matrix: cgmath::Matrix4<f32> = cgmath::perspective(cgmath::deg(45.0), 1.333, 0.0001, 100.0);
    let fixed_perspective_matrix = perspective_matrix.as_fixed();
    let view_eye: cgmath::Point3<f32> = cgmath::Point3::new(0.0, 2.0, -2.0);
    let view_center: cgmath::Point3<f32> = cgmath::Point3::new(0.0, 0.0, 0.0);
    let view_up: cgmath::Vector3<f32> = cgmath::Vector3::new(0.0, 1.0, 0.0);
    let view_matrix: cgmath::Matrix4<f32> = cgmath::Matrix4::look_at(&view_eye, &view_center, &view_up);
    let fixed_view_matrix = view_matrix.as_fixed();
    let model_matrix: cgmath::Matrix4<f32> = cgmath::Matrix4::identity();
    let fixed_model_matrix = model_matrix.as_fixed();

    let lights = [
        Light {
            position: [1.0, 1.0, 1.0, 1.0],
            attenuation: [0.8, 0.00125, 0.0000001],
            color: [1.0, 0.0, 0.0],
            radius: 1.5
        },
        Light {
            position: [0.0, 1.0, 0.0, 1.0],
            attenuation: [0.8, 0.00125, 0.0000001],
            color: [0.0, 1.0, 0.0],
            radius: 1.5
        },
        Light {
            position: [0.0, 1.0, 1.0, 1.0],
            attenuation: [0.8, 0.00125, 0.0000001],
            color: [0.0, 0.0, 1.0],
            radius: 1.5
        },
        Light {
            position: [1.0, 1.0, 0.0, 1.0],
            attenuation: [0.8, 0.00125, 0.0000001],
            color: [1.0, 1.0, 0.0],
            radius: 1.5
        }
    ];

    // the main loop
    support::start_loop(|| {
        // prepass
        let uniforms = uniform! {
            perspective_matrix: *fixed_perspective_matrix,
            view_matrix: *fixed_view_matrix,
            model_matrix: *fixed_model_matrix,
            texture: &opengl_texture
        };
        framebuffer.clear_color(0.0, 0.0, 0.0, 0.0);
        framebuffer.draw(&floor_vertex_buffer, &floor_index_buffer, &prepass_program, &uniforms, &std::default::Default::default()).unwrap();

        // lighting
        let draw_params = glium::DrawParameters {
            //depth_function: glium::DepthFunction::IfLessOrEqual,
            blending_function: Some(glium::BlendingFunction::Addition{
                source: glium::LinearBlendingFactor::One,
                destination: glium::LinearBlendingFactor::One
            }),
            .. std::default::Default::default()
        };
        light_buffer.clear_color(0.0, 0.0, 0.0, 0.0);
        for light in lights.iter() {
            let uniforms = uniform! {
                matrix: *fixed_ortho_matrix,
                position_texture: &texture1,
                normal_texture: &texture2,
                light_position: light.position,
                light_attenuation: light.attenuation,
                light_color: light.color,
                light_radius: light.radius
            };
            light_buffer.draw(&quad_vertex_buffer, &quad_index_buffer, &lighting_program, &uniforms, &draw_params).unwrap();
        }

        // composition
        let uniforms = uniform! {
            matrix: *fixed_ortho_matrix,
            decal_texture: &texture3,
            lighting_texture: &light_texture
        };
        let mut target = display.draw();
        target.clear_color(0.0, 0.0, 0.0, 0.0);
        target.draw(&quad_vertex_buffer, &quad_index_buffer, &composition_program, &uniforms, &std::default::Default::default()).unwrap();
        target.finish();

        // polling and handling the events received by the window
        for event in display.poll_events() {
            match event {
                glutin::Event::Closed => return support::Action::Stop,
                _ => ()
            }
        }

        support::Action::Continue
    });
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;

#[derive(Debug, Deserialize)]
pub struct Service {
    pub documentation: Option<String>,
    pub examples: Option<BTreeMap<String, String>>,
    pub metadata: Metadata,
    pub operations: BTreeMap<String, Operation>,
    pub shapes: BTreeMap<String, Shape>,
    pub version: String,
}

impl Service {
    pub fn client_type_name(&self) -> String {
        format!("{}Client", self.service_type_name())
    }

    pub fn error_type_name(&self) -> String {
        format!("{}Error", self.service_type_name())
    }

    fn service_type_name(&self) -> String {
        self.metadata.service_abbreviation.replace("Amazon ", "").replace(" ", "")
    }
}

#[derive(Debug, Deserialize)]
pub struct HttpRequest {
    pub method: String,
    #[serde(rename="requestUri")]
    pub request_uri: String,
}

#[derive(Debug, Deserialize)]
pub struct Input {
    pub documentation: Option<String>,
    pub shape: String,
}

#[derive(Debug, Deserialize)]
pub struct Output {
    pub documentation: Option<String>,
    #[serde(rename="resultWrapper")]
    pub result_wrapper: Option<String>,
    pub shape: String,
}

#[derive(Debug, Deserialize)]
pub struct Error {
    pub documentation: Option<String>,
    pub error: Option<HttpError>,
    pub exception: Option<bool>,
    pub fault: Option<bool>,
    pub shape: String,
}

#[derive(Debug, Deserialize)]
pub struct HttpError {
    pub code: String,
    #[serde(rename="httpStatusCode")]
    pub http_status_code: i32,
    #[serde(rename="senderFault")]
    pub sender_fault: Option<bool>,
}

#[derive(Debug, Deserialize)]
pub struct Member {
    pub deprecated: Option<bool>,
    pub documentation: Option<String>,
    pub flattened: Option<bool>,
    pub location: Option<String>,
    #[serde(rename="locationName")]
    pub location_name: Option<String>,
    pub shape: String,
    pub streaming: Option<bool>,
    #[serde(rename="xmlAttribute")]
    pub xml_attribute: Option<bool>,
    #[serde(rename="xmlNamespace")]
    pub xml_namespace: Option<XmlNamespace>,
}

#[derive(Debug, Deserialize)]
pub struct XmlNamespace {
    pub prefix: Option<String>,
    pub uri: String,
}

#[derive(Debug, Deserialize)]
pub struct Key {
    pub documentation: Option<String>,
    #[serde(rename="locationName")]
    pub location_name: Option<String>,
    pub required: Option<bool>,
    pub shape: String,
}

#[derive(Debug, Deserialize)]
pub struct Value {
    pub documentation: Option<String>,
    #[serde(rename="locationName")]
    pub location_name: Option<String>,
    pub shape: String,
}

#[derive(Debug, Deserialize)]
pub struct Shape {
    #[serde(rename="box")]
    pub aws_box: Option<bool>,
    pub documentation: Option<String>,
    pub error: Option<HttpError>,
    pub exception: Option<bool>,
    pub fault: Option<bool>,
    pub flattened: Option<bool>,
    pub key: Option<Key>,
    #[serde(rename="locationName")]
    pub location_name: Option<String>,
    pub max: Option<i32>,
    pub member: Option<Member>,
    pub members: Option<BTreeMap<String, Member>>,
    pub min: Option<i32>,
    pub pattern: Option<String>,
    pub payload: Option<String>,
    pub required: Option<Vec<String>>,
    #[serde(rename="enum")]
    pub shape_enum: Option<Vec<String>>,
    #[serde(rename="type")]
    pub shape_type: String,
    pub sensitive: Option<bool>,
    #[serde(rename="timestampFormat")]
    pub timestamp_format: Option<String>,
    pub value: Option<Value>,
    #[serde(rename="xmlNamespace")]
    pub xml_namespace: Option<XmlNamespace>,
}

impl<'a> Shape {
    pub fn key(&'a self) -> &'a str {
        &self.key.as_ref().expect("Key shape undefined").shape
    }

    pub fn value(&'a self) -> &'a str {
        &self.value.as_ref().expect("Value shape undefined").shape
    }

    pub fn member(&'a self) -> &'a str {
        &self.member.as_ref().expect("Member shape undefined").shape
    }

    pub fn required(&self, field: &'a str) -> bool {
        self.required.is_some() && self.required.as_ref().unwrap().contains(&String::from(field))
    }
}

#[derive(Debug, Deserialize)]
pub struct Operation {
    pub alias: Option<String>,
    pub deprecated: Option<bool>,
    pub documentation: Option<String>,
    #[serde(rename="documentationUrl")]
    pub documentation_url: Option<String>,
    pub errors: Vec<Error>,
    pub http: HttpRequest,
    pub input: Option<Input>,
    pub name: String,
    pub output: Option<Output>,
}

impl<'a> Operation {
    pub fn input_shape(&'a self) -> &'a str {
        &self.input.as_ref().expect("Operation input undefined").shape
    }

    pub fn output_shape_or(&'a self, default: &'a str) -> &'a str {
        match self.output.as_ref() {
            Some(output) => &output.shape,
            None => default
        }
    }
}

#[derive(Debug, Deserialize)]
pub struct Metadata {
    #[serde(rename="apiVersion")]
    pub api_version: String,
    #[serde(rename="checksumFormat")]
    pub checksum_format: Option<String>,
    #[serde(rename="endpointPrefix")]
    pub endpoint_prefix: String,
    #[serde(rename="globalEndpoint")]
    pub global_endpoint: Option<String>,
    #[serde(rename="jsonVersion")]
    pub json_version: Option<String>,
    pub protocol: String,
    #[serde(rename="serviceAbbreviation")]
    pub service_abbreviation: String,
    #[serde(rename="serviceFullName")]
    pub service_full_name: String,
    #[serde(rename="signatureVersion")]
    pub signature_version: String,
    #[serde(rename="targetPrefix")]
    pub target_prefix: Option<String>,
    #[serde(rename="timestampFormat")]
    pub timestamp_format: Option<String>,
    #[serde(rename="xmlNamespace")]
    pub xml_namespace: Option<String>
}
<commit_msg>Not all operations have errors.<commit_after>use std::collections::BTreeMap;

#[derive(Debug, Deserialize)]
pub struct Service {
    pub documentation: Option<String>,
    pub examples: Option<BTreeMap<String, String>>,
    pub metadata: Metadata,
    pub operations: BTreeMap<String, Operation>,
    pub shapes: BTreeMap<String, Shape>,
    pub version: String,
}

impl Service {
    pub fn client_type_name(&self) -> String {
        format!("{}Client", self.service_type_name())
    }

    pub fn error_type_name(&self) -> String {
        format!("{}Error", self.service_type_name())
    }

    fn service_type_name(&self) -> String {
        self.metadata.service_abbreviation.replace("Amazon ", "").replace(" ", "")
    }
}

#[derive(Debug, Deserialize)]
pub struct HttpRequest {
    pub method: String,
    #[serde(rename="requestUri")]
    pub request_uri: String,
}

#[derive(Debug, Deserialize)]
pub struct Input {
    pub documentation: Option<String>,
    pub shape: String,
}

#[derive(Debug, Deserialize)]
pub struct Output {
    pub documentation: Option<String>,
    #[serde(rename="resultWrapper")]
    pub result_wrapper: Option<String>,
    pub shape: String,
}

#[derive(Debug, Deserialize)]
pub struct Error {
    pub documentation: Option<String>,
    pub error: Option<HttpError>,
    pub exception: Option<bool>,
    pub fault: Option<bool>,
    pub shape: String,
}

#[derive(Debug, Deserialize)]
pub struct HttpError {
    pub code: String,
    #[serde(rename="httpStatusCode")]
    pub http_status_code: i32,
    #[serde(rename="senderFault")]
    pub sender_fault: Option<bool>,
}

#[derive(Debug, Deserialize)]
pub struct Member {
    pub deprecated: Option<bool>,
    pub documentation: Option<String>,
    pub flattened: Option<bool>,
    pub location: Option<String>,
    #[serde(rename="locationName")]
    pub location_name: Option<String>,
    pub shape: String,
    pub streaming: Option<bool>,
    #[serde(rename="xmlAttribute")]
    pub xml_attribute: Option<bool>,
    #[serde(rename="xmlNamespace")]
    pub xml_namespace: Option<XmlNamespace>,
}

#[derive(Debug, Deserialize)]
pub struct XmlNamespace {
    pub prefix: Option<String>,
    pub uri: String,
}

#[derive(Debug, Deserialize)]
pub struct Key {
    pub documentation: Option<String>,
    #[serde(rename="locationName")]
    pub location_name: Option<String>,
    pub required: Option<bool>,
    pub shape: String,
}

#[derive(Debug, Deserialize)]
pub struct Value {
    pub documentation: Option<String>,
    #[serde(rename="locationName")]
    pub location_name: Option<String>,
    pub shape: String,
}

#[derive(Debug, Deserialize)]
pub struct Shape {
    #[serde(rename="box")]
    pub aws_box: Option<bool>,
    pub documentation: Option<String>,
    pub error: Option<HttpError>,
    pub exception: Option<bool>,
    pub fault: Option<bool>,
    pub flattened: Option<bool>,
    pub key: Option<Key>,
    #[serde(rename="locationName")]
    pub location_name: Option<String>,
    pub max: Option<i32>,
    pub member: Option<Member>,
    pub members: Option<BTreeMap<String, Member>>,
    pub min: Option<i32>,
    pub pattern: Option<String>,
    pub payload: Option<String>,
    pub required: Option<Vec<String>>,
    #[serde(rename="enum")]
    pub shape_enum: Option<Vec<String>>,
    #[serde(rename="type")]
    pub shape_type: String,
    pub sensitive: Option<bool>,
    #[serde(rename="timestampFormat")]
    pub timestamp_format: Option<String>,
    pub value: Option<Value>,
    #[serde(rename="xmlNamespace")]
    pub xml_namespace: Option<XmlNamespace>,
}

impl<'a> Shape {
    pub fn key(&'a self) -> &'a str {
        &self.key.as_ref().expect("Key shape undefined").shape
    }

    pub fn value(&'a self) -> &'a str {
        &self.value.as_ref().expect("Value shape undefined").shape
    }

    pub fn member(&'a self) -> &'a str {
        &self.member.as_ref().expect("Member shape undefined").shape
    }

    pub fn required(&self, field: &'a str) -> bool {
        self.required.is_some() && self.required.as_ref().unwrap().contains(&String::from(field))
    }
}

#[derive(Debug, Deserialize)]
pub struct Operation {
    pub alias: Option<String>,
    pub deprecated: Option<bool>,
    pub documentation: Option<String>,
    #[serde(rename="documentationUrl")]
    pub documentation_url: Option<String>,
    pub errors: Option<Vec<Error>>,
    pub http: HttpRequest,
    pub input: Option<Input>,
    pub name: String,
    pub output: Option<Output>,
}

impl<'a> Operation {
    pub fn input_shape(&'a self) -> &'a str {
        &self.input.as_ref().expect("Operation input undefined").shape
    }

    pub fn output_shape_or(&'a self, default: &'a str) -> &'a str {
        match self.output.as_ref() {
            Some(output) => &output.shape,
            None => default
        }
    }
}

#[derive(Debug, Deserialize)]
pub struct Metadata {
    #[serde(rename="apiVersion")]
    pub api_version: String,
    #[serde(rename="checksumFormat")]
    pub checksum_format: Option<String>,
    #[serde(rename="endpointPrefix")]
    pub endpoint_prefix: String,
    #[serde(rename="globalEndpoint")]
    pub global_endpoint: Option<String>,
    #[serde(rename="jsonVersion")]
    pub json_version: Option<String>,
    pub protocol: String,
    #[serde(rename="serviceAbbreviation")]
    pub service_abbreviation: String,
    #[serde(rename="serviceFullName")]
    pub service_full_name: String,
    #[serde(rename="signatureVersion")]
    pub signature_version: String,
    #[serde(rename="targetPrefix")]
    pub target_prefix: Option<String>,
    #[serde(rename="timestampFormat")]
    pub timestamp_format: Option<String>,
    #[serde(rename="xmlNamespace")]
    pub xml_namespace: Option<String>
}
<|endoftext|>


<commit_before><commit_msg>Add a test for const<commit_after>// run-pass

#![feature(cow_is_borrowed)]

use std::borrow::Cow;

fn main() {
    const COW: Cow<str> = Cow::Borrowed("moo");

    const IS_BORROWED: bool = COW.is_borrowed();
    assert!(IS_BORROWED);

    const IS_OWNED: bool = COW.is_owned();
    assert!(!IS_OWNED);
}
<|endoftext|>


<commit_before><commit_msg>Started on integration testing<commit_after>
#![feature(box_syntax,box_patterns)]
extern crate seax_svm;

use seax_svm::svm::slist::Stack;
use seax_svm::svm::slist::List::{Cons,Nil};
use seax_svm::svm::State;
use seax_svm::svm::cell::Atom::*;
use seax_svm::svm::cell::SVMCell::*;
use seax_svm::svm::Inst::*;

macro_rules! list(
    ( $e:expr, $($rest:expr),+ ) => ( Cons($e, Box::new(list!( $( $rest ),+ )) ));
    ( $e:expr ) => ( Cons($e, Box::new(Nil)) );
    () => ( Box::new(Nil) );
);

/// SVM integration tests.
///
/// These are based on the sample programs in Zach Allaun's Clojure SECD
/// [implementation](https://github.com/zachallaun/secd). Each example also
/// provides the source code for the equivalent Lisp program.

/// Test for simple list construction through CONS.
///
/// ```lisp
/// (cons 10 (cons 20 nil))
/// ```
#[test]
fn test_list_creation() {
    let state = seax_svm::svm::eval_program(list!(
        InstCell(NIL),
        InstCell(LDC), AtomCell(SInt(10)), InstCell(CONS),
        InstCell(LDC), AtomCell(SInt(20)), InstCell(CONS)
        ));
    assert_eq!(state,
        list!(ListCell(box list!(AtomCell(SInt(20)), AtomCell(SInt(10)))))
    );
}<|endoftext|>


<commit_before><commit_msg>Add calloc test<commit_after>//ignore-windows: Uses POSIX APIs

#![feature(rustc_private)]

use core::slice;

extern crate libc;

fn main() {
    unsafe {
        let p1 = libc::calloc(0, 0);
        assert!(p1.is_null());

        let p2 = libc::calloc(20, 0);
        assert!(p2.is_null());

        let p3 = libc::calloc(0, 20);
        assert!(p3.is_null());

        let p4 = libc::calloc(4, 8) as *const u8;
        assert!(!p4.is_null());

        let slice = slice::from_raw_parts(p4, 4 * 8);
        assert_eq!(&slice, &[0_u8; 4 * 8]);
    }
}
<|endoftext|>


<commit_before><commit_msg>Add regression test for #25368. Fixes #25368.<commit_after>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

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

struct Foo<T> {foo: PhantomData<T>}

fn main() {
    let (tx, rx) = channel();

    spawn(move || {
        tx.send(Foo{ foo: PhantomData }); //~ ERROR E0282
    });
}
<|endoftext|>


<commit_before>#[allow(dead_code)]
extern crate rand;
extern crate orbclient;

use super::vid;
use super::start;

pub fn wireframe(id: u16) -> vid::Shader {
    let wireframe_shader = |triangle: &vid::Triangle, window: &mut start::Window, wrapper: &vid::Shader| {
        let flat_1 = triangle.p1.clone().flat_point(window.screen_x, window.screen_y,
                                            triangle.x + window.camera_x,
                                            triangle.y + window.camera_y,
                                            triangle.z + window.camera_z);
        let flat_2 = triangle.p2.clone().flat_point(window.screen_x, window.screen_y,
                                            triangle.x + window.camera_x,
                                            triangle.y + window.camera_y,
                                            triangle.z + window.camera_z);
        let flat_3 = triangle.p3.clone().flat_point(window.screen_x, window.screen_y,
                                            triangle.x + window.camera_x,
                                            triangle.y + window.camera_y,
                                            triangle.z + window.camera_z);

        window.window.line(flat_1.x, flat_1.y, flat_2.x, flat_2.y, triangle.color.orb_color());
        window.window.line(flat_3.x, flat_3.y, flat_2.x, flat_2.y, triangle.color.orb_color());
        window.window.line(flat_1.x, flat_1.y, flat_3.x, flat_3.y, triangle.color.orb_color());
    };

    vid::Shader::new(id, Box::new(wireframe_shader))
}

pub fn disco_wireframe(id: u16) -> vid::Shader {
    let noise_shader = |triangle: &vid::Triangle, window: &mut start::Window, wrapper: &vid::Shader| {
        let flat_1 = triangle.p1.clone().flat_point(window.screen_x, window.screen_y,
                                            triangle.x + window.camera_x,
                                            triangle.y + window.camera_y,
                                            triangle.z + window.camera_z);
        let flat_2 = triangle.p2.clone().flat_point(window.screen_x, window.screen_y,
                                            triangle.x + window.camera_x,
                                            triangle.y + window.camera_y,
                                            triangle.z + window.camera_z);
        let flat_3 = triangle.p3.clone().flat_point(window.screen_x, window.screen_y,
                                            triangle.x + window.camera_x,
                                            triangle.y + window.camera_y,
                                            triangle.z + window.camera_z);

        window.window.line(flat_1.x, flat_1.y, flat_2.x, flat_2.y, vid::Color::new(rand::random::<u8>(),
                                                                                rand::random::<u8>(),
                                                                                rand::random::<u8>()).orb_color());
        window.window.line(flat_3.x, flat_3.y, flat_2.x, flat_2.y, vid::Color::new(rand::random::<u8>(),
                                                                                rand::random::<u8>(),
                                                                                rand::random::<u8>()).orb_color());
        window.window.line(flat_1.x, flat_1.y, flat_3.x, flat_3.y, vid::Color::new(rand::random::<u8>(),
                                                                                rand::random::<u8>(),
                                                                                rand::random::<u8>()).orb_color());
    };

    vid::Shader::new(id, Box::new(noise_shader))
}

pub fn filled_triangle_color(id: u16) -> vid::Shader {
    let rasterize_shader = |triangle: &vid::Triangle, window: &mut start::Window, wrapper: &vid::Shader| {
        let p1 = triangle.p1.clone().flat_point(window.screen_x, window.screen_y,
                                                triangle.x + window.camera_x,
                                                triangle.y + window.camera_y,
                                                triangle.z + window.camera_z);

        let p2 = triangle.p2.clone().flat_point(window.screen_x, window.screen_y,
                                                triangle.x + window.camera_x,
                                                triangle.y + window.camera_y,
                                                triangle.z + window.camera_z);

        let p3 = triangle.p3.clone().flat_point(window.screen_x, window.screen_y,
                                                triangle.x + window.camera_x,
                                                triangle.y + window.camera_y,
                                                triangle.z + window.camera_z);

        struct FloatPoint {
            x: f32,
            y: f32
        }

        let points = [p1, p2, p3];

        let upmost = points.iter().max_by_key(|p| -p.y).unwrap().clone();
        let leftmost = points.iter().max_by_key(|p| -p.x).unwrap().clone();
        let rightmost = points.iter().max_by_key(|p| p.x).unwrap().clone();
        let lowmost = points.iter().max_by_key(|p| p.y).unwrap().clone();

        for px in leftmost.x..rightmost.x {
            for py in upmost.y..lowmost.y {
                let p1 = FloatPoint {x: p1.x as f32, y: p1.y as f32};
                let p2 = FloatPoint {x: p2.x as f32, y: p2.y as f32};
                let p3 = FloatPoint {x: p3.x as f32, y: p3.y as f32};

                let p = FloatPoint {x: px as f32, y: py as f32};

                let alpha = ((p2.y - p3.y)*(p.x - p3.x) + (p3.x - p2.x)*(p.y - p3.y)) / ((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
                let beta = ((p3.y - p1.y)*(p.x - p3.x) + (p1.x - p3.x)*(p.y - p3.y)) / ((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
                let gamma = 1.0 - alpha - beta;

                if alpha > 0.0 && beta > 0.0 && gamma > 0.0 {
                    window.window.pixel(px, py, triangle.color.orb_color());
                }
            }
        }
    };

    vid::Shader::new(id, Box::new(rasterize_shader))
}

pub fn filled_b_w_noise(id: u16) -> vid::Shader {
    let rasterize_shader = |triangle: &vid::Triangle, window: &mut start::Window, wrapper: &vid::Shader| {
        let p1 = triangle.p1.clone().flat_point(window.screen_x, window.screen_y,
                                                triangle.x + window.camera_x,
                                                triangle.y + window.camera_y,
                                                triangle.z + window.camera_z);

        let p2 = triangle.p2.clone().flat_point(window.screen_x, window.screen_y,
                                                triangle.x + window.camera_x,
                                                triangle.y + window.camera_y,
                                                triangle.z + window.camera_z);

        let p3 = triangle.p3.clone().flat_point(window.screen_x, window.screen_y,
                                                triangle.x + window.camera_x,
                                                triangle.y + window.camera_y,
                                                triangle.z + window.camera_z);

        struct FloatPoint {
            x: f32,
            y: f32
        }

        let points = [p1, p2, p3];

        let upmost = points.iter().max_by_key(|p| -p.y).unwrap().clone();
        let leftmost = points.iter().max_by_key(|p| -p.x).unwrap().clone();
        let rightmost = points.iter().max_by_key(|p| p.x).unwrap().clone();
        let lowmost = points.iter().max_by_key(|p| p.y).unwrap().clone();

        for px in leftmost.x..rightmost.x {
            for py in upmost.y..lowmost.y {
                let p1 = FloatPoint {x: p1.x as f32, y: p1.y as f32};
                let p2 = FloatPoint {x: p2.x as f32, y: p2.y as f32};
                let p3 = FloatPoint {x: p3.x as f32, y: p3.y as f32};

                let p = FloatPoint {x: px as f32, y: py as f32};

                let alpha = ((p2.y - p3.y)*(p.x - p3.x) + (p3.x - p2.x)*(p.y - p3.y)) / ((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
                let beta = ((p3.y - p1.y)*(p.x - p3.x) + (p1.x - p3.x)*(p.y - p3.y)) / ((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
                let gamma = 1.0 - alpha - beta;

                let random = rand::random::<u8>();

                if alpha > 0.0 && beta > 0.0 && gamma > 0.0 {
                    window.window.pixel(px, py, vid::Color::new(random, random, random).orb_color());
                }
            }
        }
    };

    vid::Shader::new(id, Box::new(rasterize_shader))
}

pub fn filled_texture_naive(id: u16, texture_path: &str) -> vid::Shader {
    let img = orbclient::BmpFile::from_path(texture_path);

    let rasterize_shader = |triangle: &vid::Triangle, window: &mut start::Window, wrapper: &vid::Shader| {
        use std::ops::Deref;

        let p1 = triangle.p1.clone().flat_point(window.screen_x, window.screen_y,
                                                triangle.x + window.camera_x,
                                                triangle.y + window.camera_y,
                                                triangle.z + window.camera_z);

        let p2 = triangle.p2.clone().flat_point(window.screen_x, window.screen_y,
                                                triangle.x + window.camera_x,
                                                triangle.y + window.camera_y,
                                                triangle.z + window.camera_z);

        let p3 = triangle.p3.clone().flat_point(window.screen_x, window.screen_y,
                                                triangle.x + window.camera_x,
                                                triangle.y + window.camera_y,
                                                triangle.z + window.camera_z);

        struct FloatPoint {
            x: f32,
            y: f32
        }

        let img_w = wrapper.image_data.width();
        let img_h = wrapper.image_data.height();

        let img_slice = wrapper.image_data.deref();

        let points = [p1, p2, p3];

        let upmost = points.iter().max_by_key(|p| -p.y).unwrap().clone();
        let leftmost = points.iter().max_by_key(|p| -p.x).unwrap().clone();
        let rightmost = points.iter().max_by_key(|p| p.x).unwrap().clone();
        let lowmost = points.iter().max_by_key(|p| p.y).unwrap().clone();

        for px in leftmost.x..rightmost.x {
            for py in upmost.y..lowmost.y {
                let p1 = FloatPoint {x: p1.x as f32, y: p1.y as f32};
                let p2 = FloatPoint {x: p2.x as f32, y: p2.y as f32};
                let p3 = FloatPoint {x: p3.x as f32, y: p3.y as f32};

                let p = FloatPoint {x: px as f32, y: py as f32};

                let alpha = ((p2.y - p3.y)*(p.x - p3.x) + (p3.x - p2.x)*(p.y - p3.y)) / ((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
                let beta = ((p3.y - p1.y)*(p.x - p3.x) + (p1.x - p3.x)*(p.y - p3.y)) / ((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
                let gamma = 1.0 - alpha - beta;

                let random = rand::random::<u8>();

                if alpha > 0.0 && beta > 0.0 && gamma > 0.0 {
                    window.window.pixel(px, py, img_slice[(px + py*(img_w as i32)) as usize]);
                }
            }
        }
    };

    let mut shader = vid::Shader::new(id, Box::new(rasterize_shader));

    shader.image_data = img;

    shader
}
<commit_msg>Added gradient shader<commit_after>extern crate rand;
extern crate orbclient;

use super::vid;
use super::start;

pub fn wireframe(id: u16) -> vid::Shader {
    let wireframe_shader = |triangle: &vid::Triangle, window: &mut start::Window, wrapper: &vid::Shader| {
        let flat_1 = triangle.p1.clone().flat_point(window.screen_x, window.screen_y,
                                            triangle.x + window.camera_x,
                                            triangle.y + window.camera_y,
                                            triangle.z + window.camera_z);
        let flat_2 = triangle.p2.clone().flat_point(window.screen_x, window.screen_y,
                                            triangle.x + window.camera_x,
                                            triangle.y + window.camera_y,
                                            triangle.z + window.camera_z);
        let flat_3 = triangle.p3.clone().flat_point(window.screen_x, window.screen_y,
                                            triangle.x + window.camera_x,
                                            triangle.y + window.camera_y,
                                            triangle.z + window.camera_z);

        window.window.line(flat_1.x, flat_1.y, flat_2.x, flat_2.y, triangle.color.orb_color());
        window.window.line(flat_3.x, flat_3.y, flat_2.x, flat_2.y, triangle.color.orb_color());
        window.window.line(flat_1.x, flat_1.y, flat_3.x, flat_3.y, triangle.color.orb_color());
    };

    vid::Shader::new(id, Box::new(wireframe_shader))
}

pub fn disco_wireframe(id: u16) -> vid::Shader {
    let noise_shader = |triangle: &vid::Triangle, window: &mut start::Window, wrapper: &vid::Shader| {
        let flat_1 = triangle.p1.clone().flat_point(window.screen_x, window.screen_y,
                                            triangle.x + window.camera_x,
                                            triangle.y + window.camera_y,
                                            triangle.z + window.camera_z);
        let flat_2 = triangle.p2.clone().flat_point(window.screen_x, window.screen_y,
                                            triangle.x + window.camera_x,
                                            triangle.y + window.camera_y,
                                            triangle.z + window.camera_z);
        let flat_3 = triangle.p3.clone().flat_point(window.screen_x, window.screen_y,
                                            triangle.x + window.camera_x,
                                            triangle.y + window.camera_y,
                                            triangle.z + window.camera_z);

        window.window.line(flat_1.x, flat_1.y, flat_2.x, flat_2.y, vid::Color::new(rand::random::<u8>(),
                                                                                rand::random::<u8>(),
                                                                                rand::random::<u8>()).orb_color());
        window.window.line(flat_3.x, flat_3.y, flat_2.x, flat_2.y, vid::Color::new(rand::random::<u8>(),
                                                                                rand::random::<u8>(),
                                                                                rand::random::<u8>()).orb_color());
        window.window.line(flat_1.x, flat_1.y, flat_3.x, flat_3.y, vid::Color::new(rand::random::<u8>(),
                                                                                rand::random::<u8>(),
                                                                                rand::random::<u8>()).orb_color());
    };

    vid::Shader::new(id, Box::new(noise_shader))
}

pub fn filled_triangle_color(id: u16) -> vid::Shader {
    let rasterize_shader = |triangle: &vid::Triangle, window: &mut start::Window, wrapper: &vid::Shader| {
        let p1 = triangle.p1.clone().flat_point(window.screen_x, window.screen_y,
                                                triangle.x + window.camera_x,
                                                triangle.y + window.camera_y,
                                                triangle.z + window.camera_z);

        let p2 = triangle.p2.clone().flat_point(window.screen_x, window.screen_y,
                                                triangle.x + window.camera_x,
                                                triangle.y + window.camera_y,
                                                triangle.z + window.camera_z);

        let p3 = triangle.p3.clone().flat_point(window.screen_x, window.screen_y,
                                                triangle.x + window.camera_x,
                                                triangle.y + window.camera_y,
                                                triangle.z + window.camera_z);

        struct FloatPoint {
            x: f32,
            y: f32
        }

        let points = [p1, p2, p3];

        let upmost = points.iter().max_by_key(|p| -p.y).unwrap().clone();
        let leftmost = points.iter().max_by_key(|p| -p.x).unwrap().clone();
        let rightmost = points.iter().max_by_key(|p| p.x).unwrap().clone();
        let lowmost = points.iter().max_by_key(|p| p.y).unwrap().clone();

        for px in leftmost.x..rightmost.x {
            for py in upmost.y..lowmost.y {
                let p1 = FloatPoint {x: p1.x as f32, y: p1.y as f32};
                let p2 = FloatPoint {x: p2.x as f32, y: p2.y as f32};
                let p3 = FloatPoint {x: p3.x as f32, y: p3.y as f32};

                let p = FloatPoint {x: px as f32, y: py as f32};

                let alpha = ((p2.y - p3.y)*(p.x - p3.x) + (p3.x - p2.x)*(p.y - p3.y)) / ((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
                let beta = ((p3.y - p1.y)*(p.x - p3.x) + (p1.x - p3.x)*(p.y - p3.y)) / ((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
                let gamma = 1.0 - alpha - beta;

                if alpha > 0.0 && beta > 0.0 && gamma > 0.0 {
                    window.window.pixel(px, py, triangle.color.orb_color());
                }
            }
        }
    };

    vid::Shader::new(id, Box::new(rasterize_shader))
}

pub fn filled_b_w_noise(id: u16) -> vid::Shader {
    let rasterize_shader = |triangle: &vid::Triangle, window: &mut start::Window, wrapper: &vid::Shader| {
        let p1 = triangle.p1.clone().flat_point(window.screen_x, window.screen_y,
                                                triangle.x + window.camera_x,
                                                triangle.y + window.camera_y,
                                                triangle.z + window.camera_z);

        let p2 = triangle.p2.clone().flat_point(window.screen_x, window.screen_y,
                                                triangle.x + window.camera_x,
                                                triangle.y + window.camera_y,
                                                triangle.z + window.camera_z);

        let p3 = triangle.p3.clone().flat_point(window.screen_x, window.screen_y,
                                                triangle.x + window.camera_x,
                                                triangle.y + window.camera_y,
                                                triangle.z + window.camera_z);

        struct FloatPoint {
            x: f32,
            y: f32
        }

        let points = [p1, p2, p3];

        let upmost = points.iter().max_by_key(|p| -p.y).unwrap().clone();
        let leftmost = points.iter().max_by_key(|p| -p.x).unwrap().clone();
        let rightmost = points.iter().max_by_key(|p| p.x).unwrap().clone();
        let lowmost = points.iter().max_by_key(|p| p.y).unwrap().clone();

        for px in leftmost.x..rightmost.x {
            for py in upmost.y..lowmost.y {
                let p1 = FloatPoint {x: p1.x as f32, y: p1.y as f32};
                let p2 = FloatPoint {x: p2.x as f32, y: p2.y as f32};
                let p3 = FloatPoint {x: p3.x as f32, y: p3.y as f32};

                let p = FloatPoint {x: px as f32, y: py as f32};

                let alpha = ((p2.y - p3.y)*(p.x - p3.x) + (p3.x - p2.x)*(p.y - p3.y)) / ((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
                let beta = ((p3.y - p1.y)*(p.x - p3.x) + (p1.x - p3.x)*(p.y - p3.y)) / ((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
                let gamma = 1.0 - alpha - beta;

                let random = rand::random::<u8>();

                if alpha > 0.0 && beta > 0.0 && gamma > 0.0 {
                    window.window.pixel(px, py, vid::Color::new(random, random, random).orb_color());
                }
            }
        }
    };

    vid::Shader::new(id, Box::new(rasterize_shader))
}

pub fn filled_texture_naive(id: u16, texture_path: &str) -> vid::Shader {
    let img = orbclient::BmpFile::from_path(texture_path);

    let rasterize_shader = |triangle: &vid::Triangle, window: &mut start::Window, wrapper: &vid::Shader| {
        use std::ops::Deref;

        let p1 = triangle.p1.clone().flat_point(window.screen_x, window.screen_y,
                                                triangle.x + window.camera_x,
                                                triangle.y + window.camera_y,
                                                triangle.z + window.camera_z);

        let p2 = triangle.p2.clone().flat_point(window.screen_x, window.screen_y,
                                                triangle.x + window.camera_x,
                                                triangle.y + window.camera_y,
                                                triangle.z + window.camera_z);

        let p3 = triangle.p3.clone().flat_point(window.screen_x, window.screen_y,
                                                triangle.x + window.camera_x,
                                                triangle.y + window.camera_y,
                                                triangle.z + window.camera_z);

        struct FloatPoint {
            x: f32,
            y: f32
        }

        let img_w = wrapper.image_data.width();
        let img_h = wrapper.image_data.height();

        let img_slice = wrapper.image_data.deref();

        let points = [p1, p2, p3];

        let upmost = points.iter().max_by_key(|p| -p.y).unwrap().clone();
        let leftmost = points.iter().max_by_key(|p| -p.x).unwrap().clone();
        let rightmost = points.iter().max_by_key(|p| p.x).unwrap().clone();
        let lowmost = points.iter().max_by_key(|p| p.y).unwrap().clone();

        for px in leftmost.x..rightmost.x {
            for py in upmost.y..lowmost.y {
                let p1 = FloatPoint {x: p1.x as f32, y: p1.y as f32};
                let p2 = FloatPoint {x: p2.x as f32, y: p2.y as f32};
                let p3 = FloatPoint {x: p3.x as f32, y: p3.y as f32};

                let p = FloatPoint {x: px as f32, y: py as f32};

                let alpha = ((p2.y - p3.y)*(p.x - p3.x) + (p3.x - p2.x)*(p.y - p3.y)) / ((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
                let beta = ((p3.y - p1.y)*(p.x - p3.x) + (p1.x - p3.x)*(p.y - p3.y)) / ((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
                let gamma = 1.0 - alpha - beta;

                let random = rand::random::<u8>();

                if alpha > 0.0 && beta > 0.0 && gamma > 0.0 {
                    window.window.pixel(px, py, img_slice[(px - leftmost.x + (py - upmost.y)*(img_w as i32)) as usize]);
                }
            }
        }
    };

    let mut shader = vid::Shader::new(id, Box::new(rasterize_shader));

    shader.image_data = img;

    shader
}

pub fn filled_triangle_gradient(id: u16) -> vid::Shader {
    let rasterize_shader = |triangle: &vid::Triangle, window: &mut start::Window, wrapper: &vid::Shader| {
        let p1 = triangle.p1.clone().flat_point(window.screen_x, window.screen_y,
                                                triangle.x + window.camera_x,
                                                triangle.y + window.camera_y,
                                                triangle.z + window.camera_z);

        let p2 = triangle.p2.clone().flat_point(window.screen_x, window.screen_y,
                                                triangle.x + window.camera_x,
                                                triangle.y + window.camera_y,
                                                triangle.z + window.camera_z);

        let p3 = triangle.p3.clone().flat_point(window.screen_x, window.screen_y,
                                                triangle.x + window.camera_x,
                                                triangle.y + window.camera_y,
                                                triangle.z + window.camera_z);

        struct FloatPoint {
            x: f32,
            y: f32
        }

        let points = [p1, p2, p3];

        let upmost = points.iter().max_by_key(|p| -p.y).unwrap().clone();
        let leftmost = points.iter().max_by_key(|p| -p.x).unwrap().clone();
        let rightmost = points.iter().max_by_key(|p| p.x).unwrap().clone();
        let lowmost = points.iter().max_by_key(|p| p.y).unwrap().clone();

        for px in leftmost.x..rightmost.x {
            for py in upmost.y..lowmost.y {
                let p1 = FloatPoint {x: p1.x as f32, y: p1.y as f32};
                let p2 = FloatPoint {x: p2.x as f32, y: p2.y as f32};
                let p3 = FloatPoint {x: p3.x as f32, y: p3.y as f32};

                let p = FloatPoint {x: px as f32, y: py as f32};

                let alpha = ((p2.y - p3.y)*(p.x - p3.x) + (p3.x - p2.x)*(p.y - p3.y)) / ((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
                let beta = ((p3.y - p1.y)*(p.x - p3.x) + (p1.x - p3.x)*(p.y - p3.y)) / ((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
                let gamma = 1.0 - alpha - beta;

                if alpha > 0.0 && beta > 0.0 && gamma > 0.0 {
                    let p1_dist = ((px as f32 - p1.x)*(px as f32 - p1.x) + (py as f32 - p1.y)*(py as f32 - p1.y)).sqrt();
                    let p2_dist = ((px as f32 - p2.x)*(px as f32 - p2.x) + (py as f32 - p2.y)*(py as f32 - p2.y)).sqrt();
                    let p3_dist = ((px as f32 - p3.x)*(px as f32 - p3.x) + (py as f32 - p3.y)*(py as f32 - p3.y)).sqrt();

                    window.window.pixel(px, py, vid::Color::new(p1_dist as u8, p2_dist as u8, p3_dist as u8).orb_color());
                }
            }
        }
    };

    vid::Shader::new(id, Box::new(rasterize_shader))
}
<|endoftext|>


<commit_before>// Copyright (C) 2020 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

use crate::{api, Error, Result};
use async_std::{fs, io};
use futures_util::future::BoxFuture;
use slog_scope::{debug, error};
use std::{
    convert::{TryFrom, TryInto},
    path::Path,
};
use surf::{
    http::headers,
    middleware::{self, Middleware},
    StatusCode,
};

struct API;

impl Middleware for API {
    fn handle<'a>(
        &'a self,
        mut req: middleware::Request,
        client: std::sync::Arc<dyn middleware::HttpClient>,
        next: middleware::Next<'a>,
    ) -> BoxFuture<'a, std::result::Result<middleware::Response, surf::Error>> {
        Box::pin(async move {
            req.insert_header(headers::USER_AGENT, "updatehub/next");
            req.insert_header(headers::CONTENT_TYPE, "application/json");
            req.insert_header("api-content-type", "application/vnd.updatehub-v1+json");
            Ok(next.run(req, client).await?)
        })
    }
}

pub struct Client<'a> {
    client: surf::Client,
    server: &'a str,
}

pub async fn get<W>(url: &str, handle: &mut W) -> Result<()>
where
    W: io::Write + Unpin,
{
    let req = surf::get(url);
    save_body_to(req, handle).await
}

async fn save_body_to<W>(req: surf::Request, handle: &mut W) -> Result<()>
where
    W: io::Write + Unpin,
{
    use async_std::prelude::StreamExt;
    use io::prelude::{ReadExt, WriteExt};
    use std::str::FromStr;

    let rep = req.await?;
    if !rep.status().is_success() {
        return Err(Error::InvalidStatusResponse(rep.status()));
    }

    let mut written: f32 = 0.;
    let mut threshold = 10;
    let length = match rep.header(headers::CONTENT_LENGTH) {
        Some(v) => usize::from_str(v.as_str())?,
        None => 0,
    };

    let mut stream = rep.bytes();
    while let Some(byte) = stream.next().await {
        let byte = byte?;
        handle.write_all(&[byte]).await?;
        if length > 0 {
            written += 1.0 / (length / 100) as f32;
            if written as usize >= threshold {
                threshold += 20;
                debug!("{}% of the file has been downloaded", std::cmp::max(written as usize, 100));
            }
        }
    }
    debug!("100% of the file has been downloaded");

    Ok(())
}

impl<'a> Client<'a> {
    pub fn new(server: &'a str) -> Self {
        Self { server, client: surf::Client::new() }
    }

    pub async fn probe(
        &self,
        num_retries: u64,
        firmware: api::FirmwareMetadata<'_>,
    ) -> Result<api::ProbeResponse> {
        let mut response = self
            .client
            .post(&format!("{}/upgrades", &self.server))
            .middleware(API)
            .set_header("api-retries", num_retries.to_string())
            .body_json(&firmware)?
            .await?;

        match response.status() {
            StatusCode::NotFound => Ok(api::ProbeResponse::NoUpdate),
            StatusCode::Ok => {
                match response
                    .header("add-extra-poll")
                    .map(|extra_poll| extra_poll.as_str())
                    .and_then(|extra_poll| extra_poll.parse().ok())
                {
                    Some(extra_poll) => Ok(api::ProbeResponse::ExtraPoll(extra_poll)),
                    None => {
                        let signature =
                            response.header("UH-Signature").map(TryInto::try_into).transpose()?;
                        Ok(api::ProbeResponse::Update(
                            api::UpdatePackage::parse(&response.body_bytes().await?)?,
                            signature,
                        ))
                    }
                }
            }
            s => Err(Error::InvalidStatusResponse(s)),
        }
    }

    pub async fn download_object(
        &self,
        product_uid: &str,
        package_uid: &str,
        download_dir: &Path,
        object: &str,
    ) -> Result<()> {
        // FIXME: Discuss the need of packages inside the route
        let mut request = self
            .client
            .get(&format!(
                "{}/products/{}/packages/{}/objects/{}",
                &self.server, product_uid, package_uid, object
            ))
            .middleware(API);

        if !download_dir.exists() {
            fs::create_dir_all(download_dir).await.map_err(|e| {
                error!("fail to create {:?} directory, error: {}", download_dir, e);
                e
            })?;
        }

        let file = download_dir.join(object);
        if file.exists() {
            request = request.set_header(
                "RANGE",
                format!("bytes={}-", file.metadata()?.len().saturating_sub(1)),
            );
        }

        let mut file = fs::OpenOptions::new().create(true).append(true).open(&file).await?;

        save_body_to(request, &mut file).await
    }

    pub async fn report(
        &self,
        state: &str,
        firmware: api::FirmwareMetadata<'_>,
        package_uid: &str,
        previous_state: Option<&str>,
        error_message: Option<String>,
        current_log: Option<String>,
    ) -> Result<()> {
        #[derive(serde::Serialize)]
        #[serde(rename_all = "kebab-case")]
        struct Payload<'a> {
            #[serde(rename = "status")]
            state: &'a str,
            #[serde(flatten)]
            firmware: api::FirmwareMetadata<'a>,
            package_uid: &'a str,
            #[serde(skip_serializing_if = "Option::is_none")]
            previous_state: Option<&'a str>,
            #[serde(skip_serializing_if = "Option::is_none")]
            error_message: Option<String>,
            #[serde(skip_serializing_if = "Option::is_none")]
            current_log: Option<String>,
        }

        let payload =
            Payload { state, firmware, package_uid, previous_state, error_message, current_log };

        self.client
            .post(&format!("{}/report", &self.server))
            .middleware(API)
            .body_json(&payload)?
            .await?;
        Ok(())
    }
}

impl TryFrom<&headers::HeaderValues> for api::Signature {
    type Error = Error;

    fn try_from(value: &headers::HeaderValues) -> Result<Self> {
        Ok(Self::from_base64_str(value.as_str())?)
    }
}
<commit_msg>updatehub-cloud-sdk: workaround for empty base64 decode bug<commit_after>// Copyright (C) 2020 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

use crate::{api, Error, Result};
use async_std::{fs, io};
use futures_util::future::BoxFuture;
use slog_scope::{debug, error};
use std::{
    convert::{TryFrom, TryInto},
    path::Path,
};
use surf::{
    http::headers,
    middleware::{self, Middleware},
    StatusCode,
};

struct API;

impl Middleware for API {
    fn handle<'a>(
        &'a self,
        mut req: middleware::Request,
        client: std::sync::Arc<dyn middleware::HttpClient>,
        next: middleware::Next<'a>,
    ) -> BoxFuture<'a, std::result::Result<middleware::Response, surf::Error>> {
        Box::pin(async move {
            req.insert_header(headers::USER_AGENT, "updatehub/next");
            req.insert_header(headers::CONTENT_TYPE, "application/json");
            req.insert_header("api-content-type", "application/vnd.updatehub-v1+json");
            Ok(next.run(req, client).await?)
        })
    }
}

pub struct Client<'a> {
    client: surf::Client,
    server: &'a str,
}

pub async fn get<W>(url: &str, handle: &mut W) -> Result<()>
where
    W: io::Write + Unpin,
{
    let req = surf::get(url);
    save_body_to(req, handle).await
}

async fn save_body_to<W>(req: surf::Request, handle: &mut W) -> Result<()>
where
    W: io::Write + Unpin,
{
    use async_std::prelude::StreamExt;
    use io::prelude::{ReadExt, WriteExt};
    use std::str::FromStr;

    let rep = req.await?;
    if !rep.status().is_success() {
        return Err(Error::InvalidStatusResponse(rep.status()));
    }

    let mut written: f32 = 0.;
    let mut threshold = 10;
    let length = match rep.header(headers::CONTENT_LENGTH) {
        Some(v) => usize::from_str(v.as_str())?,
        None => 0,
    };

    let mut stream = rep.bytes();
    while let Some(byte) = stream.next().await {
        let byte = byte?;
        handle.write_all(&[byte]).await?;
        if length > 0 {
            written += 1.0 / (length / 100) as f32;
            if written as usize >= threshold {
                threshold += 20;
                debug!("{}% of the file has been downloaded", std::cmp::max(written as usize, 100));
            }
        }
    }
    debug!("100% of the file has been downloaded");

    Ok(())
}

impl<'a> Client<'a> {
    pub fn new(server: &'a str) -> Self {
        Self { server, client: surf::Client::new() }
    }

    pub async fn probe(
        &self,
        num_retries: u64,
        firmware: api::FirmwareMetadata<'_>,
    ) -> Result<api::ProbeResponse> {
        let mut response = self
            .client
            .post(&format!("{}/upgrades", &self.server))
            .middleware(API)
            .set_header("api-retries", num_retries.to_string())
            .body_json(&firmware)?
            .await?;

        match response.status() {
            StatusCode::NotFound => Ok(api::ProbeResponse::NoUpdate),
            StatusCode::Ok => {
                match response
                    .header("add-extra-poll")
                    .map(|extra_poll| extra_poll.as_str())
                    .and_then(|extra_poll| extra_poll.parse().ok())
                {
                    Some(extra_poll) => Ok(api::ProbeResponse::ExtraPoll(extra_poll)),
                    None => {
                        let signature =
                            response.header("UH-Signature").map(TryInto::try_into).transpose()?;
                        Ok(api::ProbeResponse::Update(
                            api::UpdatePackage::parse(&response.body_bytes().await?)?,
                            signature,
                        ))
                    }
                }
            }
            s => Err(Error::InvalidStatusResponse(s)),
        }
    }

    pub async fn download_object(
        &self,
        product_uid: &str,
        package_uid: &str,
        download_dir: &Path,
        object: &str,
    ) -> Result<()> {
        // FIXME: Discuss the need of packages inside the route
        let mut request = self
            .client
            .get(&format!(
                "{}/products/{}/packages/{}/objects/{}",
                &self.server, product_uid, package_uid, object
            ))
            .middleware(API);

        if !download_dir.exists() {
            fs::create_dir_all(download_dir).await.map_err(|e| {
                error!("fail to create {:?} directory, error: {}", download_dir, e);
                e
            })?;
        }

        let file = download_dir.join(object);
        if file.exists() {
            request = request.set_header(
                "RANGE",
                format!("bytes={}-", file.metadata()?.len().saturating_sub(1)),
            );
        }

        let mut file = fs::OpenOptions::new().create(true).append(true).open(&file).await?;

        save_body_to(request, &mut file).await
    }

    pub async fn report(
        &self,
        state: &str,
        firmware: api::FirmwareMetadata<'_>,
        package_uid: &str,
        previous_state: Option<&str>,
        error_message: Option<String>,
        current_log: Option<String>,
    ) -> Result<()> {
        #[derive(serde::Serialize)]
        #[serde(rename_all = "kebab-case")]
        struct Payload<'a> {
            #[serde(rename = "status")]
            state: &'a str,
            #[serde(flatten)]
            firmware: api::FirmwareMetadata<'a>,
            package_uid: &'a str,
            #[serde(skip_serializing_if = "Option::is_none")]
            previous_state: Option<&'a str>,
            #[serde(skip_serializing_if = "Option::is_none")]
            error_message: Option<String>,
            #[serde(skip_serializing_if = "Option::is_none")]
            current_log: Option<String>,
        }

        let payload =
            Payload { state, firmware, package_uid, previous_state, error_message, current_log };

        self.client
            .post(&format!("{}/report", &self.server))
            .middleware(API)
            .body_json(&payload)?
            .await?;
        Ok(())
    }
}

impl TryFrom<&headers::HeaderValues> for api::Signature {
    type Error = Error;

    fn try_from(value: &headers::HeaderValues) -> Result<Self> {
        let value = value.as_str();

        // Workarround for https://github.com/sfackler/rust-openssl/issues/1325
        if value.is_empty() {
            return Ok(Self::from_base64_str("")?);
        }

        Ok(Self::from_base64_str(value)?)
    }
}
<|endoftext|>


<commit_before><commit_msg>Remove request body from get handlers.<commit_after><|endoftext|>


<commit_before><commit_msg>Add an empty test file which just calls `speculate!`.<commit_after>#![feature(phase)]

#[phase(plugin)]
extern crate speculate;

speculate! {
}
<|endoftext|>


<commit_before><commit_msg>Add rust code for variable-length-quantity case<commit_after>/// Convert a list of numbers to a stream of bytes encoded with variable length encoding.
pub fn to_bytes(values: &[u32]) -> Vec<u8> {
    let mut result:Vec<u8> = Vec::with_capacity(values.len() * 5);

    for w in values {
        let mut zeroable = false;

        let mut b = *w >> 28 & 0x0000_007F;
        if b != 0 {
            zeroable = true;
            result.push(0x80u8 + b as u8);
        }

        b = *w >> 21 & 0x0000_007F;
        if b != 0 || zeroable {
            zeroable = true;
            result.push(0x80u8 + b as u8);
        }

        b = *w >> 14 & 0x0000_007F;
        if b != 0 || zeroable {
            zeroable = true;
            result.push(0x80u8 + b as u8);
        }

        b = *w >> 7 & 0x0000_007F;
        if b != 0 || zeroable {
            result.push(0x80u8 + b as u8);
        }

        b = *w & 0x0000_007F;
        result.push(b as u8);
    }

    result
}

/// Given a stream of bytes, extract all numbers which are encoded in there.
pub fn from_bytes(bytes: &[u8]) -> Result<Vec<u32>, &'static str> {
    let mut length = 0;
    let mut value: u32 = 0;
    let mut result:Vec<u32> = Vec::new();

    for b in bytes {
        length += 1;

        if length > 5 {
            return Err("Invalid VLQ code");
        }

        if let Some(v) = value.checked_mul(128) {
            value = v;
        } else {
            return Err("Overflowed VLQ code");
        }

        if *b & 0x80 != 0 {
            value += (*b - 0x80u8) as u32;
        } else {
            value += *b as u32;

            result.push(value);

            value = 0;
            length = 0;
        }
    }

    if length != 0 {
        return Err("Invalid VLQ code");
    }

    Ok(result)
}
<|endoftext|>


<commit_before><commit_msg>Also use sbsps from other scenario tags<commit_after><|endoftext|>