<commit_before>use std::path::Path;
use { gfx, ImageSize, Settings };
use image::{
    self,
    DynamicImage,
    GenericImage,
    RgbaImage,
};

/// Represents a texture.
#[derive(Clone, Debug, PartialEq)]
pub struct Texture<R> where R: gfx::Resources {
    handle: gfx::TextureHandle<R>
}

impl<R: gfx::Resources> Texture<R> {
    /// Gets a handle to the Gfx texture.
    pub fn handle(&self) -> gfx::TextureHandle<R> {
        self.handle.clone()
    }

    /// Returns empty texture.
    pub fn empty<F>(factory: &mut F) -> Result<Self, gfx::tex::TextureError>
        where F: gfx::Factory<R>
    {
        use gfx::traits::*;

        let tex_handle = try!(factory.create_texture_rgba8(1, 1));
        let ref image_info = tex_handle.get_info().to_image_info();
        try!(factory.update_texture(
            &tex_handle,
            image_info,
            &[0u8; 4],
            Some(gfx::tex::TextureKind::Texture2D)
        ));
        Ok(Texture {
            handle: tex_handle
        })
    }

    /// Creates a texture from path.
    pub fn from_path<F, P>(
        factory: &mut F,
        path: P,
        settings: &Settings,
    ) -> Result<Self, String>
        where F: gfx::Factory<R>,
              P: AsRef<Path>
    {
        let img = try!(image::open(path).map_err(|e| e.to_string()));

        //if settings.force_alpha //TODO
        let mut img = match img {
            DynamicImage::ImageRgba8(img) => img,
            img => img.to_rgba()
        };

        if settings.flip_vertical {
            img = image::imageops::flip_vertical(&img);
        }

        Ok(Texture::from_image(factory, &img,
                               settings.convert_gamma,
                               settings.compress,
                               settings.generate_mipmap))
    }

    /// Creates a texture from image.
    pub fn from_image<F>(
        factory: &mut F,
        image: &RgbaImage,
        convert_gamma: bool,
        _compress: bool,
        generate_mipmap: bool
    ) -> Self
        where F: gfx::Factory<R>
    {
        let (width, height) = image.dimensions();
        let tex_info = gfx::tex::TextureInfo {
            width: width as u16,
            height: height as u16,
            depth: 1,
            levels: 1,
            kind: gfx::tex::TextureKind::Texture2D,
            format: if convert_gamma {
                gfx::tex::Format::SRGB8_A8
            } else { gfx::tex::RGBA8 }
        };
        let ref image_info = tex_info.to_image_info();
        let tex_handle = factory.create_texture(tex_info).unwrap();
        factory.update_texture(
            &tex_handle,
            image_info,
            &image,
            Some(gfx::tex::TextureKind::Texture2D)
        ).unwrap();
        if generate_mipmap {
            factory.generate_mipmap(&tex_handle);
        }
        Texture {
            handle: tex_handle
        }
    }

    /// Creates texture from memory alpha.
    pub fn from_memory_alpha<F>(
        factory: &mut F,
        buffer: &[u8],
        width: u32,
        height: u32,
    ) -> Self
        where F: gfx::Factory<R>
    {
        use gfx::traits::*;

        let width = if width == 0 { 1 } else { width as u16 };
        let height = if height == 0 { 1 } else { height as u16 };

        let mut pixels = vec![];
        for alpha in buffer {
            pixels.extend(vec![255; 3]);
            pixels.push(*alpha);
        }

        let tex_handle = factory.create_texture_rgba8(width, height).unwrap();
        let ref image_info = tex_handle.get_info().to_image_info();
        factory.update_texture(
            &tex_handle,
            image_info,
            &pixels,
            Some(gfx::tex::TextureKind::Texture2D)
        ).unwrap();

        Texture {
            handle: tex_handle
        }
    }

    /// Updates the texture with an image.
    pub fn update<F>(&mut self, factory: &mut F, image: &RgbaImage)
        where F: gfx::Factory<R>
    {
        factory.update_texture(&self.handle,
            &self.handle.get_info().to_image_info(),
            &image,
            Some(gfx::tex::TextureKind::Texture2D)
        ).unwrap();
    }
}

impl<R> ImageSize for Texture<R> where R: gfx::Resources {
    #[inline(always)]
    fn get_size(&self) -> (u32, u32) {
        let info = self.handle.get_info();
        (info.width as u32, info.height as u32)
    }
}
<commit_msg>Use create_texture_static instead create_texture<commit_after>use std::path::Path;
use { gfx, ImageSize, Settings };
use image::{
    self,
    DynamicImage,
    GenericImage,
    RgbaImage,
};

/// Represents a texture.
#[derive(Clone, Debug, PartialEq)]
pub struct Texture<R> where R: gfx::Resources {
    handle: gfx::TextureHandle<R>
}

impl<R: gfx::Resources> Texture<R> {
    /// Gets a handle to the Gfx texture.
    pub fn handle(&self) -> gfx::TextureHandle<R> {
        self.handle.clone()
    }

    /// Returns empty texture.
    pub fn empty<F>(factory: &mut F) -> Result<Self, gfx::tex::TextureError>
        where F: gfx::Factory<R>
    {
        use gfx::traits::*;

        let tex_handle = try!(factory.create_texture_rgba8(1, 1));
        let ref image_info = tex_handle.get_info().to_image_info();
        try!(factory.update_texture(
            &tex_handle,
            image_info,
            &[0u8; 4],
            Some(gfx::tex::TextureKind::Texture2D)
        ));
        Ok(Texture {
            handle: tex_handle
        })
    }

    /// Creates a texture from path.
    pub fn from_path<F, P>(
        factory: &mut F,
        path: P,
        settings: &Settings,
    ) -> Result<Self, String>
        where F: gfx::Factory<R>,
              P: AsRef<Path>
    {
        let img = try!(image::open(path).map_err(|e| e.to_string()));

        //if settings.force_alpha //TODO
        let mut img = match img {
            DynamicImage::ImageRgba8(img) => img,
            img => img.to_rgba()
        };

        if settings.flip_vertical {
            img = image::imageops::flip_vertical(&img);
        }

        Ok(Texture::from_image(factory, &img,
                               settings.convert_gamma,
                               settings.compress,
                               settings.generate_mipmap))
    }

    /// Creates a texture from image.
    pub fn from_image<F>(
        factory: &mut F,
        image: &RgbaImage,
        convert_gamma: bool,
        _compress: bool,
        generate_mipmap: bool
    ) -> Self
        where F: gfx::Factory<R>
    {
        let (width, height) = image.dimensions();
        let tex_info = gfx::tex::TextureInfo {
            width: width as u16,
            height: height as u16,
            depth: 1,
            levels: 1,
            kind: gfx::tex::TextureKind::Texture2D,
            format: if convert_gamma {
                gfx::tex::Format::SRGB8_A8
            } else { gfx::tex::RGBA8 }
        };
        let tex_handle = factory.create_texture_static(tex_info, &image).unwrap();
        if generate_mipmap {
            factory.generate_mipmap(&tex_handle);
        }
        Texture {
            handle: tex_handle
        }
    }

    /// Creates texture from memory alpha.
    pub fn from_memory_alpha<F>(
        factory: &mut F,
        buffer: &[u8],
        width: u32,
        height: u32,
    ) -> Self
        where F: gfx::Factory<R>
    {
        use gfx::traits::*;

        let width = if width == 0 { 1 } else { width as u16 };
        let height = if height == 0 { 1 } else { height as u16 };

        let mut pixels = vec![];
        for alpha in buffer {
            pixels.extend(vec![255; 3]);
            pixels.push(*alpha);
        }

        let tex_handle = factory.create_texture_rgba8(width, height).unwrap();
        let ref image_info = tex_handle.get_info().to_image_info();
        factory.update_texture(
            &tex_handle,
            image_info,
            &pixels,
            Some(gfx::tex::TextureKind::Texture2D)
        ).unwrap();

        Texture {
            handle: tex_handle
        }
    }

    /// Updates the texture with an image.
    pub fn update<F>(&mut self, factory: &mut F, image: &RgbaImage)
        where F: gfx::Factory<R>
    {
        factory.update_texture(&self.handle,
            &self.handle.get_info().to_image_info(),
            &image,
            Some(gfx::tex::TextureKind::Texture2D)
        ).unwrap();
    }
}

impl<R> ImageSize for Texture<R> where R: gfx::Resources {
    #[inline(always)]
    fn get_size(&self) -> (u32, u32) {
        let info = self.handle.get_info();
        (info.width as u32, info.height as u32)
    }
}
<|endoftext|>


<commit_before>use core::{Distribution, DefaultDistribution, IntoDistribution};

use std::ops::{RangeFull};
use std::marker;
use rand::Rng;

pub struct Uniform<T> (marker::PhantomData<fn() -> T>);

impl <T> Uniform<T> where Uniform<T>: Distribution<Output=T> {
    #[inline]
    pub fn new() -> Uniform<T> {
        Uniform(marker::PhantomData)
    }
}

impl <X> IntoDistribution<X> for RangeFull where
    Uniform<X>: Distribution<Output=X>
{
    type Distribution = Uniform<X>;

    #[inline]
    fn into_distribution(self) -> Uniform<X> {
        Uniform::new()
    }
}

macro_rules! integer_size_impls {
    ($mod_name:ident, $ty:ty, $ty32:ty, $ty64:ty) => {
        mod $mod_name {
            use super::Uniform;
            use core::Distribution;

            use std::mem;
            use rand::Rng;

            impl Distribution for Uniform<$ty> {
                type Output = $ty;

                #[inline]
                fn sample<R: Rng>(&self, rng: &mut R) -> $ty {
                    if mem::size_of::<$ty>() == 4 {
                        Uniform::<$ty32>::new().sample(rng) as $ty
                    } else {
                        Uniform::<$ty64>::new().sample(rng) as $ty
                    }
                }
            }
        }
    }
}

integer_size_impls! { isize_uniform_impls, isize, i32, i64 }
integer_size_impls! { usize_uniform_impls, usize, u32, u64 }

macro_rules! integer_impls {
    ($mod_name:ident, $ty:ty, $method_name:ident) => {
        mod $mod_name {
            use super::Uniform;
            use core::Distribution;

            use rand::Rng;

            impl Distribution for Uniform<$ty> {
                type Output = $ty;

                #[inline]
                fn sample<R: Rng>(&self, rng: &mut R) -> $ty {
                    rng.$method_name() as $ty
                }
            }
        }
    }
}

integer_impls! { i8_uniform_impls,  i8,  next_u32 }
integer_impls! { i16_uniform_impls, i16, next_u32 }
integer_impls! { i32_uniform_impls, i32, next_u32 }
integer_impls! { i64_uniform_impls, i64, next_u64 }
integer_impls! { u8_uniform_impls,  u8,  next_u32 }
integer_impls! { u16_uniform_impls, u16, next_u32 }
integer_impls! { u32_uniform_impls, u32, next_u32 }
integer_impls! { u64_uniform_impls, u64, next_u64 }

impl Distribution for Uniform<bool> {
    type Output = bool;

    #[inline]
    fn sample<R: Rng>(&self, rng: &mut R) -> bool {
        Uniform::<u8>::new().sample(rng) & 1 == 1
    }
}

macro_rules! default_distribution_is_uniform {
    ($($ty:ty),* ) => {
        $(
            impl DefaultDistribution for $ty {
                type Distribution = Uniform<Self>;

                #[inline]
                fn default_distribution() -> Uniform<Self> {
                    Uniform::new()
                }
            }
        )*
    }
}

default_distribution_is_uniform! { isize, i8, i16, i32, i64,
                                   usize, u8, u16, u32, u64,
                                   bool }

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

    use core::{Distribution, IntoDistribution};

    use rand::{self, thread_rng, Rng};
    use std::ops::{RangeFull};

    #[test]
    fn test_generate_u8() {
        let mut rng: rand::XorShiftRng = rand::thread_rng().gen();

        fn foo<D: IntoDistribution<T>, T, R: Rng>(d: D, rng: &mut R) -> T {
            d.into_distribution().sample(rng)
        }

        let _: u8 = foo(RangeFull, &mut rng);
    }

    #[test]
    fn test_range_full_into_distribution() {
        let mut rng: rand::XorShiftRng = rand::thread_rng().gen();

        let d: Uniform<u8> = (..).into_distribution();
        let _: u8 = d.sample(&mut rng);
    }
}
<commit_msg>Type annotation test.<commit_after>use core::{Distribution, DefaultDistribution, IntoDistribution};

use std::ops::{RangeFull};
use std::marker;
use rand::Rng;

pub struct Uniform<T> (marker::PhantomData<fn() -> T>);

impl <T> Uniform<T> where Uniform<T>: Distribution<Output=T> {
    #[inline]
    pub fn new() -> Uniform<T> {
        Uniform(marker::PhantomData)
    }
}

impl <X> IntoDistribution<X> for RangeFull where
    Uniform<X>: Distribution<Output=X>
{
    type Distribution = Uniform<X>;

    #[inline]
    fn into_distribution(self) -> Uniform<X> {
        Uniform::new()
    }
}

macro_rules! integer_size_impls {
    ($mod_name:ident, $ty:ty, $ty32:ty, $ty64:ty) => {
        mod $mod_name {
            use super::Uniform;
            use core::Distribution;

            use std::mem;
            use rand::Rng;

            impl Distribution for Uniform<$ty> {
                type Output = $ty;

                #[inline]
                fn sample<R: Rng>(&self, rng: &mut R) -> $ty {
                    if mem::size_of::<$ty>() == 4 {
                        Uniform::<$ty32>::new().sample(rng) as $ty
                    } else {
                        Uniform::<$ty64>::new().sample(rng) as $ty
                    }
                }
            }
        }
    }
}

integer_size_impls! { isize_uniform_impls, isize, i32, i64 }
integer_size_impls! { usize_uniform_impls, usize, u32, u64 }

macro_rules! integer_impls {
    ($mod_name:ident, $ty:ty, $method_name:ident) => {
        mod $mod_name {
            use super::Uniform;
            use core::Distribution;

            use rand::Rng;

            impl Distribution for Uniform<$ty> {
                type Output = $ty;

                #[inline]
                fn sample<R: Rng>(&self, rng: &mut R) -> $ty {
                    rng.$method_name() as $ty
                }
            }
        }
    }
}

integer_impls! { i8_uniform_impls,  i8,  next_u32 }
integer_impls! { i16_uniform_impls, i16, next_u32 }
integer_impls! { i32_uniform_impls, i32, next_u32 }
integer_impls! { i64_uniform_impls, i64, next_u64 }
integer_impls! { u8_uniform_impls,  u8,  next_u32 }
integer_impls! { u16_uniform_impls, u16, next_u32 }
integer_impls! { u32_uniform_impls, u32, next_u32 }
integer_impls! { u64_uniform_impls, u64, next_u64 }

impl Distribution for Uniform<bool> {
    type Output = bool;

    #[inline]
    fn sample<R: Rng>(&self, rng: &mut R) -> bool {
        Uniform::<u8>::new().sample(rng) & 1 == 1
    }
}

macro_rules! default_distribution_is_uniform {
    ($($ty:ty),* ) => {
        $(
            impl DefaultDistribution for $ty {
                type Distribution = Uniform<Self>;

                #[inline]
                fn default_distribution() -> Uniform<Self> {
                    Uniform::new()
                }
            }
        )*
    }
}

default_distribution_is_uniform! { isize, i8, i16, i32, i64,
                                   usize, u8, u16, u32, u64,
                                   bool }

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

    use core::{Distribution, IntoDistribution};

    use rand::{self, thread_rng, Rng};
    use std::ops::{RangeFull};

    #[test]
    fn test_generate_u8() {
        let mut rng: rand::XorShiftRng = rand::thread_rng().gen();

        fn foo<D: IntoDistribution<T>, T, R: Rng>(d: D, rng: &mut R) -> T {
            d.into_distribution().sample(rng)
        }

        let _: u8 = foo(RangeFull, &mut rng);
    }

    #[test]
    fn test_generate_u8_with_type_annotation() {
        let mut rng: rand::XorShiftRng = rand::thread_rng().gen();

        let d = IntoDistribution::<u8>::into_distribution(RangeFull);
        let _ = d.sample(&mut rng);
    }

    #[test]
    fn test_range_full_into_distribution() {
        let mut rng: rand::XorShiftRng = rand::thread_rng().gen();

        let d: Uniform<u8> = (..).into_distribution();
        let _ = d.sample(&mut rng);
    }
}
<|endoftext|>


<commit_before>//! A vector with set-like lookup.
use std::borrow::Borrow;
use core;
use iter;

#[derive(Debug,Clone,Hash,PartialEq,Eq,PartialOrd,Ord)]
pub struct SplayVecSet<T> {
    tree: core::Tree<T, ()>,
}
impl<T> SplayVecSet<T>
    where T: Ord
{
    pub fn new() -> Self {
        SplayVecSet { tree: core::Tree::new() }
    }

    pub fn clear(&mut self) {
        self.tree = core::Tree::new();
    }

    pub fn push(&mut self, value: T) -> bool {
        self.tree.insert(value, ()).is_none()
    }

    pub fn pop(&mut self) -> Option<T> {
        self.tree.pop_last().map(|(k, _)| k)
    }

    pub fn contains<Q: ?Sized>(&mut self, value: &Q) -> bool
        where T: Borrow<Q>,
              Q: Ord
    {
        self.tree.contains_key(value)
    }

    pub fn find_lower_bound<Q: ?Sized>(&mut self, value: &Q) -> Option<&T>
        where T: Borrow<Q>,
              Q: Ord
    {
        self.tree.find_lower_bound(value)
    }

    pub fn find_upper_bound<Q: ?Sized>(&mut self, value: &Q) -> Option<&T>
        where T: Borrow<Q>,
              Q: Ord
    {
        self.tree.find_upper_bound(value)
    }

    pub fn find_index<Q: ?Sized>(&mut self, value: &Q) -> Option<usize>
        where T: Borrow<Q>,
              Q: Ord
    {
        self.contains(value);
        self.tree.root().map(|i| i as usize)
    }

    pub fn get(&self, index: usize) -> Option<&T> {
        if index < self.len() {
            Some(&self.tree.node_ref(index as core::NodeIndex).key)
        } else {
            None
        }
    }
}
impl<T> SplayVecSet<T> {
    pub fn len(&self) -> usize {
        self.tree.len()
    }
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }
    // pub fn iter(&self) -> Iter<T> {
    //     Iter::new(self)
    // }
}
<commit_msg>Delete vec_set.rs<commit_after><|endoftext|>


<commit_before>use std::ops;

///A 2D Vector with x and y coordinates: Vector2
#[derive(PartialEq, Debug)]
pub struct Vector2 {
    x: f32,
    y: f32,
}

impl Vector2 {
    ///Instantiates a new vector with to be defined values of x and y;
    pub fn new(x: f32, y: f32) -> Vector2 {
        Vector2 {x: x, y: y}
    }

    ///Defines a Vector with UP direction (y=1, x=0)
    pub fn UP() -> Vector2 {
        Vector2 {x: 0f32, y: 1f32}
    }

    ///Defines a Vector with DOWN direction (y=-1, x=0)
    pub fn DOWN() -> Vector2 {
        Vector2 {x: 0f32, y: -1f32}
    }

    ///Defines a Vector with RIGHT direction (y=0, x=1)
    pub fn RIGHT() -> Vector2 {
        Vector2 {x: 1f32, y: 0f32}
    }

    ///Defines a Vector with LEFT direction (y=0, x=-1)
    pub fn LEFT() -> Vector2 {
        Vector2 {x: -1f32, y: 0f32}
    }

    ///Defines a 2D Vector with x=1 and y=1
    pub fn ONE() -> Vector2 {
        Vector2 {x: 1f32, y: 1f32}
    }

    ///Defines a Modulus ZERO Vector (x=0, y=0)
    pub fn ZERO() -> Vector2 {
        Vector2 {x: 0f32, y: 0f32}
    }
}

impl ops::Add for Vector2 {
    type Output = Vector2;

    ///Implements the Vector2 '+' trait
    fn add(self, new_vec: Vector2) -> Vector2 {
        Vector2 {x: self.x + new_vec.x, y: self.y + new_vec.y}
    }
}

impl ops::Mul<f32> for Vector2 {
    type Output = Vector2;

    ///Implements The scalar multiplication of a Vector2 with a f32. Other numbers should
    ///be passed with 'i as f32'
    fn mul(self, value: f32) -> Vector2 {
        Vector2 {x: self.x * value, y: self.y * value}
    }
}

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

    #[test]
    fn creates_vector2_with_parameters() {
        let actual = Vector2::new(1f32, 1f32);
        let expected = Vector2 {x: 1f32, y: 1f32};
        assert!(expected.x == actual.x &&
            expected.y == actual.y);
    }

    #[test]
    fn creates_vector2UP() {
        let actual = Vector2::UP();
        assert!(actual.x == 0f32 &&
            actual.y == 1f32);
    }

    #[test]
    fn adds_right_and_left_vectors() {
         let actual = Vector2::RIGHT() + Vector2::LEFT();
         assert_eq!(actual.x, 0f32);
    }

    #[test]
    fn adds_right_and_up() {
        let actual = Vector2::RIGHT() + Vector2::UP();
        assert_eq!(actual.x, 1f32);
        assert_eq!(actual.y, 1f32);
    }

    #[test]
    fn mult_one_by_3() {
        let actual = Vector2::ONE() * 3f32;
        assert_eq!(actual.x, 3f32);
        assert_eq!(actual.y, 3f32);
    }
}
<commit_msg>implements sub ops<commit_after>use std::ops;

///A 2D Vector with x and y coordinates: Vector2
#[derive(PartialEq, Debug)]
pub struct Vector2 {
    x: f32,
    y: f32,
}

impl Vector2 {
    ///Instantiates a new vector with to be defined values of x and y;
    pub fn new(x: f32, y: f32) -> Vector2 {
        Vector2 {x: x, y: y}
    }

    ///Defines a Vector with UP direction (y=1, x=0)
    pub fn UP() -> Vector2 {
        Vector2 {x: 0f32, y: 1f32}
    }

    ///Defines a Vector with DOWN direction (y=-1, x=0)
    pub fn DOWN() -> Vector2 {
        Vector2 {x: 0f32, y: -1f32}
    }

    ///Defines a Vector with RIGHT direction (y=0, x=1)
    pub fn RIGHT() -> Vector2 {
        Vector2 {x: 1f32, y: 0f32}
    }

    ///Defines a Vector with LEFT direction (y=0, x=-1)
    pub fn LEFT() -> Vector2 {
        Vector2 {x: -1f32, y: 0f32}
    }

    ///Defines a 2D Vector with x=1 and y=1
    pub fn ONE() -> Vector2 {
        Vector2 {x: 1f32, y: 1f32}
    }

    ///Defines a Modulus ZERO Vector (x=0, y=0)
    pub fn ZERO() -> Vector2 {
        Vector2 {x: 0f32, y: 0f32}
    }
}

impl ops::Add for Vector2 {
    type Output = Vector2;

    ///Implements the Vector2 '+' trait
    fn add(self, new_vec: Vector2) -> Vector2 {
        Vector2 {x: self.x + new_vec.x, y: self.y + new_vec.y}
    }
}

impl ops::Mul<f32> for Vector2 {
    type Output = Vector2;

    ///Implements The scalar multiplication of a Vector2 with a f32. Other numbers should
    ///be passed with 'i as f32'
    fn mul(self, value: f32) -> Vector2 {
        Vector2 {x: self.x * value, y: self.y * value}
    }
}

impl ops::Sub for Vector2 {
    type Output = Vector2;

    ///Implements the Vector2 '+' trait
    fn sub(self, new_vec: Vector2) -> Vector2 {
        Vector2 {x: self.x - new_vec.x, y: self.y - new_vec.y}
    }
}

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

    #[test]
    fn creates_vector2_with_parameters() {
        let actual = Vector2::new(1f32, 1f32);
        let expected = Vector2 {x: 1f32, y: 1f32};
        assert!(expected.x == actual.x &&
            expected.y == actual.y);
    }

    #[test]
    fn creates_vector2UP() {
        let actual = Vector2::UP();
        assert!(actual.x == 0f32 &&
            actual.y == 1f32);
    }

    #[test]
    fn adds_right_and_left_vectors() {
         let actual = Vector2::RIGHT() + Vector2::LEFT();
         assert_eq!(actual.x, 0f32);
    }

    #[test]
    fn adds_right_and_up() {
        let actual = Vector2::RIGHT() + Vector2::UP();
        assert_eq!(actual.x, 1f32);
        assert_eq!(actual.y, 1f32);
    }

    #[test]
    fn mult_one_by_3() {
        let actual = Vector2::ONE() * 3f32;
        assert_eq!(actual.x, 3f32);
        assert_eq!(actual.y, 3f32);
    }

    #[test]
    fn sub_right_from_one() {
        let actual = Vector2::ONE() - Vector2::RIGHT();
        assert_eq!(actual.x, 0f32);
        assert_eq!(actual.y, 1f32);
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
*  License, v. 2.0. If a copy of the MPL was not distributed with this
*  file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*  Copyright (C) 2017  Juhamatti Kuusisaari / Mles developers
* */
extern crate mles_utils;

use std::thread;
use std::time::{Duration, Instant};
use std::net::SocketAddr;

use mles_utils::*;

fn main() {
    let sec = Duration::new(2,0);
    let addr = "127.0.0.1:8077";
    let addr = addr.parse::<SocketAddr>().unwrap();
    let raddr = addr.clone();
    let uid = "User".to_string();
    let channel = "Channel".to_string();
    let message = "Hello World!".to_string();
    let mut childs = Vec::new();
    let now;

    //create server
    let server = thread::spawn(move || server_run(addr, None, "".to_string(), "".to_string(), 0, 0));
    thread::sleep(sec);

    for _ in 0..100 {
        let uid = uid.clone();
        let channel = channel.clone();
        let child = thread::spawn(move || {
            //read hello world
            let mut conn = MsgConn::new(uid, channel);
            conn = conn.connect(raddr);
            let (conn, msg) = conn.read_message();
            let msg = String::from_utf8_lossy(msg.as_slice());
            assert_eq!("Hello World!", msg);
            //close connection
            conn.close();
        });
        childs.push(child);
    }
    thread::sleep(sec);

    //send hello world
    let mut conn = MsgConn::new(uid.clone(), channel.clone());
    now = Instant::now();
    conn = conn.connect_with_msg(raddr, message.into_bytes());

    for _ in 0..100 {
        let child = childs.remove(0);
        let _res = child.join();
    }

    let endtime = now.elapsed();
    println!("{}.{}", endtime.as_secs(), endtime.subsec_nanos());

    conn.close();

    //drop server
    drop(server);
}

<commit_msg>Fix nano output leading zeroes.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
*  License, v. 2.0. If a copy of the MPL was not distributed with this
*  file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*  Copyright (C) 2017  Juhamatti Kuusisaari / Mles developers
* */
extern crate mles_utils;

use std::thread;
use std::time::{Duration, Instant};
use std::net::SocketAddr;

use mles_utils::*;

fn main() {
    let sec = Duration::new(2,0);
    let addr = "127.0.0.1:8077";
    let addr = addr.parse::<SocketAddr>().unwrap();
    let raddr = addr.clone();
    let uid = "User".to_string();
    let channel = "Channel".to_string();
    let message = "Hello World!".to_string();
    let mut childs = Vec::new();
    let now;

    //create server
    let server = thread::spawn(move || server_run(addr, None, "".to_string(), "".to_string(), 0, 0));
    thread::sleep(sec);

    for _ in 0..100 {
        let uid = uid.clone();
        let channel = channel.clone();
        let child = thread::spawn(move || {
            //read hello world
            let mut conn = MsgConn::new(uid, channel);
            conn = conn.connect(raddr);
            let (conn, msg) = conn.read_message();
            let msg = String::from_utf8_lossy(msg.as_slice());
            assert_eq!("Hello World!", msg);
            //close connection
            conn.close();
        });
        childs.push(child);
    }
    thread::sleep(sec);

    //send hello world
    let mut conn = MsgConn::new(uid.clone(), channel.clone());
    now = Instant::now();
    conn = conn.connect_with_msg(raddr, message.into_bytes());

    for _ in 0..100 {
        let child = childs.remove(0);
        let _res = child.join();
    }

    let endtime = now.elapsed();
    println!("{}.{:09}", endtime.as_secs(), endtime.subsec_nanos());

    conn.close();

    //drop server
    drop(server);
}

<|endoftext|>


<commit_before>// TODO rm allow(unused)
#![allow(unused)]
#![allow(unsafe_code)]

use std::{
    convert::{TryFrom, TryInto},
    fmt::{self, Debug},
    fs::File,
    mem::{transmute, MaybeUninit},
    path::Path,
    sync::{
        atomic::{AtomicU32, Ordering::Acquire},
        Arc,
    },
};

use crossbeam_epoch::pin;

use crate::{
    pagecache::{pread_exact, pwrite_all, MessageKind},
    stack::Stack,
    Error, Lsn, Result,
};

#[cfg(not(feature = "testing"))]
const MIN_SZ: u64 = 64 * 1024;

#[cfg(feature = "testing")]
const MIN_SZ: u64 = 32;

const MIN_TRAILING_ZEROS: u64 = MIN_SZ.trailing_zeros() as u64;

pub type SlabId = u8;
pub type SlabIdx = u32;

/// A unique identifier for a particular slot in the heap
#[allow(clippy::module_name_repetitions)]
#[derive(Clone, Copy, PartialOrd, Ord, Eq, PartialEq, Hash)]
pub struct HeapId {
    pub location: u64,
    pub original_lsn: Lsn,
}

impl Debug for HeapId {
    fn fmt(
        &self,
        f: &mut fmt::Formatter<'_>,
    ) -> std::result::Result<(), fmt::Error> {
        let (slab, idx, original_lsn) = self.decompose();
        f.debug_struct("HeapId")
            .field("slab", &slab)
            .field("idx", &idx)
            .field("original_lsn", &original_lsn)
            .finish()
    }
}

impl HeapId {
    pub fn decompose(&self) -> (SlabId, SlabIdx, Lsn) {
        const IDX_MASK: u64 = (1 << 32) - 1;
        let slab_id =
            u8::try_from((self.location >> 32).trailing_zeros()).unwrap();
        let slab_idx = u32::try_from(self.location & IDX_MASK).unwrap();
        (slab_id, slab_idx, self.original_lsn)
    }

    pub fn compose(
        slab_id: SlabId,
        slab_idx: SlabIdx,
        original_lsn: Lsn,
    ) -> HeapId {
        let slab = 1 << (32 + u64::from(slab_id));
        let heap_id = slab | u64::from(slab_idx);
        HeapId { location: heap_id, original_lsn }
    }

    fn offset(&self) -> u64 {
        let (slab_id, idx, _) = self.decompose();
        slab_id_to_size(slab_id) * u64::from(idx)
    }

    fn slab_size(&self) -> u64 {
        let (slab_id, idx, _) = self.decompose();
        slab_id_to_size(slab_id)
    }
}

pub(crate) fn slab_size(size: u64) -> u64 {
    slab_id_to_size(size_to_slab_id(size))
}

fn slab_id_to_size(slab_id: u8) -> u64 {
    1 << (MIN_TRAILING_ZEROS + u64::from(slab_id))
}

fn size_to_slab_id(size: u64) -> SlabId {
    // find the power of 2 that is at least 64k
    let normalized_size = std::cmp::max(MIN_SZ, size.next_power_of_two());

    // drop the lowest unused bits
    let rebased_size = normalized_size >> MIN_TRAILING_ZEROS;

    u8::try_from(rebased_size.trailing_zeros()).unwrap()
}

pub(crate) struct Reservation {
    slab_free: Arc<Stack<u32>>,
    completed: bool,
    file: File,
    pub heap_id: HeapId,
}

impl Drop for Reservation {
    fn drop(&mut self) {
        if !self.completed {
            let (slab_id, idx, _) = self.heap_id.decompose();
            self.slab_free.push(idx, &pin());
        }
    }
}

impl Reservation {
    pub fn complete(mut self, data: &[u8]) -> Result<HeapId> {
        log::trace!(
            "Heap::complete({:?}) to offset {} in file {:?}",
            self.heap_id,
            self.heap_id.offset(),
            self.file
        );
        assert_eq!(data.len() as u64, self.heap_id.slab_size());

        // write data
        pwrite_all(&self.file, data, self.heap_id.offset())?;

        // sync data
        #[cfg(target_os = "linux")]
        {
            use std::os::unix::io::AsRawFd;
            let ret = unsafe {
                libc::sync_file_range(
                    self.file.as_raw_fd(),
                    i64::try_from(self.heap_id.offset()).unwrap(),
                    i64::try_from(data.len()).unwrap(),
                    libc::SYNC_FILE_RANGE_WAIT_BEFORE
                        | libc::SYNC_FILE_RANGE_WRITE
                        | libc::SYNC_FILE_RANGE_WAIT_AFTER,
                )
            };
            if ret < 0 {
                let err = std::io::Error::last_os_error();
                if let Some(libc::ENOSYS) = err.raw_os_error() {
                    self.file.sync_all()?;
                } else {
                    return Err(err.into());
                }
            }
        }

        #[cfg(not(target_os = "linux"))]
        self.file.sync_all()?;

        // if this is not reached due to an IO error,
        // the offset will be returned to the Slab in Drop
        self.completed = true;

        Ok(self.heap_id)
    }

    pub fn abort(self) {
        // actual logic in Drop
    }
}

#[derive(Debug)]
pub(crate) struct Heap {
    // each slab stores
    // items that are double
    // the size of the previous,
    // ranging from 64k in the
    // smallest slab to 2^48 in
    // the last.
    slabs: [Slab; 32],
}

impl Heap {
    pub fn start<P: AsRef<Path>>(p: P) -> Result<Heap> {
        let mut slabs: [MaybeUninit<Slab>; 32] = unsafe { std::mem::zeroed() };

        for slab_id in 0..32 {
            let slab = Slab::start(&p, slab_id)?;
            slabs[slab_id as usize] = MaybeUninit::new(slab);
        }

        Ok(Heap { slabs: unsafe { transmute(slabs) } })
    }

    pub fn gc_unknown_items(
        &self,
        _snapshot: &crate::pagecache::Snapshot,
    ) -> Result<()> {
        //TODO todo!()
        Ok(())
    }

    pub fn read(
        &self,
        heap_id: HeapId,
        use_compression: bool,
    ) -> Result<(MessageKind, Vec<u8>)> {
        log::trace!("Heap::read({:?})", heap_id);
        let (slab_id, slab_idx, original_lsn) = heap_id.decompose();
        self.slabs[slab_id as usize].read(
            slab_idx,
            original_lsn,
            use_compression,
        )
    }

    pub fn free(&self, heap_id: HeapId) {
        log::trace!("Heap::free({:?})", heap_id);
        let (slab_id, slab_idx, _) = heap_id.decompose();
        self.slabs[slab_id as usize].free(slab_idx)
    }

    pub fn reserve(&self, size: u64, original_lsn: Lsn) -> Reservation {
        assert!(size < 1 << 48);
        let slab_id = size_to_slab_id(size);
        let ret = self.slabs[slab_id as usize].reserve(size, original_lsn);
        log::trace!("Heap::reserve({}) -> {:?}", size, ret.heap_id);
        ret
    }
}

#[derive(Debug)]
struct Slab {
    file: File,
    slab_id: u8,
    tip: AtomicU32,
    free: Arc<Stack<u32>>,
}

impl Slab {
    pub fn start<P: AsRef<Path>>(directory: P, slab_id: u8) -> Result<Slab> {
        let bs = slab_id_to_size(slab_id);
        let free = Arc::new(Stack::default());

        let mut options = std::fs::OpenOptions::new();
        options.create(true);
        options.read(true);
        options.write(true);

        let file =
            options.open(directory.as_ref().join(format!("{:02}", slab_id)))?;
        let len = file.metadata()?.len();
        let max_idx = len / bs;
        log::trace!(
            "starting heap slab for sizes of {}. tip: {} max idx: {}",
            bs,
            len,
            max_idx
        );
        let tip = AtomicU32::new(u32::try_from(max_idx).unwrap());

        Ok(Slab { file, slab_id, tip, free })
    }

    fn read(
        &self,
        slab_idx: SlabIdx,
        original_lsn: Lsn,
        use_compression: bool,
    ) -> Result<(MessageKind, Vec<u8>)> {
        let bs = slab_id_to_size(self.slab_id);
        let offset = u64::from(slab_idx) * bs;

        log::trace!("reading heap slab slot {} at offset {}", slab_idx, offset);

        let mut heap_buf = vec![0; usize::try_from(bs).unwrap()];

        pread_exact(&self.file, &mut heap_buf, offset)?;

        let stored_crc =
            u32::from_le_bytes(heap_buf[1..5].as_ref().try_into().unwrap());

        let mut hasher = crc32fast::Hasher::new();
        hasher.update(&heap_buf[0..1]);
        hasher.update(&heap_buf[5..]);
        let actual_crc = hasher.finalize();

        if actual_crc == stored_crc {
            let actual_lsn = Lsn::from_le_bytes(
                heap_buf[5..13].as_ref().try_into().unwrap(),
            );
            if actual_lsn != original_lsn {
                log::error!(
                    "heap slot lsn {} does not match expected original lsn {}",
                    actual_lsn,
                    original_lsn
                );
                return Err(Error::corruption(None));
            }
            let buf = heap_buf[13..].to_vec();
            let buf = if use_compression {
                crate::pagecache::decompress(buf)
            } else {
                buf
            };
            Ok((MessageKind::from(heap_buf[0]), buf))
        } else {
            log::error!(
                "heap message CRC does not match contents. stored: {} actual: {}",
                stored_crc,
                actual_crc
            );
            Err(Error::corruption(None))
        }
    }

    fn reserve(&self, size: u64, original_lsn: Lsn) -> Reservation {
        let idx = if let Some(idx) = self.free.pop(&pin()) {
            log::trace!(
                "reusing heap index {} in slab for sizes of {}",
                idx,
                slab_id_to_size(self.slab_id),
            );
            idx
        } else {
            log::trace!(
                "no free heap slots in slab for sizes of {}",
                slab_id_to_size(self.slab_id),
            );
            self.tip.fetch_add(1, Acquire)
        };

        log::trace!(
            "heap reservation for slot {} in the slab for sizes of {}",
            idx,
            slab_id_to_size(self.slab_id),
        );

        let heap_id = HeapId::compose(self.slab_id, idx, original_lsn);

        Reservation {
            slab_free: self.free.clone(),
            completed: false,
            file: self.file.try_clone().unwrap(),
            heap_id,
        }
    }

    fn free(&self, idx: u32) {
        self.punch_hole(idx);
        self.free.push(idx, &pin());
    }

    fn punch_hole(&self, idx: u32) {
        #[cfg(target_os = "linux")]
        {
            use std::{
                os::unix::io::AsRawFd,
                sync::atomic::{AtomicBool, Ordering::Relaxed},
            };

            use libc::{fallocate, FALLOC_FL_KEEP_SIZE, FALLOC_FL_PUNCH_HOLE};

            static HOLE_PUNCHING_ENABLED: AtomicBool = AtomicBool::new(true);
            const MODE: i32 = FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE;

            if HOLE_PUNCHING_ENABLED.load(Relaxed) {
                let bs = i64::try_from(slab_id_to_size(self.slab_id)).unwrap();
                let offset = i64::from(idx) * bs;

                let fd = self.file.as_raw_fd();

                let ret = unsafe {
                    fallocate(
                        fd,
                        MODE,
                        offset.try_into().unwrap(),
                        bs.try_into().unwrap(),
                    )
                };

                if ret != 0 {
                    let err = std::io::Error::last_os_error();
                    log::error!(
                        "failed to punch hole in heap file: {:?}. disabling hole punching",
                        err
                    );
                    HOLE_PUNCHING_ENABLED.store(false, Relaxed);
                }
            }
        }
    }
}
<commit_msg>Clippy feedback<commit_after>// TODO rm allow(unused)
#![allow(unused)]
#![allow(unsafe_code)]

use std::{
    convert::{TryFrom, TryInto},
    fmt::{self, Debug},
    fs::File,
    mem::{transmute, MaybeUninit},
    path::Path,
    sync::{
        atomic::{AtomicU32, Ordering::Acquire},
        Arc,
    },
};

use crossbeam_epoch::pin;

use crate::{
    pagecache::{pread_exact, pwrite_all, MessageKind},
    stack::Stack,
    Error, Lsn, Result,
};

#[cfg(not(feature = "testing"))]
const MIN_SZ: u64 = 64 * 1024;

#[cfg(feature = "testing")]
const MIN_SZ: u64 = 32;

const MIN_TRAILING_ZEROS: u64 = MIN_SZ.trailing_zeros() as u64;

pub type SlabId = u8;
pub type SlabIdx = u32;

/// A unique identifier for a particular slot in the heap
#[allow(clippy::module_name_repetitions)]
#[derive(Clone, Copy, PartialOrd, Ord, Eq, PartialEq, Hash)]
pub struct HeapId {
    pub location: u64,
    pub original_lsn: Lsn,
}

impl Debug for HeapId {
    fn fmt(
        &self,
        f: &mut fmt::Formatter<'_>,
    ) -> std::result::Result<(), fmt::Error> {
        let (slab, idx, original_lsn) = self.decompose();
        f.debug_struct("HeapId")
            .field("slab", &slab)
            .field("idx", &idx)
            .field("original_lsn", &original_lsn)
            .finish()
    }
}

impl HeapId {
    pub fn decompose(&self) -> (SlabId, SlabIdx, Lsn) {
        const IDX_MASK: u64 = (1 << 32) - 1;
        let slab_id =
            u8::try_from((self.location >> 32).trailing_zeros()).unwrap();
        let slab_idx = u32::try_from(self.location & IDX_MASK).unwrap();
        (slab_id, slab_idx, self.original_lsn)
    }

    pub fn compose(
        slab_id: SlabId,
        slab_idx: SlabIdx,
        original_lsn: Lsn,
    ) -> HeapId {
        let slab = 1 << (32 + u64::from(slab_id));
        let heap_id = slab | u64::from(slab_idx);
        HeapId { location: heap_id, original_lsn }
    }

    fn offset(&self) -> u64 {
        let (slab_id, idx, _) = self.decompose();
        slab_id_to_size(slab_id) * u64::from(idx)
    }

    fn slab_size(&self) -> u64 {
        let (slab_id, idx, _) = self.decompose();
        slab_id_to_size(slab_id)
    }
}

pub(crate) fn slab_size(size: u64) -> u64 {
    slab_id_to_size(size_to_slab_id(size))
}

fn slab_id_to_size(slab_id: u8) -> u64 {
    1 << (MIN_TRAILING_ZEROS + u64::from(slab_id))
}

fn size_to_slab_id(size: u64) -> SlabId {
    // find the power of 2 that is at least 64k
    let normalized_size = std::cmp::max(MIN_SZ, size.next_power_of_two());

    // drop the lowest unused bits
    let rebased_size = normalized_size >> MIN_TRAILING_ZEROS;

    u8::try_from(rebased_size.trailing_zeros()).unwrap()
}

pub(crate) struct Reservation {
    slab_free: Arc<Stack<u32>>,
    completed: bool,
    file: File,
    pub heap_id: HeapId,
}

impl Drop for Reservation {
    fn drop(&mut self) {
        if !self.completed {
            let (slab_id, idx, _) = self.heap_id.decompose();
            self.slab_free.push(idx, &pin());
        }
    }
}

impl Reservation {
    pub fn complete(mut self, data: &[u8]) -> Result<HeapId> {
        log::trace!(
            "Heap::complete({:?}) to offset {} in file {:?}",
            self.heap_id,
            self.heap_id.offset(),
            self.file
        );
        assert_eq!(data.len() as u64, self.heap_id.slab_size());

        // write data
        pwrite_all(&self.file, data, self.heap_id.offset())?;

        // sync data
        #[cfg(target_os = "linux")]
        {
            use std::os::unix::io::AsRawFd;
            let ret = unsafe {
                libc::sync_file_range(
                    self.file.as_raw_fd(),
                    i64::try_from(self.heap_id.offset()).unwrap(),
                    i64::try_from(data.len()).unwrap(),
                    libc::SYNC_FILE_RANGE_WAIT_BEFORE
                        | libc::SYNC_FILE_RANGE_WRITE
                        | libc::SYNC_FILE_RANGE_WAIT_AFTER,
                )
            };
            if ret < 0 {
                let err = std::io::Error::last_os_error();
                if let Some(libc::ENOSYS) = err.raw_os_error() {
                    self.file.sync_all()?;
                } else {
                    return Err(err.into());
                }
            }
        }

        #[cfg(not(target_os = "linux"))]
        self.file.sync_all()?;

        // if this is not reached due to an IO error,
        // the offset will be returned to the Slab in Drop
        self.completed = true;

        Ok(self.heap_id)
    }

    pub fn abort(self) {
        // actual logic in Drop
    }
}

#[derive(Debug)]
pub(crate) struct Heap {
    // each slab stores
    // items that are double
    // the size of the previous,
    // ranging from 64k in the
    // smallest slab to 2^48 in
    // the last.
    slabs: [Slab; 32],
}

impl Heap {
    pub fn start<P: AsRef<Path>>(p: P) -> Result<Heap> {
        let mut slabs: [MaybeUninit<Slab>; 32] = unsafe { std::mem::zeroed() };

        for slab_id in 0..32 {
            let slab = Slab::start(&p, slab_id)?;
            slabs[slab_id as usize] = MaybeUninit::new(slab);
        }

        Ok(Heap { slabs: unsafe { transmute(slabs) } })
    }

    pub fn gc_unknown_items(
        &self,
        _snapshot: &crate::pagecache::Snapshot,
    ) -> Result<()> {
        //TODO todo!()
        Ok(())
    }

    pub fn read(
        &self,
        heap_id: HeapId,
        use_compression: bool,
    ) -> Result<(MessageKind, Vec<u8>)> {
        log::trace!("Heap::read({:?})", heap_id);
        let (slab_id, slab_idx, original_lsn) = heap_id.decompose();
        self.slabs[slab_id as usize].read(
            slab_idx,
            original_lsn,
            use_compression,
        )
    }

    pub fn free(&self, heap_id: HeapId) {
        log::trace!("Heap::free({:?})", heap_id);
        let (slab_id, slab_idx, _) = heap_id.decompose();
        self.slabs[slab_id as usize].free(slab_idx)
    }

    pub fn reserve(&self, size: u64, original_lsn: Lsn) -> Reservation {
        assert!(size < 1 << 48);
        let slab_id = size_to_slab_id(size);
        let ret = self.slabs[slab_id as usize].reserve(size, original_lsn);
        log::trace!("Heap::reserve({}) -> {:?}", size, ret.heap_id);
        ret
    }
}

#[derive(Debug)]
struct Slab {
    file: File,
    slab_id: u8,
    tip: AtomicU32,
    free: Arc<Stack<u32>>,
}

impl Slab {
    pub fn start<P: AsRef<Path>>(directory: P, slab_id: u8) -> Result<Slab> {
        let bs = slab_id_to_size(slab_id);
        let free = Arc::new(Stack::default());

        let mut options = std::fs::OpenOptions::new();
        options.create(true);
        options.read(true);
        options.write(true);

        let file =
            options.open(directory.as_ref().join(format!("{:02}", slab_id)))?;
        let len = file.metadata()?.len();
        let max_idx = len / bs;
        log::trace!(
            "starting heap slab for sizes of {}. tip: {} max idx: {}",
            bs,
            len,
            max_idx
        );
        let tip = AtomicU32::new(u32::try_from(max_idx).unwrap());

        Ok(Slab { file, slab_id, tip, free })
    }

    fn read(
        &self,
        slab_idx: SlabIdx,
        original_lsn: Lsn,
        use_compression: bool,
    ) -> Result<(MessageKind, Vec<u8>)> {
        let bs = slab_id_to_size(self.slab_id);
        let offset = u64::from(slab_idx) * bs;

        log::trace!("reading heap slab slot {} at offset {}", slab_idx, offset);

        let mut heap_buf = vec![0; usize::try_from(bs).unwrap()];

        pread_exact(&self.file, &mut heap_buf, offset)?;

        let stored_crc =
            u32::from_le_bytes(heap_buf[1..5].as_ref().try_into().unwrap());

        let mut hasher = crc32fast::Hasher::new();
        hasher.update(&heap_buf[0..1]);
        hasher.update(&heap_buf[5..]);
        let actual_crc = hasher.finalize();

        if actual_crc == stored_crc {
            let actual_lsn = Lsn::from_le_bytes(
                heap_buf[5..13].as_ref().try_into().unwrap(),
            );
            if actual_lsn != original_lsn {
                log::error!(
                    "heap slot lsn {} does not match expected original lsn {}",
                    actual_lsn,
                    original_lsn
                );
                return Err(Error::corruption(None));
            }
            let buf = heap_buf[13..].to_vec();
            let buf = if use_compression {
                crate::pagecache::decompress(buf)
            } else {
                buf
            };
            Ok((MessageKind::from(heap_buf[0]), buf))
        } else {
            log::error!(
                "heap message CRC does not match contents. stored: {} actual: {}",
                stored_crc,
                actual_crc
            );
            Err(Error::corruption(None))
        }
    }

    fn reserve(&self, size: u64, original_lsn: Lsn) -> Reservation {
        let idx = if let Some(idx) = self.free.pop(&pin()) {
            log::trace!(
                "reusing heap index {} in slab for sizes of {}",
                idx,
                slab_id_to_size(self.slab_id),
            );
            idx
        } else {
            log::trace!(
                "no free heap slots in slab for sizes of {}",
                slab_id_to_size(self.slab_id),
            );
            self.tip.fetch_add(1, Acquire)
        };

        log::trace!(
            "heap reservation for slot {} in the slab for sizes of {}",
            idx,
            slab_id_to_size(self.slab_id),
        );

        let heap_id = HeapId::compose(self.slab_id, idx, original_lsn);

        Reservation {
            slab_free: self.free.clone(),
            completed: false,
            file: self.file.try_clone().unwrap(),
            heap_id,
        }
    }

    fn free(&self, idx: u32) {
        self.punch_hole(idx);
        self.free.push(idx, &pin());
    }

    fn punch_hole(&self, idx: u32) {
        #[cfg(target_os = "linux")]
        {
            use std::{
                os::unix::io::AsRawFd,
                sync::atomic::{AtomicBool, Ordering::Relaxed},
            };

            use libc::{fallocate, FALLOC_FL_KEEP_SIZE, FALLOC_FL_PUNCH_HOLE};

            static HOLE_PUNCHING_ENABLED: AtomicBool = AtomicBool::new(true);
            const MODE: i32 = FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE;

            if HOLE_PUNCHING_ENABLED.load(Relaxed) {
                let bs = i64::try_from(slab_id_to_size(self.slab_id)).unwrap();
                let offset = i64::from(idx) * bs;

                let fd = self.file.as_raw_fd();

                let ret = unsafe {
                    fallocate(
                        fd,
                        MODE,
                        #[allow(clippy::useless_conversion)]
                        offset.try_into().unwrap(),
                        #[allow(clippy::useless_conversion)]
                        bs.try_into().unwrap(),
                    )
                };

                if ret != 0 {
                    let err = std::io::Error::last_os_error();
                    log::error!(
                        "failed to punch hole in heap file: {:?}. disabling hole punching",
                        err
                    );
                    HOLE_PUNCHING_ENABLED.store(false, Relaxed);
                }
            }
        }
    }
}
<|endoftext|>


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

//! Implementation of the `build` subcommand, used to compile a book.

use std::env;
use std::fs::{self, File};
use std::io::prelude::*;
use std::io::{self, BufWriter};
use std::path::{Path, PathBuf};
use rustc_back::tempdir::TempDir;

use subcommand::Subcommand;
use term::Term;
use error::{err, CliResult, CommandResult};
use book;
use book::{Book, BookItem};

use rustdoc;

struct Build;

pub fn parse_cmd(name: &str) -> Option<Box<Subcommand>> {
    if name == "build" {
        Some(Box::new(Build))
    } else {
        None
    }
}

fn write_toc(book: &Book, current_page: &BookItem, out: &mut Write) -> io::Result<()> {
    fn walk_items(items: &[BookItem],
                  section: &str,
                  current_page: &BookItem,
                  out: &mut Write) -> io::Result<()> {
        for (i, item) in items.iter().enumerate() {
            walk_item(item, &format!("{}{}.", section, i + 1)[..], current_page, out)?;
        }
        Ok(())
    }
    fn walk_item(item: &BookItem,
                 section: &str,
                 current_page: &BookItem,
                 out: &mut Write) -> io::Result<()> {
        let class_string = if item.path == current_page.path {
            "class='active'"
        } else {
            ""
        };

        writeln!(out, "
{} {}",
                 class_string,
                 current_page.path_to_root.join(&item.path).with_extension("html").display(),
                 section,
                 item.title)?;
        if !item.children.is_empty() {
            writeln!(out, "
")?;
            let _ = walk_items(&item.children[..], section, current_page, out);
            writeln!(out, "
")?;
        }
        writeln!(out, "
")?;

        Ok(())
    }

    writeln!(out, "
")?;
    writeln!(out, "
")?;
    walk_items(&book.chapters[..], "", &current_page, out)?;
    writeln!(out, "
")?;
    writeln!(out, "
")?;

    Ok(())
}

fn render(book: &Book, tgt: &Path) -> CliResult<()> {
    let tmp = TempDir::new("rustbook")?;

    for (_section, item) in book.iter() {
        let out_path = match item.path.parent() {
            Some(p) => tgt.join(p),
            None => tgt.to_path_buf(),
        };

        let src;
        if env::args().len() < 3 {
            src = env::current_dir().unwrap().clone();
        } else {
            src = PathBuf::from(&env::args().nth(2).unwrap());
        }
        // preprocess the markdown, rerouting markdown references to html
        // references
        let mut markdown_data = String::new();
        File::open(&src.join(&item.path)).and_then(|mut f| {
            f.read_to_string(&mut markdown_data)
        })?;
        let preprocessed_path = tmp.path().join(item.path.file_name().unwrap());
        {
            let urls = markdown_data.replace(".md)", ".html)");
            File::create(&preprocessed_path).and_then(|mut f| {
                f.write_all(urls.as_bytes())
            })?;
        }

        // write the prelude to a temporary HTML file for rustdoc inclusion
        let prelude = tmp.path().join("prelude.html");
        {
            let mut buffer = BufWriter::new(File::create(&prelude)?);
            writeln!(&mut buffer, r#"

                    <button id="toggle-nav">
                        Toggle navigation

                    </button>

"#)?;
            let _ = write_toc(book, &item, &mut buffer);
            writeln!(&mut buffer, "
")?;
            writeln!(&mut buffer, "
")?;
        }

        // write the postlude to a temporary HTML file for rustdoc inclusion
        let postlude = tmp.path().join("postlude.html");
        {
            let mut buffer = BufWriter::new(File::create(&postlude)?);
            writeln!(&mut buffer, "")?;
            writeln!(&mut buffer, "")?;
            writeln!(&mut buffer, "

")?;
        }

        fs::create_dir_all(&out_path)?;

        let rustdoc_args: &[String] = &[
            "".to_string(),
            preprocessed_path.display().to_string(),
            format!("-o{}", out_path.display()),
            format!("--html-before-content={}", prelude.display()),
            format!("--html-after-content={}", postlude.display()),
            format!("--markdown-playground-url=https://play.rust-lang.org"),
            format!("--markdown-css={}", item.path_to_root.join("rustbook.css").display()),
            "--markdown-no-toc".to_string(),
        ];
        let output_result = rustdoc::main_args(rustdoc_args);
        if output_result != 0 {
            let message = format!("Could not execute `rustdoc` with {:?}: {}",
                                  rustdoc_args, output_result);
            return Err(err(&message));
        }
    }

    // create index.html from the root README
    fs::copy(&tgt.join("README.html"), &tgt.join("index.html"))?;

    // Copy js for playpen
    let mut playpen = File::create(tgt.join("playpen.js"))?;
    let js = include_bytes!("../../librustdoc/html/static/playpen.js");
    playpen.write_all(js)?;
    Ok(())
}

impl Subcommand for Build {
    fn parse_args(&mut self, _: &[String]) -> CliResult<()> {
        Ok(())
    }
    fn usage(&self) {}
    fn execute(&mut self, term: &mut Term) -> CommandResult<()> {
        let cwd = env::current_dir().unwrap();
        let src;
        let tgt;

        if env::args().len() < 3 {
            src = cwd.clone();
        } else {
            src = PathBuf::from(&env::args().nth(2).unwrap());
        }

        if env::args().len() < 4 {
            tgt = cwd.join("_book");
        } else {
            tgt = PathBuf::from(&env::args().nth(3).unwrap());
        }

        // `_book` directory may already exist from previous runs. Check and
        // delete it if it exists.
        for entry in fs::read_dir(&cwd)? {
            let path = entry?.path();
            if path == tgt { fs::remove_dir_all(&tgt)? }
        }
        fs::create_dir(&tgt)?;

        // Copy static files
        let css = include_bytes!("static/rustbook.css");
        let js = include_bytes!("static/rustbook.js");

        let mut css_file = File::create(tgt.join("rustbook.css"))?;
        css_file.write_all(css)?;

        let mut js_file = File::create(tgt.join("rustbook.js"))?;
        js_file.write_all(js)?;

        let mut summary = File::open(&src.join("SUMMARY.md"))?;
        match book::parse_summary(&mut summary, &src) {
            Ok(book) => {
                // execute rustdoc on the whole book
                render(&book, &tgt)
            }
            Err(errors) => {
                let n = errors.len();
                for err in errors {
                    term.err(&format!("error: {}", err)[..]);
                }

                Err(err(&format!("{} errors occurred", n)))
            }
        }
    }
}
<commit_msg>rustbook chapters/sections should be an ordered list.<commit_after>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementation of the `build` subcommand, used to compile a book.

use std::env;
use std::fs::{self, File};
use std::io::prelude::*;
use std::io::{self, BufWriter};
use std::path::{Path, PathBuf};
use rustc_back::tempdir::TempDir;

use subcommand::Subcommand;
use term::Term;
use error::{err, CliResult, CommandResult};
use book;
use book::{Book, BookItem};

use rustdoc;

struct Build;

pub fn parse_cmd(name: &str) -> Option<Box<Subcommand>> {
    if name == "build" {
        Some(Box::new(Build))
    } else {
        None
    }
}

fn write_toc(book: &Book, current_page: &BookItem, out: &mut Write) -> io::Result<()> {
    fn walk_items(items: &[BookItem],
                  section: &str,
                  current_page: &BookItem,
                  out: &mut Write) -> io::Result<()> {
        for (i, item) in items.iter().enumerate() {
            walk_item(item, &format!("{}{}.", section, i + 1)[..], current_page, out)?;
        }
        Ok(())
    }
    fn walk_item(item: &BookItem,
                 section: &str,
                 current_page: &BookItem,
                 out: &mut Write) -> io::Result<()> {
        let class_string = if item.path == current_page.path {
            "class='active'"
        } else {
            ""
        };

        writeln!(out, "
{} {}",
                 class_string,
                 current_page.path_to_root.join(&item.path).with_extension("html").display(),
                 section,
                 item.title)?;
        if !item.children.is_empty() {
            writeln!(out, "
")?;
            let _ = walk_items(&item.children[..], section, current_page, out);
            writeln!(out, "
")?;
        }
        writeln!(out, "
")?;

        Ok(())
    }

    writeln!(out, "
")?;
    writeln!(out, "
")?;
    walk_items(&book.chapters[..], "", &current_page, out)?;
    writeln!(out, "
")?;
    writeln!(out, "
")?;

    Ok(())
}

fn render(book: &Book, tgt: &Path) -> CliResult<()> {
    let tmp = TempDir::new("rustbook")?;

    for (_section, item) in book.iter() {
        let out_path = match item.path.parent() {
            Some(p) => tgt.join(p),
            None => tgt.to_path_buf(),
        };

        let src;
        if env::args().len() < 3 {
            src = env::current_dir().unwrap().clone();
        } else {
            src = PathBuf::from(&env::args().nth(2).unwrap());
        }
        // preprocess the markdown, rerouting markdown references to html
        // references
        let mut markdown_data = String::new();
        File::open(&src.join(&item.path)).and_then(|mut f| {
            f.read_to_string(&mut markdown_data)
        })?;
        let preprocessed_path = tmp.path().join(item.path.file_name().unwrap());
        {
            let urls = markdown_data.replace(".md)", ".html)");
            File::create(&preprocessed_path).and_then(|mut f| {
                f.write_all(urls.as_bytes())
            })?;
        }

        // write the prelude to a temporary HTML file for rustdoc inclusion
        let prelude = tmp.path().join("prelude.html");
        {
            let mut buffer = BufWriter::new(File::create(&prelude)?);
            writeln!(&mut buffer, r#"

                    <button id="toggle-nav">
                        Toggle navigation

                    </button>

"#)?;
            let _ = write_toc(book, &item, &mut buffer);
            writeln!(&mut buffer, "
")?;
            writeln!(&mut buffer, "
")?;
        }

        // write the postlude to a temporary HTML file for rustdoc inclusion
        let postlude = tmp.path().join("postlude.html");
        {
            let mut buffer = BufWriter::new(File::create(&postlude)?);
            writeln!(&mut buffer, "")?;
            writeln!(&mut buffer, "")?;
            writeln!(&mut buffer, "

")?;
        }

        fs::create_dir_all(&out_path)?;

        let rustdoc_args: &[String] = &[
            "".to_string(),
            preprocessed_path.display().to_string(),
            format!("-o{}", out_path.display()),
            format!("--html-before-content={}", prelude.display()),
            format!("--html-after-content={}", postlude.display()),
            format!("--markdown-playground-url=https://play.rust-lang.org"),
            format!("--markdown-css={}", item.path_to_root.join("rustbook.css").display()),
            "--markdown-no-toc".to_string(),
        ];
        let output_result = rustdoc::main_args(rustdoc_args);
        if output_result != 0 {
            let message = format!("Could not execute `rustdoc` with {:?}: {}",
                                  rustdoc_args, output_result);
            return Err(err(&message));
        }
    }

    // create index.html from the root README
    fs::copy(&tgt.join("README.html"), &tgt.join("index.html"))?;

    // Copy js for playpen
    let mut playpen = File::create(tgt.join("playpen.js"))?;
    let js = include_bytes!("../../librustdoc/html/static/playpen.js");
    playpen.write_all(js)?;
    Ok(())
}

impl Subcommand for Build {
    fn parse_args(&mut self, _: &[String]) -> CliResult<()> {
        Ok(())
    }
    fn usage(&self) {}
    fn execute(&mut self, term: &mut Term) -> CommandResult<()> {
        let cwd = env::current_dir().unwrap();
        let src;
        let tgt;

        if env::args().len() < 3 {
            src = cwd.clone();
        } else {
            src = PathBuf::from(&env::args().nth(2).unwrap());
        }

        if env::args().len() < 4 {
            tgt = cwd.join("_book");
        } else {
            tgt = PathBuf::from(&env::args().nth(3).unwrap());
        }

        // `_book` directory may already exist from previous runs. Check and
        // delete it if it exists.
        for entry in fs::read_dir(&cwd)? {
            let path = entry?.path();
            if path == tgt { fs::remove_dir_all(&tgt)? }
        }
        fs::create_dir(&tgt)?;

        // Copy static files
        let css = include_bytes!("static/rustbook.css");
        let js = include_bytes!("static/rustbook.js");

        let mut css_file = File::create(tgt.join("rustbook.css"))?;
        css_file.write_all(css)?;

        let mut js_file = File::create(tgt.join("rustbook.js"))?;
        js_file.write_all(js)?;

        let mut summary = File::open(&src.join("SUMMARY.md"))?;
        match book::parse_summary(&mut summary, &src) {
            Ok(book) => {
                // execute rustdoc on the whole book
                render(&book, &tgt)
            }
            Err(errors) => {
                let n = errors.len();
                for err in errors {
                    term.err(&format!("error: {}", err)[..]);
                }

                Err(err(&format!("{} errors occurred", n)))
            }
        }
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use euclid::Point3D;
use geometry::ray_intersects_rect;
use spring::{DAMPING, STIFFNESS, Spring};
use webrender_traits::{LayerPoint, LayerRect, LayerSize, LayerToScrollTransform};
use webrender_traits::{LayerToWorldTransform, PipelineId, ScrollEventPhase, ScrollLayerId};
use webrender_traits::{ScrollLayerRect, ScrollLocation, ScrollToWorldTransform, WorldPoint};
use webrender_traits::{WorldPoint4D};

#[cfg(target_os = "macos")]
const CAN_OVERSCROLL: bool = true;

#[cfg(not(target_os = "macos"))]
const CAN_OVERSCROLL: bool = false;

/// Contains scrolling and transform information stacking contexts.
#[derive(Clone)]
pub struct Layer {
    /// Manages scrolling offset, overscroll state etc.
    pub scrolling: ScrollingState,

    /// Size of the content inside the scroll region (in logical pixels)
    pub content_size: LayerSize,

    /// Viewing rectangle
    pub local_viewport_rect: LayerRect,

    /// Viewing rectangle clipped against parent layer(s)
    pub combined_local_viewport_rect: LayerRect,

    /// World transform for the viewport rect itself.
    pub world_viewport_transform: LayerToWorldTransform,

    /// World transform for content within this layer
    pub world_content_transform: LayerToWorldTransform,

    /// Transform for this layer, relative to parent scrollable layer.
    pub local_transform: LayerToScrollTransform,

    /// Pipeline that this layer belongs to
    pub pipeline_id: PipelineId,

    /// Child layers
    pub children: Vec<ScrollLayerId>,
}

impl Layer {
    pub fn new(local_viewport_rect: &LayerRect,
               content_size: LayerSize,
               local_transform: &LayerToScrollTransform,
               pipeline_id: PipelineId)
               -> Layer {
        Layer {
            scrolling: ScrollingState::new(),
            content_size: content_size,
            local_viewport_rect: *local_viewport_rect,
            combined_local_viewport_rect: *local_viewport_rect,
            world_viewport_transform: LayerToWorldTransform::identity(),
            world_content_transform: LayerToWorldTransform::identity(),
            local_transform: *local_transform,
            children: Vec::new(),
            pipeline_id: pipeline_id,
        }
    }

    pub fn add_child(&mut self, child: ScrollLayerId) {
        self.children.push(child);
    }

    pub fn finalize(&mut self, scrolling: &ScrollingState) {
        self.scrolling = *scrolling;
    }

    pub fn overscroll_amount(&self) -> LayerSize {
        let scrollable_width = self.scrollable_width();
        let overscroll_x = if self.scrolling.offset.x > 0.0 {
            -self.scrolling.offset.x
        } else if self.scrolling.offset.x < -scrollable_width {
            -scrollable_width - self.scrolling.offset.x
        } else {
            0.0
        };

        let scrollable_height = self.scrollable_height();
        let overscroll_y = if self.scrolling.offset.y > 0.0 {
            -self.scrolling.offset.y
        } else if self.scrolling.offset.y < -scrollable_height {
            -scrollable_height - self.scrolling.offset.y
        } else {
            0.0
        };

        LayerSize::new(overscroll_x, overscroll_y)
    }

    pub fn set_scroll_origin(&mut self, origin: &LayerPoint) -> bool {
        let scrollable_height = self.scrollable_height();
        let scrollable_width = self.scrollable_width();
        if scrollable_height <= 0. && scrollable_width <= 0. {
            return false;
        }

        let new_offset = LayerPoint::new((-origin.x).max(-scrollable_width).min(0.0).round(),
                                         (-origin.y).max(-scrollable_height).min(0.0).round());
        if new_offset == self.scrolling.offset {
            return false;
        }

        self.scrolling.offset = new_offset;
        self.scrolling.bouncing_back = false;
        self.scrolling.started_bouncing_back = false;
        return true;
    }

    pub fn update_transform(&mut self,
                            parent_world_transform: &ScrollToWorldTransform,
                            parent_viewport_rect: &ScrollLayerRect) {
        let inv_transform = self.local_transform.inverse().unwrap();
        let parent_viewport_rect_in_local_space = inv_transform.transform_rect(parent_viewport_rect)
                                                               .translate(&-self.scrolling.offset);
        let local_viewport_rect = self.local_viewport_rect.translate(&-self.scrolling.offset);
        let viewport_rect = parent_viewport_rect_in_local_space.intersection(&local_viewport_rect)
                                                               .unwrap_or(LayerRect::zero());

        self.combined_local_viewport_rect = viewport_rect;
        self.world_viewport_transform = parent_world_transform.pre_mul(&self.local_transform);
        self.world_content_transform = self.world_viewport_transform
                                                     .pre_translated(self.scrolling.offset.x,
                                                                     self.scrolling.offset.y,
                                                                     0.0);
    }

    pub fn scrollable_height(&self) -> f32 {
        self.content_size.height - self.local_viewport_rect.size.height
    }

    pub fn scrollable_width(&self) -> f32 {
        self.content_size.width - self.local_viewport_rect.size.width
    }

    pub fn scroll(&mut self, scroll_location: ScrollLocation, phase: ScrollEventPhase) -> bool {
        if self.scrolling.started_bouncing_back && phase == ScrollEventPhase::Move(false) {
            return false;
        }

        let mut delta = match scroll_location {
            ScrollLocation::Delta(delta) => delta,
            ScrollLocation::Start => {
                if self.scrolling.offset.y.round() >= 0.0 {
                    // Nothing to do on this layer.
                    return false;
                }

                self.scrolling.offset.y = 0.0;
                return true;
            },
            ScrollLocation::End => {
                let end_pos = self.local_viewport_rect.size.height - self.content_size.height;

                if self.scrolling.offset.y.round() <= end_pos {
                    // Nothing to do on this layer.
                    return false;
                }

                self.scrolling.offset.y = end_pos;
                return true;
            }
        };

        let overscroll_amount = self.overscroll_amount();
        let overscrolling = CAN_OVERSCROLL && (overscroll_amount.width != 0.0 ||
                                               overscroll_amount.height != 0.0);
        if overscrolling {
            if overscroll_amount.width != 0.0 {
                delta.x /= overscroll_amount.width.abs()
            }
            if overscroll_amount.height != 0.0 {
                delta.y /= overscroll_amount.height.abs()
            }
        }

        let scrollable_width = self.scrollable_width();
        let scrollable_height = self.scrollable_height();
        let is_unscrollable = scrollable_width <= 0. && scrollable_height <= 0.;
        let original_layer_scroll_offset = self.scrolling.offset;

        if scrollable_width > 0. {
            self.scrolling.offset.x = self.scrolling.offset.x + delta.x;
            if is_unscrollable || !CAN_OVERSCROLL {
                self.scrolling.offset.x =
                    self.scrolling.offset.x.min(0.0).max(-scrollable_width).round();
            }
        }

        if scrollable_height > 0. {
            self.scrolling.offset.y = self.scrolling.offset.y + delta.y;
            if is_unscrollable || !CAN_OVERSCROLL {
                self.scrolling.offset.y =
                    self.scrolling.offset.y.min(0.0).max(-scrollable_height).round();
            }
        }

        if phase == ScrollEventPhase::Start || phase == ScrollEventPhase::Move(true) {
            self.scrolling.started_bouncing_back = false
        } else if overscrolling &&
                ((delta.x < 1.0 && delta.y < 1.0) || phase == ScrollEventPhase::End) {
            self.scrolling.started_bouncing_back = true;
            self.scrolling.bouncing_back = true
        }

        if CAN_OVERSCROLL {
            self.stretch_overscroll_spring();
        }

        self.scrolling.offset != original_layer_scroll_offset ||
            self.scrolling.started_bouncing_back
    }

    pub fn stretch_overscroll_spring(&mut self) {
        let overscroll_amount = self.overscroll_amount();
        self.scrolling.spring.coords(self.scrolling.offset,
                                     self.scrolling.offset,
                                     self.scrolling.offset + overscroll_amount);
    }

    pub fn tick_scrolling_bounce_animation(&mut self) {
        let finished = self.scrolling.spring.animate();
        self.scrolling.offset = self.scrolling.spring.current();
        if finished {
            self.scrolling.bouncing_back = false
        }
    }

    pub fn ray_intersects_layer(&self, cursor: &WorldPoint) -> bool {
        let inv = self.world_viewport_transform.inverse().unwrap();
        let z0 = -10000.0;
        let z1 =  10000.0;

        let p0 = inv.transform_point4d(&WorldPoint4D::new(cursor.x, cursor.y, z0, 1.0));
        let p0 = Point3D::new(p0.x / p0.w,
                              p0.y / p0.w,
                              p0.z / p0.w);
        let p1 = inv.transform_point4d(&WorldPoint4D::new(cursor.x, cursor.y, z1, 1.0));
        let p1 = Point3D::new(p1.x / p1.w,
                              p1.y / p1.w,
                              p1.z / p1.w);

        if self.scrollable_width() <= 0. && self.scrollable_height() <= 0. {
            return false;
        }
        ray_intersects_rect(p0, p1, self.local_viewport_rect.to_untyped())
    }
}

#[derive(Copy, Clone)]
pub struct ScrollingState {
    pub offset: LayerPoint,
    pub spring: Spring,
    pub started_bouncing_back: bool,
    pub bouncing_back: bool,
    pub should_handoff_scroll: bool
}

impl ScrollingState {
    pub fn new() -> ScrollingState {
        ScrollingState {
            offset: LayerPoint::zero(),
            spring: Spring::at(LayerPoint::zero(), STIFFNESS, DAMPING),
            started_bouncing_back: false,
            bouncing_back: false,
            should_handoff_scroll: false
        }
    }
}

<commit_msg>Fix the panic when transform is non-invertible<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use euclid::Point3D;
use geometry::ray_intersects_rect;
use spring::{DAMPING, STIFFNESS, Spring};
use webrender_traits::{LayerPoint, LayerRect, LayerSize, LayerToScrollTransform};
use webrender_traits::{LayerToWorldTransform, PipelineId, ScrollEventPhase, ScrollLayerId};
use webrender_traits::{ScrollLayerRect, ScrollLocation, ScrollToWorldTransform, WorldPoint};
use webrender_traits::{WorldPoint4D};

#[cfg(target_os = "macos")]
const CAN_OVERSCROLL: bool = true;

#[cfg(not(target_os = "macos"))]
const CAN_OVERSCROLL: bool = false;

/// Contains scrolling and transform information stacking contexts.
#[derive(Clone)]
pub struct Layer {
    /// Manages scrolling offset, overscroll state etc.
    pub scrolling: ScrollingState,

    /// Size of the content inside the scroll region (in logical pixels)
    pub content_size: LayerSize,

    /// Viewing rectangle
    pub local_viewport_rect: LayerRect,

    /// Viewing rectangle clipped against parent layer(s)
    pub combined_local_viewport_rect: LayerRect,

    /// World transform for the viewport rect itself.
    pub world_viewport_transform: LayerToWorldTransform,

    /// World transform for content within this layer
    pub world_content_transform: LayerToWorldTransform,

    /// Transform for this layer, relative to parent scrollable layer.
    pub local_transform: LayerToScrollTransform,

    /// Pipeline that this layer belongs to
    pub pipeline_id: PipelineId,

    /// Child layers
    pub children: Vec<ScrollLayerId>,
}

impl Layer {
    pub fn new(local_viewport_rect: &LayerRect,
               content_size: LayerSize,
               local_transform: &LayerToScrollTransform,
               pipeline_id: PipelineId)
               -> Layer {
        Layer {
            scrolling: ScrollingState::new(),
            content_size: content_size,
            local_viewport_rect: *local_viewport_rect,
            combined_local_viewport_rect: *local_viewport_rect,
            world_viewport_transform: LayerToWorldTransform::identity(),
            world_content_transform: LayerToWorldTransform::identity(),
            local_transform: *local_transform,
            children: Vec::new(),
            pipeline_id: pipeline_id,
        }
    }

    pub fn add_child(&mut self, child: ScrollLayerId) {
        self.children.push(child);
    }

    pub fn finalize(&mut self, scrolling: &ScrollingState) {
        self.scrolling = *scrolling;
    }

    pub fn overscroll_amount(&self) -> LayerSize {
        let scrollable_width = self.scrollable_width();
        let overscroll_x = if self.scrolling.offset.x > 0.0 {
            -self.scrolling.offset.x
        } else if self.scrolling.offset.x < -scrollable_width {
            -scrollable_width - self.scrolling.offset.x
        } else {
            0.0
        };

        let scrollable_height = self.scrollable_height();
        let overscroll_y = if self.scrolling.offset.y > 0.0 {
            -self.scrolling.offset.y
        } else if self.scrolling.offset.y < -scrollable_height {
            -scrollable_height - self.scrolling.offset.y
        } else {
            0.0
        };

        LayerSize::new(overscroll_x, overscroll_y)
    }

    pub fn set_scroll_origin(&mut self, origin: &LayerPoint) -> bool {
        let scrollable_height = self.scrollable_height();
        let scrollable_width = self.scrollable_width();
        if scrollable_height <= 0. && scrollable_width <= 0. {
            return false;
        }

        let new_offset = LayerPoint::new((-origin.x).max(-scrollable_width).min(0.0).round(),
                                         (-origin.y).max(-scrollable_height).min(0.0).round());
        if new_offset == self.scrolling.offset {
            return false;
        }

        self.scrolling.offset = new_offset;
        self.scrolling.bouncing_back = false;
        self.scrolling.started_bouncing_back = false;
        return true;
    }

    pub fn update_transform(&mut self,
                            parent_world_transform: &ScrollToWorldTransform,
                            parent_viewport_rect: &ScrollLayerRect) {
        let inv_transform = match self.local_transform.inverse() {
            Some(transform) => transform,
            None => {
                // If a transform function causes the current transformation matrix of an object
                // to be non-invertible, the object and its content do not get displayed.
                self.combined_local_viewport_rect = LayerRect::zero();
                return;
            }
        };

        let parent_viewport_rect_in_local_space = inv_transform.transform_rect(parent_viewport_rect)
                                                               .translate(&-self.scrolling.offset);
        let local_viewport_rect = self.local_viewport_rect.translate(&-self.scrolling.offset);
        let viewport_rect = parent_viewport_rect_in_local_space.intersection(&local_viewport_rect)
                                                               .unwrap_or(LayerRect::zero());

        self.combined_local_viewport_rect = viewport_rect;
        self.world_viewport_transform = parent_world_transform.pre_mul(&self.local_transform);
        self.world_content_transform = self.world_viewport_transform
                                                     .pre_translated(self.scrolling.offset.x,
                                                                     self.scrolling.offset.y,
                                                                     0.0);
    }

    pub fn scrollable_height(&self) -> f32 {
        self.content_size.height - self.local_viewport_rect.size.height
    }

    pub fn scrollable_width(&self) -> f32 {
        self.content_size.width - self.local_viewport_rect.size.width
    }

    pub fn scroll(&mut self, scroll_location: ScrollLocation, phase: ScrollEventPhase) -> bool {
        if self.scrolling.started_bouncing_back && phase == ScrollEventPhase::Move(false) {
            return false;
        }

        let mut delta = match scroll_location {
            ScrollLocation::Delta(delta) => delta,
            ScrollLocation::Start => {
                if self.scrolling.offset.y.round() >= 0.0 {
                    // Nothing to do on this layer.
                    return false;
                }

                self.scrolling.offset.y = 0.0;
                return true;
            },
            ScrollLocation::End => {
                let end_pos = self.local_viewport_rect.size.height - self.content_size.height;

                if self.scrolling.offset.y.round() <= end_pos {
                    // Nothing to do on this layer.
                    return false;
                }

                self.scrolling.offset.y = end_pos;
                return true;
            }
        };

        let overscroll_amount = self.overscroll_amount();
        let overscrolling = CAN_OVERSCROLL && (overscroll_amount.width != 0.0 ||
                                               overscroll_amount.height != 0.0);
        if overscrolling {
            if overscroll_amount.width != 0.0 {
                delta.x /= overscroll_amount.width.abs()
            }
            if overscroll_amount.height != 0.0 {
                delta.y /= overscroll_amount.height.abs()
            }
        }

        let scrollable_width = self.scrollable_width();
        let scrollable_height = self.scrollable_height();
        let is_unscrollable = scrollable_width <= 0. && scrollable_height <= 0.;
        let original_layer_scroll_offset = self.scrolling.offset;

        if scrollable_width > 0. {
            self.scrolling.offset.x = self.scrolling.offset.x + delta.x;
            if is_unscrollable || !CAN_OVERSCROLL {
                self.scrolling.offset.x =
                    self.scrolling.offset.x.min(0.0).max(-scrollable_width).round();
            }
        }

        if scrollable_height > 0. {
            self.scrolling.offset.y = self.scrolling.offset.y + delta.y;
            if is_unscrollable || !CAN_OVERSCROLL {
                self.scrolling.offset.y =
                    self.scrolling.offset.y.min(0.0).max(-scrollable_height).round();
            }
        }

        if phase == ScrollEventPhase::Start || phase == ScrollEventPhase::Move(true) {
            self.scrolling.started_bouncing_back = false
        } else if overscrolling &&
                ((delta.x < 1.0 && delta.y < 1.0) || phase == ScrollEventPhase::End) {
            self.scrolling.started_bouncing_back = true;
            self.scrolling.bouncing_back = true
        }

        if CAN_OVERSCROLL {
            self.stretch_overscroll_spring();
        }

        self.scrolling.offset != original_layer_scroll_offset ||
            self.scrolling.started_bouncing_back
    }

    pub fn stretch_overscroll_spring(&mut self) {
        let overscroll_amount = self.overscroll_amount();
        self.scrolling.spring.coords(self.scrolling.offset,
                                     self.scrolling.offset,
                                     self.scrolling.offset + overscroll_amount);
    }

    pub fn tick_scrolling_bounce_animation(&mut self) {
        let finished = self.scrolling.spring.animate();
        self.scrolling.offset = self.scrolling.spring.current();
        if finished {
            self.scrolling.bouncing_back = false
        }
    }

    pub fn ray_intersects_layer(&self, cursor: &WorldPoint) -> bool {
        let inv = self.world_viewport_transform.inverse().unwrap();
        let z0 = -10000.0;
        let z1 =  10000.0;

        let p0 = inv.transform_point4d(&WorldPoint4D::new(cursor.x, cursor.y, z0, 1.0));
        let p0 = Point3D::new(p0.x / p0.w,
                              p0.y / p0.w,
                              p0.z / p0.w);
        let p1 = inv.transform_point4d(&WorldPoint4D::new(cursor.x, cursor.y, z1, 1.0));
        let p1 = Point3D::new(p1.x / p1.w,
                              p1.y / p1.w,
                              p1.z / p1.w);

        if self.scrollable_width() <= 0. && self.scrollable_height() <= 0. {
            return false;
        }
        ray_intersects_rect(p0, p1, self.local_viewport_rect.to_untyped())
    }
}

#[derive(Copy, Clone)]
pub struct ScrollingState {
    pub offset: LayerPoint,
    pub spring: Spring,
    pub started_bouncing_back: bool,
    pub bouncing_back: bool,
    pub should_handoff_scroll: bool
}

impl ScrollingState {
    pub fn new() -> ScrollingState {
        ScrollingState {
            offset: LayerPoint::zero(),
            spring: Spring::at(LayerPoint::zero(), STIFFNESS, DAMPING),
            started_bouncing_back: false,
            bouncing_back: false,
            should_handoff_scroll: false
        }
    }
}

<|endoftext|>


<commit_before>extern crate clap;

use clap::{App, Arg, SubCommand};

fn main() {
	let version = format!("{}.{}.{}{}",
                          env!("CARGO_PKG_VERSION_MAJOR"),
                          env!("CARGO_PKG_VERSION_MINOR"),
                          env!("CARGO_PKG_VERSION_PATCH"),
                          option_env!("CARGO_PKG_VERSION_PRE").unwrap_or(""));
    let matches = App::new("claptests")
    					.version(&version[..])
    					.about("tests clap library")
    					.author("Kevin K. <kbknapp@gmail.com>")
    					.arg(Arg::new("flag")
    								.short("f")
    								.long("flag")
    								.help("tests flags")
    								.multiple(true))
    					.arg(Arg::new("option")
    								.short("o")
    								.long("option")
    								.help("tests options")
    								.takes_value(true)
    								.multiple(true))
    					.arg(Arg::new("positional")
    								.index(1)
    								.help("tests positionals"))
    					.subcommand(SubCommand::new("subcmd")
    											.about("tests subcommands")
    											.version("0.1")
    											.author("Kevin K. <kbknapp@gmail.com>")
						    					.arg(Arg::new("scflag")
						    								.short("f")
						    								.long("flag")
						    								.help("tests flags")
						    								.multiple(true))
						    					.arg(Arg::new("scoption")
						    								.short("o")
						    								.long("option")
						    								.help("tests options")
						    								.takes_value(true)
						    								.multiple(true))
						    					.arg(Arg::new("scpositional")
						    								.index(1)
						    								.help("tests positionals")))
    					.get_matches();

    if matches.is_present("flag") {
    	println!("flag present {} times", matches.occurrences_of("flag"));
    } else {
    	println!("flag NOT present");
    }

    if matches.is_present("option") {
        if let Some(v) = matches.value_of("option") {
        	println!("option present {} times with value: {}",matches.occurrences_of("option"), v);
        }
        if let Some(ref ov) = matches.values_of("option") {
        	for o in ov {
        		println!("An option: {}", o);
        	}
        }
    } else {
        println!("option NOT present");
    }

    if let Some(p) = matches.value_of("positional") {
    	println!("positional present with value: {}", p);
    } else {
        println!("positional NOT present");
    }

    if matches.is_present("subcmd") {
        println!("subcmd present");
        if let Some(matches) = matches.subcommand_matches("subcmd") {
            if matches.is_present("scflag") {
                println!("scflag present {} times", matches.occurrences_of("scflag"));
            } else {
                println!("scflag NOT present");
            }

            if matches.is_present("scoption") {
                if let Some(v) = matches.value_of("scoption") {
                    println!("scoption present with value: {}", v);
                }
                if let Some(ref ov) = matches.values_of("scoption") {
                    for o in ov {
                        println!("An scoption: {}", o);
                    }
                }
            } else {
                println!("scoption NOT present");
            }

            if let Some(p) = matches.value_of("scpositional") {
                println!("scpositional present with value: {}", p);
            }
        }
    } else {
        println!("subcmd NOT present");
    }
}
<commit_msg>test(clap): add wider capability test coverage - wip<commit_after>extern crate clap;

use clap::{App, Arg, SubCommand};

fn main() {
    // Test version from Cargo.toml
    let version = format!("{}.{}.{}{}",
                          env!("CARGO_PKG_VERSION_MAJOR"),
                          env!("CARGO_PKG_VERSION_MINOR"),
                          env!("CARGO_PKG_VERSION_PATCH"),
                          option_env!("CARGO_PKG_VERSION_PRE").unwrap_or(""));
    let matches = App::new("claptests")
                        .version(&version[..])
                        .about("tests clap library")
                        .author("Kevin K. <kbknapp@gmail.com>")
                        .arg(Arg::new("flag")
                                    .short("f")
                                    .long("flag")
                                    .help("tests flags")
                                    .multiple(true))
                        .arg(Arg::new("option")
                                    .short("o")
                                    .long("option")
                                    .required(true)
                                    .help("tests options")
                                    .takes_value(true)
                                    .multiple(true))
                        .arg(Arg::new("positional")
                                    .index(1)
                                    .help("tests positionals"))
                        .args(vec![
                            Arg::new("flag2").short("F").mutually_excludes("flag").help("tests flags with exclusions").requires("option2"),
                            Arg::new("option2").long("long-option-2").mutually_excludes("option").help("tests long options with exclusions and requirements").requires_all(vec!["positional", "positional2"]),
                            Arg::new("positional2").index(2).help("tests positionals with exclusions and multiple"),
                            Arg::new("option3").takes_value(true).short("O").possible_values(vec!["fast", "slow"]).help("test options with specific value sets").requires("positional3"),
                            Arg::new("positional3").index(3).multiple(true).possible_values(vec!["vi", "emacs"]).help("tests positionals with specific value sets")
                        ])
                        .subcommand(SubCommand::new("subcmd")
                                                .about("tests subcommands")
                                                .version("0.1")
                                                .author("Kevin K. <kbknapp@gmail.com>")
                                                .arg(Arg::new("scflag")
                                                            .short("f")
                                                            .long("flag")
                                                            .help("tests flags")
                                                            .multiple(true))
                                                .arg(Arg::new("scoption")
                                                            .short("o")
                                                            .long("option")
                                                            .help("tests options")
                                                            .takes_value(true)
                                                            .multiple(true))
                                                .arg(Arg::new("scpositional")
                                                            .index(1)
                                                            .help("tests positionals")))
                        .get_matches();

    if matches.is_present("flag") {
        println!("flag present {} times", matches.occurrences_of("flag"));
    } else {
        println!("flag NOT present");
    }

    if matches.is_present("option") {
        if let Some(v) = matches.value_of("option") {
            println!("option present {} times with value: {}",matches.occurrences_of("option"), v);
        }
        if let Some(ref ov) = matches.values_of("option") {
            for o in ov {
                println!("An option: {}", o);
            }
        }
    } else {
        println!("option NOT present");
    }

    if let Some(p) = matches.value_of("positional") {
        println!("positional present with value: {}", p);
    } else {
        println!("positional NOT present");
    }

    if matches.is_present("flag2") {
        println!("flag2 present");
        println!("option2 present with value of: {}", matches.value_of("option2").unwrap());
        println!("positional2 present with value of: {}", matches.value_of("positional2").unwrap());
    } else {
        println!("flag2 NOT present");
        println!("option2 maybe present with value of: {}", matches.value_of("option2").unwrap_or("Nothing"));
        println!("positional2 maybe present with value of: {}", matches.value_of("positional2").unwrap_or("Nothing"));
    }

    match matches.value_of("option3").unwrap_or("") {
        "fast" => println!("option3 present quickly"),
        "slow" => println!("option3 present slowly"),
        _      => println!("option3 NOT present")
    }

    match matches.value_of("positional3").unwrap_or("") {
        "vi" => println!("positional3 present in vi mode"),
        "emacs" => println!("positional3 present in emacs mode"),
        _      => println!("positional3 NOT present")
    }

    if matches.is_present("option") {
        if let Some(v) = matches.value_of("option") {
            println!("option present {} times with value: {}",matches.occurrences_of("option"), v);
        }
        if let Some(ref ov) = matches.values_of("option") {
            for o in ov {
                println!("An option: {}", o);
            }
        }
    } else {
        println!("option NOT present");
    }

    if let Some(p) = matches.value_of("positional") {
        println!("positional present with value: {}", p);
    } else {
        println!("positional NOT present");
    }
    if matches.is_present("subcmd") {
        println!("subcmd present");
        if let Some(matches) = matches.subcommand_matches("subcmd") {
            if matches.is_present("scflag") {
                println!("scflag present {} times", matches.occurrences_of("scflag"));
            } else {
                println!("scflag NOT present");
            }

            if matches.is_present("scoption") {
                if let Some(v) = matches.value_of("scoption") {
                    println!("scoption present with value: {}", v);
                }
                if let Some(ref ov) = matches.values_of("scoption") {
                    for o in ov {
                        println!("An scoption: {}", o);
                    }
                }
            } else {
                println!("scoption NOT present");
            }

            if let Some(p) = matches.value_of("scpositional") {
                println!("scpositional present with value: {}", p);
            }
        }
    } else {
        println!("subcmd NOT present");
    }
}
<|endoftext|>