<commit_before>//============================================================================
//
// A simple Mandelbrot image generator in Rust
//
// Copyright (c) 2014 Gavin Baker <gavinb@antonym.org>
// Published under the MIT license
//
// Packages required:
//
// - OpenGLES
// - GLFW
// - cgmath
//
//============================================================================

#[license = "BSD"];

#[allow(deprecated_owned_vector)];
#[allow(dead_code)];

extern crate native;
extern crate num;

extern crate opengles;
extern crate glfw;
extern crate cgmath;

use opengles::gl2;

use cgmath::vector::Vec3;
use cgmath::aabb::Aabb3;

use std::comm::{Sender, Receiver, channel};
use std::vec_ng::Vec;

use num::complex::{Cmplx, Complex64};

use std::num::{sin};

type Vec3f = Vec3<f32>;
type AABB3f = Aabb3<f32>;

//----------------------------------------------------------------------------

static vertex_shader_source: &'static str = "

#version 150

in vec2 position;
in vec3 color;

out vec3 Color;

void main()
{
    Color = color;
    gl_Position = vec4(position, 0.0, 1.0);
}
";

static fragment_shader_source: &'static str = "

#version 150

in vec3 Color;
out vec4 outColor;

void main()
{
    outColor = vec4(Color, 1.0);
}
";

//----------------------------------------------------------------------------

struct ErrorContext;
impl glfw::ErrorCallback for ErrorContext {
    fn call(&self, _: glfw::Error, description: ~str) {
        println!("GLFW Error: {:s}", description);
    }
}

//----------------------------------------------------------------------------

struct WindowController<'a> {
    window: &'a glfw::Window,
    vertices: ~[f32],
    vao: ~[gl2::GLuint],
    vbo: ~[gl2::GLuint],
    vertex_shader: gl2::GLuint,
    fragment_shader: gl2::GLuint,
    shader_program: gl2::GLuint,
    uni_color: gl2::GLint,
    buffer_width: uint,
    buffer_height: uint,
}

impl<'a> WindowController<'a> {
    fn new(window: &'a glfw::Window) -> WindowController<'a> {
        let mut wc = WindowController { window: window,
                                        vao: ~[0],
                                        vbo: ~[0],
                                        vertices: ~[],
                                        vertex_shader: 0,
                                        fragment_shader: 0,
                                        shader_program: 0,
                                        uni_color: 0,
                                        buffer_width: 0,
                                        buffer_height: 0,
        };

        let (w, h) =  wc.window.get_framebuffer_size();
        wc.buffer_width = w as uint;
        wc.buffer_height = h as uint;

        gl2::viewport(0, 0, wc.buffer_width as i32, wc.buffer_height as i32);

        println!("Viewport: {} x {}", wc.buffer_width, wc.buffer_height);

        wc.vertices = ~[
            0.0,  0.5, 1.0, 0.0, 0.0,
            0.5, -0.5, 0.0, 1.0, 0.0,
            -0.5, -0.5, 0.0, 0.0, 1.0,
            ];

        // VAO

        wc.vao = gl2::gen_vertex_arrays(1);
        gl2::bind_vertex_array(wc.vao[0]);

        // VBO

        wc.vbo = gl2::gen_buffers(1);
        gl2::bind_buffer(gl2::ARRAY_BUFFER, wc.vbo[0]);
        gl2::buffer_data(gl2::ARRAY_BUFFER, wc.vertices, gl2::STATIC_DRAW);

        // Vertex Shader

        wc.vertex_shader = gl2::create_shader(gl2::VERTEX_SHADER);

        if wc.vertex_shader == 0 {
            fail!("Create v.shader failed");
        }

        gl2::shader_source(wc.vertex_shader, [vertex_shader_source.to_owned().as_bytes()]);

        let err = gl2::get_error();
        if err != 0 {
            fail!("glShaderSource.v err 0x{:x}", err);
        }

        gl2::compile_shader(wc.vertex_shader);

        let err = gl2::get_error();
        if err != 0 {
            fail!("glCompileShader.f err 0x{:x}", err);
        }

        let status = gl2::get_shader_iv(wc.vertex_shader, gl2::COMPILE_STATUS);

        if status != gl2::TRUE as i32 {
            let log = gl2::get_shader_info_log(wc.vertex_shader);
            fail!("glCompileShader.v err 0x{:x}: {}", status, log);
        }

        // Fragment Shader

        wc.fragment_shader = gl2::create_shader(gl2::FRAGMENT_SHADER);

        if wc.vertex_shader == 0 {
            fail!("Create f.shader failed");
        }

        gl2::shader_source(wc.fragment_shader, [fragment_shader_source.to_owned().as_bytes()]);

        let err = gl2::get_error();
        if err != 0 {
            fail!("glShaderSource.f -> 0x{:x}", err);
        }

        gl2::compile_shader(wc.fragment_shader);

        let err = gl2::get_error();
        if err != 0 {
            fail!("glCompileShader.v err 0x{:x}", err);
        }

        let status = gl2::get_shader_iv(wc.fragment_shader, gl2::COMPILE_STATUS);

        if status != gl2::TRUE as i32 {
            let log = gl2::get_shader_info_log(wc.fragment_shader);
            fail!("glCompileShader.f err 0x{:x}: {}", status, log);
        }

        // Link

        wc.shader_program = gl2::create_program();

        if wc.shader_program == 0 {
            fail!("glCreateProgram failed");
        }

        gl2::attach_shader(wc.shader_program, wc.vertex_shader);
        gl2::attach_shader(wc.shader_program, wc.fragment_shader);

        let err = gl2::get_error();
        if err != 0 {
            fail!("glAttachShader err 0x{:x}", err);
        }

        gl2::link_program(wc.shader_program);

        let err = gl2::get_error();
        if err != 0 {
            fail!("glLinkProgram err 0x{:x}", err);
        }

        let status = gl2::get_program_iv(wc.shader_program, gl2::LINK_STATUS);

        if status != gl2::TRUE as i32 {
            let log = gl2::get_shader_info_log(wc.shader_program);
            fail!("glLinkProgram err {}: {}", status, log);
        }

        gl2::use_program(wc.shader_program);

        let err = gl2::get_error();
        if err != 0 {
            let log = gl2::get_program_info_log(wc.shader_program);
            fail!("glUseProgram error: {}", log);
        }

        // Attributes

        let pos_attrib = gl2::get_attrib_location(wc.shader_program, "position");
        gl2::enable_vertex_attrib_array(pos_attrib as gl2::GLuint);
        gl2::vertex_attrib_pointer_f32(pos_attrib as gl2::GLuint, 2, false, 5*4, 0);

        let col_attrib = gl2::get_attrib_location(wc.shader_program, "color");
        gl2::enable_vertex_attrib_array(col_attrib as gl2::GLuint);
        gl2::vertex_attrib_pointer_f32(col_attrib as gl2::GLuint, 3, false, 5*4, 2*4);

        // Uniforms

        wc.uni_color = gl2::get_uniform_location(wc.shader_program, "triangleColor");

        let err = gl2::get_error();
        if err != 0 {
            fail!("attrib err = {:x}", err);
        }

        wc
    }

    // Rescale pixel coord (x,y) into cspace
    fn scale_coords(&self, x: uint, y: uint) -> (f32, f32) {
        let x0 = -2.5f32;
        let x1 =  1.0f32;
        let y0 = -1.0f32;
        let y1 =  1.0f32;

        let xx = (x as f32) / (self.buffer_width  as f32) * (x1-x0) + x0;
        let yy = (y as f32) / (self.buffer_height as f32) * (y1-y0) + y0;

        (xx, yy)
    }

    fn draw(&self) {

        // Clear

        gl2::clear_color(0.4, 0.4, 0.4, 1.0);
        gl2::clear(gl2::COLOR_BUFFER_BIT);

        // Animate

        let time = glfw::get_time();
        gl2::uniform_3f(self.uni_color, (sin(time * 4.0f32 as f64) as f32 + 1.0f32) / 2.0f32, 0.0f32, 0.0f32);

        // Draw!

        gl2::draw_arrays(gl2::TRIANGLES, 0, 3);

        let err = gl2::get_error();
        if err != 0 {
            println!("draw err = 0x{:x}", err);
        }

        self.window.swap_buffers();
    }

    fn uninit(&mut self) {

        // Cleanup

        gl2::delete_program(self.shader_program);
        gl2::delete_shader(self.fragment_shader);
        gl2::delete_shader(self.vertex_shader);

        gl2::delete_buffers(self.vbo);

        // @todo Missing from bindings
        //gl2::delete_vertex_arrays(vao);
    }

    fn handle_window_event(&self, window: &glfw::Window, (time, event): (f64, glfw::WindowEvent)) {
        match event {

            glfw::CloseEvent => println!("Time: {}, Window close requested.", time),

            glfw::KeyEvent(key, scancode, action, mods) => {
                println!("Time: {}, Key: {}, ScanCode: {}, Action: {}, Modifiers: [{}]", time, key, scancode, action, mods);
                match (key, action) {
                    (glfw::KeyEscape, glfw::Press) => window.set_should_close(true),
                    (glfw::KeyR, glfw::Press) => {
                        // Resize should cause the window to "refresh"
                        let (window_width, window_height) = window.get_size();
                        window.set_size(window_width + 1, window_height);
                        window.set_size(window_width, window_height);
                    }
                    _ => {}
                }
            }
            _ => {}
        }
    }
}

//----------------------------------------------------------------------------

struct MandelEngine {
    buffer_width: uint,
    buffer_height: uint,
    buffer: Vec<u32>,// RGBA
}

impl MandelEngine {

    fn new(w: uint, h: uint) -> MandelEngine {
        MandelEngine {
            buffer_width: w,
            buffer_height: h,
            buffer: Vec::with_capacity(w*h), // Monochrome, 8-bit
        }
    }

    // Rescale pixel coord (x,y) into cspace
    fn scale_coords(&self, x: uint, y: uint) -> (f32, f32) {
        let x0 = -2.5f32;
        let x1 =  1.0f32;
        let y0 = -1.0f32;
        let y1 =  1.0f32;

        let xx = (x as f32) / (self.buffer_width  as f32) * (x1-x0) + x0;
        let yy = (y as f32) / (self.buffer_height as f32) * (y1-y0) + y0;

        (xx, yy)
    }

    // Evalute entire region
    fn process(&mut self) {

        let max_iteration = 1000;

        println!("+++ process in {} bytes", self.buffer.capacity());

        // Process each pixel
        for py in range(0, self.buffer_height) {
            for px in range(0, self.buffer_width) {

                // Project pixels into Mandelbrot domain
                let (x0, y0) = self.scale_coords(px, py);

                println!("({},{}) -> ({}, {})", px, py, x0, y0);

                let mut x = 0.0f32;
                let mut y = 0.0f32;
                let mut iteration = 0;

                // Iterate!
                while (x*x + y*y < 2.0*2.0) && (iteration < max_iteration) {
                    let xtemp = x*x - y*y + x0;
                    y = 2.0*x*y + y0;
                    x = xtemp;

                    iteration += 1;
                }

                // Colour and plot
                //color = palette[iteration];
                let color = iteration;
                let ofs = px+self.buffer_width*py;
//                *self.buffer.get_mut(ofs) = color;
            }
        }

        println!("--- process");
    }

    // Evaluate a single point
    fn mandel(&self, z: Complex64) -> uint {
        let maxiter: uint = 80;
        let mut c: Complex64 = z;
        for n in range(0, maxiter) {
            if c.norm() > 2.0 {
                return n;
            }
            c = c*c+z;
        }
        return maxiter;
    }
}

//----------------------------------------------------------------------------

fn start_engine(tx: &Sender<uint>) {
    let mut engine = MandelEngine::new(1920, 960);
    engine.process();
//    tx.send(42);
}

//----------------------------------------------------------------------------

#[start]
fn start(argc: int, argv: **u8) -> int {
    native::start(argc, argv, main)
}

fn main() {

    println!("GLFW version: {:s}", glfw::get_version_string());

    glfw::start(proc() {

        glfw::window_hint::context_version_major(3);
        glfw::window_hint::context_version_minor(2);
        glfw::window_hint::opengl_forward_compat(true);
        glfw::window_hint::opengl_profile(glfw::OpenGlCoreProfile);
        glfw::window_hint::resizable(false);

        let window = glfw::Window::create(640, 480,
                                          "MandelRust",
                                          glfw::Windowed)
            .expect("Failed to create GLFW window.");

        window.make_context_current();

        let win_ctrl = ~WindowController::new(&window);

        let (tx, rx): (Sender<uint>, Receiver<uint>) = channel();

        native::task::spawn( proc() {
            start_engine(&tx);
        });

//         let indata = rx.recv();
//         println!("indata {}", indata);

        while !window.should_close() {
            glfw::poll_events();
            for event in window.flush_events() {
                win_ctrl.handle_window_event(&window, event);
            }
            win_ctrl.draw();
        }
    });
}
<commit_msg>Got very basic render of Mandelbrot set working<commit_after>//============================================================================
//
// A simple Mandelbrot image generator in Rust
//
// Copyright (c) 2014 Gavin Baker <gavinb@antonym.org>
// Published under the MIT license
//
// Packages required:
//
// - OpenGLES
// - GLFW
// - cgmath
//
//============================================================================

#[license = "MIT"];

#[allow(deprecated_owned_vector)];
#[allow(dead_code)];

extern crate native;
extern crate num;

extern crate opengles;
extern crate glfw;
extern crate cgmath;

use opengles::gl2;

use cgmath::vector::Vec3;
use cgmath::aabb::Aabb3;

use std::comm::{Sender, Receiver, channel};
use std::vec_ng::Vec;
use std::io::File;
use std::path::Path;

use num::complex::{Cmplx, Complex64};

use std::num::{sin};

type Vec3f = Vec3<f32>;
type AABB3f = Aabb3<f32>;

//----------------------------------------------------------------------------

static vertex_shader_source: &'static str = "

#version 150

in vec2 position;
in vec3 color;

out vec3 Color;

void main()
{
    Color = color;
    gl_Position = vec4(position, 0.0, 1.0);
}
";

static fragment_shader_source: &'static str = "

#version 150

in vec3 Color;
out vec4 outColor;

void main()
{
    outColor = vec4(Color, 1.0);
}
";

//----------------------------------------------------------------------------

struct ErrorContext;
impl glfw::ErrorCallback for ErrorContext {
    fn call(&self, _: glfw::Error, description: ~str) {
        println!("GLFW Error: {:s}", description);
    }
}

//----------------------------------------------------------------------------

struct WindowController<'a> {
    window: &'a glfw::Window,
    vertices: ~[f32],
    vao: ~[gl2::GLuint],
    vbo: ~[gl2::GLuint],
    vertex_shader: gl2::GLuint,
    fragment_shader: gl2::GLuint,
    shader_program: gl2::GLuint,
    uni_color: gl2::GLint,
    buffer_width: uint,
    buffer_height: uint,
}

impl<'a> WindowController<'a> {
    fn new(window: &'a glfw::Window) -> WindowController<'a> {
        let mut wc = WindowController { window: window,
                                        vao: ~[0],
                                        vbo: ~[0],
                                        vertices: ~[],
                                        vertex_shader: 0,
                                        fragment_shader: 0,
                                        shader_program: 0,
                                        uni_color: 0,
                                        buffer_width: 0,
                                        buffer_height: 0,
        };

        let (w, h) =  wc.window.get_framebuffer_size();
        wc.buffer_width = w as uint;
        wc.buffer_height = h as uint;

        gl2::viewport(0, 0, wc.buffer_width as i32, wc.buffer_height as i32);

        println!("Viewport: {} x {}", wc.buffer_width, wc.buffer_height);

        wc.vertices = ~[
            0.0,  0.5, 1.0, 0.0, 0.0,
            0.5, -0.5, 0.0, 1.0, 0.0,
            -0.5, -0.5, 0.0, 0.0, 1.0,
            ];

        // VAO

        wc.vao = gl2::gen_vertex_arrays(1);
        gl2::bind_vertex_array(wc.vao[0]);

        // VBO

        wc.vbo = gl2::gen_buffers(1);
        gl2::bind_buffer(gl2::ARRAY_BUFFER, wc.vbo[0]);
        gl2::buffer_data(gl2::ARRAY_BUFFER, wc.vertices, gl2::STATIC_DRAW);

        // Vertex Shader

        wc.vertex_shader = gl2::create_shader(gl2::VERTEX_SHADER);

        if wc.vertex_shader == 0 {
            fail!("Create v.shader failed");
        }

        gl2::shader_source(wc.vertex_shader, [vertex_shader_source.to_owned().as_bytes()]);

        let err = gl2::get_error();
        if err != 0 {
            fail!("glShaderSource.v err 0x{:x}", err);
        }

        gl2::compile_shader(wc.vertex_shader);

        let err = gl2::get_error();
        if err != 0 {
            fail!("glCompileShader.f err 0x{:x}", err);
        }

        let status = gl2::get_shader_iv(wc.vertex_shader, gl2::COMPILE_STATUS);

        if status != gl2::TRUE as i32 {
            let log = gl2::get_shader_info_log(wc.vertex_shader);
            fail!("glCompileShader.v err 0x{:x}: {}", status, log);
        }

        // Fragment Shader

        wc.fragment_shader = gl2::create_shader(gl2::FRAGMENT_SHADER);

        if wc.vertex_shader == 0 {
            fail!("Create f.shader failed");
        }

        gl2::shader_source(wc.fragment_shader, [fragment_shader_source.to_owned().as_bytes()]);

        let err = gl2::get_error();
        if err != 0 {
            fail!("glShaderSource.f -> 0x{:x}", err);
        }

        gl2::compile_shader(wc.fragment_shader);

        let err = gl2::get_error();
        if err != 0 {
            fail!("glCompileShader.v err 0x{:x}", err);
        }

        let status = gl2::get_shader_iv(wc.fragment_shader, gl2::COMPILE_STATUS);

        if status != gl2::TRUE as i32 {
            let log = gl2::get_shader_info_log(wc.fragment_shader);
            fail!("glCompileShader.f err 0x{:x}: {}", status, log);
        }

        // Link

        wc.shader_program = gl2::create_program();

        if wc.shader_program == 0 {
            fail!("glCreateProgram failed");
        }

        gl2::attach_shader(wc.shader_program, wc.vertex_shader);
        gl2::attach_shader(wc.shader_program, wc.fragment_shader);

        let err = gl2::get_error();
        if err != 0 {
            fail!("glAttachShader err 0x{:x}", err);
        }

        gl2::link_program(wc.shader_program);

        let err = gl2::get_error();
        if err != 0 {
            fail!("glLinkProgram err 0x{:x}", err);
        }

        let status = gl2::get_program_iv(wc.shader_program, gl2::LINK_STATUS);

        if status != gl2::TRUE as i32 {
            let log = gl2::get_shader_info_log(wc.shader_program);
            fail!("glLinkProgram err {}: {}", status, log);
        }

        gl2::use_program(wc.shader_program);

        let err = gl2::get_error();
        if err != 0 {
            let log = gl2::get_program_info_log(wc.shader_program);
            fail!("glUseProgram error: {}", log);
        }

        // Attributes

        let pos_attrib = gl2::get_attrib_location(wc.shader_program, "position");
        gl2::enable_vertex_attrib_array(pos_attrib as gl2::GLuint);
        gl2::vertex_attrib_pointer_f32(pos_attrib as gl2::GLuint, 2, false, 5*4, 0);

        let col_attrib = gl2::get_attrib_location(wc.shader_program, "color");
        gl2::enable_vertex_attrib_array(col_attrib as gl2::GLuint);
        gl2::vertex_attrib_pointer_f32(col_attrib as gl2::GLuint, 3, false, 5*4, 2*4);

        // Uniforms

        wc.uni_color = gl2::get_uniform_location(wc.shader_program, "triangleColor");

        let err = gl2::get_error();
        if err != 0 {
            fail!("attrib err = {:x}", err);
        }

        wc
    }

    // Rescale pixel coord (x,y) into cspace
    fn scale_coords(&self, x: uint, y: uint) -> (f32, f32) {
        let x0 = -2.5f32;
        let x1 =  1.0f32;
        let y0 = -1.0f32;
        let y1 =  1.0f32;

        let xx = (x as f32) / (self.buffer_width  as f32) * (x1-x0) + x0;
        let yy = (y as f32) / (self.buffer_height as f32) * (y1-y0) + y0;

        (xx, yy)
    }

    fn draw(&self) {

        // Clear

        gl2::clear_color(0.4, 0.4, 0.4, 1.0);
        gl2::clear(gl2::COLOR_BUFFER_BIT);

        // Animate

        let time = glfw::get_time();
        gl2::uniform_3f(self.uni_color, (sin(time * 4.0f32 as f64) as f32 + 1.0f32) / 2.0f32, 0.0f32, 0.0f32);

        // Draw!

        gl2::draw_arrays(gl2::TRIANGLES, 0, 3);

        let err = gl2::get_error();
        if err != 0 {
            println!("draw err = 0x{:x}", err);
        }

        self.window.swap_buffers();
    }

    fn uninit(&mut self) {

        // Cleanup

        gl2::delete_program(self.shader_program);
        gl2::delete_shader(self.fragment_shader);
        gl2::delete_shader(self.vertex_shader);

        gl2::delete_buffers(self.vbo);

        // @todo Missing from bindings
        //gl2::delete_vertex_arrays(vao);
    }

    fn handle_window_event(&self, window: &glfw::Window, (time, event): (f64, glfw::WindowEvent)) {
        match event {

            glfw::CloseEvent => println!("Time: {}, Window close requested.", time),

            glfw::KeyEvent(key, scancode, action, mods) => {
                println!("Time: {}, Key: {}, ScanCode: {}, Action: {}, Modifiers: [{}]", time, key, scancode, action, mods);
                match (key, action) {
                    (glfw::KeyEscape, glfw::Press) => window.set_should_close(true),
                    (glfw::KeyR, glfw::Press) => {
                        // Resize should cause the window to "refresh"
                        let (window_width, window_height) = window.get_size();
                        window.set_size(window_width + 1, window_height);
                        window.set_size(window_width, window_height);
                    }
                    _ => {}
                }
            }
            _ => {}
        }
    }
}

//----------------------------------------------------------------------------

struct MandelEngine {
    buffer_width: uint,
    buffer_height: uint,
    buffer: Vec<u8>,// RGBA
}

impl MandelEngine {

    fn new(w: uint, h: uint) -> MandelEngine {
        MandelEngine {
            buffer_width: w,
            buffer_height: h,
            buffer: Vec::with_capacity(w*h), // Monochrome, 8-bit
        }
    }

    // Rescale pixel coord (x,y) into cspace
    fn scale_coords(&self, x: uint, y: uint) -> (f32, f32) {
        let x0 = -2.5f32;
        let x1 =  1.0f32;
        let y0 = -1.0f32;
        let y1 =  1.0f32;

        let xx = (x as f32) / (self.buffer_width  as f32) * (x1-x0) + x0;
        let yy = (y as f32) / (self.buffer_height as f32) * (y1-y0) + y0;

        (xx, yy)
    }

    // Evalute entire region
    fn process(&mut self) {

        let max_iteration = 255;

        println!("+++ process in {} bytes", self.buffer.capacity());

        // Process each pixel
        for py in range(0, self.buffer_height) {
            for px in range(0, self.buffer_width) {

                // Project pixels into Mandelbrot domain
                let (x0, y0) = self.scale_coords(px, py);

                //println!("({},{}) -> ({}, {})", px, py, x0, y0);

                let mut x = 0.0f32;
                let mut y = 0.0f32;
                let mut iteration = 0;

                // Iterate!
                while (x*x + y*y < 4.0) && (iteration < max_iteration) {
                    let x1 = x*x - y*y + x0;
                    y = 2.0*x*y + y0;
                    x = x1;

                    iteration += 1;
                }

                // Colour and plot
                //color = palette[iteration];
                let color = iteration;
                let ofs = px+self.buffer_width*py;
//                *self.buffer.get_mut(ofs) = color;
                self.buffer.push(color);
            }
        }

        // Save
        let filename = "m1.pgm";
        let mut file = File::create(&Path::new(filename));
        file.write(bytes!("P5\n"));
        file.write_str(format!("{} {}\n255\n", self.buffer_width, self.buffer_height));
        file.write(self.buffer.slice(0, self.buffer.capacity()));
    }

    // Evaluate a single point
    fn mandel(&self, z: Complex64) -> uint {
        let maxiter: uint = 80;
        let mut c: Complex64 = z;
        for n in range(0, maxiter) {
            if c.norm() > 2.0 {
                return n;
            }
            c = c*c+z;
        }
        return maxiter;
    }
}

//----------------------------------------------------------------------------

fn start_engine(tx: &Sender<uint>) {
    let mut engine = MandelEngine::new(1920, 960);
    engine.process();
//    tx.send(42);
}

//----------------------------------------------------------------------------

#[start]
fn start(argc: int, argv: **u8) -> int {
    native::start(argc, argv, main)
}

fn main() {

    println!("GLFW version: {:s}", glfw::get_version_string());

    glfw::start(proc() {

        glfw::window_hint::context_version_major(3);
        glfw::window_hint::context_version_minor(2);
        glfw::window_hint::opengl_forward_compat(true);
        glfw::window_hint::opengl_profile(glfw::OpenGlCoreProfile);
        glfw::window_hint::resizable(false);

        let window = glfw::Window::create(640, 480,
                                          "MandelRust",
                                          glfw::Windowed)
            .expect("Failed to create GLFW window.");

        window.make_context_current();

        let win_ctrl = ~WindowController::new(&window);

        let (tx, rx): (Sender<uint>, Receiver<uint>) = channel();

        native::task::spawn( proc() {
            start_engine(&tx);
        });

//         let indata = rx.recv();
//         println!("indata {}", indata);

        while !window.should_close() {
            glfw::poll_events();
            for event in window.flush_events() {
                win_ctrl.handle_window_event(&window, event);
            }
            win_ctrl.draw();
        }
    });
}
<|endoftext|>


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

#[derive(Debug)]
pub enum Icon {
    Update,
    Error,
}

#[cfg(unix)]
mod unix {
    extern crate notify_rust;
    use std::error::Error;
    use notification::Icon;
    use self::notify_rust::Notification;

    pub fn create(icon: Icon, title: &str, body: &str) -> Result<(), Box<Error>> {
        let icon = match icon {
            Icon::Update => "emblem-sound",
            Icon::Error  => "dialog-error",
        };

        Notification::new()
            .summary(title)
            .body(body)
            .icon(icon)
            .show()
            .map(|_| ())
            .map_err(|e| e.into())
    }
}

#[cfg(windows)]
mod windows {
    extern crate winapi;
    extern crate user32;
    extern crate kernel32;

    use std::cmp;
    use std::error::Error;
    use std::ptr;
    use std::sync::Mutex;
    use self::winapi::winuser::{IDI_INFORMATION, IDI_ERROR};
    use self::winapi::minwindef::{UINT, HINSTANCE};
    use notification::Icon;
    use util::windows::*;

    const NIM_ADD: UINT    = 0;
    const NIM_DELETE: UINT = 2;

    pub fn create(icon: Icon, title: &str, body: &str) -> Result<(), Box<Error>> {
        lazy_static! {
            static ref NOTIF_DATA: Mutex<NotifData> = unsafe {
                Mutex::new(NotifData::new())
            };
        }

        let mut notif = NOTIF_DATA.lock().unwrap();
        let notif = &mut notif.data;

        let icon = match icon {
            Icon::Update => IDI_INFORMATION,
            Icon::Error  => IDI_ERROR,
        };

        unsafe {
            notif.hIcon = user32::LoadIconW(0 as HINSTANCE, icon);

            let title = to_wstring(title);
            ptr::copy(title.as_ptr(), notif.szInfoTitle.as_mut_ptr(), cmp::min(title.len(), notif.szInfoTitle.len()));

            let body = to_wstring(body);
            ptr::copy(body.as_ptr(), notif.szInfo.as_mut_ptr(), cmp::min(body.len(), notif.szInfo.len()));

            Shell_NotifyIconW(NIM_ADD, notif);
            Shell_NotifyIconW(NIM_DELETE, notif);
        }

        Ok(())
    }
}

#[cfg(unix)]
use self::unix::create;

#[cfg(windows)]
use self::windows::create;

pub fn create_update(feed_idx: i32, max_feed_idx: i32, feed: &Feed, feed_delta: i32) ->
    Result<(), Box<Error>> {

    let alert = match feed.alert {
        Some(ref alert) => format!("\nAlert: {}", alert),
        None            => String::new(),
    };

    create(
        Icon::Update,
        &format!("Broadcastify Update ({} of {})", feed_idx, max_feed_idx),
        &format!("Name: {}\nListeners: {} (^{}){}\nLink: http://broadcastify.com/listen/feed/{}",
            feed.name,
            feed.listeners,
            feed_delta,
            &alert,
            feed.id))
}

pub fn create_error(body: &str) -> Result<(), Box<Error>> {
    create(
        Icon::Error,
        "Broadcastify Update Error",
        body)
}<commit_msg>Remove call to unwrap()<commit_after>use std::error::Error;
use feed::Feed;

#[derive(Debug)]
pub enum Icon {
    Update,
    Error,
}

#[cfg(unix)]
mod unix {
    extern crate notify_rust;
    use std::error::Error;
    use notification::Icon;
    use self::notify_rust::Notification;

    pub fn create(icon: Icon, title: &str, body: &str) -> Result<(), Box<Error>> {
        let icon = match icon {
            Icon::Update => "emblem-sound",
            Icon::Error  => "dialog-error",
        };

        Notification::new()
            .summary(title)
            .body(body)
            .icon(icon)
            .show()
            .map(|_| ())
            .map_err(|e| e.into())
    }
}

#[cfg(windows)]
mod windows {
    extern crate winapi;
    extern crate user32;
    extern crate kernel32;

    use std::cmp;
    use std::error::Error;
    use std::ptr;
    use std::sync::Mutex;
    use self::winapi::winuser::{IDI_INFORMATION, IDI_ERROR};
    use self::winapi::minwindef::{UINT, HINSTANCE};
    use notification::Icon;
    use util::windows::*;

    const NIM_ADD: UINT    = 0;
    const NIM_DELETE: UINT = 2;

    pub fn create(icon: Icon, title: &str, body: &str) -> Result<(), Box<Error>> {
        lazy_static! {
            static ref NOTIF_DATA: Mutex<NotifData> = unsafe {
                Mutex::new(NotifData::new())
            };
        }

        let mut notif = NOTIF_DATA.lock()?;
        let notif = &mut notif.data;

        let icon = match icon {
            Icon::Update => IDI_INFORMATION,
            Icon::Error  => IDI_ERROR,
        };

        unsafe {
            notif.hIcon = user32::LoadIconW(0 as HINSTANCE, icon);

            let title = to_wstring(title);
            ptr::copy(title.as_ptr(), notif.szInfoTitle.as_mut_ptr(), cmp::min(title.len(), notif.szInfoTitle.len()));

            let body = to_wstring(body);
            ptr::copy(body.as_ptr(), notif.szInfo.as_mut_ptr(), cmp::min(body.len(), notif.szInfo.len()));

            Shell_NotifyIconW(NIM_ADD, notif);
            Shell_NotifyIconW(NIM_DELETE, notif);
        }

        Ok(())
    }
}

#[cfg(unix)]
use self::unix::create;

#[cfg(windows)]
use self::windows::create;

pub fn create_update(feed_idx: i32, max_feed_idx: i32, feed: &Feed, feed_delta: i32) ->
    Result<(), Box<Error>> {

    let alert = match feed.alert {
        Some(ref alert) => format!("\nAlert: {}", alert),
        None            => String::new(),
    };

    create(
        Icon::Update,
        &format!("Broadcastify Update ({} of {})", feed_idx, max_feed_idx),
        &format!("Name: {}\nListeners: {} (^{}){}\nLink: http://broadcastify.com/listen/feed/{}",
            feed.name,
            feed.listeners,
            feed_delta,
            &alert,
            feed.id))
}

pub fn create_error(body: &str) -> Result<(), Box<Error>> {
    create(
        Icon::Error,
        "Broadcastify Update Error",
        body)
}<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2014 Y. T. CHUNG <zonyitoo@gmail.com>

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

//! TcpRelay server that running on local environment

use std::io;
use std::net::SocketAddr;
use std::sync::Arc;

use futures::{self, Future, BoxFuture};
use futures::stream::Stream;

use tokio_core::net::{TcpStream, TcpListener};
use tokio_core::reactor::Handle;
use tokio_core::io::Io;
use tokio_core::io::{ReadHalf, WriteHalf};
use tokio_core::io::{flush, copy, write_all};

use hyper::method::Method;

use config::{Config, ServerConfig};

use relay::socks5::{self, HandshakeRequest, HandshakeResponse, Address};
use relay::socks5::{TcpRequestHeader, TcpResponseHeader};
use relay::loadbalancing::server::RoundRobin;
use relay::loadbalancing::server::LoadBalancer;

use super::http::{self, HttpRequestFut, HttpResponseFut};

/// TCP relay local server
pub struct TcpRelayLocal {
    config: Arc<Config>,
}

impl TcpRelayLocal {
    pub fn new(config: Arc<Config>) -> TcpRelayLocal {
        TcpRelayLocal { config: config }
    }

    pub fn run(self, handle: Handle) -> Box<Future<Item = (), Error = io::Error>> {
        let tcp_fut = Socks5RelayLocal::new(self.config.clone()).run(handle.clone());
        match &self.config.http_proxy {
            &Some(..) => {
                let http_fut = HttpRelayServer::new(self.config.clone()).run(handle);
                Box::new(tcp_fut.join(http_fut)
                    .map(|_| ()))
            }
            &None => tcp_fut,
        }
    }
}

/// Socks5 local server
pub struct Socks5RelayLocal {
    config: Arc<Config>,
}

impl Socks5RelayLocal {
    pub fn new(config: Arc<Config>) -> Socks5RelayLocal {
        Socks5RelayLocal { config: config }
    }

    fn handle_socks5_connect(handle: &Handle,
                             (r, w): (ReadHalf<TcpStream>, WriteHalf<TcpStream>),
                             client_addr: SocketAddr,
                             addr: Address,
                             svr_cfg: Arc<ServerConfig>)
                             -> BoxFuture<(), io::Error> {
        let cloned_addr = addr.clone();
        super::connect_proxy_server(handle, svr_cfg, addr)
            .and_then(move |(svr_r, svr_w)| {
                let header = TcpResponseHeader::new(socks5::Reply::Succeeded,
                                                    Address::SocketAddress(client_addr));
                trace!("Send header: {:?}", header);

                header.write_to(w)
                    .and_then(|w| flush(w))
                    .and_then(|w| Ok((svr_r, svr_w, w)))
            })
            .and_then(move |(svr_r, svr_w, w)| {
                let c2s = copy(r, svr_w);
                let s2c = copy(svr_r, w);
                c2s.join(s2c)
                    .and_then(move |(c2s_amt, s2c_amt)| {
                        trace!("Relayed {} client -> remote {}bytes", cloned_addr, c2s_amt);
                        trace!("Relayed {} client <- remote {}bytes", cloned_addr, s2c_amt);
                        Ok(())
                    })
            })
            .boxed()
    }

    fn handle_client(handle: &Handle, s: TcpStream, _: SocketAddr, conf: Arc<ServerConfig>) -> io::Result<()> {
        let cloned_handle = handle.clone();
        let client_addr = try!(s.peer_addr());
        let cloned_client_addr = client_addr.clone();
        let fut = futures::lazy(|| Ok(s.split()))
            .and_then(|(r, w)| {
                // Socks5 handshakes
                HandshakeRequest::read_from(r).and_then(move |(r, req)| {
                    trace!("Socks5 {:?}", req);

                    if !req.methods.contains(&socks5::SOCKS5_AUTH_METHOD_NONE) {
                        let resp = HandshakeResponse::new(socks5::SOCKS5_AUTH_METHOD_NOT_ACCEPTABLE);
                        resp.write_to(w)
                            .then(|_| {
                                warn!("Currently shadowsocks-rust does not support authentication");
                                Err(io::Error::new(io::ErrorKind::Other,
                                                   "Currently shadowsocks-rust does not support authentication"))
                            })
                            .boxed()
                    } else {
                        // Reply to client
                        let resp = HandshakeResponse::new(socks5::SOCKS5_AUTH_METHOD_NONE);
                        trace!("Reply handshake {:?}", resp);
                        resp.write_to(w).and_then(|w| Ok((r, w))).boxed()
                    }
                })
            })
            .and_then(move |(r, w)| {
                // Fetch headers
                TcpRequestHeader::read_from(r).then(move |res| {
                    match res {
                        Ok((r, h)) => futures::finished((r, w, h)).boxed(),
                        Err(err) => {
                            error!("Failed to get TcpRequestHeader: {}", err);
                            TcpResponseHeader::new(err.reply, Address::SocketAddress(client_addr))
                                .write_to(w)
                                .then(|_| Err(From::from(err)))
                                .boxed()
                        }
                    }
                })
            })
            .and_then(move |(r, w, header)| {
                trace!("Socks5 {:?}", header);

                let addr = header.address;
                match header.command {
                    socks5::Command::TcpConnect => {
                        info!("CONNECT {}", addr);
                        Socks5RelayLocal::handle_socks5_connect(&cloned_handle, (r, w), cloned_client_addr, addr, conf)
                    }
                    socks5::Command::TcpBind => {
                        warn!("BIND is not supported");
                        TcpResponseHeader::new(socks5::Reply::CommandNotSupported, addr)
                            .write_to(w)
                            .map(|_| ())
                            .boxed()
                    }
                    socks5::Command::UdpAssociate => unimplemented!(),
                }
            });

        // Runs in Tokio
        handle.spawn(fut.then(|res| {
            match res {
                Ok(..) => Ok(()),
                Err(err) => {
                    error!("Failed to handle client: {}", err);
                    Err(())
                }
            }
        }));

        Ok(())
    }

    // Runs TCP relay local server
    pub fn run(self, handle: Handle) -> Box<Future<Item = (), Error = io::Error>> {
        let listener = {
            let local_addr = self.config.local.as_ref().unwrap();
            let listener = TcpListener::bind(local_addr, &handle).unwrap();
            info!("ShadowSocks TCP Listening on {}", local_addr);
            listener
        };

        let mut servers = RoundRobin::new(self.config);
        let listening = listener.incoming()
            .for_each(move |(socket, addr)| {
                let server_cfg = servers.pick_server();
                trace!("Got connection, addr: {}", addr);
                trace!("Picked proxy server: {:?}", server_cfg);
                Socks5RelayLocal::handle_client(&handle, socket, addr, server_cfg)
            });

        Box::new(listening.map_err(|err| {
            error!("Socks5 server run failed: {}", err);
            err
        }))
    }
}

/// HTTP local server
pub struct HttpRelayServer {
    config: Arc<Config>,
}

impl HttpRelayServer {
    pub fn new(config: Arc<Config>) -> HttpRelayServer {
        HttpRelayServer { config: config }
    }

    fn handle_connect(handle: Handle,
                      (r, w): (ReadHalf<TcpStream>, WriteHalf<TcpStream>),
                      req: http::HttpRequest,
                      addr: Address,
                      remains: Vec<u8>,
                      svr_cfg: Arc<ServerConfig>)
                      -> BoxFuture<(), io::Error> {
        let cloned_addr = addr.clone();
        let http_version = req.version;
        super::connect_proxy_server(&handle, svr_cfg, addr)
            .and_then(move |(svr_r, svr_w)| {
                let handshake_resp = format!("{} 200 Connection Established\r\n\r\n", http_version);
                trace!("Sending HTTP tunnel handshake response");
                write_all(w, handshake_resp.into_bytes()).and_then(|(w, _)| flush(w)).map(|w| (svr_r, svr_w, w))
            })
            .and_then(move |(svr_r, svr_w, w)| write_all(svr_w, remains).map(|(svr_w, _)| (svr_r, svr_w, w)))
            .and_then(move |(svr_r, svr_w, w)| {
                let c2s = copy(r, svr_w);
                let s2c = copy(svr_r, w);
                c2s.join(s2c)
                    .and_then(move |(c2s_amt, s2c_amt)| {
                        trace!("Relayed {} client -> remote {}bytes", cloned_addr, c2s_amt);
                        trace!("Relayed {} client <- remote {}bytes", cloned_addr, s2c_amt);
                        Ok(())
                    })
            })
            .boxed()
    }

    fn handle_http_again((r, w): (ReadHalf<TcpStream>, WriteHalf<TcpStream>),
                         (svr_r, svr_w): (super::DecryptedHalf, super::EncryptedHalf),
                         client_addr: SocketAddr,
                         (req_remains, rsp_remains): (Vec<u8>, Vec<u8>),
                         svr_cfg: Arc<ServerConfig>)
                         -> BoxFuture<(), io::Error> {
        let client_addr_cloned = client_addr.clone();
        HttpRequestFut::with_buf(r, req_remains)
            .and_then(move |(r, req, req_remains)| {
                let svr_addr = svr_cfg.addr.clone();
                http::proxy_request((r, svr_w), client_addr, req, req_remains)
                    .and_then(move |(r, svr_w, req_remains)| {
                        HttpResponseFut::with_buf(svr_r, rsp_remains)
                            .and_then(move |(svr_r, rsp, rsp_remains)| {
                                http::proxy_response((svr_r, w), svr_addr, rsp, rsp_remains)
                            })
                            .map(move |(svr_r, w, rsp_remains)| (r, w, svr_r, svr_w, req_remains, rsp_remains))
                    })
                    .and_then(move |(r, w, svr_r, svr_w, req_remains, rsp_remains)| {
                        HttpRelayServer::handle_http_again((r, w),
                                                           (svr_r, svr_w),
                                                           client_addr_cloned,
                                                           (req_remains, rsp_remains),
                                                           svr_cfg)
                    })
            })
            .boxed()
    }

    fn handle_http_proxy(handle: Handle,
                         (r, w): (ReadHalf<TcpStream>, WriteHalf<TcpStream>),
                         client_addr: SocketAddr,
                         req: http::HttpRequest,
                         addr: Address,
                         remains: Vec<u8>,
                         svr_cfg: Arc<ServerConfig>)
                         -> BoxFuture<(), io::Error> {
        let client_addr_cloned = client_addr.clone();

        super::connect_proxy_server(&handle, svr_cfg.clone(), addr)
            .and_then(move |(svr_r, svr_w)| {
                trace!("Going to pass req to server: {:?}", req);
                let svr_addr = svr_cfg.addr.clone();
                http::proxy_request((r, svr_w), client_addr, req, remains)
                    .and_then(move |(r, svr_w, req_remains)| {
                        HttpResponseFut::new(svr_r)
                            .and_then(move |(svr_r, rsp, rsp_remains)| {
                                http::proxy_response((svr_r, w), svr_addr, rsp, rsp_remains)
                            })
                            .map(move |(svr_r, w, rsp_remains)| (r, w, svr_r, svr_w, req_remains, rsp_remains))
                    })
                    .and_then(move |(r, w, svr_r, svr_w, req_remains, rsp_remains)| {
                        HttpRelayServer::handle_http_again((r, w),
                                                           (svr_r, svr_w),
                                                           client_addr_cloned,
                                                           (req_remains, rsp_remains),
                                                           svr_cfg)
                    })
            })
            .boxed()
    }

    fn handle_client(handle: &Handle, socket: TcpStream, _: SocketAddr, svr_cfg: Arc<ServerConfig>) -> io::Result<()> {
        let cloned_handle = handle.clone();
        let client_addr = try!(socket.peer_addr());
        let fut = futures::lazy(|| Ok(socket.split()))
            .and_then(|(r, w)| {
                HttpRequestFut::new(r).and_then(move |(r, mut req, remains)| {
                    trace!("Got HTTP Request, version: {}, method: {}, uri: {}",
                           req.version,
                           req.method,
                           req.request_uri);

                    match req.get_address() {
                        Ok(addr) => {
                            req.clear_request_uri_host();
                            futures::finished((r, w, req, addr, remains)).boxed()
                        }
                        Err(status_code) => {
                            http::write_response(w, req.version, status_code)
                                .then(|_| {
                                    let err = io::Error::new(io::ErrorKind::Other, "Invalid Uri");
                                    Err(err)
                                })
                                .boxed()
                        }
                    }
                })
            })
            .and_then(move |(r, w, req, addr, remains)| {
                match req.method.clone() {
                    Method::Connect => {
                        info!("CONNECT (Http) {}", addr);
                        HttpRelayServer::handle_connect(cloned_handle, (r, w), req, addr, remains, svr_cfg)
                    }
                    met => {
                        info!("{} (Http) {}", met, addr);
                        HttpRelayServer::handle_http_proxy(cloned_handle,
                                                           (r, w),
                                                           client_addr,
                                                           req,
                                                           addr,
                                                           remains,
                                                           svr_cfg)
                    }
                }
            });

        handle.spawn(fut.then(|res| {
            match res {
                Ok(..) => Ok(()),
                Err(err) => {
                    error!("Failed to handle client: {}", err);
                    Err(())
                }
            }
        }));

        Ok(())
    }

    pub fn run(self, handle: Handle) -> Box<Future<Item = (), Error = io::Error>> {
        let listener = {
            let local_addr = self.config.http_proxy.as_ref().unwrap();
            let listener = TcpListener::bind(local_addr, &handle).unwrap();
            info!("ShadowSocks HTTP Listening on {}", local_addr);
            listener
        };

        let mut servers = RoundRobin::new(self.config);
        let listening = listener.incoming()
            .for_each(move |(socket, addr)| {
                let server_cfg = servers.pick_server();
                trace!("Got connection, addr: {}", addr);
                trace!("Picked proxy server: {:?}", server_cfg);
                HttpRelayServer::handle_client(&handle, socket, addr, server_cfg)
            });

        Box::new(listening.map_err(|err| {
            error!("HTTP server run failed: {}", err);
            err
        }))
    }
}
<commit_msg>response instead of panic<commit_after>// The MIT License (MIT)

// Copyright (c) 2014 Y. T. CHUNG <zonyitoo@gmail.com>

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

//! TcpRelay server that running on local environment

use std::io;
use std::net::SocketAddr;
use std::sync::Arc;

use futures::{self, Future, BoxFuture};
use futures::stream::Stream;

use tokio_core::net::{TcpStream, TcpListener};
use tokio_core::reactor::Handle;
use tokio_core::io::Io;
use tokio_core::io::{ReadHalf, WriteHalf};
use tokio_core::io::{flush, copy, write_all};

use hyper::method::Method;

use config::{Config, ServerConfig};

use relay::socks5::{self, HandshakeRequest, HandshakeResponse, Address};
use relay::socks5::{TcpRequestHeader, TcpResponseHeader};
use relay::loadbalancing::server::RoundRobin;
use relay::loadbalancing::server::LoadBalancer;

use super::http::{self, HttpRequestFut, HttpResponseFut};

/// TCP relay local server
pub struct TcpRelayLocal {
    config: Arc<Config>,
}

impl TcpRelayLocal {
    pub fn new(config: Arc<Config>) -> TcpRelayLocal {
        TcpRelayLocal { config: config }
    }

    pub fn run(self, handle: Handle) -> Box<Future<Item = (), Error = io::Error>> {
        let tcp_fut = Socks5RelayLocal::new(self.config.clone()).run(handle.clone());
        match &self.config.http_proxy {
            &Some(..) => {
                let http_fut = HttpRelayServer::new(self.config.clone()).run(handle);
                Box::new(tcp_fut.join(http_fut)
                    .map(|_| ()))
            }
            &None => tcp_fut,
        }
    }
}

/// Socks5 local server
pub struct Socks5RelayLocal {
    config: Arc<Config>,
}

impl Socks5RelayLocal {
    pub fn new(config: Arc<Config>) -> Socks5RelayLocal {
        Socks5RelayLocal { config: config }
    }

    fn handle_socks5_connect(handle: &Handle,
                             (r, w): (ReadHalf<TcpStream>, WriteHalf<TcpStream>),
                             client_addr: SocketAddr,
                             addr: Address,
                             svr_cfg: Arc<ServerConfig>)
                             -> BoxFuture<(), io::Error> {
        let cloned_addr = addr.clone();
        super::connect_proxy_server(handle, svr_cfg, addr)
            .and_then(move |(svr_r, svr_w)| {
                let header = TcpResponseHeader::new(socks5::Reply::Succeeded,
                                                    Address::SocketAddress(client_addr));
                trace!("Send header: {:?}", header);

                header.write_to(w)
                    .and_then(|w| flush(w))
                    .and_then(|w| Ok((svr_r, svr_w, w)))
            })
            .and_then(move |(svr_r, svr_w, w)| {
                let c2s = copy(r, svr_w);
                let s2c = copy(svr_r, w);
                c2s.join(s2c)
                    .and_then(move |(c2s_amt, s2c_amt)| {
                        trace!("Relayed {} client -> remote {}bytes", cloned_addr, c2s_amt);
                        trace!("Relayed {} client <- remote {}bytes", cloned_addr, s2c_amt);
                        Ok(())
                    })
            })
            .boxed()
    }

    fn handle_client(handle: &Handle, s: TcpStream, _: SocketAddr, conf: Arc<ServerConfig>) -> io::Result<()> {
        let cloned_handle = handle.clone();
        let client_addr = try!(s.peer_addr());
        let cloned_client_addr = client_addr.clone();
        let fut = futures::lazy(|| Ok(s.split()))
            .and_then(|(r, w)| {
                // Socks5 handshakes
                HandshakeRequest::read_from(r).and_then(move |(r, req)| {
                    trace!("Socks5 {:?}", req);

                    if !req.methods.contains(&socks5::SOCKS5_AUTH_METHOD_NONE) {
                        let resp = HandshakeResponse::new(socks5::SOCKS5_AUTH_METHOD_NOT_ACCEPTABLE);
                        resp.write_to(w)
                            .then(|_| {
                                warn!("Currently shadowsocks-rust does not support authentication");
                                Err(io::Error::new(io::ErrorKind::Other,
                                                   "Currently shadowsocks-rust does not support authentication"))
                            })
                            .boxed()
                    } else {
                        // Reply to client
                        let resp = HandshakeResponse::new(socks5::SOCKS5_AUTH_METHOD_NONE);
                        trace!("Reply handshake {:?}", resp);
                        resp.write_to(w).and_then(|w| Ok((r, w))).boxed()
                    }
                })
            })
            .and_then(move |(r, w)| {
                // Fetch headers
                TcpRequestHeader::read_from(r).then(move |res| {
                    match res {
                        Ok((r, h)) => futures::finished((r, w, h)).boxed(),
                        Err(err) => {
                            error!("Failed to get TcpRequestHeader: {}", err);
                            TcpResponseHeader::new(err.reply, Address::SocketAddress(client_addr))
                                .write_to(w)
                                .then(|_| Err(From::from(err)))
                                .boxed()
                        }
                    }
                })
            })
            .and_then(move |(r, w, header)| {
                trace!("Socks5 {:?}", header);

                let addr = header.address;
                match header.command {
                    socks5::Command::TcpConnect => {
                        info!("CONNECT {}", addr);
                        Socks5RelayLocal::handle_socks5_connect(&cloned_handle, (r, w), cloned_client_addr, addr, conf)
                    }
                    socks5::Command::TcpBind => {
                        warn!("BIND is not supported");
                        TcpResponseHeader::new(socks5::Reply::CommandNotSupported, addr)
                            .write_to(w)
                            .map(|_| ())
                            .boxed()
                    }
                    socks5::Command::UdpAssociate => {
                        warn!("UDP Associate is not supported");
                        TcpResponseHeader::new(socks5::Reply::CommandNotSupported, addr)
                            .write_to(w)
                            .map(|_| ())
                            .boxed()
                    }
                }
            });

        // Runs in Tokio
        handle.spawn(fut.then(|res| {
            match res {
                Ok(..) => Ok(()),
                Err(err) => {
                    error!("Failed to handle client: {}", err);
                    Err(())
                }
            }
        }));

        Ok(())
    }

    // Runs TCP relay local server
    pub fn run(self, handle: Handle) -> Box<Future<Item = (), Error = io::Error>> {
        let listener = {
            let local_addr = self.config.local.as_ref().unwrap();
            let listener = TcpListener::bind(local_addr, &handle).unwrap();
            info!("ShadowSocks TCP Listening on {}", local_addr);
            listener
        };

        let mut servers = RoundRobin::new(self.config);
        let listening = listener.incoming()
            .for_each(move |(socket, addr)| {
                let server_cfg = servers.pick_server();
                trace!("Got connection, addr: {}", addr);
                trace!("Picked proxy server: {:?}", server_cfg);
                Socks5RelayLocal::handle_client(&handle, socket, addr, server_cfg)
            });

        Box::new(listening.map_err(|err| {
            error!("Socks5 server run failed: {}", err);
            err
        }))
    }
}

/// HTTP local server
pub struct HttpRelayServer {
    config: Arc<Config>,
}

impl HttpRelayServer {
    pub fn new(config: Arc<Config>) -> HttpRelayServer {
        HttpRelayServer { config: config }
    }

    fn handle_connect(handle: Handle,
                      (r, w): (ReadHalf<TcpStream>, WriteHalf<TcpStream>),
                      req: http::HttpRequest,
                      addr: Address,
                      remains: Vec<u8>,
                      svr_cfg: Arc<ServerConfig>)
                      -> BoxFuture<(), io::Error> {
        let cloned_addr = addr.clone();
        let http_version = req.version;
        super::connect_proxy_server(&handle, svr_cfg, addr)
            .and_then(move |(svr_r, svr_w)| {
                let handshake_resp = format!("{} 200 Connection Established\r\n\r\n", http_version);
                trace!("Sending HTTP tunnel handshake response");
                write_all(w, handshake_resp.into_bytes()).and_then(|(w, _)| flush(w)).map(|w| (svr_r, svr_w, w))
            })
            .and_then(move |(svr_r, svr_w, w)| write_all(svr_w, remains).map(|(svr_w, _)| (svr_r, svr_w, w)))
            .and_then(move |(svr_r, svr_w, w)| {
                let c2s = copy(r, svr_w);
                let s2c = copy(svr_r, w);
                c2s.join(s2c)
                    .and_then(move |(c2s_amt, s2c_amt)| {
                        trace!("Relayed {} client -> remote {}bytes", cloned_addr, c2s_amt);
                        trace!("Relayed {} client <- remote {}bytes", cloned_addr, s2c_amt);
                        Ok(())
                    })
            })
            .boxed()
    }

    fn handle_http_again((r, w): (ReadHalf<TcpStream>, WriteHalf<TcpStream>),
                         (svr_r, svr_w): (super::DecryptedHalf, super::EncryptedHalf),
                         client_addr: SocketAddr,
                         (req_remains, rsp_remains): (Vec<u8>, Vec<u8>),
                         svr_cfg: Arc<ServerConfig>)
                         -> BoxFuture<(), io::Error> {
        let client_addr_cloned = client_addr.clone();
        HttpRequestFut::with_buf(r, req_remains)
            .and_then(move |(r, req, req_remains)| {
                let svr_addr = svr_cfg.addr.clone();
                http::proxy_request((r, svr_w), client_addr, req, req_remains)
                    .and_then(move |(r, svr_w, req_remains)| {
                        HttpResponseFut::with_buf(svr_r, rsp_remains)
                            .and_then(move |(svr_r, rsp, rsp_remains)| {
                                http::proxy_response((svr_r, w), svr_addr, rsp, rsp_remains)
                            })
                            .map(move |(svr_r, w, rsp_remains)| (r, w, svr_r, svr_w, req_remains, rsp_remains))
                    })
                    .and_then(move |(r, w, svr_r, svr_w, req_remains, rsp_remains)| {
                        HttpRelayServer::handle_http_again((r, w),
                                                           (svr_r, svr_w),
                                                           client_addr_cloned,
                                                           (req_remains, rsp_remains),
                                                           svr_cfg)
                    })
            })
            .boxed()
    }

    fn handle_http_proxy(handle: Handle,
                         (r, w): (ReadHalf<TcpStream>, WriteHalf<TcpStream>),
                         client_addr: SocketAddr,
                         req: http::HttpRequest,
                         addr: Address,
                         remains: Vec<u8>,
                         svr_cfg: Arc<ServerConfig>)
                         -> BoxFuture<(), io::Error> {
        let client_addr_cloned = client_addr.clone();

        super::connect_proxy_server(&handle, svr_cfg.clone(), addr)
            .and_then(move |(svr_r, svr_w)| {
                trace!("Going to pass req to server: {:?}", req);
                let svr_addr = svr_cfg.addr.clone();
                http::proxy_request((r, svr_w), client_addr, req, remains)
                    .and_then(move |(r, svr_w, req_remains)| {
                        HttpResponseFut::new(svr_r)
                            .and_then(move |(svr_r, rsp, rsp_remains)| {
                                http::proxy_response((svr_r, w), svr_addr, rsp, rsp_remains)
                            })
                            .map(move |(svr_r, w, rsp_remains)| (r, w, svr_r, svr_w, req_remains, rsp_remains))
                    })
                    .and_then(move |(r, w, svr_r, svr_w, req_remains, rsp_remains)| {
                        HttpRelayServer::handle_http_again((r, w),
                                                           (svr_r, svr_w),
                                                           client_addr_cloned,
                                                           (req_remains, rsp_remains),
                                                           svr_cfg)
                    })
            })
            .boxed()
    }

    fn handle_client(handle: &Handle, socket: TcpStream, _: SocketAddr, svr_cfg: Arc<ServerConfig>) -> io::Result<()> {
        let cloned_handle = handle.clone();
        let client_addr = try!(socket.peer_addr());
        let fut = futures::lazy(|| Ok(socket.split()))
            .and_then(|(r, w)| {
                HttpRequestFut::new(r).and_then(move |(r, mut req, remains)| {
                    trace!("Got HTTP Request, version: {}, method: {}, uri: {}",
                           req.version,
                           req.method,
                           req.request_uri);

                    match req.get_address() {
                        Ok(addr) => {
                            req.clear_request_uri_host();
                            futures::finished((r, w, req, addr, remains)).boxed()
                        }
                        Err(status_code) => {
                            http::write_response(w, req.version, status_code)
                                .then(|_| {
                                    let err = io::Error::new(io::ErrorKind::Other, "Invalid Uri");
                                    Err(err)
                                })
                                .boxed()
                        }
                    }
                })
            })
            .and_then(move |(r, w, req, addr, remains)| {
                match req.method.clone() {
                    Method::Connect => {
                        info!("CONNECT (Http) {}", addr);
                        HttpRelayServer::handle_connect(cloned_handle, (r, w), req, addr, remains, svr_cfg)
                    }
                    met => {
                        info!("{} (Http) {}", met, addr);
                        HttpRelayServer::handle_http_proxy(cloned_handle,
                                                           (r, w),
                                                           client_addr,
                                                           req,
                                                           addr,
                                                           remains,
                                                           svr_cfg)
                    }
                }
            });

        handle.spawn(fut.then(|res| {
            match res {
                Ok(..) => Ok(()),
                Err(err) => {
                    error!("Failed to handle client: {}", err);
                    Err(())
                }
            }
        }));

        Ok(())
    }

    pub fn run(self, handle: Handle) -> Box<Future<Item = (), Error = io::Error>> {
        let listener = {
            let local_addr = self.config.http_proxy.as_ref().unwrap();
            let listener = TcpListener::bind(local_addr, &handle).unwrap();
            info!("ShadowSocks HTTP Listening on {}", local_addr);
            listener
        };

        let mut servers = RoundRobin::new(self.config);
        let listening = listener.incoming()
            .for_each(move |(socket, addr)| {
                let server_cfg = servers.pick_server();
                trace!("Got connection, addr: {}", addr);
                trace!("Picked proxy server: {:?}", server_cfg);
                HttpRelayServer::handle_client(&handle, socket, addr, server_cfg)
            });

        Box::new(listening.map_err(|err| {
            error!("HTTP server run failed: {}", err);
            err
        }))
    }
}
<|endoftext|>


<commit_before>use rusqlite::Connection;

#[derive(Debug)]
pub struct JobDepend {
    pub id: i32,
    pub fk_job: i32,
    pub fk_provider: i32,
    pub sq_order: i32,
}

pub fn table_create_job_depend(conn: &Connection) -> &Connection {
    conn.execute(
        "CREATE TABLE JOBDEPEND (
                  id                INTEGER PRIMARY KEY ASC,
                  fk_job            INTEGER NOT NULL,
                  fk_provider       INTEGER NOT NULL,
                  sq_order          INTEGER NOT NULL,
                  UNIQUE (fk_job, fk_provider) ON CONFLICT REPLACE
                  FOREIGN KEY(fk_job) REFERENCES JOB(id) ON UPDATE CASCADE
                  FOREIGN KEY(fk_provider) REFERENCES PROVIDER(id) ON UPDATE CASCADE
                  )",
        &[],
    ).unwrap();
    return conn;
}

pub fn insert_job_depend(
    conn: &Connection,
    job: &i32,
    provider: &i32,
    sq_order: &i32,
) -> Result<i32, &'static str> {
    let me = JobDepend {
        id: 0,
        fk_job: *job,
        fk_provider: *provider,
        sq_order: *sq_order,
    };
    let job_depend_instance = conn.execute(
        "INSERT INTO JOBDEPEND (fk_job, fk_provider, sq_order)
                  VALUES (?1, ?2, ?3)",
        &[&me.fk_job, &me.fk_provider, &me.sq_order],
    );
    if job_depend_instance.is_err() {
        return Err("Insert failed");
    }
    job_depend_instance.unwrap();
    return Ok(0);
}

pub fn list_job_depend(conn: &Connection) -> Vec<JobDepend> {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_provider, sq_order  FROM JOBDEPEND")
        .unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| {
        JobDepend {
            id: row.get(0),
            fk_job: row.get(1),
            fk_provider: row.get(2),
            sq_order: row.get(3),
        }
    });
    let mut items = Vec::<JobDepend>::new();
    if wraped_fs_file_iter.is_err() {
        return items;

    }
    let fs_file_iter = wraped_fs_file_iter.unwrap();
    for person in fs_file_iter {

        items.push(person.unwrap());
    }
    return items;
}

pub fn job_depend_list(conn: &Connection) {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_provider, sq_order FROM JOBDEPEND")
        .unwrap();
    let person_iter = stmt.query_map(&[], |row| {
        JobDepend {
            id: row.get(0),
            fk_job: row.get(1),
            fk_provider: row.get(2),
            sq_order: row.get(3),
        }
    }).unwrap();

    for person in person_iter {
        info!("Found job_depend {:?}", person.unwrap());
    }
}

pub fn pk_job_depend_by_all(
    conn: &Connection,
    fk_job: &i32,
    provider: &i32,
    sq_order: &i32,
) -> Result<i32, &'static str> {
    let mut output = 0;
    let mut stmt = conn.prepare("SELECT JOBDEPEND.id, JOBDEPEND.fk_job, JOBDEPEND.fk_provider, JOBDEPEND.sq_order  FROM JOBDEPEND WHERE JOBDEPEND.fk_job = ?1 AND JOBDEPEND.fk_provider=?2 AND JOBDEPEND.sq_order=?3 ").unwrap();
    let job_depend_iter = stmt.query_map(&[fk_job, provider, sq_order], |row| {
        JobDepend {
            id: row.get(0),
            fk_job: row.get(1),
            fk_provider: row.get(2),
            sq_order: row.get(3),
        }
    });
    if job_depend_iter.is_err() {
        return Err("Insert failed");
    }
    let result = job_depend_iter.unwrap();
    let mut found = 0;
    for person in result {
        let bill = person.unwrap();
        output = bill.id;
        found = 1;
    }
    if found != 0 {
        return Ok(output);
    }
    return Err("None found");
}
<commit_msg>Move away from using PROVIDER<commit_after>use rusqlite::Connection;

#[derive(Debug)]
pub struct JobDepend {
    pub id: i32,
    pub fk_job: i32,
    pub fk_variable: i32,
    pub sq_order: i32,
}

pub fn table_create_job_depend(conn: &Connection) -> &Connection {
    conn.execute(
        "CREATE TABLE JOBDEPEND (
                  id                INTEGER PRIMARY KEY ASC,
                  fk_job            INTEGER NOT NULL,
                  fk_variable       INTEGER NOT NULL,
                  sq_order          INTEGER NOT NULL,
                  UNIQUE (fk_job, fk_variable) ON CONFLICT REPLACE
                  FOREIGN KEY(fk_job) REFERENCES JOB(id) ON UPDATE CASCADE
                  FOREIGN KEY(fk_variable) REFERENCES VARIABLE_NAME(id) ON UPDATE CASCADE
                  )",
        &[],
    ).unwrap();
    return conn;
}

pub fn insert_job_depend(
    conn: &Connection,
    job: &i32,
    provider: &i32,
    sq_order: &i32,
) -> Result<i32, &'static str> {
    let me = JobDepend {
        id: 0,
        fk_job: *job,
        fk_variable: *provider,
        sq_order: *sq_order,
    };
    let job_depend_instance = conn.execute(
        "INSERT INTO JOBDEPEND (fk_job, fk_variable, sq_order)
                  VALUES (?1, ?2, ?3)",
        &[&me.fk_job, &me.fk_variable, &me.sq_order],
    );
    if job_depend_instance.is_err() {
        return Err("Insert failed");
    }
    job_depend_instance.unwrap();
    return Ok(0);
}

pub fn list_job_depend(conn: &Connection) -> Vec<JobDepend> {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_variable, sq_order  FROM JOBDEPEND")
        .unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| {
        JobDepend {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable: row.get(2),
            sq_order: row.get(3),
        }
    });
    let mut items = Vec::<JobDepend>::new();
    if wraped_fs_file_iter.is_err() {
        return items;

    }
    let fs_file_iter = wraped_fs_file_iter.unwrap();
    for person in fs_file_iter {

        items.push(person.unwrap());
    }
    return items;
}

pub fn job_depend_list(conn: &Connection) {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_variable, sq_order FROM JOBDEPEND")
        .unwrap();
    let person_iter = stmt.query_map(&[], |row| {
        JobDepend {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable: row.get(2),
            sq_order: row.get(3),
        }
    }).unwrap();

    for person in person_iter {
        info!("Found job_depend {:?}", person.unwrap());
    }
}

pub fn pk_job_depend_by_all(
    conn: &Connection,
    fk_job: &i32,
    provider: &i32,
    sq_order: &i32,
) -> Result<i32, &'static str> {
    let mut output = 0;
    let mut stmt = conn.prepare("SELECT JOBDEPEND.id, JOBDEPEND.fk_job, JOBDEPEND.fk_variable, JOBDEPEND.sq_order  FROM JOBDEPEND WHERE JOBDEPEND.fk_job = ?1 AND JOBDEPEND.fk_variable=?2 AND JOBDEPEND.sq_order=?3 ").unwrap();
    let job_depend_iter = stmt.query_map(&[fk_job, provider, sq_order], |row| {
        JobDepend {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable: row.get(2),
            sq_order: row.get(3),
        }
    });
    if job_depend_iter.is_err() {
        return Err("Insert failed");
    }
    let result = job_depend_iter.unwrap();
    let mut found = 0;
    for person in result {
        let bill = person.unwrap();
        output = bill.id;
        found = 1;
    }
    if found != 0 {
        return Ok(output);
    }
    return Err("None found");
}
<|endoftext|>


<commit_before>//! Helper functions and structures for the translation.
use crate::environ::WasmResult;
use crate::wasm_unsupported;
use core::u32;
use cranelift_codegen::entity::entity_impl;
use cranelift_codegen::ir;
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
use wasmparser;

/// Index type of a function (imported or defined) inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct FuncIndex(u32);
entity_impl!(FuncIndex);

/// Index type of a defined function inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct DefinedFuncIndex(u32);
entity_impl!(DefinedFuncIndex);

/// Index type of a defined table inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct DefinedTableIndex(u32);
entity_impl!(DefinedTableIndex);

/// Index type of a defined memory inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct DefinedMemoryIndex(u32);
entity_impl!(DefinedMemoryIndex);

/// Index type of a defined global inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct DefinedGlobalIndex(u32);
entity_impl!(DefinedGlobalIndex);

/// Index type of a table (imported or defined) inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct TableIndex(u32);
entity_impl!(TableIndex);

/// Index type of a global variable (imported or defined) inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct GlobalIndex(u32);
entity_impl!(GlobalIndex);

/// Index type of a linear memory (imported or defined) inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct MemoryIndex(u32);
entity_impl!(MemoryIndex);

/// Index type of a signature (imported or defined) inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct SignatureIndex(u32);
entity_impl!(SignatureIndex);

/// WebAssembly global.
#[derive(Debug, Clone, Copy, Hash)]
pub struct Global {
    /// The type of the value stored in the global.
    pub ty: ir::Type,
    /// A flag indicating whether the value may change at runtime.
    pub mutability: bool,
    /// The source of the initial value.
    pub initializer: GlobalInit,
}

/// Globals are initialized via the `const` operators or by referring to another import.
#[derive(Debug, Clone, Copy, Hash)]
pub enum GlobalInit {
    /// An `i32.const`.
    I32Const(i32),
    /// An `i64.const`.
    I64Const(i64),
    /// An `f32.const`.
    F32Const(u32),
    /// An `f64.const`.
    F64Const(u64),
    /// A `vconst`.
    V128Const([u8; 16]),
    /// A `get_global` of another global.
    GetGlobal(GlobalIndex),
    ///< The global is imported from, and thus initialized by, a different module.
    Import,
}

/// WebAssembly table.
#[derive(Debug, Clone, Copy, Hash)]
pub struct Table {
    /// The type of data stored in elements of the table.
    pub ty: TableElementType,
    /// The minimum number of elements in the table.
    pub minimum: u32,
    /// The maximum number of elements in the table.
    pub maximum: Option<u32>,
}

/// WebAssembly table element. Can be a function or a scalar type.
#[derive(Debug, Clone, Copy, Hash)]
pub enum TableElementType {
    /// A scalar type.
    Val(ir::Type),
    /// A function.
    Func,
}

/// WebAssembly linear memory.
#[derive(Debug, Clone, Copy, Hash)]
pub struct Memory {
    /// The minimum number of pages in the memory.
    pub minimum: u32,
    /// The maximum number of pages in the memory.
    pub maximum: Option<u32>,
    /// Whether the memory may be shared between multiple threads.
    pub shared: bool,
}

/// Helper function translating wasmparser types to Cranelift types when possible.
pub fn type_to_type(ty: wasmparser::Type) -> WasmResult<ir::Type> {
    match ty {
        wasmparser::Type::I32 => Ok(ir::types::I32),
        wasmparser::Type::I64 => Ok(ir::types::I64),
        wasmparser::Type::F32 => Ok(ir::types::F32),
        wasmparser::Type::F64 => Ok(ir::types::F64),
        ty => wasm_unsupported!("type_to_type: wasm type {:?}", ty),
    }
}

/// Helper function translating wasmparser possible table types to Cranelift types when possible,
/// or None for Func tables.
pub fn tabletype_to_type(ty: wasmparser::Type) -> WasmResult<Option<ir::Type>> {
    match ty {
        wasmparser::Type::I32 => Ok(Some(ir::types::I32)),
        wasmparser::Type::I64 => Ok(Some(ir::types::I64)),
        wasmparser::Type::F32 => Ok(Some(ir::types::F32)),
        wasmparser::Type::F64 => Ok(Some(ir::types::F64)),
        wasmparser::Type::AnyFunc => Ok(None),
        ty => wasm_unsupported!("tabletype_to_type: table wasm type {:?}", ty),
    }
}

/// Helper function translating wasmparser block signatures to Cranelift types when possible.
pub fn blocktype_to_type(ty_or_ft: wasmparser::TypeOrFuncType) -> WasmResult<Option<ir::Type>> {
    match ty_or_ft {
        wasmparser::TypeOrFuncType::Type(ty) => match ty {
            wasmparser::Type::I32 => Ok(Some(ir::types::I32)),
            wasmparser::Type::I64 => Ok(Some(ir::types::I64)),
            wasmparser::Type::F32 => Ok(Some(ir::types::F32)),
            wasmparser::Type::F64 => Ok(Some(ir::types::F64)),
            wasmparser::Type::EmptyBlockType => Ok(None),
            ty => wasm_unsupported!("blocktype_to_type: type {:?}", ty),
        },
        wasmparser::TypeOrFuncType::FuncType(_) => wasm_unsupported!(
            "blocktype_to_type: multi-value block signature {:?}",
            ty_or_ft
        ),
    }
}

/// Turns a `wasmparser` `f32` into a `Cranelift` one.
pub fn f32_translation(x: wasmparser::Ieee32) -> ir::immediates::Ieee32 {
    ir::immediates::Ieee32::with_bits(x.bits())
}

/// Turns a `wasmparser` `f64` into a `Cranelift` one.
pub fn f64_translation(x: wasmparser::Ieee64) -> ir::immediates::Ieee64 {
    ir::immediates::Ieee64::with_bits(x.bits())
}

/// Translate a `wasmparser` type into its `Cranelift` equivalent, when possible
pub fn num_return_values(ty: wasmparser::TypeOrFuncType) -> WasmResult<usize> {
    match ty {
        wasmparser::TypeOrFuncType::Type(ty) => match ty {
            wasmparser::Type::EmptyBlockType => Ok(0),
            wasmparser::Type::I32
            | wasmparser::Type::F32
            | wasmparser::Type::I64
            | wasmparser::Type::F64 => Ok(1),
            ty => wasm_unsupported!("unsupported return value type {:?}", ty),
        },
        wasmparser::TypeOrFuncType::FuncType(_) => {
            wasm_unsupported!("multi-value block signature {:?}", ty);
        }
    }
}

/// Special VMContext value label. It is tracked as 0xffff_fffe label.
pub fn get_vmctx_value_label() -> ir::ValueLabel {
    const VMCTX_LABEL: u32 = 0xffff_fffe;
    ir::ValueLabel::from_u32(VMCTX_LABEL)
}
<commit_msg>Add V128 -> I8X16 type conversions<commit_after>//! Helper functions and structures for the translation.
use crate::environ::WasmResult;
use crate::wasm_unsupported;
use core::u32;
use cranelift_codegen::entity::entity_impl;
use cranelift_codegen::ir;
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
use wasmparser;

/// Index type of a function (imported or defined) inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct FuncIndex(u32);
entity_impl!(FuncIndex);

/// Index type of a defined function inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct DefinedFuncIndex(u32);
entity_impl!(DefinedFuncIndex);

/// Index type of a defined table inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct DefinedTableIndex(u32);
entity_impl!(DefinedTableIndex);

/// Index type of a defined memory inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct DefinedMemoryIndex(u32);
entity_impl!(DefinedMemoryIndex);

/// Index type of a defined global inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct DefinedGlobalIndex(u32);
entity_impl!(DefinedGlobalIndex);

/// Index type of a table (imported or defined) inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct TableIndex(u32);
entity_impl!(TableIndex);

/// Index type of a global variable (imported or defined) inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct GlobalIndex(u32);
entity_impl!(GlobalIndex);

/// Index type of a linear memory (imported or defined) inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct MemoryIndex(u32);
entity_impl!(MemoryIndex);

/// Index type of a signature (imported or defined) inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct SignatureIndex(u32);
entity_impl!(SignatureIndex);

/// WebAssembly global.
#[derive(Debug, Clone, Copy, Hash)]
pub struct Global {
    /// The type of the value stored in the global.
    pub ty: ir::Type,
    /// A flag indicating whether the value may change at runtime.
    pub mutability: bool,
    /// The source of the initial value.
    pub initializer: GlobalInit,
}

/// Globals are initialized via the `const` operators or by referring to another import.
#[derive(Debug, Clone, Copy, Hash)]
pub enum GlobalInit {
    /// An `i32.const`.
    I32Const(i32),
    /// An `i64.const`.
    I64Const(i64),
    /// An `f32.const`.
    F32Const(u32),
    /// An `f64.const`.
    F64Const(u64),
    /// A `vconst`.
    V128Const([u8; 16]),
    /// A `get_global` of another global.
    GetGlobal(GlobalIndex),
    ///< The global is imported from, and thus initialized by, a different module.
    Import,
}

/// WebAssembly table.
#[derive(Debug, Clone, Copy, Hash)]
pub struct Table {
    /// The type of data stored in elements of the table.
    pub ty: TableElementType,
    /// The minimum number of elements in the table.
    pub minimum: u32,
    /// The maximum number of elements in the table.
    pub maximum: Option<u32>,
}

/// WebAssembly table element. Can be a function or a scalar type.
#[derive(Debug, Clone, Copy, Hash)]
pub enum TableElementType {
    /// A scalar type.
    Val(ir::Type),
    /// A function.
    Func,
}

/// WebAssembly linear memory.
#[derive(Debug, Clone, Copy, Hash)]
pub struct Memory {
    /// The minimum number of pages in the memory.
    pub minimum: u32,
    /// The maximum number of pages in the memory.
    pub maximum: Option<u32>,
    /// Whether the memory may be shared between multiple threads.
    pub shared: bool,
}

/// Helper function translating wasmparser types to Cranelift types when possible.
pub fn type_to_type(ty: wasmparser::Type) -> WasmResult<ir::Type> {
    match ty {
        wasmparser::Type::I32 => Ok(ir::types::I32),
        wasmparser::Type::I64 => Ok(ir::types::I64),
        wasmparser::Type::F32 => Ok(ir::types::F32),
        wasmparser::Type::F64 => Ok(ir::types::F64),
        wasmparser::Type::V128 => Ok(ir::types::I8X16),
        ty => wasm_unsupported!("type_to_type: wasm type {:?}", ty),
    }
}

/// Helper function translating wasmparser possible table types to Cranelift types when possible,
/// or None for Func tables.
pub fn tabletype_to_type(ty: wasmparser::Type) -> WasmResult<Option<ir::Type>> {
    match ty {
        wasmparser::Type::I32 => Ok(Some(ir::types::I32)),
        wasmparser::Type::I64 => Ok(Some(ir::types::I64)),
        wasmparser::Type::F32 => Ok(Some(ir::types::F32)),
        wasmparser::Type::F64 => Ok(Some(ir::types::F64)),
        wasmparser::Type::V128 => Ok(Some(ir::types::I8X16)),
        wasmparser::Type::AnyFunc => Ok(None),
        ty => wasm_unsupported!("tabletype_to_type: table wasm type {:?}", ty),
    }
}

/// Helper function translating wasmparser block signatures to Cranelift types when possible.
pub fn blocktype_to_type(ty_or_ft: wasmparser::TypeOrFuncType) -> WasmResult<Option<ir::Type>> {
    match ty_or_ft {
        wasmparser::TypeOrFuncType::Type(ty) => match ty {
            wasmparser::Type::I32 => Ok(Some(ir::types::I32)),
            wasmparser::Type::I64 => Ok(Some(ir::types::I64)),
            wasmparser::Type::F32 => Ok(Some(ir::types::F32)),
            wasmparser::Type::F64 => Ok(Some(ir::types::F64)),
            wasmparser::Type::V128 => Ok(Some(ir::types::I8X16)),
            wasmparser::Type::EmptyBlockType => Ok(None),
            ty => wasm_unsupported!("blocktype_to_type: type {:?}", ty),
        },
        wasmparser::TypeOrFuncType::FuncType(_) => wasm_unsupported!(
            "blocktype_to_type: multi-value block signature {:?}",
            ty_or_ft
        ),
    }
}

/// Turns a `wasmparser` `f32` into a `Cranelift` one.
pub fn f32_translation(x: wasmparser::Ieee32) -> ir::immediates::Ieee32 {
    ir::immediates::Ieee32::with_bits(x.bits())
}

/// Turns a `wasmparser` `f64` into a `Cranelift` one.
pub fn f64_translation(x: wasmparser::Ieee64) -> ir::immediates::Ieee64 {
    ir::immediates::Ieee64::with_bits(x.bits())
}

/// Translate a `wasmparser` type into its `Cranelift` equivalent, when possible
pub fn num_return_values(ty: wasmparser::TypeOrFuncType) -> WasmResult<usize> {
    match ty {
        wasmparser::TypeOrFuncType::Type(ty) => match ty {
            wasmparser::Type::EmptyBlockType => Ok(0),
            wasmparser::Type::I32
            | wasmparser::Type::F32
            | wasmparser::Type::I64
            | wasmparser::Type::F64
            | wasmparser::Type::V128 => Ok(1),
            ty => wasm_unsupported!("unsupported return value type {:?}", ty),
        },
        wasmparser::TypeOrFuncType::FuncType(_) => {
            wasm_unsupported!("multi-value block signature {:?}", ty);
        }
    }
}

/// Special VMContext value label. It is tracked as 0xffff_fffe label.
pub fn get_vmctx_value_label() -> ir::ValueLabel {
    const VMCTX_LABEL: u32 = 0xffff_fffe;
    ir::ValueLabel::from_u32(VMCTX_LABEL)
}
<|endoftext|>


<commit_before>#[test]
fn test_bool_to_option() {
    assert_eq!(false.then(0), None);
    assert_eq!(true.then(0), Some(0));
    assert_eq!(false.then_with(|| 0), None);
    assert_eq!(true.then_with(|| 0), Some(0));
}
<commit_msg>Fix libcore tests<commit_after>#[test]
fn test_bool_to_option() {
    assert_eq!(false.to_option(0), None);
    assert_eq!(true.to_option(0), Some(0));
    assert_eq!(false.to_option_with(|| 0), None);
    assert_eq!(true.to_option_with(|| 0), Some(0));
}
<|endoftext|>