<commit_before>extern crate image;
extern crate time;

use std::iter;
use std::path::Path;
use std::thread;

use vector::*;
use objects::*;
mod lighting;

pub type Image = image::RgbImage;

pub fn write_image(image: Image, filename: &str) {
    let _ = image.save(&Path::new(filename));
}

pub fn raytrace(scene: &Scene, width: u32, height: u32, h_fov: f64) {
    let start_time = time::precise_time_ns();
    let f_width = width as f64;
    let f_height = height as f64;
    let v_fov = h_fov * (f_height / f_width);

    let vw_per_pixel = 2.0 * (h_fov / 2.0).tan() / f_width;
    let vh_per_pixel = 2.0 * (v_fov / 2.0).tan() / f_height;

    let norm_up = scene.camera.up.normalized();
    let norm_right = scene.camera.direction.cross(scene.camera.up).normalized();

    let tracer = move |row_start, num_rows, scene: Scene| {
        move || {
            let coords = (0..width).flat_map(|y| {
                iter::repeat(y).zip(row_start..(row_start + num_rows))
            });
            let trace_coord = |coord| {
                let (x, y) = coord;
                let mut rays = 0;
                let cast_ray = |dx: f64, dy: f64, rays: &mut u64| {
                    *rays += 1;
                    let fi = (x as f64) + dx;
                    let fj = (y as f64) + dy;

                    let u_rel = vw_per_pixel * (fi - (f_width / 2.0));
                    let v_rel = vh_per_pixel * (fj - (f_height / 2.0));

                    let pixel_loc = scene.camera.position + scene.camera.direction +
                        (norm_right * u_rel) + (norm_up * v_rel);

                    let ray = Ray {
                        origin: scene.camera.position,
                        direction: pixel_loc - scene.camera.position
                    };

                    let (color, new_rays) = lighting::get_color(&scene, &ray, 3);
                    *rays += new_rays;
                    color
                };

                let c1 = cast_ray(0.25, 0.25, &mut rays);
                let c2 = cast_ray(0.75, 0.25, &mut rays);
                let c3 = cast_ray(0.50, 0.50, &mut rays);
                let c4 = cast_ray(0.75, 0.75, &mut rays);
                let c5 = cast_ray(0.25, 0.75, &mut rays);

                (coord, rays, (c1 + c2 + c3 + c4 + c5) / 5.0)
            };

            let mut result = Vec::with_capacity((num_rows * width) as usize);
            let mut rays = 0;
            for (coord, new_rays, color) in coords.map(trace_coord) {
                rays += new_rays;
                result.push((coord, color))
            }

            (rays, result)
        }
    };

    // TODO: split based on core count
    let split = height / 2;
    let handle1 = thread::spawn(tracer(0, split, (*scene).clone()));
    let handle2 = thread::spawn(tracer(split, height - split, (*scene).clone()));

    let mut image = image::RgbImage::new(width, height);
    let mut rays = 0;
    let (new_rays, pixels): (u64, Vec<((u32, u32), Color)>) = handle1.join().unwrap();

    // TODO: direct copying into image. Also see Image.sub_image
    for ((x, y), pixel) in pixels {
        image.put_pixel(x as u32, y as u32, pixel.to_rgb());
    }
    rays += new_rays;

    let (new_rays, pixels): (u64, Vec<((u32, u32), Color)>) = handle2.join().unwrap();

    for ((x, y), pixel) in pixels {
        image.put_pixel(x as u32, y as u32, pixel.to_rgb());
    }
    rays += new_rays;

    write_image(image, "test.png");

    let elapsed_time = ((time::precise_time_ns() - start_time) as f64) /
        1000000.0;
    let rays_per_s = 1000.0 * (rays as f64) / elapsed_time;
    println!("Traced {} rays in {} ms ({} rays per second).",
             rays, elapsed_time, rays_per_s);
}
<commit_msg>Use subimages and direct copy into final image<commit_after>extern crate image;
extern crate time;

use std::path::Path;
use std::thread;

use vector::*;
use objects::*;
mod lighting;

pub type Image = image::RgbImage;

pub fn write_image(image: Image, filename: &str) {
    let _ = image.save(&Path::new(filename));
}

pub fn raytrace(scene: &Scene, width: u32, height: u32, h_fov: f64) {
    let start_time = time::precise_time_ns();
    let f_width = width as f64;
    let f_height = height as f64;
    let v_fov = h_fov * (f_height / f_width);

    let vw_per_pixel = 2.0 * (h_fov / 2.0).tan() / f_width;
    let vh_per_pixel = 2.0 * (v_fov / 2.0).tan() / f_height;

    let norm_up = scene.camera.up.normalized();
    let norm_right = scene.camera.direction.cross(scene.camera.up).normalized();

    let tracer = move |row_start, num_rows, scene: Scene| {
        move || {
            let mut subimage = image::RgbImage::new(width, num_rows);
            let mut rays = 0;
            for (x, y, pixel) in subimage.enumerate_pixels_mut() {
                let y = y + row_start;
                let cast_ray = |dx: f64, dy: f64, rays: &mut u64| {
                    *rays += 1;
                    let fi = (x as f64) + dx;
                    let fj = (y as f64) + dy;

                    let u_rel = vw_per_pixel * (fi - (f_width / 2.0));
                    let v_rel = vh_per_pixel * (fj - (f_height / 2.0));

                    let pixel_loc = scene.camera.position + scene.camera.direction +
                        (norm_right * u_rel) + (norm_up * v_rel);

                    let ray = Ray {
                        origin: scene.camera.position,
                        direction: pixel_loc - scene.camera.position
                    };

                    let (color, new_rays) = lighting::get_color(&scene, &ray, 3);
                    *rays += new_rays;
                    color
                };

                let c1 = cast_ray(0.25, 0.25, &mut rays);
                let c2 = cast_ray(0.75, 0.25, &mut rays);
                let c3 = cast_ray(0.50, 0.50, &mut rays);
                let c4 = cast_ray(0.75, 0.75, &mut rays);
                let c5 = cast_ray(0.25, 0.75, &mut rays);

                *pixel = ((c1 + c2 + c3 + c4 + c5) / 5.0).to_rgb();
            };

            (rays, subimage)
        }
    };

    // TODO: split based on core count
    let split = height / 2;
    let handle1 = thread::spawn(tracer(0, split, (*scene).clone()));
    let handle2 = thread::spawn(tracer(split, height - split, (*scene).clone()));

    let mut image = image::RgbImage::new(width, height);
    let mut rays = 0;
    let (new_rays, subimage): (u64, image::RgbImage) = handle1.join().unwrap();

    // TODO: see Image.sub_image - is it thread safe?
    image::GenericImage::copy_from(&mut image, &subimage, 0, 0);
    rays += new_rays;

    let (new_rays, subimage): (u64, image::RgbImage) = handle2.join().unwrap();

    image::GenericImage::copy_from(&mut image, &subimage, 0, split);
    rays += new_rays;

    write_image(image, "test.png");

    let elapsed_time = ((time::precise_time_ns() - start_time) as f64) /
        1000000.0;
    let rays_per_s = 1000.0 * (rays as f64) / elapsed_time;
    println!("Traced {} rays in {} ms ({} rays per second).",
             rays, elapsed_time, rays_per_s);
}
<|endoftext|>


<commit_before>//! The LLVM Stack Map Section format is documented here:
//!
//! http://llvm.org/docs/StackMaps.html#stack-map-format
//!
//! portions of which I am transcribing here.
//!
//! ```
//! Header {
//!     uint8  : Stack Map Version (current version is 1)
//!     uint8  : Reserved (expected to be 0)
//!     uint16 : Reserved (expected to be 0)
//! }
//! uint32 : NumFunctions
//! uint32 : NumConstants
//! uint32 : NumRecords
//! StkSizeRecord[NumFunctions] {
//!     uint64 : Function Address
//!     uint64 : Stack Size
//! }
//! Constants[NumConstants] {
//!     uint64 : LargeConstant
//! }
//! StkMapRecord[NumRecords] {
//!     uint64 : PatchPoint ID
//!     uint32 : Instruction Offset
//!     uint16 : Reserved (record flags)
//!     uint16 : NumLocations
//!     Location[NumLocations] {
//!         uint8  : Register | Direct | Indirect | Constant | ConstantIndex
//!         uint8  : Reserved (location flags)
//!         uint16 : Dwarf RegNum
//!         int32  : Offset or SmallConstant
//!     }
//!     uint16 : Padding
//!     uint16 : NumLiveOuts
//!     LiveOuts[NumLiveOuts] {
//!         uint16 : Dwarf RegNum
//!         uint8  : Reserved
//!         uint8  : Size in Bytes
//!     }
//!     uint32 : Padding (only if required to align to 8 byte)
//! }
//! ```

use byteorder::{ByteOrder, ReadBytesExt};
use byteorder::{BigEndian, LittleEndian};

use std::io::{Read};

pub trait ReadFrom: Sized {
    type Error;
    fn read_from<R:Read, T:OrderedReadFrom>(r: &mut R) -> Result<Self, Self::Error>;
}

pub trait Many {
    type Count;
}

pub mod errors {
    use std::io;

    #[derive(Debug)]
    pub enum StackMapError {
        Truncated { reading: &'static str },
        Header(HeaderError),
    }

    #[derive(Debug)]
    pub enum HeaderError {
        Prim(PrimError),
    }
    #[derive(Debug)]
    pub struct ConstantError { pub name: &'static str, pub err: io::Error }
    #[derive(Debug)]
    pub enum StackSizeError {
        Prim(PrimError),
    }
    #[derive(Debug)]
    pub enum LargeConstantError {
        Prim(PrimError),
    }
    #[derive(Debug)]
    pub enum RecordError {
        Prim(PrimError),
        Constant(ConstantError),
    }
    #[derive(Debug)]
    pub enum PrimError {
        Io(io::Error),
    }

    macro_rules! impl_from_for_read_error {
        ($VariantErr:ident, $Variant:ident) => {
            impl From<$VariantErr> for ReadError {
                fn from(x: $VariantErr) -> Self { ReadError::$Variant(x) }
            }
        }
    }

    macro_rules! enum_read_error {
        {$($Variant:ident($VariantErr:ident),)*} => {
            #[derive(Debug)]
            pub enum ReadError {
                $($Variant($VariantErr),)*
            }
            $(impl_from_for_read_error!{$VariantErr, $Variant})*
        }
    }

    enum_read_error!{
        StackMap(StackMapError),
        Constant(ConstantError),
        Header(HeaderError),
        StackSize(StackSizeError),
        LargeConstant(LargeConstantError),
        Record(RecordError),
        Prim(PrimError),
    }

    impl From<io::Error> for PrimError {
        fn from(x: io::Error) -> Self { PrimError::Io(x) }
    }

    impl From<PrimError> for HeaderError {
        fn from(x: PrimError) -> Self { HeaderError::Prim(x) }
    }

    impl From<PrimError> for StackSizeError {
        fn from(x: PrimError) -> Self { StackSizeError::Prim(x) }
    }

    impl From<PrimError> for LargeConstantError {
        fn from(x: PrimError) -> Self { LargeConstantError::Prim(x) }
    }

    impl From<PrimError> for RecordError {
        fn from(x: PrimError) -> Self { RecordError::Prim(x) }
    }

    impl From<ConstantError> for RecordError {
        fn from(x: ConstantError) -> Self { RecordError::Constant(x) }
    }
}

use self::errors::*;

pub trait OrderedReadFrom: ByteOrder + Sized {
    fn read_from<R:Read, S:ReadFrom>(r: &mut R) -> Result<S, S::Error> {
        S::read_from::<R, Self>(r)
    }
}

impl OrderedReadFrom for BigEndian { }
impl OrderedReadFrom for LittleEndian { }

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct NumFunctions(pub u32);
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct NumConstants(pub u32);
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct NumRecords(pub u32);
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct NumLocations(pub u32);
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct NumLiveOuts(pub u32);

trait ToUsize { fn to_usize(&self) -> usize; }

macro_rules! impl_read_from_constant_u32 {
    ($This:ident, $name:expr) => {
        impl ReadFrom for $This {
            type Error = ConstantError;
            fn read_from<R,T>(r: &mut R) -> Result<Self, Self::Error>
                where R:Read, T:OrderedReadFrom
            {
                Ok($This(match r.read_u32::<T>() {
                    Ok(num) => num,
                    Err(err) => return Err(ConstantError { name: $name, err: err }),
                }))
            }
        }
        impl ToUsize for $This { fn to_usize(&self) -> usize { self.0 as usize } }
    }
}

impl_read_from_constant_u32!(NumFunctions, "num_functions");
impl_read_from_constant_u32!(NumConstants, "num_constants");
impl_read_from_constant_u32!(NumRecords, "num_records");
impl_read_from_constant_u32!(NumLocations, "num_locations");
impl_read_from_constant_u32!(NumLiveOuts, "num_live_outs");

trait ReadMany<T:OrderedReadFrom>: Sized {
    type Count: ToUsize;
    fn read<R:Read>(r: &mut R, c: &Self::Count) -> Result<Vec<Self>, ReadError>;
}

fn read_many<RM, R, T>(r: &mut R, c: &RM::Count) -> Result<Vec<RM>, ReadError>
    where RM: ReadFrom + ReadMany<T>, R:Read, T:OrderedReadFrom, ReadError: From<RM::Error>
{
        let mut v = Vec::with_capacity(c.to_usize());
        for _ in 0..(c.to_usize()) {
            v.push(T::read_from(r)?: RM)
        }
        Ok(v)
}

macro_rules! impl_read_many {
    ($Struct:ident, $Count:ident) => {
        impl<T:OrderedReadFrom> ReadMany<T> for $Struct {
            type Count = $Count;
            fn read<R:Read>(r: &mut R, c: &Self::Count) -> Result<Vec<Self>, ReadError> {
                read_many::<Self, R, T>(r, c)
            }
        }
    }
}

impl_read_many!(StackSize, NumFunctions);
impl_read_many!(LargeConstant, NumConstants);
impl_read_many!(Record, NumRecords);
impl_read_many!(Location, NumLocations);
impl_read_many!(LiveOut, NumLiveOuts);

impl StackMap {
    pub fn read_from<T>(mut r: &[u8]) -> Result<Self, ReadError>
        where T:OrderedReadFrom
    {
        ReadFrom::read_from::<&[u8],T>(&mut r)
    }
}

impl ReadFrom for StackMap {
    type Error = ReadError;
    fn read_from<R:Read, T:OrderedReadFrom>(r: &mut R) -> Result<Self, Self::Error> {
        let header: Header = T::read_from(r)?;
        let num_functions: NumFunctions = T::read_from(r)?;
        let num_constants: NumConstants = T::read_from(r)?;
        let num_records: NumRecords = T::read_from(r)?;
        let stack_size_records: Vec<StackSize> = ReadMany::<T>::read(r, &num_functions)?;
        let large_constants: Vec<LargeConstant> = ReadMany::<T>::read(r, &num_constants)?;
        let records: Vec<Record> = ReadMany::<T>::read(r, &num_records)?;
        Ok(StackMap {
            header: header,
            stack_sizes: stack_size_records,
            large_constants: large_constants,
            records: records,
        })
    }
}

impl ReadFrom for Header {
    type Error = HeaderError;
    fn read_from<R:Read, T:OrderedReadFrom>(r: &mut R) -> Result<Self, Self::Error> {
        let version: u8 = T::read_from(r)?;
        let reserved_1: u8 = T::read_from(r)?;
        let reserved_2: u16 = T::read_from(r)?;
        Ok(Header { version: version,
                    reserved_1: reserved_1,
                    reserved_2: reserved_2 })
    }
}

impl ReadFrom for StackSize {
    type Error = StackSizeError;
    fn read_from<R:Read, T:OrderedReadFrom>(r: &mut R) -> Result<Self, Self::Error> {
        let function_address: u64 = T::read_from(r)?;
        let stack_size: u64 = T::read_from(r)?;
        Ok(StackSize { function_address: function_address,
                       stack_size: stack_size })
    }
}

impl ReadFrom for LargeConstant {
    type Error = LargeConstantError;
    fn read_from<R:Read, T:OrderedReadFrom>(r: &mut R) -> Result<Self, Self::Error> {
        let value: u64 = T::read_from(r)?;
        Ok(LargeConstant { value: value })
    }
}

impl ReadFrom for Record {
    type Error = ReadError;
    fn read_from<R:Read, T:OrderedReadFrom>(r: &mut R) -> Result<Self, Self::Error> {
        let patchpoint_id: u64 = T::read_from(r)?;
        let instruction_offset: u32 = T::read_from(r)?;
        let reserved_1: u16 = T::read_from(r)?;
        let num_locations: NumLocations = T::read_from(r)?;
        let locations: Vec<Location> = ReadMany::<T>::read(r, &num_locations)?;
        let padding_1:u16 = T::read_from(r)?;
        let num_live_outs: NumLiveOuts = T::read_from(r)?;
        let live_outs: Vec<LiveOut> = ReadMany::<T>::read(r, &num_live_outs)?;
        Ok(Record {
            patchpoint_id: patchpoint_id,
            instruction_offset: instruction_offset,
            reserved: reserved_1,
            num_locations: num_locations,
            locations: locations,
            padding_1: padding_1,
            num_live_outs: num_live_outs,
            live_outs: live_outs,
            padding_2: None, // FIXME
        })
    }
}

impl ReadFrom for Location {
    type Error = ReadError;
    fn read_from<R:Read, T:OrderedReadFrom>(r: &mut R) -> Result<Self, Self::Error> {
        let val_type: u8 = T::read_from(r)?;
        let reserved: u8 = T::read_from(r)?;
        let dwarf_regnum: u16 = T::read_from(r)?;
        let offset_or_small_constant: i32 = T::read_from(r)?;
        Ok(Location {
            val_type: val_type,
            reserved: reserved,
            dwarf_regnum: dwarf_regnum,
            offset_or_small_constant: offset_or_small_constant,
        })
    }
}

impl ReadFrom for LiveOut {
    type Error = ReadError;
    fn read_from<R:Read, T:OrderedReadFrom>(r: &mut R) -> Result<Self, Self::Error> {
        let dwarf_regnum: u16 = T::read_from(r)?;
        let reserved: u8 = T::read_from(r)?;
        let size_in_bytes: u8 = T::read_from(r)?;
        Ok(LiveOut {
            dwarf_regnum: dwarf_regnum,
            reserved: reserved,
            size_in_bytes: size_in_bytes,
        })
    }
}

macro_rules! impl_read_from_for_prim {
    (u8) => {
        impl ReadFrom for u8 {
            type Error = PrimError;
            fn read_from<R,T>(r: &mut R) -> Result<Self, Self::Error>
                where R:Read, T:OrderedReadFrom
            {
                Ok(r.read_u8()?)
            }
        }
    };
    ($prim:ident, $read:ident) => {
        impl ReadFrom for $prim {
            type Error = PrimError;
            fn read_from<R,T>(r: &mut R) -> Result<Self, Self::Error>
                where R:Read, T:OrderedReadFrom
            {
                Ok(r.$read::<T>()?)
            }
        }
    }
}

impl_read_from_for_prim!(u8);
impl_read_from_for_prim!(u16, read_u16);
impl_read_from_for_prim!(u32, read_u32);
impl_read_from_for_prim!(u64, read_u64);

impl_read_from_for_prim!(i32, read_i32);

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct StackMap {
    header: Header,
    stack_sizes: Vec<StackSize>,
    large_constants: Vec<LargeConstant>,
    records: Vec<Record>
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Header {
    version: u8,
    reserved_1: u8,
    reserved_2: u16,
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct StackSize {
    function_address: u64,
    stack_size: u64,
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct LargeConstant {
    value: u64,
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Record {
    patchpoint_id: u64,
    instruction_offset: u32,
    reserved: u16,
    num_locations: NumLocations,
    locations: Vec<Location>,
    padding_1: u16,
    num_live_outs: NumLiveOuts,
    live_outs: Vec<LiveOut>,
    padding_2: Option<u32>, // only if required to align to 8 byte
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Location {
    val_type: u8,
    reserved: u8,
    dwarf_regnum: u16,
    offset_or_small_constant: i32,
}

#[repr(u8)]
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum ValType { Register, Direct, Indirect, Constant, ConstantIndex }

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct LiveOut {
    dwarf_regnum: u16,
    reserved: u8,
    size_in_bytes: u8,
}
<commit_msg>stripping out broken parse code and starting fresh.<commit_after>//! The LLVM Stack Map Section format is documented here:
//!
//! http://llvm.org/docs/StackMaps.html#stack-map-format
//!
//! portions of which I am transcribing here.
//!
//! ```
//! Header {
//!     uint8  : Stack Map Version (current version is 1)
//!     uint8  : Reserved (expected to be 0)
//!     uint16 : Reserved (expected to be 0)
//! }
//! uint32 : NumFunctions
//! uint32 : NumConstants
//! uint32 : NumRecords
//! StkSizeRecord[NumFunctions] {
//!     uint64 : Function Address
//!     uint64 : Stack Size
//! }
//! Constants[NumConstants] {
//!     uint64 : LargeConstant
//! }
//! StkMapRecord[NumRecords] {
//!     uint64 : PatchPoint ID
//!     uint32 : Instruction Offset
//!     uint16 : Reserved (record flags)
//!     uint16 : NumLocations
//!     Location[NumLocations] {
//!         uint8  : Register | Direct | Indirect | Constant | ConstantIndex
//!         uint8  : Reserved (location flags)
//!         uint16 : Dwarf RegNum
//!         int32  : Offset or SmallConstant
//!     }
//!     uint16 : Padding
//!     uint16 : NumLiveOuts
//!     LiveOuts[NumLiveOuts] {
//!         uint16 : Dwarf RegNum
//!         uint8  : Reserved
//!         uint8  : Size in Bytes
//!     }
//!     uint32 : Padding (only if required to align to 8 byte)
//! }
//! ```

use byteorder::{ByteOrder, ReadBytesExt};
use byteorder::{BigEndian, LittleEndian};

use std::io::{Read};

pub trait Many {
    type Count;
}

pub mod errors {
    use std::io;

    #[derive(Debug)]
    pub enum StackMapError {
        Truncated { reading: &'static str },
        Header(HeaderError),
    }

    #[derive(Debug)]
    pub enum HeaderError {
        Prim(PrimError),
    }
    #[derive(Debug)]
    pub struct ConstantError { pub name: &'static str, pub err: io::Error }
    #[derive(Debug)]
    pub enum StackSizeError {
        Prim(PrimError),
    }
    #[derive(Debug)]
    pub enum LargeConstantError {
        Prim(PrimError),
    }
    #[derive(Debug)]
    pub enum RecordError {
        Prim(PrimError),
        Constant(ConstantError),
    }
    #[derive(Debug)]
    pub enum PrimError {
        Io(io::Error),
    }

    macro_rules! impl_from_for_read_error {
        ($VariantErr:ident, $Variant:ident) => {
            impl From<$VariantErr> for ReadError {
                fn from(x: $VariantErr) -> Self { ReadError::$Variant(x) }
            }
        }
    }

    macro_rules! enum_read_error {
        {$($Variant:ident($VariantErr:ident),)*} => {
            #[derive(Debug)]
            pub enum ReadError {
                $($Variant($VariantErr),)*
            }
            $(impl_from_for_read_error!{$VariantErr, $Variant})*
        }
    }

    enum_read_error!{
        StackMap(StackMapError),
        Constant(ConstantError),
        Header(HeaderError),
        StackSize(StackSizeError),
        LargeConstant(LargeConstantError),
        Record(RecordError),
        Prim(PrimError),
    }

    impl From<io::Error> for PrimError {
        fn from(x: io::Error) -> Self { PrimError::Io(x) }
    }

    impl From<PrimError> for HeaderError {
        fn from(x: PrimError) -> Self { HeaderError::Prim(x) }
    }

    impl From<PrimError> for StackSizeError {
        fn from(x: PrimError) -> Self { StackSizeError::Prim(x) }
    }

    impl From<PrimError> for LargeConstantError {
        fn from(x: PrimError) -> Self { LargeConstantError::Prim(x) }
    }

    impl From<PrimError> for RecordError {
        fn from(x: PrimError) -> Self { RecordError::Prim(x) }
    }

    impl From<ConstantError> for RecordError {
        fn from(x: ConstantError) -> Self { RecordError::Constant(x) }
    }
}

use self::errors::*;

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct NumFunctions(pub u32);
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct NumConstants(pub u32);
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct NumRecords(pub u32);
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct NumLocations(pub u32);
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct NumLiveOuts(pub u32);

trait ToUsize { fn to_usize(&self) -> usize; }

impl StackMap {
    pub fn read_from<T>(r: &[u8]) -> Result<Self, ReadError>
        where T:ByteOrder
    {
        ReadFrom<T>::read_from(r)
    }
}

trait ReadFrom<T:ByteOrder> {
    //
    fn read_from(bytes: &[u8]) -> Option<(Self, usize)>;
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct StackMap {
    header: Header,
    stack_sizes: Vec<StackSize>,
    large_constants: Vec<LargeConstant>,
    records: Vec<Record>
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Header {
    version: u8,
    reserved_1: u8,
    reserved_2: u16,
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct StackSize {
    function_address: u64,
    stack_size: u64,
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct LargeConstant {
    value: u64,
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Record {
    patchpoint_id: u64,
    instruction_offset: u32,
    reserved: u16,
    num_locations: NumLocations,
    locations: Vec<Location>,
    padding_1: u16,
    num_live_outs: NumLiveOuts,
    live_outs: Vec<LiveOut>,
    padding_2: Option<u32>, // only if required to align to 8 byte
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Location {
    val_type: u8,
    reserved: u8,
    dwarf_regnum: u16,
    offset_or_small_constant: i32,
}

#[repr(u8)]
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum ValType { Register, Direct, Indirect, Constant, ConstantIndex }

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct LiveOut {
    dwarf_regnum: u16,
    reserved: u8,
    size_in_bytes: u8,
}
<|endoftext|>


<commit_before>use std::cmp;
use std::cmp::TotalOrd;

enum AVLNode<T> {
  // left, right, height, value
  Branch(~AVLNode<T>, ~AVLNode<T>, int, T),
  Nil
}

impl<T:TotalOrd> AVLNode<T> {
  fn in_order_traverse(&self, f: |&T|) {
    match self {
      &Branch(ref left, ref right, _, ref value) => {
        left.in_order_traverse(|x| f(x));
        f(value);
        right.in_order_traverse(|x| f(x));
      },
      &Nil => {}
    }
  }

  // immutable insert function since mutable is horrible
  fn insert(self, insValue: T) -> AVLNode<T> {
    match self {
      Branch(left, right, height, value) => {
        let (newLeft, newRight) = match insValue.cmp(&value) {
          Equal => (left, right),
          Less => (~left.insert(insValue), right),
          Greater => (left, ~right.insert(insValue))
        };
        let newHeight = cmp::max(newLeft.get_height(), newRight.get_height()) + 1;

        // if newHeight is not old height balance could have changed
        Branch(newLeft, newRight, newHeight, value).balance()
      }
      Nil => {
        Branch(~Nil, ~Nil, 0, insValue)
      }
    }
  }

  fn balance(self) -> AVLNode<T> {
    let balance = self.get_balance();
    match self {
      Branch(left, right, height, value) => {
        if balance > 1 {
          if left.get_balance() == -1 {
            return Branch(~left.left_rotate(), right, height, value).right_rotate();
          } else {
            return Branch(left, right, height, value).right_rotate();
          }
        } else if balance < -1 {
          if right.get_balance() == 1 {
            return Branch(left, ~right.right_rotate(), height, value).left_rotate();
          } else {
            return Branch(left, right, height, value).left_rotate();
          }
        } else {
          return Branch(left, right, height, value);
        }
      },
      Nil => return Nil
    }
  }

  fn left_rotate(self) -> AVLNode<T> {
    match self {
      Branch(left, right, height, value) => {
        match right {
          ~Branch(pivleft, pivright, pivheight, pivval) => {
            // the math is weird but this works
            let left_height = cmp::max(left.get_height(), pivleft.get_height()) + 1;
            let root_height = cmp::max(left_height + 1, pivright.get_height());
            return Branch(~Branch(left, pivleft, left_height, value), pivright, root_height, pivval);
          },
          ~Nil => fail!("nope")
        }
      },
      Nil => fail!("not even once")
    }
  }

  fn right_rotate(self) -> AVLNode<T> {
    match self {
      Branch(left, right, height, value) => {
        match left {
          ~Branch(pivleft, pivright, pivheight, pivval) => {
            let right_height = cmp::max(right.get_height(), pivright.get_height()) + 1;
            let root_height = cmp::max(right_height + 1, pivleft.get_height());

            return Branch(pivleft, ~Branch(pivright, right, right_height, value), root_height, pivval);
          },
          ~Nil => fail!("no")
        }
      },
      Nil => fail!("not even once")
    }
  }

  fn get_balance(&self) -> int {
    match self {
      &Branch(ref left, ref right, _, _) => left.get_height() - right.get_height(),
      &Nil => 0
    }
  }

  fn get_height(&self) -> int {
    match self {
      &Branch(_, _, height, _) => height,
      &Nil => -1
    }
  }

  // please be log(n)
  fn get_depth(&self) -> int {
    match self {
      &Branch(ref left, ref right, _, _) => cmp::max(left.get_depth(), right.get_depth())+1,
      &Nil => 0
    }
  }

  fn find(self, findValue: T) -> bool {
    match self {
      Branch(left, right, _, value) => {
        if value < findValue {
          return left.find(findValue);
        } else if value > findValue {
          return right.find(findValue);
        } else {
          return true;
        }
      },
      Nil => {
        return false;
      }
    }
  }

  fn good(&self) -> bool {
    match self {
      &Branch(ref left, ref right, height, ref value) => {
        match left {
          &~Branch(_, _, _, ref leftValue) => {
            if leftValue > value {
              println!("{:?} is not less than {:?}", leftValue, value);
              return false;
            }
          },
          &~Nil => {}
        }
        match right {
          &~Branch(_, _, _, ref rightValue) => {
            if rightValue < value {
              println!("{:?} is not greater than {:?}", rightValue, value);
              return false;
            }
          },
          &~Nil => {}
        }
        let trueHeight = cmp::max(left.get_depth(), right.get_depth());
        if trueHeight != height {
          println!("incorrect height {}, should be {}", height, trueHeight);
          return false;
        }

        return left.good() && right.good();
      },
      &Nil => return true
    }
  }
}

#[test]
fn test_left_rotate() {
  let tree = Branch(~Branch(~Nil, ~Branch(~Nil, ~Nil, 0, 4), -1, 3), ~Nil, 2, 5);
  assert_eq!(tree.left_rotate(), Branch(~Branch(~Nil, ~Branch(~Nil, ~Nil, 0, 4), -1, 3), ~Nil, 2, 5));
}

fn main() {
  let mut tree : AVLNode<int> = Branch(~Nil, ~Nil, 0, 0);
  for i in range(0,8192) {
    tree = tree.insert(i);
    if !tree.good() {
      break;
    }
  }
  println!("depth: {:?}", tree.get_depth());
  // println!("tree: {:?}", tree);

  // let left_right_tree = Branch(~Branch(~Nil, ~Branch(~Nil, ~Nil, 0, 4), -1, 3), ~Nil, 2, 5);
  // tree = Branch(~Nil, ~Branch(~Nil, ~Branch(~Nil, ~Nil, 0, 3), -1, 2), -2, 1);
  // println!("tree: {:?}", tree);
  // println!("tree: {:?}", tree.left_rotate());
  // println!("left_rotate left child: {:?}", Branch(~Branch(~Nil, ~Branch(~Nil, ~Nil, 0, 4), -1, 3).left_rotate(), ~Nil, 2, 5));
  // println!("bal?: {:?}", tree.balance());
  // println!("bal: {:?}", Branch(~Branch(~Nil, ~Branch(~Nil, ~Nil, 0, 4), -1, 3).left_rotate(), ~Nil, 2, 5).right_rotate());
}

<commit_msg>Add benchmarks<commit_after>extern crate test;

use std::cmp;
use std::cmp::TotalOrd;
use test::BenchHarness;

enum AVLNode<T> {
  // left, right, height, value
  Branch(~AVLNode<T>, ~AVLNode<T>, int, T),
  Nil
}

impl<T:TotalOrd> AVLNode<T> {
  fn in_order_traverse(&self, f: |&T|) {
    match self {
      &Branch(ref left, ref right, _, ref value) => {
        left.in_order_traverse(|x| f(x));
        f(value);
        right.in_order_traverse(|x| f(x));
      },
      &Nil => {}
    }
  }

  // immutable insert function since mutable is horrible
  fn insert(self, insValue: T) -> AVLNode<T> {
    match self {
      Branch(left, right, height, value) => {
        let (newLeft, newRight) = match insValue.cmp(&value) {
          Equal => (left, right),
          Less => (~left.insert(insValue), right),
          Greater => (left, ~right.insert(insValue))
        };
        let newHeight = cmp::max(newLeft.get_height(), newRight.get_height()) + 1;

        // if newHeight is not old height balance could have changed
        Branch(newLeft, newRight, newHeight, value).balance()
      }
      Nil => {
        Branch(~Nil, ~Nil, 0, insValue)
      }
    }
  }

  fn balance(self) -> AVLNode<T> {
    let balance = self.get_balance();
    match self {
      Branch(left, right, height, value) => {
        if balance > 1 {
          if left.get_balance() == -1 {
            return Branch(~left.left_rotate(), right, height, value).right_rotate();
          } else {
            return Branch(left, right, height, value).right_rotate();
          }
        } else if balance < -1 {
          if right.get_balance() == 1 {
            return Branch(left, ~right.right_rotate(), height, value).left_rotate();
          } else {
            return Branch(left, right, height, value).left_rotate();
          }
        } else {
          return Branch(left, right, height, value);
        }
      },
      Nil => return Nil
    }
  }

  fn left_rotate(self) -> AVLNode<T> {
    match self {
      Branch(left, right, height, value) => {
        match right {
          ~Branch(pivleft, pivright, pivheight, pivval) => {
            // the math is weird but this works
            let left_height = cmp::max(left.get_height(), pivleft.get_height()) + 1;
            let root_height = cmp::max(left_height + 1, pivright.get_height());
            return Branch(~Branch(left, pivleft, left_height, value), pivright, root_height, pivval);
          },
          ~Nil => fail!("nope")
        }
      },
      Nil => fail!("not even once")
    }
  }

  fn right_rotate(self) -> AVLNode<T> {
    match self {
      Branch(left, right, height, value) => {
        match left {
          ~Branch(pivleft, pivright, pivheight, pivval) => {
            let right_height = cmp::max(right.get_height(), pivright.get_height()) + 1;
            let root_height = cmp::max(right_height + 1, pivleft.get_height());

            return Branch(pivleft, ~Branch(pivright, right, right_height, value), root_height, pivval);
          },
          ~Nil => fail!("no")
        }
      },
      Nil => fail!("not even once")
    }
  }

  fn get_balance(&self) -> int {
    match self {
      &Branch(ref left, ref right, _, _) => left.get_height() - right.get_height(),
      &Nil => 0
    }
  }

  fn get_height(&self) -> int {
    match self {
      &Branch(_, _, height, _) => height,
      &Nil => -1
    }
  }

  // please be log(n)
  fn get_depth(&self) -> int {
    match self {
      &Branch(ref left, ref right, _, _) => cmp::max(left.get_depth(), right.get_depth())+1,
      &Nil => 0
    }
  }

  fn find(self, findValue: T) -> bool {
    match self {
      Branch(left, right, _, value) => {
        if value < findValue {
          return left.find(findValue);
        } else if value > findValue {
          return right.find(findValue);
        } else {
          return true;
        }
      },
      Nil => {
        return false;
      }
    }
  }

  fn good(&self) -> bool {
    match self {
      &Branch(ref left, ref right, height, ref value) => {
        match left {
          &~Branch(_, _, _, ref leftValue) => {
            if leftValue > value {
              println!("{:?} is not less than {:?}", leftValue, value);
              return false;
            }
          },
          &~Nil => {}
        }
        match right {
          &~Branch(_, _, _, ref rightValue) => {
            if rightValue < value {
              println!("{:?} is not greater than {:?}", rightValue, value);
              return false;
            }
          },
          &~Nil => {}
        }
        let trueHeight = cmp::max(left.get_depth(), right.get_depth());
        if trueHeight != height {
          println!("incorrect height {}, should be {}", height, trueHeight);
          return false;
        }

        return left.good() && right.good();
      },
      &Nil => return true
    }
  }
}

#[test]
fn test_left_rotate() {
  // let tree = Branch(~Branch(~Nil, ~Branch(~Nil, ~Nil, 0, 4), -1, 3), ~Nil, 2, 5);
  // assert_eq!(tree.left_rotate(), Branch(~Branch(~Nil, ~Branch(~Nil, ~Nil, 0, 4), -1, 3), ~Nil, 2, 5));
}

#[bench]
fn bench_insert_10(bh: &mut BenchHarness) {
  bh.iter(|| {
    bench_insert(10);
  });
}

#[bench]
fn bench_insert_100(bh: &mut BenchHarness) {
  bh.iter(|| {
    bench_insert(100);
  });
}

#[bench]
fn bench_insert_500(bh: &mut BenchHarness) {
  bh.iter(|| {
    bench_insert(500);
  });
}

#[bench]
fn bench_insert_1000(bh: &mut BenchHarness) {
  bh.iter(|| {
    bench_insert(1000);
  });
}

fn bench_insert(n: uint) {
  let mut tree : AVLNode<int> = Branch(~Nil, ~Nil, 0, 0);
  for i in range(0,n) {
    tree = tree.insert(i as int);
    if !tree.good() {
      fail!("incorrect tree...ONE MILLION YEARS DUNGEON");
    }
  }
}

fn main() {
  // println!("depth: {:?}", tree.get_depth());
  // println!("tree: {:?}", tree);

  // let left_right_tree = Branch(~Branch(~Nil, ~Branch(~Nil, ~Nil, 0, 4), -1, 3), ~Nil, 2, 5);
  // tree = Branch(~Nil, ~Branch(~Nil, ~Branch(~Nil, ~Nil, 0, 3), -1, 2), -2, 1);
  // println!("tree: {:?}", tree);
  // println!("tree: {:?}", tree.left_rotate());
  // println!("left_rotate left child: {:?}", Branch(~Branch(~Nil, ~Branch(~Nil, ~Nil, 0, 4), -1, 3).left_rotate(), ~Nil, 2, 5));
  // println!("bal?: {:?}", tree.balance());
  // println!("bal: {:?}", Branch(~Branch(~Nil, ~Branch(~Nil, ~Nil, 0, 4), -1, 3).left_rotate(), ~Nil, 2, 5).right_rotate());
}

<|endoftext|>


<commit_before>#![cfg_attr(not(feature = "std"), no_std)]
#![allow(incomplete_features)]
#![feature(
    adt_const_params,
    const_fn_trait_bound,
    const_panic,
    platform_intrinsics,
    repr_simd,
    simd_ffi,
    staged_api,
    stdsimd
)]
#![cfg_attr(feature = "generic_const_exprs", feature(generic_const_exprs))]
#![warn(missing_docs)]
#![deny(unsafe_op_in_unsafe_fn)]
#![unstable(feature = "portable_simd", issue = "86656")]
//! Portable SIMD module.

#[path = "mod.rs"]
mod core_simd;
pub use self::core_simd::simd;
pub use simd::*;
<commit_msg>Remove adt_const_params feature<commit_after>#![cfg_attr(not(feature = "std"), no_std)]
#![feature(
    const_fn_trait_bound,
    const_panic,
    platform_intrinsics,
    repr_simd,
    simd_ffi,
    staged_api,
    stdsimd
)]
#![cfg_attr(feature = "generic_const_exprs", feature(generic_const_exprs))]
#![cfg_attr(feature = "generic_const_exprs", allow(incomplete_features))]
#![warn(missing_docs)]
#![deny(unsafe_op_in_unsafe_fn)]
#![unstable(feature = "portable_simd", issue = "86656")]
//! Portable SIMD module.

#[path = "mod.rs"]
mod core_simd;
pub use self::core_simd::simd;
pub use simd::*;
<|endoftext|>


<commit_before>use std::cell::{Cell, RefCell};
use std::io::{self, ErrorKind};
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use std::sync::mpsc;

use mio;
use slab::Slab;
use futures::{Future, Tokens, Wake};

use slot::{self, Slot};

pub type Source = Arc<mio::Evented + Send + Sync>;

static NEXT_LOOP_ID: AtomicUsize = ATOMIC_USIZE_INIT;
scoped_thread_local!(static CURRENT_LOOP: Loop);

const SLAB_CAPACITY: usize = 1024 * 64;

pub struct Loop {
    id: usize,
    active: Cell<bool>,
    io: RefCell<mio::Poll>,
    tx: mio::channel::Sender<Message>,
    rx: mio::channel::Receiver<Message>,
    dispatch: RefCell<Slab<Scheduled, usize>>,
}

/// Handle to an event loop, used to construct I/O objects, send messages, and
/// otherwise interact indirectly with the event loop itself.
///
/// Handles can be cloned, and when cloned they will still refer to the
/// same underlying event loop.
#[derive(Clone)]
pub struct LoopHandle {
    id: usize,
    tx: mio::channel::Sender<Message>,
}

#[derive(Copy, Clone)]
pub enum Direction {
    Read,
    Write,
}

struct Scheduled {
    source: Source,
    reader: Option<Arc<Wake>>,
    writer: Option<Arc<Wake>>,
}

impl Scheduled {
    fn waiter_for(&mut self, dir: Direction) -> &mut Option<Arc<Wake>> {
        match dir {
            Direction::Read => &mut self.reader,
            Direction::Write => &mut self.writer,
        }
    }

    fn event_set(&self) -> mio::EventSet {
        let mut set = mio::EventSet::none();
        if self.reader.is_some() {
            set = set | mio::EventSet::readable()
        }
        if self.writer.is_some() {
            set = set | mio::EventSet::writable()
        }
        set
    }
}

enum Message {
    AddSource(Source, Arc<Slot<io::Result<usize>>>),
    DropSource(usize),
    Schedule(usize, Direction, Arc<Wake>),
    Deschedule(usize, Direction),
    Shutdown,
}

fn register(poll: &mut mio::Poll,
            token: usize,
            sched: &Scheduled) -> io::Result<()> {
    poll.register(&*sched.source,
                  mio::Token(token),
                  mio::EventSet::none(),
                  mio::PollOpt::level())
}

fn reregister(poll: &mut mio::Poll, token: usize, sched: &Scheduled) {
    // TODO: handle error
    poll.reregister(&*sched.source,
                    mio::Token(token),
                    sched.event_set(),
                    mio::PollOpt::edge() | mio::PollOpt::oneshot())
        .unwrap();
}

fn deregister(poll: &mut mio::Poll, sched: &Scheduled) {
    // TODO: handle error
    poll.deregister(&*sched.source).unwrap();
}

impl Loop {
    pub fn new() -> io::Result<Loop> {
        let (tx, rx) = mio::channel::from_std_channel(mpsc::channel());
        let io = try!(mio::Poll::new());
        try!(io.register(&rx,
                         mio::Token(0),
                         mio::EventSet::readable(),
                         mio::PollOpt::edge()));
        Ok(Loop {
            id: NEXT_LOOP_ID.fetch_add(1, Ordering::Relaxed),
            active: Cell::new(true),
            io: RefCell::new(io),
            tx: tx,
            rx: rx,
            dispatch: RefCell::new(Slab::new_starting_at(1, SLAB_CAPACITY)),
        })
    }

    pub fn handle(&self) -> LoopHandle {
        LoopHandle {
            id: self.id,
            tx: self.tx.clone(),
        }
    }

    pub fn run<F: Future>(self, f: F) -> Result<F::Item, F::Error> {
        let (tx_res, rx_res) = mpsc::channel();
        let handle = self.handle();
        f.then(move |res| {
            handle.shutdown();
            tx_res.send(res)
        }).forget();

        while self.active.get() {
            let amt;
            // On Linux, Poll::poll is epoll_wait, which may return EINTR if a
            // ptracer attaches. This retry loop prevents crashing when
            // attaching strace, or similar.
            loop {
                match self.io.borrow_mut().poll(None) {
                    Ok(a) => {
                        amt = a;
                        break;
                    }
                    Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
                    err @ Err(_) => {
                        err.unwrap();
                    }
                }
            }

            // TODO: coalesce token sets for a given Wake?
            for i in 0..amt {
                let event = self.io.borrow_mut().events().get(i).unwrap();
                let token = event.token().as_usize();
                if token == 0 {
                    self.consume_queue();
                } else {
                    let mut reader = None;
                    let mut writer = None;

                    if let Some(sched) = self.dispatch.borrow_mut().get_mut(token) {
                        if event.kind().is_readable() {
                            reader = sched.reader.take();
                        }

                        if event.kind().is_writable() {
                            writer = sched.writer.take();
                        }
                    }

                    CURRENT_LOOP.set(&self, || {
                        if let Some(reader_wake) = reader.take() {
                            reader_wake.wake(&Tokens::from_usize(token));
                        }
                        if let Some(writer_wake) = writer.take() {
                            writer_wake.wake(&Tokens::from_usize(token));
                        }
                    });

                    // For now, always reregister, to deal with the fact that
                    // combined oneshot + read|write requires rearming even if
                    // only one side fired.
                    //
                    // TODO: optimize this
                    if let Some(sched) = self.dispatch.borrow().get(token) {
                        reregister(&mut self.io.borrow_mut(), token, &sched);
                    }
                }
            }
        }

        rx_res.recv().unwrap()
    }

    fn add_source(&self, source: Source) -> io::Result<usize> {
        let sched = Scheduled {
            source: source,
            reader: None,
            writer: None,
        };
        let mut dispatch = self.dispatch.borrow_mut();
        // TODO: handle out of space
        let entry = dispatch.vacant_entry().unwrap();
        try!(register(&mut self.io.borrow_mut(), entry.index(), &sched));
        Ok(entry.insert(sched).index())
    }

    fn drop_source(&self, token: usize) {
        let sched = self.dispatch.borrow_mut().remove(token).unwrap();
        deregister(&mut self.io.borrow_mut(), &sched);
    }

    fn schedule(&self, token: usize, dir: Direction, wake: Arc<Wake>) {
        let mut dispatch = self.dispatch.borrow_mut();
        let sched = dispatch.get_mut(token).unwrap();
        *sched.waiter_for(dir) = Some(wake);
        reregister(&mut self.io.borrow_mut(), token, sched);
    }

    fn deschedule(&self, token: usize, dir: Direction) {
        let mut dispatch = self.dispatch.borrow_mut();
        let sched = dispatch.get_mut(token).unwrap();
        *sched.waiter_for(dir) = None;
        reregister(&mut self.io.borrow_mut(), token, sched);
    }

    fn consume_queue(&self) {
        while let Ok(msg) = self.rx.try_recv() {
            self.notify(msg);
        }
    }

    fn notify(&self, msg: Message) {
        match msg {
            Message::AddSource(source, slot) => {
                // This unwrap() should always be ok as we're the only producer
                slot.try_produce(self.add_source(source))
                    .ok().expect("interference with try_produce");
            }
            Message::DropSource(tok) => self.drop_source(tok),
            Message::Schedule(tok, dir, wake) => self.schedule(tok, dir, wake),
            Message::Deschedule(tok, dir) => self.deschedule(tok, dir),
            Message::Shutdown => self.active.set(false),
        }
    }
}

impl LoopHandle {
    fn send(&self, msg: Message) {
        self.with_loop(|lp| {
            match lp {
                Some(lp) => {
                    // Need to execute all existing requests first, to ensure
                    // that our message is processed "in order"
                    lp.consume_queue();
                    lp.notify(msg);
                }
                None => {
                    // TODO: handle failure
                    self.tx
                        .send(msg)
                        .map_err(|_| ())
                        .expect("failed to send register message")
                }
            }
        })
    }

    fn with_loop<F, R>(&self, f: F) -> R
        where F: FnOnce(Option<&Loop>) -> R
    {
        if CURRENT_LOOP.is_set() {
            CURRENT_LOOP.with(|lp| {
                if lp.id == self.id {
                    f(Some(lp))
                } else {
                    f(None)
                }
            })
        } else {
            f(None)
        }
    }

    /// Add a new source to an event loop, returning a future which will resolve
    /// to the token that can be used to identify this source.
    ///
    /// When a new I/O object is created it needs to be communicated to the
    /// event loop to ensure that it's registered and ready to receive
    /// notifications. The event loop with then respond with a unique token that
    /// this handle can be identified with (the resolved value of the returned
    /// future).
    ///
    /// This token is then passed in turn to each of the methods below to
    /// interact with notifications on the I/O object itself.
    pub fn add_source(&self, source: Source) -> AddSource {
        AddSource {
            loop_handle: self.clone(),
            source: Some(source),
            result: None,
        }
    }

    fn add_source_(&self, source: Source, slot: Arc<Slot<io::Result<usize>>>) {
        self.send(Message::AddSource(source, slot));
    }

    /// Begin listening for events on an event loop.
    ///
    /// Once an I/O object has been registered with the event loop through the
    /// `add_source` method, this method can be used with the assigned token to
    /// begin awaiting notifications.
    ///
    /// The `dir` argument indicates how the I/O object is expected to be
    /// awaited on (either readable or writable) and the `wake` callback will be
    /// invoked. Note that one the `wake` callback is invoked once it will not
    /// be invoked again, it must be re-`schedule`d to continue receiving
    /// notifications.
    pub fn schedule(&self, tok: usize, dir: Direction, wake: Arc<Wake>) {
        self.send(Message::Schedule(tok, dir, wake));
    }

    /// Stop listening for events on an event loop.
    ///
    /// Once a callback has been scheduled with the `schedule` method, it can be
    /// unregistered from the event loop with this method. This method does not
    /// guarantee that the callback will not be invoked if it hasn't already,
    /// but a best effort will be made to ensure it is not called.
    pub fn deschedule(&self, tok: usize, dir: Direction) {
        self.send(Message::Deschedule(tok, dir));
    }

    /// Unregister all information associated with a token on an event loop,
    /// deallocating all internal resources assigned to the given token.
    ///
    /// This method should be called whenever a source of events is being
    /// destroyed. This will ensure that the event loop can reuse `tok` for
    /// another I/O object if necessary and also remove it from any poll
    /// notifications and callbacks.
    ///
    /// Note that wake callbacks may still be invoked after this method is
    /// called as it may take some time for the message to drop a source to
    /// reach the event loop. Despite this fact, this method will attempt to
    /// ensure that the callbacks are **not** invoked, so pending scheduled
    /// callbacks cannot be relied upon to get called.
    pub fn drop_source(&self, tok: usize) {
        self.send(Message::DropSource(tok));
    }

    pub fn shutdown(&self) {
        self.send(Message::Shutdown);
    }
}

const ADD_SOURCE_TOKEN: usize = 0;

/// A future which will resolve a unique `tok` token for an I/O object.
///
/// Created through the `LoopHandle::add_source` method, this future can also
/// resolve to an error if there's an issue communicating with the event loop.
pub struct AddSource {
    loop_handle: LoopHandle,
    source: Option<Source>,
    result: Option<(Arc<Slot<io::Result<usize>>>, slot::Token)>,
}

impl Future for AddSource {
    type Item = usize;
    type Error = io::Error;

    fn poll(&mut self, tokens: &Tokens) -> Option<Result<usize, io::Error>> {
        match self.result {
            Some((ref result, _)) => {
                if tokens.may_contain(&Tokens::from_usize(ADD_SOURCE_TOKEN)) {
                    result.try_consume().ok()
                } else {
                    None
                }
            }
            None => {
                let source = &mut self.source;
                self.loop_handle.with_loop(|lp| {
                    lp.map(|lp| {
                        lp.add_source(source.take().unwrap())
                    })
                })
            }
        }
    }

    fn schedule(&mut self, wake: Arc<Wake>) {
        if let Some((ref result, ref mut token)) = self.result {
            result.cancel(*token);
            *token = result.on_full(move |_| {
                wake.wake(&Tokens::from_usize(ADD_SOURCE_TOKEN));
            });
            return
        }

        let result = Arc::new(Slot::new(None));
        let token = result.on_full(move |_| {
            wake.wake(&Tokens::from_usize(ADD_SOURCE_TOKEN));
        });
        self.result = Some((result.clone(), token));
        self.loop_handle.add_source_(self.source.take().unwrap(), result);
    }
}
<commit_msg>Grow the dispatch list if needed during add_source<commit_after>use std::cell::{Cell, RefCell};
use std::io::{self, ErrorKind};
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use std::sync::mpsc;

use mio;
use slab::Slab;
use futures::{Future, Tokens, Wake};

use slot::{self, Slot};

pub type Source = Arc<mio::Evented + Send + Sync>;

static NEXT_LOOP_ID: AtomicUsize = ATOMIC_USIZE_INIT;
scoped_thread_local!(static CURRENT_LOOP: Loop);

const SLAB_CAPACITY: usize = 1024 * 64;

pub struct Loop {
    id: usize,
    active: Cell<bool>,
    io: RefCell<mio::Poll>,
    tx: mio::channel::Sender<Message>,
    rx: mio::channel::Receiver<Message>,
    dispatch: RefCell<Slab<Scheduled, usize>>,
}

/// Handle to an event loop, used to construct I/O objects, send messages, and
/// otherwise interact indirectly with the event loop itself.
///
/// Handles can be cloned, and when cloned they will still refer to the
/// same underlying event loop.
#[derive(Clone)]
pub struct LoopHandle {
    id: usize,
    tx: mio::channel::Sender<Message>,
}

#[derive(Copy, Clone)]
pub enum Direction {
    Read,
    Write,
}

struct Scheduled {
    source: Source,
    reader: Option<Arc<Wake>>,
    writer: Option<Arc<Wake>>,
}

impl Scheduled {
    fn waiter_for(&mut self, dir: Direction) -> &mut Option<Arc<Wake>> {
        match dir {
            Direction::Read => &mut self.reader,
            Direction::Write => &mut self.writer,
        }
    }

    fn event_set(&self) -> mio::EventSet {
        let mut set = mio::EventSet::none();
        if self.reader.is_some() {
            set = set | mio::EventSet::readable()
        }
        if self.writer.is_some() {
            set = set | mio::EventSet::writable()
        }
        set
    }
}

enum Message {
    AddSource(Source, Arc<Slot<io::Result<usize>>>),
    DropSource(usize),
    Schedule(usize, Direction, Arc<Wake>),
    Deschedule(usize, Direction),
    Shutdown,
}

fn register(poll: &mut mio::Poll,
            token: usize,
            sched: &Scheduled) -> io::Result<()> {
    poll.register(&*sched.source,
                  mio::Token(token),
                  mio::EventSet::none(),
                  mio::PollOpt::level())
}

fn reregister(poll: &mut mio::Poll, token: usize, sched: &Scheduled) {
    // TODO: handle error
    poll.reregister(&*sched.source,
                    mio::Token(token),
                    sched.event_set(),
                    mio::PollOpt::edge() | mio::PollOpt::oneshot())
        .unwrap();
}

fn deregister(poll: &mut mio::Poll, sched: &Scheduled) {
    // TODO: handle error
    poll.deregister(&*sched.source).unwrap();
}

impl Loop {
    pub fn new() -> io::Result<Loop> {
        let (tx, rx) = mio::channel::from_std_channel(mpsc::channel());
        let io = try!(mio::Poll::new());
        try!(io.register(&rx,
                         mio::Token(0),
                         mio::EventSet::readable(),
                         mio::PollOpt::edge()));
        Ok(Loop {
            id: NEXT_LOOP_ID.fetch_add(1, Ordering::Relaxed),
            active: Cell::new(true),
            io: RefCell::new(io),
            tx: tx,
            rx: rx,
            dispatch: RefCell::new(Slab::new_starting_at(1, SLAB_CAPACITY)),
        })
    }

    pub fn handle(&self) -> LoopHandle {
        LoopHandle {
            id: self.id,
            tx: self.tx.clone(),
        }
    }

    pub fn run<F: Future>(self, f: F) -> Result<F::Item, F::Error> {
        let (tx_res, rx_res) = mpsc::channel();
        let handle = self.handle();
        f.then(move |res| {
            handle.shutdown();
            tx_res.send(res)
        }).forget();

        while self.active.get() {
            let amt;
            // On Linux, Poll::poll is epoll_wait, which may return EINTR if a
            // ptracer attaches. This retry loop prevents crashing when
            // attaching strace, or similar.
            loop {
                match self.io.borrow_mut().poll(None) {
                    Ok(a) => {
                        amt = a;
                        break;
                    }
                    Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
                    err @ Err(_) => {
                        err.unwrap();
                    }
                }
            }

            // TODO: coalesce token sets for a given Wake?
            for i in 0..amt {
                let event = self.io.borrow_mut().events().get(i).unwrap();
                let token = event.token().as_usize();
                if token == 0 {
                    self.consume_queue();
                } else {
                    let mut reader = None;
                    let mut writer = None;

                    if let Some(sched) = self.dispatch.borrow_mut().get_mut(token) {
                        if event.kind().is_readable() {
                            reader = sched.reader.take();
                        }

                        if event.kind().is_writable() {
                            writer = sched.writer.take();
                        }
                    }

                    CURRENT_LOOP.set(&self, || {
                        if let Some(reader_wake) = reader.take() {
                            reader_wake.wake(&Tokens::from_usize(token));
                        }
                        if let Some(writer_wake) = writer.take() {
                            writer_wake.wake(&Tokens::from_usize(token));
                        }
                    });

                    // For now, always reregister, to deal with the fact that
                    // combined oneshot + read|write requires rearming even if
                    // only one side fired.
                    //
                    // TODO: optimize this
                    if let Some(sched) = self.dispatch.borrow().get(token) {
                        reregister(&mut self.io.borrow_mut(), token, &sched);
                    }
                }
            }
        }

        rx_res.recv().unwrap()
    }

    fn add_source(&self, source: Source) -> io::Result<usize> {
        let sched = Scheduled {
            source: source,
            reader: None,
            writer: None,
        };
        let mut dispatch = self.dispatch.borrow_mut();
        if dispatch.vacant_entry().is_none() {
            let amt = dispatch.count();
            dispatch.grow(amt);
        }
        let entry = dispatch.vacant_entry().unwrap();
        try!(register(&mut self.io.borrow_mut(), entry.index(), &sched));
        Ok(entry.insert(sched).index())
    }

    fn drop_source(&self, token: usize) {
        let sched = self.dispatch.borrow_mut().remove(token).unwrap();
        deregister(&mut self.io.borrow_mut(), &sched);
    }

    fn schedule(&self, token: usize, dir: Direction, wake: Arc<Wake>) {
        let mut dispatch = self.dispatch.borrow_mut();
        let sched = dispatch.get_mut(token).unwrap();
        *sched.waiter_for(dir) = Some(wake);
        reregister(&mut self.io.borrow_mut(), token, sched);
    }

    fn deschedule(&self, token: usize, dir: Direction) {
        let mut dispatch = self.dispatch.borrow_mut();
        let sched = dispatch.get_mut(token).unwrap();
        *sched.waiter_for(dir) = None;
        reregister(&mut self.io.borrow_mut(), token, sched);
    }

    fn consume_queue(&self) {
        while let Ok(msg) = self.rx.try_recv() {
            self.notify(msg);
        }
    }

    fn notify(&self, msg: Message) {
        match msg {
            Message::AddSource(source, slot) => {
                // This unwrap() should always be ok as we're the only producer
                slot.try_produce(self.add_source(source))
                    .ok().expect("interference with try_produce");
            }
            Message::DropSource(tok) => self.drop_source(tok),
            Message::Schedule(tok, dir, wake) => self.schedule(tok, dir, wake),
            Message::Deschedule(tok, dir) => self.deschedule(tok, dir),
            Message::Shutdown => self.active.set(false),
        }
    }
}

impl LoopHandle {
    fn send(&self, msg: Message) {
        self.with_loop(|lp| {
            match lp {
                Some(lp) => {
                    // Need to execute all existing requests first, to ensure
                    // that our message is processed "in order"
                    lp.consume_queue();
                    lp.notify(msg);
                }
                None => {
                    // TODO: handle failure
                    self.tx
                        .send(msg)
                        .map_err(|_| ())
                        .expect("failed to send register message")
                }
            }
        })
    }

    fn with_loop<F, R>(&self, f: F) -> R
        where F: FnOnce(Option<&Loop>) -> R
    {
        if CURRENT_LOOP.is_set() {
            CURRENT_LOOP.with(|lp| {
                if lp.id == self.id {
                    f(Some(lp))
                } else {
                    f(None)
                }
            })
        } else {
            f(None)
        }
    }

    /// Add a new source to an event loop, returning a future which will resolve
    /// to the token that can be used to identify this source.
    ///
    /// When a new I/O object is created it needs to be communicated to the
    /// event loop to ensure that it's registered and ready to receive
    /// notifications. The event loop with then respond with a unique token that
    /// this handle can be identified with (the resolved value of the returned
    /// future).
    ///
    /// This token is then passed in turn to each of the methods below to
    /// interact with notifications on the I/O object itself.
    pub fn add_source(&self, source: Source) -> AddSource {
        AddSource {
            loop_handle: self.clone(),
            source: Some(source),
            result: None,
        }
    }

    fn add_source_(&self, source: Source, slot: Arc<Slot<io::Result<usize>>>) {
        self.send(Message::AddSource(source, slot));
    }

    /// Begin listening for events on an event loop.
    ///
    /// Once an I/O object has been registered with the event loop through the
    /// `add_source` method, this method can be used with the assigned token to
    /// begin awaiting notifications.
    ///
    /// The `dir` argument indicates how the I/O object is expected to be
    /// awaited on (either readable or writable) and the `wake` callback will be
    /// invoked. Note that one the `wake` callback is invoked once it will not
    /// be invoked again, it must be re-`schedule`d to continue receiving
    /// notifications.
    pub fn schedule(&self, tok: usize, dir: Direction, wake: Arc<Wake>) {
        self.send(Message::Schedule(tok, dir, wake));
    }

    /// Stop listening for events on an event loop.
    ///
    /// Once a callback has been scheduled with the `schedule` method, it can be
    /// unregistered from the event loop with this method. This method does not
    /// guarantee that the callback will not be invoked if it hasn't already,
    /// but a best effort will be made to ensure it is not called.
    pub fn deschedule(&self, tok: usize, dir: Direction) {
        self.send(Message::Deschedule(tok, dir));
    }

    /// Unregister all information associated with a token on an event loop,
    /// deallocating all internal resources assigned to the given token.
    ///
    /// This method should be called whenever a source of events is being
    /// destroyed. This will ensure that the event loop can reuse `tok` for
    /// another I/O object if necessary and also remove it from any poll
    /// notifications and callbacks.
    ///
    /// Note that wake callbacks may still be invoked after this method is
    /// called as it may take some time for the message to drop a source to
    /// reach the event loop. Despite this fact, this method will attempt to
    /// ensure that the callbacks are **not** invoked, so pending scheduled
    /// callbacks cannot be relied upon to get called.
    pub fn drop_source(&self, tok: usize) {
        self.send(Message::DropSource(tok));
    }

    pub fn shutdown(&self) {
        self.send(Message::Shutdown);
    }
}

const ADD_SOURCE_TOKEN: usize = 0;

/// A future which will resolve a unique `tok` token for an I/O object.
///
/// Created through the `LoopHandle::add_source` method, this future can also
/// resolve to an error if there's an issue communicating with the event loop.
pub struct AddSource {
    loop_handle: LoopHandle,
    source: Option<Source>,
    result: Option<(Arc<Slot<io::Result<usize>>>, slot::Token)>,
}

impl Future for AddSource {
    type Item = usize;
    type Error = io::Error;

    fn poll(&mut self, tokens: &Tokens) -> Option<Result<usize, io::Error>> {
        match self.result {
            Some((ref result, _)) => {
                if tokens.may_contain(&Tokens::from_usize(ADD_SOURCE_TOKEN)) {
                    result.try_consume().ok()
                } else {
                    None
                }
            }
            None => {
                let source = &mut self.source;
                self.loop_handle.with_loop(|lp| {
                    lp.map(|lp| {
                        lp.add_source(source.take().unwrap())
                    })
                })
            }
        }
    }

    fn schedule(&mut self, wake: Arc<Wake>) {
        if let Some((ref result, ref mut token)) = self.result {
            result.cancel(*token);
            *token = result.on_full(move |_| {
                wake.wake(&Tokens::from_usize(ADD_SOURCE_TOKEN));
            });
            return
        }

        let result = Arc::new(Slot::new(None));
        let token = result.on_full(move |_| {
            wake.wake(&Tokens::from_usize(ADD_SOURCE_TOKEN));
        });
        self.result = Some((result.clone(), token));
        self.loop_handle.add_source_(self.source.take().unwrap(), result);
    }
}
<|endoftext|>


<commit_before>//! Kata OS security coordinator fake support

extern crate alloc;
use alloc::string::{String, ToString};
use hashbrown::HashMap;
use kata_os_common::sel4_sys;
use kata_os_common::slot_allocator;
use kata_memory_interface::ObjDescBundle;
use kata_memory_interface::kata_object_free;
use kata_security_interface::*;
use kata_storage_interface::KeyValueData;
use log::error;

use sel4_sys::seL4_CNode_Delete;
use sel4_sys::seL4_CPtr;
use sel4_sys::seL4_WordBits;

use slot_allocator::KATA_CSPACE_SLOTS;

extern "C" {
    static SELF_CNODE: seL4_CPtr;
}

struct BundleData {
    pkg_contents: ObjDescBundle,
    pkg_size: usize,
    manifest: String,
    keys: HashMap<String, KeyValueData>,
}
impl BundleData {
    fn new(pkg_contents: &ObjDescBundle) -> Self {
        let size = pkg_contents.objs.len() * 4096; // XXX
        BundleData {
            pkg_contents: pkg_contents.clone(),
            pkg_size: size,
            manifest: String::from(
                "# Comments like this
                        [Manifest]
                        BundleId=com.google.cerebra.hw.HelloWorld

                        [Binaries]
                        App=HelloWorldBin
                        Model=NeuralNetworkName

                        [Storage]
                        Required=1
                      ",
            ),
            keys: HashMap::with_capacity(2),
        }
    }
}
impl Drop for BundleData {
    fn drop(&mut self) {
        let _ = kata_object_free(&self.pkg_contents);
        unsafe {
            KATA_CSPACE_SLOTS.free(self.pkg_contents.cnode, 1);
            if let Err(e) = seL4_CNode_Delete(SELF_CNODE, self.pkg_contents.cnode, seL4_WordBits as u8) {
                // XXX no bundle_id
                error!("Error deleting CNode {}, error {:?}", self.pkg_contents.cnode, e);
            }
        }
    }
}

pub struct FakeSecurityCoordinator {
    bundles: HashMap<String, BundleData>,
}
impl Default for FakeSecurityCoordinator {
    fn default() -> Self {
        Self::new()
    }
}
impl FakeSecurityCoordinator {
    pub fn new() -> Self {
        FakeSecurityCoordinator {
            bundles: HashMap::with_capacity(2),
        }
    }

    fn get_bundle(&self, bundle_id: &str) -> Result<&BundleData, SecurityRequestError> {
        self.bundles
            .get(bundle_id)
            .map_or_else(|| Err(SecurityRequestError::SreBundleNotFound), Ok)
    }
    fn get_bundle_mut(&mut self, bundle_id: &str) -> Result<&mut BundleData, SecurityRequestError> {
        self.bundles
            .get_mut(bundle_id)
            .map_or_else(|| Err(SecurityRequestError::SreBundleNotFound), Ok)
    }
    fn remove_bundle(&mut self, bundle_id: &str) -> Result<(), SecurityRequestError> {
        self.bundles
            .remove(bundle_id)
            .map_or_else(|| Err(SecurityRequestError::SreBundleNotFound), |_| Ok(()))
    }
}
pub type KataSecurityCoordinatorInterface = FakeSecurityCoordinator;

impl SecurityCoordinatorInterface for FakeSecurityCoordinator {
    fn install(&mut self, pkg_contents: &ObjDescBundle) -> Result<String, SecurityRequestError> {
        let bundle_id = "fubar".to_string(); // XXX
        if self.bundles.contains_key(&bundle_id) {
            return Err(SecurityRequestError::SreDeleteFirst);
        }
        assert!(self.bundles.insert(bundle_id.clone(), BundleData::new(pkg_contents)).is_none());
        Ok(bundle_id)
    }
    fn uninstall(&mut self, bundle_id: &str) -> Result<(), SecurityRequestError> {
        self.remove_bundle(bundle_id)
    }
    fn size_buffer(&self, bundle_id: &str) -> Result<usize, SecurityRequestError> {
        let bundle = self.get_bundle(bundle_id)?;
        Ok(bundle.pkg_size) // TODO(sleffler): do better
    }
    fn get_manifest(&self, bundle_id: &str) -> Result<String, SecurityRequestError> {
        let bundle = self.get_bundle(bundle_id)?;
        // return &?
        Ok(bundle.manifest.clone())
    }
    fn load_application(&self, bundle_id: &str) -> Result<ObjDescBundle, SecurityRequestError> {
        let bundle_data = self.get_bundle(bundle_id)?;
        // XXX just return the package for now
        Ok(bundle_data.pkg_contents.clone())
    }
    fn load_model(&self, bundle_id: &str, _model_id: &str) -> Result<ObjDescBundle, SecurityRequestError> {
        let bundle_data = self.get_bundle(bundle_id)?;
        // TODO(sleffler): check model id
        // XXX just return the package for now
        Ok(bundle_data.pkg_contents.clone())
    }
    fn read_key(&self, bundle_id: &str, key: &str) -> Result<&KeyValueData, SecurityRequestError> {
        let bundle = self.get_bundle(bundle_id)?;
        bundle.keys.get(key).ok_or(SecurityRequestError::SreKeyNotFound)
    }
    fn write_key(&mut self, bundle_id: &str, key: &str, value: &KeyValueData) -> Result<(), SecurityRequestError> {
        let bundle = self.get_bundle_mut(bundle_id)?;
        let _ = bundle.keys.insert(key.to_string(), *value);
        Ok(())
    }
    fn delete_key(&mut self, bundle_id: &str, key: &str) -> Result<(), SecurityRequestError> {
        let bundle = self.get_bundle_mut(bundle_id)?;
        // TODO(sleffler): error if no entry?
        let _ = bundle.keys.remove(key);
        Ok(())
    }
}
<commit_msg>kata-security-coordinator: fix fakeimpl memory stats<commit_after>//! Kata OS security coordinator fake support

extern crate alloc;
use alloc::string::{String, ToString};
use hashbrown::HashMap;
use kata_memory_interface::ObjDescBundle;
use kata_memory_interface::kata_object_free_in_cnode;
use kata_security_interface::*;
use kata_storage_interface::KeyValueData;

struct BundleData {
    pkg_contents: ObjDescBundle,
    pkg_size: usize,
    manifest: String,
    keys: HashMap<String, KeyValueData>,
}
impl BundleData {
    fn new(pkg_contents: &ObjDescBundle) -> Self {
        let size = pkg_contents.objs.len() * 4096; // XXX
        BundleData {
            pkg_contents: pkg_contents.clone(),
            pkg_size: size,
            manifest: String::from(
                "# Comments like this
                        [Manifest]
                        BundleId=com.google.cerebra.hw.HelloWorld

                        [Binaries]
                        App=HelloWorldBin
                        Model=NeuralNetworkName

                        [Storage]
                        Required=1
                      ",
            ),
            keys: HashMap::with_capacity(2),
        }
    }
}
impl Drop for BundleData {
    fn drop(&mut self) {
        let _ = kata_object_free_in_cnode(&self.pkg_contents);
    }
}

pub struct FakeSecurityCoordinator {
    bundles: HashMap<String, BundleData>,
}
impl Default for FakeSecurityCoordinator {
    fn default() -> Self {
        Self::new()
    }
}
impl FakeSecurityCoordinator {
    pub fn new() -> Self {
        FakeSecurityCoordinator {
            bundles: HashMap::with_capacity(2),
        }
    }

    fn get_bundle(&self, bundle_id: &str) -> Result<&BundleData, SecurityRequestError> {
        self.bundles
            .get(bundle_id)
            .map_or_else(|| Err(SecurityRequestError::SreBundleNotFound), Ok)
    }
    fn get_bundle_mut(&mut self, bundle_id: &str) -> Result<&mut BundleData, SecurityRequestError> {
        self.bundles
            .get_mut(bundle_id)
            .map_or_else(|| Err(SecurityRequestError::SreBundleNotFound), Ok)
    }
    fn remove_bundle(&mut self, bundle_id: &str) -> Result<(), SecurityRequestError> {
        self.bundles
            .remove(bundle_id)
            .map_or_else(|| Err(SecurityRequestError::SreBundleNotFound), |_| Ok(()))
    }
}
pub type KataSecurityCoordinatorInterface = FakeSecurityCoordinator;

impl SecurityCoordinatorInterface for FakeSecurityCoordinator {
    fn install(&mut self, pkg_contents: &ObjDescBundle) -> Result<String, SecurityRequestError> {
        let bundle_id = "fubar".to_string(); // XXX
        if self.bundles.contains_key(&bundle_id) {
            return Err(SecurityRequestError::SreDeleteFirst);
        }
        assert!(self.bundles.insert(bundle_id.clone(), BundleData::new(pkg_contents)).is_none());
        Ok(bundle_id)
    }
    fn uninstall(&mut self, bundle_id: &str) -> Result<(), SecurityRequestError> {
        self.remove_bundle(bundle_id)
    }
    fn size_buffer(&self, bundle_id: &str) -> Result<usize, SecurityRequestError> {
        let bundle = self.get_bundle(bundle_id)?;
        Ok(bundle.pkg_size) // TODO(sleffler): do better
    }
    fn get_manifest(&self, bundle_id: &str) -> Result<String, SecurityRequestError> {
        let bundle = self.get_bundle(bundle_id)?;
        // return &?
        Ok(bundle.manifest.clone())
    }
    fn load_application(&self, bundle_id: &str) -> Result<ObjDescBundle, SecurityRequestError> {
        let bundle_data = self.get_bundle(bundle_id)?;
        // XXX just return the package for now
        Ok(bundle_data.pkg_contents.clone())
    }
    fn load_model(&self, bundle_id: &str, _model_id: &str) -> Result<ObjDescBundle, SecurityRequestError> {
        let bundle_data = self.get_bundle(bundle_id)?;
        // TODO(sleffler): check model id
        // XXX just return the package for now
        Ok(bundle_data.pkg_contents.clone())
    }
    fn read_key(&self, bundle_id: &str, key: &str) -> Result<&KeyValueData, SecurityRequestError> {
        let bundle = self.get_bundle(bundle_id)?;
        bundle.keys.get(key).ok_or(SecurityRequestError::SreKeyNotFound)
    }
    fn write_key(&mut self, bundle_id: &str, key: &str, value: &KeyValueData) -> Result<(), SecurityRequestError> {
        let bundle = self.get_bundle_mut(bundle_id)?;
        let _ = bundle.keys.insert(key.to_string(), *value);
        Ok(())
    }
    fn delete_key(&mut self, bundle_id: &str, key: &str) -> Result<(), SecurityRequestError> {
        let bundle = self.get_bundle_mut(bundle_id)?;
        // TODO(sleffler): error if no entry?
        let _ = bundle.keys.remove(key);
        Ok(())
    }
}
<|endoftext|>


<commit_before>#![allow(unused_variables,unused_must_use)]
#[macro_use] extern crate log;
extern crate env_logger;
extern crate sozu_lib as sozu;
extern crate openssl;
extern crate time;
extern crate libc;
extern crate mio;
extern crate mio_uds;
extern crate hex;

use std::net::{UdpSocket,ToSocketAddrs};
use std::thread;
use std::env;
use std::io::stdout;
use sozu::network;
use sozu::logging::{Logger,LoggerBackend};
use sozu::messages;
use sozu::network::metrics::{METRICS,ProxyMetrics};
use sozu::channel::Channel;
use openssl::ssl;

fn main() {
  if env::var("RUST_LOG").is_ok() {
   Logger::init("EXAMPLE".to_string(), &env::var("RUST_LOG").expect("could not get the RUST_LOG env var"), LoggerBackend::Stdout(stdout()));
  } else {
   Logger::init("EXAMPLE".to_string(), "info", LoggerBackend::Stdout(stdout()));
  }

  info!("MAIN\tstarting up");
  let metrics_socket = UdpSocket::bind("0.0.0.0:0").expect("could not parse address");
  let metrics_host   = ("192.168.59.103", 8125).to_socket_addrs().expect("could not parse address").next().expect("could not get first address");
  METRICS.lock().expect("could not get metrics instance").set_up_remote(metrics_socket, metrics_host);
  let metrics_guard = ProxyMetrics::run();
  METRICS.lock().expect("could not get metrics instance").gauge("TEST", 42);

  let config = messages::HttpProxyConfiguration {
    front: "127.0.0.1:8080".parse().expect("could not parse address"),
    max_connections: 500,
    buffer_size: 16384,
    ..Default::default()
  };

  let (mut command, channel) = Channel::generate(1000, 10000).expect("should create a channel");
  let jg = thread::spawn(move || {
    network::http::start(config, channel);
  });

  let http_front = messages::HttpFront { app_id: String::from("app_1"), hostname: String::from("lolcatho.st:8080"), path_begin: String::from("/") };
  let http_instance = messages::Instance { app_id: String::from("app_1"), ip_address: String::from("127.0.0.1"), port: 1026 };
  command.write_message(&network::ProxyOrder { id: String::from("ID_ABCD"), order: messages::Order::AddHttpFront(http_front) });
  command.write_message(&network::ProxyOrder { id: String::from("ID_EFGH"), order: messages::Order::AddInstance(http_instance) });
  info!("MAIN\tHTTP -> {:?}", command.read_message());
  info!("MAIN\tHTTP -> {:?}", command.read_message());

  let config = messages::TlsProxyConfiguration {
    front: "127.0.0.1:8443".parse().expect("could not parse address"),
    max_connections: 500,
    buffer_size: 16384,
    options: (ssl::SSL_OP_CIPHER_SERVER_PREFERENCE | ssl::SSL_OP_NO_COMPRESSION |
               ssl::SSL_OP_NO_TICKET | ssl::SSL_OP_NO_SSLV2 |
               ssl::SSL_OP_NO_SSLV3 | ssl::SSL_OP_NO_TLSV1).bits(),
    cipher_list: String::from("ECDHE-ECDSA-CHACHA20-POLY1305:\
    ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:\
    ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:\
    ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:\
    DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:\
    ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:\
    ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:\
    ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:\
    ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:\
    DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:\
    ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:\
    AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:\
    AES256-SHA:DES-CBC3-SHA:!DSS"),

    ..Default::default()
  };

  let (mut command2, channel2) = Channel::generate(1000, 10000).expect("should create a channel");
  let jg2 = thread::spawn(move || {
    network::tls::start(config, channel2);
  });

  let cert1 = include_str!("../../assets/certificate.pem");
  let key1  = include_str!("../../assets/key.pem");

  let certificate_and_key = messages::CertificateAndKey {
    certificate:       String::from(cert1),
    key:               String::from(key1),
    certificate_chain: vec!()
  };
  command2.write_message(&network::ProxyOrder {
    id:    String::from("ID_IJKL1"),
    order: messages::Order::AddCertificate(certificate_and_key)
  });

  let tls_front = messages::TlsFront {
    app_id:      String::from("app_1"),
    hostname:    String::from("lolcatho.st"),
    path_begin:  String::from("/"),
    fingerprint: hex::FromHex::from_hex("AB2618B674E15243FD02A5618C66509E4840BA60E7D64CEBEC84CDBFECEEE0C5").unwrap()
  };
  command2.write_message(&network::ProxyOrder { id: String::from("ID_IJKL2"), order: messages::Order::AddTlsFront(tls_front) });
  let tls_instance = messages::Instance { app_id: String::from("app_1"), ip_address: String::from("127.0.0.1"), port: 1026 };
  command2.write_message(&network::ProxyOrder { id: String::from("ID_MNOP"), order: messages::Order::AddInstance(tls_instance) });

  let cert2 = include_str!("../../assets/cert_test.pem");
  let key2  = include_str!("../../assets/key_test.pem");

  let certificate_and_key2 = messages::CertificateAndKey {
    certificate: String::from(cert2),
    key: String::from(key2),
    certificate_chain: vec!()
  };
  command2.write_message(&network::ProxyOrder {
    id:    String::from("ID_QRST1"),
    order: messages::Order::AddCertificate(certificate_and_key2)
  });
  let tls_front2 = messages::TlsFront {
    app_id:     String::from("app_2"),
    hostname:   String::from("test.local"),
    path_begin: String::from("/"),
    fingerprint: hex::FromHex::from_hex("7E8EBF9AD0645AB755A2E51EB3734B91D4ACACEF1F28AD9D96D9385487FAE6E6").unwrap()
  };
  command2.write_message(&network::ProxyOrder { id: String::from("ID_QRST2"), order: messages::Order::AddTlsFront(tls_front2) });
  let tls_instance2 = messages::Instance { app_id: String::from("app_2"), ip_address: String::from("127.0.0.1"), port: 1026 };
  command2.write_message(&network::ProxyOrder { id: String::from("ID_UVWX"), order: messages::Order::AddInstance(tls_instance2) });

  info!("MAIN\tTLS -> {:?}", command2.read_message());
  info!("MAIN\tTLS -> {:?}", command2.read_message());
  info!("MAIN\tTLS -> {:?}", command2.read_message());
  info!("MAIN\tTLS -> {:?}", command2.read_message());

  let _ = jg.join();
  info!("MAIN\tgood bye");
}

<commit_msg>expect the right domain name in examples<commit_after>#![allow(unused_variables,unused_must_use)]
#[macro_use] extern crate log;
extern crate env_logger;
extern crate sozu_lib as sozu;
extern crate openssl;
extern crate time;
extern crate libc;
extern crate mio;
extern crate mio_uds;
extern crate hex;

use std::net::{UdpSocket,ToSocketAddrs};
use std::thread;
use std::env;
use std::io::stdout;
use sozu::network;
use sozu::logging::{Logger,LoggerBackend};
use sozu::messages;
use sozu::network::metrics::{METRICS,ProxyMetrics};
use sozu::channel::Channel;
use openssl::ssl;

fn main() {
  if env::var("RUST_LOG").is_ok() {
   Logger::init("EXAMPLE".to_string(), &env::var("RUST_LOG").expect("could not get the RUST_LOG env var"), LoggerBackend::Stdout(stdout()));
  } else {
   Logger::init("EXAMPLE".to_string(), "info", LoggerBackend::Stdout(stdout()));
  }

  info!("MAIN\tstarting up");
  let metrics_socket = UdpSocket::bind("0.0.0.0:0").expect("could not parse address");
  let metrics_host   = ("192.168.59.103", 8125).to_socket_addrs().expect("could not parse address").next().expect("could not get first address");
  METRICS.lock().expect("could not get metrics instance").set_up_remote(metrics_socket, metrics_host);
  let metrics_guard = ProxyMetrics::run();
  METRICS.lock().expect("could not get metrics instance").gauge("TEST", 42);

  let config = messages::HttpProxyConfiguration {
    front: "127.0.0.1:8080".parse().expect("could not parse address"),
    max_connections: 500,
    buffer_size: 16384,
    ..Default::default()
  };

  let (mut command, channel) = Channel::generate(1000, 10000).expect("should create a channel");
  let jg = thread::spawn(move || {
    network::http::start(config, channel);
  });

  let http_front = messages::HttpFront { app_id: String::from("app_1"), hostname: String::from("lolcatho.st"), path_begin: String::from("/") };
  let http_instance = messages::Instance { app_id: String::from("app_1"), ip_address: String::from("127.0.0.1"), port: 1026 };
  command.write_message(&network::ProxyOrder { id: String::from("ID_ABCD"), order: messages::Order::AddHttpFront(http_front) });
  command.write_message(&network::ProxyOrder { id: String::from("ID_EFGH"), order: messages::Order::AddInstance(http_instance) });
  info!("MAIN\tHTTP -> {:?}", command.read_message());
  info!("MAIN\tHTTP -> {:?}", command.read_message());

  let config = messages::TlsProxyConfiguration {
    front: "127.0.0.1:8443".parse().expect("could not parse address"),
    max_connections: 500,
    buffer_size: 16384,
    options: (ssl::SSL_OP_CIPHER_SERVER_PREFERENCE | ssl::SSL_OP_NO_COMPRESSION |
               ssl::SSL_OP_NO_TICKET | ssl::SSL_OP_NO_SSLV2 |
               ssl::SSL_OP_NO_SSLV3 | ssl::SSL_OP_NO_TLSV1).bits(),
    cipher_list: String::from("ECDHE-ECDSA-CHACHA20-POLY1305:\
    ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:\
    ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:\
    ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:\
    DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:\
    ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:\
    ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:\
    ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:\
    ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:\
    DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:\
    ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:\
    AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:\
    AES256-SHA:DES-CBC3-SHA:!DSS"),

    ..Default::default()
  };

  let (mut command2, channel2) = Channel::generate(1000, 10000).expect("should create a channel");
  let jg2 = thread::spawn(move || {
    network::tls::start(config, channel2);
  });

  let cert1 = include_str!("../../assets/certificate.pem");
  let key1  = include_str!("../../assets/key.pem");

  let certificate_and_key = messages::CertificateAndKey {
    certificate:       String::from(cert1),
    key:               String::from(key1),
    certificate_chain: vec!()
  };
  command2.write_message(&network::ProxyOrder {
    id:    String::from("ID_IJKL1"),
    order: messages::Order::AddCertificate(certificate_and_key)
  });

  let tls_front = messages::TlsFront {
    app_id:      String::from("app_1"),
    hostname:    String::from("lolcatho.st"),
    path_begin:  String::from("/"),
    fingerprint: hex::FromHex::from_hex("AB2618B674E15243FD02A5618C66509E4840BA60E7D64CEBEC84CDBFECEEE0C5").unwrap()
  };
  command2.write_message(&network::ProxyOrder { id: String::from("ID_IJKL2"), order: messages::Order::AddTlsFront(tls_front) });
  let tls_instance = messages::Instance { app_id: String::from("app_1"), ip_address: String::from("127.0.0.1"), port: 1026 };
  command2.write_message(&network::ProxyOrder { id: String::from("ID_MNOP"), order: messages::Order::AddInstance(tls_instance) });

  let cert2 = include_str!("../../assets/cert_test.pem");
  let key2  = include_str!("../../assets/key_test.pem");

  let certificate_and_key2 = messages::CertificateAndKey {
    certificate: String::from(cert2),
    key: String::from(key2),
    certificate_chain: vec!()
  };
  command2.write_message(&network::ProxyOrder {
    id:    String::from("ID_QRST1"),
    order: messages::Order::AddCertificate(certificate_and_key2)
  });
  let tls_front2 = messages::TlsFront {
    app_id:     String::from("app_2"),
    hostname:   String::from("test.local"),
    path_begin: String::from("/"),
    fingerprint: hex::FromHex::from_hex("7E8EBF9AD0645AB755A2E51EB3734B91D4ACACEF1F28AD9D96D9385487FAE6E6").unwrap()
  };
  command2.write_message(&network::ProxyOrder { id: String::from("ID_QRST2"), order: messages::Order::AddTlsFront(tls_front2) });
  let tls_instance2 = messages::Instance { app_id: String::from("app_2"), ip_address: String::from("127.0.0.1"), port: 1026 };
  command2.write_message(&network::ProxyOrder { id: String::from("ID_UVWX"), order: messages::Order::AddInstance(tls_instance2) });

  info!("MAIN\tTLS -> {:?}", command2.read_message());
  info!("MAIN\tTLS -> {:?}", command2.read_message());
  info!("MAIN\tTLS -> {:?}", command2.read_message());
  info!("MAIN\tTLS -> {:?}", command2.read_message());

  let _ = jg.join();
  info!("MAIN\tgood bye");
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017-2018 Ryan Huang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

use imgui_sys::{self, ImVec2};

use model::{Model, Move};
use view::board_parts::*;
use view::Event;
use vec2::Vec2;

const SQRT_3: f32 = 1.732_050_807_568_877_f32;

// #f7b102
const SELECT_HIGHLIGHT: [f32; 4] = [0.9686, 0.6941, 0.0078, 0.8];
// #ffff00
const LAST_MOVE_HIGHLIGHT: [f32; 4] = [1.0, 1.0, 0.0, 0.8];
// #ff0000
const EXCHANGE_HIGHLIGHT: [f32; 4] = [1.0, 0.0, 0.0, 0.8];

pub fn board(model: &Model, size: Vec2) -> Option<Event> {
    let mouse_click;
    let mut mouse_pos = ImVec2::default();
    let mut cursor_pos = ImVec2::default();
    unsafe {
        mouse_click = imgui_sys::igIsMouseClicked(0, false);
        imgui_sys::igGetMousePos(&mut mouse_pos);
        imgui_sys::igGetCursorScreenPos(&mut cursor_pos);
    }
    let cursor_pos = Vec2::from(cursor_pos);
    let mouse_pos = Vec2::from(mouse_pos);

    let side_len = (size.x / 8.0).min(size.y / (5.0 * SQRT_3));
    let origin = cursor_pos + size / 2.0;

    let extant_hexes = model.board.extant_hexes();
    let is_hex_extant = |hex| extant_hexes.contains(&hex);

    for hex in &extant_hexes {
        draw_hex(hex, origin, side_len);
    }

    if let Some(mv) = model.last_move {
        match mv {
            Move::Exchange(ref exchanged) => {
                if is_hex_extant(exchanged.to_hex()) {
                    highlight_field(EXCHANGE_HIGHLIGHT, exchanged, origin, side_len);
                }
            }
            Move::Move(ref from, ref to) => {
                if is_hex_extant(from.to_hex()) {
                    highlight_field(LAST_MOVE_HIGHLIGHT, from, origin, side_len);
                }
                highlight_field(LAST_MOVE_HIGHLIGHT, to, origin, side_len);
            }
        }
    }

    if let Some(ref coord) = model.selected_piece {
        highlight_field(SELECT_HIGHLIGHT, coord, origin, side_len);
    }

    if let Some(ref coords) = model.available_moves {
        for coord in coords {
            highlight_field_dot(SELECT_HIGHLIGHT, coord, origin, side_len);
        }
    }

    let hover_field = pixel_to_field(mouse_pos, origin, side_len);
    if let Some(ref coord) = hover_field {
        if model.exchanging && coord.color() != model.board.turn() && is_hex_extant(coord.to_hex())
            && model.board.is_piece_on_field(coord)
        {
            highlight_field(EXCHANGE_HIGHLIGHT, coord, origin, side_len);
        }
    }

    for hex in &extant_hexes {
        for f in 0..6 {
            let coord = hex.to_field(f);
            if model.board.is_piece_on_field(&coord) {
                draw_piece(&coord, origin, side_len);
            }
        }
    }

    unsafe {
        imgui_sys::igDummy(&size.into());
    }

    if mouse_click {
        hover_field.map(Event::Click)
    } else {
        None
    }
}
<commit_msg>Suppress clicks on removed hexes<commit_after>/*
 * Copyright (C) 2017-2018 Ryan Huang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

use imgui_sys::{self, ImVec2};

use model::{Model, Move};
use view::board_parts::*;
use view::Event;
use vec2::Vec2;

const SQRT_3: f32 = 1.732_050_807_568_877_f32;

// #f7b102
const SELECT_HIGHLIGHT: [f32; 4] = [0.9686, 0.6941, 0.0078, 0.8];
// #ffff00
const LAST_MOVE_HIGHLIGHT: [f32; 4] = [1.0, 1.0, 0.0, 0.8];
// #ff0000
const EXCHANGE_HIGHLIGHT: [f32; 4] = [1.0, 0.0, 0.0, 0.8];

pub fn board(model: &Model, size: Vec2) -> Option<Event> {
    let mouse_click;
    let mut mouse_pos = ImVec2::default();
    let mut cursor_pos = ImVec2::default();
    unsafe {
        mouse_click = imgui_sys::igIsMouseClicked(0, false);
        imgui_sys::igGetMousePos(&mut mouse_pos);
        imgui_sys::igGetCursorScreenPos(&mut cursor_pos);
    }
    let cursor_pos = Vec2::from(cursor_pos);
    let mouse_pos = Vec2::from(mouse_pos);

    let side_len = (size.x / 8.0).min(size.y / (5.0 * SQRT_3));
    let origin = cursor_pos + size / 2.0;

    let extant_hexes = model.board.extant_hexes();
    let is_hex_extant = |hex| extant_hexes.contains(&hex);

    for hex in &extant_hexes {
        draw_hex(hex, origin, side_len);
    }

    if let Some(mv) = model.last_move {
        match mv {
            Move::Exchange(ref exchanged) => {
                if is_hex_extant(exchanged.to_hex()) {
                    highlight_field(EXCHANGE_HIGHLIGHT, exchanged, origin, side_len);
                }
            }
            Move::Move(ref from, ref to) => {
                if is_hex_extant(from.to_hex()) {
                    highlight_field(LAST_MOVE_HIGHLIGHT, from, origin, side_len);
                }
                highlight_field(LAST_MOVE_HIGHLIGHT, to, origin, side_len);
            }
        }
    }

    if let Some(ref coord) = model.selected_piece {
        highlight_field(SELECT_HIGHLIGHT, coord, origin, side_len);
    }

    if let Some(ref coords) = model.available_moves {
        for coord in coords {
            highlight_field_dot(SELECT_HIGHLIGHT, coord, origin, side_len);
        }
    }

    let mut hover_field = pixel_to_field(mouse_pos, origin, side_len);
    if !hover_field
        .map(|field| is_hex_extant(field.to_hex()))
        .unwrap_or(false)
    {
        hover_field = None;
    }
    if let Some(ref coord) = hover_field {
        if model.exchanging && coord.color() != model.board.turn()
            && model.board.is_piece_on_field(coord)
        {
            highlight_field(EXCHANGE_HIGHLIGHT, coord, origin, side_len);
        }
    }

    for hex in &extant_hexes {
        for f in 0..6 {
            let coord = hex.to_field(f);
            if model.board.is_piece_on_field(&coord) {
                draw_piece(&coord, origin, side_len);
            }
        }
    }

    unsafe {
        imgui_sys::igDummy(&size.into());
    }

    if mouse_click {
        hover_field.map(Event::Click)
    } else {
        None
    }
}
<|endoftext|>


<commit_before>#!/usr/local/bin/rust

fn is_three(num: int) -> bool {
	num % 3 == 0
}

fn is_five(num: int) -> bool {
	num % 5 == 0
}

fn is_fifteen(num: int) -> bool {
	num % 15 == 0
}

fn for_loop() {
	for num in range(1, 101) {
		println!("Number: {} is = {}", num,
			if (num % 15 == 0) { ~"FizzBuzz" }
			else if (num % 3 == 0) { ~"Buzz" }
			else if (num % 5 == 0) { ~"Fizz" }
			else { ~"" }
		);
	}
}

fn while_loop() {
	let mut num:uint = 1;
	while num <= 100 {
		println!("Number: {} is = {}", num,
			if (num % 15 == 0) { ~"FizzBuzz" }
			else if (num % 3 == 0) { ~"Buzz" }
			else if (num % 5 == 0) { ~"Fizz" }
			else { ~"" }
		);
		num += 1;
	}
}

fn first() {
	for num in range(1, 101) {
		let mut answer = "";

		if is_fifteen(num) {
			answer = "FizzBuzz";
		} else if is_three(num) {
			answer = "Buzz";
		} else if is_five(num) {
			answer = "Fizz";
		} else {
			answer = "";
		}
		println!("Number: {} is: {}", num, answer);
	}
}

fn second() {
	for num in range(1, 101) {
		let answer =
		if is_fifteen(num) {
			"FizzBuzz"
		} else if is_three(num) {
			"Buzz"
		} else if is_five(num) {
			"Fizz"
		} else {
			""
		};
		if (answer != "") {
			println!("Number: {} is: {}", num, answer);
		}
	}
}

fn third() {
	for num in range(1, 101) {
		println!("Number: {} is = {}", num,
			if is_fifteen(num) { ~"FizzBuzz" }
			else if is_three(num) { ~"Buzz" }
			else if is_fifteen(num) { ~"Fizz" }
			else { ~"" }
		);
	}
}

fn main() {
	//for_loop();
		/*
		real	0m0.006s
		user	0m0.002s
		sys		0m0.005s
		*/
	//while_loop();
		/*
		real	0m0.006s
		user	0m0.002s
		sys		0m0.005s
		*/
	//first();
		/*
		real	0m0.006s
		user	0m0.002s
		sys		0m0.005s
		*/
	//second();
		/*
		real	0m0.006s
		user	0m0.002s
		sys		0m0.005s
		*/
	//third();
		/*
		real	0m0.006s
		user	0m0.002s
		sys		0m0.005s
		*/
}
<commit_msg>Updated rust fizzbuzz<commit_after>#!/usr/local/bin/rust

fn is_three(num: int) -> bool {
	num % 3 == 0
}

fn is_five(num: int) -> bool {
	num % 5 == 0
}

fn is_fifteen(num: int) -> bool {
	num % 15 == 0
}

fn for_loop() {
	for num in range(1, 101) {
		println!("Number: {} is = {}", num,
			if (num % 15 == 0) { ~"FizzBuzz" }
			else if (num % 3 == 0) { ~"Buzz" }
			else if (num % 5 == 0) { ~"Fizz" }
			else { ~"" }
		);
	}
}

fn while_loop() {
	let mut num:uint = 1;
	while num <= 100 {
		println!("Number: {} is = {}", num,
			if (num % 15 == 0) { ~"FizzBuzz" }
			else if (num % 3 == 0) { ~"Buzz" }
			else if (num % 5 == 0) { ~"Fizz" }
			else { ~"" }
		);
		num += 1;
	}
}

fn first() {
	for num in range(1, 101) {
		let mut answer = "";

		if is_fifteen(num) {
			answer = "FizzBuzz";
		} else if is_three(num) {
			answer = "Buzz";
		} else if is_five(num) {
			answer = "Fizz";
		} else {
			answer = "";
		}
		println!("Number: {} is: {}", num, answer);
	}
}

fn second() {
	for num in range(1, 101) {
		let answer =
		if is_fifteen(num) {
			"FizzBuzz"
		} else if is_three(num) {
			"Buzz"
		} else if is_five(num) {
			"Fizz"
		} else {
			""
		};
		if (answer != "") {
			println!("Number: {} is: {}", num, answer);
		}
	}
}

fn third() {
	for num in range(1, 101) {
		println!("Number: {} is = {}", num,
			if is_fifteen(num) { ~"FizzBuzz" }
			else if is_three(num) { ~"Buzz" }
			else if is_fifteen(num) { ~"Fizz" }
			else { ~"" }
		);
	}
}

fn main() {
	//for_loop();
	//while_loop();
	//first();
	//second();
	third();
}
<|endoftext|>