<commit_before>use std::env::consts::EXE_SUFFIX;
use std::env;
use std::fs::File;
use std::io::{self, Write};
use std::path::{PathBuf, Path};
use std::process::Command;

fn main() {
    let mut args = env::args_os().skip(1);
    match args.next().as_ref().and_then(|s| s.to_str()) {
        Some("--version") => {
            let me = env::current_exe().unwrap();
            let mut version_file = PathBuf::from(format!("{}.version", me.display()));
            let mut hash_file = PathBuf::from(format!("{}.version-hash", me.display()));
            if !version_file.exists() {
                // There's a "MAJOR HACKS" statement in `toolchain.rs` right
                // now where custom toolchains use a `cargo.exe` that's
                // temporarily located elsewhere so they can execute the correct
                // `rustc.exe`. This means that our dummy version files may not
                // be just next to use.
                //
                // Detect this here and work around it.
                assert!(cfg!(windows));
                assert!(env::var_os("RUSTUP_TOOLCHAIN").is_some());
                let mut alt = me.clone();
                alt.pop(); // remove our filename
                assert!(alt.ends_with("fallback"));
                alt.pop(); // pop 'fallback'
                alt.push("toolchains");

                let mut part = PathBuf::from("bin");
                part.push(me.file_name().unwrap());

                let path = alt.read_dir().unwrap()
                    .map(|e| e.unwrap().path().join(&part))
                    .filter(|p| p.exists())
                    .find(|p| equivalent(&p, &me))
                    .unwrap();

                version_file = format!("{}.version", path.display()).into();
                hash_file = format!("{}.version-hash", path.display()).into();
            }
            let version = std::fs::read_to_string(&version_file).unwrap();
            let hash = std::fs::read_to_string(&hash_file).unwrap();
            println!("{} ({})", version, hash);
        }
        Some("--empty-arg-test") => {
            assert_eq!(args.next().unwrap(), "");
        }
        Some("--huge-output") => {
            let mut out = io::stderr();
            for _ in 0 .. 10000 {
                out.write_all(b"error: a value named `fail` has already been defined in this module [E0428]\n").unwrap();
            }
        }
        Some("--call-rustc") => {
            // Used by the fallback_cargo_calls_correct_rustc test. Tests that
            // the environment has been set up right such that invoking rustc
            // will actually invoke the wrapper
            let rustc = &format!("rustc{}", EXE_SUFFIX);
            Command::new(rustc).arg("--version").status().unwrap();
        }
        Some("--echo-args") => {
            let mut out = io::stderr();
            for arg in args {
                writeln!(out, "{}", arg.to_string_lossy()).unwrap();
            }
        }
        _ => panic!("bad mock proxy commandline"),
    }
}

#[cfg(unix)]
fn equivalent(_: &Path, _: &Path) -> bool { false }

#[cfg(windows)]
#[allow(warnings)]
fn equivalent(a: &Path, b: &Path) -> bool {
    use std::mem;
    use std::os::windows::prelude::*;
    use std::os::windows::raw::HANDLE;

    extern "system" {
        fn GetFileInformationByHandle(a: HANDLE, b: *mut BY_HANDLE_FILE_INFORMATION)
            -> i32;
    }

    #[repr(C)]
    struct BY_HANDLE_FILE_INFORMATION {
        dwFileAttributes: u32,
        ftCreationTime: FILETIME,
        ftLastAccessTime: FILETIME,
        ftLastWriteTime: FILETIME,
        dwVolumeSerialNumber: u32,
        nFileSizeHigh: u32,
        nFileSizeLow: u32,
        nNumberOfLinks: u32,
        nFileIndexHigh: u32,
        nFileIndexLow: u32,
    }

    #[repr(C)]
    struct FILETIME {
        dwLowDateTime: u32,
        dwHighDateTime: u32,
    }

    let a = File::open(a).unwrap();
    let b = File::open(b).unwrap();

    unsafe {
        let mut ainfo = mem::zeroed();
        let mut binfo = mem::zeroed();
        GetFileInformationByHandle(a.as_raw_handle(), &mut ainfo);
        GetFileInformationByHandle(b.as_raw_handle(), &mut binfo);

        ainfo.dwVolumeSerialNumber == binfo.dwVolumeSerialNumber &&
            ainfo.nFileIndexHigh == binfo.nFileIndexHigh &&
            ainfo.nFileIndexLow == binfo.nFileIndexLow
    }
}
<commit_msg>mock_bin_src.rs: Localise import of std::fs::File<commit_after>use std::env::consts::EXE_SUFFIX;
use std::env;
use std::io::{self, Write};
use std::path::{PathBuf, Path};
use std::process::Command;

fn main() {
    let mut args = env::args_os().skip(1);
    match args.next().as_ref().and_then(|s| s.to_str()) {
        Some("--version") => {
            let me = env::current_exe().unwrap();
            let mut version_file = PathBuf::from(format!("{}.version", me.display()));
            let mut hash_file = PathBuf::from(format!("{}.version-hash", me.display()));
            if !version_file.exists() {
                // There's a "MAJOR HACKS" statement in `toolchain.rs` right
                // now where custom toolchains use a `cargo.exe` that's
                // temporarily located elsewhere so they can execute the correct
                // `rustc.exe`. This means that our dummy version files may not
                // be just next to use.
                //
                // Detect this here and work around it.
                assert!(cfg!(windows));
                assert!(env::var_os("RUSTUP_TOOLCHAIN").is_some());
                let mut alt = me.clone();
                alt.pop(); // remove our filename
                assert!(alt.ends_with("fallback"));
                alt.pop(); // pop 'fallback'
                alt.push("toolchains");

                let mut part = PathBuf::from("bin");
                part.push(me.file_name().unwrap());

                let path = alt.read_dir().unwrap()
                    .map(|e| e.unwrap().path().join(&part))
                    .filter(|p| p.exists())
                    .find(|p| equivalent(&p, &me))
                    .unwrap();

                version_file = format!("{}.version", path.display()).into();
                hash_file = format!("{}.version-hash", path.display()).into();
            }
            let version = std::fs::read_to_string(&version_file).unwrap();
            let hash = std::fs::read_to_string(&hash_file).unwrap();
            println!("{} ({})", version, hash);
        }
        Some("--empty-arg-test") => {
            assert_eq!(args.next().unwrap(), "");
        }
        Some("--huge-output") => {
            let mut out = io::stderr();
            for _ in 0 .. 10000 {
                out.write_all(b"error: a value named `fail` has already been defined in this module [E0428]\n").unwrap();
            }
        }
        Some("--call-rustc") => {
            // Used by the fallback_cargo_calls_correct_rustc test. Tests that
            // the environment has been set up right such that invoking rustc
            // will actually invoke the wrapper
            let rustc = &format!("rustc{}", EXE_SUFFIX);
            Command::new(rustc).arg("--version").status().unwrap();
        }
        Some("--echo-args") => {
            let mut out = io::stderr();
            for arg in args {
                writeln!(out, "{}", arg.to_string_lossy()).unwrap();
            }
        }
        _ => panic!("bad mock proxy commandline"),
    }
}

#[cfg(unix)]
fn equivalent(_: &Path, _: &Path) -> bool { false }

#[cfg(windows)]
#[allow(warnings)]
fn equivalent(a: &Path, b: &Path) -> bool {
    use std::mem;
    use std::os::windows::prelude::*;
    use std::os::windows::raw::HANDLE;
    use std::fs::File;

    extern "system" {
        fn GetFileInformationByHandle(a: HANDLE, b: *mut BY_HANDLE_FILE_INFORMATION)
            -> i32;
    }

    #[repr(C)]
    struct BY_HANDLE_FILE_INFORMATION {
        dwFileAttributes: u32,
        ftCreationTime: FILETIME,
        ftLastAccessTime: FILETIME,
        ftLastWriteTime: FILETIME,
        dwVolumeSerialNumber: u32,
        nFileSizeHigh: u32,
        nFileSizeLow: u32,
        nNumberOfLinks: u32,
        nFileIndexHigh: u32,
        nFileIndexLow: u32,
    }

    #[repr(C)]
    struct FILETIME {
        dwLowDateTime: u32,
        dwHighDateTime: u32,
    }

    let a = File::open(a).unwrap();
    let b = File::open(b).unwrap();

    unsafe {
        let mut ainfo = mem::zeroed();
        let mut binfo = mem::zeroed();
        GetFileInformationByHandle(a.as_raw_handle(), &mut ainfo);
        GetFileInformationByHandle(b.as_raw_handle(), &mut binfo);

        ainfo.dwVolumeSerialNumber == binfo.dwVolumeSerialNumber &&
            ainfo.nFileIndexHigh == binfo.nFileIndexHigh &&
            ainfo.nFileIndexLow == binfo.nFileIndexLow
    }
}
<|endoftext|>


<commit_before>struct TssContext { handle: u32 }
struct TssTpm { handle: u32 }

type TssHContext = u32;
type TssResult = u32;

const TSS_SUCCESS: TssResult = 0;

#[link(name = "tspi")]
extern {
    fn Tspi_Context_Create(phContext: *mut TssHContext) -> TssResult;
    fn Tspi_Context_Close(phContext: TssHContext) -> TssResult;
}

impl TssContext {
    fn new() -> Result<TssContext, TssResult> {
        unsafe {
            let mut handle = 0;
            let result = Tspi_Context_Create(&mut handle);
            if result == TSS_SUCCESS {
                Ok(TssContext { handle: handle })
            } else {
                Err(result)
            }
        }
    }
}

impl Drop for TssContext {
    fn drop(&mut self) {
        unsafe {
            Tspi_Context_Close(self.handle);
        }
    }
}

fn main() {
    let blah = TssContext::new();
    match blah {
        Ok(context) => println!("Context created! {:?}", context.handle),
        Err(e) => println!("Context failed with err {:?}", e),
    }
    println!("Hello world!");
}
<commit_msg>Implement Tspi_Context_Connect, Tspi_Context_GetTpmObject<commit_after>use std::ptr;

struct TssContext { handle: u32 }
struct TssTpm { handle: u32 }

type TssHContext = u32;
type TssHTPM = u32;
type TssResult = u32;
type TssUnicode = u16;

const TSS_SUCCESS: TssResult = 0;

#[link(name = "tspi")]
extern {
    fn Tspi_Context_Create(phContext: *mut TssHContext) -> TssResult;
    fn Tspi_Context_Connect(phContext: TssHContext, wszDestination: *const TssUnicode) -> TssResult;
    fn Tspi_Context_GetTpmObject(phContext: TssHContext, phTPM: *mut TssHTPM) -> TssResult;
    fn Tspi_Context_Close(phContext: TssHContext) -> TssResult;
}

impl TssContext {
    fn new() -> Result<TssContext, TssResult> {
        unsafe {
            let mut handle = 0;
            let result = Tspi_Context_Create(&mut handle);
            if result != TSS_SUCCESS {
                Err(result)
            } else {
                Ok(TssContext { handle: handle })
            }
        }
    }

    // TODO: support destination
    fn connect(&self) -> Result<(), TssResult> {
        unsafe {
            let result = Tspi_Context_Connect(self.handle, ptr::null());
            if result != TSS_SUCCESS {
                Err(result)
            } else {
                Ok(())
            }
        }
    }

    fn get_tpm_object(&self) -> Result<TssTpm, TssResult> {
        unsafe {
            let mut handle = 0;
            let result = Tspi_Context_GetTpmObject(self.handle, &mut handle);
            if result != TSS_SUCCESS {
                Err(result)
            } else {
                Ok(TssTpm { handle: handle })
            }
        }
    }
}

impl Drop for TssContext {
    fn drop(&mut self) {
        unsafe {
            Tspi_Context_Close(self.handle);
        }
    }
}

fn main() {
    // TODO: Any cleaner way to write this?
    let contextresult = TssContext::new();
    if let Ok(context) = contextresult {
        if let Ok(_) = context.connect() {
            if let Ok(tpm) = context.get_tpm_object() {
                println!("Success! TPM handle: {:?}", tpm.handle);
            } else {
                println!("Failed to get TPM handle :(")
            }
        } else {
            println!("Failed to connect :(");
        }
    } else {
        println!("Failed :(");
    }

    /*
    match blah {
        Ok(context) => println!("Context created! {:?}", context.handle),
        Err(e) => println!("Context failed with err {:?}", e),
    }
    println!("Hello world!");
    */
}
<|endoftext|>


<commit_before>use base::math::*;
use world::WorldView;
use glium::Surface;
use super::{Camera, GameContext};
use view::Sun;
use view::SkyView;
use std::rc::Rc;
use std::error::Error;
use std::env;
use super::weather::Weather;
use glium::texture::texture2d::Texture2d;
use glium::texture::{DepthFormat, DepthTexture2d, MipmapsOption, UncompressedFloatFormat};
use glium::framebuffer::SimpleFrameBuffer;
use glium::{IndexBuffer, Program, VertexBuffer};
use glium::index::PrimitiveType;
use glium::backend::Facade;
use glium::framebuffer::ToColorAttachment;

const SHADOW_MAP_SIZE: u32 = 1024;
const SHADOW_ORTHO_WIDTH: f32 = 300.0;
const SHADOW_ORTHO_HEIGHT: f32 = 300.0;
const SHADOW_ORTHO_NEAR: f32 = 100.0;
const SHADOW_ORTHO_FAR: f32 = 400.0;

pub struct Renderer {
    context: Rc<GameContext>,
    /// Screen-sized texture the scene is rendered into and then post-processed.
    quad_tex: Texture2d,
    /// Depth texture used by the normal render.
    depth_texture: DepthTexture2d,
    /// Depth texture rendered to from sun perspective.
    shadow_map: DepthTexture2d,
    /// Render the shadow map to the screen instead of the world.
    shadow_debug: bool,
    shadow_debug_program: Program,
    quad_vertex_buffer: VertexBuffer<Vertex>,
    quad_index_buffer: IndexBuffer<u16>,
    resolution: (u32, u32),
    bloom_filter_tex: Texture2d,
    bloom_horz_tex: Texture2d,
    bloom_vert_tex: Texture2d,
    bloom_blend_tex: Texture2d,
    tonemapping_program: Program,
    bloom_filter_program: Program,
    bloom_blur_program: Program,
    bloom_blend_program: Program,
}

impl Renderer {
    pub fn new(context: Rc<GameContext>) -> Self {

        // FIXME The index buffer is useless, switch to using `NoIndices` and
        // `TriangleStrip`
        let ibuf = IndexBuffer::new(context.get_facade(),
                                    PrimitiveType::TrianglesList,
                                    &[0u16, 1, 2, 0, 2, 3])
            .unwrap();

        let shadow_map = DepthTexture2d::empty_with_format(context.get_facade(),
                                                           DepthFormat::I16,
                                                           MipmapsOption::NoMipmap,
                                                           SHADOW_MAP_SIZE,
                                                           SHADOW_MAP_SIZE)
            .unwrap();

        let tonemapping_program = context.load_program("tonemapping").unwrap();
        let bloom_filter_program = context.load_program("bloom_filter").unwrap();
        let bloom_blur_program = context.load_program("bloom_blur").unwrap();
        let bloom_blend_program = context.load_program("bloom_blending").unwrap();
        let shadow_debug_program = context.load_program("shadow_debug").unwrap();

        let mut this = Renderer {
            context: context.clone(),
            quad_tex: Texture2d::empty(context.get_facade(), 1, 1).unwrap(),
            tonemapping_program: tonemapping_program,
            depth_texture: DepthTexture2d::empty(context.get_facade(), 1, 1).unwrap(),
            shadow_map: shadow_map,
            shadow_debug: env::var("SHADOW_DEBUG").is_ok(),
            shadow_debug_program: shadow_debug_program,
            quad_vertex_buffer: Renderer::create_vertex_buf(context.get_facade()),
            quad_index_buffer: ibuf,
            resolution: (0, 0),
            bloom_filter_tex: Texture2d::empty(context.get_facade(), 1, 1).unwrap(),
            bloom_horz_tex: Texture2d::empty(context.get_facade(), 1, 1).unwrap(),
            bloom_vert_tex: Texture2d::empty(context.get_facade(), 1, 1).unwrap(),
            bloom_blend_tex: Texture2d::empty(context.get_facade(), 1, 1).unwrap(),
            bloom_filter_program: bloom_filter_program,
            bloom_blur_program: bloom_blur_program,
            bloom_blend_program: bloom_blend_program,
        };

        // Create all textures with correct screen size
        this.render_update();
        this
    }

    /// Renders `world_view` into the renderer's shadow map from the
    /// perspective of the sun, whose position is `sun_pos`.
    ///
    /// Returns the MVP matrix used.
    fn render_shadow_map(&mut self,
                         world_view: &WorldView,
                         sun_pos: Point3f,
                         camera: Point3f)
                         -> Result<Matrix4<f32>, Box<Error>> {
        let mut shadow_target = try!(SimpleFrameBuffer::depth_only(self.context
                                                                       .get_facade(),
                                                                   &self.shadow_map));
        shadow_target.clear_depth(1.0);

        // Render the world from the perspective of the sun.
        let mut cam_pos = camera.to_vec();
        cam_pos.z = 0.0;
        let mut sun_cam = Camera::new_from_vector(sun_pos + cam_pos,
                                                  -sun_pos.to_vec(),
                                                  SHADOW_ORTHO_WIDTH / SHADOW_ORTHO_HEIGHT);
        // Set an orthographic projection matrix.
        sun_cam.set_proj_matrix(ortho(-SHADOW_ORTHO_WIDTH / 2.0,
                                      SHADOW_ORTHO_WIDTH / 2.0,
                                      -SHADOW_ORTHO_HEIGHT / 2.0,
                                      SHADOW_ORTHO_HEIGHT / 2.0,
                                      SHADOW_ORTHO_NEAR,
                                      SHADOW_ORTHO_FAR));
        world_view.draw_shadow(&mut shadow_target, &sun_cam);

        Ok(sun_cam.proj_matrix() * sun_cam.view_matrix())
    }

    /// Is called once every main loop iteration
    pub fn render(&mut self,
                  world_view: &WorldView,
                  camera: &Camera,
                  sun: &Sun,
                  weather: &mut Weather,
                  sky_view: &SkyView)
                  -> Result<(), Box<Error>> {
        // ===================================================================
        // check dimensions
        // ===================================================================
        let new_res = self.context.get_facade().get_framebuffer_dimensions();
        if self.resolution != new_res {
            self.render_update();
        }

        // ===================================================================
        // Creating shadow map
        // ===================================================================
        let depth_mvp = try!(self.render_shadow_map(world_view, sun.position(), camera.position));

        // ===================================================================
        // Rendering into HDR framebuffer
        // ===================================================================
        let mut hdr_buffer = try!(SimpleFrameBuffer::with_depth_buffer(self.context.get_facade(),
                                                                       &self.quad_tex,
                                                                       &self.depth_texture));
        hdr_buffer.clear_color_and_depth((0.0, 0.0, 1.0, 1.0), 1.0);

        if self.shadow_debug {
            let mut target = self.context.get_facade().draw();
            target.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0);
            try!(target.draw(&self.quad_vertex_buffer,
                             &self.quad_index_buffer,
                             &self.shadow_debug_program,
                             &uniform!{
                          decal_texture: &self.shadow_map,
                      },
                             &Default::default()));
            try!(target.finish());
            return Ok(());
        }

        world_view.draw(&mut hdr_buffer, camera, &self.shadow_map, &depth_mvp);
        sky_view.draw_skydome(&mut hdr_buffer, camera);
        sun.draw_sun(&mut hdr_buffer, camera);
        weather.draw(&mut hdr_buffer, camera);

        // ===================================================================
        // Creating the Bloom framebuffer
        // ===================================================================

        // =======================  light texture  ===========================

        // Bloom state
        // 0: Disable Bloom
        // 1: Enable Bloom
        // 2: Show only Bloom Map
        let bloom_state = 1;

        let uniforms = uniform! {
            decal_texture: &self.quad_tex,
            exposure: 1.0f32
        };

        let mut bloom_buffer = try!(SimpleFrameBuffer::new(self.context.get_facade(),
                                                           self.bloom_filter_tex
                                                               .to_color_attachment()));

        bloom_buffer.clear_color(0.0, 0.0, 0.0, 1.0);

        try!(bloom_buffer.draw(&self.quad_vertex_buffer,
                               &self.quad_index_buffer,
                               &self.bloom_filter_program,
                               &uniforms,
                               &Default::default()));

        // ============================  blur  ===============================

        let mut bloom_blur_horz_buffer = try!(SimpleFrameBuffer::new(self.context.get_facade(),
                                                                     self.bloom_horz_tex
                                                                         .to_color_attachment()));

        bloom_blur_horz_buffer.clear_color(0.0, 0.0, 0.0, 1.0);

        let mut bloom_blur_vert_buffer = try!(SimpleFrameBuffer::new(self.context.get_facade(),
                                                                     self.bloom_vert_tex
                                                                         .to_color_attachment()));
        bloom_blur_vert_buffer.clear_color(0.0, 0.0, 0.0, 1.0);

        let mut uniforms_horz_blur = uniform! {
            //for the first iteration: Use the bloom quad texture, from second iteration on this
            // will change to bloom_vert_tex
            image: &self.bloom_filter_tex,
            horizontal: true,
        };
        let uniforms_vert_blur = uniform! {
            image: &self.bloom_horz_tex,
            horizontal: false,
        };

        let mut first_iteration = true; //to know when we need to switch uniforms_horz_blur
        let mut horizontal = true;      //to switch between horizontal and vertical blur

        for _ in 0..10 {
            if horizontal {
                try!(bloom_blur_horz_buffer.draw(&self.quad_vertex_buffer,
                                                 &self.quad_index_buffer,
                                                 &self.bloom_blur_program,
                                                 &uniforms_horz_blur,
                                                 &Default::default()));
            } else {
                try!(bloom_blur_vert_buffer.draw(&self.quad_vertex_buffer,
                                                 &self.quad_index_buffer,
                                                 &self.bloom_blur_program,
                                                 &uniforms_vert_blur,
                                                 &Default::default()));
            }
            if first_iteration {
                uniforms_horz_blur = uniform! {
                    image: &self.bloom_vert_tex,
                    horizontal: true,
                };
                first_iteration = false;
            }
            horizontal = !horizontal;
        }

        // ==========================  blending  =============================

        let mut bloom_blend_buffer = try!(SimpleFrameBuffer::new(self.context.get_facade(),
                                                                 self.bloom_blend_tex
                                                                     .to_color_attachment()));

        bloom_blend_buffer.clear_color(0.0, 0.0, 0.0, 1.0);

        let u_blend_tex =
            if horizontal { &self.bloom_vert_tex } else { &self.bloom_horz_tex };

        let uniforms = uniform! {
            bloom_tex: u_blend_tex,
            world_tex: &self.quad_tex,
        };

        try!(bloom_blend_buffer.draw(&self.quad_vertex_buffer,
                                     &self.quad_index_buffer,
                                     &self.bloom_blend_program,
                                     &uniforms,
                                     &Default::default()));

        // ===================================================================
        // Tonemapping
        // ===================================================================

        let decal_texture = match bloom_state {
            0 => &self.quad_tex,
            2 => u_blend_tex,
            _ => &self.bloom_blend_tex,
        };

        let uniforms = uniform! {
            decal_texture: decal_texture,
            exposure: 1.0f32,
        };

        let mut target = self.context.get_facade().draw();
        target.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0);

        try!(target.draw(&self.quad_vertex_buffer,
                         &self.quad_index_buffer,
                         &self.tonemapping_program,
                         &uniforms,
                         &Default::default()));

        try!(target.finish());

        Ok(())
    }

    fn create_vertex_buf<F: Facade>(facade: &F) -> VertexBuffer<Vertex> {

        VertexBuffer::new(facade,
                          &[Vertex {
                                in_position: [-1.0, -1.0, 0.0, 1.0],
                                in_texcoord: [0.0, 0.0],
                            },
                            Vertex {
                                in_position: [1.0, -1.0, 0.0, 1.0],
                                in_texcoord: [1.0, 0.0],
                            },
                            Vertex {
                                in_position: [1.0, 1.0, 0.0, 1.0],
                                in_texcoord: [1.0, 1.0],
                            },
                            Vertex {
                                in_position: [-1.0, 1.0, 0.0, 1.0],
                                in_texcoord: [0.0, 1.0],
                            }])
            .unwrap()
    }

    // render update is called when a dimensions resize of the facade occures
    // recreates the 2D textures
    fn render_update(&mut self) {
        self.resolution = self.context.get_facade().get_framebuffer_dimensions();
        info!("time to resize framebuffer with dimensions {},{}",
              self.resolution.0,
              self.resolution.1);

        self.quad_tex = Texture2d::empty_with_format(self.context.get_facade(),
                                                     UncompressedFloatFormat::F32F32F32F32,
                                                     MipmapsOption::NoMipmap,
                                                     self.resolution.0,
                                                     self.resolution.1)
            .unwrap();

        self.depth_texture = DepthTexture2d::empty_with_format(self.context.get_facade(),
                                                               DepthFormat::F32,
                                                               MipmapsOption::NoMipmap,
                                                               self.resolution.0,
                                                               self.resolution.1)
            .unwrap();

        self.bloom_filter_tex = Texture2d::empty_with_format(self.context.get_facade(),
                                                             UncompressedFloatFormat::F32F32F32F32,
                                                             MipmapsOption::NoMipmap,
                                                             self.resolution.0,
                                                             self.resolution.1)
            .unwrap();

        self.bloom_horz_tex = Texture2d::empty_with_format(self.context.get_facade(),
                                                           UncompressedFloatFormat::F32F32F32F32,
                                                           MipmapsOption::NoMipmap,
                                                           self.resolution.0,
                                                           self.resolution.1)
            .unwrap();

        self.bloom_vert_tex = Texture2d::empty_with_format(self.context.get_facade(),
                                                           UncompressedFloatFormat::F32F32F32F32,
                                                           MipmapsOption::NoMipmap,
                                                           self.resolution.0,
                                                           self.resolution.1)
            .unwrap();

        self.bloom_blend_tex = Texture2d::empty_with_format(self.context.get_facade(),
                                                            UncompressedFloatFormat::F32F32F32F32,
                                                            MipmapsOption::NoMipmap,
                                                            self.resolution.0,
                                                            self.resolution.1)
            .unwrap();
    }
}

#[derive(Copy, Clone)]
struct Vertex {
    in_position: [f32; 4],
    in_texcoord: [f32; 2],
}

implement_vertex!(Vertex, in_position, in_texcoord);
<commit_msg>Increase shadow projection far plane<commit_after>use base::math::*;
use world::WorldView;
use glium::Surface;
use super::{Camera, GameContext};
use view::Sun;
use view::SkyView;
use std::rc::Rc;
use std::error::Error;
use std::env;
use super::weather::Weather;
use glium::texture::texture2d::Texture2d;
use glium::texture::{DepthFormat, DepthTexture2d, MipmapsOption, UncompressedFloatFormat};
use glium::framebuffer::SimpleFrameBuffer;
use glium::{IndexBuffer, Program, VertexBuffer};
use glium::index::PrimitiveType;
use glium::backend::Facade;
use glium::framebuffer::ToColorAttachment;

const SHADOW_MAP_SIZE: u32 = 1024;
const SHADOW_ORTHO_WIDTH: f32 = 300.0;
const SHADOW_ORTHO_HEIGHT: f32 = 300.0;
const SHADOW_ORTHO_NEAR: f32 = 100.0;
const SHADOW_ORTHO_FAR: f32 = 600.0;

pub struct Renderer {
    context: Rc<GameContext>,
    /// Screen-sized texture the scene is rendered into and then post-processed.
    quad_tex: Texture2d,
    /// Depth texture used by the normal render.
    depth_texture: DepthTexture2d,
    /// Depth texture rendered to from sun perspective.
    shadow_map: DepthTexture2d,
    /// Render the shadow map to the screen instead of the world.
    shadow_debug: bool,
    shadow_debug_program: Program,
    quad_vertex_buffer: VertexBuffer<Vertex>,
    quad_index_buffer: IndexBuffer<u16>,
    resolution: (u32, u32),
    bloom_filter_tex: Texture2d,
    bloom_horz_tex: Texture2d,
    bloom_vert_tex: Texture2d,
    bloom_blend_tex: Texture2d,
    tonemapping_program: Program,
    bloom_filter_program: Program,
    bloom_blur_program: Program,
    bloom_blend_program: Program,
}

impl Renderer {
    pub fn new(context: Rc<GameContext>) -> Self {

        // FIXME The index buffer is useless, switch to using `NoIndices` and
        // `TriangleStrip`
        let ibuf = IndexBuffer::new(context.get_facade(),
                                    PrimitiveType::TrianglesList,
                                    &[0u16, 1, 2, 0, 2, 3])
            .unwrap();

        let shadow_map = DepthTexture2d::empty_with_format(context.get_facade(),
                                                           DepthFormat::I16,
                                                           MipmapsOption::NoMipmap,
                                                           SHADOW_MAP_SIZE,
                                                           SHADOW_MAP_SIZE)
            .unwrap();

        let tonemapping_program = context.load_program("tonemapping").unwrap();
        let bloom_filter_program = context.load_program("bloom_filter").unwrap();
        let bloom_blur_program = context.load_program("bloom_blur").unwrap();
        let bloom_blend_program = context.load_program("bloom_blending").unwrap();
        let shadow_debug_program = context.load_program("shadow_debug").unwrap();

        let mut this = Renderer {
            context: context.clone(),
            quad_tex: Texture2d::empty(context.get_facade(), 1, 1).unwrap(),
            tonemapping_program: tonemapping_program,
            depth_texture: DepthTexture2d::empty(context.get_facade(), 1, 1).unwrap(),
            shadow_map: shadow_map,
            shadow_debug: env::var("SHADOW_DEBUG").is_ok(),
            shadow_debug_program: shadow_debug_program,
            quad_vertex_buffer: Renderer::create_vertex_buf(context.get_facade()),
            quad_index_buffer: ibuf,
            resolution: (0, 0),
            bloom_filter_tex: Texture2d::empty(context.get_facade(), 1, 1).unwrap(),
            bloom_horz_tex: Texture2d::empty(context.get_facade(), 1, 1).unwrap(),
            bloom_vert_tex: Texture2d::empty(context.get_facade(), 1, 1).unwrap(),
            bloom_blend_tex: Texture2d::empty(context.get_facade(), 1, 1).unwrap(),
            bloom_filter_program: bloom_filter_program,
            bloom_blur_program: bloom_blur_program,
            bloom_blend_program: bloom_blend_program,
        };

        // Create all textures with correct screen size
        this.render_update();
        this
    }

    /// Renders `world_view` into the renderer's shadow map from the
    /// perspective of the sun, whose position is `sun_pos`.
    ///
    /// Returns the MVP matrix used.
    fn render_shadow_map(&mut self,
                         world_view: &WorldView,
                         sun_pos: Point3f,
                         camera: Point3f)
                         -> Result<Matrix4<f32>, Box<Error>> {
        let mut shadow_target = try!(SimpleFrameBuffer::depth_only(self.context
                                                                       .get_facade(),
                                                                   &self.shadow_map));
        shadow_target.clear_depth(1.0);

        // Render the world from the perspective of the sun.
        let mut cam_pos = camera.to_vec();
        cam_pos.z = 0.0;
        let mut sun_cam = Camera::new_from_vector(sun_pos + cam_pos,
                                                  -sun_pos.to_vec(),
                                                  SHADOW_ORTHO_WIDTH / SHADOW_ORTHO_HEIGHT);
        // Set an orthographic projection matrix.
        sun_cam.set_proj_matrix(ortho(-SHADOW_ORTHO_WIDTH / 2.0,
                                      SHADOW_ORTHO_WIDTH / 2.0,
                                      -SHADOW_ORTHO_HEIGHT / 2.0,
                                      SHADOW_ORTHO_HEIGHT / 2.0,
                                      SHADOW_ORTHO_NEAR,
                                      SHADOW_ORTHO_FAR));
        world_view.draw_shadow(&mut shadow_target, &sun_cam);

        Ok(sun_cam.proj_matrix() * sun_cam.view_matrix())
    }

    /// Is called once every main loop iteration
    pub fn render(&mut self,
                  world_view: &WorldView,
                  camera: &Camera,
                  sun: &Sun,
                  weather: &mut Weather,
                  sky_view: &SkyView)
                  -> Result<(), Box<Error>> {
        // ===================================================================
        // check dimensions
        // ===================================================================
        let new_res = self.context.get_facade().get_framebuffer_dimensions();
        if self.resolution != new_res {
            self.render_update();
        }

        // ===================================================================
        // Creating shadow map
        // ===================================================================
        let depth_mvp = try!(self.render_shadow_map(world_view, sun.position(), camera.position));

        // ===================================================================
        // Rendering into HDR framebuffer
        // ===================================================================
        let mut hdr_buffer = try!(SimpleFrameBuffer::with_depth_buffer(self.context.get_facade(),
                                                                       &self.quad_tex,
                                                                       &self.depth_texture));
        hdr_buffer.clear_color_and_depth((0.0, 0.0, 1.0, 1.0), 1.0);

        if self.shadow_debug {
            let mut target = self.context.get_facade().draw();
            target.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0);
            try!(target.draw(&self.quad_vertex_buffer,
                             &self.quad_index_buffer,
                             &self.shadow_debug_program,
                             &uniform!{
                          decal_texture: &self.shadow_map,
                      },
                             &Default::default()));
            try!(target.finish());
            return Ok(());
        }

        world_view.draw(&mut hdr_buffer, camera, &self.shadow_map, &depth_mvp);
        sky_view.draw_skydome(&mut hdr_buffer, camera);
        sun.draw_sun(&mut hdr_buffer, camera);
        weather.draw(&mut hdr_buffer, camera);

        // ===================================================================
        // Creating the Bloom framebuffer
        // ===================================================================

        // =======================  light texture  ===========================

        // Bloom state
        // 0: Disable Bloom
        // 1: Enable Bloom
        // 2: Show only Bloom Map
        let bloom_state = 1;

        let uniforms = uniform! {
            decal_texture: &self.quad_tex,
            exposure: 1.0f32
        };

        let mut bloom_buffer = try!(SimpleFrameBuffer::new(self.context.get_facade(),
                                                           self.bloom_filter_tex
                                                               .to_color_attachment()));

        bloom_buffer.clear_color(0.0, 0.0, 0.0, 1.0);

        try!(bloom_buffer.draw(&self.quad_vertex_buffer,
                               &self.quad_index_buffer,
                               &self.bloom_filter_program,
                               &uniforms,
                               &Default::default()));

        // ============================  blur  ===============================

        let mut bloom_blur_horz_buffer = try!(SimpleFrameBuffer::new(self.context.get_facade(),
                                                                     self.bloom_horz_tex
                                                                         .to_color_attachment()));

        bloom_blur_horz_buffer.clear_color(0.0, 0.0, 0.0, 1.0);

        let mut bloom_blur_vert_buffer = try!(SimpleFrameBuffer::new(self.context.get_facade(),
                                                                     self.bloom_vert_tex
                                                                         .to_color_attachment()));
        bloom_blur_vert_buffer.clear_color(0.0, 0.0, 0.0, 1.0);

        let mut uniforms_horz_blur = uniform! {
            //for the first iteration: Use the bloom quad texture, from second iteration on this
            // will change to bloom_vert_tex
            image: &self.bloom_filter_tex,
            horizontal: true,
        };
        let uniforms_vert_blur = uniform! {
            image: &self.bloom_horz_tex,
            horizontal: false,
        };

        let mut first_iteration = true; //to know when we need to switch uniforms_horz_blur
        let mut horizontal = true;      //to switch between horizontal and vertical blur

        for _ in 0..10 {
            if horizontal {
                try!(bloom_blur_horz_buffer.draw(&self.quad_vertex_buffer,
                                                 &self.quad_index_buffer,
                                                 &self.bloom_blur_program,
                                                 &uniforms_horz_blur,
                                                 &Default::default()));
            } else {
                try!(bloom_blur_vert_buffer.draw(&self.quad_vertex_buffer,
                                                 &self.quad_index_buffer,
                                                 &self.bloom_blur_program,
                                                 &uniforms_vert_blur,
                                                 &Default::default()));
            }
            if first_iteration {
                uniforms_horz_blur = uniform! {
                    image: &self.bloom_vert_tex,
                    horizontal: true,
                };
                first_iteration = false;
            }
            horizontal = !horizontal;
        }

        // ==========================  blending  =============================

        let mut bloom_blend_buffer = try!(SimpleFrameBuffer::new(self.context.get_facade(),
                                                                 self.bloom_blend_tex
                                                                     .to_color_attachment()));

        bloom_blend_buffer.clear_color(0.0, 0.0, 0.0, 1.0);

        let u_blend_tex =
            if horizontal { &self.bloom_vert_tex } else { &self.bloom_horz_tex };

        let uniforms = uniform! {
            bloom_tex: u_blend_tex,
            world_tex: &self.quad_tex,
        };

        try!(bloom_blend_buffer.draw(&self.quad_vertex_buffer,
                                     &self.quad_index_buffer,
                                     &self.bloom_blend_program,
                                     &uniforms,
                                     &Default::default()));

        // ===================================================================
        // Tonemapping
        // ===================================================================

        let decal_texture = match bloom_state {
            0 => &self.quad_tex,
            2 => u_blend_tex,
            _ => &self.bloom_blend_tex,
        };

        let uniforms = uniform! {
            decal_texture: decal_texture,
            exposure: 1.0f32,
        };

        let mut target = self.context.get_facade().draw();
        target.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0);

        try!(target.draw(&self.quad_vertex_buffer,
                         &self.quad_index_buffer,
                         &self.tonemapping_program,
                         &uniforms,
                         &Default::default()));

        try!(target.finish());

        Ok(())
    }

    fn create_vertex_buf<F: Facade>(facade: &F) -> VertexBuffer<Vertex> {

        VertexBuffer::new(facade,
                          &[Vertex {
                                in_position: [-1.0, -1.0, 0.0, 1.0],
                                in_texcoord: [0.0, 0.0],
                            },
                            Vertex {
                                in_position: [1.0, -1.0, 0.0, 1.0],
                                in_texcoord: [1.0, 0.0],
                            },
                            Vertex {
                                in_position: [1.0, 1.0, 0.0, 1.0],
                                in_texcoord: [1.0, 1.0],
                            },
                            Vertex {
                                in_position: [-1.0, 1.0, 0.0, 1.0],
                                in_texcoord: [0.0, 1.0],
                            }])
            .unwrap()
    }

    // render update is called when a dimensions resize of the facade occures
    // recreates the 2D textures
    fn render_update(&mut self) {
        self.resolution = self.context.get_facade().get_framebuffer_dimensions();
        info!("time to resize framebuffer with dimensions {},{}",
              self.resolution.0,
              self.resolution.1);

        self.quad_tex = Texture2d::empty_with_format(self.context.get_facade(),
                                                     UncompressedFloatFormat::F32F32F32F32,
                                                     MipmapsOption::NoMipmap,
                                                     self.resolution.0,
                                                     self.resolution.1)
            .unwrap();

        self.depth_texture = DepthTexture2d::empty_with_format(self.context.get_facade(),
                                                               DepthFormat::F32,
                                                               MipmapsOption::NoMipmap,
                                                               self.resolution.0,
                                                               self.resolution.1)
            .unwrap();

        self.bloom_filter_tex = Texture2d::empty_with_format(self.context.get_facade(),
                                                             UncompressedFloatFormat::F32F32F32F32,
                                                             MipmapsOption::NoMipmap,
                                                             self.resolution.0,
                                                             self.resolution.1)
            .unwrap();

        self.bloom_horz_tex = Texture2d::empty_with_format(self.context.get_facade(),
                                                           UncompressedFloatFormat::F32F32F32F32,
                                                           MipmapsOption::NoMipmap,
                                                           self.resolution.0,
                                                           self.resolution.1)
            .unwrap();

        self.bloom_vert_tex = Texture2d::empty_with_format(self.context.get_facade(),
                                                           UncompressedFloatFormat::F32F32F32F32,
                                                           MipmapsOption::NoMipmap,
                                                           self.resolution.0,
                                                           self.resolution.1)
            .unwrap();

        self.bloom_blend_tex = Texture2d::empty_with_format(self.context.get_facade(),
                                                            UncompressedFloatFormat::F32F32F32F32,
                                                            MipmapsOption::NoMipmap,
                                                            self.resolution.0,
                                                            self.resolution.1)
            .unwrap();
    }
}

#[derive(Copy, Clone)]
struct Vertex {
    in_position: [f32; 4],
    in_texcoord: [f32; 2],
}

implement_vertex!(Vertex, in_position, in_texcoord);
<|endoftext|>


<commit_before>//! Descriptor sets and layouts.

use std::fmt;
use std::ops::Range;

use {Backend};
use image::ImageLayout;
use super::ShaderStageFlags;

///
// TODO: Grasping and remembering the differences between these
//       types is a tough task. We might be able to come up with better names?
//       Or even use tuples to describe functionality instead of coming up with fancy names.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum DescriptorType {
    /// Controls filtering parameters for sampling from images.
    Sampler,
    /// Allows sampling (filtered loading) from associated image memory.
    /// Usually combined with a `Sampler`.
    SampledImage,
    /// Allows atomic operations, (non-filtered) loads and stores on image memory.
    StorageImage,
    /// Read-only, formatted buffer.
    UniformTexelBuffer,
    /// Read-Write, formatted buffer.
    StorageTexelBuffer,
    /// Read-only, structured buffer.
    UniformBuffer,
    /// Read-Write, structured buffer.
    StorageBuffer,
    /// Allows unfiltered loads of pixel local data in the fragment shader.
    InputAttachment,

    // TODO: Dynamic descriptors
}

/// Binding descriptiong of a descriptor set
///
/// A descriptor set consists of multiple binding points.
/// Each binding point contains one or multiple descriptors of a certain type.
/// The binding point is only valid for the pipelines stages specified.
///
/// The binding _must_ match with the corresponding shader interface.
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct DescriptorSetLayoutBinding {
    /// Integer identifier of the binding.
    pub binding: usize,
    /// Type of the bound descriptors.
    pub ty: DescriptorType,
    /// Number of descriptors bound.
    pub count: usize,
    /// Valid shader stages.
    pub stage_flags: ShaderStageFlags,

    // TODO: immutable samplers?
}

/// Set of descriptors of a specific type.
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct DescriptorRangeDesc {
    /// Type of the stored descriptors.
    pub ty: DescriptorType,
    /// Amount of space.
    pub count: usize,
}

///
pub trait DescriptorPool<B: Backend>: Send + fmt::Debug {
    /// Allocate one or multiple descriptor sets from the pool.
    ///
    /// Each descriptor set will be allocated from the pool according to the corresponding set layout.
    /// The descriptor pool _must_ have enough space in to allocate the required descriptors.
    /// Descriptors will become invalid once the pool got reset. Usage of invalidated descriptor sets results
    /// in undefined behavior.
    fn allocate_sets(&mut self, layouts: &[&B::DescriptorSetLayout]) -> Vec<B::DescriptorSet>;

    ///
    fn reset(&mut self);
}

#[allow(missing_docs)] //TODO
pub struct DescriptorSetWrite<'a, 'b, B: Backend> {
    pub set: &'a B::DescriptorSet,
    pub binding: usize,
    pub array_offset: usize,
    pub write: DescriptorWrite<'b, B>,
}

#[allow(missing_docs)] //TODO
pub enum DescriptorWrite<'a, B: Backend> {
    Sampler(Vec<&'a B::Sampler>),
    SampledImage(Vec<(&'a B::ImageView, ImageLayout)>),
    StorageImage(Vec<(&'a B::ImageView, ImageLayout)>),
    InputAttachment(Vec<(&'a B::ImageView, ImageLayout)>),
    UniformBuffer(Vec<(&'a B::Buffer, Range<u64>)>),
    StorageBuffer(Vec<(&'a B::Buffer, Range<u64>)>),
    UniformTexelBuffer(Vec<&'a B::BufferView>),
    StorageTexelBuffer(Vec<&'a B::BufferView>),
}
<commit_msg>Require `DescriptorPool` to be `Sync`<commit_after>//! Descriptor sets and layouts.

use std::fmt;
use std::ops::Range;

use {Backend};
use image::ImageLayout;
use super::ShaderStageFlags;

///
// TODO: Grasping and remembering the differences between these
//       types is a tough task. We might be able to come up with better names?
//       Or even use tuples to describe functionality instead of coming up with fancy names.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum DescriptorType {
    /// Controls filtering parameters for sampling from images.
    Sampler,
    /// Allows sampling (filtered loading) from associated image memory.
    /// Usually combined with a `Sampler`.
    SampledImage,
    /// Allows atomic operations, (non-filtered) loads and stores on image memory.
    StorageImage,
    /// Read-only, formatted buffer.
    UniformTexelBuffer,
    /// Read-Write, formatted buffer.
    StorageTexelBuffer,
    /// Read-only, structured buffer.
    UniformBuffer,
    /// Read-Write, structured buffer.
    StorageBuffer,
    /// Allows unfiltered loads of pixel local data in the fragment shader.
    InputAttachment,

    // TODO: Dynamic descriptors
}

/// Binding descriptiong of a descriptor set
///
/// A descriptor set consists of multiple binding points.
/// Each binding point contains one or multiple descriptors of a certain type.
/// The binding point is only valid for the pipelines stages specified.
///
/// The binding _must_ match with the corresponding shader interface.
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct DescriptorSetLayoutBinding {
    /// Integer identifier of the binding.
    pub binding: usize,
    /// Type of the bound descriptors.
    pub ty: DescriptorType,
    /// Number of descriptors bound.
    pub count: usize,
    /// Valid shader stages.
    pub stage_flags: ShaderStageFlags,

    // TODO: immutable samplers?
}

/// Set of descriptors of a specific type.
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct DescriptorRangeDesc {
    /// Type of the stored descriptors.
    pub ty: DescriptorType,
    /// Amount of space.
    pub count: usize,
}

///
pub trait DescriptorPool<B: Backend>: Send + Sync + fmt::Debug {
    /// Allocate one or multiple descriptor sets from the pool.
    ///
    /// Each descriptor set will be allocated from the pool according to the corresponding set layout.
    /// The descriptor pool _must_ have enough space in to allocate the required descriptors.
    /// Descriptors will become invalid once the pool got reset. Usage of invalidated descriptor sets results
    /// in undefined behavior.
    fn allocate_sets(&mut self, layouts: &[&B::DescriptorSetLayout]) -> Vec<B::DescriptorSet>;

    ///
    fn reset(&mut self);
}

#[allow(missing_docs)] //TODO
pub struct DescriptorSetWrite<'a, 'b, B: Backend> {
    pub set: &'a B::DescriptorSet,
    pub binding: usize,
    pub array_offset: usize,
    pub write: DescriptorWrite<'b, B>,
}

#[allow(missing_docs)] //TODO
pub enum DescriptorWrite<'a, B: Backend> {
    Sampler(Vec<&'a B::Sampler>),
    SampledImage(Vec<(&'a B::ImageView, ImageLayout)>),
    StorageImage(Vec<(&'a B::ImageView, ImageLayout)>),
    InputAttachment(Vec<(&'a B::ImageView, ImageLayout)>),
    UniformBuffer(Vec<(&'a B::Buffer, Range<u64>)>),
    StorageBuffer(Vec<(&'a B::Buffer, Range<u64>)>),
    UniformTexelBuffer(Vec<&'a B::BufferView>),
    StorageTexelBuffer(Vec<&'a B::BufferView>),
}
<|endoftext|>


<commit_before>/* diosix hypervisor's system for passing messages between physical CPU cores and services
 *
 * (c) Chris Williams, 2019-2020.
 *
 * See LICENSE for usage and copying.
 */

use super::lock::Mutex;
use alloc::collections::vec_deque::VecDeque;
use hashbrown::hash_map::HashMap;
use super::error::Cause;
use super::service::{self, ServiceID};
use super::capsule::CapsuleID;
use super::pcore::{PhysicalCoreID, PhysicalCore};

/* here's how message passing works, depending on the target:
    * To an individual physical core:
        1. locate the physical core's message queue in MAILBOXES
        2. insert the message at the end of the queue
        3. interrupt the physical CPU core to check its mailbox
    * To all physical cores:
        1. iterate over each physical core in MAILBOXES
        2. insert a copy of the message in the message queue of each physical CPU
        3. interrupt each physical CPU core to check its mailbox
    * To a service registered by a capsule:
        1. locate the service's mailbox
        2. insert the message into the mailbox
        3. raise an interrupt or wait for the capsule to poll the mailbox
*/

/* maintain a mailbox of messages per physical CPU core */
lazy_static!
{
    static ref MAILBOXES: Mutex<HashMap<PhysicalCoreID, VecDeque<Message>>> = Mutex::new(HashMap::new());
}

/* create a mailbox for physical CPU core coreid */
pub fn create_mailbox(coreid: PhysicalCoreID)
{
    MAILBOXES.lock().insert(coreid, VecDeque::<Message>::new());
}

#[derive(Clone)]
pub enum Sender
{
    PhysicalCore(PhysicalCoreID),
    Capsule(CapsuleID)
}

#[derive(Clone, Copy)]
pub enum Recipient
{
    Broadcast,                      /* send to all physical CPU cores */
    PhysicalCore(PhysicalCoreID),   /* send to a single physical CPU core */
    Service(ServiceID)              /* send to a single registered service */
}

impl Recipient
{
    /* broadcast message to all physical cores */
    pub fn send_to_all() -> Recipient { Recipient::Broadcast }

    /* send to a particular physical core */
    pub fn send_to_pcore(id: PhysicalCoreID) -> Recipient
    {
        Recipient::PhysicalCore(id)
    }

    /* send to a particular capsule-hosted service */
    pub fn send_to_service(id: ServiceID) -> Recipient
    {
        Recipient::Service(id)
    }
}

#[derive(Clone, Copy)]
pub enum MessageContent
{
    /* warn all physical CPUs capsule is dying */
    CapsuleTeardown(CapsuleID),
    /* return any queued virtual core to the global queue for other physical CPUs to schedule */
    DisownQueuedVirtualCore
}

#[derive(Clone)]
pub struct Message
{
    sender: Sender,
    receiver: Recipient,
    code: MessageContent
}

impl Message
{
    /* create a new message
       => recv = end point to send the message to
          data = message to send to the recipient
       <= returns message structure
    */
    pub fn new(recv: Recipient, data: MessageContent) -> Message
    {
        Message
        {
            receiver: recv,
            code: data,

            /* determine sender from message type */
            sender: match data
            {
                MessageContent::CapsuleTeardown(_) => Sender::PhysicalCore(PhysicalCore::get_id()),
                MessageContent::DisownQueuedVirtualCore => Sender::PhysicalCore(PhysicalCore::get_id())
            }
        }
    }

    pub fn get_receiver(&self) -> Recipient
    {
        self.receiver
    }
}

/* send the given message msg, consuming it so it can't be reused or resent */
pub fn send(msg: Message) -> Result<(), Cause>
{
    let receiver = msg.receiver;
    match receiver
    {
        /* iterate over all physical CPU cores */
        Recipient::Broadcast =>
        {
            for (_, mailbox) in MAILBOXES.lock().iter_mut()
            {
                mailbox.push_back(msg.clone())
            }
        },

        /* send to a particular physical CPU core */
        Recipient::PhysicalCore(pid) =>
        {
            if let Some(mailbox) = MAILBOXES.lock().get_mut(&pid)
            {
                mailbox.push_back(msg);
            }
            else
            {
                return Err(Cause::PhysicalCoreBadID);
            }
        },

        /* send to a service */
        Recipient::Service(_) =>
        {
            return service::send(msg);
        }
    };

    Ok(())
}
<commit_msg>Use named mutex<commit_after>/* diosix hypervisor's system for passing messages between physical CPU cores and services
 *
 * (c) Chris Williams, 2019-2020.
 *
 * See LICENSE for usage and copying.
 */

use super::lock::Mutex;
use alloc::collections::vec_deque::VecDeque;
use hashbrown::hash_map::HashMap;
use super::error::Cause;
use super::service::{self, ServiceID};
use super::capsule::CapsuleID;
use super::pcore::{PhysicalCoreID, PhysicalCore};

/* here's how message passing works, depending on the target:
    * To an individual physical core:
        1. locate the physical core's message queue in MAILBOXES
        2. insert the message at the end of the queue
        3. interrupt the physical CPU core to check its mailbox
    * To all physical cores:
        1. iterate over each physical core in MAILBOXES
        2. insert a copy of the message in the message queue of each physical CPU
        3. interrupt each physical CPU core to check its mailbox
    * To a service registered by a capsule:
        1. locate the service's mailbox
        2. insert the message into the mailbox
        3. raise an interrupt or wait for the capsule to poll the mailbox
*/

/* maintain a mailbox of messages per physical CPU core */
lazy_static!
{
    static ref MAILBOXES: Mutex<HashMap<PhysicalCoreID, VecDeque<Message>>> = Mutex::new("mailbox", HashMap::new());
}

/* create a mailbox for physical CPU core coreid */
pub fn create_mailbox(coreid: PhysicalCoreID)
{
    MAILBOXES.lock().insert(coreid, VecDeque::<Message>::new());
}

#[derive(Clone)]
pub enum Sender
{
    PhysicalCore(PhysicalCoreID),
    Capsule(CapsuleID)
}

#[derive(Clone, Copy)]
pub enum Recipient
{
    Broadcast,                      /* send to all physical CPU cores */
    PhysicalCore(PhysicalCoreID),   /* send to a single physical CPU core */
    Service(ServiceID)              /* send to a single registered service */
}

impl Recipient
{
    /* broadcast message to all physical cores */
    pub fn send_to_all() -> Recipient { Recipient::Broadcast }

    /* send to a particular physical core */
    pub fn send_to_pcore(id: PhysicalCoreID) -> Recipient
    {
        Recipient::PhysicalCore(id)
    }

    /* send to a particular capsule-hosted service */
    pub fn send_to_service(id: ServiceID) -> Recipient
    {
        Recipient::Service(id)
    }
}

#[derive(Clone, Copy)]
pub enum MessageContent
{
    /* warn all physical CPUs capsule is dying */
    CapsuleTeardown(CapsuleID),
    /* return any queued virtual core to the global queue for other physical CPUs to schedule */
    DisownQueuedVirtualCore
}

#[derive(Clone)]
pub struct Message
{
    sender: Sender,
    receiver: Recipient,
    code: MessageContent
}

impl Message
{
    /* create a new message
       => recv = end point to send the message to
          data = message to send to the recipient
       <= returns message structure
    */
    pub fn new(recv: Recipient, data: MessageContent) -> Message
    {
        Message
        {
            receiver: recv,
            code: data,

            /* determine sender from message type */
            sender: match data
            {
                MessageContent::CapsuleTeardown(_) => Sender::PhysicalCore(PhysicalCore::get_id()),
                MessageContent::DisownQueuedVirtualCore => Sender::PhysicalCore(PhysicalCore::get_id())
            }
        }
    }

    pub fn get_receiver(&self) -> Recipient
    {
        self.receiver
    }
}

/* send the given message msg, consuming it so it can't be reused or resent */
pub fn send(msg: Message) -> Result<(), Cause>
{
    let receiver = msg.receiver;
    match receiver
    {
        /* iterate over all physical CPU cores */
        Recipient::Broadcast =>
        {
            for (_, mailbox) in MAILBOXES.lock().iter_mut()
            {
                mailbox.push_back(msg.clone())
            }
        },

        /* send to a particular physical CPU core */
        Recipient::PhysicalCore(pid) =>
        {
            if let Some(mailbox) = MAILBOXES.lock().get_mut(&pid)
            {
                mailbox.push_back(msg);
            }
            else
            {
                return Err(Cause::PhysicalCoreBadID);
            }
        },

        /* send to a service */
        Recipient::Service(_) =>
        {
            return service::send(msg);
        }
    };

    Ok(())
}
<|endoftext|>


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

//! The implementations of `Rand` for the built-in types.

use char;
use int;
use option::{Option, Some, None};
use rand::{Rand,Rng};
use u32;
use uint;

impl Rand for int {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> int {
        if int::bits == 32 {
            rng.gen::<i32>() as int
        } else {
            rng.gen::<i64>() as int
        }
    }
}

impl Rand for i8 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i8 {
        rng.next_u32() as i8
    }
}

impl Rand for i16 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i16 {
        rng.next_u32() as i16
    }
}

impl Rand for i32 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i32 {
        rng.next_u32() as i32
    }
}

impl Rand for i64 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i64 {
        rng.next_u64() as i64
    }
}

impl Rand for uint {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> uint {
        if uint::bits == 32 {
            rng.gen::<u32>() as uint
        } else {
            rng.gen::<u64>() as uint
        }
    }
}

impl Rand for u8 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u8 {
        rng.next_u32() as u8
    }
}

impl Rand for u16 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u16 {
        rng.next_u32() as u16
    }
}

impl Rand for u32 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u32 {
        rng.next_u32()
    }
}

impl Rand for u64 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u64 {
        rng.next_u64()
    }
}

impl Rand for f32 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> f32 {
        rng.gen::<f64>() as f32
    }
}

static SCALE : f64 = (u32::max_value as f64) + 1.0f64;
impl Rand for f64 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> f64 {
        let u1 = rng.next_u32() as f64;
        let u2 = rng.next_u32() as f64;
        let u3 = rng.next_u32() as f64;

        ((u1 / SCALE + u2) / SCALE + u3) / SCALE
    }
}

impl Rand for char {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> char {
        // a char is 21 bits
        static CHAR_MASK: u32 = 0x001f_ffff;
        loop {
            // Rejection sampling. About 0.2% of numbers with at most
            // 21-bits are invalid codepoints (surrogates), so this
            // will succeed first go almost every time.
            match char::from_u32(rng.next_u32() & CHAR_MASK) {
                Some(c) => return c,
                None => {}
            }
        }
    }
}

impl Rand for bool {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> bool {
        rng.gen::<u8>() & 1 == 1
    }
}

macro_rules! tuple_impl {
    // use variables to indicate the arity of the tuple
    ($($tyvar:ident),* ) => {
        // the trailing commas are for the 1 tuple
        impl<
            $( $tyvar : Rand ),*
            > Rand for ( $( $tyvar ),* , ) {

            #[inline]
            fn rand<R: Rng>(_rng: &mut R) -> ( $( $tyvar ),* , ) {
                (
                    // use the $tyvar's to get the appropriate number of
                    // repeats (they're not actually needed)
                    $(
                        _rng.gen::<$tyvar>()
                    ),*
                    ,
                )
            }
        }
    }
}

impl Rand for () {
    #[inline]
    fn rand<R: Rng>(_: &mut R) -> () { () }
}
tuple_impl!{A}
tuple_impl!{A, B}
tuple_impl!{A, B, C}
tuple_impl!{A, B, C, D}
tuple_impl!{A, B, C, D, E}
tuple_impl!{A, B, C, D, E, F}
tuple_impl!{A, B, C, D, E, F, G}
tuple_impl!{A, B, C, D, E, F, G, H}
tuple_impl!{A, B, C, D, E, F, G, H, I}
tuple_impl!{A, B, C, D, E, F, G, H, I, J}

impl<T:Rand> Rand for Option<T> {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> Option<T> {
        if rng.gen() {
            Some(rng.gen())
        } else {
            None
        }
    }
}

impl<T: Rand> Rand for ~T {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> ~T { ~rng.gen() }
}

impl<T: Rand + 'static> Rand for @T {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> @T { @rng.gen() }
}
<commit_msg>std::rand: adjust the f32 & f64 Rand instances.<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The implementations of `Rand` for the built-in types.

use char;
use int;
use option::{Option, Some, None};
use rand::{Rand,Rng};
use uint;

impl Rand for int {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> int {
        if int::bits == 32 {
            rng.gen::<i32>() as int
        } else {
            rng.gen::<i64>() as int
        }
    }
}

impl Rand for i8 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i8 {
        rng.next_u32() as i8
    }
}

impl Rand for i16 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i16 {
        rng.next_u32() as i16
    }
}

impl Rand for i32 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i32 {
        rng.next_u32() as i32
    }
}

impl Rand for i64 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i64 {
        rng.next_u64() as i64
    }
}

impl Rand for uint {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> uint {
        if uint::bits == 32 {
            rng.gen::<u32>() as uint
        } else {
            rng.gen::<u64>() as uint
        }
    }
}

impl Rand for u8 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u8 {
        rng.next_u32() as u8
    }
}

impl Rand for u16 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u16 {
        rng.next_u32() as u16
    }
}

impl Rand for u32 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u32 {
        rng.next_u32()
    }
}

impl Rand for u64 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u64 {
        rng.next_u64()
    }
}

impl Rand for f32 {
    /// A random `f32` in the range `[0, 1)`.
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> f32 {
        // weird, but this is the easiest way to get 2**32
        static SCALE: f32 = 2.0 * (1u32 << 31) as f32;
        rng.next_u32() as f32 / SCALE
    }
}

impl Rand for f64 {
    /// A random `f64` in the range `[0, 1)`.
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> f64 {
        // weird, but this is the easiest way to get 2**64
        static SCALE: f64 = 2.0 * (1u64 << 63) as f64;

        rng.next_u64() as f64 / SCALE
    }
}

impl Rand for char {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> char {
        // a char is 21 bits
        static CHAR_MASK: u32 = 0x001f_ffff;
        loop {
            // Rejection sampling. About 0.2% of numbers with at most
            // 21-bits are invalid codepoints (surrogates), so this
            // will succeed first go almost every time.
            match char::from_u32(rng.next_u32() & CHAR_MASK) {
                Some(c) => return c,
                None => {}
            }
        }
    }
}

impl Rand for bool {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> bool {
        rng.gen::<u8>() & 1 == 1
    }
}

macro_rules! tuple_impl {
    // use variables to indicate the arity of the tuple
    ($($tyvar:ident),* ) => {
        // the trailing commas are for the 1 tuple
        impl<
            $( $tyvar : Rand ),*
            > Rand for ( $( $tyvar ),* , ) {

            #[inline]
            fn rand<R: Rng>(_rng: &mut R) -> ( $( $tyvar ),* , ) {
                (
                    // use the $tyvar's to get the appropriate number of
                    // repeats (they're not actually needed)
                    $(
                        _rng.gen::<$tyvar>()
                    ),*
                    ,
                )
            }
        }
    }
}

impl Rand for () {
    #[inline]
    fn rand<R: Rng>(_: &mut R) -> () { () }
}
tuple_impl!{A}
tuple_impl!{A, B}
tuple_impl!{A, B, C}
tuple_impl!{A, B, C, D}
tuple_impl!{A, B, C, D, E}
tuple_impl!{A, B, C, D, E, F}
tuple_impl!{A, B, C, D, E, F, G}
tuple_impl!{A, B, C, D, E, F, G, H}
tuple_impl!{A, B, C, D, E, F, G, H, I}
tuple_impl!{A, B, C, D, E, F, G, H, I, J}

impl<T:Rand> Rand for Option<T> {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> Option<T> {
        if rng.gen() {
            Some(rng.gen())
        } else {
            None
        }
    }
}

impl<T: Rand> Rand for ~T {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> ~T { ~rng.gen() }
}

impl<T: Rand + 'static> Rand for @T {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> @T { @rng.gen() }
}
<|endoftext|>


<commit_before>#![feature(test)]
extern crate test;
extern crate sudoku;
use sudoku::Sudoku;

fn read_sudokus(sudokus_str: &str) -> Vec<Sudoku> {
    let sudokus_str = sudokus_str.replace("\r\n", "\n");
    let mut sudokus = vec![];
    for i in 0.. {
        // 9 lines with 9 cells each + 1 linefeed character per line
        // + 1 LF char between each sudoku
        // 9*(9+1) + 1
        let rg = 0+i*91..90+i*91;
        if rg.end > sudokus_str.len() { break }
        sudokus.push( Sudoku::from_str( &sudokus_str[rg] ).expect("Benchmark sudokus file contains sudoku in incorrect format") )
    }
    sudokus
}

#[bench]
fn easy_sudokus_solve(b: &mut test::Bencher) {
    let sudokus = read_sudokus( &include_str!("../sudokus/easy_sudokus.txt") );
    let sudokus_1000 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();;
	b.iter(|| {
		for mut sudoku in sudokus_1000.iter().cloned() { sudoku.solve(); }
	})
}

#[bench]
fn easy_sudokus_solve_unique(b: &mut test::Bencher) {
    let sudokus = read_sudokus( &include_str!("../sudokus/easy_sudokus.txt") );
    let sudokus_1000 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();;
	b.iter(|| {
		for sudoku in sudokus_1000.iter().cloned() { sudoku.solve_unique(); }
	})
}

#[bench]
fn easy_sudokus_solve_one(b: &mut test::Bencher) {
    let sudokus = read_sudokus( &include_str!("../sudokus/easy_sudokus.txt") );
    let sudokus_1000 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();;
	b.iter(|| {
		for sudoku in sudokus_1000.iter().cloned() { sudoku.solve_one(); }
	})
}

#[bench]
fn easy_sudokus_solve_at_most_100(b: &mut test::Bencher) {
    let sudokus = read_sudokus( &include_str!("../sudokus/easy_sudokus.txt") );
    let sudokus_1000 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();;
	b.iter(|| {
		for sudoku in sudokus_1000.iter().cloned() { sudoku.solve_at_most(100); }
	})
}

#[bench]
fn medium_sudokus_solve(b: &mut test::Bencher) {
    let sudokus = read_sudokus( &include_str!("../sudokus/medium_sudokus.txt") );
    let sudokus_1000 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();;
	b.iter(|| {
		for mut sudoku in sudokus_1000.iter().cloned() { sudoku.solve(); }
	})
}

#[bench]
fn medium_sudokus_solve_unique(b: &mut test::Bencher) {
    let sudokus = read_sudokus( &include_str!("../sudokus/medium_sudokus.txt") );
    let sudokus_1000 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();;
	b.iter(|| {
		for sudoku in sudokus_1000.iter().cloned() { sudoku.solve_unique(); }
	})
}

#[bench]
fn medium_sudokus_solve_one(b: &mut test::Bencher) {
    let sudokus = read_sudokus( &include_str!("../sudokus/medium_sudokus.txt") );
    let sudokus_1000 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();;
	b.iter(|| {
		for sudoku in sudokus_1000.iter().cloned() { sudoku.solve_one(); }
	})
}

#[bench]
fn medium_sudokus_solve_at_most_100(b: &mut test::Bencher) {
    let sudokus = read_sudokus( &include_str!("../sudokus/medium_sudokus.txt") );
    let sudokus_1000 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();;
	b.iter(|| {
		for sudoku in sudokus_1000.iter().cloned() { sudoku.solve_at_most(100); }
	})
}

#[bench]
fn hard_sudokus_solve(b: &mut test::Bencher) {
    let sudokus = read_sudokus( &include_str!("../sudokus/hard_sudokus.txt") );
    let sudokus_1000 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();;
	b.iter(|| {
		for mut sudoku in sudokus_1000.iter().cloned() { sudoku.solve(); }
	})
}

#[bench]
fn hard_sudokus_solve_unique(b: &mut test::Bencher) {
    let sudokus = read_sudokus( &include_str!("../sudokus/hard_sudokus.txt") );
    let sudokus_1000 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();;
	b.iter(|| {
		for sudoku in sudokus_1000.iter().cloned() { sudoku.solve_unique(); }
	})
}

#[bench]
fn hard_sudokus_solve_one(b: &mut test::Bencher) {
    let sudokus = read_sudokus( &include_str!("../sudokus/hard_sudokus.txt") );
    let sudokus_1000 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();;
	b.iter(|| {
		for sudoku in sudokus_1000.iter().cloned() { sudoku.solve_one(); }
	})
}

#[bench]
fn hard_sudokus_solve_at_most_100(b: &mut test::Bencher) {
    let sudokus = read_sudokus( &include_str!("../sudokus/hard_sudokus.txt") );
    let sudokus_1000 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();;
	b.iter(|| {
		for sudoku in sudokus_1000.iter().cloned() { sudoku.solve_at_most(100); }
	})
}
<commit_msg>fix bench suite<commit_after>#![feature(test)]
extern crate test;
extern crate sudoku;
use sudoku::Sudoku;

fn read_sudokus(sudokus_str: &str) -> Vec<Sudoku> {
    sudokus_str.lines()
        .map(|line| Sudoku::from_str_line(line).unwrap_or_else(|err| panic!("{:?}", err)))
        .collect()
}

#[bench]
fn easy_sudokus_solve(b: &mut test::Bencher) {
    let sudokus = read_sudokus( &include_str!("../sudokus/Lines/easy_sudokus.txt") );
    let sudokus_1000 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();;
	b.iter(|| {
		for mut sudoku in sudokus_1000.iter().cloned() { sudoku.solve(); }
	})
}

#[bench]
fn easy_sudokus_solve_unique(b: &mut test::Bencher) {
    let sudokus = read_sudokus( &include_str!("../sudokus/Lines/easy_sudokus.txt") );
    let sudokus_1000 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();;
	b.iter(|| {
		for sudoku in sudokus_1000.iter().cloned() { sudoku.solve_unique(); }
	})
}

#[bench]
fn easy_sudokus_solve_one(b: &mut test::Bencher) {
    let sudokus = read_sudokus( &include_str!("../sudokus/Lines/easy_sudokus.txt") );
    let sudokus_1000 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();;
	b.iter(|| {
		for sudoku in sudokus_1000.iter().cloned() { sudoku.solve_one(); }
	})
}

#[bench]
fn easy_sudokus_solve_at_most_100(b: &mut test::Bencher) {
    let sudokus = read_sudokus( &include_str!("../sudokus/Lines/easy_sudokus.txt") );
    let sudokus_1000 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();;
	b.iter(|| {
		for sudoku in sudokus_1000.iter().cloned() { sudoku.solve_at_most(100); }
	})
}

#[bench]
fn medium_sudokus_solve(b: &mut test::Bencher) {
    let sudokus = read_sudokus( &include_str!("../sudokus/Lines/medium_sudokus.txt") );
    let sudokus_1000 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();;
	b.iter(|| {
		for mut sudoku in sudokus_1000.iter().cloned() { sudoku.solve(); }
	})
}

#[bench]
fn medium_sudokus_solve_unique(b: &mut test::Bencher) {
    let sudokus = read_sudokus( &include_str!("../sudokus/Lines/medium_sudokus.txt") );
    let sudokus_1000 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();;
	b.iter(|| {
		for sudoku in sudokus_1000.iter().cloned() { sudoku.solve_unique(); }
	})
}

#[bench]
fn medium_sudokus_solve_one(b: &mut test::Bencher) {
    let sudokus = read_sudokus( &include_str!("../sudokus/Lines/medium_sudokus.txt") );
    let sudokus_1000 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();;
	b.iter(|| {
		for sudoku in sudokus_1000.iter().cloned() { sudoku.solve_one(); }
	})
}

#[bench]
fn medium_sudokus_solve_at_most_100(b: &mut test::Bencher) {
    let sudokus = read_sudokus( &include_str!("../sudokus/Lines/medium_sudokus.txt") );
    let sudokus_1000 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();;
	b.iter(|| {
		for sudoku in sudokus_1000.iter().cloned() { sudoku.solve_at_most(100); }
	})
}

#[bench]
fn hard_sudokus_solve(b: &mut test::Bencher) {
    let sudokus = read_sudokus( &include_str!("../sudokus/Lines/hard_sudokus.txt") );
    let sudokus_1000 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();;
	b.iter(|| {
		for mut sudoku in sudokus_1000.iter().cloned() { sudoku.solve(); }
	})
}

#[bench]
fn hard_sudokus_solve_unique(b: &mut test::Bencher) {
    let sudokus = read_sudokus( &include_str!("../sudokus/Lines/hard_sudokus.txt") );
    let sudokus_1000 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();;
	b.iter(|| {
		for sudoku in sudokus_1000.iter().cloned() { sudoku.solve_unique(); }
	})
}

#[bench]
fn hard_sudokus_solve_one(b: &mut test::Bencher) {
    let sudokus = read_sudokus( &include_str!("../sudokus/Lines/hard_sudokus.txt") );
    let sudokus_1000 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();;
	b.iter(|| {
		for sudoku in sudokus_1000.iter().cloned() { sudoku.solve_one(); }
	})
}

#[bench]
fn hard_sudokus_solve_at_most_100(b: &mut test::Bencher) {
    let sudokus = read_sudokus( &include_str!("../sudokus/Lines/hard_sudokus.txt") );
    let sudokus_1000 = sudokus.iter().cycle().cloned().take(100).collect::<Vec<_>>();;
	b.iter(|| {
		for sudoku in sudokus_1000.iter().cloned() { sudoku.solve_at_most(100); }
	})
}
<|endoftext|>


<commit_before>//! Metamethods for accesssing the registry values!

use super::super::super::registry;

use hlua::any::AnyLuaValue;

use rustc_serialize::json::{Json, ToJson};
use std::ops::Deref;

pub fn index(table: AnyLuaValue, lua_key: AnyLuaValue)
             -> Result<AnyLuaValue, &'static str> {
    if let AnyLuaValue::LuaString(key) = lua_key {
        let maybe_json = registry::get_json(&key);
        if let Some(json) = maybe_json {
            Ok(convert_json(json.deref().to_json()))
        }
        else {
            // Should be nil, nil doesn't seem to be included
            Err("No value found for that key!")
        }
    }
    else {
        Err("The registry can only be indexed with keys!")
    }
}

// Prevent lua from changing the registry?
pub fn new_index(table: AnyLuaValue, key: AnyLuaValue, val: AnyLuaValue)
                 -> Result<(), &'static str> {
    Err("You can't set the registry!")
}

fn convert_json(json: Json) -> AnyLuaValue {
    match json {
        Json::String(val) => AnyLuaValue::LuaString(val),
        Json::Boolean(val) => AnyLuaValue::LuaBoolean(val),
        Json::F64(val) => AnyLuaValue::LuaNumber(val),
        Json::I64(val) => AnyLuaValue::LuaNumber((val as i32) as f64),
        Json::U64(val) => AnyLuaValue::LuaNumber((val as u32) as f64),
        Json::Null => AnyLuaValue::LuaString("none".to_string()),
        Json::Array(vals) => {
            let mut count = 0f64;
            // Gotta love that 1-based indexing. Start at zero but increment for
            // the first one. It works here at least.
            AnyLuaValue::LuaArray(vals.into_iter().map(|v| {
                count += 1.0;
                (AnyLuaValue::LuaNumber(count), convert_json(v))
            }).collect())
        },
        Json::Object(vals) => {
            AnyLuaValue::LuaArray(vals.into_iter().map(|(key, val)| {
                (AnyLuaValue::LuaString(key), convert_json(val))
            }).collect())
        }
    }
}

#[cfg(test)]
mod tests {
    use super::convert_json;
    use hlua::any::AnyLuaValue::*;
    use rustc_serialize::json::{Json, ToJson, Object};
    use std::collections::BTreeMap;

    #[test]
    fn convert_string() {
        let input = "Hello World".to_string();
        let json_input = Json::String(input.clone());
        assert_eq!(convert_json(json_input), LuaString(input));
    }
    #[test]
    fn convert_numbers() {
        let lua_number = LuaNumber(42f64);
        assert_eq!(convert_json(Json::F64(42f64)), lua_number);
        assert_eq!(convert_json(Json::I64(42i64)), lua_number);
        assert_eq!(convert_json(Json::U64(42u64)), lua_number);
    }

    #[test]
    fn convert_bool() {
        assert_eq!(convert_json(Json::Boolean(true)), LuaBoolean(true));
        assert_eq!(convert_json(Json::Boolean(false)), LuaBoolean(false));
    }

    #[test]
    fn convert_array() {
        let json = Json::Array(
            vec![Json::Boolean(true), Json::F64(11f64),
                 Json::String("Foo".to_string())]
        );
        let lua = LuaArray(vec![
                (LuaNumber(1f64), LuaBoolean(true)),
                (LuaNumber(2f64), LuaNumber(11f64)),
                (LuaNumber(3f64), LuaString("Foo".to_string()))
            ]);
        assert_eq!(convert_json(json), lua);
    }

    #[test]
    fn convert_object() {
        // { name="foo", point: {x=0, y=1}, valid=false }
        // The fields are emitted in alphabetical order thanks to Json's
        // internal BTreeMap representation.

        let mut json_tree: Object = BTreeMap::new();
        let mut point_tree: Object = BTreeMap::new();
        point_tree.insert("x".to_string(), Json::U64(0u64));
        point_tree.insert("y".to_string(), Json::U64(1u64));
        json_tree.insert("point".to_string(), Json::Object(point_tree));
        json_tree.insert("name".to_string(), Json::String("foo".to_string()));
        json_tree.insert("valid".to_string(), Json::Boolean(false));

        let lua = LuaArray(vec![
            (LuaString("name".to_string()), LuaString("foo".to_string())),
            (LuaString("point".to_string()), LuaArray(vec![
                (LuaString("x".to_string()), LuaNumber(0f64)),
                (LuaString("y".to_string()), LuaNumber(1f64))
            ])),
            (LuaString("valid".to_string()), LuaBoolean(false)),
        ]);

        assert_eq!(convert_json(Json::Object(json_tree)), lua);
    }
}
<commit_msg>Add support for LuaNil from hlua 0.1.8<commit_after>//! Metamethods for accesssing the registry values!

use super::super::super::registry;

use hlua::any::AnyLuaValue;

use rustc_serialize::json::{Json, ToJson};
use std::ops::Deref;

pub fn index(table: AnyLuaValue, lua_key: AnyLuaValue)
             -> Result<AnyLuaValue, &'static str> {
    if let AnyLuaValue::LuaString(key) = lua_key {
        let maybe_json = registry::get_json(&key);
        if let Some(json) = maybe_json {
            Ok(convert_json(json.deref().to_json()))
        }
        else {
            // Should be nil, nil doesn't seem to be included
            Err("No value found for that key!")
        }
    }
    else {
        Err("The registry can only be indexed with keys!")
    }
}

// Prevent lua from changing the registry?
pub fn new_index(table: AnyLuaValue, key: AnyLuaValue, val: AnyLuaValue)
                 -> Result<(), &'static str> {
    //Err("You can't set the registry!")
}

fn convert_json(json: Json) -> AnyLuaValue {
    match json {
        Json::String(val) => AnyLuaValue::LuaString(val),
        Json::Boolean(val) => AnyLuaValue::LuaBoolean(val),
        Json::F64(val) => AnyLuaValue::LuaNumber(val),
        Json::I64(val) => AnyLuaValue::LuaNumber((val as i32) as f64),
        Json::U64(val) => AnyLuaValue::LuaNumber((val as u32) as f64),
        Json::Null => AnyLuaValue::LuaNil,
        Json::Array(vals) => {
            let mut count = 0f64;
            // Gotta love that 1-based indexing. Start at zero but increment for
            // the first one. It works here at least.
            AnyLuaValue::LuaArray(vals.into_iter().map(|v| {
                count += 1.0;
                (AnyLuaValue::LuaNumber(count), convert_json(v))
            }).collect())
        },
        Json::Object(vals) => {
            AnyLuaValue::LuaArray(vals.into_iter().map(|(key, val)| {
                (AnyLuaValue::LuaString(key), convert_json(val))
            }).collect())
        }
    }
}

#[cfg(test)]
mod tests {
    use super::convert_json;
    use hlua::any::AnyLuaValue::*;
    use rustc_serialize::json::{Json, ToJson, Object};
    use std::collections::BTreeMap;

    #[test]
    fn convert_string() {
        let input = "Hello World".to_string();
        let json_input = Json::String(input.clone());
        assert_eq!(convert_json(json_input), LuaString(input));
    }
    #[test]
    fn convert_numbers() {
        let lua_number = LuaNumber(42f64);
        assert_eq!(convert_json(Json::F64(42f64)), lua_number);
        assert_eq!(convert_json(Json::I64(42i64)), lua_number);
        assert_eq!(convert_json(Json::U64(42u64)), lua_number);
    }

    #[test]
    fn convert_bool() {
        assert_eq!(convert_json(Json::Boolean(true)), LuaBoolean(true));
        assert_eq!(convert_json(Json::Boolean(false)), LuaBoolean(false));
    }

    #[test]
    fn convert_array() {
        let json = Json::Array(
            vec![Json::Boolean(true), Json::F64(11f64),
                 Json::String("Foo".to_string())]
        );
        let lua = LuaArray(vec![
                (LuaNumber(1f64), LuaBoolean(true)),
                (LuaNumber(2f64), LuaNumber(11f64)),
                (LuaNumber(3f64), LuaString("Foo".to_string()))
            ]);
        assert_eq!(convert_json(json), lua);
    }

    #[test]
    fn convert_object() {
        // { name="foo", point: {x=0, y=1}, valid=false }
        // The fields are emitted in alphabetical order thanks to Json's
        // internal BTreeMap representation.

        let mut json_tree: Object = BTreeMap::new();
        let mut point_tree: Object = BTreeMap::new();
        point_tree.insert("x".to_string(), Json::U64(0u64));
        point_tree.insert("y".to_string(), Json::U64(1u64));
        json_tree.insert("point".to_string(), Json::Object(point_tree));
        json_tree.insert("name".to_string(), Json::String("foo".to_string()));
        json_tree.insert("valid".to_string(), Json::Boolean(false));

        let lua = LuaArray(vec![
            (LuaString("name".to_string()), LuaString("foo".to_string())),
            (LuaString("point".to_string()), LuaArray(vec![
                (LuaString("x".to_string()), LuaNumber(0f64)),
                (LuaString("y".to_string()), LuaNumber(1f64))
            ])),
            (LuaString("valid".to_string()), LuaBoolean(false)),
        ]);

        assert_eq!(convert_json(Json::Object(json_tree)), lua);
    }
}
<|endoftext|>


<commit_before>use types::*;

use nom::{be_i8, be_u8, be_i16, be_u16, be_i32, be_u32, be_i64, be_u64, float, double};

/* FIXME: we convert to a Some so that nom can happily handle some _ case which would otherwise fail as we're exhaustive */
named!(pub parse_value<AMQPValue>,                 switch!(map!(parse_type, |t| Some(t)),
    Some(AMQPType::Boolean)        => map!(call!(parse_boolean),          |b| AMQPValue::Boolean(b))        |
    Some(AMQPType::ShortShortInt)  => map!(call!(parse_short_short_int),  |i| AMQPValue::ShortShortInt(i))  |
    Some(AMQPType::ShortShortUInt) => map!(call!(parse_short_short_uint), |u| AMQPValue::ShortShortUInt(u)) |
    Some(AMQPType::ShortInt)       => map!(call!(parse_short_int),        |i| AMQPValue::ShortInt(i))       |
    Some(AMQPType::ShortUInt)      => map!(call!(parse_short_uint),       |u| AMQPValue::ShortUInt(u))      |
    Some(AMQPType::LongInt)        => map!(call!(parse_long_int),         |i| AMQPValue::LongInt(i))        |
    Some(AMQPType::LongUInt)       => map!(call!(parse_long_uint),        |u| AMQPValue::LongUInt(u))       |
    Some(AMQPType::LongLongInt)    => map!(call!(parse_long_long_int),    |i| AMQPValue::LongLongInt(i))    |
    Some(AMQPType::LongLongUInt)   => map!(call!(parse_long_long_uint),   |u| AMQPValue::LongLongUInt(u))   |
    Some(AMQPType::Float)          => map!(call!(parse_float),            |f| AMQPValue::Float(f))          |
    Some(AMQPType::Double)         => map!(call!(parse_double),           |d| AMQPValue::Double(d))         |
    Some(AMQPType::DecimalValue)   => map!(call!(parse_decimal_value),    |d| AMQPValue::DecimalValue(d))   |
    Some(AMQPType::ShortString)    => map!(call!(parse_short_string),     |s| AMQPValue::ShortString(s))    |
    Some(AMQPType::LongString)     => map!(call!(parse_long_string),      |s| AMQPValue::LongString(s))     |
    Some(AMQPType::FieldArray)     => map!(call!(parse_field_array),      |a| AMQPValue::FieldArray(a))     |
    Some(AMQPType::Timestamp)      => map!(call!(parse_timestamp),        |t| AMQPValue::Timestamp(t))      |
    Some(AMQPType::FieldTable)     => map!(call!(parse_field_table),      |t| AMQPValue::FieldTable(t))     |
    Some(AMQPType::Void)           => value!(AMQPValue::Void)
));

named!(pub parse_type<AMQPType>,                   map_opt!(be_u8, |t| AMQPType::from_id(t as char)));

named!(pub parse_boolean<Boolean>,                 map!(be_u8, |b| b != 0));
named!(pub parse_short_short_int<ShortShortInt>,   call!(be_i8));
named!(pub parse_short_short_uint<ShortShortUInt>, call!(be_u8));
named!(pub parse_short_int<ShortInt>,              call!(be_i16));
named!(pub parse_short_uint<ShortUInt>,            call!(be_u16));
named!(pub parse_long_int<LongInt>,                call!(be_i32));
named!(pub parse_long_uint<LongUInt>,              call!(be_u32));
named!(pub parse_long_long_int<LongLongInt>,       call!(be_i64));
named!(pub parse_long_long_uint<LongLongUInt>,     call!(be_u64));
named!(pub parse_float<Float>,                     call!(float));
named!(pub parse_double<Double>,                   call!(double));
named!(pub parse_decimal_value<DecimalValue>,      do_parse!(scale: parse_short_short_uint >> value: parse_long_uint >> (DecimalValue { scale: scale, value: value, })));
named!(pub parse_short_string<ShortString>,        do_parse!(length: parse_short_short_uint >> s: take_str!(length) >> (s.to_string())));
named!(pub parse_long_string<LongString>,          do_parse!(length: parse_long_uint >> s: take_str!(length) >> (s.to_string())));
named!(pub parse_field_array<FieldArray>,          do_parse!(length: parse_long_int >> array: count!(parse_value, length as usize) >> (array)));
named!(pub parse_timestamp<Timestamp>,             call!(parse_long_long_uint));
named!(pub parse_field_table<FieldTable>,          do_parse!(length: parse_long_uint >> table: flat_map!(take!(length as usize), fold_many0!(complete!(pair!(parse_short_string, parse_value)), FieldTable::new(), |mut acc: FieldTable, (key, value)| {
    acc.insert(key, value);
    acc
})) >> (table)));
<commit_msg>types: fix float parsing<commit_after>use types::*;

use nom::{be_i8, be_u8, be_i16, be_u16, be_i32, be_u32, be_i64, be_u64, be_f32, be_f64};

/* FIXME: we convert to a Some so that nom can happily handle some _ case which would otherwise fail as we're exhaustive */
named!(pub parse_value<AMQPValue>,                 switch!(map!(parse_type, |t| Some(t)),
    Some(AMQPType::Boolean)        => map!(call!(parse_boolean),          |b| AMQPValue::Boolean(b))        |
    Some(AMQPType::ShortShortInt)  => map!(call!(parse_short_short_int),  |i| AMQPValue::ShortShortInt(i))  |
    Some(AMQPType::ShortShortUInt) => map!(call!(parse_short_short_uint), |u| AMQPValue::ShortShortUInt(u)) |
    Some(AMQPType::ShortInt)       => map!(call!(parse_short_int),        |i| AMQPValue::ShortInt(i))       |
    Some(AMQPType::ShortUInt)      => map!(call!(parse_short_uint),       |u| AMQPValue::ShortUInt(u))      |
    Some(AMQPType::LongInt)        => map!(call!(parse_long_int),         |i| AMQPValue::LongInt(i))        |
    Some(AMQPType::LongUInt)       => map!(call!(parse_long_uint),        |u| AMQPValue::LongUInt(u))       |
    Some(AMQPType::LongLongInt)    => map!(call!(parse_long_long_int),    |i| AMQPValue::LongLongInt(i))    |
    Some(AMQPType::LongLongUInt)   => map!(call!(parse_long_long_uint),   |u| AMQPValue::LongLongUInt(u))   |
    Some(AMQPType::Float)          => map!(call!(parse_float),            |f| AMQPValue::Float(f))          |
    Some(AMQPType::Double)         => map!(call!(parse_double),           |d| AMQPValue::Double(d))         |
    Some(AMQPType::DecimalValue)   => map!(call!(parse_decimal_value),    |d| AMQPValue::DecimalValue(d))   |
    Some(AMQPType::ShortString)    => map!(call!(parse_short_string),     |s| AMQPValue::ShortString(s))    |
    Some(AMQPType::LongString)     => map!(call!(parse_long_string),      |s| AMQPValue::LongString(s))     |
    Some(AMQPType::FieldArray)     => map!(call!(parse_field_array),      |a| AMQPValue::FieldArray(a))     |
    Some(AMQPType::Timestamp)      => map!(call!(parse_timestamp),        |t| AMQPValue::Timestamp(t))      |
    Some(AMQPType::FieldTable)     => map!(call!(parse_field_table),      |t| AMQPValue::FieldTable(t))     |
    Some(AMQPType::Void)           => value!(AMQPValue::Void)
));

named!(pub parse_type<AMQPType>,                   map_opt!(be_u8, |t| AMQPType::from_id(t as char)));

named!(pub parse_boolean<Boolean>,                 map!(be_u8, |b| b != 0));
named!(pub parse_short_short_int<ShortShortInt>,   call!(be_i8));
named!(pub parse_short_short_uint<ShortShortUInt>, call!(be_u8));
named!(pub parse_short_int<ShortInt>,              call!(be_i16));
named!(pub parse_short_uint<ShortUInt>,            call!(be_u16));
named!(pub parse_long_int<LongInt>,                call!(be_i32));
named!(pub parse_long_uint<LongUInt>,              call!(be_u32));
named!(pub parse_long_long_int<LongLongInt>,       call!(be_i64));
named!(pub parse_long_long_uint<LongLongUInt>,     call!(be_u64));
named!(pub parse_float<Float>,                     call!(be_f32));
named!(pub parse_double<Double>,                   call!(be_f64));
named!(pub parse_decimal_value<DecimalValue>,      do_parse!(scale: parse_short_short_uint >> value: parse_long_uint >> (DecimalValue { scale: scale, value: value, })));
named!(pub parse_short_string<ShortString>,        do_parse!(length: parse_short_short_uint >> s: take_str!(length) >> (s.to_string())));
named!(pub parse_long_string<LongString>,          do_parse!(length: parse_long_uint >> s: take_str!(length) >> (s.to_string())));
named!(pub parse_field_array<FieldArray>,          do_parse!(length: parse_long_int >> array: count!(parse_value, length as usize) >> (array)));
named!(pub parse_timestamp<Timestamp>,             call!(parse_long_long_uint));
named!(pub parse_field_table<FieldTable>,          do_parse!(length: parse_long_uint >> table: flat_map!(take!(length as usize), fold_many0!(complete!(pair!(parse_short_string, parse_value)), FieldTable::new(), |mut acc: FieldTable, (key, value)| {
    acc.insert(key, value);
    acc
})) >> (table)));
<|endoftext|>