<commit_before>/* automatically generated by rust-bindgen */

#[repr(C)]
#[derive(Copy)]
pub struct Struct_zmq_msg_t {
    pub unknown: [c_uchar; 64usize],
}
impl ::std::clone::Clone for Struct_zmq_msg_t {
    fn clone(&self) -> Self { *self }
}
impl ::std::default::Default for Struct_zmq_msg_t {
    fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
pub type zmq_msg_t = Struct_zmq_msg_t;
pub type zmq_free_fn =
    unsafe extern "C" fn(data: *mut c_void,
                         hint: *mut c_void);
#[repr(C)]
#[derive(Copy)]
pub struct Struct_zmq_pollitem_t {
    pub socket: *mut c_void,
    #[cfg(target_os = "windows")]       // Need to fix this manually
    pub fd: ::libc::intptr_t,           // Windows Socket is defined as UINT_PTR
    #[cfg(not(target_os = "windows"))]
    pub fd: c_int,
    pub events: c_short,
    pub revents: c_short,
}
impl ::std::clone::Clone for Struct_zmq_pollitem_t {
    fn clone(&self) -> Self { *self }
}
impl ::std::default::Default for Struct_zmq_pollitem_t {
    fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
pub type zmq_pollitem_t = Struct_zmq_pollitem_t;
pub enum Struct_iovec { }
pub type zmq_thread_fn =
    unsafe extern "C" fn(arg1: *mut c_void);
extern "C" {
    pub fn zmq_errno() -> c_int;
    pub fn zmq_strerror(errnum: c_int)
     -> *const c_char;
    pub fn zmq_version(major: *mut c_int,
                       minor: *mut c_int,
                       patch: *mut c_int);
    pub fn zmq_ctx_new() -> *mut c_void;
    pub fn zmq_ctx_term(context: *mut c_void)
     -> c_int;
    pub fn zmq_ctx_shutdown(ctx_: *mut c_void)
     -> c_int;
    pub fn zmq_ctx_set(context: *mut c_void,
                       option: c_int,
                       optval: c_int)
     -> c_int;
    pub fn zmq_ctx_get(context: *mut c_void,
                       option: c_int)
     -> c_int;
    pub fn zmq_init(io_threads: c_int)
     -> *mut c_void;
    pub fn zmq_term(context: *mut c_void)
     -> c_int;
    pub fn zmq_ctx_destroy(context: *mut c_void)
     -> c_int;
    pub fn zmq_msg_init(msg: *mut zmq_msg_t) -> c_int;
    pub fn zmq_msg_init_size(msg: *mut zmq_msg_t, size: size_t)
     -> c_int;
    pub fn zmq_msg_init_data(msg: *mut zmq_msg_t,
                             data: *mut c_void, size: size_t,
                             ffn: *mut zmq_free_fn,
                             hint: *mut c_void)
     -> c_int;
    pub fn zmq_msg_send(msg: *mut zmq_msg_t, s: *mut c_void,
                        flags: c_int)
     -> c_int;
    pub fn zmq_msg_recv(msg: *mut zmq_msg_t, s: *mut c_void,
                        flags: c_int)
     -> c_int;
    pub fn zmq_msg_close(msg: *mut zmq_msg_t) -> c_int;
    pub fn zmq_msg_move(dest: *mut zmq_msg_t, src: *mut zmq_msg_t)
     -> c_int;
    pub fn zmq_msg_copy(dest: *mut zmq_msg_t, src: *mut zmq_msg_t)
     -> c_int;
    pub fn zmq_msg_data(msg: *mut zmq_msg_t) -> *mut c_void;
    pub fn zmq_msg_size(msg: *mut zmq_msg_t) -> size_t;
    pub fn zmq_msg_more(msg: *mut zmq_msg_t) -> c_int;
    pub fn zmq_msg_get(msg: *mut zmq_msg_t, property: c_int)
     -> c_int;
    pub fn zmq_msg_set(msg: *mut zmq_msg_t, property: c_int,
                       optval: c_int)
     -> c_int;
    pub fn zmq_msg_gets(msg: *mut zmq_msg_t,
                        property: *const c_char)
     -> *const c_char;
    pub fn zmq_socket(arg1: *mut c_void,
                      _type: c_int)
     -> *mut c_void;
    pub fn zmq_close(s: *mut c_void) -> c_int;
    pub fn zmq_setsockopt(s: *mut c_void,
                          option: c_int,
                          optval: *const c_void,
                          optvallen: size_t) -> c_int;
    pub fn zmq_getsockopt(s: *mut c_void,
                          option: c_int,
                          optval: *mut c_void,
                          optvallen: *mut size_t) -> c_int;
    pub fn zmq_bind(s: *mut c_void,
                    addr: *const c_char)
     -> c_int;
    pub fn zmq_connect(s: *mut c_void,
                       addr: *const c_char)
     -> c_int;
    pub fn zmq_unbind(s: *mut c_void,
                      addr: *const c_char)
     -> c_int;
    pub fn zmq_disconnect(s: *mut c_void,
                          addr: *const c_char)
     -> c_int;
    pub fn zmq_send(s: *mut c_void,
                    buf: *const c_void, len: size_t,
                    flags: c_int) -> c_int;
    pub fn zmq_send_const(s: *mut c_void,
                          buf: *const c_void, len: size_t,
                          flags: c_int)
     -> c_int;
    pub fn zmq_recv(s: *mut c_void,
                    buf: *mut c_void, len: size_t,
                    flags: c_int) -> c_int;
    pub fn zmq_socket_monitor(s: *mut c_void,
                              addr: *const c_char,
                              events: c_int)
     -> c_int;
    pub fn zmq_poll(items: *mut zmq_pollitem_t, nitems: c_int,
                    timeout: c_long) -> c_int;
    pub fn zmq_proxy(frontend: *mut c_void,
                     backend: *mut c_void,
                     capture: *mut c_void)
     -> c_int;
    pub fn zmq_proxy_steerable(frontend: *mut c_void,
                               backend: *mut c_void,
                               capture: *mut c_void,
                               control: *mut c_void)
     -> c_int;
    pub fn zmq_has(capability: *const c_char)
     -> c_int;
    pub fn zmq_device(_type: c_int,
                      frontend: *mut c_void,
                      backend: *mut c_void)
     -> c_int;
    pub fn zmq_sendmsg(s: *mut c_void, msg: *mut zmq_msg_t,
                       flags: c_int) -> c_int;
    pub fn zmq_recvmsg(s: *mut c_void, msg: *mut zmq_msg_t,
                       flags: c_int) -> c_int;
    pub fn zmq_z85_encode(dest: *mut c_char,
                          data: *const uint8_t, size: size_t)
     -> *mut c_char;
    pub fn zmq_z85_decode(dest: *mut uint8_t,
                          string: *const c_char)
     -> *mut uint8_t;
    pub fn zmq_curve_keypair(z85_public_key: *mut c_char,
                             z85_secret_key: *mut c_char)
     -> c_int;
    pub fn zmq_sendiov(s: *mut c_void, iov: *mut Struct_iovec,
                       count: size_t, flags: c_int)
     -> c_int;
    pub fn zmq_recviov(s: *mut c_void, iov: *mut Struct_iovec,
                       count: *mut size_t, flags: c_int)
     -> c_int;
    pub fn zmq_stopwatch_start() -> *mut c_void;
    pub fn zmq_stopwatch_stop(watch_: *mut c_void)
     -> c_ulong;
    pub fn zmq_sleep(seconds_: c_int);
    pub fn zmq_threadstart(func: *mut zmq_thread_fn,
                           arg: *mut c_void)
     -> *mut c_void;
    pub fn zmq_threadclose(thread: *mut c_void);
}
<commit_msg>Use the correct function pointer types in FFI signatures.<commit_after>/* automatically generated by rust-bindgen */

#[repr(C)]
#[derive(Copy)]
pub struct Struct_zmq_msg_t {
    pub unknown: [c_uchar; 64usize],
}
impl ::std::clone::Clone for Struct_zmq_msg_t {
    fn clone(&self) -> Self { *self }
}
impl ::std::default::Default for Struct_zmq_msg_t {
    fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
pub type zmq_msg_t = Struct_zmq_msg_t;
pub type zmq_free_fn =
    unsafe extern "C" fn(data: *mut c_void,
                         hint: *mut c_void);
#[repr(C)]
#[derive(Copy)]
pub struct Struct_zmq_pollitem_t {
    pub socket: *mut c_void,
    #[cfg(target_os = "windows")]       // Need to fix this manually
    pub fd: ::libc::intptr_t,           // Windows Socket is defined as UINT_PTR
    #[cfg(not(target_os = "windows"))]
    pub fd: c_int,
    pub events: c_short,
    pub revents: c_short,
}
impl ::std::clone::Clone for Struct_zmq_pollitem_t {
    fn clone(&self) -> Self { *self }
}
impl ::std::default::Default for Struct_zmq_pollitem_t {
    fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
pub type zmq_pollitem_t = Struct_zmq_pollitem_t;
pub enum Struct_iovec { }
pub type zmq_thread_fn =
    unsafe extern "C" fn(arg1: *mut c_void);
extern "C" {
    pub fn zmq_errno() -> c_int;
    pub fn zmq_strerror(errnum: c_int)
     -> *const c_char;
    pub fn zmq_version(major: *mut c_int,
                       minor: *mut c_int,
                       patch: *mut c_int);
    pub fn zmq_ctx_new() -> *mut c_void;
    pub fn zmq_ctx_term(context: *mut c_void)
     -> c_int;
    pub fn zmq_ctx_shutdown(ctx_: *mut c_void)
     -> c_int;
    pub fn zmq_ctx_set(context: *mut c_void,
                       option: c_int,
                       optval: c_int)
     -> c_int;
    pub fn zmq_ctx_get(context: *mut c_void,
                       option: c_int)
     -> c_int;
    pub fn zmq_init(io_threads: c_int)
     -> *mut c_void;
    pub fn zmq_term(context: *mut c_void)
     -> c_int;
    pub fn zmq_ctx_destroy(context: *mut c_void)
     -> c_int;
    pub fn zmq_msg_init(msg: *mut zmq_msg_t) -> c_int;
    pub fn zmq_msg_init_size(msg: *mut zmq_msg_t, size: size_t)
     -> c_int;
    pub fn zmq_msg_init_data(msg: *mut zmq_msg_t,
                             data: *mut c_void, size: size_t,
                             ffn: zmq_free_fn,
                             hint: *mut c_void)
     -> c_int;
    pub fn zmq_msg_send(msg: *mut zmq_msg_t, s: *mut c_void,
                        flags: c_int)
     -> c_int;
    pub fn zmq_msg_recv(msg: *mut zmq_msg_t, s: *mut c_void,
                        flags: c_int)
     -> c_int;
    pub fn zmq_msg_close(msg: *mut zmq_msg_t) -> c_int;
    pub fn zmq_msg_move(dest: *mut zmq_msg_t, src: *mut zmq_msg_t)
     -> c_int;
    pub fn zmq_msg_copy(dest: *mut zmq_msg_t, src: *mut zmq_msg_t)
     -> c_int;
    pub fn zmq_msg_data(msg: *mut zmq_msg_t) -> *mut c_void;
    pub fn zmq_msg_size(msg: *mut zmq_msg_t) -> size_t;
    pub fn zmq_msg_more(msg: *mut zmq_msg_t) -> c_int;
    pub fn zmq_msg_get(msg: *mut zmq_msg_t, property: c_int)
     -> c_int;
    pub fn zmq_msg_set(msg: *mut zmq_msg_t, property: c_int,
                       optval: c_int)
     -> c_int;
    pub fn zmq_msg_gets(msg: *mut zmq_msg_t,
                        property: *const c_char)
     -> *const c_char;
    pub fn zmq_socket(arg1: *mut c_void,
                      _type: c_int)
     -> *mut c_void;
    pub fn zmq_close(s: *mut c_void) -> c_int;
    pub fn zmq_setsockopt(s: *mut c_void,
                          option: c_int,
                          optval: *const c_void,
                          optvallen: size_t) -> c_int;
    pub fn zmq_getsockopt(s: *mut c_void,
                          option: c_int,
                          optval: *mut c_void,
                          optvallen: *mut size_t) -> c_int;
    pub fn zmq_bind(s: *mut c_void,
                    addr: *const c_char)
     -> c_int;
    pub fn zmq_connect(s: *mut c_void,
                       addr: *const c_char)
     -> c_int;
    pub fn zmq_unbind(s: *mut c_void,
                      addr: *const c_char)
     -> c_int;
    pub fn zmq_disconnect(s: *mut c_void,
                          addr: *const c_char)
     -> c_int;
    pub fn zmq_send(s: *mut c_void,
                    buf: *const c_void, len: size_t,
                    flags: c_int) -> c_int;
    pub fn zmq_send_const(s: *mut c_void,
                          buf: *const c_void, len: size_t,
                          flags: c_int)
     -> c_int;
    pub fn zmq_recv(s: *mut c_void,
                    buf: *mut c_void, len: size_t,
                    flags: c_int) -> c_int;
    pub fn zmq_socket_monitor(s: *mut c_void,
                              addr: *const c_char,
                              events: c_int)
     -> c_int;
    pub fn zmq_poll(items: *mut zmq_pollitem_t, nitems: c_int,
                    timeout: c_long) -> c_int;
    pub fn zmq_proxy(frontend: *mut c_void,
                     backend: *mut c_void,
                     capture: *mut c_void)
     -> c_int;
    pub fn zmq_proxy_steerable(frontend: *mut c_void,
                               backend: *mut c_void,
                               capture: *mut c_void,
                               control: *mut c_void)
     -> c_int;
    pub fn zmq_has(capability: *const c_char)
     -> c_int;
    pub fn zmq_device(_type: c_int,
                      frontend: *mut c_void,
                      backend: *mut c_void)
     -> c_int;
    pub fn zmq_sendmsg(s: *mut c_void, msg: *mut zmq_msg_t,
                       flags: c_int) -> c_int;
    pub fn zmq_recvmsg(s: *mut c_void, msg: *mut zmq_msg_t,
                       flags: c_int) -> c_int;
    pub fn zmq_z85_encode(dest: *mut c_char,
                          data: *const uint8_t, size: size_t)
     -> *mut c_char;
    pub fn zmq_z85_decode(dest: *mut uint8_t,
                          string: *const c_char)
     -> *mut uint8_t;
    pub fn zmq_curve_keypair(z85_public_key: *mut c_char,
                             z85_secret_key: *mut c_char)
     -> c_int;
    pub fn zmq_sendiov(s: *mut c_void, iov: *mut Struct_iovec,
                       count: size_t, flags: c_int)
     -> c_int;
    pub fn zmq_recviov(s: *mut c_void, iov: *mut Struct_iovec,
                       count: *mut size_t, flags: c_int)
     -> c_int;
    pub fn zmq_stopwatch_start() -> *mut c_void;
    pub fn zmq_stopwatch_stop(watch_: *mut c_void)
     -> c_ulong;
    pub fn zmq_sleep(seconds_: c_int);
    pub fn zmq_threadstart(func: zmq_thread_fn,
                           arg: *mut c_void)
     -> *mut c_void;
    pub fn zmq_threadclose(thread: *mut c_void);
}
<|endoftext|>


<commit_before>use std::fs;

use clap;

use cargo_shim::{
    Profile,
    TargetKind
};

use build::BuildArgs;
use deployment::Deployment;
use error::Error;

pub fn command_deploy< 'a >( matches: &clap::ArgMatches< 'a > ) -> Result< (), Error > {
    let build_args = BuildArgs::new( matches )?;
    let project = build_args.load_project()?;

    let package = project.package();
    let targets = project.target_or_select( |target| {
        target.kind == TargetKind::Bin ||
        (target.kind == TargetKind::CDyLib && project.backend().is_native_wasm())
    })?;

    let config = project.aggregate_configuration( Profile::Main )?;
    let target = targets[ 0 ];
    let result = project.build( &config, target )?;

    let deployment = Deployment::new( package, target, &result )?;
    let directory = project.target_directory().join( "deploy" );
    if directory.exists() {
        let entries = fs::read_dir( &directory ).map_err( |error| Error::CannotRemoveDirectory( directory.clone(), error ) )?; // TODO: Another error?
        for entry in entries {
            let entry = entry.expect( "cannot unwrap directory entry" );
            let path = entry.path();
            if path.is_dir() {
                fs::remove_dir_all( &path ).map_err( |error| Error::CannotRemoveDirectory( path.clone(), error ) )?;
            } else {
                fs::remove_file( &path ).map_err( |error| Error::CannotRemoveFile( path.clone(), error ) )?;
            }
        }
    }

    deployment.deploy_to( &directory )?;

    eprintln!( "The `{}` was deployed to {:?}!", target.name, directory );
    Ok(())
}
<commit_msg>`deploy` should not panic when it doesn't find a valid target<commit_after>use std::fs;

use clap;

use cargo_shim::{
    Profile,
    TargetKind
};

use build::BuildArgs;
use deployment::Deployment;
use error::Error;

pub fn command_deploy< 'a >( matches: &clap::ArgMatches< 'a > ) -> Result< (), Error > {
    let build_args = BuildArgs::new( matches )?;
    let project = build_args.load_project()?;

    let package = project.package();
    let targets = project.target_or_select( |target| {
        target.kind == TargetKind::Bin ||
        (target.kind == TargetKind::CDyLib && project.backend().is_native_wasm())
    })?;

    if targets.is_empty() {
        if project.backend().is_native_wasm() {
            return Err( "No valid target found for deployment; expected a `bin` crate or a `cdylib`".into() );
        } else {
            return Err( "No valid target found for deployment; expected a `bin` crate".into() );
        }
    }

    let config = project.aggregate_configuration( Profile::Main )?;
    let target = targets[ 0 ];
    let result = project.build( &config, target )?;

    let deployment = Deployment::new( package, target, &result )?;
    let directory = project.target_directory().join( "deploy" );
    if directory.exists() {
        let entries = fs::read_dir( &directory ).map_err( |error| Error::CannotRemoveDirectory( directory.clone(), error ) )?; // TODO: Another error?
        for entry in entries {
            let entry = entry.expect( "cannot unwrap directory entry" );
            let path = entry.path();
            if path.is_dir() {
                fs::remove_dir_all( &path ).map_err( |error| Error::CannotRemoveDirectory( path.clone(), error ) )?;
            } else {
                fs::remove_file( &path ).map_err( |error| Error::CannotRemoveFile( path.clone(), error ) )?;
            }
        }
    }

    deployment.deploy_to( &directory )?;

    eprintln!( "The `{}` was deployed to {:?}!", target.name, directory );
    Ok(())
}
<|endoftext|>


<commit_before>//!  Decoding of DDS images
//!
//!  DDS (DirectDraw Surface) is a container format for storing DXT (S3TC) compressed images.
//!
//!  # Related Links
//!  * <https://docs.microsoft.com/en-us/windows/win32/direct3ddds/dx-graphics-dds-pguide> - Description of the DDS format.

use std::io::Read;
use std::{error, fmt};

use byteorder::{LittleEndian, ReadBytesExt};

#[allow(deprecated)]
use crate::codecs::dxt::{DxtDecoder, DxtReader, DxtVariant};
use crate::color::ColorType;
use crate::error::{
    DecodingError, ImageError, ImageFormatHint, ImageResult, UnsupportedError, UnsupportedErrorKind,
};
use crate::image::{ImageDecoder, ImageFormat};

/// Errors that can occur during decoding and parsing a DDS image
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
enum DecoderError {
    /// Wrong DDS channel width
    PixelFormatSizeInvalid(u32),
    /// Wrong DDS header size
    HeaderSizeInvalid(u32),
    /// Wrong DDS header flags
    HeaderFlagsInvalid(u32),

    /// DDS "DDS " signature invalid or missing
    DdsSignatureInvalid,
}

impl fmt::Display for DecoderError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            DecoderError::PixelFormatSizeInvalid(s) => {
                f.write_fmt(format_args!("Invalid DDS PixelFormat size: {}", s))
            }
            DecoderError::HeaderSizeInvalid(s) => {
                f.write_fmt(format_args!("Invalid DDS header size: {}", s))
            }
            DecoderError::HeaderFlagsInvalid(fs) => {
                f.write_fmt(format_args!("Invalid DDS header flags: {:#010X}", fs))
            }
            DecoderError::DdsSignatureInvalid => f.write_str("DDS signature not found"),
        }
    }
}

impl From<DecoderError> for ImageError {
    fn from(e: DecoderError) -> ImageError {
        ImageError::Decoding(DecodingError::new(ImageFormat::Dds.into(), e))
    }
}

impl error::Error for DecoderError {}

/// Header used by DDS image files
#[derive(Debug)]
struct Header {
    flags: u32,
    height: u32,
    width: u32,
    pitch_or_linear_size: u32,
    depth: u32,
    mipmap_count: u32,
    pixel_format: PixelFormat,
    caps: u32,
    caps2: u32,
}

/// Extended DX10 header used by some DDS image files
#[derive(Debug)]
struct DX10Header {
    dxgi_format: u32,
    resource_dimension: u32,
    misc_flag: u32,
    array_size: u32,
    misc_flags_2: u32,
}

/// DDS pixel format
#[derive(Debug)]
struct PixelFormat {
    flags: u32,
    fourcc: [u8; 4],
    rgb_bit_count: u32,
    r_bit_mask: u32,
    g_bit_mask: u32,
    b_bit_mask: u32,
    a_bit_mask: u32,
}

impl PixelFormat {
    fn from_reader(r: &mut dyn Read) -> ImageResult<Self> {
        let size = r.read_u32::<LittleEndian>()?;
        if size != 32 {
            return Err(DecoderError::PixelFormatSizeInvalid(size).into());
        }

        Ok(Self {
            flags: r.read_u32::<LittleEndian>()?,
            fourcc: {
                let mut v = [0; 4];
                r.read_exact(&mut v)?;
                v
            },
            rgb_bit_count: r.read_u32::<LittleEndian>()?,
            r_bit_mask: r.read_u32::<LittleEndian>()?,
            g_bit_mask: r.read_u32::<LittleEndian>()?,
            b_bit_mask: r.read_u32::<LittleEndian>()?,
            a_bit_mask: r.read_u32::<LittleEndian>()?,
        })
    }
}

impl Header {
    fn from_reader(r: &mut dyn Read) -> ImageResult<Self> {
        let size = r.read_u32::<LittleEndian>()?;
        if size != 124 {
            return Err(DecoderError::HeaderSizeInvalid(size).into());
        }

        const REQUIRED_FLAGS: u32 = 0x1 | 0x2 | 0x4 | 0x1000;
        const VALID_FLAGS: u32 = 0x1 | 0x2 | 0x4 | 0x8 | 0x1000 | 0x20000 | 0x80000 | 0x800000;
        let flags = r.read_u32::<LittleEndian>()?;
        if flags & (REQUIRED_FLAGS | !VALID_FLAGS) != REQUIRED_FLAGS {
            return Err(DecoderError::HeaderFlagsInvalid(flags).into());
        }

        let height = r.read_u32::<LittleEndian>()?;
        let width = r.read_u32::<LittleEndian>()?;
        let pitch_or_linear_size = r.read_u32::<LittleEndian>()?;
        let depth = r.read_u32::<LittleEndian>()?;
        let mipmap_count = r.read_u32::<LittleEndian>()?;
        // Skip `dwReserved1`
        {
            let mut skipped = [0; 4 * 11];
            r.read_exact(&mut skipped)?;
        }
        let pixel_format = PixelFormat::from_reader(r)?;
        let caps = r.read_u32::<LittleEndian>()?;
        let caps2 = r.read_u32::<LittleEndian>()?;
        // Skip `dwCaps3`, `dwCaps4`, `dwReserved2` (unused)
        {
            let mut skipped = [0; 4 + 4 + 4];
            r.read_exact(&mut skipped)?;
        }

        Ok(Self {
            flags,
            height,
            width,
            pitch_or_linear_size,
            depth,
            mipmap_count,
            pixel_format,
            caps,
            caps2,
        })
    }
}

impl DX10Header {
    fn from_reader(r: &mut dyn Read) -> ImageResult<Self> {
        let dxgi_format = r.read_u32::<LittleEndian>()?;
        let resource_dimension = r.read_u32::<LittleEndian>()?;
        let misc_flag = r.read_u32::<LittleEndian>()?;
        let array_size = r.read_u32::<LittleEndian>()?;
        let misc_flags_2 = r.read_u32::<LittleEndian>()?;

        Ok(Self {
            dxgi_format,
            resource_dimension,
            misc_flag,
            array_size,
            misc_flags_2,
        })
    }
}

/// The representation of a DDS decoder
pub struct DdsDecoder<R: Read> {
    #[allow(deprecated)]
    inner: DxtDecoder<R>,
}

impl<R: Read> DdsDecoder<R> {
    /// Create a new decoder that decodes from the stream `r`
    pub fn new(mut r: R) -> ImageResult<Self> {
        let mut magic = [0; 4];
        r.read_exact(&mut magic)?;
        if magic != b"DDS "[..] {
            return Err(DecoderError::DdsSignatureInvalid.into());
        }

        let header = Header::from_reader(&mut r)?;

        if header.pixel_format.flags & 0x4 != 0 {
            #[allow(deprecated)]
            let variant = match &header.pixel_format.fourcc {
                b"DXT1" => DxtVariant::DXT1,
                b"DXT3" => DxtVariant::DXT3,
                b"DXT5" => DxtVariant::DXT5,
                b"DX10" => {
                    let dx10_header = DX10Header::from_reader(&mut r)?;
                    match dx10_header.dxgi_format {
                        70 | 71 | 72 => DxtVariant::DXT1,
                        73 | 74 | 75 => DxtVariant::DXT3,
                        76 | 77 | 78 => DxtVariant::DXT5,
                        _ => return Err(ImageError::Unsupported(
                            UnsupportedError::from_format_and_kind(
                                ImageFormat::Dds.into(),
                                UnsupportedErrorKind::GenericFeature(format!(
                                    "DDS DXGI Format {}",
                                    dx10_header.dxgi_format
                                )),
                            ),
                        ))
                    }
                }
                fourcc => {
                    return Err(ImageError::Unsupported(
                        UnsupportedError::from_format_and_kind(
                            ImageFormat::Dds.into(),
                            UnsupportedErrorKind::GenericFeature(format!(
                                "DDS FourCC {:?}",
                                fourcc
                            )),
                        ),
                    ))
                }
            };

            #[allow(deprecated)]
            let bytes_per_pixel = variant.color_type().bytes_per_pixel();

            if crate::utils::check_dimension_overflow(header.width, header.height, bytes_per_pixel)
            {
                return Err(ImageError::Unsupported(
                    UnsupportedError::from_format_and_kind(
                        ImageFormat::Dds.into(),
                        UnsupportedErrorKind::GenericFeature(format!(
                            "Image dimensions ({}x{}) are too large",
                            header.width, header.height
                        )),
                    ),
                ));
            }

            #[allow(deprecated)]
            let inner = DxtDecoder::new(r, header.width, header.height, variant)?;
            Ok(Self { inner })
        } else {
            // For now, supports only DXT variants
            Err(ImageError::Unsupported(
                UnsupportedError::from_format_and_kind(
                    ImageFormat::Dds.into(),
                    UnsupportedErrorKind::Format(ImageFormatHint::Name("DDS".to_string())),
                ),
            ))
        }
    }
}

impl<'a, R: 'a + Read> ImageDecoder<'a> for DdsDecoder<R> {
    #[allow(deprecated)]
    type Reader = DxtReader<R>;

    fn dimensions(&self) -> (u32, u32) {
        self.inner.dimensions()
    }

    fn color_type(&self) -> ColorType {
        self.inner.color_type()
    }

    fn scanline_bytes(&self) -> u64 {
        self.inner.scanline_bytes()
    }

    fn into_reader(self) -> ImageResult<Self::Reader> {
        self.inner.into_reader()
    }

    fn read_image(self, buf: &mut [u8]) -> ImageResult<()> {
        self.inner.read_image(buf)
    }
}

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

    #[test]
    fn dimension_overflow() {
        // A DXT1 header set to 0xFFFF_FFFC width and height (the highest u32%4 == 0)
        let header = vec![
            0x44, 0x44, 0x53, 0x20, 0x7C, 0x0, 0x0, 0x0, 0x7, 0x10, 0x8, 0x0, 0xFC, 0xFF, 0xFF,
            0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0x0, 0xC0, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0,
            0x0, 0x49, 0x4D, 0x41, 0x47, 0x45, 0x4D, 0x41, 0x47, 0x49, 0x43, 0x4B, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0,
            0x4, 0x0, 0x0, 0x0, 0x44, 0x58, 0x54, 0x31, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
        ];

        assert!(DdsDecoder::new(&header[..]).is_err());
    }
}
<commit_msg>Styling changes<commit_after>//!  Decoding of DDS images
//!
//!  DDS (DirectDraw Surface) is a container format for storing DXT (S3TC) compressed images.
//!
//!  # Related Links
//!  * <https://docs.microsoft.com/en-us/windows/win32/direct3ddds/dx-graphics-dds-pguide> - Description of the DDS format.

use std::io::Read;
use std::{error, fmt};

use byteorder::{LittleEndian, ReadBytesExt};

#[allow(deprecated)]
use crate::codecs::dxt::{DxtDecoder, DxtReader, DxtVariant};
use crate::color::ColorType;
use crate::error::{
    DecodingError, ImageError, ImageFormatHint, ImageResult, UnsupportedError, UnsupportedErrorKind,
};
use crate::image::{ImageDecoder, ImageFormat};

/// Errors that can occur during decoding and parsing a DDS image
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
enum DecoderError {
    /// Wrong DDS channel width
    PixelFormatSizeInvalid(u32),
    /// Wrong DDS header size
    HeaderSizeInvalid(u32),
    /// Wrong DDS header flags
    HeaderFlagsInvalid(u32),

    /// DDS "DDS " signature invalid or missing
    DdsSignatureInvalid,
}

impl fmt::Display for DecoderError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            DecoderError::PixelFormatSizeInvalid(s) => {
                f.write_fmt(format_args!("Invalid DDS PixelFormat size: {}", s))
            }
            DecoderError::HeaderSizeInvalid(s) => {
                f.write_fmt(format_args!("Invalid DDS header size: {}", s))
            }
            DecoderError::HeaderFlagsInvalid(fs) => {
                f.write_fmt(format_args!("Invalid DDS header flags: {:#010X}", fs))
            }
            DecoderError::DdsSignatureInvalid => f.write_str("DDS signature not found"),
        }
    }
}

impl From<DecoderError> for ImageError {
    fn from(e: DecoderError) -> ImageError {
        ImageError::Decoding(DecodingError::new(ImageFormat::Dds.into(), e))
    }
}

impl error::Error for DecoderError {}

/// Header used by DDS image files
#[derive(Debug)]
struct Header {
    flags: u32,
    height: u32,
    width: u32,
    pitch_or_linear_size: u32,
    depth: u32,
    mipmap_count: u32,
    pixel_format: PixelFormat,
    caps: u32,
    caps2: u32,
}

/// Extended DX10 header used by some DDS image files
#[derive(Debug)]
struct DX10Header {
    dxgi_format: u32,
    resource_dimension: u32,
    misc_flag: u32,
    array_size: u32,
    misc_flags_2: u32,
}

/// DDS pixel format
#[derive(Debug)]
struct PixelFormat {
    flags: u32,
    fourcc: [u8; 4],
    rgb_bit_count: u32,
    r_bit_mask: u32,
    g_bit_mask: u32,
    b_bit_mask: u32,
    a_bit_mask: u32,
}

impl PixelFormat {
    fn from_reader(r: &mut dyn Read) -> ImageResult<Self> {
        let size = r.read_u32::<LittleEndian>()?;
        if size != 32 {
            return Err(DecoderError::PixelFormatSizeInvalid(size).into());
        }

        Ok(Self {
            flags: r.read_u32::<LittleEndian>()?,
            fourcc: {
                let mut v = [0; 4];
                r.read_exact(&mut v)?;
                v
            },
            rgb_bit_count: r.read_u32::<LittleEndian>()?,
            r_bit_mask: r.read_u32::<LittleEndian>()?,
            g_bit_mask: r.read_u32::<LittleEndian>()?,
            b_bit_mask: r.read_u32::<LittleEndian>()?,
            a_bit_mask: r.read_u32::<LittleEndian>()?,
        })
    }
}

impl Header {
    fn from_reader(r: &mut dyn Read) -> ImageResult<Self> {
        let size = r.read_u32::<LittleEndian>()?;
        if size != 124 {
            return Err(DecoderError::HeaderSizeInvalid(size).into());
        }

        const REQUIRED_FLAGS: u32 = 0x1 | 0x2 | 0x4 | 0x1000;
        const VALID_FLAGS: u32 = 0x1 | 0x2 | 0x4 | 0x8 | 0x1000 | 0x20000 | 0x80000 | 0x800000;
        let flags = r.read_u32::<LittleEndian>()?;
        if flags & (REQUIRED_FLAGS | !VALID_FLAGS) != REQUIRED_FLAGS {
            return Err(DecoderError::HeaderFlagsInvalid(flags).into());
        }

        let height = r.read_u32::<LittleEndian>()?;
        let width = r.read_u32::<LittleEndian>()?;
        let pitch_or_linear_size = r.read_u32::<LittleEndian>()?;
        let depth = r.read_u32::<LittleEndian>()?;
        let mipmap_count = r.read_u32::<LittleEndian>()?;
        // Skip `dwReserved1`
        {
            let mut skipped = [0; 4 * 11];
            r.read_exact(&mut skipped)?;
        }
        let pixel_format = PixelFormat::from_reader(r)?;
        let caps = r.read_u32::<LittleEndian>()?;
        let caps2 = r.read_u32::<LittleEndian>()?;
        // Skip `dwCaps3`, `dwCaps4`, `dwReserved2` (unused)
        {
            let mut skipped = [0; 4 + 4 + 4];
            r.read_exact(&mut skipped)?;
        }

        Ok(Self {
            flags,
            height,
            width,
            pitch_or_linear_size,
            depth,
            mipmap_count,
            pixel_format,
            caps,
            caps2,
        })
    }
}

impl DX10Header {
    fn from_reader(r: &mut dyn Read) -> ImageResult<Self> {
        let dxgi_format = r.read_u32::<LittleEndian>()?;
        let resource_dimension = r.read_u32::<LittleEndian>()?;
        let misc_flag = r.read_u32::<LittleEndian>()?;
        let array_size = r.read_u32::<LittleEndian>()?;
        let misc_flags_2 = r.read_u32::<LittleEndian>()?;

        Ok(Self {
            dxgi_format,
            resource_dimension,
            misc_flag,
            array_size,
            misc_flags_2,
        })
    }
}

/// The representation of a DDS decoder
pub struct DdsDecoder<R: Read> {
    #[allow(deprecated)]
    inner: DxtDecoder<R>,
}

impl<R: Read> DdsDecoder<R> {
    /// Create a new decoder that decodes from the stream `r`
    pub fn new(mut r: R) -> ImageResult<Self> {
        let mut magic = [0; 4];
        r.read_exact(&mut magic)?;
        if magic != b"DDS "[..] {
            return Err(DecoderError::DdsSignatureInvalid.into());
        }

        let header = Header::from_reader(&mut r)?;

        if header.pixel_format.flags & 0x4 != 0 {
            #[allow(deprecated)]
            let variant = match &header.pixel_format.fourcc {
                b"DXT1" => DxtVariant::DXT1,
                b"DXT3" => DxtVariant::DXT3,
                b"DXT5" => DxtVariant::DXT5,
                b"DX10" => {
                    let dx10_header = DX10Header::from_reader(&mut r)?;
                    match dx10_header.dxgi_format {
                        70 | 71 | 72 => DxtVariant::DXT1,
                        73 | 74 | 75 => DxtVariant::DXT3,
                        76 | 77 | 78 => DxtVariant::DXT5,
                        _ => {
                            return Err(ImageError::Unsupported(
                                UnsupportedError::from_format_and_kind(
                                    ImageFormat::Dds.into(),
                                    UnsupportedErrorKind::GenericFeature(format!(
                                        "DDS DXGI Format {}",
                                        dx10_header.dxgi_format
                                    )),
                                ),
                            ))
                        }
                    }
                }
                fourcc => {
                    return Err(ImageError::Unsupported(
                        UnsupportedError::from_format_and_kind(
                            ImageFormat::Dds.into(),
                            UnsupportedErrorKind::GenericFeature(format!(
                                "DDS FourCC {:?}",
                                fourcc
                            )),
                        ),
                    ))
                }
            };

            #[allow(deprecated)]
            let bytes_per_pixel = variant.color_type().bytes_per_pixel();

            if crate::utils::check_dimension_overflow(header.width, header.height, bytes_per_pixel)
            {
                return Err(ImageError::Unsupported(
                    UnsupportedError::from_format_and_kind(
                        ImageFormat::Dds.into(),
                        UnsupportedErrorKind::GenericFeature(format!(
                            "Image dimensions ({}x{}) are too large",
                            header.width, header.height
                        )),
                    ),
                ));
            }

            #[allow(deprecated)]
            let inner = DxtDecoder::new(r, header.width, header.height, variant)?;
            Ok(Self { inner })
        } else {
            // For now, supports only DXT variants
            Err(ImageError::Unsupported(
                UnsupportedError::from_format_and_kind(
                    ImageFormat::Dds.into(),
                    UnsupportedErrorKind::Format(ImageFormatHint::Name("DDS".to_string())),
                ),
            ))
        }
    }
}

impl<'a, R: 'a + Read> ImageDecoder<'a> for DdsDecoder<R> {
    #[allow(deprecated)]
    type Reader = DxtReader<R>;

    fn dimensions(&self) -> (u32, u32) {
        self.inner.dimensions()
    }

    fn color_type(&self) -> ColorType {
        self.inner.color_type()
    }

    fn scanline_bytes(&self) -> u64 {
        self.inner.scanline_bytes()
    }

    fn into_reader(self) -> ImageResult<Self::Reader> {
        self.inner.into_reader()
    }

    fn read_image(self, buf: &mut [u8]) -> ImageResult<()> {
        self.inner.read_image(buf)
    }
}

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

    #[test]
    fn dimension_overflow() {
        // A DXT1 header set to 0xFFFF_FFFC width and height (the highest u32%4 == 0)
        let header = vec![
            0x44, 0x44, 0x53, 0x20, 0x7C, 0x0, 0x0, 0x0, 0x7, 0x10, 0x8, 0x0, 0xFC, 0xFF, 0xFF,
            0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0x0, 0xC0, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0,
            0x0, 0x49, 0x4D, 0x41, 0x47, 0x45, 0x4D, 0x41, 0x47, 0x49, 0x43, 0x4B, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0,
            0x4, 0x0, 0x0, 0x0, 0x44, 0x58, 0x54, 0x31, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
        ];

        assert!(DdsDecoder::new(&header[..]).is_err());
    }
}
<|endoftext|>


<commit_before>//! Types and traits associated with collections of data.

use std::hash::Hash;

use timely::Data;
use timely::progress::Timestamp;
use timely::progress::nested::product::Product;
use timely::dataflow::scopes::Child;
use timely::dataflow::{Scope, Stream};
use timely::dataflow::operators::*;

use ::Diff;

/// A mutable collection of values of type `D`
///
/// The `Collection` type is the core abstraction in differential dataflow programs. As you write your
/// differential dataflow computation, you write as if the collection is a static dataset to which you
/// apply functional transformations, creating new collections. Once your computation is written, you
/// are able to mutate the collection (by inserting and removing elements); differential dataflow will
/// propagate changes through your functional computation and report the corresponding changes to the
/// output collections.
///
/// Each collection has three generic parameters. The parameter `G` is for the scope in which the
/// collection exists; as you write more complicated programs you may wish to introduce nested scopes
/// (e.g. for iteration) and this parameter tracks the scope (for timely dataflow's benefit). The `D`
/// parameter is the type of data in your collection, for example `String`, or `(u32, Vec<Option<()>>)`.
/// The `R` parameter represents the types of changes that the data undergo, and is most commonly (and
/// defaults to) `isize`, representing changes to the occurrence count of each record.
#[derive(Clone)]
pub struct Collection<G: Scope, D, R: Diff = isize> {
    /// The underlying timely dataflow stream.
    ///
    /// This field is exposed to support direct timely dataflow manipulation when required, but it is
    /// not intended to be the idiomatic way to work with the collection.
    pub inner: Stream<G, (D, G::Timestamp, R)>
}

impl<G: Scope, D: Data, R: Diff> Collection<G, D, R> where G::Timestamp: Data {
    /// Creates a new Collection from a timely dataflow stream.
    pub fn new(stream: Stream<G, (D, G::Timestamp, R)>) -> Collection<G, D, R> {
        Collection { inner: stream }
    }
    /// Creates a new collection by applying the supplied function to each input element.
    pub fn map<D2: Data, L: Fn(D) -> D2 + 'static>(&self, logic: L) -> Collection<G, D2, R> {
        self.inner.map(move |(data, time, delta)| (logic(data), time, delta))
                  .as_collection()
    }
    /// Creates a new collection by applying the supplied function to each input element.
    ///
    /// Although the name suggests in-place mutation, this function does not change the source collection,
    /// but rather re-uses the underlying allocations in its implementation. The method is semantically
    /// equivalent to `map`, but can be more efficient.
    pub fn map_in_place<L: Fn(&mut D) + 'static>(&self, logic: L) -> Collection<G, D, R> {
        self.inner.map_in_place(move |&mut (ref mut data, _, _)| logic(data))
                  .as_collection()
    }
    /// Creates a new collection by applying the supplied function to each input element and accumulating the results.
    ///
    /// This method extracts an iterator from each input element, and extracts the full contents of the iterator. Be
    /// warned that if the iterators produce substantial amounts of data, they are currently fully drained before attempting
    /// to consolidate the results.
    pub fn flat_map<D2: Data, I: IntoIterator<Item=D2>, L: Fn(D) -> I + 'static>(&self, logic: L) -> Collection<G, D2, R>
        where G::Timestamp: Clone {
        self.inner.flat_map(move |(data, time, delta)| logic(data).into_iter().map(move |x| (x, time.clone(), delta)))
                  .as_collection()
    }
    /// Creates a new collection whose counts are the negation of those in the input.
    ///
    /// This method is most commonly used with `concat` to get those element in one collection but not another.
    /// However, differential dataflow computations are still defined for all values of the difference type `R`,
    /// including negative counts.
    pub fn negate(&self) -> Collection<G, D, R> {
        self.inner.map_in_place(|x| x.2 = -x.2)
                  .as_collection()
    }
    /// Creates a new collection containing those input records satisfying the supplied predicate.
    pub fn filter<L: Fn(&D) -> bool + 'static>(&self, logic: L) -> Collection<G, D, R> {
        self.inner.filter(move |&(ref data, _, _)| logic(data))
                  .as_collection()
    }
    /// Creates a new collection accumulating the contents of the two collections.
    ///
    /// Despite the name, differential dataflow collections are unordered. This method is so named because the
    /// implementation is the concatenation of the stream of updates, but it corresponds to the addition of the
    /// two collections.
    pub fn concat(&self, other: &Collection<G, D, R>) -> Collection<G, D, R> {
        self.inner.concat(&other.inner)
                  .as_collection()
    }
    /// Brings a Collection into a nested scope.
    pub fn enter<'a, T: Timestamp>(&self, child: &Child<'a, G, T>) -> Collection<Child<'a, G, T>, D, R> {
        self.inner.enter(child)
                  .map(|(data, time, diff)| (data, Product::new(time, Default::default()), diff))
                  .as_collection()
    }
    /// Brings a Collection into a nested scope, at varying times.
    ///
    /// The `initial` function indicates the time at which each element of the Collection should appear.
    pub fn enter_at<'a, T: Timestamp, F>(&self, child: &Child<'a, G, T>, initial: F) -> Collection<Child<'a, G, T>, D, R>
    where F: Fn(&D) -> T + 'static,
          G::Timestamp: Hash, T: Hash {

        let initial1 = ::std::rc::Rc::new(initial);
        let initial2 = initial1.clone();

        self.inner.enter_at(child, move |x| (*initial1)(&x.0))
                  .map(move |(data, time, diff)| {
                      let new_time = Product::new(time, (*initial2)(&data));
                      (data, new_time, diff)
                  })
                  .as_collection()
    }
    /// Applies a supplied function to each update.
    ///
    /// This method is most commonly used to report information back to the user, often for debugging purposes.
    /// Any function can be used here, but be warned that the incremental nature of differential dataflow does
    /// not guarantee that it will be called as many times as you might expect.
    ///
    /// The `(data, time, diff)` triples indicate a change `diff` to the frequency of `data` which takes effect
    /// at the logical time `time`. When times are totally ordered (for example, `usize`), these updates reflect
    /// the changes along the sequence of collections. For partially ordered times, the mathematics are more
    /// interesting and less intuitive, unfortunately.
    pub fn inspect<F: FnMut(&(D, G::Timestamp, R))+'static>(&self, func: F) -> Collection<G, D, R> {
        self.inner.inspect(func)
                  .as_collection()
    }
    /// Applies a supplied function to each batch of updates.
    ///
    /// This method is analogous to `inspect`, but operates on batches and reveals the timely dataflow capability
    /// associated with the batch of updates.
    pub fn inspect_batch<F: FnMut(&G::Timestamp, &[(D, G::Timestamp, R)])+'static>(&self, func: F) -> Collection<G, D, R> {
        self.inner.inspect_batch(func)
                  .as_collection()
    }
    /// Attaches a timely dataflow probe to the output of a Collection.
    ///
    /// This probe is used to determine when the state of the Collection has stabilized and can
    /// be read out.
    pub fn probe(&self) -> probe::Handle<G::Timestamp> {
        self.inner.probe()
    }
    /// Attaches a timely dataflow probe to the output of a Collection.
    ///
    /// This probe is used to determine when the state of the Collection has stabilized and all updates observed.
    /// In addition, a probe is also often use to limit the number of rounds of input in flight at any moment; a
    /// computation can wait until the probe has caught up to the input before introducing more rounds of data, to
    /// avoid swamping the system.
    pub fn probe_with(&self, handle: &mut ::timely::dataflow::operators::probe::Handle<G::Timestamp>) -> Collection<G, D, R> {
        self.inner.probe_with(handle).as_collection()
    }
    /// The scope containing the underlying timely dataflow stream.
    pub fn scope(&self) -> G {
        self.inner.scope()
    }
}

impl<'a, G: Scope, T: Timestamp, D: Data, R: Diff> Collection<Child<'a, G, T>, D, R> {
    /// Returns the final value of a Collection from a nested scope to its containing scope.
    pub fn leave(&self) -> Collection<G, D, R> {
        self.inner.leave()
                  .map(|(data, time, diff)| (data, time.outer, diff))
                  .as_collection()
    }
}

/// Conversion to a differential dataflow Collection.
pub trait AsCollection<G: Scope, D: Data, R: Diff> {
    /// Converts the type to a differential dataflow collection.
    fn as_collection(&self) -> Collection<G, D, R>;
}

impl<G: Scope, D: Data, R: Diff> AsCollection<G, D, R> for Stream<G, (D, G::Timestamp, R)> {
    fn as_collection(&self) -> Collection<G, D, R> {
        Collection::new(self.clone())
    }
}<commit_msg>add explode operator<commit_after>//! Types and traits associated with collections of data.

use std::hash::Hash;
use std::ops::Mul;

use timely::Data;
use timely::progress::Timestamp;
use timely::progress::nested::product::Product;
use timely::dataflow::scopes::Child;
use timely::dataflow::{Scope, Stream};
use timely::dataflow::operators::*;

use ::Diff;

/// A mutable collection of values of type `D`
///
/// The `Collection` type is the core abstraction in differential dataflow programs. As you write your
/// differential dataflow computation, you write as if the collection is a static dataset to which you
/// apply functional transformations, creating new collections. Once your computation is written, you
/// are able to mutate the collection (by inserting and removing elements); differential dataflow will
/// propagate changes through your functional computation and report the corresponding changes to the
/// output collections.
///
/// Each collection has three generic parameters. The parameter `G` is for the scope in which the
/// collection exists; as you write more complicated programs you may wish to introduce nested scopes
/// (e.g. for iteration) and this parameter tracks the scope (for timely dataflow's benefit). The `D`
/// parameter is the type of data in your collection, for example `String`, or `(u32, Vec<Option<()>>)`.
/// The `R` parameter represents the types of changes that the data undergo, and is most commonly (and
/// defaults to) `isize`, representing changes to the occurrence count of each record.
#[derive(Clone)]
pub struct Collection<G: Scope, D, R: Diff = isize> {
    /// The underlying timely dataflow stream.
    ///
    /// This field is exposed to support direct timely dataflow manipulation when required, but it is
    /// not intended to be the idiomatic way to work with the collection.
    pub inner: Stream<G, (D, G::Timestamp, R)>
}

impl<G: Scope, D: Data, R: Diff> Collection<G, D, R> where G::Timestamp: Data {
    /// Creates a new Collection from a timely dataflow stream.
    pub fn new(stream: Stream<G, (D, G::Timestamp, R)>) -> Collection<G, D, R> {
        Collection { inner: stream }
    }
    /// Creates a new collection by applying the supplied function to each input element.
    pub fn map<D2, L>(&self, logic: L) -> Collection<G, D2, R>
    where D2: Data,
          L: Fn(D) -> D2 + 'static
    {
        self.inner.map(move |(data, time, delta)| (logic(data), time, delta))
                  .as_collection()
    }
    /// Creates a new collection by applying the supplied function to each input element.
    ///
    /// Although the name suggests in-place mutation, this function does not change the source collection,
    /// but rather re-uses the underlying allocations in its implementation. The method is semantically
    /// equivalent to `map`, but can be more efficient.
    pub fn map_in_place<L>(&self, logic: L) -> Collection<G, D, R>
    where L: Fn(&mut D) + 'static {
        self.inner.map_in_place(move |&mut (ref mut data, _, _)| logic(data))
                  .as_collection()
    }
    /// Creates a new collection by applying the supplied function to each input element and accumulating the results.
    ///
    /// This method extracts an iterator from each input element, and extracts the full contents of the iterator. Be
    /// warned that if the iterators produce substantial amounts of data, they are currently fully drained before attempting
    /// to consolidate the results.
    pub fn flat_map<I, L>(&self, logic: L) -> Collection<G, I::Item, R>
        where G::Timestamp: Clone,
              I: IntoIterator,
              I::Item: Data,
              L: Fn(D) -> I + 'static {
        self.inner.flat_map(move |(data, time, delta)| logic(data).into_iter().map(move |x| (x, time.clone(), delta)))
                  .as_collection()
    }
    /// Creates a new collection whose counts are the negation of those in the input.
    ///
    /// This method is most commonly used with `concat` to get those element in one collection but not another.
    /// However, differential dataflow computations are still defined for all values of the difference type `R`,
    /// including negative counts.
    pub fn negate(&self) -> Collection<G, D, R> {
        self.inner.map_in_place(|x| x.2 = -x.2)
                  .as_collection()
    }
    /// Creates a new collection containing those input records satisfying the supplied predicate.
    pub fn filter<L>(&self, logic: L) -> Collection<G, D, R>
    where L: Fn(&D) -> bool + 'static {
        self.inner.filter(move |&(ref data, _, _)| logic(data))
                  .as_collection()
    }
    /// Creates a new collection accumulating the contents of the two collections.
    ///
    /// Despite the name, differential dataflow collections are unordered. This method is so named because the
    /// implementation is the concatenation of the stream of updates, but it corresponds to the addition of the
    /// two collections.
    pub fn concat(&self, other: &Collection<G, D, R>) -> Collection<G, D, R> {
        self.inner.concat(&other.inner)
                  .as_collection()
    }
    /// Replaces each record with another, with a new difference type.
    ///
    /// This method is most commonly used to take records containing aggregatable data (e.g. numbers to be summed)
    /// and move the data into the difference component. This will allow differential dataflow to update in-place.
    ///
    /// #Examples
    ///
    /// ```ignore
    /// // moves `salary` to accumulable data, and results
    /// // in the total salary for people by name (e.g. how
    /// // much do people named "Frank" get paid).
    /// employees.explode(|(name, salary)| (name, salary))
    ///          .count();
    /// ```
    pub fn explode<D2, R2, I, L>(&self, logic: L) -> Collection<G, D2, <R2 as Mul<R>>::Output>
    where D2: Data,
          R2: Diff+Mul<R>,
          <R2 as Mul<R>>::Output: Data+Diff,
          I: IntoIterator<Item=(D2,R2)>,
          L: Fn(D)->I+'static,
    {
        self.inner
            .flat_map(move |(x, t, d)| logic(x).into_iter().map(move |(x,d2)| (x, t.clone(), d2 * d)))
            .as_collection()
    }

    /// Brings a Collection into a nested scope.
    pub fn enter<'a, T>(&self, child: &Child<'a, G, T>) -> Collection<Child<'a, G, T>, D, R>
    where T: Timestamp {
        self.inner.enter(child)
                  .map(|(data, time, diff)| (data, Product::new(time, Default::default()), diff))
                  .as_collection()
    }
    /// Brings a Collection into a nested scope, at varying times.
    ///
    /// The `initial` function indicates the time at which each element of the Collection should appear.
    pub fn enter_at<'a, T, F>(&self, child: &Child<'a, G, T>, initial: F) -> Collection<Child<'a, G, T>, D, R>
    where T: Timestamp,
          F: Fn(&D) -> T + 'static,
          G::Timestamp: Hash, T: Hash {

        let initial1 = ::std::rc::Rc::new(initial);
        let initial2 = initial1.clone();

        self.inner.enter_at(child, move |x| (*initial1)(&x.0))
                  .map(move |(data, time, diff)| {
                      let new_time = Product::new(time, (*initial2)(&data));
                      (data, new_time, diff)
                  })
                  .as_collection()
    }
    /// Applies a supplied function to each update.
    ///
    /// This method is most commonly used to report information back to the user, often for debugging purposes.
    /// Any function can be used here, but be warned that the incremental nature of differential dataflow does
    /// not guarantee that it will be called as many times as you might expect.
    ///
    /// The `(data, time, diff)` triples indicate a change `diff` to the frequency of `data` which takes effect
    /// at the logical time `time`. When times are totally ordered (for example, `usize`), these updates reflect
    /// the changes along the sequence of collections. For partially ordered times, the mathematics are more
    /// interesting and less intuitive, unfortunately.
    pub fn inspect<F>(&self, func: F) -> Collection<G, D, R>
    where F: FnMut(&(D, G::Timestamp, R))+'static {
        self.inner.inspect(func)
                  .as_collection()
    }
    /// Applies a supplied function to each batch of updates.
    ///
    /// This method is analogous to `inspect`, but operates on batches and reveals the timely dataflow capability
    /// associated with the batch of updates.
    pub fn inspect_batch<F>(&self, func: F) -> Collection<G, D, R>
    where F: FnMut(&G::Timestamp, &[(D, G::Timestamp, R)])+'static {
        self.inner.inspect_batch(func)
                  .as_collection()
    }
    /// Attaches a timely dataflow probe to the output of a Collection.
    ///
    /// This probe is used to determine when the state of the Collection has stabilized and can
    /// be read out.
    pub fn probe(&self) -> probe::Handle<G::Timestamp> {
        self.inner.probe()
    }
    /// Attaches a timely dataflow probe to the output of a Collection.
    ///
    /// This probe is used to determine when the state of the Collection has stabilized and all updates observed.
    /// In addition, a probe is also often use to limit the number of rounds of input in flight at any moment; a
    /// computation can wait until the probe has caught up to the input before introducing more rounds of data, to
    /// avoid swamping the system.
    pub fn probe_with(&self, handle: &mut ::timely::dataflow::operators::probe::Handle<G::Timestamp>) -> Collection<G, D, R> {
        self.inner.probe_with(handle).as_collection()
    }
    /// The scope containing the underlying timely dataflow stream.
    pub fn scope(&self) -> G {
        self.inner.scope()
    }
}

impl<'a, G: Scope, T: Timestamp, D: Data, R: Diff> Collection<Child<'a, G, T>, D, R> {
    /// Returns the final value of a Collection from a nested scope to its containing scope.
    pub fn leave(&self) -> Collection<G, D, R> {
        self.inner.leave()
                  .map(|(data, time, diff)| (data, time.outer, diff))
                  .as_collection()
    }
}

/// Conversion to a differential dataflow Collection.
pub trait AsCollection<G: Scope, D: Data, R: Diff> {
    /// Converts the type to a differential dataflow collection.
    fn as_collection(&self) -> Collection<G, D, R>;
}

impl<G: Scope, D: Data, R: Diff> AsCollection<G, D, R> for Stream<G, (D, G::Timestamp, R)> {
    fn as_collection(&self) -> Collection<G, D, R> {
        Collection::new(self.clone())
    }
}<|endoftext|>


<commit_before>use compiler::*;
use typecheck::*;
use vm::*;
use interner::*;
use core::{Module, Type, Qualified};
use core::Type::{Application, Constructor};
use core::translate::*;
use lambda_lift::*;
use parser::Parser;
use renamer::{Name, rename_expr};

///Returns whether the type in question is an IO action
fn is_io(typ: &Type) -> bool {
    match *typ {
        Type::Application(ref lhs, _) =>
            match **lhs {
                Type::Constructor(ref op) => op.name.as_slice() == "IO",
                _ => false
            },
        _ => false
    }
}

///Compiles an expression into an assembly
fn compile_expr(prelude: &Assembly, expr_str: &str) -> Assembly {
    let mut parser = Parser::new(expr_str.chars());
    let mut expr = rename_expr(parser.expression_());

    let mut type_env = TypeEnvironment::new();
    type_env.add_types(prelude as &DataTypes);
    type_env.typecheck_expr(&mut expr);
    let temp_module = Module::from_expr(translate_expr(expr));
    let m = do_lambda_lift(temp_module);

    let mut compiler = Compiler::new();
    compiler.assemblies.push(prelude);
    compiler.compile_module(&m)
}

///Finds the main function and if it is an IO function, adds instructions to push the "RealWorld" argument
fn find_main(assembly: &Assembly) -> (Vec<Instruction>, Qualified<Type, Name>) {
    assembly.superCombinators.iter()
        .find(|sc| sc.name == Name { name: intern("main"), uid: 0 })
        .map(|sc| {
            if is_io(&sc.typ.value) {
                //If the expression we compiled is IO we need to add an extra argument
                //'RealWorld' which can be any dumb value (42 here), len - 3 is used because
                //it is currently 3 instructions Eval, Update(0), Unwind at the end of each instruction list
                //to finish the expression
                let mut vec: Vec<Instruction> = sc.instructions.iter().map(|x| x.clone()).collect();
                let len = vec.len();
                vec.insert(len - 3, Instruction::Mkap);
                vec.insert(0, Instruction::PushInt(42));//Realworld
                (vec, sc.typ.clone())
            }
            else {
                (sc.instructions.clone(), sc.typ.clone())
            }
        })
        .expect("Expected main function")
}

pub fn run_and_print_expr(expr_str: &str) {
    let prelude = compile_file("Prelude.hs");
    let mut vm = VM::new();
    vm.add_assembly(prelude);
    let assembly = compile_expr(vm.get_assembly(0), expr_str.as_slice());
    let (instructions, type_decl) = find_main(&assembly);
    let assembly_index = vm.add_assembly(assembly);
    let result = evaluate(&vm, &*instructions, assembly_index);//TODO 0 is not necessarily correct
    println!("{:?}  {:?}", result, type_decl);
}

///Starts the REPL
pub fn start() {
    let prelude = compile_file("Prelude.hs");
    let mut vm = VM::new();
    vm.add_assembly(prelude);
    for line in ::std::io::stdin().lock().lines() {
        let expr_str = match line {
            Ok(l) => l,
            Err(e) => panic!("Reading line failed with '{:?}'", e)
        };
        let assembly = compile_expr(vm.get_assembly(0), expr_str.as_slice());
        let (instructions, typ) = find_main(&assembly);
        let assembly_index = vm.add_assembly(assembly);
        let result = evaluate(&vm, &*instructions, assembly_index);//TODO 0 is not necessarily correct
        println!("{:?}  {:?}", result, typ);
    }
}
<commit_msg>Fixed repl.rs not getting the earlier changes incorporated<commit_after>use compiler::*;
use typecheck::*;
use vm::*;
use interner::*;
use core::{Module, Type, Qualified};
use core::Type::{Application, Constructor};
use core::translate::*;
use lambda_lift::*;
use parser::Parser;
use renamer::{Name, rename_expr};

///Returns whether the type in question is an IO action
fn is_io(typ: &Type) -> bool {
    match *typ {
        Type::Application(ref lhs, _) =>
            match **lhs {
                Type::Constructor(ref op) => op.name.as_slice() == "IO",
                _ => false
            },
        _ => false
    }
}

///Compiles an expression into an assembly
fn compile_expr(prelude: &Assembly, expr_str: &str) -> Assembly {
    let mut parser = Parser::new(expr_str.chars());
    let mut expr = rename_expr(parser.expression_());

    let mut type_env = TypeEnvironment::new();
    type_env.add_types(prelude as &DataTypes);
    type_env.typecheck_expr(&mut expr);
    let temp_module = Module::from_expr(translate_expr(expr));
    let m = do_lambda_lift(temp_module);

    let mut compiler = Compiler::new();
    compiler.assemblies.push(prelude);
    compiler.compile_module(&m)
}

///Finds the main function and if it is an IO function, adds instructions to push the "RealWorld" argument
fn find_main(assembly: &Assembly) -> (Vec<Instruction>, Qualified<Type, Name>) {
    assembly.super_combinators.iter()
        .find(|sc| sc.name == Name { name: intern("main"), uid: 0 })
        .map(|sc| {
            if is_io(&sc.typ.value) {
                //If the expression we compiled is IO we need to add an extra argument
                //'RealWorld' which can be any dumb value (42 here), len - 3 is used because
                //it is currently 3 instructions Eval, Update(0), Unwind at the end of each instruction list
                //to finish the expression
                let mut vec: Vec<Instruction> = sc.instructions.iter().map(|x| x.clone()).collect();
                let len = vec.len();
                vec.insert(len - 3, Instruction::Mkap);
                vec.insert(0, Instruction::PushInt(42));//Realworld
                (vec, sc.typ.clone())
            }
            else {
                (sc.instructions.clone(), sc.typ.clone())
            }
        })
        .expect("Expected main function")
}

pub fn run_and_print_expr(expr_str: &str) {
    let prelude = compile_file("Prelude.hs");
    let mut vm = VM::new();
    vm.add_assembly(prelude);
    let assembly = compile_expr(vm.get_assembly(0), expr_str.as_slice());
    let (instructions, type_decl) = find_main(&assembly);
    let assembly_index = vm.add_assembly(assembly);
    let result = vm.evaluate(&*instructions, assembly_index);//TODO 0 is not necessarily correct
    println!("{:?}  {:?}", result, type_decl);
}

///Starts the REPL
pub fn start() {
    let prelude = compile_file("Prelude.hs");
    let mut vm = VM::new();
    vm.add_assembly(prelude);
    for line in ::std::io::stdin().lock().lines() {
        let expr_str = match line {
            Ok(l) => l,
            Err(e) => panic!("Reading line failed with '{:?}'", e)
        };
        let assembly = compile_expr(vm.get_assembly(0), expr_str.as_slice());
        let (instructions, typ) = find_main(&assembly);
        let assembly_index = vm.add_assembly(assembly);
        let result = vm.evaluate(&*instructions, assembly_index);//TODO 0 is not necessarily correct
        println!("{:?}  {:?}", result, typ);
    }
}
<|endoftext|>


<commit_before>//! Compositor: wm state including the layout, helm, and interactions
//! state machines.

use std::sync::RwLock;

use rustwlc;
use rustwlc::*;
use rustwlc::handle::WlcView;

lazy_static! {
    static ref COMPOSITOR: RwLock<Compositor> = RwLock::new(Compositor::new());
}

const ERR_LOCK: &'static str = "Unable to lock compositor!";
const ERR_GEO: &'static str = "Unable to access view geometry!";

#[derive(Debug, PartialEq)]
pub struct Compositor {
    pub view: Option<WlcView>,
    pub grab: Point,
    pub edges: ResizeEdge,
    //pub actions: ClientState
}

impl Compositor {
    fn new() -> Compositor {
        Compositor {
            view: None,
            grab: Point {x: 0, y: 0},
            edges: ResizeEdge::empty()
        }
    }
}

#[derive(Debug, PartialEq, Clone)]
pub struct ClientState {
    view_action: ViewAction,
    next_action: ClickAction
}

impl Default for ClientState {
    fn default() -> ClientState {
        ClientState {
            view_action: ViewAction::None,
            next_action: ClickAction::None
        }
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[allow(dead_code)]
pub enum ViewAction {
    None,
    Resize,
    Move
}

impl ViewAction {
    /// Is this ViewAction set
    #[allow(dead_code)]
    pub fn is_some(&self) -> bool {
        *self != ViewAction::None
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
/// Actions that the user may set before clicking on a window
#[allow(dead_code)]
enum ClickAction {
    None,
    CloseWindow,
    BeginMoving,
    BeginResizing,
    SelectWindow,

}

/// Maximizes the view to the size of the output it sits in
pub fn set_focused_window_maximized(wlc_view: &WlcView) {
    let maybe_geometry = wlc_view.get_geometry();
    if maybe_geometry.is_none() {
        return;
    }
    let geometry = maybe_geometry.expect(ERR_GEO);
    start_interactive_action(wlc_view, &geometry.origin);
    {
        let mut comp = COMPOSITOR.write().expect(ERR_LOCK);
        if let Some(ref mut view) = comp.view {
            let output = view.get_output();
            trace!("Output size of the view: {:?}", output.get_resolution());
            let output_size = output.get_resolution();
            let geometry = Geometry { origin: Point { x: 0, y: 0},
                                        size: output_size.clone() };
            view.set_geometry(EDGE_NONE, &geometry);
        }
    }
    stop_interactive_action();
}

pub fn stop_interactive_action() {
    if let Ok(mut comp) = COMPOSITOR.write() {
        match comp.view {
            None => return,
            Some(ref view) => view.set_state(VIEW_RESIZING, false)
        }

        comp.view = None;
        comp.edges = ResizeEdge::empty();
    }
}

pub fn start_interactive_resize(view: &WlcView, edges: ResizeEdge, origin: &Point) {
    let geometry = match view.get_geometry() {
        None => { return; }
        Some(g) => g,
    };

    if !start_interactive_action(view, origin) {
        return;
    }
    let halfw = geometry.origin.x + geometry.size.w as i32 / 2;
    let halfh = geometry.origin.y + geometry.size.h as i32 / 2;

    if let Ok(mut comp) = COMPOSITOR.write() {
        comp.edges = edges.clone();
        if comp.edges.bits() == 0 {
            let flag_x = if origin.x < halfw {
                RESIZE_LEFT
            } else if origin.x > halfw {
                RESIZE_RIGHT
            } else {
                ResizeEdge::empty()
            };

            let flag_y = if origin.y < halfh {
                RESIZE_TOP
            } else if origin.y > halfh {
                RESIZE_BOTTOM
            } else {
                ResizeEdge::empty()
            };

            comp.edges = flag_x | flag_y;
        }
    }
    view.set_state(VIEW_RESIZING, true);
}

pub fn start_interactive_move(view: &WlcView, origin: &Point) -> bool {
    if let Ok(mut comp) = COMPOSITOR.write() {
        if comp.view != None {
            return false;
        }
        comp.grab = origin.clone();
        comp.view = Some(view.clone());
        true
    } else {
        false
    }

}

pub fn on_pointer_button(view: WlcView, _time: u32, mods: &KeyboardModifiers, button: u32,
                         state: ButtonState, point: &Point) -> bool {
    if state == ButtonState::Pressed {
        if !view.is_root() {
            view.focus();
            view.bring_to_front();
            if mods.mods.contains(MOD_CTRL) {
                // Button left, we need to include linux/input.h somehow
                if button == 0x110 {
                    start_interactive_move(&view, point);
                }
                if button == 0x111 {
                    start_interactive_resize(&view, ResizeEdge::empty(), point);
                }
                if mods.mods.contains(MOD_SHIFT) {
                    set_focused_window_maximized(&view);
                }
            }
        }
    }
    else {
        stop_interactive_action();
    }

    {
        let comp = COMPOSITOR.read().expect(ERR_LOCK);
        return comp.view.is_some();
    }
}

pub fn on_pointer_motion(_view: WlcView, _time: u32, point: &Point) -> bool {
    rustwlc::input::pointer::set_position(point);
    if let Ok(comp) = COMPOSITOR.read() {
        if let Some(ref view) = comp.view {
            let dx = point.x - comp.grab.x;
            let dy = point.y - comp.grab.y;
            let mut geo = view.get_geometry().expect(ERR_GEO).clone();
            if comp.edges.bits() != 0 {
                let min = Size { w: 80u32, h: 40u32};
                let mut new_geo = geo.clone();

                if comp.edges.contains(RESIZE_LEFT) {
                    if dx < 0 {
                        new_geo.size.w += dx.abs() as u32;
                    } else {
                        new_geo.size.w -= dx.abs() as u32;
                    }
                    new_geo.origin.x += dx;
                }
                else if comp.edges.contains(RESIZE_RIGHT) {
                    if dx < 0 {
                        new_geo.size.w -= dx.abs() as u32;
                    } else {
                        new_geo.size.w += dx.abs() as u32;
                    }
                }

                if comp.edges.contains(RESIZE_TOP) {
                    if dy < 0 {
                        new_geo.size.h += dy.abs() as u32;
                    } else {
                        new_geo.size.h -= dy.abs() as u32;
                    }
                    new_geo.origin.y += dy;
                }
                else if comp.edges.contains(RESIZE_BOTTOM) {
                    if dy < 0 {
                        new_geo.size.h -= dy.abs() as u32;
                    } else {
                        new_geo.size.h += dy.abs() as u32;
                    }
                }

                if new_geo.size.w >= min.w {
                    geo.origin.x = new_geo.origin.x;
                    geo.size.w = new_geo.size.w;
                }

                if new_geo.size.h >= min.h {
                    geo.origin.y = new_geo.origin.y;
                    geo.size.h = new_geo.size.h;
                }

                view.set_geometry(comp.edges, &geo);
            }
            else {
                geo.origin.x += dx;
                geo.origin.y += dy;
                view.set_geometry(ResizeEdge::empty(), &geo);
            }
        }
    }
    if let Ok(mut comp) = COMPOSITOR.write() {
        comp.grab = point.clone();
        comp.view.is_some()
    } else {
        false
    }
}

fn start_interactive_action(view: &WlcView, origin: &Point) -> bool {
    if let Ok(mut comp) = COMPOSITOR.write() {
        if comp.view != None {
            return false;
        }
        comp.grab = origin.clone();
        comp.view = Some(view.clone());
    }

    view.bring_to_front();
    return true;
}

<commit_msg>Fixed build error<commit_after>//! Compositor: wm state including the layout, helm, and interactions
//! state machines.

use std::sync::RwLock;

use rustwlc;
use rustwlc::*;

lazy_static! {
    static ref COMPOSITOR: RwLock<Compositor> = RwLock::new(Compositor::new());
}

const ERR_LOCK: &'static str = "Unable to lock compositor!";
const ERR_GEO: &'static str = "Unable to access view geometry!";

#[derive(Debug, PartialEq)]
pub struct Compositor {
    pub view: Option<WlcView>,
    pub grab: Point,
    pub edges: ResizeEdge,
    //pub actions: ClientState
}

impl Compositor {
    fn new() -> Compositor {
        Compositor {
            view: None,
            grab: Point {x: 0, y: 0},
            edges: ResizeEdge::empty()
        }
    }
}

#[derive(Debug, PartialEq, Clone)]
pub struct ClientState {
    view_action: ViewAction,
    next_action: ClickAction
}

impl Default for ClientState {
    fn default() -> ClientState {
        ClientState {
            view_action: ViewAction::None,
            next_action: ClickAction::None
        }
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[allow(dead_code)]
pub enum ViewAction {
    None,
    Resize,
    Move
}

impl ViewAction {
    /// Is this ViewAction set
    #[allow(dead_code)]
    pub fn is_some(&self) -> bool {
        *self != ViewAction::None
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
/// Actions that the user may set before clicking on a window
#[allow(dead_code)]
enum ClickAction {
    None,
    CloseWindow,
    BeginMoving,
    BeginResizing,
    SelectWindow,

}

/// Maximizes the view to the size of the output it sits in
pub fn set_focused_window_maximized(wlc_view: &WlcView) {
    let maybe_geometry = wlc_view.get_geometry();
    if maybe_geometry.is_none() {
        return;
    }
    let geometry = maybe_geometry.expect(ERR_GEO);
    start_interactive_action(wlc_view, &geometry.origin);
    {
        let mut comp = COMPOSITOR.write().expect(ERR_LOCK);
        if let Some(ref mut view) = comp.view {
            let output = view.get_output();
            trace!("Output size of the view: {:?}", output.get_resolution());
            let output_size = output.get_resolution();
            let geometry = Geometry { origin: Point { x: 0, y: 0},
                                        size: output_size.clone() };
            view.set_geometry(EDGE_NONE, &geometry);
        }
    }
    stop_interactive_action();
}

pub fn stop_interactive_action() {
    if let Ok(mut comp) = COMPOSITOR.write() {
        match comp.view {
            None => return,
            Some(ref view) => view.set_state(VIEW_RESIZING, false)
        }

        comp.view = None;
        comp.edges = ResizeEdge::empty();
    }
}

pub fn start_interactive_resize(view: &WlcView, edges: ResizeEdge, origin: &Point) {
    let geometry = match view.get_geometry() {
        None => { return; }
        Some(g) => g,
    };

    if !start_interactive_action(view, origin) {
        return;
    }
    let halfw = geometry.origin.x + geometry.size.w as i32 / 2;
    let halfh = geometry.origin.y + geometry.size.h as i32 / 2;

    if let Ok(mut comp) = COMPOSITOR.write() {
        comp.edges = edges.clone();
        if comp.edges.bits() == 0 {
            let flag_x = if origin.x < halfw {
                RESIZE_LEFT
            } else if origin.x > halfw {
                RESIZE_RIGHT
            } else {
                ResizeEdge::empty()
            };

            let flag_y = if origin.y < halfh {
                RESIZE_TOP
            } else if origin.y > halfh {
                RESIZE_BOTTOM
            } else {
                ResizeEdge::empty()
            };

            comp.edges = flag_x | flag_y;
        }
    }
    view.set_state(VIEW_RESIZING, true);
}

pub fn start_interactive_move(view: &WlcView, origin: &Point) -> bool {
    if let Ok(mut comp) = COMPOSITOR.write() {
        if comp.view != None {
            return false;
        }
        comp.grab = origin.clone();
        comp.view = Some(view.clone());
        true
    } else {
        false
    }

}

pub fn on_pointer_button(view: WlcView, _time: u32, mods: &KeyboardModifiers, button: u32,
                         state: ButtonState, point: &Point) -> bool {
    if state == ButtonState::Pressed {
        if !view.is_root() {
            view.focus();
            view.bring_to_front();
            if mods.mods.contains(MOD_CTRL) {
                // Button left, we need to include linux/input.h somehow
                if button == 0x110 {
                    start_interactive_move(&view, point);
                }
                if button == 0x111 {
                    start_interactive_resize(&view, ResizeEdge::empty(), point);
                }
                if mods.mods.contains(MOD_SHIFT) {
                    set_focused_window_maximized(&view);
                }
            }
        }
    }
    else {
        stop_interactive_action();
    }

    {
        let comp = COMPOSITOR.read().expect(ERR_LOCK);
        return comp.view.is_some();
    }
}

pub fn on_pointer_motion(_view: WlcView, _time: u32, point: &Point) -> bool {
    rustwlc::input::pointer::set_position(point);
    if let Ok(comp) = COMPOSITOR.read() {
        if let Some(ref view) = comp.view {
            let dx = point.x - comp.grab.x;
            let dy = point.y - comp.grab.y;
            let mut geo = view.get_geometry().expect(ERR_GEO).clone();
            if comp.edges.bits() != 0 {
                let min = Size { w: 80u32, h: 40u32};
                let mut new_geo = geo.clone();

                if comp.edges.contains(RESIZE_LEFT) {
                    if dx < 0 {
                        new_geo.size.w += dx.abs() as u32;
                    } else {
                        new_geo.size.w -= dx.abs() as u32;
                    }
                    new_geo.origin.x += dx;
                }
                else if comp.edges.contains(RESIZE_RIGHT) {
                    if dx < 0 {
                        new_geo.size.w -= dx.abs() as u32;
                    } else {
                        new_geo.size.w += dx.abs() as u32;
                    }
                }

                if comp.edges.contains(RESIZE_TOP) {
                    if dy < 0 {
                        new_geo.size.h += dy.abs() as u32;
                    } else {
                        new_geo.size.h -= dy.abs() as u32;
                    }
                    new_geo.origin.y += dy;
                }
                else if comp.edges.contains(RESIZE_BOTTOM) {
                    if dy < 0 {
                        new_geo.size.h -= dy.abs() as u32;
                    } else {
                        new_geo.size.h += dy.abs() as u32;
                    }
                }

                if new_geo.size.w >= min.w {
                    geo.origin.x = new_geo.origin.x;
                    geo.size.w = new_geo.size.w;
                }

                if new_geo.size.h >= min.h {
                    geo.origin.y = new_geo.origin.y;
                    geo.size.h = new_geo.size.h;
                }

                view.set_geometry(comp.edges, &geo);
            }
            else {
                geo.origin.x += dx;
                geo.origin.y += dy;
                view.set_geometry(ResizeEdge::empty(), &geo);
            }
        }
    }
    if let Ok(mut comp) = COMPOSITOR.write() {
        comp.grab = point.clone();
        comp.view.is_some()
    } else {
        false
    }
}

fn start_interactive_action(view: &WlcView, origin: &Point) -> bool {
    if let Ok(mut comp) = COMPOSITOR.write() {
        if comp.view != None {
            return false;
        }
        comp.grab = origin.clone();
        comp.view = Some(view.clone());
    }

    view.bring_to_front();
    return true;
}

<|endoftext|>


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

//! Rust wrappers around the raw JS apis

use libc::types::os::arch::c95::{size_t, c_uint};
use libc::uintptr_t;
use libc::c_char;
use std::cmp;
use std::ffi;
use std::rc;
use std::str;
use std::string;
use jsapi::*;
use jsapi::JSVersion::JSVERSION_LATEST;
use jsval::{JSVal, NullValue};
use default_stacksize;
use default_heapsize;
use JSOPTION_VAROBJFIX;
use JSOPTION_METHODJIT;
use JSOPTION_TYPE_INFERENCE;
use JSOPTION_DONT_REPORT_UNCAUGHT;
use JSOPTION_AUTOJSAPI_OWNS_ERROR_REPORTING;
use ERR;

// ___________________________________________________________________________
// friendly Rustic API to runtimes

pub type rt = rc::Rc<rt_rsrc>;

pub struct rt_rsrc {
    pub ptr : *mut JSRuntime,
}

impl Drop for rt_rsrc {
    fn drop(&mut self) {
        unsafe {
            JS_Finish(self.ptr);
        }
    }
}

pub fn new_runtime(p: *mut JSRuntime) -> rt {
    return rc::Rc::new(rt_rsrc {
        ptr: p
    })
}

pub trait RtUtils {
    fn cx(&self) -> rc::Rc<Cx>;
}

impl RtUtils for rc::Rc<rt_rsrc> {
    fn cx(&self) -> rc::Rc<Cx> {
        unsafe {
            new_context(JS_NewContext(self.ptr,
                                      default_stacksize as size_t), self.clone())
        }
    }
}

pub fn rt() -> rt {
    unsafe {
        let runtime = JS_Init(default_heapsize);
        return new_runtime(runtime);
    }
}

// ___________________________________________________________________________
// contexts

pub struct Cx {
    pub ptr: *mut JSContext,
    pub rt: rt,
}

#[unsafe_destructor]
impl Drop for Cx {
    fn drop(&mut self) {
        unsafe {
            JS_DestroyContext(self.ptr);
        }
    }
}

pub fn new_context(ptr: *mut JSContext, rt: rt) -> rc::Rc<Cx> {
    return rc::Rc::new(Cx {
        ptr: ptr,
        rt: rt,
    })
}

impl Cx {
    pub fn set_default_options_and_version(&self) {
        self.set_options(JSOPTION_VAROBJFIX | JSOPTION_METHODJIT |
                         JSOPTION_TYPE_INFERENCE |
                         JSOPTION_DONT_REPORT_UNCAUGHT |
                         JSOPTION_AUTOJSAPI_OWNS_ERROR_REPORTING);
        self.set_version(JSVERSION_LATEST);
    }

    pub fn set_options(&self, v: c_uint) {
        unsafe {
            JS_SetOptions(self.ptr, v);
        }
    }

    pub fn set_version(&self, v: JSVersion) {
        unsafe {
            JS_SetVersion(self.ptr, v);
        }
    }

    pub fn set_logging_error_reporter(&self) {
        unsafe {
            JS_SetErrorReporter(self.ptr, Some(reportError as unsafe extern "C" fn(*mut JSContext, *const c_char, *mut JSErrorReport)));
        }
    }

    pub fn set_error_reporter(&self, reportfn: unsafe extern "C" fn(*mut JSContext, *const c_char, *mut JSErrorReport)) {
        unsafe {
            JS_SetErrorReporter(self.ptr, Some(reportfn));
        }
    }

    pub fn evaluate_script(&self, glob: *mut JSObject, script: String, filename: String, line_num: uint)
                    -> Result<(),()> {
        let script_utf16: Vec<u16> = script.as_slice().utf16_units().collect();
        let filename_cstr = ffi::CString::from_slice(filename.as_bytes());
        let mut rval: JSVal = NullValue();
        debug!("Evaluating script from {} with content {}", filename, script);
        // SpiderMonkey does not approve of null pointers.
        let (ptr, len) = if script_utf16.len() == 0 {
            static empty: &'static [u16] = &[];
            (empty.as_ptr(), 0)
        } else {
            (script_utf16.as_ptr(), script_utf16.len() as c_uint)
        };
        assert!(!ptr.is_null());
        unsafe {
            if ERR == JS_EvaluateUCScript(self.ptr, glob, ptr, len,
                                          filename_cstr.as_ptr(), line_num as c_uint,
                                          &mut rval) {
                debug!("...err!");
                Err(())
            } else {
                // we could return the script result but then we'd have
                // to root it and so forth and, really, who cares?
                debug!("...ok!");
                Ok(())
            }
        }
    }
}

pub unsafe extern fn reportError(_cx: *mut JSContext, msg: *const c_char, report: *mut JSErrorReport) {
    let fnptr = (*report).filename;
    let fname = if !fnptr.is_null() {
        let c_str = ffi::c_str_to_bytes(&fnptr);
        str::from_utf8(c_str).ok().unwrap().to_string()
    } else {
        "none".to_string()
    };
    let lineno = (*report).lineno;
    let c_str = ffi::c_str_to_bytes(&msg);
    let msg = str::from_utf8(c_str).ok().unwrap().to_string();
    error!("Error at {}:{}: {}\n", fname, lineno, msg);
}

pub fn with_compartment<R, F: FnMut() -> R>(cx: *mut JSContext, object: *mut JSObject, mut cb: F) -> R {
    unsafe {
        let call = JS_EnterCrossCompartmentCall(cx, object);
        let result = cb();
        JS_LeaveCrossCompartmentCall(call);
        result
    }
}

#[cfg(test)]
pub mod test {
    use super::rt;
    use super::RtUtils;

    #[test]
    pub fn dummy() {
        let rt = rt();
        let cx = rt.cx();
        cx.deref().set_default_options_and_version();
        cx.deref().set_logging_error_reporter();
    }

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

//! Rust wrappers around the raw JS apis

use libc::types::os::arch::c95::{size_t, c_uint};
use libc::uintptr_t;
use libc::c_char;
use std::cmp;
use std::ffi;
use std::rc;
use std::str;
use std::string;
use std::u32;
use jsapi::*;
use jsapi::JSVersion::JSVERSION_LATEST;
use jsval::{JSVal, NullValue};
use default_stacksize;
use default_heapsize;
use JSOPTION_VAROBJFIX;
use JSOPTION_METHODJIT;
use JSOPTION_TYPE_INFERENCE;
use JSOPTION_DONT_REPORT_UNCAUGHT;
use JSOPTION_AUTOJSAPI_OWNS_ERROR_REPORTING;
use ERR;

// ___________________________________________________________________________
// friendly Rustic API to runtimes

/// A wrapper for the `JSRuntime` and `JSContext` structures in SpiderMonkey.
pub struct Runtime {
    pub rt: rt,
    pub cx: rc::Rc<Cx>,
}

impl Runtime {
    /// Creates a new `JSRuntime` and `JSContext`.
    pub fn new() -> Runtime {
        let js_runtime = rt();
        assert!({
            let ptr: *mut JSRuntime = (*js_runtime).ptr;
            !ptr.is_null()
        });

        // Unconstrain the runtime's threshold on nominal heap size, to avoid
        // triggering GC too often if operating continuously near an arbitrary
        // finite threshold. This leaves the maximum-JS_malloc-bytes threshold
        // still in effect to cause periodical, and we hope hygienic,
        // last-ditch GCs from within the GC's allocator.
        unsafe {
            JS_SetGCParameter(js_runtime.ptr, JSGC_MAX_BYTES, u32::MAX);
        }

        let js_context = js_runtime.cx();
        assert!({
            let ptr: *mut JSContext = (*js_context).ptr;
            !ptr.is_null()
        });
        js_context.set_default_options_and_version();
        js_context.set_logging_error_reporter();
        unsafe {
            JS_SetGCZeal((*js_context).ptr, 0, JS_DEFAULT_ZEAL_FREQ);
        }

        Runtime {
            rt: js_runtime,
            cx: js_context,
        }
    }

    /// Returns the `JSRuntime` object.
    pub fn rt(&self) -> *mut JSRuntime {
        self.rt.ptr
    }

    /// Returns the `JSContext` object.
    pub fn cx(&self) -> *mut JSContext {
        self.cx.ptr
    }
}

pub type rt = rc::Rc<rt_rsrc>;

pub struct rt_rsrc {
    pub ptr : *mut JSRuntime,
}

impl Drop for rt_rsrc {
    fn drop(&mut self) {
        unsafe {
            JS_Finish(self.ptr);
        }
    }
}

pub fn new_runtime(p: *mut JSRuntime) -> rt {
    return rc::Rc::new(rt_rsrc {
        ptr: p
    })
}

pub trait RtUtils {
    fn cx(&self) -> rc::Rc<Cx>;
}

impl RtUtils for rc::Rc<rt_rsrc> {
    fn cx(&self) -> rc::Rc<Cx> {
        unsafe {
            new_context(JS_NewContext(self.ptr,
                                      default_stacksize as size_t), self.clone())
        }
    }
}

pub fn rt() -> rt {
    unsafe {
        let runtime = JS_Init(default_heapsize);
        return new_runtime(runtime);
    }
}

// ___________________________________________________________________________
// contexts

pub struct Cx {
    pub ptr: *mut JSContext,
    pub rt: rt,
}

#[unsafe_destructor]
impl Drop for Cx {
    fn drop(&mut self) {
        unsafe {
            JS_DestroyContext(self.ptr);
        }
    }
}

pub fn new_context(ptr: *mut JSContext, rt: rt) -> rc::Rc<Cx> {
    return rc::Rc::new(Cx {
        ptr: ptr,
        rt: rt,
    })
}

impl Cx {
    pub fn set_default_options_and_version(&self) {
        self.set_options(JSOPTION_VAROBJFIX | JSOPTION_METHODJIT |
                         JSOPTION_TYPE_INFERENCE |
                         JSOPTION_DONT_REPORT_UNCAUGHT |
                         JSOPTION_AUTOJSAPI_OWNS_ERROR_REPORTING);
        self.set_version(JSVERSION_LATEST);
    }

    pub fn set_options(&self, v: c_uint) {
        unsafe {
            JS_SetOptions(self.ptr, v);
        }
    }

    pub fn set_version(&self, v: JSVersion) {
        unsafe {
            JS_SetVersion(self.ptr, v);
        }
    }

    pub fn set_logging_error_reporter(&self) {
        unsafe {
            JS_SetErrorReporter(self.ptr, Some(reportError as unsafe extern "C" fn(*mut JSContext, *const c_char, *mut JSErrorReport)));
        }
    }

    pub fn set_error_reporter(&self, reportfn: unsafe extern "C" fn(*mut JSContext, *const c_char, *mut JSErrorReport)) {
        unsafe {
            JS_SetErrorReporter(self.ptr, Some(reportfn));
        }
    }

    pub fn evaluate_script(&self, glob: *mut JSObject, script: String, filename: String, line_num: uint)
                    -> Result<(),()> {
        let script_utf16: Vec<u16> = script.as_slice().utf16_units().collect();
        let filename_cstr = ffi::CString::from_slice(filename.as_bytes());
        let mut rval: JSVal = NullValue();
        debug!("Evaluating script from {} with content {}", filename, script);
        // SpiderMonkey does not approve of null pointers.
        let (ptr, len) = if script_utf16.len() == 0 {
            static empty: &'static [u16] = &[];
            (empty.as_ptr(), 0)
        } else {
            (script_utf16.as_ptr(), script_utf16.len() as c_uint)
        };
        assert!(!ptr.is_null());
        unsafe {
            if ERR == JS_EvaluateUCScript(self.ptr, glob, ptr, len,
                                          filename_cstr.as_ptr(), line_num as c_uint,
                                          &mut rval) {
                debug!("...err!");
                Err(())
            } else {
                // we could return the script result but then we'd have
                // to root it and so forth and, really, who cares?
                debug!("...ok!");
                Ok(())
            }
        }
    }
}

pub unsafe extern fn reportError(_cx: *mut JSContext, msg: *const c_char, report: *mut JSErrorReport) {
    let fnptr = (*report).filename;
    let fname = if !fnptr.is_null() {
        let c_str = ffi::c_str_to_bytes(&fnptr);
        str::from_utf8(c_str).ok().unwrap().to_string()
    } else {
        "none".to_string()
    };
    let lineno = (*report).lineno;
    let c_str = ffi::c_str_to_bytes(&msg);
    let msg = str::from_utf8(c_str).ok().unwrap().to_string();
    error!("Error at {}:{}: {}\n", fname, lineno, msg);
}

pub fn with_compartment<R, F: FnMut() -> R>(cx: *mut JSContext, object: *mut JSObject, mut cb: F) -> R {
    unsafe {
        let call = JS_EnterCrossCompartmentCall(cx, object);
        let result = cb();
        JS_LeaveCrossCompartmentCall(call);
        result
    }
}

#[cfg(test)]
pub mod test {
    use super::rt;
    use super::RtUtils;

    #[test]
    pub fn dummy() {
        let rt = rt();
        let cx = rt.cx();
        cx.deref().set_default_options_and_version();
        cx.deref().set_logging_error_reporter();
    }

}
<|endoftext|>