<commit_before>use std::result::Result;
use glium::{VertexBuffer, GlObject, Frame, Surface, Program};
use glium::index::{NoIndices, PrimitiveType};
use glium::uniforms::EmptyUniforms;
use glium::backend::Facade;
use cgmath::{PerspectiveFov, Rad};
use ocl::{Buffer, ProQue, Context, Program as ClProgram};
use ocl::aliases::ClFloat3;
use ocl::core::MEM_READ_WRITE;
use point::Point;

const VERTEX_SRC: &'static str = include_str!("shaders/default.vert");
const FRAGMENT_SRC: &'static str = include_str!("shaders/default.frag");
const PARTICLES_KERN_SRC: &'static str = include_str!("kernels/particles.cl");

pub type PartResult<T> = Result<T, &'static str>;

#[derive(Copy, Clone)]
struct Position {
    position: [f32; 4]
}

#[derive(Copy, Clone)]
struct Velocity {
    velocity: [f32; 4]
}

implement_vertex!(Position, position);
implement_vertex!(Velocity, velocity);

struct GlSide {
    positions: VertexBuffer<Position>,
    velocities: VertexBuffer<Velocity>,
    program: Program,
    persp_proj: PerspectiveFov<f32>
}

struct ClSide {
    positions: Buffer<ClFloat3>,
    velocities: Buffer<ClFloat3>,
    proque: ProQue
}

pub struct Particles {
    quantity: usize,
    gl_side: GlSide,
    cl_side: ClSide
}

impl Particles {
    pub fn new<F: Facade>(facade: &F, context: Context, quantity: usize) -> PartResult<Particles> {
        match quantity {
            0 => { return Err("Cannot emit zero particles.") },
            x if x > 3_000_000 => { return Err("Cannot emit more than 3 millions particles.") },
            _ => ()
        }
        let gl_side = GlSide {
            positions: VertexBuffer::empty_dynamic(facade, quantity).unwrap(),
            velocities: VertexBuffer::empty_dynamic(facade, quantity).unwrap(),
            program: Program::from_source(facade, VERTEX_SRC, FRAGMENT_SRC, None).unwrap(),
            persp_proj: PerspectiveFov { fovy: Rad { s: 60.0 }, aspect: 0.0f32, near: 0.1, far: 1000.0 } // TODO need to be computed ?
        };

        let prog_bldr = ClProgram::builder().src(PARTICLES_KERN_SRC);
        let device = context.devices().first().unwrap().clone();
        let proque = ProQue::builder().context(context).prog_bldr(prog_bldr)
                        .device(device).dims([quantity]).build().unwrap();

        let cl_side = ClSide {
            positions: Buffer::from_gl_buffer(&proque, Some(MEM_READ_WRITE),
                [quantity], gl_side.positions.get_id()).unwrap(),
            velocities: Buffer::from_gl_buffer(&proque, Some(MEM_READ_WRITE),
                [quantity], gl_side.velocities.get_id()).unwrap(),
            proque: proque
        };
        Ok(Particles {
            quantity: quantity,
            gl_side: gl_side,
            cl_side: cl_side
        })
    }

    fn acquire_buffers(&mut self) {
        self.cl_side.positions.cmd().gl_acquire().enq().unwrap();
        self.cl_side.velocities.cmd().gl_acquire().enq().unwrap();
    }

    fn release_buffers(&mut self) {
        self.cl_side.positions.cmd().gl_release().enq().unwrap();
        self.cl_side.velocities.cmd().gl_release().enq().unwrap();
    }

    pub fn init_sphere(&mut self) {
        self.acquire_buffers();

        self.cl_side.proque.create_kernel("init_sphere").unwrap()
            .arg_buf(&self.cl_side.positions)
            .arg_buf(&self.cl_side.velocities)
            .enq().unwrap();

        self.release_buffers();
    }

    pub fn init_cube(&mut self) {
        self.acquire_buffers();

        self.cl_side.proque.create_kernel("init_cube").unwrap()
            .arg_buf(&self.cl_side.positions)
            .arg_buf(&self.cl_side.velocities)
            .enq().unwrap();

        self.release_buffers();
    }

    pub fn update(&mut self, gravity_point: Point) {
        self.acquire_buffers();

        self.cl_side.proque.create_kernel("update").unwrap()
            .arg_buf(&self.cl_side.positions)
            .arg_buf(&self.cl_side.velocities)
            .arg_vec(gravity_point)
            .enq().unwrap();

        self.release_buffers();
    }

    pub fn draw(&self, frame: &mut Frame) {
        let indices = NoIndices(PrimitiveType::Points);
        frame.draw(&self.gl_side.positions, &indices, &self.gl_side.program,
            &EmptyUniforms, &Default::default()).unwrap();
        frame.set_finish().unwrap();
    }
}
<commit_msg>cleaned up spaces<commit_after>use std::result::Result;
use glium::{VertexBuffer, GlObject, Frame, Surface, Program};
use glium::index::{NoIndices, PrimitiveType};
use glium::uniforms::EmptyUniforms;
use glium::backend::Facade;
use cgmath::{PerspectiveFov, Rad};
use ocl::{Buffer, ProQue, Context, Program as ClProgram};
use ocl::aliases::ClFloat3;
use ocl::core::MEM_READ_WRITE;
use point::Point;

const VERTEX_SRC: &'static str = include_str!("shaders/default.vert");
const FRAGMENT_SRC: &'static str = include_str!("shaders/default.frag");
const PARTICLES_KERN_SRC: &'static str = include_str!("kernels/particles.cl");

pub type PartResult<T> = Result<T, &'static str>;

#[derive(Copy, Clone)]
struct Position {
    position: [f32; 4]
}

#[derive(Copy, Clone)]
struct Velocity {
    velocity: [f32; 4]
}

implement_vertex!(Position, position);
implement_vertex!(Velocity, velocity);

struct GlSide {
    positions: VertexBuffer<Position>,
    velocities: VertexBuffer<Velocity>,
    program: Program,
    persp_proj: PerspectiveFov<f32>
}

struct ClSide {
    positions: Buffer<ClFloat3>,
    velocities: Buffer<ClFloat3>,
    proque: ProQue
}

pub struct Particles {
    quantity: usize,
    gl_side: GlSide,
    cl_side: ClSide
}

impl Particles {
    pub fn new<F: Facade>(facade: &F, context: Context, quantity: usize) -> PartResult<Particles> {
        match quantity {
            0 => { return Err("Cannot emit zero particles.") },
            x if x > 3_000_000 => { return Err("Cannot emit more than 3 millions particles.") },
            _ => ()
        }
        let gl_side = GlSide {
            positions: VertexBuffer::empty_dynamic(facade, quantity).unwrap(),
            velocities: VertexBuffer::empty_dynamic(facade, quantity).unwrap(),
            program: Program::from_source(facade, VERTEX_SRC, FRAGMENT_SRC, None).unwrap(),
            persp_proj: PerspectiveFov { fovy: Rad { s: 60.0 }, aspect: 0.0f32, near: 0.1, far: 1000.0 } // TODO need to be computed ?
        };

        let prog_bldr = ClProgram::builder().src(PARTICLES_KERN_SRC);
        let device = context.devices().first().unwrap().clone();
        let proque = ProQue::builder().context(context).prog_bldr(prog_bldr)
                        .device(device).dims([quantity]).build().unwrap();

        let cl_side = ClSide {
            positions: Buffer::from_gl_buffer(&proque, Some(MEM_READ_WRITE),
                [quantity], gl_side.positions.get_id()).unwrap(),
            velocities: Buffer::from_gl_buffer(&proque, Some(MEM_READ_WRITE),
                [quantity], gl_side.velocities.get_id()).unwrap(),
            proque: proque
        };
        Ok(Particles {
            quantity: quantity,
            gl_side: gl_side,
            cl_side: cl_side
        })
    }

    fn acquire_buffers(&mut self) {
        self.cl_side.positions.cmd().gl_acquire().enq().unwrap();
        self.cl_side.velocities.cmd().gl_acquire().enq().unwrap();
    }

    fn release_buffers(&mut self) {
        self.cl_side.positions.cmd().gl_release().enq().unwrap();
        self.cl_side.velocities.cmd().gl_release().enq().unwrap();
    }

    pub fn init_sphere(&mut self) {
        self.acquire_buffers();
        self.cl_side.proque.create_kernel("init_sphere").unwrap()
            .arg_buf(&self.cl_side.positions)
            .arg_buf(&self.cl_side.velocities)
            .enq().unwrap();
        self.release_buffers();
    }

    pub fn init_cube(&mut self) {
        self.acquire_buffers();
        self.cl_side.proque.create_kernel("init_cube").unwrap()
            .arg_buf(&self.cl_side.positions)
            .arg_buf(&self.cl_side.velocities)
            .enq().unwrap();
        self.release_buffers();
    }

    pub fn update(&mut self, gravity_point: Point) {
        self.acquire_buffers();
        self.cl_side.proque.create_kernel("update").unwrap()
            .arg_buf(&self.cl_side.positions)
            .arg_buf(&self.cl_side.velocities)
            .arg_vec(gravity_point)
            .enq().unwrap();
        self.release_buffers();
    }

    pub fn draw(&self, frame: &mut Frame) {
        let indices = NoIndices(PrimitiveType::Points);
        frame.draw(&self.gl_side.positions, &indices, &self.gl_side.program,
            &EmptyUniforms, &Default::default()).unwrap();
        frame.set_finish().unwrap();
    }
}
<|endoftext|>


<commit_before>use std::{
    convert::TryFrom,
    fmt,
    hash::{Hash, Hasher},
    iter::FromIterator,
    ops::{Deref, DerefMut},
};

use crate::Arc;

const CUTOFF: usize = 22;

type Inner = [u8; CUTOFF];

/// A buffer that may either be inline or remote and protected
/// by an Arc
#[derive(Clone)]
pub struct IVec(IVecInner);

impl Default for IVec {
    fn default() -> Self {
        Self::from(&[])
    }
}

#[derive(Clone)]
enum IVecInner {
    Inline(u8, Inner),
    Remote(Arc<[u8]>),
}

impl Hash for IVec {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.deref().hash(state);
    }
}

const fn is_inline_candidate(length: usize) -> bool {
    length <= CUTOFF
}

impl IVec {
    fn inline(slice: &[u8]) -> Self {
        assert!(is_inline_candidate(slice.len()));

        let mut data = Inner::default();

        #[allow(unsafe_code)]
        unsafe {
            std::ptr::copy_nonoverlapping(
                slice.as_ptr(),
                data.as_mut_ptr(),
                slice.len(),
            );
        }

        Self(IVecInner::Inline(u8::try_from(slice.len()).unwrap(), data))
    }

    fn remote(arc: Arc<[u8]>) -> Self {
        Self(IVecInner::Remote(arc))
    }

    fn make_mut(&mut self) {
        match self.0 {
            IVecInner::Remote(ref mut buf) if Arc::strong_count(buf) != 1 => {
                self.0 = IVecInner::Remote(buf.to_vec().into());
            }
            _ => {}
        }
    }
}

impl FromIterator<u8> for IVec {
    fn from_iter<T>(iter: T) -> Self
    where
        T: IntoIterator<Item = u8>,
    {
        let bs: Vec<u8> = iter.into_iter().collect();
        bs.into()
    }
}

impl From<Box<[u8]>> for IVec {
    fn from(b: Box<[u8]>) -> Self {
        if is_inline_candidate(b.len()) {
            Self::inline(&b)
        } else {
            Self::remote(Arc::from(b))
        }
    }
}

impl From<&[u8]> for IVec {
    fn from(slice: &[u8]) -> Self {
        if is_inline_candidate(slice.len()) {
            Self::inline(slice)
        } else {
            Self::remote(Arc::from(slice))
        }
    }
}

impl From<Arc<[u8]>> for IVec {
    fn from(arc: Arc<[u8]>) -> Self {
        if is_inline_candidate(arc.len()) {
            Self::inline(&arc)
        } else {
            Self::remote(arc)
        }
    }
}

impl From<&str> for IVec {
    fn from(s: &str) -> Self {
        Self::from(s.as_bytes())
    }
}

impl From<&IVec> for IVec {
    fn from(v: &Self) -> Self {
        v.clone()
    }
}

impl From<Vec<u8>> for IVec {
    fn from(v: Vec<u8>) -> Self {
        if is_inline_candidate(v.len()) {
            Self::inline(&v)
        } else {
            // rely on the Arc From specialization
            // for Vec<T>, which may improve
            // over time
            Self::remote(Arc::from(v))
        }
    }
}

impl std::borrow::Borrow<[u8]> for IVec {
    fn borrow(&self) -> &[u8] {
        self.as_ref()
    }
}

impl std::borrow::Borrow<[u8]> for &IVec {
    fn borrow(&self) -> &[u8] {
        self.as_ref()
    }
}

macro_rules! from_array {
    ($($s:expr),*) => {
        $(
            impl From<&[u8; $s]> for IVec {
                fn from(v: &[u8; $s]) -> Self {
                    Self::from(&v[..])
                }
            }
        )*
    }
}

from_array!(
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
    21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
);

impl Into<Arc<[u8]>> for IVec {
    fn into(self) -> Arc<[u8]> {
        match self.0 {
            IVecInner::Inline(..) => Arc::from(self.as_ref()),
            IVecInner::Remote(arc) => arc,
        }
    }
}

impl Deref for IVec {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        self.as_ref()
    }
}

impl AsRef<[u8]> for IVec {
    #[inline]
    #[allow(unsafe_code)]
    fn as_ref(&self) -> &[u8] {
        match &self.0 {
            IVecInner::Inline(sz, buf) => unsafe {
                buf.get_unchecked(..*sz as usize)
            },
            IVecInner::Remote(buf) => buf,
        }
    }
}

impl DerefMut for IVec {
    #[inline]
    fn deref_mut(&mut self) -> &mut [u8] {
        self.as_mut()
    }
}

impl AsMut<[u8]> for IVec {
    #[inline]
    #[allow(unsafe_code)]
    fn as_mut(&mut self) -> &mut [u8] {
        self.make_mut();

        match self.0 {
            IVecInner::Inline(ref sz, mut buf) => unsafe {
                std::slice::from_raw_parts_mut(buf.as_mut_ptr(), *sz as usize)
            },
            IVecInner::Remote(ref mut buf) => Arc::get_mut(buf).unwrap(),
        }
    }
}

impl Ord for IVec {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.as_ref().cmp(other.as_ref())
    }
}

impl PartialOrd for IVec {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl<T: AsRef<[u8]>> PartialEq<T> for IVec {
    fn eq(&self, other: &T) -> bool {
        self.as_ref() == other.as_ref()
    }
}

impl PartialEq<[u8]> for IVec {
    fn eq(&self, other: &[u8]) -> bool {
        self.as_ref() == other
    }
}

impl Eq for IVec {}

impl fmt::Debug for IVec {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.as_ref().fmt(f)
    }
}

#[test]
fn ivec_usage() {
    let iv1 = IVec::from(vec![1, 2, 3]);
    assert_eq!(iv1, vec![1, 2, 3]);
    let iv2 = IVec::from(&[4; 128][..]);
    assert_eq!(iv2, vec![4; 128]);
}

#[test]
fn boxed_slice_conversion() {
    let boite1: Box<[u8]> = Box::new([1, 2, 3]);
    let iv1: IVec = boite1.into();
    assert_eq!(iv1, vec![1, 2, 3]);
    let boite2: Box<[u8]> = Box::new([4; 128]);
    let iv2: IVec = boite2.into();
    assert_eq!(iv2, vec![4; 128]);
}
<commit_msg>Add doctest for IVec::subslice<commit_after>use std::{
    convert::TryFrom,
    fmt,
    hash::{Hash, Hasher},
    iter::FromIterator,
    ops::{Deref, DerefMut},
};

use crate::Arc;

const CUTOFF: usize = 22;

type Inner = [u8; CUTOFF];

/// A buffer that may either be inline or remote and protected
/// by an Arc
#[derive(Clone)]
pub struct IVec(IVecInner);

impl Default for IVec {
    fn default() -> Self {
        Self::from(&[])
    }
}

#[derive(Clone)]
enum IVecInner {
    Inline(u8, Inner),
    Remote(Arc<[u8]>),
    Subslice { base: Arc<[u8]>, offset: usize, len: usize },
}

impl Hash for IVec {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.deref().hash(state);
    }
}

const fn is_inline_candidate(length: usize) -> bool {
    length <= CUTOFF
}

impl IVec {
    /// Create a subslice of this `IVec` that shares
    /// the same backing data and reference counter.
    ///
    /// # Panics
    ///
    /// Panics if `self.len() - offset >= len`.
    ///
    /// # Examples
    /// ```
    /// let iv = IVec::from(vec![1]);
    /// let subslice = iv.subslice(0, 1);
    /// assert_eq!(&subslice, &[1]);
    /// let subslice = subslice.subslice(0, 1);
    /// assert_eq!(&subslice, &[1]);
    /// let subslice = subslice.subslice(1, 0);
    /// assert_eq!(&subslice, &[]);
    /// let subslice = subslice.subslice(0, 0);
    /// assert_eq!(&subslice, &[]);
    ///
    /// let iv2 = IVec::from(vec![1, 2, 3]);
    /// let subslice = iv2.subslice(3, 0);
    /// assert_eq!(&subslice, &[]);
    /// let subslice = iv2.subslice(2, 1);
    /// assert_eq!(&subslice, &[3]);
    /// let subslice = iv2.subslice(1, 2);
    /// assert_eq!(&subslice, &[2, 3]);
    /// let subslice = iv2.subslice(0, 3);
    /// assert_eq!(&subslice, &[1, 2, 3]);
    /// let subslice = subslice.subslice(1, 2);
    /// assert_eq!(&subslice, &[2, 3]);
    /// let subslice = subslice.subslice(1, 1);
    /// assert_eq!(&subslice, &[3]);
    /// let subslice = subslice.subslice(1, 0);
    /// assert_eq!(&subslice, &[]);
    /// ```
    pub fn subslice(&self, offset: usize, len: usize) -> Self {
        assert!(self.len().checked_sub(offset).unwrap() >= len);

        let new_offset = offset;
        let new_len = len;

        let inner = match self.0 {
            IVecInner::Remote(ref base) => {
                IVecInner::Subslice { base: base.clone(), offset, len }
            }
            IVecInner::Inline(_, old_inner) => {
                // old length already checked above in assertion
                let mut new_inner = Inner::default();
                new_inner[..new_len].copy_from_slice(
                    &old_inner[new_offset..new_offset + new_len],
                );

                IVecInner::Inline(u8::try_from(new_len).unwrap(), new_inner)
            }
            IVecInner::Subslice { ref base, ref offset, .. } => {
                IVecInner::Subslice {
                    base: base.clone(),
                    offset: offset + new_offset,
                    len: new_len,
                }
            }
        };

        IVec(inner)
    }

    fn inline(slice: &[u8]) -> Self {
        assert!(is_inline_candidate(slice.len()));

        let mut data = Inner::default();

        #[allow(unsafe_code)]
        unsafe {
            std::ptr::copy_nonoverlapping(
                slice.as_ptr(),
                data.as_mut_ptr(),
                slice.len(),
            );
        }

        Self(IVecInner::Inline(u8::try_from(slice.len()).unwrap(), data))
    }

    fn remote(arc: Arc<[u8]>) -> Self {
        Self(IVecInner::Remote(arc))
    }

    fn make_mut(&mut self) {
        match self.0 {
            IVecInner::Remote(ref mut buf) if Arc::strong_count(buf) != 1 => {
                self.0 = IVecInner::Remote(buf.to_vec().into());
            }
            IVecInner::Subslice { ref mut base, offset, len }
                if Arc::strong_count(base) != 1 =>
            {
                self.0 = IVecInner::Remote(
                    base[offset..offset + len].to_vec().into(),
                );
            }
            _ => {}
        }
    }
}

impl FromIterator<u8> for IVec {
    fn from_iter<T>(iter: T) -> Self
    where
        T: IntoIterator<Item = u8>,
    {
        let bs: Vec<u8> = iter.into_iter().collect();
        bs.into()
    }
}

impl From<Box<[u8]>> for IVec {
    fn from(b: Box<[u8]>) -> Self {
        if is_inline_candidate(b.len()) {
            Self::inline(&b)
        } else {
            Self::remote(Arc::from(b))
        }
    }
}

impl From<&[u8]> for IVec {
    fn from(slice: &[u8]) -> Self {
        if is_inline_candidate(slice.len()) {
            Self::inline(slice)
        } else {
            Self::remote(Arc::from(slice))
        }
    }
}

impl From<Arc<[u8]>> for IVec {
    fn from(arc: Arc<[u8]>) -> Self {
        if is_inline_candidate(arc.len()) {
            Self::inline(&arc)
        } else {
            Self::remote(arc)
        }
    }
}

impl From<&str> for IVec {
    fn from(s: &str) -> Self {
        Self::from(s.as_bytes())
    }
}

impl From<&IVec> for IVec {
    fn from(v: &Self) -> Self {
        v.clone()
    }
}

impl From<Vec<u8>> for IVec {
    fn from(v: Vec<u8>) -> Self {
        if is_inline_candidate(v.len()) {
            Self::inline(&v)
        } else {
            // rely on the Arc From specialization
            // for Vec<T>, which may improve
            // over time
            Self::remote(Arc::from(v))
        }
    }
}

impl std::borrow::Borrow<[u8]> for IVec {
    fn borrow(&self) -> &[u8] {
        self.as_ref()
    }
}

impl std::borrow::Borrow<[u8]> for &IVec {
    fn borrow(&self) -> &[u8] {
        self.as_ref()
    }
}

macro_rules! from_array {
    ($($s:expr),*) => {
        $(
            impl From<&[u8; $s]> for IVec {
                fn from(v: &[u8; $s]) -> Self {
                    Self::from(&v[..])
                }
            }
        )*
    }
}

from_array!(
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
    21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
);

impl Into<Arc<[u8]>> for IVec {
    fn into(self) -> Arc<[u8]> {
        match self.0 {
            IVecInner::Inline(..) => Arc::from(self.as_ref()),
            IVecInner::Remote(arc) => arc,
            IVecInner::Subslice { .. } => self.deref().into(),
        }
    }
}

impl Deref for IVec {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        self.as_ref()
    }
}

impl AsRef<[u8]> for IVec {
    #[inline]
    #[allow(unsafe_code)]
    fn as_ref(&self) -> &[u8] {
        match &self.0 {
            IVecInner::Inline(sz, buf) => unsafe {
                buf.get_unchecked(..*sz as usize)
            },
            IVecInner::Remote(buf) => buf,
            IVecInner::Subslice { base, offset, len } => {
                &base[*offset..*offset + *len]
            }
        }
    }
}

impl DerefMut for IVec {
    #[inline]
    fn deref_mut(&mut self) -> &mut [u8] {
        self.as_mut()
    }
}

impl AsMut<[u8]> for IVec {
    #[inline]
    #[allow(unsafe_code)]
    fn as_mut(&mut self) -> &mut [u8] {
        self.make_mut();

        match self.0 {
            IVecInner::Inline(ref sz, mut buf) => unsafe {
                std::slice::from_raw_parts_mut(buf.as_mut_ptr(), *sz as usize)
            },
            IVecInner::Remote(ref mut buf) => Arc::get_mut(buf).unwrap(),
            IVecInner::Subslice { ref mut base, offset, len } => {
                &mut Arc::get_mut(base).unwrap()[offset..offset + len]
            }
        }
    }
}

impl Ord for IVec {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.as_ref().cmp(other.as_ref())
    }
}

impl PartialOrd for IVec {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl<T: AsRef<[u8]>> PartialEq<T> for IVec {
    fn eq(&self, other: &T) -> bool {
        self.as_ref() == other.as_ref()
    }
}

impl PartialEq<[u8]> for IVec {
    fn eq(&self, other: &[u8]) -> bool {
        self.as_ref() == other
    }
}

impl Eq for IVec {}

impl fmt::Debug for IVec {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.as_ref().fmt(f)
    }
}

#[test]
fn ivec_usage() {
    let iv1 = IVec::from(vec![1, 2, 3]);
    assert_eq!(iv1, vec![1, 2, 3]);
    let iv2 = IVec::from(&[4; 128][..]);
    assert_eq!(iv2, vec![4; 128]);
}

#[test]
fn boxed_slice_conversion() {
    let boite1: Box<[u8]> = Box::new([1, 2, 3]);
    let iv1: IVec = boite1.into();
    assert_eq!(iv1, vec![1, 2, 3]);
    let boite2: Box<[u8]> = Box::new([4; 128]);
    let iv2: IVec = boite2.into();
    assert_eq!(iv2, vec![4; 128]);
}

#[test]
#[should_panic]
fn subslice_usage_00() {
    let iv1 = IVec::from(vec![1, 2, 3]);
    let _subslice = iv1.subslice(0, 4);
}

#[test]
#[should_panic]
fn subslice_usage_01() {
    let iv1 = IVec::from(vec![1, 2, 3]);
    let _subslice = iv1.subslice(3, 1);
}
<|endoftext|>


<commit_before>use libc::{timespec, time_t, c_int, c_long};
use errno::{SysResult, SysError};
use fcntl::Fd;

pub use self::ffi::kevent as KEvent;

mod ffi {
    pub use libc::{c_int, c_void, uintptr_t, intptr_t, timespec};
    use super::{EventFilter, EventFlag, FilterFlag};

    #[repr(C)]
    pub struct kevent {
        pub ident: uintptr_t,       // 8
        pub filter: EventFilter,    // 2
        pub flags: EventFlag,       // 2
        pub fflags: FilterFlag,     // 4
        pub data: intptr_t,         // 8
        pub udata: u64              // 8
    }

    // Bug in rustc, cannot determine that kevent is #[repr(C)]
    #[allow(ctypes)]
    extern {
        pub fn kqueue() -> c_int;

        pub fn kevent(
            kq: c_int,
            changelist: *const kevent,
            nchanges: c_int,
            eventlist: *mut kevent,
            nevents: c_int,
            timeout: *const timespec) -> c_int;
    }
}

#[repr(i16)]
#[deriving(Show, PartialEq)]
pub enum EventFilter {
    EVFILT_READ = -1,
    EVFILT_WRITE = -2,
    EVFILT_AIO = -3,
    EVFILT_VNODE = -4,
    EVFILT_PROC = -5,
    EVFILT_SIGNAL = -6,
    EVFILT_TIMER = -7,
    EVFILT_MACHPORT = -8,
    EVFILT_FS = -9,
    EVFILT_USER = -10,
    // -11: unused
    EVFILT_VM = -12,
    EVFILT_SYSCOUNT = 13
}

bitflags!(
    flags EventFlag: u16 {
        static EV_ADD       = 0x0001,
        static EV_DELETE    = 0x0002,
        static EV_ENABLE    = 0x0004,
        static EV_DISABLE   = 0x0008,
        static EV_RECEIPT   = 0x0040,
        static EV_ONESHOT   = 0x0010,
        static EV_CLEAR     = 0x0020,
        static EV_DISPATCH  = 0x0080,
        static EV_SYSFLAGS  = 0xF000,
        static EV_FLAG0     = 0x1000,
        static EV_FLAG1     = 0x2000,
        static EV_EOF       = 0x8000,
        static EV_ERROR     = 0x4000
    }
)

bitflags!(
    flags FilterFlag: u32 {
        static NOTE_TRIGGER                         = 0x01000000,
        static NOTE_FFNOP                           = 0x00000000,
        static NOTE_FFAND                           = 0x40000000,
        static NOTE_FFOR                            = 0x80000000,
        static NOTE_FFCOPY                          = 0xc0000000,
        static NOTE_FFCTRLMASK                      = 0xc0000000,
        static NOTE_FFLAGSMASK                      = 0x00ffffff,
        static NOTE_LOWAT                           = 0x00000001,
        static NOTE_DELETE                          = 0x00000001,
        static NOTE_WRITE                           = 0x00000002,
        static NOTE_EXTEND                          = 0x00000004,
        static NOTE_ATTRIB                          = 0x00000008,
        static NOTE_LINK                            = 0x00000010,
        static NOTE_RENAME                          = 0x00000020,
        static NOTE_REVOKE                          = 0x00000040,
        static NOTE_NONE                            = 0x00000080,
        static NOTE_EXIT                            = 0x80000000,
        static NOTE_FORK                            = 0x40000000,
        static NOTE_EXEC                            = 0x20000000,
        static NOTE_REAP                            = 0x10000000,
        static NOTE_SIGNAL                          = 0x08000000,
        static NOTE_EXITSTATUS                      = 0x04000000,
        static NOTE_RESOURCEEND                     = 0x02000000,
        static NOTE_APPACTIVE                       = 0x00800000,
        static NOTE_APPBACKGROUND                   = 0x00400000,
        static NOTE_APPNONUI                        = 0x00200000,
        static NOTE_APPINACTIVE                     = 0x00100000,
        static NOTE_APPALLSTATES                    = 0x00f00000,
        static NOTE_PDATAMASK                       = 0x000fffff,
        static NOTE_PCTRLMASK                       = 0xfff00000,
        static NOTE_EXIT_REPARENTED                 = 0x00080000,
        static NOTE_VM_PRESSURE                     = 0x80000000,
        static NOTE_VM_PRESSURE_TERMINATE           = 0x40000000,
        static NOTE_VM_PRESSURE_SUDDEN_TERMINATE    = 0x20000000,
        static NOTE_VM_ERROR                        = 0x10000000,
        static NOTE_SECONDS                         = 0x00000001,
        static NOTE_USECONDS                        = 0x00000002,
        static NOTE_NSECONDS                        = 0x00000004,
        static NOTE_ABSOLUTE                        = 0x00000008,
        static NOTE_TRACK                           = 0x00000001,
        static NOTE_TRACKERR                        = 0x00000002,
        static NOTE_CHILD                           = 0x00000004
    }
)

pub static EV_POLL: EventFlag = EV_FLAG0;
pub static EV_OOBAND: EventFlag = EV_FLAG1;

pub fn kqueue() -> SysResult<Fd> {
    let res = unsafe { ffi::kqueue() };

    if res < 0 {
        return Err(SysError::last());
    }

    Ok(res)
}

pub fn kevent(kq: Fd,
              changelist: &[KEvent],
              eventlist: &mut [KEvent],
              timeout_ms: uint) -> SysResult<uint> {

    // Convert ms to timespec
    let timeout = timespec {
        tv_sec: (timeout_ms / 1000) as time_t,
        tv_nsec: ((timeout_ms % 1000) * 1_000_000) as c_long
    };

    let res = unsafe {
        ffi::kevent(
            kq,
            changelist.as_ptr(),
            changelist.len() as c_int,
            eventlist.as_mut_ptr(),
            eventlist.len() as c_int,
            &timeout as *const timespec)
    };

    if res < 0 {
        return Err(SysError::last());
    }

    return Ok(res as uint)
}

#[inline]
pub fn ev_set(ev: &mut KEvent,
              ident: uint,
              filter: EventFilter,
              flags: EventFlag,
              fflags: FilterFlag,
              udata: u64) {

    ev.ident  = ident as u64;
    ev.filter = filter;
    ev.flags  = flags;
    ev.fflags = fflags;
    ev.data   = 0;
    ev.udata  = udata;
}
<commit_msg>correctly match the kqueue man page<commit_after>use libc::{timespec, time_t, c_int, c_long};
use errno::{SysResult, SysError};
use fcntl::Fd;

pub use self::ffi::kevent as KEvent;

mod ffi {
    pub use libc::{c_int, c_void, uintptr_t, intptr_t, timespec};
    use super::{EventFilter, EventFlag, FilterFlag};

    #[repr(C)]
    pub struct kevent {
        pub ident: uintptr_t,       // 8
        pub filter: EventFilter,    // 2
        pub flags: EventFlag,       // 2
        pub fflags: FilterFlag,     // 4
        pub data: intptr_t,         // 8
        pub udata: uint             // 8
    }

    // Bug in rustc, cannot determine that kevent is #[repr(C)]
    #[allow(ctypes)]
    extern {
        pub fn kqueue() -> c_int;

        pub fn kevent(
            kq: c_int,
            changelist: *const kevent,
            nchanges: c_int,
            eventlist: *mut kevent,
            nevents: c_int,
            timeout: *const timespec) -> c_int;
    }
}

#[repr(i16)]
#[deriving(Show, PartialEq)]
pub enum EventFilter {
    EVFILT_READ = -1,
    EVFILT_WRITE = -2,
    EVFILT_AIO = -3,
    EVFILT_VNODE = -4,
    EVFILT_PROC = -5,
    EVFILT_SIGNAL = -6,
    EVFILT_TIMER = -7,
    EVFILT_MACHPORT = -8,
    EVFILT_FS = -9,
    EVFILT_USER = -10,
    // -11: unused
    EVFILT_VM = -12,
    EVFILT_SYSCOUNT = 13
}

bitflags!(
    flags EventFlag: u16 {
        static EV_ADD       = 0x0001,
        static EV_DELETE    = 0x0002,
        static EV_ENABLE    = 0x0004,
        static EV_DISABLE   = 0x0008,
        static EV_RECEIPT   = 0x0040,
        static EV_ONESHOT   = 0x0010,
        static EV_CLEAR     = 0x0020,
        static EV_DISPATCH  = 0x0080,
        static EV_SYSFLAGS  = 0xF000,
        static EV_FLAG0     = 0x1000,
        static EV_FLAG1     = 0x2000,
        static EV_EOF       = 0x8000,
        static EV_ERROR     = 0x4000
    }
)

bitflags!(
    flags FilterFlag: u32 {
        static NOTE_TRIGGER                         = 0x01000000,
        static NOTE_FFNOP                           = 0x00000000,
        static NOTE_FFAND                           = 0x40000000,
        static NOTE_FFOR                            = 0x80000000,
        static NOTE_FFCOPY                          = 0xc0000000,
        static NOTE_FFCTRLMASK                      = 0xc0000000,
        static NOTE_FFLAGSMASK                      = 0x00ffffff,
        static NOTE_LOWAT                           = 0x00000001,
        static NOTE_DELETE                          = 0x00000001,
        static NOTE_WRITE                           = 0x00000002,
        static NOTE_EXTEND                          = 0x00000004,
        static NOTE_ATTRIB                          = 0x00000008,
        static NOTE_LINK                            = 0x00000010,
        static NOTE_RENAME                          = 0x00000020,
        static NOTE_REVOKE                          = 0x00000040,
        static NOTE_NONE                            = 0x00000080,
        static NOTE_EXIT                            = 0x80000000,
        static NOTE_FORK                            = 0x40000000,
        static NOTE_EXEC                            = 0x20000000,
        static NOTE_REAP                            = 0x10000000,
        static NOTE_SIGNAL                          = 0x08000000,
        static NOTE_EXITSTATUS                      = 0x04000000,
        static NOTE_RESOURCEEND                     = 0x02000000,
        static NOTE_APPACTIVE                       = 0x00800000,
        static NOTE_APPBACKGROUND                   = 0x00400000,
        static NOTE_APPNONUI                        = 0x00200000,
        static NOTE_APPINACTIVE                     = 0x00100000,
        static NOTE_APPALLSTATES                    = 0x00f00000,
        static NOTE_PDATAMASK                       = 0x000fffff,
        static NOTE_PCTRLMASK                       = 0xfff00000,
        static NOTE_EXIT_REPARENTED                 = 0x00080000,
        static NOTE_VM_PRESSURE                     = 0x80000000,
        static NOTE_VM_PRESSURE_TERMINATE           = 0x40000000,
        static NOTE_VM_PRESSURE_SUDDEN_TERMINATE    = 0x20000000,
        static NOTE_VM_ERROR                        = 0x10000000,
        static NOTE_SECONDS                         = 0x00000001,
        static NOTE_USECONDS                        = 0x00000002,
        static NOTE_NSECONDS                        = 0x00000004,
        static NOTE_ABSOLUTE                        = 0x00000008,
        static NOTE_TRACK                           = 0x00000001,
        static NOTE_TRACKERR                        = 0x00000002,
        static NOTE_CHILD                           = 0x00000004
    }
)

pub static EV_POLL: EventFlag = EV_FLAG0;
pub static EV_OOBAND: EventFlag = EV_FLAG1;

pub fn kqueue() -> SysResult<Fd> {
    let res = unsafe { ffi::kqueue() };

    if res < 0 {
        return Err(SysError::last());
    }

    Ok(res)
}

pub fn kevent(kq: Fd,
              changelist: &[KEvent],
              eventlist: &mut [KEvent],
              timeout_ms: uint) -> SysResult<uint> {

    // Convert ms to timespec
    let timeout = timespec {
        tv_sec: (timeout_ms / 1000) as time_t,
        tv_nsec: ((timeout_ms % 1000) * 1_000_000) as c_long
    };

    let res = unsafe {
        ffi::kevent(
            kq,
            changelist.as_ptr(),
            changelist.len() as c_int,
            eventlist.as_mut_ptr(),
            eventlist.len() as c_int,
            &timeout as *const timespec)
    };

    if res < 0 {
        return Err(SysError::last());
    }

    return Ok(res as uint)
}

#[inline]
pub fn ev_set(ev: &mut KEvent,
              ident: uint,
              filter: EventFilter,
              flags: EventFlag,
              fflags: FilterFlag,
              udata: uint) {

    ev.ident  = ident as u64;
    ev.filter = filter;
    ev.flags  = flags;
    ev.fflags = fflags;
    ev.data   = 0;
    ev.udata  = udata;
}
<|endoftext|>


<commit_before>use std::io::fs::PathExtensions;
use std::io::{File, Open, ReadWrite};
use todo::entry::Entry;

pub struct List {
    file: File,
    entries: Vec<Entry>
}

impl List {
    pub fn new(path: Path) -> List {
        let file = if path.exists() {
            match File::open_mode(&path, Open, ReadWrite) {
                Ok(result) => result,
                Err(reason) => panic!("Couldn't open file `{}` for writing: {}", path.display(), reason.desc)
            }
        } else {
            File::create(&path).unwrap()
        };

        List {
            file: file,
            entries: vec![]
        }
    }

    pub fn load(&mut self) {
        let text = &self.file.read_to_string().unwrap();
        let mut i = 0;
        for line in text.lines() {
            i += 1;
            &self.entries.push(Entry::new(i, line.to_string()));
        }
    }

    pub fn save(&mut self) {
        &self.file.write("Hi!".as_bytes());
    }

    pub fn index(&self, context: Option<String>) {
        for entry in (&self.entries).iter() {
            println!("({}) {}", entry.id, entry.content);
        }
    }

    pub fn add(&self, context: Option<String>) {
        println!("adding!");
    }

    pub fn edit(&self, context: Option<String>) {
        println!("editting!");
    }

    pub fn remove(&self, context: Option<String>) {
        println!("removing!");
    }

    pub fn finish(&self, context: Option<String>) {
        println!("finishing!");
    }

    pub fn count(&self, context: Option<String>) {
        println!("counting!");
    }
}
<commit_msg>Begin filter implementation<commit_after>use std::io::fs::PathExtensions;
use std::io::{File, Open, ReadWrite};
use todo::entry::Entry;

pub struct List {
    file: File,
    entries: Vec<Entry>
}

impl List {
    pub fn new(path: Path) -> List {
        let file = if path.exists() {
            match File::open_mode(&path, Open, ReadWrite) {
                Ok(result) => result,
                Err(reason) => panic!("Couldn't open file `{}` for writing: {}", path.display(), reason.desc)
            }
        } else {
            File::create(&path).unwrap()
        };

        List {
            file: file,
            entries: vec![]
        }
    }

    pub fn load(&mut self) {
        let text = &self.file.read_to_string().unwrap();
        let mut i = 0;
        for line in text.lines() {
            i += 1;
            &self.entries.push(Entry::new(i, line.to_string()));
        }
    }

    pub fn save(&mut self) {
        &self.file.write("Hi!".as_bytes());
    }

    pub fn index(&self, context: Option<String>) {
        for entry in (&self.entries).iter().filter(|current| List::filter(current, &context)) {
            println!("({}) {}", entry.id, entry.content);
        }
    }

    pub fn add(&self, context: Option<String>) {
        println!("adding!");
    }

    pub fn edit(&self, context: Option<String>) {
        println!("editting!");
    }

    pub fn remove(&self, context: Option<String>) {
        println!("removing!");
    }

    pub fn finish(&self, context: Option<String>) {
        println!("finishing!");
    }

    pub fn count(&self, context: Option<String>) {
        println!("counting!");
    }

    fn filter(entry: &&Entry, context: &Option<String>) -> bool {
        match context {
            _ => true
        }
    }
}<|endoftext|>


<commit_before>use std::fmt;
use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashMap;
use error::{ RuntimeError, RuntimeResult, CastError, CastTarget };

pub mod ops;

const MAX_DEBUG_STRING_LENGTH: usize = 128;
const MAX_DEBUG_ARRAY_LENGTH: usize = 4;
const MAX_DEBUG_HASH_LENGTH: usize = 4;

#[derive(Hash, PartialEq, Eq, PartialOrd)]
pub enum HashKey {
    Int(i64),
    Str(String),
}

impl fmt::Debug for HashKey {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            HashKey::Int(ref v) => write!(f, "{}", v),
            HashKey::Str(ref v) => write!(f, "{:?}", v),
        }
    }
}

pub enum Value {
    Int(i64),
    Float(f64),
    Str(String),
    Array(Vec<Value>),
    Hash(HashMap<HashKey, Value>),
    Obj(Rc<RefCell<Object>>),
    Func(Rc<for<'r> Fn(&'r [Value]) -> Option<Value> >)
}

impl PartialEq for Value {
    fn eq(&self, other: &Value) -> bool {
        match (self, other) {
            (&Value::Int(ref a), &Value::Int(ref b)) => a.eq(b),
            (&Value::Float(ref a), &Value::Float(ref b)) => a.eq(b),
            (&Value::Str(ref a), &Value::Str(ref b)) => a.eq(b),
            (&Value::Array(ref a), &Value::Array(ref b)) => a.eq(b),
            (&Value::Hash(ref a), &Value::Hash(ref b)) => a.eq(b),
            (&Value::Obj(ref a), &Value::Obj(ref b)) => false,
            (&Value::Func(ref a), &Value::Func(ref b)) => false,
            _ => false,
        }
    }
}

impl fmt::Debug for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Value::Int(ref v) => write!(f, "{}", v),
            Value::Float(ref v) => write!(f, "{}", v),
            Value::Str(ref v) => write!(f, "{:?}", ops::to_string_limited(v)),
            Value::Array(ref v) => {
                let mut list = f.debug_list();
                for (i, item) in v.iter().enumerate() {
                    list.entry(item);
                    if i >= MAX_DEBUG_ARRAY_LENGTH {
                        list.entry(&"...");
                        break;
                    }
                }
                list.finish()
            },
            Value::Hash(ref hash) => {
                let mut map = f.debug_map();
                let i = 0;
                for (k, v) in hash {
                    map.entry(k, v);
                    if i >= MAX_DEBUG_ARRAY_LENGTH {
                        map.entry(&"...", &"...");
                        break;
                    }
                }
                map.finish()
            },
            Value::Obj(_) => write!(f, "Object"),
            Value::Func(_) => write!(f, "Function"),
        }
    }
}

impl Value {
    /// If possible, returns this value represented as integer.
    pub fn int(self) -> RuntimeResult<i64> {
        Ok(match self {
            Value::Int(v) => v,
            Value::Float(v) => return ops::float_to_int(v),
            Value::Str(v) => {
                match ops::parse_as_numeric(&v) {
                    Ok(ops::ParseAsNumericResult::Int(v)) => v,
                    Ok(ops::ParseAsNumericResult::Float(v)) => try!(ops::float_to_int(v)),
                    Err(e) => return Err(e),
                }
            },
            Value::Array(_) => return Err(RuntimeError::ImpossibleCast {
                target: CastTarget::Int,
                reason: CastError::Array,
            }),
            Value::Hash(_) => return Err(RuntimeError::ImpossibleCast {
                target: CastTarget::Int,
                reason: CastError::Hash,
            }),
            Value::Obj(_) => return Err(RuntimeError::ImpossibleCast {
                target: CastTarget::Int,
                reason: CastError::Object,
            }),
            Value::Func(_) => return Err(RuntimeError::ImpossibleCast {
                target: CastTarget::Int,
                reason: CastError::Function,
            }),
        })
    }
}

pub trait Object {
    fn property_error(&self, name: &str) -> RuntimeError {
        RuntimeError::ObjectHasNoProperty(name.into())
    }

    fn method_error(&self, name: &str) -> RuntimeError {
        RuntimeError::ObjectHasNoMethod(name.into())
    }

    fn get(&self, name: &str) -> RuntimeResult<Value> {
        Err(self.property_error(name))
    }

    fn set(&mut self, name: &str, value: Value) -> RuntimeResult<()> {
        Err(self.property_error(name))
    }

    fn call(&mut self, name: &str, values: &[Value]) -> RuntimeResult<Value> {
        Err(self.method_error(name))
    }
}

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

    struct Point {
        x: i64,
        y: i64,
    }

    impl Object for Point {
        fn get(&self, name: &str) -> RuntimeResult<Value> {
            Ok(match name {
                "x" => Value::Int(self.x),
                "y" => Value::Int(self.y),
                _ => return Err(self.property_error(name)),
            })
        }

        fn set(&mut self, name: &str, value: Value) -> RuntimeResult<()> {
            Ok(match name {
                "x" => self.x = try!(value.int()),
                "y" => self.y = try!(value.int()),
                _ => return Err(self.property_error(name)),
            })
        }
    }

    #[test]
    fn object_getters_and_setters() {
        let mut point = Point { x: 12, y: 13 };
        assert_eq!(point.get("x").ok().unwrap(), Value::Int(12));
        assert_eq!(point.get("y").ok().unwrap(), Value::Int(13));

        point.set("x", Value::Int(42));
        point.set("y", Value::Int(43));
        assert_eq!(point.get("x").ok().unwrap(), Value::Int(42));
        assert_eq!(point.get("y").ok().unwrap(), Value::Int(43));
    }

    #[test]
    fn object_setter_can_convert_values() {
        let mut point = Point { x: 12, y: 13 };

        point.set("x", Value::Str("48".into()));
        assert_eq!(point.get("x").ok().unwrap(), Value::Int(48));
    }
}
<commit_msg>Use correct constant for hash length.<commit_after>use std::fmt;
use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashMap;
use error::{ RuntimeError, RuntimeResult, CastError, CastTarget };

pub mod ops;

const MAX_DEBUG_STRING_LENGTH: usize = 128;
const MAX_DEBUG_ARRAY_LENGTH: usize = 4;
const MAX_DEBUG_HASH_LENGTH: usize = 4;

#[derive(Hash, PartialEq, Eq, PartialOrd)]
pub enum HashKey {
    Int(i64),
    Str(String),
}

impl fmt::Debug for HashKey {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            HashKey::Int(ref v) => write!(f, "{}", v),
            HashKey::Str(ref v) => write!(f, "{:?}", v),
        }
    }
}

pub enum Value {
    Int(i64),
    Float(f64),
    Str(String),
    Array(Vec<Value>),
    Hash(HashMap<HashKey, Value>),
    Obj(Rc<RefCell<Object>>),
    Func(Rc<for<'r> Fn(&'r [Value]) -> Option<Value> >)
}

impl PartialEq for Value {
    fn eq(&self, other: &Value) -> bool {
        match (self, other) {
            (&Value::Int(ref a), &Value::Int(ref b)) => a.eq(b),
            (&Value::Float(ref a), &Value::Float(ref b)) => a.eq(b),
            (&Value::Str(ref a), &Value::Str(ref b)) => a.eq(b),
            (&Value::Array(ref a), &Value::Array(ref b)) => a.eq(b),
            (&Value::Hash(ref a), &Value::Hash(ref b)) => a.eq(b),
            (&Value::Obj(ref a), &Value::Obj(ref b)) => false,
            (&Value::Func(ref a), &Value::Func(ref b)) => false,
            _ => false,
        }
    }
}

impl fmt::Debug for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Value::Int(ref v) => write!(f, "{}", v),
            Value::Float(ref v) => write!(f, "{}", v),
            Value::Str(ref v) => write!(f, "{:?}", ops::to_string_limited(v)),
            Value::Array(ref v) => {
                let mut list = f.debug_list();
                for (i, item) in v.iter().enumerate() {
                    list.entry(item);
                    if i >= MAX_DEBUG_ARRAY_LENGTH {
                        list.entry(&"...");
                        break;
                    }
                }
                list.finish()
            },
            Value::Hash(ref hash) => {
                let mut map = f.debug_map();
                let i = 0;
                for (k, v) in hash {
                    map.entry(k, v);
                    if i >= MAX_DEBUG_HASH_LENGTH {
                        map.entry(&"...", &"...");
                        break;
                    }
                }
                map.finish()
            },
            Value::Obj(_) => write!(f, "Object"),
            Value::Func(_) => write!(f, "Function"),
        }
    }
}

impl Value {
    /// If possible, returns this value represented as integer.
    pub fn int(self) -> RuntimeResult<i64> {
        Ok(match self {
            Value::Int(v) => v,
            Value::Float(v) => return ops::float_to_int(v),
            Value::Str(v) => {
                match ops::parse_as_numeric(&v) {
                    Ok(ops::ParseAsNumericResult::Int(v)) => v,
                    Ok(ops::ParseAsNumericResult::Float(v)) => try!(ops::float_to_int(v)),
                    Err(e) => return Err(e),
                }
            },
            Value::Array(_) => return Err(RuntimeError::ImpossibleCast {
                target: CastTarget::Int,
                reason: CastError::Array,
            }),
            Value::Hash(_) => return Err(RuntimeError::ImpossibleCast {
                target: CastTarget::Int,
                reason: CastError::Hash,
            }),
            Value::Obj(_) => return Err(RuntimeError::ImpossibleCast {
                target: CastTarget::Int,
                reason: CastError::Object,
            }),
            Value::Func(_) => return Err(RuntimeError::ImpossibleCast {
                target: CastTarget::Int,
                reason: CastError::Function,
            }),
        })
    }
}

pub trait Object {
    fn property_error(&self, name: &str) -> RuntimeError {
        RuntimeError::ObjectHasNoProperty(name.into())
    }

    fn method_error(&self, name: &str) -> RuntimeError {
        RuntimeError::ObjectHasNoMethod(name.into())
    }

    fn get(&self, name: &str) -> RuntimeResult<Value> {
        Err(self.property_error(name))
    }

    fn set(&mut self, name: &str, value: Value) -> RuntimeResult<()> {
        Err(self.property_error(name))
    }

    fn call(&mut self, name: &str, values: &[Value]) -> RuntimeResult<Value> {
        Err(self.method_error(name))
    }
}

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

    struct Point {
        x: i64,
        y: i64,
    }

    impl Object for Point {
        fn get(&self, name: &str) -> RuntimeResult<Value> {
            Ok(match name {
                "x" => Value::Int(self.x),
                "y" => Value::Int(self.y),
                _ => return Err(self.property_error(name)),
            })
        }

        fn set(&mut self, name: &str, value: Value) -> RuntimeResult<()> {
            Ok(match name {
                "x" => self.x = try!(value.int()),
                "y" => self.y = try!(value.int()),
                _ => return Err(self.property_error(name)),
            })
        }
    }

    #[test]
    fn object_getters_and_setters() {
        let mut point = Point { x: 12, y: 13 };
        assert_eq!(point.get("x").ok().unwrap(), Value::Int(12));
        assert_eq!(point.get("y").ok().unwrap(), Value::Int(13));

        point.set("x", Value::Int(42));
        point.set("y", Value::Int(43));
        assert_eq!(point.get("x").ok().unwrap(), Value::Int(42));
        assert_eq!(point.get("y").ok().unwrap(), Value::Int(43));
    }

    #[test]
    fn object_setter_can_convert_values() {
        let mut point = Point { x: 12, y: 13 };

        point.set("x", Value::Str("48".into()));
        assert_eq!(point.get("x").ok().unwrap(), Value::Int(48));
    }
}
<|endoftext|>


<commit_before>//! Provides types and functions related to working with SQLite
//!
//! Much of this module is re-exported from database agnostic locations.
//! However, if you are writing code specifically to extend Diesel on
//! SQLite, you may need to work with this module directly.

mod backend;
mod connection;
mod types;

pub mod query_builder;

pub use self::backend::{Sqlite, SqliteType};
pub use self::connection::SqliteConnection;
pub use self::query_builder::SqliteQueryBuilder;

/// Trait for the implementation of a SQLite aggregate function
///
/// This trait is to be used in conjunction with the `sql_function!`
/// macro for defining a custom SQLite aggregate function. See
/// the documentation [there](../../diesel_derives/macro.sql_function_proc.html) for details.
pub trait SqliteAggregateFunction<Args>: Default {
    /// The result type of the SQLite aggregate function
    type Output;

    /// The `step()` method is called once for every record of the query
    fn step(&mut self, args: Args);
    /// After the last row has been processed, the `finalize()` method is
    /// called to compute the result of the aggregate function. If no rows
    /// were processed, `finalize()` is not called and `None` is returned
    /// instead
    fn finalize(self) -> Self::Output;
}
<commit_msg>Update link to sql_function in documentation<commit_after>//! Provides types and functions related to working with SQLite
//!
//! Much of this module is re-exported from database agnostic locations.
//! However, if you are writing code specifically to extend Diesel on
//! SQLite, you may need to work with this module directly.

mod backend;
mod connection;
mod types;

pub mod query_builder;

pub use self::backend::{Sqlite, SqliteType};
pub use self::connection::SqliteConnection;
pub use self::query_builder::SqliteQueryBuilder;

/// Trait for the implementation of a SQLite aggregate function
///
/// This trait is to be used in conjunction with the `sql_function!`
/// macro for defining a custom SQLite aggregate function. See
/// the documentation [there](../prelude/macro.sql_function.html) for details.
pub trait SqliteAggregateFunction<Args>: Default {
    /// The result type of the SQLite aggregate function
    type Output;

    /// The `step()` method is called once for every record of the query
    fn step(&mut self, args: Args);
    /// After the last row has been processed, the `finalize()` method is
    /// called to compute the result of the aggregate function. If no rows
    /// were processed, `finalize()` is not called and `None` is returned
    /// instead
    fn finalize(self) -> Self::Output;
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

#[macro_use]
extern crate quick_error;
extern crate regex;
extern crate toml;
extern crate semver;
extern crate clap;

use std::process::exit;

use clap::{App, ArgMatches, SubCommand};
use semver::Identifier;

mod config;
mod error;
mod cmd;
mod git;
mod cargo;

fn execute(args: &ArgMatches) -> Result<i32, error::FatalError> {
    let dry_run = args.occurrences_of("dry-run") > 0;
    let sign = args.occurrences_of("sign") > 0;

    // STEP 0: Check if working directory is clean
    if !try!(git::status()) {
        println!("Uncommitted changes detected, please commit before release");
        if !dry_run {
            return Ok(101);
        }
    }

    // STEP 1: Read version from Cargo.toml and remove
    let result = try!(config::parse_cargo_config());

    let mut version = result.get("package")
                            .and_then(|f| f.as_table())
                            .and_then(|f| f.get("version"))
                            .and_then(|f| f.as_str())
                            .and_then(|f| config::parse_version(f).ok())
                            .unwrap();

    // STEP 2: update current version, save and commit
    let mut need_commit = false;
    match args.value_of("level") {
        Some(level) => {
            match level {
                "major" => {
                    version.increment_major();
                    need_commit = true;
                }
                "minor" => {
                    version.increment_minor();
                    need_commit = true
                }
                "patch" => {
                    if !version.is_prerelease() {
                        version.increment_patch();
                    } else {
                        version.pre.clear();
                    }
                    need_commit = true
                }
                _ => {
                    panic!("Invalid level: {}", level);
                }
            }
        }
        None => {
            if version.is_prerelease() {
                version.pre.clear();
                need_commit = true;
            }
        }
    }

    if need_commit {
        let new_version_string = version.to_string();
        if !dry_run {
            try!(config::rewrite_cargo_version(&new_version_string));
        }

        let commit_msg = format!("(cargo-release) version {}", new_version_string);
        if !dry_run {
            if !try!(git::commit_all(&commit_msg, sign)) {
                // commit failed, abort release
                return Ok(102);
            }
        } else {
            println!("{}", commit_msg);
        }
    }

    // STEP 3: cargo publish
    if !dry_run {
        if !try!(cargo::publish()) {
            return Ok(103);
        }
    }

    // STEP 4: Tag
    let root = try!(git::top_level());
    let rel_path = try!(cmd::relative_path_for(&root));

    let current_version = version.to_string();
    let tag_name = rel_path.clone().map_or_else(|| current_version.clone(),
                                                |x| format!("{}-{}", x, current_version));

    let tag_message = format!("(cargo-release) {} version {}",
                              rel_path.unwrap_or("".to_owned()),
                              current_version);
    if !dry_run {
        if !try!(git::tag(&tag_name, &tag_message, sign)) {
            // tag failed, abort release
            return Ok(104);
        }
    }

    // STEP 5: bump version
    version.increment_patch();
    version.pre.push(Identifier::AlphaNumeric("pre".to_owned()));
    println!("Starting next development cycle {}", version);
    let updated_version_string = version.to_string();
    if !dry_run {
        try!(config::rewrite_cargo_version(&updated_version_string));
    }
    let commit_msg = format!("(cargo-release) start next development cycle {}",
                             updated_version_string);
    if !dry_run {
        if !try!(git::commit_all(&commit_msg, sign)) {
            return Ok(105);
        }
    }

    // STEP 6: git push
    if !dry_run {
        if !try!(git::push()) {
            return Ok(106);
        }
    }

    Ok(0)
}

static USAGE: &'static str = "-l, --level=[level] 'Release level: bumpping major|minor|patch \
                              version on release or removing prerelease extensions by default'
                    \
                              [sign]... --sign 'Sign git commit and tag'
                    \
                              [dry-run]... --dry-run 'Donot actually change anything.'";

fn main() {
    let matches = App::new("cargo release")
                      .subcommand(SubCommand::with_name("release")
                                      .version(env!("CARGO_PKG_VERSION"))
                                      .author("Ning Sun <sunng@about.me>")
                                      .about("Cargo subcommand for you to smooth your release \
                                              process.")
                                      .args_from_usage(USAGE))
                      .get_matches();

    if let Some(ref release_matches) = matches.subcommand_matches("release") {
        match execute(release_matches) {
            Ok(code) => exit(code),
            Err(e) => {
                println!("Fatal: {}", e);
                exit(128);
            }
        }
    }
}
<commit_msg>(feat) tag prefix [#1]<commit_after>#![allow(dead_code)]

#[macro_use]
extern crate quick_error;
extern crate regex;
extern crate toml;
extern crate semver;
extern crate clap;

use std::process::exit;

use clap::{App, ArgMatches, SubCommand};
use semver::Identifier;

mod config;
mod error;
mod cmd;
mod git;
mod cargo;

fn execute(args: &ArgMatches) -> Result<i32, error::FatalError> {
    let dry_run = args.occurrences_of("dry-run") > 0;
    let sign = args.occurrences_of("sign") > 0;

    // STEP 0: Check if working directory is clean
    if !try!(git::status()) {
        println!("Uncommitted changes detected, please commit before release");
        if !dry_run {
            return Ok(101);
        }
    }

    // STEP 1: Read version from Cargo.toml and remove
    let result = try!(config::parse_cargo_config());

    let mut version = result.get("package")
                            .and_then(|f| f.as_table())
                            .and_then(|f| f.get("version"))
                            .and_then(|f| f.as_str())
                            .and_then(|f| config::parse_version(f).ok())
                            .unwrap();

    // STEP 2: update current version, save and commit
    let mut need_commit = false;
    match args.value_of("level") {
        Some(level) => {
            match level {
                "major" => {
                    version.increment_major();
                    need_commit = true;
                }
                "minor" => {
                    version.increment_minor();
                    need_commit = true
                }
                "patch" => {
                    if !version.is_prerelease() {
                        version.increment_patch();
                    } else {
                        version.pre.clear();
                    }
                    need_commit = true
                }
                _ => {
                    panic!("Invalid level: {}", level);
                }
            }
        }
        None => {
            if version.is_prerelease() {
                version.pre.clear();
                need_commit = true;
            }
        }
    }

    if need_commit {
        let new_version_string = version.to_string();
        if !dry_run {
            try!(config::rewrite_cargo_version(&new_version_string));
        }

        let commit_msg = format!("(cargo-release) version {}", new_version_string);
        if !dry_run {
            if !try!(git::commit_all(&commit_msg, sign)) {
                // commit failed, abort release
                return Ok(102);
            }
        } else {
            println!("{}", commit_msg);
        }
    }

    // STEP 3: cargo publish
    if !dry_run {
        if !try!(cargo::publish()) {
            return Ok(103);
        }
    }

    // STEP 4: Tag
    let root = try!(git::top_level());
    let rel_path = try!(cmd::relative_path_for(&root));
    let tag_prefix = args.value_of("tag-prefix").or(rel_path.as_ref().map(|t| t.as_ref()));

    let current_version = version.to_string();
    let tag_name = tag_prefix.as_ref().map_or_else(|| current_version.clone(),
                                                   |x| format!("{}{}", x, current_version));

    let tag_message = format!("(cargo-release) {} version {}",
                              tag_prefix.unwrap_or(""),
                              current_version);
    if !dry_run {
        if !try!(git::tag(&tag_name, &tag_message, sign)) {
            // tag failed, abort release
            return Ok(104);
        }
    }

    // STEP 5: bump version
    version.increment_patch();
    version.pre.push(Identifier::AlphaNumeric("pre".to_owned()));
    println!("Starting next development cycle {}", version);
    let updated_version_string = version.to_string();
    if !dry_run {
        try!(config::rewrite_cargo_version(&updated_version_string));
    }
    let commit_msg = format!("(cargo-release) start next development cycle {}",
                             updated_version_string);
    if !dry_run {
        if !try!(git::commit_all(&commit_msg, sign)) {
            return Ok(105);
        }
    }

    // STEP 6: git push
    if !dry_run {
        if !try!(git::push()) {
            return Ok(106);
        }
    }

    Ok(0)
}

static USAGE: &'static str = "-l, --level=[level] 'Release level: bumpping major|minor|patch \
                              version on release or removing prerelease extensions by default'
                    \
                              [sign]... --sign 'Sign git commit and tag'
                    \
                              [dry-run]... --dry-run 'Donot actually change anything.'
                              --tag-prefix=[tag-prefix] 'Prefix of git tag'";

fn main() {
    let matches = App::new("cargo release")
                      .subcommand(SubCommand::with_name("release")
                                      .version(env!("CARGO_PKG_VERSION"))
                                      .author("Ning Sun <sunng@about.me>")
                                      .about("Cargo subcommand for you to smooth your release \
                                              process.")
                                      .args_from_usage(USAGE))
                      .get_matches();

    if let Some(ref release_matches) = matches.subcommand_matches("release") {
        match execute(release_matches) {
            Ok(code) => exit(code),
            Err(e) => {
                println!("Fatal: {}", e);
                exit(128);
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate kernel32;
extern crate user32;
extern crate winapi;
extern crate libc;
extern crate gdi32;

use winapi::windef::HWND;
use winapi::windef::HMENU;
use winapi::windef::HBRUSH;
use winapi::minwindef::HINSTANCE;

use winapi::minwindef::UINT;
use winapi::minwindef::DWORD;
use winapi::minwindef::WPARAM;
use winapi::minwindef::LPARAM;
use winapi::minwindef::LRESULT;
use winapi::winnt::LPCWSTR;

use winapi::winuser::WS_OVERLAPPEDWINDOW;
use winapi::winuser::WS_VISIBLE;
use winapi::winuser::WNDCLASSW;
use winapi::winuser::CF_BITMAP;

use std::os::windows::ffi::OsStrExt;
use std::ffi::OsStr;

const g_class_name: &'static str = "winshot";

// Rectangle represents screen coordinates
struct Rectangle {
	x: i32,
	y: i32,
	x2: i32,
	y2: i32,
}

// convert normal string to wide string
#[allow(dead_code)]
fn to_wstring(str: &str) -> *const u16 {
	let v: Vec<u16> = OsStr::new(str).encode_wide() . chain(Some(0).into_iter()).collect();
	v.as_ptr()
}

// This is our window message handler function. Currently,
// it only processes the WM_DESTROY message to exit our window properly on close event.
#[allow(dead_code)]
pub unsafe extern "system" fn window_proc(h_wnd: HWND, msg: UINT, w_param: WPARAM, l_param: LPARAM) -> LRESULT {
	if msg == winapi::winuser::WM_DESTROY {
		user32::PostQuitMessage(0);
	} else if msg == winapi::winuser::WM_MOUSEMOVE {
		return 0 as LRESULT;
	} else if msg == winapi::winuser::WM_LBUTTONDOWN {
		return 0 as LRESULT;
	} else if msg == winapi::winuser::WM_LBUTTONUP {
		return 0 as LRESULT;
	} else {
		return user32::DefWindowProcW(h_wnd, msg, w_param, l_param);
	}
}

// The following function hides the Console Window since we are building a GUI application.
#[allow(dead_code)]
fn hide_console_window() {
	let window = unsafe {
		kernel32::GetConsoleWindow()
	};

	if window != std::ptr::null_mut() {
		unsafe {
			user32::ShowWindow(window, winapi::SW_HIDE)
		};
	}
}

fn normalize_coords(rect: Rectangle) -> Rectangle {
    let Rectangle{mut x, mut y, mut x2, mut y2} = rect;

    if x > x2 {
        let tmp = x;
        x = x2;
        x2 = tmp;
    }
    if y > y2 {
        let tmp = y;
        y = y2;
        y2 = tmp;
    }

    Rectangle{x: x, y: y, x2: x2, y2: y2}
}

fn get_screen_rect() -> Rectangle {
	Rectangle{
		x /* left */: user32::GetSystemMetrics(winapi::winuser::SM_XVIRTUALSCREEN),
		y /* top */: user32::GetSystemMetrics(winapi::winuser::SM_YVIRTUALSCREEN),
		x2 /* right */: user32::GetSystemMetrics(winapi::winuser::SM_CXVIRTUALSCREEN) + user32::GetSystemMetrics(winapi::winuser::SM_XVIRTUALSCREEN),
		y2 /* bottom */: user32::GetSystemMetrics(winapi::winuser::SM_CYVIRTUALSCREEN) + user32::GetSystemMetrics(winapi::winuser::SM_CYVIRTUALSCREEN),
	}
}

fn capture_screen_clipboard(hwnd: HWND, mut rect: Rectangle) -> bool {
	// normalize coordinates
	let rect = normalize_coords(rect);
	let w = rect.x2 - rect.x;
	let h = rect.y2 - rect.y;

	let screen_dc = user32::GetDC(0 as HWND);
	let shot_dc = gdi32::CreateCompatibleDC(screen_dc);
	let shot_bitmap = gdi32::CreateCompatibleBitmap(screen_dc, w, h);
	let old_obj = gdi32::SelectObject(shot_dc, shot_bitmap);

	if !gdi32::BitBlt(shot_dc, 0, 0, w, h, screen_dc, rect.x, rect.y, 0 as DWORD) {
		println!("{:?}", "BitBlt failed? Perhaps.");
		false
	}

	let mut ret = false;
	if user32::OpenClipboard(hwnd) {
		if user32::EmptyClipboard() {
			if user32::SetClipboardData(CF_BITMAP, shot_bitmap) {
				ret = true;
			}
			user32::CloseClipboard();
		}
	} else {
		println!("{:?}", "could not open clipboard");
	}

	// Clean up
	gdi32::DeleteDC(shot_dc);
	gdi32::DeleteDC(screen_dc);
	gdi32::SelectObject(shot_dc, old_obj);

	return ret;
}

fn main() {
	unsafe {
		let hInstance = kernel32::GetModuleHandleW(0 as LPCWSTR);
		let m_class_name = to_wstring(g_class_name);
		let wnd = WNDCLASSW {
			hInstance: hInstance,
			lpszClassName: m_class_name,
			lpszMenuName: 0 as LPCWSTR,
			lpfnWndProc: Some(window_proc),
			cbClsExtra: 0,
			cbWndExtra: 0,
			style: winapi::winuser::CS_HREDRAW | winapi::winuser::CS_VREDRAW,
			hbrBackground: 0,
			hCursor: user32::LoadCursorW(0 as HINSTANCE, winapi::winuser::IDC_CROSS),
			hIcon: user32::LoadIconW(0 as HINSTANCE, winapi::winuser::IDI_APPLICATION),
		};

		user32::RegisterClassW(&wnd);
		let rect = get_screen_rect();
		let exstyle = winapi::winuser::WS_EX_TRANSPARENT;
		let style = winapi::winuser::WS_POPUP;

		let win = user32::CreateWindowExW(exstyle,
			m_class_name.as_ptr() as *mut _,
			m_class_name.as_ptr() as *mut _,
			style,
			// dimensions
			0, 0, rect.x2, rect.y2,
			0, // no parent
			0 as HWND, // no menu
			hInstance, // module_instance
			0 as LPARAM,
		);

		user32::ShowWindow(win, winapi::winuser::SW_SHOW);
		user32::ShowWindow(win, winapi::winuser::SW_SHOWMAXIMIZED);
		user32::SetForegroundWindow(win);

		capture_screen_clipboard(win, Rectangle{
			x: 0,
			y: 0,
			x2: 200,
			y2: 200,
		});
		user32::DestroyWindow(win);
	}
}

// fn main() {
// 	// Here our unsafe code goes
// 	unsafe {
// 		// First we hide the console window
// 		hide_console_window();

// 		// Then we initialize the WNDCLASS structure
// 		let m_class_name = to_wstring(g_class_name);
// 		let wnd = WNDCLASSW {
// 			hInstance: 0 as HINSTANCE,
// 			lpszClassName = m_class_name,
// 			lpszMenuName: 0 as LPCWSTR,
// 			lpfnWndProc: Some(window_proc),

// 			style: winapi::winuser::CS_HREDRAW | winapi::winuser::CS_VREDRAW,

// 			cbClsExtra: 0,
// 			cbWndExtra: 0,

// 			hIcon: user32::LoadIconW(0 as HINSTANCE, winapi::winuser::IDI_APPLICATION),
// 			hCursor: user32::LoadCursorW(0 as HINSTANCE, winapi::winuser::IDI_APPLICATION),
// 			hbrBackground: 16 as HBRUSH,

// 		};

// 		// Register our class
// 		user32::RegisterClassW(&wnd);

// 		let h_wnd_desktop = user32::GetDesktopWindow();

// 		user32::CreateWindowExA(0, "my_window".as_ptr() as *mut _,
// 			"Simple Window".as_ptr() as *mut _, WS_OVERLAPPEDWINDOW | WS_VISIBLE,
// 			0, 0, 400, 400, h_wnd_desktop, 0 as HMENU, 0 as HINSTANCE,
// 			std::ptr::null_mut());

// 		let mut msg = winapi::winuser::MSG {
// 			hwnd: 0 as HWND,
// 			message: 0 as UINT,
// 			wParam: 0 as WPARAM,
// 			lParam: 0 as LPARAM,
// 			time: 0 as DWORD,
// 			pt : winapi::windef::POINT{ x: 0, y: 0, },
// 		};

// 		// Kick off the application loop
// 		loop {
// 			let pm = user32::PeekMessageW(&mut msg, 0 as HWND, 0, 0, winapi::winuser::PM_REMOVE);

// 			if pm == 0 {
// 				continue;
// 			}

// 			if msg.message == winapi::winuser::WM_QUIT {
// 				break;
// 			}

// 			user32::TranslateMessage(&mut msg);
// 			user32::DispatchMessageW(&mut msg);
// 		}
// 	}
// }<commit_msg>other types?<commit_after>extern crate kernel32;
extern crate user32;
extern crate winapi;
extern crate libc;
extern crate gdi32;

use winapi::windef::HWND;
use winapi::windef::HMENU;
use winapi::windef::HBRUSH;
use winapi::minwindef::HINSTANCE;

use winapi::minwindef::UINT;
use winapi::minwindef::DWORD;
use winapi::minwindef::WPARAM;
use winapi::minwindef::LPARAM;
use winapi::minwindef::LRESULT;
use winapi::minwindef::BOOL;
use winapi::minwindef::TRUE;
use winapi::minwindef::FALSE;
use winapi::winnt::LPCWSTR;

use winapi::winuser::WS_OVERLAPPEDWINDOW;
use winapi::winuser::WS_VISIBLE;
use winapi::winuser::WNDCLASSW;
use winapi::winuser::CF_BITMAP;

use std::os::windows::ffi::OsStrExt;
use std::ffi::OsStr;

const g_class_name: &'static str = "winshot";

// Rectangle represents screen coordinates
struct Rectangle {
	x: i32,
	y: i32,
	x2: i32,
	y2: i32,
}

// convert normal string to wide string
#[allow(dead_code)]
fn to_wstring(str: &str) -> *const u16 {
	let v: Vec<u16> = OsStr::new(str).encode_wide() . chain(Some(0).into_iter()).collect();
	v.as_ptr()
}

// This is our window message handler function. Currently,
// it only processes the WM_DESTROY message to exit our window properly on close event.
#[allow(dead_code)]
pub unsafe extern "system" fn window_proc(h_wnd: HWND, msg: UINT, w_param: WPARAM, l_param: LPARAM) -> LRESULT {
	if msg == winapi::winuser::WM_DESTROY {
		user32::PostQuitMessage(0);
	} else if msg == winapi::winuser::WM_MOUSEMOVE {
		return 0 as LRESULT;
	} else if msg == winapi::winuser::WM_LBUTTONDOWN {
		return 0 as LRESULT;
	} else if msg == winapi::winuser::WM_LBUTTONUP {
		return 0 as LRESULT;
	} else {
		return user32::DefWindowProcW(h_wnd, msg, w_param, l_param);
	}
}

// The following function hides the Console Window since we are building a GUI application.
#[allow(dead_code)]
fn hide_console_window() {
	let window = unsafe {
		kernel32::GetConsoleWindow()
	};

	if window != std::ptr::null_mut() {
		unsafe {
			user32::ShowWindow(window, winapi::SW_HIDE)
		};
	}
}

// TODO figure out how the heck to use pointers
fn normalize_coords(rect: Rectangle) -> Rectangle {
    let Rectangle{mut x, mut y, mut x2, mut y2} = rect;

    if x > x2 {
        let tmp = x;
        x = x2;
        x2 = tmp;
    }
    if y > y2 {
        let tmp = y;
        y = y2;
        y2 = tmp;
    }

    Rectangle{x: x, y: y, x2: x2, y2: y2}
}

fn get_screen_rect() -> Rectangle {
	Rectangle{
		x /* left */: user32::GetSystemMetrics(winapi::winuser::SM_XVIRTUALSCREEN),
		y /* top */: user32::GetSystemMetrics(winapi::winuser::SM_YVIRTUALSCREEN),
		x2 /* right */: user32::GetSystemMetrics(winapi::winuser::SM_CXVIRTUALSCREEN) + user32::GetSystemMetrics(winapi::winuser::SM_XVIRTUALSCREEN),
		y2 /* bottom */: user32::GetSystemMetrics(winapi::winuser::SM_CYVIRTUALSCREEN) + user32::GetSystemMetrics(winapi::winuser::SM_CYVIRTUALSCREEN),
	}
}

fn capture_screen_clipboard(hwnd: HWND, mut rect: Rectangle) -> bool {
	// normalize coordinates
	let rect = normalize_coords(rect);
	let w = rect.x2 - rect.x;
	let h = rect.y2 - rect.y;

	let screen_dc = user32::GetDC(0 as HWND);
	let shot_dc = gdi32::CreateCompatibleDC(screen_dc);
	let shot_bitmap = gdi32::CreateCompatibleBitmap(screen_dc, w, h);
	let old_obj = gdi32::SelectObject(shot_dc, shot_bitmap);

	if !gdi32::BitBlt(shot_dc, 0, 0, w, h, screen_dc, rect.x, rect.y, 0 as DWORD) {
		println!("{:?}", "BitBlt failed? Perhaps.");
		false
	}

	let mut ret = false;
	if user32::OpenClipboard(hwnd) as BOOL == TRUE {
		if user32::EmptyClipboard() as BOOL == TRUE {
			if user32::SetClipboardData(CF_BITMAP, shot_bitmap) as BOOL == TRUE {
				ret = true;
			}
			user32::CloseClipboard();
		}
	} else {
		println!("{:?}", "could not open clipboard");
	}

	// Clean up
	gdi32::DeleteDC(shot_dc);
	gdi32::DeleteDC(screen_dc);
	gdi32::SelectObject(shot_dc, old_obj);

	return ret;
}

fn main() {
	unsafe {
		let hInstance = kernel32::GetModuleHandleW(0 as LPCWSTR);
		let m_class_name = to_wstring(g_class_name);
		let wnd = WNDCLASSW {
			hInstance: hInstance,
			lpszClassName: m_class_name,
			lpszMenuName: 0 as LPCWSTR,
			lpfnWndProc: Some(window_proc),
			cbClsExtra: 0,
			cbWndExtra: 0,
			style: winapi::winuser::CS_HREDRAW | winapi::winuser::CS_VREDRAW,
			hbrBackground: 0,
			hCursor: user32::LoadCursorW(0 as HINSTANCE, winapi::winuser::IDC_CROSS),
			hIcon: user32::LoadIconW(0 as HINSTANCE, winapi::winuser::IDI_APPLICATION),
		};

		user32::RegisterClassW(&wnd);
		let rect = get_screen_rect();
		let exstyle = winapi::winuser::WS_EX_TRANSPARENT;
		let style = winapi::winuser::WS_POPUP;

		let win = user32::CreateWindowExW(exstyle,
			m_class_name.as_ptr() as *mut _,
			m_class_name.as_ptr() as *mut _,
			style,
			// dimensions
			0, 0, rect.x2, rect.y2,
			0, // no parent
			0 as HWND, // no menu
			hInstance, // module_instance
			0 as LPARAM,
		);

		user32::ShowWindow(win, winapi::winuser::SW_SHOW);
		user32::ShowWindow(win, winapi::winuser::SW_SHOWMAXIMIZED);
		user32::SetForegroundWindow(win);

		capture_screen_clipboard(win, Rectangle{
			x: 0,
			y: 0,
			x2: 200,
			y2: 200,
		});
		user32::DestroyWindow(win);
	}
}

// fn main() {
// 	// Here our unsafe code goes
// 	unsafe {
// 		// First we hide the console window
// 		hide_console_window();

// 		// Then we initialize the WNDCLASS structure
// 		let m_class_name = to_wstring(g_class_name);
// 		let wnd = WNDCLASSW {
// 			hInstance: 0 as HINSTANCE,
// 			lpszClassName = m_class_name,
// 			lpszMenuName: 0 as LPCWSTR,
// 			lpfnWndProc: Some(window_proc),

// 			style: winapi::winuser::CS_HREDRAW | winapi::winuser::CS_VREDRAW,

// 			cbClsExtra: 0,
// 			cbWndExtra: 0,

// 			hIcon: user32::LoadIconW(0 as HINSTANCE, winapi::winuser::IDI_APPLICATION),
// 			hCursor: user32::LoadCursorW(0 as HINSTANCE, winapi::winuser::IDI_APPLICATION),
// 			hbrBackground: 16 as HBRUSH,

// 		};

// 		// Register our class
// 		user32::RegisterClassW(&wnd);

// 		let h_wnd_desktop = user32::GetDesktopWindow();

// 		user32::CreateWindowExA(0, "my_window".as_ptr() as *mut _,
// 			"Simple Window".as_ptr() as *mut _, WS_OVERLAPPEDWINDOW | WS_VISIBLE,
// 			0, 0, 400, 400, h_wnd_desktop, 0 as HMENU, 0 as HINSTANCE,
// 			std::ptr::null_mut());

// 		let mut msg = winapi::winuser::MSG {
// 			hwnd: 0 as HWND,
// 			message: 0 as UINT,
// 			wParam: 0 as WPARAM,
// 			lParam: 0 as LPARAM,
// 			time: 0 as DWORD,
// 			pt : winapi::windef::POINT{ x: 0, y: 0, },
// 		};

// 		// Kick off the application loop
// 		loop {
// 			let pm = user32::PeekMessageW(&mut msg, 0 as HWND, 0, 0, winapi::winuser::PM_REMOVE);

// 			if pm == 0 {
// 				continue;
// 			}

// 			if msg.message == winapi::winuser::WM_QUIT {
// 				break;
// 			}

// 			user32::TranslateMessage(&mut msg);
// 			user32::DispatchMessageW(&mut msg);
// 		}
// 	}
// }<|endoftext|>


<commit_before>/// Easy to use Let's Encrypt client to issue and renew TLS certs

extern crate acme_client;
extern crate clap;
extern crate env_logger;

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

fn main() {
    let _ = env_logger::init();
    let matches = App::new(env!("CARGO_PKG_NAME"))
        .version(env!("CARGO_PKG_VERSION"))
        .about(env!("CARGO_PKG_DESCRIPTION"))
        .usage("letsencrypt-rs sign -D example.org -P /var/www -K domain.key -o domain.crt\
                \n    letsencrypt-rs revoke -K user_or_domain.key -C signed.crt")
        .subcommand(SubCommand::with_name("sign")
            .about("Signs a certificate")
            .display_order(1)
            .arg(Arg::with_name("USER_KEY_PATH")
                .help("User private key path to use it in account registration.")
                .long("user-key")
                .short("U")
                .takes_value(true))
            .arg(Arg::with_name("DOMAIN_KEY_PATH")
                .help("Domain private key path to use it in CSR generation.")
                .short("K")
                .long("domain-key")
                .takes_value(true))
            .arg(Arg::with_name("DOMAIN")
                .help("Name of domain for identification. This option is required.")
                .short("D")
                .long("domain")
                .required(true)
                .takes_value(true))
            .arg(Arg::with_name("PUBLIC_DIR")
                .help("Directory to save ACME simple http challenge. This option is required.")
                .short("P")
                .long("public-dir")
                .required(true)
                .takes_value(true))
            .arg(Arg::with_name("EMAIL")
                .help("Contact email address (optional).")
                .short("E")
                .long("email")
                .takes_value(true))
            .arg(Arg::with_name("DOMAIN_CSR")
                .help("Path to domain certificate signing request.")
                .short("C")
                .long("domain-csr")
                .takes_value(true))
            .arg(Arg::with_name("SAVE_USER_KEY")
                .help("Path to save private user key.")
                .long("save-user-key")
                .short("u")
                .takes_value(true))
            .arg(Arg::with_name("SAVE_DOMAIN_KEY")
                .help("Path to save domain private key.")
                .short("k")
                .long("save-domain-key")
                .takes_value(true))
            .arg(Arg::with_name("SAVE_DOMAIN_CSR")
                .help("Path to save domain certificate signing request.")
                .long("save-csr")
                .short("S")
                .takes_value(true))
            .arg(Arg::with_name("SAVE_SIGNED_CERTIFICATE")
                .help("Path to save signed certificate. Default is STDOUT.")
                .short("o")
                .long("save-crt")
                .takes_value(true))
            .arg(Arg::with_name("BIT_LENGHT")
                .help("Bit length for CSR. Default is 2048.")
                .long("bit-length")
                .short("B")
                .takes_value(true))
            .arg(Arg::with_name("CHAIN")
                .help("Chains the signed certificate with Let's Encrypt Authority X3 \
                       (IdenTrust cross-signed) intermediate certificate.")
                .short("c")
                .long("chain")
                .takes_value(false)))
        .subcommand(SubCommand::with_name("revoke")
            .about("Revokes a signed certificate")
            .display_order(2)
            .arg(Arg::with_name("USER_KEY")
                .help("User or domain private key path.")
                .long("user-key")
                .short("K")
                .required(true)
                .takes_value(true))
            .arg(Arg::with_name("SIGNED_CRT")
                .help("Path to signed domain certificate to revoke.")
                .long("signed-crt")
                .short("C")
                .required(true)
                .takes_value(true)))
        .get_matches();

    let mut ac = AcmeClient::new().expect("Failed to create new AcmeClient");

    // sign certificate
    if let Some(matches) = matches.subcommand_matches("sign") {

        if let Some(csr_path) = matches.value_of("DOMAIN_CSR") {
            ac = ac.load_csr(csr_path).expect("Failed to load CSR");
        }

        if let Some(domain) = matches.value_of("DOMAIN") {
            ac = ac.set_domain(domain).expect("Failed to set domain")
        }

        if matches.is_present("CHAIN") {
            ac = ac.set_chain_url("https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem")
                .expect("Failed to set chain URL")
        }

        if let Some(bit_length) = matches.value_of("BIT_LENGTH") {
            ac = ac.set_bit_length(bit_length.parse().expect("Bit length must be a number"))
                .expect("Failed to set bit lenght");
        }

        if let Some(user_key_path) = matches.value_of("USER_KEY_PATH") {
            ac = ac.load_user_key(user_key_path).expect("Failed to load user key");
        }

        if let Some(domain_key_path) = matches.value_of("DOMAIN_KEY_PATH") {
            ac = ac.load_domain_key(domain_key_path).expect("Failed to load domain key");
        }

        if let Some(domain_crt_path) = matches.value_of("DOMAIN_CRT") {
            ac = ac.load_certificate(domain_crt_path)
                .expect("Failed to load signed domain certificate");
        }

        ac = ac.register_account(matches.value_of("EMAIL"))
            .and_then(|ac| ac.identify_domain())
            .and_then(|ac| ac.save_http_challenge_into(matches.value_of("PUBLIC_DIR").unwrap()))
            .and_then(|ac| ac.simple_http_validation())  // unwrap is fine here ~~~~^
            .and_then(|ac| ac.sign_certificate())        // PUBLIC_DIR is always required
            .expect("Failed to sign certificate");

        if let Some(path) = matches.value_of("SAVE_SIGNED_CERTIFICATE") {
            ac = ac.save_signed_certificate(path).expect("Failed to save signed certificate");
        } else {
            use std::io::stdout;
            ac = ac.write_signed_certificate(&mut stdout())
                .expect("Failed to write signed certificate");
        }

        if let Some(path) = matches.value_of("SAVE_USER_KEY") {
            ac = ac.save_user_private_key(path).expect("Failed to save user private key");
        }

        if let Some(path) = matches.value_of("SAVE_DOMAIN_KEY") {
            ac.save_domain_private_key(path).expect("Failed to save domain private key");
        }
    }
    // revoke certificate
    else if let Some(matches) = matches.subcommand_matches("revoke") {
        ac = ac.load_user_key(matches.value_of("USER_KEY").unwrap())
            .expect("Failed to load user key");
        ac = ac.load_certificate(matches.value_of("SIGNED_CRT").unwrap())
            .expect("Failed to load signed domain certificate");
        ac.revoke_signed_certificate().expect("Failed to revoke certificate");
        println!("Certificate successfully revoked!");
    }
    // if none of them matches, show usage
    else {
        println!("{}", matches.usage());
    }
}
<commit_msg>Fix short value of SAVE_DOMAIN_KEY in usage<commit_after>/// Easy to use Let's Encrypt client to issue and renew TLS certs

extern crate acme_client;
extern crate clap;
extern crate env_logger;

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

fn main() {
    let _ = env_logger::init();
    let matches = App::new(env!("CARGO_PKG_NAME"))
        .version(env!("CARGO_PKG_VERSION"))
        .about(env!("CARGO_PKG_DESCRIPTION"))
        .usage("letsencrypt-rs sign -D example.org -P /var/www -k domain.key -o domain.crt\
                \n    letsencrypt-rs revoke -K user_or_domain.key -C signed.crt")
        .subcommand(SubCommand::with_name("sign")
            .about("Signs a certificate")
            .display_order(1)
            .arg(Arg::with_name("USER_KEY_PATH")
                .help("User private key path to use it in account registration.")
                .long("user-key")
                .short("U")
                .takes_value(true))
            .arg(Arg::with_name("DOMAIN_KEY_PATH")
                .help("Domain private key path to use it in CSR generation.")
                .short("K")
                .long("domain-key")
                .takes_value(true))
            .arg(Arg::with_name("DOMAIN")
                .help("Name of domain for identification. This option is required.")
                .short("D")
                .long("domain")
                .required(true)
                .takes_value(true))
            .arg(Arg::with_name("PUBLIC_DIR")
                .help("Directory to save ACME simple http challenge. This option is required.")
                .short("P")
                .long("public-dir")
                .required(true)
                .takes_value(true))
            .arg(Arg::with_name("EMAIL")
                .help("Contact email address (optional).")
                .short("E")
                .long("email")
                .takes_value(true))
            .arg(Arg::with_name("DOMAIN_CSR")
                .help("Path to domain certificate signing request.")
                .short("C")
                .long("domain-csr")
                .takes_value(true))
            .arg(Arg::with_name("SAVE_USER_KEY")
                .help("Path to save private user key.")
                .long("save-user-key")
                .short("u")
                .takes_value(true))
            .arg(Arg::with_name("SAVE_DOMAIN_KEY")
                .help("Path to save domain private key.")
                .short("k")
                .long("save-domain-key")
                .takes_value(true))
            .arg(Arg::with_name("SAVE_DOMAIN_CSR")
                .help("Path to save domain certificate signing request.")
                .long("save-csr")
                .short("S")
                .takes_value(true))
            .arg(Arg::with_name("SAVE_SIGNED_CERTIFICATE")
                .help("Path to save signed certificate. Default is STDOUT.")
                .short("o")
                .long("save-crt")
                .takes_value(true))
            .arg(Arg::with_name("BIT_LENGHT")
                .help("Bit length for CSR. Default is 2048.")
                .long("bit-length")
                .short("B")
                .takes_value(true))
            .arg(Arg::with_name("CHAIN")
                .help("Chains the signed certificate with Let's Encrypt Authority X3 \
                       (IdenTrust cross-signed) intermediate certificate.")
                .short("c")
                .long("chain")
                .takes_value(false)))
        .subcommand(SubCommand::with_name("revoke")
            .about("Revokes a signed certificate")
            .display_order(2)
            .arg(Arg::with_name("USER_KEY")
                .help("User or domain private key path.")
                .long("user-key")
                .short("K")
                .required(true)
                .takes_value(true))
            .arg(Arg::with_name("SIGNED_CRT")
                .help("Path to signed domain certificate to revoke.")
                .long("signed-crt")
                .short("C")
                .required(true)
                .takes_value(true)))
        .get_matches();

    let mut ac = AcmeClient::new().expect("Failed to create new AcmeClient");

    // sign certificate
    if let Some(matches) = matches.subcommand_matches("sign") {

        if let Some(csr_path) = matches.value_of("DOMAIN_CSR") {
            ac = ac.load_csr(csr_path).expect("Failed to load CSR");
        }

        if let Some(domain) = matches.value_of("DOMAIN") {
            ac = ac.set_domain(domain).expect("Failed to set domain")
        }

        if matches.is_present("CHAIN") {
            ac = ac.set_chain_url("https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem")
                .expect("Failed to set chain URL")
        }

        if let Some(bit_length) = matches.value_of("BIT_LENGTH") {
            ac = ac.set_bit_length(bit_length.parse().expect("Bit length must be a number"))
                .expect("Failed to set bit lenght");
        }

        if let Some(user_key_path) = matches.value_of("USER_KEY_PATH") {
            ac = ac.load_user_key(user_key_path).expect("Failed to load user key");
        }

        if let Some(domain_key_path) = matches.value_of("DOMAIN_KEY_PATH") {
            ac = ac.load_domain_key(domain_key_path).expect("Failed to load domain key");
        }

        if let Some(domain_crt_path) = matches.value_of("DOMAIN_CRT") {
            ac = ac.load_certificate(domain_crt_path)
                .expect("Failed to load signed domain certificate");
        }

        ac = ac.register_account(matches.value_of("EMAIL"))
            .and_then(|ac| ac.identify_domain())
            .and_then(|ac| ac.save_http_challenge_into(matches.value_of("PUBLIC_DIR").unwrap()))
            .and_then(|ac| ac.simple_http_validation())  // unwrap is fine here ~~~~^
            .and_then(|ac| ac.sign_certificate())        // PUBLIC_DIR is always required
            .expect("Failed to sign certificate");

        if let Some(path) = matches.value_of("SAVE_SIGNED_CERTIFICATE") {
            ac = ac.save_signed_certificate(path).expect("Failed to save signed certificate");
        } else {
            use std::io::stdout;
            ac = ac.write_signed_certificate(&mut stdout())
                .expect("Failed to write signed certificate");
        }

        if let Some(path) = matches.value_of("SAVE_USER_KEY") {
            ac = ac.save_user_private_key(path).expect("Failed to save user private key");
        }

        if let Some(path) = matches.value_of("SAVE_DOMAIN_KEY") {
            ac.save_domain_private_key(path).expect("Failed to save domain private key");
        }
    }
    // revoke certificate
    else if let Some(matches) = matches.subcommand_matches("revoke") {
        ac = ac.load_user_key(matches.value_of("USER_KEY").unwrap())
            .expect("Failed to load user key");
        ac = ac.load_certificate(matches.value_of("SIGNED_CRT").unwrap())
            .expect("Failed to load signed domain certificate");
        ac.revoke_signed_certificate().expect("Failed to revoke certificate");
        println!("Certificate successfully revoked!");
    }
    // if none of them matches, show usage
    else {
        println!("{}", matches.usage());
    }
}
<|endoftext|>