<commit_before>extern crate tempdir;

use std::env;
use std::fs::{self, File, OpenOptions};
use std::process::Command;
use std::io::Write;

use tempdir::TempDir;

macro_rules! try {
    ($e:expr) => {
        $e.unwrap_or_else(|e| panic!("{} with {}", stringify!($e), e))
    }
}

const CRATES: &'static [&'static str] = &["alloc", "collections", "core", "rand", "rustc_unicode"];
const LIB_RS: &'static [u8] = b"#![no_std]";

const CUSTOM_JSON: &'static str = r#"
    {
      "arch": "arm",
      "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64",
      "llvm-target": "thumbv7m-none-eabi",
      "os": "none",
      "target-endian": "little",
      "target-pointer-width": "32"
    }
"#;

fn xargo() -> Command {
    let mut path = try!(env::current_exe());
    path.pop();
    path.push("xargo");
    Command::new(path)
}

fn run(cmd: &mut Command) {
    println!("running: {:?}", cmd);
    let output = try!(cmd.output());
    if !output.status.success() {
        println!("--- stdout:\n{}", String::from_utf8_lossy(&output.stdout));
        println!("--- stderr:\n{}", String::from_utf8_lossy(&output.stderr));
        panic!("expected success, got: {}", output.status);
    }
}

fn exists_rlib(krate: &str, target: &str) -> bool {
    let home = env::home_dir().unwrap();

    for entry in try!(fs::read_dir(home.join(format!(".xargo/lib/rustlib/{}/lib", target)))) {
        let path = &try!(entry).path();

        if path.is_file() && path.extension().and_then(|e| e.to_str()) == Some("rlib") &&
           path.file_stem()
               .and_then(|f| f.to_str())
               .map(|s| s.starts_with(&format!("lib{}", krate))) == Some(true) {
            return true;
        }
    }

    false
}

fn cleanup(target: &str) {
    try!(fs::remove_dir_all(env::home_dir()
                                .unwrap()
                                .join(format!(".xargo/lib/rustlib/{}", target))));
}

#[test]
fn simple() {
    const TARGET: &'static str = "__simple";

    let td = try!(TempDir::new("xargo"));
    let td = &td.path();
    try!(try!(File::create(td.join(format!("{}.json", TARGET)))).write_all(CUSTOM_JSON.as_bytes()));

    run(xargo().args(&["init", "--vcs", "none", "--name", TARGET]).current_dir(td));
    try!(try!(OpenOptions::new().truncate(true).write(true).open(td.join("src/lib.rs")))
             .write_all(LIB_RS));
    run(xargo().args(&["build", "--target", TARGET]).current_dir(td));

    for krate in CRATES {
        assert!(exists_rlib(krate, TARGET));
    }

    cleanup(TARGET);
}

// Check that `xargo build` builds a sysroot for the default target in .cargo/config
#[test]
fn cargo_config() {
    const CONFIG: &'static str = "[build]\ntarget = '{}'";
    const TARGET: &'static str = "__cargo_config";

    let td = try!(TempDir::new("xargo"));
    let td = &td.path();
    try!(try!(File::create(td.join(format!("{}.json", TARGET)))).write_all(CUSTOM_JSON.as_bytes()));

    run(xargo().args(&["init", "--vcs", "none", "--name", TARGET]).current_dir(td));
    try!(try!(OpenOptions::new().truncate(true).write(true).open(td.join("src/lib.rs")))
             .write_all(LIB_RS));
    try!(fs::create_dir(td.join(".cargo")));
    try!(try!(File::create(td.join(".cargo/config")))
             .write_all(CONFIG.replace("{}", TARGET).as_bytes()));
    run(xargo().arg("build").current_dir(td));

    for krate in CRATES {
        assert!(exists_rlib(krate, TARGET));
    }

    cleanup(TARGET);
}

// Check that `--targer foo` overrides the default target in .cargo/config
#[test]
fn override_cargo_config() {
    const CONFIG: &'static [u8] = b"[build]\ntarget = 'dummy'";
    const TARGET: &'static str = "__override_cargo_config";

    let td = try!(TempDir::new("xargo"));
    let td = &td.path();
    try!(try!(File::create(td.join(format!("{}.json", TARGET)))).write_all(CUSTOM_JSON.as_bytes()));

    run(xargo().args(&["init", "--vcs", "none", "--name", TARGET]).current_dir(td));
    try!(try!(OpenOptions::new().truncate(true).write(true).open(td.join("src/lib.rs")))
             .write_all(LIB_RS));
    try!(fs::create_dir(td.join(".cargo")));
    try!(try!(File::create(td.join(".cargo/config"))).write_all(CONFIG));
    run(xargo().args(&["build", "--target", TARGET]).current_dir(td));

    for krate in CRATES {
        assert!(exists_rlib(krate, TARGET));
    }

    cleanup(TARGET);
}

// Check that the rustflags in .cargo/config are used to build the sysroot
#[test]
fn rustflags_in_cargo_config() {
    const TARGET: &'static str = "__rustflags_in_cargo_config";
    const CARGO_CONFIG: &'static str = "[build]\nrustflags = ['--cfg', 'xargo']";

    let td = try!(TempDir::new("xargo"));
    let td = &td.path();
    try!(try!(File::create(td.join(format!("{}.json", TARGET)))).write_all(CUSTOM_JSON.as_bytes()));
    try!(fs::create_dir(td.join(".cargo")));
    try!(try!(File::create(td.join(".cargo/config"))).write_all(CARGO_CONFIG.as_bytes()));

    run(xargo().args(&["init", "--vcs", "none", "--name", TARGET]).current_dir(td));
    try!(try!(OpenOptions::new().truncate(true).write(true).open(td.join("src/lib.rs")))
             .write_all(LIB_RS));
    let output = try!(xargo()
                          .args(&["build", "--target", TARGET, "--verbose"])
                          .current_dir(td)
                          .output());

    assert!(output.status.success());

    for krate in CRATES {
        assert!(exists_rlib(krate, TARGET));
    }

    for line in try!(String::from_utf8(output.stdout)).lines() {
        if line.contains("Running") && line.contains("rustc") && line.contains(TARGET) {
            assert!(line.contains("--cfg xargo"));
        }
    }

    cleanup(TARGET);
}

// Check that the sysroot is rebuilt when RUSTFLAGS is modified
#[test]
fn rebuild_on_modified_rustflags() {
    const TARGET: &'static str = "__rebuild_on_modified_rustflags";

    let td = try!(TempDir::new("xargo"));
    let td = &td.path();
    try!(try!(File::create(td.join(format!("{}.json", TARGET)))).write_all(CUSTOM_JSON.as_bytes()));

    run(xargo().args(&["init", "--vcs", "none", "--name", TARGET]).current_dir(td));
    try!(try!(OpenOptions::new().truncate(true).write(true).open(td.join("src/lib.rs")))
             .write_all(LIB_RS));
    run(xargo()
            .args(&["build", "--target", TARGET, "--verbose"])
            .current_dir(td));

    for krate in CRATES {
        assert!(exists_rlib(krate, TARGET));
    }

    let output = try!(xargo()
                          .args(&["build", "--target", TARGET])
                          .current_dir(td)
                          .env("RUSTFLAGS", "--cfg xargo")
                          .output());

    assert!(output.status.success());

    let stdout = try!(String::from_utf8(output.stdout));

    for krate in CRATES {
        assert!(stdout.lines().any(|l| l.contains("Compiling") && l.contains(krate)));
        assert!(exists_rlib(krate, TARGET));
    }

    cleanup(TARGET);
}
<commit_msg>test that calling `xargo build` twice doesn't trigger a sysroot rebuild<commit_after>extern crate tempdir;

use std::env;
use std::fs::{self, File, OpenOptions};
use std::process::Command;
use std::io::Write;

use tempdir::TempDir;

macro_rules! try {
    ($e:expr) => {
        $e.unwrap_or_else(|e| panic!("{} with {}", stringify!($e), e))
    }
}

const CRATES: &'static [&'static str] = &["alloc", "collections", "core", "rand", "rustc_unicode"];
const LIB_RS: &'static [u8] = b"#![no_std]";

const CUSTOM_JSON: &'static str = r#"
    {
      "arch": "arm",
      "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64",
      "llvm-target": "thumbv7m-none-eabi",
      "os": "none",
      "target-endian": "little",
      "target-pointer-width": "32"
    }
"#;

fn xargo() -> Command {
    let mut path = try!(env::current_exe());
    path.pop();
    path.push("xargo");
    Command::new(path)
}

fn run(cmd: &mut Command) {
    println!("running: {:?}", cmd);
    let output = try!(cmd.output());
    if !output.status.success() {
        println!("--- stdout:\n{}", String::from_utf8_lossy(&output.stdout));
        println!("--- stderr:\n{}", String::from_utf8_lossy(&output.stderr));
        panic!("expected success, got: {}", output.status);
    }
}

fn exists_rlib(krate: &str, target: &str) -> bool {
    let home = env::home_dir().unwrap();

    for entry in try!(fs::read_dir(home.join(format!(".xargo/lib/rustlib/{}/lib", target)))) {
        let path = &try!(entry).path();

        if path.is_file() && path.extension().and_then(|e| e.to_str()) == Some("rlib") &&
           path.file_stem()
               .and_then(|f| f.to_str())
               .map(|s| s.starts_with(&format!("lib{}", krate))) == Some(true) {
            return true;
        }
    }

    false
}

fn cleanup(target: &str) {
    try!(fs::remove_dir_all(env::home_dir()
                                .unwrap()
                                .join(format!(".xargo/lib/rustlib/{}", target))));
}

#[test]
fn simple() {
    const TARGET: &'static str = "__simple";

    let td = try!(TempDir::new("xargo"));
    let td = &td.path();
    try!(try!(File::create(td.join(format!("{}.json", TARGET)))).write_all(CUSTOM_JSON.as_bytes()));

    run(xargo().args(&["init", "--vcs", "none", "--name", TARGET]).current_dir(td));
    try!(try!(OpenOptions::new().truncate(true).write(true).open(td.join("src/lib.rs")))
             .write_all(LIB_RS));
    run(xargo().args(&["build", "--target", TARGET]).current_dir(td));

    for krate in CRATES {
        assert!(exists_rlib(krate, TARGET));
    }

    cleanup(TARGET);
}

// Calling `xargo build` twice shouldn't trigger a sysroot rebuild
// The only case the sysroot would have to be rebuild is when the source is updated but that
// shouldn't happen when running this test suite.
#[test]
fn twice() {
    const TARGET: &'static str = "__twice";

    let td = try!(TempDir::new("xargo"));
    let td = &td.path();
    try!(try!(File::create(td.join(format!("{}.json", TARGET)))).write_all(CUSTOM_JSON.as_bytes()));

    run(xargo().args(&["init", "--vcs", "none", "--name", TARGET]).current_dir(td));
    try!(try!(OpenOptions::new().truncate(true).write(true).open(td.join("src/lib.rs")))
         .write_all(LIB_RS));
    run(xargo().args(&["build", "--target", TARGET]).current_dir(td));

    let output = try!(xargo().args(&["build", "--target", TARGET]).current_dir(td).output());

    assert!(output.status.success());

    assert!(try!(String::from_utf8(output.stdout)).lines().all(|l| !l.contains("Compiling")));

    cleanup(TARGET);
}

// Check that `xargo build` builds a sysroot for the default target in .cargo/config
#[test]
fn cargo_config() {
    const CONFIG: &'static str = "[build]\ntarget = '{}'";
    const TARGET: &'static str = "__cargo_config";

    let td = try!(TempDir::new("xargo"));
    let td = &td.path();
    try!(try!(File::create(td.join(format!("{}.json", TARGET)))).write_all(CUSTOM_JSON.as_bytes()));

    run(xargo().args(&["init", "--vcs", "none", "--name", TARGET]).current_dir(td));
    try!(try!(OpenOptions::new().truncate(true).write(true).open(td.join("src/lib.rs")))
             .write_all(LIB_RS));
    try!(fs::create_dir(td.join(".cargo")));
    try!(try!(File::create(td.join(".cargo/config")))
             .write_all(CONFIG.replace("{}", TARGET).as_bytes()));
    run(xargo().arg("build").current_dir(td));

    for krate in CRATES {
        assert!(exists_rlib(krate, TARGET));
    }

    cleanup(TARGET);
}

// Check that `--targer foo` overrides the default target in .cargo/config
#[test]
fn override_cargo_config() {
    const CONFIG: &'static [u8] = b"[build]\ntarget = 'dummy'";
    const TARGET: &'static str = "__override_cargo_config";

    let td = try!(TempDir::new("xargo"));
    let td = &td.path();
    try!(try!(File::create(td.join(format!("{}.json", TARGET)))).write_all(CUSTOM_JSON.as_bytes()));

    run(xargo().args(&["init", "--vcs", "none", "--name", TARGET]).current_dir(td));
    try!(try!(OpenOptions::new().truncate(true).write(true).open(td.join("src/lib.rs")))
             .write_all(LIB_RS));
    try!(fs::create_dir(td.join(".cargo")));
    try!(try!(File::create(td.join(".cargo/config"))).write_all(CONFIG));
    run(xargo().args(&["build", "--target", TARGET]).current_dir(td));

    for krate in CRATES {
        assert!(exists_rlib(krate, TARGET));
    }

    cleanup(TARGET);
}

// Check that the rustflags in .cargo/config are used to build the sysroot
#[test]
fn rustflags_in_cargo_config() {
    const TARGET: &'static str = "__rustflags_in_cargo_config";
    const CARGO_CONFIG: &'static str = "[build]\nrustflags = ['--cfg', 'xargo']";

    let td = try!(TempDir::new("xargo"));
    let td = &td.path();
    try!(try!(File::create(td.join(format!("{}.json", TARGET)))).write_all(CUSTOM_JSON.as_bytes()));
    try!(fs::create_dir(td.join(".cargo")));
    try!(try!(File::create(td.join(".cargo/config"))).write_all(CARGO_CONFIG.as_bytes()));

    run(xargo().args(&["init", "--vcs", "none", "--name", TARGET]).current_dir(td));
    try!(try!(OpenOptions::new().truncate(true).write(true).open(td.join("src/lib.rs")))
             .write_all(LIB_RS));
    let output = try!(xargo()
                          .args(&["build", "--target", TARGET, "--verbose"])
                          .current_dir(td)
                          .output());

    assert!(output.status.success());

    for krate in CRATES {
        assert!(exists_rlib(krate, TARGET));
    }

    for line in try!(String::from_utf8(output.stdout)).lines() {
        if line.contains("Running") && line.contains("rustc") && line.contains(TARGET) {
            assert!(line.contains("--cfg xargo"));
        }
    }

    cleanup(TARGET);
}

// Check that the sysroot is rebuilt when RUSTFLAGS is modified
#[test]
fn rebuild_on_modified_rustflags() {
    const TARGET: &'static str = "__rebuild_on_modified_rustflags";

    let td = try!(TempDir::new("xargo"));
    let td = &td.path();
    try!(try!(File::create(td.join(format!("{}.json", TARGET)))).write_all(CUSTOM_JSON.as_bytes()));

    run(xargo().args(&["init", "--vcs", "none", "--name", TARGET]).current_dir(td));
    try!(try!(OpenOptions::new().truncate(true).write(true).open(td.join("src/lib.rs")))
             .write_all(LIB_RS));
    run(xargo()
            .args(&["build", "--target", TARGET, "--verbose"])
            .current_dir(td));

    for krate in CRATES {
        assert!(exists_rlib(krate, TARGET));
    }

    let output = try!(xargo()
                          .args(&["build", "--target", TARGET])
                          .current_dir(td)
                          .env("RUSTFLAGS", "--cfg xargo")
                          .output());

    assert!(output.status.success());

    let stdout = try!(String::from_utf8(output.stdout));

    for krate in CRATES {
        assert!(stdout.lines().any(|l| l.contains("Compiling") && l.contains(krate)));
        assert!(exists_rlib(krate, TARGET));
    }

    cleanup(TARGET);
}
<|endoftext|>


<commit_before>extern crate mach;
extern crate glium;

use std;
use std::rc::Rc;
use std::mem;
use std::collections::HashMap;

use self::glium::backend::glutin_backend::GlutinFacade;

use support::{SceneEnv, Instance, InstanceFactory, Normal, PolygonModel, Vertex};

pub struct ExamplesRenderer {
    program: glium::Program,
    cube: Rc<PolygonModel>,
    instances: HashMap<mach::ID, Instance>,
    factory: InstanceFactory,
}

impl ExamplesRenderer {
    pub fn new(display: &GlutinFacade) -> Result<ExamplesRenderer, String> {
        let program = try!(
            glium::Program::from_source(
                display,
                include_str!("shaders/foreground.vert.glsl"),
                include_str!("shaders/foreground.frag.glsl"),
                None,
            ).map_err(|err| format!("{}", err))
        );

        let cube = {
            let vertices: [Vertex; 8] = [
                Vertex { position: (-1.0, -1.0, -1.0) },
                Vertex { position: ( 1.0, -1.0, -1.0) },
                Vertex { position: ( 1.0,  1.0, -1.0) },
                Vertex { position: (-1.0,  1.0, -1.0) },
                Vertex { position: (-1.0, -1.0,  1.0) },
                Vertex { position: ( 1.0, -1.0,  1.0) },
                Vertex { position: ( 1.0,  1.0,  1.0) },
                Vertex { position: (-1.0,  1.0,  1.0) },
            ];

            let normals: [Normal; 8] = [
                Normal { normal: (-1.0, -1.0, -1.0) },
                Normal { normal: ( 1.0, -1.0, -1.0) },
                Normal { normal: ( 1.0,  1.0, -1.0) },
                Normal { normal: (-1.0,  1.0, -1.0) },
                Normal { normal: (-1.0, -1.0,  1.0) },
                Normal { normal: ( 1.0, -1.0,  1.0) },
                Normal { normal: ( 1.0,  1.0,  1.0) },
                Normal { normal: (-1.0,  1.0,  1.0) },
            ];

            let indices: [u16; 36] = [
                0, 5, 1,
                0, 4, 5,
                3, 6, 7,
                3, 2, 6,
                1, 6, 2,
                1, 5, 6,
                0, 3, 7,
                0, 7, 4,
                0, 2, 3,
                0, 1, 2,
                4, 6, 5,
                4, 7, 6,
            ];

            let vertex_buffer = glium::VertexBuffer::new(display, &vertices).unwrap();
            let normal_buffer = glium::VertexBuffer::new(display, &normals).unwrap();
            let indices = glium::IndexBuffer::new(display, glium::index::PrimitiveType::TrianglesList, &indices).unwrap();

            PolygonModel {
                vertices: vertex_buffer,
                normals: normal_buffer,
                indices: indices,
            }
        };

        Ok(ExamplesRenderer {
            instances: HashMap::new(),
            cube: Rc::new(cube),
            program: program,
            factory: InstanceFactory::new(),
        })
    }

    pub fn render<S: glium::Surface>(&mut self, surface: &mut S, world: &mach::World, env: &SceneEnv) -> Result<(), String> {
        surface.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0);

        let mut old_instances = HashMap::new();

        std::mem::swap(&mut old_instances, &mut self.instances);

        for body in world.bodies_iter() {
            if let Some(instance) = old_instances.remove(&body.id()) {
                self.render_and_save(surface, instance, body.state().transform(), env);
            } else {
                let instance = self.generate_new_instance(body.id(), body.shape());

                self.render_and_save(surface, instance, body.state().transform(), env);
            }
        }

        return Ok(());
    }

    fn render_and_save<S: glium::Surface>(&mut self, surface: &mut S, instance: Instance, transform: &mach::maths::Transform, env: &SceneEnv) {
        let model_matrix: [[f32; 4]; 4] = [
            [instance.scale.0, 0.0, 0.0, 0.0],
            [0.0, instance.scale.1, 0.0, 0.0],
            [0.0, 0.0, instance.scale.2, 0.0],
            [transform.translation().x, transform.translation().y, transform.translation().z, 1.0],
        ];

        let view_matrix: [[f32; 4]; 4] = unsafe {
            mem::transmute(env.camera.view_matrix())
        };

        surface.draw(
            (&instance.polygon_model.vertices, &instance.polygon_model.normals),
            &instance.polygon_model.indices,
            &self.program,
            &uniform! {
                projection_matrix: *env.camera.projection_matrix(),
                view_matrix: view_matrix,
                model_matrix: model_matrix,
                light_direction: [1.0, 2.0, 1.0f32],
                surface_color: instance.color.clone(),
            },
            &glium::DrawParameters {
                depth: glium::Depth {
                    test: glium::draw_parameters::DepthTest::IfLess,
                    write: true,
                    .. Default::default()
                },
                .. Default::default()
            },
        ).unwrap();

        self.instances.insert(instance.id, instance);
    }

    fn generate_new_instance(&mut self, id: mach::ID, shape: &mach::Shape) -> Instance {
        match shape.spec() {
            mach::ShapeSpec::Cuboid { width, depth, height} => {
                self.factory.generate(id, (width, depth, height), self.cube.clone())
            },

            _ => unimplemented!(),
        }
    }
}
<commit_msg>fixed failing compilation with high_precision enabled<commit_after>extern crate mach;
extern crate glium;

use std;
use std::rc::Rc;
use std::mem;
use std::collections::HashMap;

use self::glium::backend::glutin_backend::GlutinFacade;

use support::{SceneEnv, Instance, InstanceFactory, Normal, PolygonModel, Vertex};

pub struct ExamplesRenderer {
    program: glium::Program,
    cube: Rc<PolygonModel>,
    instances: HashMap<mach::ID, Instance>,
    factory: InstanceFactory,
}

impl ExamplesRenderer {
    pub fn new(display: &GlutinFacade) -> Result<ExamplesRenderer, String> {
        let program = try!(
            glium::Program::from_source(
                display,
                include_str!("shaders/foreground.vert.glsl"),
                include_str!("shaders/foreground.frag.glsl"),
                None,
            ).map_err(|err| format!("{}", err))
        );

        let cube = {
            let vertices: [Vertex; 8] = [
                Vertex { position: (-1.0, -1.0, -1.0) },
                Vertex { position: ( 1.0, -1.0, -1.0) },
                Vertex { position: ( 1.0,  1.0, -1.0) },
                Vertex { position: (-1.0,  1.0, -1.0) },
                Vertex { position: (-1.0, -1.0,  1.0) },
                Vertex { position: ( 1.0, -1.0,  1.0) },
                Vertex { position: ( 1.0,  1.0,  1.0) },
                Vertex { position: (-1.0,  1.0,  1.0) },
            ];

            let normals: [Normal; 8] = [
                Normal { normal: (-1.0, -1.0, -1.0) },
                Normal { normal: ( 1.0, -1.0, -1.0) },
                Normal { normal: ( 1.0,  1.0, -1.0) },
                Normal { normal: (-1.0,  1.0, -1.0) },
                Normal { normal: (-1.0, -1.0,  1.0) },
                Normal { normal: ( 1.0, -1.0,  1.0) },
                Normal { normal: ( 1.0,  1.0,  1.0) },
                Normal { normal: (-1.0,  1.0,  1.0) },
            ];

            let indices: [u16; 36] = [
                0, 5, 1,
                0, 4, 5,
                3, 6, 7,
                3, 2, 6,
                1, 6, 2,
                1, 5, 6,
                0, 3, 7,
                0, 7, 4,
                0, 2, 3,
                0, 1, 2,
                4, 6, 5,
                4, 7, 6,
            ];

            let vertex_buffer = glium::VertexBuffer::new(display, &vertices).unwrap();
            let normal_buffer = glium::VertexBuffer::new(display, &normals).unwrap();
            let indices = glium::IndexBuffer::new(display, glium::index::PrimitiveType::TrianglesList, &indices).unwrap();

            PolygonModel {
                vertices: vertex_buffer,
                normals: normal_buffer,
                indices: indices,
            }
        };

        Ok(ExamplesRenderer {
            instances: HashMap::new(),
            cube: Rc::new(cube),
            program: program,
            factory: InstanceFactory::new(),
        })
    }

    pub fn render<S: glium::Surface>(&mut self, surface: &mut S, world: &mach::World, env: &SceneEnv) -> Result<(), String> {
        surface.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0);

        let mut old_instances = HashMap::new();

        std::mem::swap(&mut old_instances, &mut self.instances);

        for body in world.bodies_iter() {
            if let Some(instance) = old_instances.remove(&body.id()) {
                self.render_and_save(surface, instance, body.state().transform(), env);
            } else {
                let instance = self.generate_new_instance(body.id(), body.shape());

                self.render_and_save(surface, instance, body.state().transform(), env);
            }
        }

        return Ok(());
    }

    fn render_and_save<S: glium::Surface>(&mut self, surface: &mut S, instance: Instance, transform: &mach::maths::Transform, env: &SceneEnv) {
        let model_matrix: [[f32; 4]; 4] = [
            [instance.scale.0, 0.0, 0.0, 0.0],
            [0.0, instance.scale.1, 0.0, 0.0],
            [0.0, 0.0, instance.scale.2, 0.0],
            [transform.translation().x as f32, transform.translation().y as f32, transform.translation().z as f32, 1.0],
        ];

        let view_matrix: [[f32; 4]; 4] = unsafe {
            mem::transmute(env.camera.view_matrix())
        };

        surface.draw(
            (&instance.polygon_model.vertices, &instance.polygon_model.normals),
            &instance.polygon_model.indices,
            &self.program,
            &uniform! {
                projection_matrix: *env.camera.projection_matrix(),
                view_matrix: view_matrix,
                model_matrix: model_matrix,
                light_direction: [1.0, 2.0, 1.0f32],
                surface_color: instance.color.clone(),
            },
            &glium::DrawParameters {
                depth: glium::Depth {
                    test: glium::draw_parameters::DepthTest::IfLess,
                    write: true,
                    .. Default::default()
                },
                .. Default::default()
            },
        ).unwrap();

        self.instances.insert(instance.id, instance);
    }

    fn generate_new_instance(&mut self, id: mach::ID, shape: &mach::Shape) -> Instance {
        match shape.spec() {
            mach::ShapeSpec::Cuboid { width, depth, height} => {
                self.factory.generate(id, (width as f32, depth as f32, height as f32), self.cube.clone())
            },

            _ => unimplemented!(),
        }
    }
}
<|endoftext|>


<commit_before>#![warn(bad_style,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, unused_typecasts)]

extern crate curl;
extern crate "oauth-client" as oauth;

use std::borrow::IntoCow;
use std::collections::HashMap;
use std::str;
use std::string::CowString;
use std::rand::{self, Rng};
use curl::http;
use curl::http::handle::Method;
use oauth::Token;

mod api {
    pub const REQUEST_TOKEN: &'static str = "http://term.ie/oauth/example/request_token.php";
    pub const ACCESS_TOKEN: &'static str = "http://term.ie/oauth/example/access_token.php";
    pub const ECHO: &'static str = "http://term.ie/oauth/example/echo_api.php";
}

fn split_query<'a>(query: &'a str) -> HashMap<CowString<'a>, CowString<'a>> {
    let mut param = HashMap::new();
    for q in query.split('&') {
        let mut s = q.splitn(2, '=');
        let k = s.next().unwrap();
        let v = s.next().unwrap();
        let _ = param.insert(k.into_cow(), v.into_cow());
    }
    param
}

fn get_request_token(consumer: &Token) -> Token<'static> {
    let header = oauth::authorization_header(Method::Get, api::REQUEST_TOKEN, consumer, None, None);
    let resp = http::handle()
        .get(api::REQUEST_TOKEN)
        .header("Authorization", header.as_slice())
        .exec()
        .unwrap();
    let resp = str::from_utf8(resp.get_body())
        .unwrap()
        .to_string();
    println!("get_request_token response: {:?}", resp);
    let param = split_query(resp.as_slice());
    Token::new(param.get("oauth_token").unwrap().to_string(),
               param.get("oauth_token_secret").unwrap().to_string())
}

fn get_access_token(consumer: &Token, request: &Token) -> Token<'static> {
    let header = oauth::authorization_header(Method::Get, api::ACCESS_TOKEN, consumer, Some(request), None);
    let resp = http::handle()
        .get(api::ACCESS_TOKEN)
        .header("Authorization", header.as_slice())
        .exec()
        .unwrap();
    let resp = str::from_utf8(resp.get_body())
        .unwrap()
        .to_string();
    println!("get_access_token response: {:?}", resp);
    let param = split_query(resp.as_slice());
    Token::new(param.get("oauth_token").unwrap().to_string(),
               param.get("oauth_token_secret").unwrap().to_string())
}

fn echo(consumer: &Token, access: &Token) {
    let header = oauth::authorization_header(Method::Post, api::ECHO, consumer, Some(access), None);

    let mut rng = rand::thread_rng();
    let req_body = rng.gen_ascii_chars().take(100).collect::<String>();
    let resp = http::handle()
        .post(api::ECHO, req_body.as_slice())
        .header("Authorization", header.as_slice())
        .exec()
        .unwrap();
    let resp = str::from_utf8(resp.get_body()).unwrap();
    println!("echo response: {:?}", resp);
    let resp_body = resp.as_slice();
    assert_eq!("", resp_body);
}

fn main() {
    let consumer = Token::new("key", "secret");
    println!("consumer: {:?}", consumer);

    let request = get_request_token(&consumer);
    println!("request: {:?}", request);

    let access = get_access_token(&consumer, &request);
    println!("access: {:?}", access);

    echo(&consumer, &access);

    println!("OK");
}

<commit_msg>fix example warnings<commit_after>#![warn(bad_style,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, unused_typecasts)]

#![feature(core)]

extern crate curl;
extern crate "oauth-client" as oauth;
extern crate rand;

use std::borrow::IntoCow;
use std::collections::HashMap;
use std::str;
use std::string::CowString;
use curl::http;
use curl::http::handle::Method;
use oauth::Token;
use rand::Rng;

mod api {
    pub const REQUEST_TOKEN: &'static str = "http://term.ie/oauth/example/request_token.php";
    pub const ACCESS_TOKEN: &'static str = "http://term.ie/oauth/example/access_token.php";
    pub const ECHO: &'static str = "http://term.ie/oauth/example/echo_api.php";
}

fn split_query<'a>(query: &'a str) -> HashMap<CowString<'a>, CowString<'a>> {
    let mut param = HashMap::new();
    for q in query.split('&') {
        let mut s = q.splitn(2, '=');
        let k = s.next().unwrap();
        let v = s.next().unwrap();
        let _ = param.insert(k.into_cow(), v.into_cow());
    }
    param
}

fn get_request_token(consumer: &Token) -> Token<'static> {
    let header = oauth::authorization_header(Method::Get, api::REQUEST_TOKEN, consumer, None, None);
    let resp = http::handle()
        .get(api::REQUEST_TOKEN)
        .header("Authorization", header.as_slice())
        .exec()
        .unwrap();
    let resp = str::from_utf8(resp.get_body())
        .unwrap()
        .to_string();
    println!("get_request_token response: {:?}", resp);
    let param = split_query(resp.as_slice());
    Token::new(param.get("oauth_token").unwrap().to_string(),
               param.get("oauth_token_secret").unwrap().to_string())
}

fn get_access_token(consumer: &Token, request: &Token) -> Token<'static> {
    let header = oauth::authorization_header(Method::Get, api::ACCESS_TOKEN, consumer, Some(request), None);
    let resp = http::handle()
        .get(api::ACCESS_TOKEN)
        .header("Authorization", header.as_slice())
        .exec()
        .unwrap();
    let resp = str::from_utf8(resp.get_body())
        .unwrap()
        .to_string();
    println!("get_access_token response: {:?}", resp);
    let param = split_query(resp.as_slice());
    Token::new(param.get("oauth_token").unwrap().to_string(),
               param.get("oauth_token_secret").unwrap().to_string())
}

fn echo(consumer: &Token, access: &Token) {
    let header = oauth::authorization_header(Method::Post, api::ECHO, consumer, Some(access), None);

    let mut rng = rand::thread_rng();
    let req_body = rng.gen_ascii_chars().take(100).collect::<String>();
    let resp = http::handle()
        .post(api::ECHO, req_body.as_slice())
        .header("Authorization", header.as_slice())
        .exec()
        .unwrap();
    let resp = str::from_utf8(resp.get_body()).unwrap();
    println!("echo response: {:?}", resp);
    let resp_body = resp.as_slice();
    assert_eq!("", resp_body);
}

fn main() {
    let consumer = Token::new("key", "secret");
    println!("consumer: {:?}", consumer);

    let request = get_request_token(&consumer);
    println!("request: {:?}", request);

    let access = get_access_token(&consumer, &request);
    println!("access: {:?}", access);

    echo(&consumer, &access);

    println!("OK");
}

<|endoftext|>


<commit_before>use curl::easy::Easy;

use itertools::Itertools;

use futures::{Future, Then};
use futures::future::{err, join_all};

use serde_json;

use tokio_core::reactor::Core;
use tokio_curl::Session;

use std::collections::HashSet;
use std::io::{self, Write};
use std::error::Error;

use constants;
use ::SearchResult;

pub fn search(packages: &HashSet<&str>) -> Vec<String> {
    let mut results = Vec::new();
    let mut rpc = Easy::new();
    let url = constants::AUR_RPC_URL.to_owned() + constants::AUR_RPC_SEARCH_FMT + constants::AUR_RPC_SEARCH_ARG;
    let raw_results = make_requests(&url, &packages);
}

fn make_requests(url: &str, packages: &HashSet<&str>) -> Vec<Result<SearchResult, String>> {
    // TODO: Figure out a better way to do this, i.e. not requiring that the error be passed as a
    // string.
    let make_error = |package, e| format!("Error searching for \"{}\": {}", package, e);
    let mut lp = Core::new().unwrap();
    let session = Session::new(lp.handle());
    let requests = packages.iter().map(move |package| {
        // I think we need this to be owned because of the error messages. Also, it's weird that we
        // get a &&str here - it makes sense, but implies that there might be a cleaner/more
        // idiomatic way to do things
        // TODO: Find a better way to do error messages without requiring creating an owned copy
        let package = String::from(*package);
        let mut search_req = Easy::new();
        let mut search_data = Vec::new();
        match search_req.url(&format!("{}{}", url, package)) {
            Ok(_)   => {
                search_req.write_function(|data| {
                    io::stdout().write_all(data.clone()).unwrap();
                    search_data.extend_from_slice(data);
                    Ok(search_data.len())
                }).unwrap();
                session.perform(search_req).then(|result| {
                    result.map(|_| serde_json::from_slice(&search_data).map_err(|e| make_error(package, e.description())))
                        // I don't really like losing the error like this.
                        // TODO: Unify the error types here in a better way
                }).map_err(|e| make_error(package, e.description())).boxed()
            },
            Err(e)  => err(make_error(package, e.description())).boxed()
        }})
    .collect();
    // TODO: Figure out a way to not make the failure of one future make all the rest fail. This
    // will involve not using join(), but at this time there doesn't seem to be a great alternative
    // in futures-rs
    lp.run(join_all(requests)).unwrap()
}
<commit_msg>WIP AUR Search: I lied in the last commit, but it really does compile now. Kinda messy/there are some ugly bits I want to think more about later<commit_after>use curl::easy::Easy;

use itertools::Itertools;

use futures::{Future, Then, BoxFuture};
use futures::future::{err, join_all};

use serde_json;

use tokio_core::reactor::Core;
use tokio_curl::Session;

use std::collections::HashSet;
use std::io::{self, Write};
use std::error::Error;
use std::sync::{Mutex, Arc};

use constants;
use ::SearchResult;

pub fn search(packages: &HashSet<&str>) -> Vec<String> {
    let mut rpc = Easy::new();
    let url = constants::AUR_RPC_URL.to_owned() + constants::AUR_RPC_SEARCH_FMT + constants::AUR_RPC_SEARCH_ARG;
    let raw_results = make_requests(&url, packages);
    Vec::new()
}

fn make_requests(url: &str, packages: &HashSet<&str>) -> Vec<Result<SearchResult, String>> {
    let mut lp = Core::new().unwrap();
    let session = Session::new(lp.handle());
    // TODO: Think about a way to not make the failure of one future make all the rest fail. This
    // will involve not using join_all(), but at this time there doesn't seem to be a great alternative
    // in futures-rs
    lp.run(join_all(packages.iter().map(move |package_name| {
        // I think we need this to be owned because of the error messages. Also, it's weird that we
        // get a &&str here - it makes sense, but implies that there might be a cleaner/more
        // idiomatic way to do things
        // TODO: Find a better way to do error messages without requiring creating an owned copy
        let package = String::from(*package_name);
        let mut search_req = Easy::new();
        let search_data = Arc::new(Mutex::new(Vec::new()));
        let write_handle = search_data.clone();
        match search_req.url(&format!("{}{}", url, package)) {
            Ok(_)   => {
                search_req.write_function(move |data| {
                    io::stdout().write_all(data.clone()).unwrap();
                    write_handle.lock().unwrap().extend_from_slice(data);
                    Ok(data.len())
                }).unwrap();
                // TODO: This is bad and there is presumably a better way to do it
                let p = package.clone();
                session.perform(search_req).then(move |result| {
                    result.map(|_|
                               serde_json::from_slice(
                                   &search_data.lock().unwrap()
                                )
                               .map_err(|e| format!("{}: {:?}", p, e)))
                        // I don't really like losing the error like this.
                        // TODO: Unify the error types here in a better way
                }).map_err(move |e| format!("{}: {:?}", package, e)).boxed()
            },
            Err(e)  => err(format!("{}: {:?}", package, e)).boxed()
        }}).collect::<Vec<_>>())).unwrap()
}
<|endoftext|>


<commit_before>use docopt::{self, Docopt, ArgvMap};

const USAGE: &'static str = "
mprovision
A tool that helps iOS developers to manage mobileprovision files.

Usage:
  mprovision list [--filter <text>] [--expires-in-days <days>] [<directory>]

Options:
  -h --help     Show this help message.
  --version     Show version.
";

pub fn parse<I, S>(args: I) -> Result<ArgvMap, docopt::Error>
    where I: IntoIterator<Item = S>,
          S: AsRef<str>
{
    Docopt::new(USAGE).and_then(|docopt| {
        docopt.argv(args).version(Some(format!("mprovision {}", version!()))).parse()
    })
}

#[cfg(test)]
mod tests {
    use super::*;
    use expectest::prelude::*;

    #[test]
    fn list_command() {
        expect!(parse(&["mprovision", "list"])).to(be_ok());
        expect!(parse(&["mprovision", "list", "."])).to(be_ok());
        expect!(parse(&["mprovision", "list", "--filter abc"])).to(be_ok());
        expect!(parse(&["mprovision", "list", "--filter abc", "."])).to(be_ok());
        expect!(parse(&["mprovision", "list", "--expires-in-days 0"])).to(be_ok());
        expect!(parse(&["mprovision", "list", "--expires-in-days 0", "."])).to(be_ok());
    }
}
<commit_msg>Move some types to cli module<commit_after>use docopt::{self, Docopt, ArgvMap};
use std::io::{self, Write};
use std::process;
use std::path::Path;
use std::error;
use std::result;
use std::fmt;
use mprovision as mp;

const USAGE: &'static str = "
mprovision
A tool that helps iOS developers to manage mobileprovision files.

Usage:
  mprovision list [--filter <text>] [--expires-in-days <days>] [<directory>]
  mprovision (-h | --help)
  mprovision --version

Options:
  -h --help     Show this help message.
  --version     Show version.
";

#[derive(Debug)]
pub enum Command {
    List,
}

pub type Result = result::Result<Command, Error>;

#[derive(Debug)]
pub enum Error {
    Lib(mp::Error),
    Docopt(docopt::Error),
    Custom(String),
}

impl Error {
    pub fn exit(&self) -> ! {
        match *self {
            Error::Docopt(ref e) => e.exit(),
            _ => {
                writeln!(&mut io::stderr(), "{}", self).unwrap();
                process::exit(1);
            }
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Lib(ref e) => e.description(),
            Error::Docopt(ref e) => e.description(),
            Error::Custom(ref e) => e,
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Lib(ref e) => Some(e),
            Error::Docopt(ref e) => Some(e),
            Error::Custom(_) => None,
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Lib(ref e) => error::Error::description(e).fmt(f),
            Error::Docopt(ref e) => error::Error::description(e).fmt(f),
            Error::Custom(ref e) => e.fmt(f),
        }
    }
}

impl From<mp::Error> for Error {
    fn from(e: mp::Error) -> Self {
        Error::Lib(e)
    }
}

impl From<docopt::Error> for Error {
    fn from(e: docopt::Error) -> Self {
        Error::Docopt(e)
    }
}

pub fn parse<I, S>(args: I) -> Result
    where I: IntoIterator<Item = S>,
          S: AsRef<str>
{
    let version = format!("mprovision {}", version!());
    let argv_map = Docopt::new(USAGE)?.argv(args).version(Some(version)).parse()?;
    Ok(Command::List)
}

#[cfg(test)]
mod tests {
    use super::*;
    use expectest::prelude::*;

    #[test]
    fn list_command() {
        expect!(parse(&["mprovision", "list"])).to(be_ok());
        expect!(parse(&["mprovision", "list", "."])).to(be_ok());
        expect!(parse(&["mprovision", "list", "--filter abc"])).to(be_ok());
        expect!(parse(&["mprovision", "list", "--filter abc", "."])).to(be_ok());
        expect!(parse(&["mprovision", "list", "--expires-in-days 0"])).to(be_ok());
        expect!(parse(&["mprovision", "list", "--expires-in-days 0", "."])).to(be_ok());
    }
}
<|endoftext|>


<commit_before>extern crate lz4;

use std::iter::FromIterator;
use std::env;
use std::fs::File;
use std::io::Result;
use std::io::Read;
use std::io::Write;
use std::path::Path;

fn main() {
    println!("LZ4 version: {}", lz4::version());
    let suffix = ".lz4";
    for arg in Vec::from_iter(env::args())[1..].iter() {
        if arg.ends_with(suffix) {
            decompress(&Path::new(arg),
                       &Path::new(&arg[0..arg.len() - suffix.len()]))
                .unwrap();
        } else {
            compress(&Path::new(arg), &Path::new(&(arg.to_string() + suffix))).unwrap();
        }
    }
}

fn compress(src: &Path, dst: &Path) -> Result<()> {
    println!("Compressing: {:?} -> {:?}", src, dst);
    let mut fi = try!(File::open(src));
    let mut fo = try!(lz4::EncoderBuilder::new().build(try!(File::create(dst))));
    try!(copy(&mut fi, &mut fo));
    match fo.finish() {
        (_, result) => result,
    }
}

fn decompress(src: &Path, dst: &Path) -> Result<()> {
    println!("Decompressing: {:?} -> {:?}", src, dst);
    let mut fi = try!(lz4::Decoder::new(try!(File::open(src))));
    let mut fo = try!(File::create(dst));
    copy(&mut fi, &mut fo)
}

fn copy(src: &mut Read, dst: &mut Write) -> Result<()> {
    let mut buffer: [u8; 1024] = [0; 1024];
    loop {
        let len = try!(src.read(&mut buffer));
        if len == 0 {
            break;
        }
        try!(dst.write_all(&buffer[0..len]));
    }
    Ok(())
}

struct Wrapper<W: Write> {
    w: W,
    written_size: usize,
}

impl<W: Write> Wrapper<W> {
    pub fn get_written_size(&self) -> usize {
        self.written_size
    }
}

impl<W: Write> Write for Wrapper<W> {
    fn write(&mut self, buffer: &[u8]) -> Result<usize> {
        self.written_size += buffer.len();
        self.w.write(buffer)
    }

    fn flush(&mut self) -> Result<()> {
        self.w.flush()
    }
}
<commit_msg>Remove unused code<commit_after>extern crate lz4;

use std::iter::FromIterator;
use std::env;
use std::fs::File;
use std::io::Result;
use std::io::Read;
use std::io::Write;
use std::path::Path;

fn main() {
    println!("LZ4 version: {}", lz4::version());
    let suffix = ".lz4";
    for arg in Vec::from_iter(env::args())[1..].iter() {
        if arg.ends_with(suffix) {
            decompress(&Path::new(arg),
                       &Path::new(&arg[0..arg.len() - suffix.len()]))
                .unwrap();
        } else {
            compress(&Path::new(arg), &Path::new(&(arg.to_string() + suffix))).unwrap();
        }
    }
}

fn compress(src: &Path, dst: &Path) -> Result<()> {
    println!("Compressing: {:?} -> {:?}", src, dst);
    let mut fi = try!(File::open(src));
    let mut fo = try!(lz4::EncoderBuilder::new().build(try!(File::create(dst))));
    try!(copy(&mut fi, &mut fo));
    match fo.finish() {
        (_, result) => result,
    }
}

fn decompress(src: &Path, dst: &Path) -> Result<()> {
    println!("Decompressing: {:?} -> {:?}", src, dst);
    let mut fi = try!(lz4::Decoder::new(try!(File::open(src))));
    let mut fo = try!(File::create(dst));
    copy(&mut fi, &mut fo)
}

fn copy(src: &mut Read, dst: &mut Write) -> Result<()> {
    let mut buffer: [u8; 1024] = [0; 1024];
    loop {
        let len = try!(src.read(&mut buffer));
        if len == 0 {
            break;
        }
        try!(dst.write_all(&buffer[0..len]));
    }
    Ok(())
}
<|endoftext|>


<commit_before>//! This module serves as the entry point into Xtensis's main binary.

// This file is part of Xtensis.

// This is the Xtensis text editor; it edits text.
// Copyright (C) 2016-2017  The Xtensis Developers

// This program is free software: you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.

// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see
// <http://www.gnu.org/licenses/>.

extern crate clap;
extern crate xtensis_core as xtensis;

#[macro_use]
extern crate slog;
extern crate slog_term;

use clap::{App, Arg, ArgMatches, SubCommand};
use xtensis::logging::init_logger;
use xtensis::utils::get_version;

fn retrieve_arguments() -> ArgMatches<'static> {
    App::new("xtensis-core")
        .version(get_version())
        .author("Dom Rodriguez <shymega@shymega.org.uk>")
        .about("Extensible editing: screw limits.")
        .arg(Arg::with_name("verbose")
            .short("v")
            .multiple(true)
            .required(false)
            .help("Set the level of logging verbosity"))
        .subcommand(SubCommand::with_name("spawn")
            .about("Spawn a new instance of xtensis-core.")
            .version(get_version())
            .author("Dom Rodriguez <shymega@shymega.org.uk>"))
        .get_matches()
}

fn main() {
    let cargs = retrieve_arguments();

    let logger = init_logger();

    if cargs.subcommand_matches("spawn").is_some() {
        info!(logger, "xtensis-core starting.. initialising ")
    }

    error!(logger, "This program is unable to start right now.");
}
<commit_msg>Rustfmt bin<commit_after>//! This module serves as the entry point into Xtensis's main binary.

// This file is part of Xtensis.

// This is the Xtensis text editor; it edits text.
// Copyright (C) 2016-2017  The Xtensis Developers

// This program is free software: you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.

// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see
// <http://www.gnu.org/licenses/>.

extern crate clap;
extern crate xtensis_core as xtensis;

#[macro_use]
extern crate slog;
extern crate slog_term;

use clap::{App, Arg, ArgMatches, SubCommand};
use xtensis::logging::init_logger;
use xtensis::utils::get_version;

fn retrieve_arguments() -> ArgMatches<'static> {
    App::new("xtensis-core")
        .version(get_version())
        .author("Dom Rodriguez <shymega@shymega.org.uk>")
        .about("Extensible editing: screw limits.")
        .arg(Arg::with_name("verbose")
                 .short("v")
                 .multiple(true)
                 .required(false)
                 .help("Set the level of logging verbosity"))
        .subcommand(SubCommand::with_name("spawn")
                        .about("Spawn a new instance of xtensis-core.")
                        .version(get_version())
                        .author("Dom Rodriguez <shymega@shymega.org.uk>"))
        .get_matches()
}

fn main() {
    let cargs = retrieve_arguments();

    let logger = init_logger();

    if cargs.subcommand_matches("spawn").is_some() {
        info!(logger, "xtensis-core starting.. initialising ")
    }

    error!(logger, "This program is unable to start right now.");
}
<|endoftext|>


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

use std::marker::PhantomData;
use std::mem;
use std::str::FromStr;

use specs::{
    Join,
    Read,
    ReadStorage,
    System,
    Write,
};

use xsecurelock_saver::engine::{
    components::{
        delete::Deleted,
        physics::{
            Mass,
            Position,
        },
    },
    resources::{
        draw::View,
        scene::SceneChange,
    },
};

use config::scoring::ScoringConfig;
use model::{Scenario, World};
use storage::Storage;
use worldgenerator::WorldGenerator;

use self::scoring_function::Expression;

mod scoring_function;

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(transparent)]
pub struct ScoringFunction(Expression);

impl ScoringFunction {
    /// Evaluate the expression given the scoring function inputs.
    pub fn eval(&self, tick: f64, total_mass: f64, mass_count: f64) -> f64 {
        self.0.eval(tick, total_mass, mass_count)
    }
}

impl FromStr for ScoringFunction {
    type Err = String;

    fn from_str(source: &str) -> Result<ScoringFunction, String> {
        source.parse().map(ScoringFunction)
    }
}

/// Resource for tracking the status of the currently active scene.
pub struct ActiveWorld {
    /// The world being scored.
    pub world: World,
    /// The parent of the world being scored.
    pub parent: Option<Scenario>,
    /// The score the world has received so far.
    pub cumulative_score: f64,
    /// The number of physics ticks that the world has been scored on so far.
    pub ticks_completed: u32,
}

impl Default for ActiveWorld {
    fn default() -> Self {
        ActiveWorld {
            world: World { planets: vec![] },
            parent: None,
            cumulative_score: 0.,
            ticks_completed: 0,
        }
    }
}

#[derive(Default)]
pub struct ScoreKeeper<T>(PhantomData<T>);

impl<'a, T> System<'a> for ScoreKeeper<T> where T: Storage + Default + Send + Sync + 'static {
    type SystemData = (
        Read<'a, ScoringConfig>,
        Read<'a, View>,
        Write<'a, ActiveWorld>,
        Write<'a, T>,
        Write<'a, SceneChange>,
        ReadStorage<'a, Position>,
        ReadStorage<'a, Mass>,
        ReadStorage<'a, Deleted>,
    );

    fn run(
        &mut self,
        (
            scoring,
            view,
            mut world_track,
            mut storage,
            mut scene_change,
            positions,
            masses,
            deleted,
        ): Self::SystemData,
    ) {
        if world_track.ticks_completed < scoring.scored_ticks {
            let vertical_half_extent = scoring.scored_area.height / 2.;
            let horizontal_half_extent = if scoring.scored_area.scale_width_by_aspect {
                // x / y = w / w_0; w_0 * x / y = w
                let aspect = view.size.x / view.size.y;
                scoring.scored_area.width * aspect
            } else {
                scoring.scored_area.width
            } / 2.;

            let mut mass_count = 0f64;
            let mut total_mass = 0f64;
            for (position, mass, _) in (&positions, &masses, !&deleted).join() {
                let pos = position.pos();
                if pos.x.abs() <= horizontal_half_extent && pos.y.abs() <= vertical_half_extent {
                    mass_count += 1.;
                    total_mass += mass.linear as f64
                }
            }
            world_track.cumulative_score += scoring.per_frame_scoring
                .eval(world_track.ticks_completed as f64, total_mass, mass_count);
            world_track.ticks_completed += 1;
        } else {
            info!("Storing scored world");
            let world = mem::replace(&mut world_track.world, World::default());
            let parent = mem::replace(&mut world_track.parent, None);
            let score = mem::replace(&mut world_track.cumulative_score, 0.);
            world_track.ticks_completed = 0;
            let store_result = match parent {
                Some(parent) => storage.add_child_scenario(world, score, &parent),
                None => storage.add_root_scenario(world, score),
            };
            match store_result {
                Err(error) => error!("Error while storing finished scenario: {}", error),
                Ok(scenario) => info!(
                    "Saved scenario {} (parent: {:?}, family: {}, generation: {}) with score {}",
                    scenario.id,
                    scenario.parent,
                    scenario.family,
                    scenario.generation,
                    scenario.score,
                ),
            }
            scene_change.change_scene(WorldGenerator::<T>::default());
        }
    }
}
<commit_msg>replace NaN scores with -inf<commit_after>// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::marker::PhantomData;
use std::mem;
use std::str::FromStr;

use specs::{
    Join,
    Read,
    ReadStorage,
    System,
    Write,
};

use xsecurelock_saver::engine::{
    components::{
        delete::Deleted,
        physics::{
            Mass,
            Position,
        },
    },
    resources::{
        draw::View,
        scene::SceneChange,
    },
};

use config::scoring::ScoringConfig;
use model::{Scenario, World};
use storage::Storage;
use worldgenerator::WorldGenerator;

use self::scoring_function::Expression;

mod scoring_function;

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(transparent)]
pub struct ScoringFunction(Expression);

impl ScoringFunction {
    /// Evaluate the expression given the scoring function inputs.
    pub fn eval(&self, tick: f64, total_mass: f64, mass_count: f64) -> f64 {
        self.0.eval(tick, total_mass, mass_count)
    }
}

impl FromStr for ScoringFunction {
    type Err = String;

    fn from_str(source: &str) -> Result<ScoringFunction, String> {
        source.parse().map(ScoringFunction)
    }
}

/// Resource for tracking the status of the currently active scene.
pub struct ActiveWorld {
    /// The world being scored.
    pub world: World,
    /// The parent of the world being scored.
    pub parent: Option<Scenario>,
    /// The score the world has received so far.
    pub cumulative_score: f64,
    /// The number of physics ticks that the world has been scored on so far.
    pub ticks_completed: u32,
}

impl Default for ActiveWorld {
    fn default() -> Self {
        ActiveWorld {
            world: World { planets: vec![] },
            parent: None,
            cumulative_score: 0.,
            ticks_completed: 0,
        }
    }
}

#[derive(Default)]
pub struct ScoreKeeper<T>(PhantomData<T>);

impl<'a, T> System<'a> for ScoreKeeper<T> where T: Storage + Default + Send + Sync + 'static {
    type SystemData = (
        Read<'a, ScoringConfig>,
        Read<'a, View>,
        Write<'a, ActiveWorld>,
        Write<'a, T>,
        Write<'a, SceneChange>,
        ReadStorage<'a, Position>,
        ReadStorage<'a, Mass>,
        ReadStorage<'a, Deleted>,
    );

    fn run(
        &mut self,
        (
            scoring,
            view,
            mut world_track,
            mut storage,
            mut scene_change,
            positions,
            masses,
            deleted,
        ): Self::SystemData,
    ) {
        if world_track.ticks_completed < scoring.scored_ticks {
            let vertical_half_extent = scoring.scored_area.height / 2.;
            let horizontal_half_extent = if scoring.scored_area.scale_width_by_aspect {
                // x / y = w / w_0; w_0 * x / y = w
                let aspect = view.size.x / view.size.y;
                scoring.scored_area.width * aspect
            } else {
                scoring.scored_area.width
            } / 2.;

            let mut mass_count = 0f64;
            let mut total_mass = 0f64;
            for (position, mass, _) in (&positions, &masses, !&deleted).join() {
                let pos = position.pos();
                if pos.x.abs() <= horizontal_half_extent && pos.y.abs() <= vertical_half_extent {
                    mass_count += 1.;
                    total_mass += mass.linear as f64
                }
            }
            world_track.cumulative_score += scoring.per_frame_scoring
                .eval(world_track.ticks_completed as f64, total_mass, mass_count);
            world_track.ticks_completed += 1;
        } else {
            info!("Storing scored world");
            let world = mem::replace(&mut world_track.world, World::default());
            let parent = mem::replace(&mut world_track.parent, None);
            let score = match mem::replace(&mut world_track.cumulative_score, 0.) {
                score if score.is_nan() => {
                    warn!("Score was NaN, replacing with -inf");
                    ::std::f64::NEG_INFINITY
                },
                score => score,
            };
            world_track.ticks_completed = 0;
            let store_result = match parent {
                Some(parent) => storage.add_child_scenario(world, score, &parent),
                None => storage.add_root_scenario(world, score),
            };
            match store_result {
                Err(error) => error!("Error while storing finished scenario: {}", error),
                Ok(scenario) => info!(
                    "Saved scenario {} (parent: {:?}, family: {}, generation: {}) with score {}",
                    scenario.id,
                    scenario.parent,
                    scenario.family,
                    scenario.generation,
                    scenario.score,
                ),
            }
            scene_change.change_scene(WorldGenerator::<T>::default());
        }
    }
}
<|endoftext|>


<commit_before>//! Connection helper.
use tokio::{
    io::{AsyncRead, AsyncWrite},
    net::TcpStream,
};

use tungstenite::{
    client::uri_mode,
    error::{Error, UrlError},
    handshake::client::{Request, Response},
    protocol::WebSocketConfig,
};

use super::{client_async_with_config, IntoClientRequest, WebSocketStream};

#[cfg(feature = "native-tls")]
pub(crate) mod encryption {
    use native_tls_crate::TlsConnector as NativeTlsConnector;
    use tokio_native_tls::{TlsConnector as TokioTlsConnector, TlsStream};

    use tokio::io::{AsyncRead, AsyncWrite};

    use tungstenite::{error::TlsError, stream::Mode, Error};

    use crate::stream::Stream as StreamSwitcher;

    /// A stream that might be protected with TLS.
    pub type MaybeTlsStream<S> = StreamSwitcher<S, TlsStream<S>>;

    pub type AutoStream<S> = MaybeTlsStream<S>;

    /// A TLS connector that can be used when establishing TLS connections.
    pub type TlsConnector = NativeTlsConnector;

    pub async fn wrap_stream<S>(
        socket: S,
        domain: String,
        mode: Mode,
        tls_connector: Option<TlsConnector>,
    ) -> Result<AutoStream<S>, Error>
    where
        S: 'static + AsyncRead + AsyncWrite + Send + Unpin,
    {
        match mode {
            Mode::Plain => Ok(StreamSwitcher::Plain(socket)),
            Mode::Tls => {
                let try_connector = tls_connector.map_or_else(TlsConnector::new, Ok);
                let connector = try_connector.map_err(TlsError::Native)?;
                let stream = TokioTlsConnector::from(connector);
                let connected = stream.connect(&domain, socket).await;
                match connected {
                    Err(e) => Err(Error::Tls(e.into())),
                    Ok(s) => Ok(StreamSwitcher::Tls(s)),
                }
            }
        }
    }
}

#[cfg(all(feature = "rustls-tls", not(feature = "native-tls")))]
pub(crate) mod encryption {
    pub use rustls::ClientConfig;
    use tokio_rustls::{webpki::DNSNameRef, TlsConnector as TokioTlsConnector, TlsStream};

    use std::sync::Arc;
    use tokio::io::{AsyncRead, AsyncWrite};

    use tungstenite::{error::TlsError, stream::Mode, Error};

    use crate::stream::Stream as StreamSwitcher;

    /// A stream that might be protected with TLS.
    pub type MaybeTlsStream<S> = StreamSwitcher<S, TlsStream<S>>;

    pub type AutoStream<S> = MaybeTlsStream<S>;

    /// A TLS connector that can be used when establishing TLS connections.
    pub type TlsConnector = Arc<ClientConfig>;

    pub async fn wrap_stream<S>(
        socket: S,
        domain: String,
        mode: Mode,
        tls_connector: Option<TlsConnector>,
    ) -> Result<AutoStream<S>, Error>
    where
        S: 'static + AsyncRead + AsyncWrite + Send + Unpin,
    {
        match mode {
            Mode::Plain => Ok(StreamSwitcher::Plain(socket)),
            Mode::Tls => {
                let config = tls_connector.unwrap_or_else(|| {
                    let mut config = ClientConfig::new();
                    config.root_store.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);

                    Arc::new(config)
                });
                let domain = DNSNameRef::try_from_ascii_str(&domain).map_err(TlsError::Dns)?;
                let stream = TokioTlsConnector::from(config);
                let connected = stream.connect(domain, socket).await;

                match connected {
                    Err(e) => Err(Error::Io(e)),
                    Ok(s) => Ok(StreamSwitcher::Tls(TlsStream::Client(s))),
                }
            }
        }
    }
}

#[cfg(feature = "native-tls")]
pub use self::encryption::MaybeTlsStream;
#[cfg(all(feature = "rustls-tls", not(feature = "native-tls")))]
pub use self::encryption::MaybeTlsStream;

pub use self::encryption::TlsConnector;

#[cfg(not(any(feature = "native-tls", feature = "rustls-tls")))]
pub(crate) mod encryption {
    use tokio::io::{AsyncRead, AsyncWrite};

    use tungstenite::{
        error::{Error, UrlError},
        stream::Mode,
    };

    pub type AutoStream<S> = S;

    /// A TLS connector that can be used when establishing TLS connections.
    pub type TlsConnector = ();

    pub async fn wrap_stream<S>(
        socket: S,
        _domain: String,
        mode: Mode,
        _tls_connector: Option<TlsConnector>,
    ) -> Result<AutoStream<S>, Error>
    where
        S: 'static + AsyncRead + AsyncWrite + Send + Unpin,
    {
        match mode {
            Mode::Plain => Ok(socket),
            Mode::Tls => Err(Error::Url(UrlError::TlsFeatureNotEnabled)),
        }
    }
}

use self::encryption::{wrap_stream, AutoStream};

/// Get a domain from an URL.
#[inline]
fn domain(request: &Request) -> Result<String, Error> {
    match request.uri().host() {
        Some(d) => Ok(d.to_string()),
        None => Err(Error::Url(UrlError::NoHostName)),
    }
}

/// Creates a WebSocket handshake from a request and a stream,
/// upgrading the stream to TLS if required.
pub async fn client_async_tls<R, S>(
    request: R,
    stream: S,
) -> Result<(WebSocketStream<AutoStream<S>>, Response), Error>
where
    R: IntoClientRequest + Unpin,
    S: 'static + AsyncRead + AsyncWrite + Send + Unpin,
    AutoStream<S>: Unpin,
{
    client_async_tls_with_config(request, stream, None, None).await
}

/// The same as `client_async_tls()` but the one can specify a websocket configuration,
/// and an optional TLS connector. If no connector is specified, the default one will
/// be created.
///
/// Please refer to `client_async_tls()` for more details.
pub async fn client_async_tls_with_config<R, S>(
    request: R,
    stream: S,
    config: Option<WebSocketConfig>,
    tls_connector: Option<TlsConnector>,
) -> Result<(WebSocketStream<AutoStream<S>>, Response), Error>
where
    R: IntoClientRequest + Unpin,
    S: 'static + AsyncRead + AsyncWrite + Send + Unpin,
    AutoStream<S>: Unpin,
{
    let request = request.into_client_request()?;

    let domain = domain(&request)?;

    // Make sure we check domain and mode first. URL must be valid.
    let mode = uri_mode(&request.uri())?;

    let stream = wrap_stream(stream, domain, mode, tls_connector).await?;
    client_async_with_config(request, stream, config).await
}

/// Connect to a given URL.
pub async fn connect_async<R>(
    request: R,
) -> Result<(WebSocketStream<AutoStream<TcpStream>>, Response), Error>
where
    R: IntoClientRequest + Unpin,
{
    connect_async_with_config(request, None).await
}

/// The same as `connect_async()` but the one can specify a websocket configuration.
/// Please refer to `connect_async()` for more details.
pub async fn connect_async_with_config<R>(
    request: R,
    config: Option<WebSocketConfig>,
) -> Result<(WebSocketStream<AutoStream<TcpStream>>, Response), Error>
where
    R: IntoClientRequest + Unpin,
{
    let request = request.into_client_request()?;

    let domain = domain(&request)?;
    let port = request
        .uri()
        .port_u16()
        .or_else(|| match request.uri().scheme_str() {
            Some("wss") => Some(443),
            Some("ws") => Some(80),
            _ => None,
        })
        .ok_or(Error::Url(UrlError::UnsupportedUrlScheme))?;

    let addr = format!("{}:{}", domain, port);
    let try_socket = TcpStream::connect(addr).await;
    let socket = try_socket.map_err(Error::Io)?;
    client_async_tls_with_config(request, socket, config, None).await
}
<commit_msg>Simply duplicate public use statement<commit_after>//! Connection helper.
use tokio::{
    io::{AsyncRead, AsyncWrite},
    net::TcpStream,
};

use tungstenite::{
    client::uri_mode,
    error::{Error, UrlError},
    handshake::client::{Request, Response},
    protocol::WebSocketConfig,
};

use super::{client_async_with_config, IntoClientRequest, WebSocketStream};

#[cfg(feature = "native-tls")]
pub(crate) mod encryption {
    use native_tls_crate::TlsConnector as NativeTlsConnector;
    use tokio_native_tls::{TlsConnector as TokioTlsConnector, TlsStream};

    use tokio::io::{AsyncRead, AsyncWrite};

    use tungstenite::{error::TlsError, stream::Mode, Error};

    use crate::stream::Stream as StreamSwitcher;

    /// A stream that might be protected with TLS.
    pub type MaybeTlsStream<S> = StreamSwitcher<S, TlsStream<S>>;

    pub type AutoStream<S> = MaybeTlsStream<S>;

    /// A TLS connector that can be used when establishing TLS connections.
    pub type TlsConnector = NativeTlsConnector;

    pub async fn wrap_stream<S>(
        socket: S,
        domain: String,
        mode: Mode,
        tls_connector: Option<TlsConnector>,
    ) -> Result<AutoStream<S>, Error>
    where
        S: 'static + AsyncRead + AsyncWrite + Send + Unpin,
    {
        match mode {
            Mode::Plain => Ok(StreamSwitcher::Plain(socket)),
            Mode::Tls => {
                let try_connector = tls_connector.map_or_else(TlsConnector::new, Ok);
                let connector = try_connector.map_err(TlsError::Native)?;
                let stream = TokioTlsConnector::from(connector);
                let connected = stream.connect(&domain, socket).await;
                match connected {
                    Err(e) => Err(Error::Tls(e.into())),
                    Ok(s) => Ok(StreamSwitcher::Tls(s)),
                }
            }
        }
    }
}

#[cfg(all(feature = "rustls-tls", not(feature = "native-tls")))]
pub(crate) mod encryption {
    pub use rustls::ClientConfig;
    use tokio_rustls::{webpki::DNSNameRef, TlsConnector as TokioTlsConnector, TlsStream};

    use std::sync::Arc;
    use tokio::io::{AsyncRead, AsyncWrite};

    use tungstenite::{error::TlsError, stream::Mode, Error};

    use crate::stream::Stream as StreamSwitcher;

    /// A stream that might be protected with TLS.
    pub type MaybeTlsStream<S> = StreamSwitcher<S, TlsStream<S>>;

    pub type AutoStream<S> = MaybeTlsStream<S>;

    /// A TLS connector that can be used when establishing TLS connections.
    pub type TlsConnector = Arc<ClientConfig>;

    pub async fn wrap_stream<S>(
        socket: S,
        domain: String,
        mode: Mode,
        tls_connector: Option<TlsConnector>,
    ) -> Result<AutoStream<S>, Error>
    where
        S: 'static + AsyncRead + AsyncWrite + Send + Unpin,
    {
        match mode {
            Mode::Plain => Ok(StreamSwitcher::Plain(socket)),
            Mode::Tls => {
                let config = tls_connector.unwrap_or_else(|| {
                    let mut config = ClientConfig::new();
                    config.root_store.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);

                    Arc::new(config)
                });
                let domain = DNSNameRef::try_from_ascii_str(&domain).map_err(TlsError::Dns)?;
                let stream = TokioTlsConnector::from(config);
                let connected = stream.connect(domain, socket).await;

                match connected {
                    Err(e) => Err(Error::Io(e)),
                    Ok(s) => Ok(StreamSwitcher::Tls(TlsStream::Client(s))),
                }
            }
        }
    }
}

#[cfg(any(feature = "native-tls", feature = "rustls-tls"))]
pub use self::encryption::MaybeTlsStream;
pub use self::encryption::TlsConnector;

#[cfg(not(any(feature = "native-tls", feature = "rustls-tls")))]
pub(crate) mod encryption {
    use tokio::io::{AsyncRead, AsyncWrite};

    use tungstenite::{
        error::{Error, UrlError},
        stream::Mode,
    };

    pub type AutoStream<S> = S;

    /// A TLS connector that can be used when establishing TLS connections.
    pub type TlsConnector = ();

    pub async fn wrap_stream<S>(
        socket: S,
        _domain: String,
        mode: Mode,
        _tls_connector: Option<TlsConnector>,
    ) -> Result<AutoStream<S>, Error>
    where
        S: 'static + AsyncRead + AsyncWrite + Send + Unpin,
    {
        match mode {
            Mode::Plain => Ok(socket),
            Mode::Tls => Err(Error::Url(UrlError::TlsFeatureNotEnabled)),
        }
    }
}

use self::encryption::{wrap_stream, AutoStream};

/// Get a domain from an URL.
#[inline]
fn domain(request: &Request) -> Result<String, Error> {
    match request.uri().host() {
        Some(d) => Ok(d.to_string()),
        None => Err(Error::Url(UrlError::NoHostName)),
    }
}

/// Creates a WebSocket handshake from a request and a stream,
/// upgrading the stream to TLS if required.
pub async fn client_async_tls<R, S>(
    request: R,
    stream: S,
) -> Result<(WebSocketStream<AutoStream<S>>, Response), Error>
where
    R: IntoClientRequest + Unpin,
    S: 'static + AsyncRead + AsyncWrite + Send + Unpin,
    AutoStream<S>: Unpin,
{
    client_async_tls_with_config(request, stream, None, None).await
}

/// The same as `client_async_tls()` but the one can specify a websocket configuration,
/// and an optional TLS connector. If no connector is specified, the default one will
/// be created.
///
/// Please refer to `client_async_tls()` for more details.
pub async fn client_async_tls_with_config<R, S>(
    request: R,
    stream: S,
    config: Option<WebSocketConfig>,
    tls_connector: Option<TlsConnector>,
) -> Result<(WebSocketStream<AutoStream<S>>, Response), Error>
where
    R: IntoClientRequest + Unpin,
    S: 'static + AsyncRead + AsyncWrite + Send + Unpin,
    AutoStream<S>: Unpin,
{
    let request = request.into_client_request()?;

    let domain = domain(&request)?;

    // Make sure we check domain and mode first. URL must be valid.
    let mode = uri_mode(&request.uri())?;

    let stream = wrap_stream(stream, domain, mode, tls_connector).await?;
    client_async_with_config(request, stream, config).await
}

/// Connect to a given URL.
pub async fn connect_async<R>(
    request: R,
) -> Result<(WebSocketStream<AutoStream<TcpStream>>, Response), Error>
where
    R: IntoClientRequest + Unpin,
{
    connect_async_with_config(request, None).await
}

/// The same as `connect_async()` but the one can specify a websocket configuration.
/// Please refer to `connect_async()` for more details.
pub async fn connect_async_with_config<R>(
    request: R,
    config: Option<WebSocketConfig>,
) -> Result<(WebSocketStream<AutoStream<TcpStream>>, Response), Error>
where
    R: IntoClientRequest + Unpin,
{
    let request = request.into_client_request()?;

    let domain = domain(&request)?;
    let port = request
        .uri()
        .port_u16()
        .or_else(|| match request.uri().scheme_str() {
            Some("wss") => Some(443),
            Some("ws") => Some(80),
            _ => None,
        })
        .ok_or(Error::Url(UrlError::UnsupportedUrlScheme))?;

    let addr = format!("{}:{}", domain, port);
    let try_socket = TcpStream::connect(addr).await;
    let socket = try_socket.map_err(Error::Io)?;
    client_async_tls_with_config(request, socket, config, None).await
}
<|endoftext|>


<commit_before>
use {
    AddColor,
    AddEllipse,
    AddPolygon,
    AddRectangle,
    Borrowed,
    ColorContext,
    EllipseContext,
    Field,
    Matrix2d,
    PolygonContext,
    RectangleContext,
    Transform2d,
    Value,
    View,
};
use vecmath::{
    identity,
    multiply,
    rotate_radians,
    scale,
    shear,
    translate,
};

/// Drawing 2d context.
pub struct Context<'a> {
    /// Base/original transformation.
    pub base: Field<'a, Matrix2d>,
    /// Current transformation.
    pub transform: Field<'a, Matrix2d>,
}

impl<'a> Transform2d<'a> for Context<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let trans = translate(x, y);
                 multiply(&trans, self.transform.get())
            }),
        }
    }

    #[inline(always)]
    fn trans_local(&'a self, x: f64, y: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let trans = translate(x, y);
                 multiply(self.transform.get(), &trans)
            }),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let rot = rotate_radians(angle);
                multiply(&rot, self.transform.get())
            }),
        }
    }

    #[inline(always)]
    fn rot_rad_local(&'a self, angle: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let rot = rotate_radians(angle);
                multiply(self.transform.get(), &rot)
            }),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let scale = scale(sx, sy);
                multiply(&scale, self.transform.get())
            }),
        }
    }

    #[inline(always)]
    fn scale_local(&'a self, sx: f64, sy: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let scale = scale(sx, sy);
                multiply(self.transform.get(), &scale)
            }),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let shear = shear(sx, sy);
                multiply(&shear, self.transform.get())
            }),
        }
    }

    #[inline(always)]
    fn shear_local(&'a self, sx: f64, sy: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let shear = shear(sx, sy);
                multiply(self.transform.get(), &shear)
            }),
        }
    }
}

impl<'a> Context<'a> {
    /// Creates a new drawing context.
    pub fn new() -> Context {
        Context {
            base:  Value([1.0, 0.0, 0.0,
                          0.0, 1.0, 0.0]),
            transform: Value([1.0, 0.0, 0.0,
                          0.0, 1.0, 0.0]),
        }
    }
}

#[test]
fn test_context() {
    let c = Context::new();
    {
        let d = c.trans(20.0, 40.0);
        let d = d.trans(10.0, 10.0);
        assert_eq!(d.transform.get()[2], 30.0);
        assert_eq!(d.transform.get()[5], 50.0);
    }
    assert_eq!(c.transform.get()[2], 0.0);
    assert_eq!(c.transform.get()[5], 0.0);

    let c = c.rot_deg(90.0);
    assert!((c.transform.get()[0] - 0.0).abs() < 0.00001);
    assert!((c.transform.get()[1] - 1.0).abs() < 0.00001);
}

#[test]
fn test_scale() {
    let c = Context::new();
    let c = c.scale(2.0, 3.0);
    assert!((c.transform.get()[0] - 2.0).abs() < 0.00001);
    assert!((c.transform.get()[4] - 3.0).abs() < 0.00001);
}

impl<'a> AddRectangle<'a, RectangleContext<'a>> for Context<'a> {
    #[inline(always)]
    fn rect(&'a self, x: f64, y: f64, w: f64, h: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Value([x, y, w, h]),
        }
    }
}

#[test]
fn test_rect() {
    let c = Context::new();
    let d = c.rect(0.0, 0.0, 100.0, 50.0);
    assert_eq!(d.rect.get()[2], 100.0);
}

impl<'a> AddColor<'a, ColorContext<'a>> for Context<'a> {
    #[inline(always)]
    fn rgba(&'a self, r: f32, g: f32, b: f32, a: f32) -> ColorContext<'a> {
        ColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            color: Value([r, g, b, a]),
        }
    }
}

#[test]
fn test_rgba() {
    let c = Context::new();
    let d: ColorContext = c.rgba(1.0, 0.0, 0.0, 1.0);
    assert_eq!(d.color.get()[0], 1.0);
}

impl<'a> AddEllipse<'a, EllipseContext<'a>> for Context<'a> {
    #[inline(always)]
    fn ellipse(&'a self, x: f64, y: f64, w: f64, h: f64) -> EllipseContext<'a> {
        EllipseContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Value([x, y, w, h]),
        }
    }
}

#[test]
fn test_ellipse() {
    let c = Context::new();
    let d: EllipseContext = c.ellipse(0.0, 0.0, 100.0, 100.0);
    assert_eq!(d.rect.get()[2], 100.0);
}

impl<'a> AddPolygon<'a, PolygonContext<'a>> for Context<'a> {
    #[inline(always)]
    fn polygon(&'a self, polygon: &'a [f64]) -> PolygonContext<'a> {
        PolygonContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            polygon: Value(polygon),
        }
    }
}

impl<'a> View<'a> for Context<'a> {
    #[inline(always)]
    fn view(&'a self) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.base.get()),
        }
    }

    #[inline(always)]
    fn reset(&'a self) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value(identity()),
        }
    }

    #[inline(always)]
    fn store_view(&'a self) -> Context<'a> {
        Context {
            base: Borrowed(self.transform.get()),
            transform: Borrowed(self.transform.get()),
        }
    }
}

<commit_msg>Implemented `AddImage` for `Context`<commit_after>
use {
    AddColor,
    AddEllipse,
    AddImage,
    AddPolygon,
    AddRectangle,
    Borrowed,
    ColorContext,
    EllipseContext,
    Field,
    Image,
    ImageRectangleContext,
    Matrix2d,
    PolygonContext,
    RectangleContext,
    Transform2d,
    Value,
    View,
};
use vecmath::{
    identity,
    multiply,
    rotate_radians,
    scale,
    shear,
    translate,
};

/// Drawing 2d context.
pub struct Context<'a> {
    /// Base/original transformation.
    pub base: Field<'a, Matrix2d>,
    /// Current transformation.
    pub transform: Field<'a, Matrix2d>,
}

impl<'a> Transform2d<'a> for Context<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let trans = translate(x, y);
                 multiply(&trans, self.transform.get())
            }),
        }
    }

    #[inline(always)]
    fn trans_local(&'a self, x: f64, y: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let trans = translate(x, y);
                 multiply(self.transform.get(), &trans)
            }),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let rot = rotate_radians(angle);
                multiply(&rot, self.transform.get())
            }),
        }
    }

    #[inline(always)]
    fn rot_rad_local(&'a self, angle: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let rot = rotate_radians(angle);
                multiply(self.transform.get(), &rot)
            }),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let scale = scale(sx, sy);
                multiply(&scale, self.transform.get())
            }),
        }
    }

    #[inline(always)]
    fn scale_local(&'a self, sx: f64, sy: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let scale = scale(sx, sy);
                multiply(self.transform.get(), &scale)
            }),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let shear = shear(sx, sy);
                multiply(&shear, self.transform.get())
            }),
        }
    }

    #[inline(always)]
    fn shear_local(&'a self, sx: f64, sy: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let shear = shear(sx, sy);
                multiply(self.transform.get(), &shear)
            }),
        }
    }
}

impl<'a> Context<'a> {
    /// Creates a new drawing context.
    pub fn new() -> Context {
        Context {
            base:  Value([1.0, 0.0, 0.0,
                          0.0, 1.0, 0.0]),
            transform: Value([1.0, 0.0, 0.0,
                          0.0, 1.0, 0.0]),
        }
    }
}

#[test]
fn test_context() {
    let c = Context::new();
    {
        let d = c.trans(20.0, 40.0);
        let d = d.trans(10.0, 10.0);
        assert_eq!(d.transform.get()[2], 30.0);
        assert_eq!(d.transform.get()[5], 50.0);
    }
    assert_eq!(c.transform.get()[2], 0.0);
    assert_eq!(c.transform.get()[5], 0.0);

    let c = c.rot_deg(90.0);
    assert!((c.transform.get()[0] - 0.0).abs() < 0.00001);
    assert!((c.transform.get()[1] - 1.0).abs() < 0.00001);
}

#[test]
fn test_scale() {
    let c = Context::new();
    let c = c.scale(2.0, 3.0);
    assert!((c.transform.get()[0] - 2.0).abs() < 0.00001);
    assert!((c.transform.get()[4] - 3.0).abs() < 0.00001);
}

impl<'a> AddRectangle<'a, RectangleContext<'a>> for Context<'a> {
    #[inline(always)]
    fn rect(&'a self, x: f64, y: f64, w: f64, h: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Value([x, y, w, h]),
        }
    }
}

#[test]
fn test_rect() {
    let c = Context::new();
    let d = c.rect(0.0, 0.0, 100.0, 50.0);
    assert_eq!(d.rect.get()[2], 100.0);
}

impl<'a> AddColor<'a, ColorContext<'a>> for Context<'a> {
    #[inline(always)]
    fn rgba(&'a self, r: f32, g: f32, b: f32, a: f32) -> ColorContext<'a> {
        ColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            color: Value([r, g, b, a]),
        }
    }
}

#[test]
fn test_rgba() {
    let c = Context::new();
    let d: ColorContext = c.rgba(1.0, 0.0, 0.0, 1.0);
    assert_eq!(d.color.get()[0], 1.0);
}

impl<'a> AddEllipse<'a, EllipseContext<'a>> for Context<'a> {
    #[inline(always)]
    fn ellipse(&'a self, x: f64, y: f64, w: f64, h: f64) -> EllipseContext<'a> {
        EllipseContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Value([x, y, w, h]),
        }
    }
}

#[test]
fn test_ellipse() {
    let c = Context::new();
    let d: EllipseContext = c.ellipse(0.0, 0.0, 100.0, 100.0);
    assert_eq!(d.rect.get()[2], 100.0);
}

impl<'a> AddPolygon<'a, PolygonContext<'a>> for Context<'a> {
    #[inline(always)]
    fn polygon(&'a self, polygon: &'a [f64]) -> PolygonContext<'a> {
        PolygonContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            polygon: Value(polygon),
        }
    }
}

impl<'a> View<'a> for Context<'a> {
    #[inline(always)]
    fn view(&'a self) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.base.get()),
        }
    }

    #[inline(always)]
    fn reset(&'a self) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value(identity()),
        }
    }

    #[inline(always)]
    fn store_view(&'a self) -> Context<'a> {
        Context {
            base: Borrowed(self.transform.get()),
            transform: Borrowed(self.transform.get()),
        }
    }
}

impl<'a> AddImage<'a, ImageRectangleContext<'a>> for Context<'a> {
    #[inline(always)]
    fn image(&'a self, image: Image) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Value([0.0, 0.0, image.source_rect[2] as f64, image.source_rect[3] as f64]),
            image: Value(image),
        }
    }
}

<|endoftext|>