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

#![allow(non_camel_case_types)]

use convert::TryInto;
use io;
use os::raw::c_char;
use u64;

use libc::{c_int, c_void};

pub type mx_handle_t = i32;
pub type mx_vaddr_t = usize;
pub type mx_rights_t = u32;
pub type mx_status_t = i32;

pub type mx_size_t = usize;
pub type mx_ssize_t = isize;

pub const MX_HANDLE_INVALID: mx_handle_t = 0;

pub type mx_time_t = u64;
pub const MX_TIME_INFINITE : mx_time_t = u64::MAX;

pub type mx_signals_t = u32;

pub const MX_OBJECT_SIGNAL_3         : mx_signals_t = 1 << 3;

pub const MX_TASK_TERMINATED        : mx_signals_t = MX_OBJECT_SIGNAL_3;

pub const MX_RIGHT_SAME_RIGHTS  : mx_rights_t = 1 << 31;

pub type mx_object_info_topic_t = u32;

pub const MX_INFO_PROCESS         : mx_object_info_topic_t = 3;

pub const MX_HND_TYPE_JOB: u32 = 6;

pub fn mx_cvt<T>(t: T) -> io::Result<T> where T: TryInto<mx_status_t>+Copy {
    if let Ok(status) = TryInto::try_into(t) {
        if status < 0 {
            Err(io::Error::from_raw_os_error(status))
        } else {
            Ok(t)
        }
    } else {
        Err(io::Error::last_os_error())
    }
}

// Safe wrapper around mx_handle_t
pub struct Handle {
    raw: mx_handle_t,
}

impl Handle {
    pub fn new(raw: mx_handle_t) -> Handle {
        Handle {
            raw: raw,
        }
    }

    pub fn raw(&self) -> mx_handle_t {
        self.raw
    }
}

impl Drop for Handle {
    fn drop(&mut self) {
        unsafe { mx_cvt(mx_handle_close(self.raw)).expect("Failed to close mx_handle_t"); }
    }
}

// Common MX_INFO header
#[derive(Default)]
#[repr(C)]
pub struct mx_info_header_t {
    pub topic: u32,              // identifies the info struct
    pub avail_topic_size: u16,   // “native” size of the struct
    pub topic_size: u16,         // size of the returned struct (<=topic_size)
    pub avail_count: u32,        // number of records the kernel has
    pub count: u32,              // number of records returned (limited by buffer size)
}

#[derive(Default)]
#[repr(C)]
pub struct mx_record_process_t {
    pub return_code: c_int,
}

// Returned for topic MX_INFO_PROCESS
#[derive(Default)]
#[repr(C)]
pub struct mx_info_process_t {
    pub hdr: mx_info_header_t,
    pub rec: mx_record_process_t,
}

extern {
    pub fn mx_task_kill(handle: mx_handle_t) -> mx_status_t;

    pub fn mx_handle_close(handle: mx_handle_t) -> mx_status_t;

    pub fn mx_handle_duplicate(handle: mx_handle_t, rights: mx_rights_t,
                               out: *const mx_handle_t) -> mx_handle_t;

    pub fn mx_handle_wait_one(handle: mx_handle_t, signals: mx_signals_t, timeout: mx_time_t,
                              pending: *mut mx_signals_t) -> mx_status_t;

    pub fn mx_object_get_info(handle: mx_handle_t, topic: u32, buffer: *mut c_void,
                              buffer_size: mx_size_t, actual_size: *mut mx_size_t,
                              avail: *mut mx_size_t) -> mx_status_t;
}

// Handle Info entries associate a type and optional
// argument with each handle included in the process
// arguments message.
pub fn mx_hnd_info(hnd_type: u32, arg: u32) -> u32 {
    (hnd_type & 0xFFFF) | ((arg & 0xFFFF) << 16)
}

extern {
    pub fn mxio_get_startup_handle(id: u32) -> mx_handle_t;
}

// From `enum special_handles` in system/ulib/launchpad/launchpad.c
#[allow(unused)] pub const HND_LOADER_SVC: usize = 0;
// HND_EXEC_VMO = 1
#[allow(unused)] pub const HND_SPECIAL_COUNT: usize = 2;

#[repr(C)]
pub struct launchpad_t {
    argc: u32,
    envc: u32,
    args: *const c_char,
    args_len: usize,
    env: *const c_char,
    env_len: usize,

    handles: *mut mx_handle_t,
    handles_info: *mut u32,
    handle_count: usize,
    handle_alloc: usize,

    entry: mx_vaddr_t,
    base: mx_vaddr_t,
    vdso_base: mx_vaddr_t,

    stack_size: usize,

    special_handles: [mx_handle_t; HND_SPECIAL_COUNT],
    loader_message: bool,
}

extern {
    pub fn launchpad_create(job: mx_handle_t, name: *const c_char,
                            lp: *mut *mut launchpad_t) -> mx_status_t;

    pub fn launchpad_start(lp: *mut launchpad_t) -> mx_status_t;

    pub fn launchpad_destroy(lp: *mut launchpad_t);

    pub fn launchpad_arguments(lp: *mut launchpad_t, argc: c_int,
                               argv: *const *const c_char) -> mx_status_t;

    pub fn launchpad_environ(lp: *mut launchpad_t, envp: *const *const c_char) -> mx_status_t;

    pub fn launchpad_clone_mxio_root(lp: *mut launchpad_t) -> mx_status_t;

    pub fn launchpad_clone_mxio_cwd(lp: *mut launchpad_t) -> mx_status_t;

    pub fn launchpad_clone_fd(lp: *mut launchpad_t, fd: c_int, target_fd: c_int) -> mx_status_t;

    pub fn launchpad_transfer_fd(lp: *mut launchpad_t, fd: c_int, target_fd: c_int) -> mx_status_t;

    pub fn launchpad_elf_load(lp: *mut launchpad_t, vmo: mx_handle_t) -> mx_status_t;

    pub fn launchpad_add_vdso_vmo(lp: *mut launchpad_t) -> mx_status_t;

    pub fn launchpad_load_vdso(lp: *mut launchpad_t, vmo: mx_handle_t) -> mx_status_t;

    pub fn launchpad_vmo_from_file(filename: *const c_char) -> mx_handle_t;
}
<commit_msg>Rollup merge of #38521 - jxson:remove-magenta-warnings, r=sfackler<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(non_camel_case_types)]

use convert::TryInto;
use io;
use os::raw::c_char;
use u64;

use libc::{c_int, c_void};

pub type mx_handle_t = i32;
pub type mx_vaddr_t = usize;
pub type mx_rights_t = u32;
pub type mx_status_t = i32;

pub type mx_size_t = usize;

pub const MX_HANDLE_INVALID: mx_handle_t = 0;

pub type mx_time_t = u64;
pub const MX_TIME_INFINITE : mx_time_t = u64::MAX;

pub type mx_signals_t = u32;

pub const MX_OBJECT_SIGNAL_3         : mx_signals_t = 1 << 3;

pub const MX_TASK_TERMINATED        : mx_signals_t = MX_OBJECT_SIGNAL_3;

pub const MX_RIGHT_SAME_RIGHTS  : mx_rights_t = 1 << 31;

pub type mx_object_info_topic_t = u32;

pub const MX_INFO_PROCESS         : mx_object_info_topic_t = 3;

pub const MX_HND_TYPE_JOB: u32 = 6;

pub fn mx_cvt<T>(t: T) -> io::Result<T> where T: TryInto<mx_status_t>+Copy {
    if let Ok(status) = TryInto::try_into(t) {
        if status < 0 {
            Err(io::Error::from_raw_os_error(status))
        } else {
            Ok(t)
        }
    } else {
        Err(io::Error::last_os_error())
    }
}

// Safe wrapper around mx_handle_t
pub struct Handle {
    raw: mx_handle_t,
}

impl Handle {
    pub fn new(raw: mx_handle_t) -> Handle {
        Handle {
            raw: raw,
        }
    }

    pub fn raw(&self) -> mx_handle_t {
        self.raw
    }
}

impl Drop for Handle {
    fn drop(&mut self) {
        unsafe { mx_cvt(mx_handle_close(self.raw)).expect("Failed to close mx_handle_t"); }
    }
}

// Common MX_INFO header
#[derive(Default)]
#[repr(C)]
pub struct mx_info_header_t {
    pub topic: u32,              // identifies the info struct
    pub avail_topic_size: u16,   // “native” size of the struct
    pub topic_size: u16,         // size of the returned struct (<=topic_size)
    pub avail_count: u32,        // number of records the kernel has
    pub count: u32,              // number of records returned (limited by buffer size)
}

#[derive(Default)]
#[repr(C)]
pub struct mx_record_process_t {
    pub return_code: c_int,
}

// Returned for topic MX_INFO_PROCESS
#[derive(Default)]
#[repr(C)]
pub struct mx_info_process_t {
    pub hdr: mx_info_header_t,
    pub rec: mx_record_process_t,
}

extern {
    pub fn mx_task_kill(handle: mx_handle_t) -> mx_status_t;

    pub fn mx_handle_close(handle: mx_handle_t) -> mx_status_t;

    pub fn mx_handle_duplicate(handle: mx_handle_t, rights: mx_rights_t,
                               out: *const mx_handle_t) -> mx_handle_t;

    pub fn mx_handle_wait_one(handle: mx_handle_t, signals: mx_signals_t, timeout: mx_time_t,
                              pending: *mut mx_signals_t) -> mx_status_t;

    pub fn mx_object_get_info(handle: mx_handle_t, topic: u32, buffer: *mut c_void,
                              buffer_size: mx_size_t, actual_size: *mut mx_size_t,
                              avail: *mut mx_size_t) -> mx_status_t;
}

// Handle Info entries associate a type and optional
// argument with each handle included in the process
// arguments message.
pub fn mx_hnd_info(hnd_type: u32, arg: u32) -> u32 {
    (hnd_type & 0xFFFF) | ((arg & 0xFFFF) << 16)
}

extern {
    pub fn mxio_get_startup_handle(id: u32) -> mx_handle_t;
}

// From `enum special_handles` in system/ulib/launchpad/launchpad.c
#[allow(unused)] pub const HND_LOADER_SVC: usize = 0;
// HND_EXEC_VMO = 1
#[allow(unused)] pub const HND_SPECIAL_COUNT: usize = 2;

#[repr(C)]
pub struct launchpad_t {
    argc: u32,
    envc: u32,
    args: *const c_char,
    args_len: usize,
    env: *const c_char,
    env_len: usize,

    handles: *mut mx_handle_t,
    handles_info: *mut u32,
    handle_count: usize,
    handle_alloc: usize,

    entry: mx_vaddr_t,
    base: mx_vaddr_t,
    vdso_base: mx_vaddr_t,

    stack_size: usize,

    special_handles: [mx_handle_t; HND_SPECIAL_COUNT],
    loader_message: bool,
}

extern {
    pub fn launchpad_create(job: mx_handle_t, name: *const c_char,
                            lp: *mut *mut launchpad_t) -> mx_status_t;

    pub fn launchpad_start(lp: *mut launchpad_t) -> mx_status_t;

    pub fn launchpad_destroy(lp: *mut launchpad_t);

    pub fn launchpad_arguments(lp: *mut launchpad_t, argc: c_int,
                               argv: *const *const c_char) -> mx_status_t;

    pub fn launchpad_environ(lp: *mut launchpad_t, envp: *const *const c_char) -> mx_status_t;

    pub fn launchpad_clone_mxio_root(lp: *mut launchpad_t) -> mx_status_t;

    pub fn launchpad_clone_mxio_cwd(lp: *mut launchpad_t) -> mx_status_t;

    pub fn launchpad_clone_fd(lp: *mut launchpad_t, fd: c_int, target_fd: c_int) -> mx_status_t;

    pub fn launchpad_transfer_fd(lp: *mut launchpad_t, fd: c_int, target_fd: c_int) -> mx_status_t;

    pub fn launchpad_elf_load(lp: *mut launchpad_t, vmo: mx_handle_t) -> mx_status_t;

    pub fn launchpad_add_vdso_vmo(lp: *mut launchpad_t) -> mx_status_t;

    pub fn launchpad_load_vdso(lp: *mut launchpad_t, vmo: mx_handle_t) -> mx_status_t;

    pub fn launchpad_vmo_from_file(filename: *const c_char) -> mx_handle_t;
}
<|endoftext|>


<commit_before>//! Produces the "deterministic" validator private keys used for inter-operability testing for
//! Ethereum 2.0 clients.
//!
//! Each private key is the first hash in the sha2 hash-chain that is less than 2^255. As such,
//! keys generated here are **not secret** and are **not for production use**.
//!
//! Note: these keys have not been tested against a reference implementation, yet.
#[macro_use]
extern crate lazy_static;

use eth2_hashing::hash;
use milagro_bls::{Keypair, PublicKey, SecretKey};
use num_bigint::BigUint;

pub const CURVE_ORDER_BITS: usize = 255;
pub const PRIVATE_KEY_BYTES: usize = 48;
pub const HASH_BYTES: usize = 32;

lazy_static! {
    static ref CURVE_ORDER: BigUint =
        "52435875175126190479447740508185965837690552500527637822603658699938581184513"
            .parse::<BigUint>()
            .expect("Curve order should be valid");
}

pub fn le_private_key(validator_index: usize) -> [u8; PRIVATE_KEY_BYTES] {
    let preimage = {
        let mut bytes = [0; HASH_BYTES];
        let index = validator_index.to_le_bytes();
        bytes[0..index.len()].copy_from_slice(&index);
        bytes
    };

    let privkey = BigUint::from_bytes_le(&hash(&preimage)) % &*CURVE_ORDER;

    let mut bytes = [0; PRIVATE_KEY_BYTES];
    let privkey_bytes = privkey.to_bytes_le();
    bytes[0..privkey_bytes.len()].copy_from_slice(&privkey_bytes);
    bytes
}

pub fn keypair(validator_index: usize) -> Keypair {
    let bytes = le_private_key(validator_index);

    let sk =
        SecretKey::from_bytes(&swap_bytes(bytes.to_vec())).expect("Should be valid private key");

    Keypair {
        pk: PublicKey::from_secret_key(&sk),
        sk,
    }
}

fn swap_bytes<T>(input: Vec<T>) -> Vec<T> {
    let mut output = vec![];
    input.into_iter().rev().for_each(|byte| output.push(byte));
    output
}
<commit_msg>Remove pub const from interop keypairs<commit_after>//! Produces the "deterministic" validator private keys used for inter-operability testing for
//! Ethereum 2.0 clients.
//!
//! Each private key is the first hash in the sha2 hash-chain that is less than 2^255. As such,
//! keys generated here are **not secret** and are **not for production use**.
//!
//! Note: these keys have not been tested against a reference implementation, yet.
#[macro_use]
extern crate lazy_static;

use eth2_hashing::hash;
use milagro_bls::{Keypair, PublicKey, SecretKey};
use num_bigint::BigUint;

pub const PRIVATE_KEY_BYTES: usize = 48;
pub const HASH_BYTES: usize = 32;

lazy_static! {
    static ref CURVE_ORDER: BigUint =
        "52435875175126190479447740508185965837690552500527637822603658699938581184513"
            .parse::<BigUint>()
            .expect("Curve order should be valid");
}

pub fn le_private_key(validator_index: usize) -> [u8; PRIVATE_KEY_BYTES] {
    let preimage = {
        let mut bytes = [0; HASH_BYTES];
        let index = validator_index.to_le_bytes();
        bytes[0..index.len()].copy_from_slice(&index);
        bytes
    };

    let privkey = BigUint::from_bytes_le(&hash(&preimage)) % &*CURVE_ORDER;

    let mut bytes = [0; PRIVATE_KEY_BYTES];
    let privkey_bytes = privkey.to_bytes_le();
    bytes[0..privkey_bytes.len()].copy_from_slice(&privkey_bytes);
    bytes
}

pub fn keypair(validator_index: usize) -> Keypair {
    let bytes = le_private_key(validator_index);

    let sk =
        SecretKey::from_bytes(&swap_bytes(bytes.to_vec())).expect("Should be valid private key");

    Keypair {
        pk: PublicKey::from_secret_key(&sk),
        sk,
    }
}

fn swap_bytes<T>(input: Vec<T>) -> Vec<T> {
    let mut output = vec![];
    input.into_iter().rev().for_each(|byte| output.push(byte));
    output
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::error;
use std::fmt;

use VulkanObject;
use buffer::TypedBufferAccess;
use device::Device;
use device::DeviceOwned;
use format::AcceptsPixels;
use format::Format;
use format::IncompatiblePixelsType;
use image::ImageAccess;

/// Type of operation to check.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum CheckCopyBufferImageTy {
    BufferToImage,
    ImageToBuffer,
}

/// Checks whether a copy buffer-image command is valid. Can check both buffer-to-image copies and
/// image-to-buffer copies.
///
/// # Panic
///
/// - Panics if the buffer and image were not created with `device`.
///
// TODO: handle compressed image formats
pub fn check_copy_buffer_image<B, I, P>(device: &Device, buffer: &B, image: &I,
                                        ty: CheckCopyBufferImageTy, image_offset: [u32; 3],
                                        image_size: [u32; 3], image_first_layer: u32,
                                        image_num_layers: u32, image_mipmap: u32)
                                        -> Result<(), CheckCopyBufferImageError>
    where I: ?Sized + ImageAccess,
          B: ?Sized + TypedBufferAccess<Content = [P]>,
          Format: AcceptsPixels<P>,     // TODO: use a trait on the image itself instead
{
    let buffer_inner = buffer.inner();
    let image_inner = image.inner();

    assert_eq!(buffer_inner.buffer.device().internal_object(),
               device.internal_object());
    assert_eq!(image_inner.image.device().internal_object(),
               device.internal_object());

    match ty {
        CheckCopyBufferImageTy::BufferToImage => {
            if !buffer_inner.buffer.usage_transfer_source() {
                return Err(CheckCopyBufferImageError::SourceMissingTransferUsage);
            }
            if !image_inner.image.usage_transfer_destination() {
                return Err(CheckCopyBufferImageError::DestinationMissingTransferUsage);
            }
        },
        CheckCopyBufferImageTy::ImageToBuffer => {
            if !image_inner.image.usage_transfer_source() {
                return Err(CheckCopyBufferImageError::SourceMissingTransferUsage);
            }
            if !buffer_inner.buffer.usage_transfer_destination() {
                return Err(CheckCopyBufferImageError::DestinationMissingTransferUsage);
            }
        },
    }

    if image.samples() != 1 {
        return Err(CheckCopyBufferImageError::UnexpectedMultisampled);
    }

    if image_mipmap >= image.mipmap_levels() {
        return Err(CheckCopyBufferImageError::ImageCoordinatesOutOfRange);
    }

    // TODO: wrong because we don't take the mipmap level into account for the dimensions
    let image_dimensions = image.dimensions();

    if image_first_layer + image_num_layers > image_dimensions.array_layers() {
        return Err(CheckCopyBufferImageError::ImageCoordinatesOutOfRange);
    }

    if image_offset[0] + image_size[0] > image_dimensions.width() {
        return Err(CheckCopyBufferImageError::ImageCoordinatesOutOfRange);
    }

    if image_offset[1] + image_size[1] > image_dimensions.height() {
        return Err(CheckCopyBufferImageError::ImageCoordinatesOutOfRange);
    }

    if image_offset[2] + image_size[2] > image_dimensions.depth() {
        return Err(CheckCopyBufferImageError::ImageCoordinatesOutOfRange);
    }

    image.format().ensure_accepts()?;

    if image_dimensions.num_texels() as usize * image.format().rate() as usize > buffer.len() {
        return Err(CheckCopyBufferImageError::BufferTooSmall);
    }

    // TODO: check memory overlap?

    Ok(())
}

/// Error that can happen from `check_copy_buffer_image`.
#[derive(Debug, Copy, Clone)]
pub enum CheckCopyBufferImageError {
    /// The source buffer or image is missing the transfer source usage.
    SourceMissingTransferUsage,
    /// The destination buffer or image is missing the transfer destination usage.
    DestinationMissingTransferUsage,
    /// The source and destination are overlapping.
    OverlappingRanges,
    /// The image must not be multisampled.
    UnexpectedMultisampled,
    /// The image coordinates are out of range.
    ImageCoordinatesOutOfRange,
    /// The type of pixels in the buffer isn't compatible with the image format.
    WrongPixelType(IncompatiblePixelsType),
    /// The buffer is too small for the copy operation.
    BufferTooSmall,
}

impl error::Error for CheckCopyBufferImageError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            CheckCopyBufferImageError::SourceMissingTransferUsage => {
                "the source buffer is missing the transfer source usage"
            },
            CheckCopyBufferImageError::DestinationMissingTransferUsage => {
                "the destination buffer is missing the transfer destination usage"
            },
            CheckCopyBufferImageError::OverlappingRanges => {
                "the source and destination are overlapping"
            },
            CheckCopyBufferImageError::UnexpectedMultisampled => {
                "the image must not be multisampled"
            },
            CheckCopyBufferImageError::ImageCoordinatesOutOfRange => {
                "the image coordinates are out of range"
            },
            CheckCopyBufferImageError::WrongPixelType(_) => {
                "the type of pixels in the buffer isn't compatible with the image format"
            },
            CheckCopyBufferImageError::BufferTooSmall => {
                "the buffer is too small for the copy operation"
            },
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            CheckCopyBufferImageError::WrongPixelType(ref err) => {
                Some(err)
            },
            _ => None
        }
    }
}

impl fmt::Display for CheckCopyBufferImageError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "{}", error::Error::description(self))
    }
}

impl From<IncompatiblePixelsType> for CheckCopyBufferImageError {
    #[inline]
    fn from(err: IncompatiblePixelsType) -> CheckCopyBufferImageError {
        CheckCopyBufferImageError::WrongPixelType(err)
    }
}
<commit_msg>Fix wrong image dimensions being checked when copying from buffer (#728)<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::error;
use std::fmt;

use VulkanObject;
use buffer::TypedBufferAccess;
use device::Device;
use device::DeviceOwned;
use format::AcceptsPixels;
use format::Format;
use format::IncompatiblePixelsType;
use image::ImageAccess;

/// Type of operation to check.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum CheckCopyBufferImageTy {
    BufferToImage,
    ImageToBuffer,
}

/// Checks whether a copy buffer-image command is valid. Can check both buffer-to-image copies and
/// image-to-buffer copies.
///
/// # Panic
///
/// - Panics if the buffer and image were not created with `device`.
///
// TODO: handle compressed image formats
pub fn check_copy_buffer_image<B, I, P>(device: &Device, buffer: &B, image: &I,
                                        ty: CheckCopyBufferImageTy, image_offset: [u32; 3],
                                        image_size: [u32; 3], image_first_layer: u32,
                                        image_num_layers: u32, image_mipmap: u32)
                                        -> Result<(), CheckCopyBufferImageError>
    where I: ?Sized + ImageAccess,
          B: ?Sized + TypedBufferAccess<Content = [P]>,
          Format: AcceptsPixels<P>,     // TODO: use a trait on the image itself instead
{
    let buffer_inner = buffer.inner();
    let image_inner = image.inner();

    assert_eq!(buffer_inner.buffer.device().internal_object(),
               device.internal_object());
    assert_eq!(image_inner.image.device().internal_object(),
               device.internal_object());

    match ty {
        CheckCopyBufferImageTy::BufferToImage => {
            if !buffer_inner.buffer.usage_transfer_source() {
                return Err(CheckCopyBufferImageError::SourceMissingTransferUsage);
            }
            if !image_inner.image.usage_transfer_destination() {
                return Err(CheckCopyBufferImageError::DestinationMissingTransferUsage);
            }
        },
        CheckCopyBufferImageTy::ImageToBuffer => {
            if !image_inner.image.usage_transfer_source() {
                return Err(CheckCopyBufferImageError::SourceMissingTransferUsage);
            }
            if !buffer_inner.buffer.usage_transfer_destination() {
                return Err(CheckCopyBufferImageError::DestinationMissingTransferUsage);
            }
        },
    }

    if image.samples() != 1 {
        return Err(CheckCopyBufferImageError::UnexpectedMultisampled);
    }

    if image_mipmap >= image.mipmap_levels() {
        return Err(CheckCopyBufferImageError::ImageCoordinatesOutOfRange);
    }

    // TODO: wrong because we don't take the mipmap level into account for the dimensions
    let image_dimensions = image.dimensions();

    if image_first_layer + image_num_layers > image_dimensions.array_layers() {
        return Err(CheckCopyBufferImageError::ImageCoordinatesOutOfRange);
    }

    if image_offset[0] + image_size[0] > image_dimensions.width() {
        return Err(CheckCopyBufferImageError::ImageCoordinatesOutOfRange);
    }

    if image_offset[1] + image_size[1] > image_dimensions.height() {
        return Err(CheckCopyBufferImageError::ImageCoordinatesOutOfRange);
    }

    if image_offset[2] + image_size[2] > image_dimensions.depth() {
        return Err(CheckCopyBufferImageError::ImageCoordinatesOutOfRange);
    }

    image.format().ensure_accepts()?;

    {
        let num_texels = image_size[0] * image_size[1] * image_size[2] * image_num_layers;
        let required_len = num_texels as usize * image.format().rate() as usize;
        if required_len > buffer.len() {
            return Err(CheckCopyBufferImageError::BufferTooSmall {
                required_len: required_len,
                actual_len: buffer.len(),
            });
        }
    }

    // TODO: check memory overlap?

    Ok(())
}

/// Error that can happen from `check_copy_buffer_image`.
#[derive(Debug, Copy, Clone)]
pub enum CheckCopyBufferImageError {
    /// The source buffer or image is missing the transfer source usage.
    SourceMissingTransferUsage,
    /// The destination buffer or image is missing the transfer destination usage.
    DestinationMissingTransferUsage,
    /// The source and destination are overlapping.
    OverlappingRanges,
    /// The image must not be multisampled.
    UnexpectedMultisampled,
    /// The image coordinates are out of range.
    ImageCoordinatesOutOfRange,
    /// The type of pixels in the buffer isn't compatible with the image format.
    WrongPixelType(IncompatiblePixelsType),
    /// The buffer is too small for the copy operation.
    BufferTooSmall {
        /// Required number of elements in the buffer.
        required_len: usize,
        /// Actual number of elements in the buffer.
        actual_len: usize,
    },
}

impl error::Error for CheckCopyBufferImageError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            CheckCopyBufferImageError::SourceMissingTransferUsage => {
                "the source buffer is missing the transfer source usage"
            },
            CheckCopyBufferImageError::DestinationMissingTransferUsage => {
                "the destination buffer is missing the transfer destination usage"
            },
            CheckCopyBufferImageError::OverlappingRanges => {
                "the source and destination are overlapping"
            },
            CheckCopyBufferImageError::UnexpectedMultisampled => {
                "the image must not be multisampled"
            },
            CheckCopyBufferImageError::ImageCoordinatesOutOfRange => {
                "the image coordinates are out of range"
            },
            CheckCopyBufferImageError::WrongPixelType(_) => {
                "the type of pixels in the buffer isn't compatible with the image format"
            },
            CheckCopyBufferImageError::BufferTooSmall { .. } => {
                "the buffer is too small for the copy operation"
            },
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            CheckCopyBufferImageError::WrongPixelType(ref err) => {
                Some(err)
            },
            _ => None
        }
    }
}

impl fmt::Display for CheckCopyBufferImageError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "{}", error::Error::description(self))
    }
}

impl From<IncompatiblePixelsType> for CheckCopyBufferImageError {
    #[inline]
    fn from(err: IncompatiblePixelsType) -> CheckCopyBufferImageError {
        CheckCopyBufferImageError::WrongPixelType(err)
    }
}
<|endoftext|>


<commit_before>use nalgebra::na::Translation;
use nalgebra::na;
use math::{Scalar, Vect, RotationMatrix};
use bounding_volume::{BoundingVolume, BoundingSphere};

// FIXME: make a structure 'cone' ?
struct SpacializedCone {
    sphere:  BoundingSphere,
    axis:    Vect,
    angle:   Scalar,
    changle: Scalar,
    shangle: Scalar
}

impl SpacializedCone {
    pub fn new(sphere: BoundingSphere, axis: Vect, angle: Scalar) -> SpacializedCone {
        let axis = na::normalize(&axis);

        SpacializedCone {
            sphere:  sphere,
            axis:    axis,
            angle:   angle,
            changle: angle.cos(),
            shangle: angle.sin(),
        }
    }

    #[inline]
    pub fn sphere<'a>(&'a self) -> &'a BoundingSphere {
        &self.sphere
    }

    #[inline]
    pub fn axis<'a>(&'a self) -> &'a Vect {
        &self.axis
    }

    #[inline]
    pub fn hangle(&self) -> Scalar {
        self.hangle.clone()
    }
}

impl BoundingVolume for SpacializedCone {
    #[inline]
    fn intersects(&self, other: &SpacializedCone) -> bool {
        if self.sphere.intersects(&other.sphere) {
            let cangle = na::dot(&self.axis, &(-other.axis));

            // cos(a + b) = cos(b) cos(b) + sin(a) sin(b)
            let angsum = self.changle * other.changle - self.shangle * other.shangle;

            cangle >= angsum
        }
        else {
            false
        }
    }

    #[inline]
    fn contains(&self, other: &SpacializedCone) -> bool {
        if self.sphere.contains(&other.sphere) && self.changle >= other.changle {
            let cangle = na::dot(&self.axis, &other.axis);

            cangle >= self.changle
        }
        else {
            false
        }
    }

    #[inline]
    fn merge(&mut self, other: &SpacializedCone) {
        self.sphere.merge(other.sphere);

        // merge the cone
        let alpha = na::dot(&self.axis, &other.axis).acos();

        let mut rot_axis = na::cross(&self.axis, &other.axis);
        if !rot_axis.normalize().is_zero() {
            let dangle = (alpha - self.angle + other.angle) * na::cast(0.5f64);
            let rot    = na::append_rotation(&na::one::<RotationMatrix>(), &(rot_axis * dangle));

            self.axis    = rot * self.axis;
            self.angle   = na::clamp(self.angle + other.angle + alpha, na::zero(), Float::pi());
            self.changle = self.angle.cos();
            self.shangle = self.angle.sin();
        }
        else {
            self.angle   = Float::pi();
            self.changle = -na::one::<Scalar>();
            self.shangle = na::zero();
        }
    }

    #[inline]
    fn merged(&self, other: &SpacializedCone) -> SpacializedCone {
        let mut res = self.clone();

        res.merge(other);

        res
    }
}

impl Translation<Vect> for SpacializedCone {
    #[inline]
    fn translation(&self) -> Vect {
        self.sphere.center.clone()
    }

    #[inline]
    fn inv_translation(&self) -> Vect {
        -self.sphere.translation()
    }

    #[inline]
    fn append_translation(&mut self, dv: &Vect) {
        self.sphere.center = self.sphere.center + *dv
    }

    #[inline]
    fn append_translation_cpy(sc: &SpacializedCone, dv: &Vect) -> SpacializedCone {
        SpacializedCone::new(
            BoundingSphere::new(sc.sphere.center + *dv, sc.sphere.radius),
            sc.axis.clone(),
            sc.angle.clone())
    }

    #[inline]
    fn prepend_translation(&mut self, dv: &Vect) {
        self.sphere.append_translation(dv)
    }

    #[inline]
    fn prepend_translation_cpy(sc: &SpacializedCone, dv: &Vect) -> SpacializedCone {
        Translation::append_translation_cpy(sc, dv)
    }

    #[inline]
    fn set_translation(&mut self, v: Vect) {
        self.sphere.center = v
    }
}
<commit_msg>Fix the spacialized cone.<commit_after>use std::num::Zero;
use nalgebra::na::{Norm, Translation};
use nalgebra::na;
use math::{Scalar, Vect, RotationMatrix};
use bounding_volume::{BoundingVolume, BoundingSphere};

// FIXME: make a structure 'cone' ?
#[deriving(Show, PartialEq, Clone, Encodable, Decodable)]
/// A normal cone with a bounding sphere.
pub struct SpacializedCone {
    sphere:  BoundingSphere,
    axis:    Vect,
    hangle:  Scalar,
}

impl SpacializedCone {
    /// Creates a new spacialized cone with a given bounding sphere, axis, and half-angle.
    pub fn new(sphere: BoundingSphere, axis: Vect, hangle: Scalar) -> SpacializedCone {
        let axis = na::normalize(&axis);

        SpacializedCone {
            sphere:  sphere,
            axis:    axis,
            hangle:   hangle
        }
    }

    /// The bounding sphere of this spacialized cone.
    #[inline]
    pub fn sphere<'a>(&'a self) -> &'a BoundingSphere {
        &self.sphere
    }

    /// This cone axis.
    #[inline]
    pub fn axis<'a>(&'a self) -> &'a Vect {
        &self.axis
    }

    /// This cone half angle.
    #[inline]
    pub fn hangle(&self) -> Scalar {
        self.hangle.clone()
    }
}

#[not_dim4]
impl BoundingVolume for SpacializedCone {
    #[inline]
    fn intersects(&self, other: &SpacializedCone) -> bool {
        if self.sphere.intersects(&other.sphere) {
            let dangle = na::dot(&self.axis, &(-other.axis));
            println!("dot: {}", dangle);
            let dangle = na::clamp(dangle, -na::one::<Scalar>(), na::one()).acos();
            let angsum = self.hangle + other.hangle;

            println!("c: {} a: {}", dangle, angsum);

            dangle <= angsum
        }
        else {
            false
        }
    }

    #[inline]
    fn contains(&self, other: &SpacializedCone) -> bool {
        if self.sphere.contains(&other.sphere) {
            fail!("Not yet implemented.")
        }
        else {
            false
        }
    }

    #[inline]
    fn merge(&mut self, other: &SpacializedCone) {
        self.sphere.merge(&other.sphere);

        // merge the cone
        let alpha = na::clamp(na::dot(&self.axis, &other.axis), -na::one::<Scalar>(), na::one()).acos();

        let mut rot_axis = na::cross(&self.axis, &other.axis);
        if !rot_axis.normalize().is_zero() {
            let dangle = (alpha - self.hangle + other.hangle) * na::cast(0.5f64);
            let rot    = na::append_rotation(&na::one::<RotationMatrix>(), &(rot_axis * dangle));

            self.axis    = rot * self.axis;
            self.hangle  = na::clamp(self.hangle + other.hangle + alpha, na::zero(), Float::pi());

            // println!("merged {} {} with hangle: {}", *self, *other, self.hangle);
        }
        else {
            // This happens if alpha ~= 0 or alpha ~= pi.
            if alpha > na::one() { // NOTE: 1.0 is just a randomly chosen number in-between 0 and pi.
                // alpha ~= pi
                self.hangle = alpha;
            }
            else {
                // alpha ~= 0, do nothing.
            }
        }
    }

    #[inline]
    fn merged(&self, other: &SpacializedCone) -> SpacializedCone {
        let mut res = self.clone();

        res.merge(other);

        res
    }
}

impl Translation<Vect> for SpacializedCone {
    #[inline]
    fn translation(&self) -> Vect {
        self.sphere.center().clone()
    }

    #[inline]
    fn inv_translation(&self) -> Vect {
        -self.sphere.translation()
    }

    #[inline]
    fn append_translation(&mut self, dv: &Vect) {
        self.sphere.append_translation(dv);
    }

    #[inline]
    fn append_translation_cpy(sc: &SpacializedCone, dv: &Vect) -> SpacializedCone {
        SpacializedCone::new(
            Translation::append_translation_cpy(&sc.sphere, dv),
            sc.axis.clone(),
            sc.hangle.clone())
    }

    #[inline]
    fn prepend_translation(&mut self, dv: &Vect) {
        self.sphere.append_translation(dv)
    }

    #[inline]
    fn prepend_translation_cpy(sc: &SpacializedCone, dv: &Vect) -> SpacializedCone {
        Translation::append_translation_cpy(sc, dv)
    }

    #[inline]
    fn set_translation(&mut self, v: Vect) {
        self.sphere.set_translation(v)
    }
}
<|endoftext|>


<commit_before>#[cfg(feature = "image")]
extern crate image;

#[macro_use]
extern crate glium;

use glium::glutin;
#[cfg(feature = "image")]
use std::io::Cursor;
#[cfg(feature = "image")]
use glium::Surface;

mod support;

#[cfg(not(all(feature = "image", feature = "nalgebra")))]
fn main() {
    println!("This example requires the `image` feature to be enabled");
}

#[cfg(all(feature = "image", feature = "nalgebra"))]
fn main() {
    use glium::DisplayBuild;

    // building the display, ie. the main object
    let display = glutin::WindowBuilder::new()
        .build_glium()
        .unwrap();

    let image = image::load(Cursor::new(&include_bytes!("../tests/fixture/opengl.png")[..]),
        image::PNG).unwrap();
    let opengl_texture = glium::texture::CompressedSrgbTexture2d::new(&display, image);

    // building the vertex buffer, which contains all the vertices that we will draw
    let vertex_buffer = {
        #[derive(Copy, Clone)]
        struct Vertex {
            position: [f32; 3],
            tex_coords: [f32; 2],
        }

        implement_vertex!(Vertex, position, tex_coords);

        glium::VertexBuffer::new(&display,
            vec![
                Vertex { position: [-0.5,  0.5, 3.0], tex_coords: [1.0, 1.0] },
                Vertex { position: [ 0.5,  0.5, 3.0], tex_coords: [0.0, 1.0] },
                Vertex { position: [-0.5, -0.5, 3.0], tex_coords: [1.0, 0.0] },
                Vertex { position: [ 0.5,  0.5, 3.0], tex_coords: [0.0, 1.0] },
                Vertex { position: [ 0.5, -0.5, 3.0], tex_coords: [0.0, 0.0] },
                Vertex { position: [-0.5, -0.5, 3.0], tex_coords: [1.0, 0.0] },
            ]
        )
    };

    // compiling shaders and linking them together
    let program = glium::Program::new(&display,
        glium::program::SourceCode {
            vertex_shader: "
                #version 400

                in vec3 position;
                in vec2 tex_coords;

                out vec3 v_position;
                out vec3 v_normal;
                out vec2 v_tex_coords;

                void main() {
                    v_position = position;
                    v_normal = vec3(0.0, 0.0, -1.0);
                    v_tex_coords = tex_coords;
                }
            ",
            tessellation_control_shader: Some("
                #version 400

                layout(vertices = 3) out;

                in vec3 v_position[];
                in vec3 v_normal[];
                in vec2 v_tex_coords[];

                out vec3 tc_position[];
                out vec3 tc_normal[];
                out vec2 tc_tex_coords[];

                uniform float inner_level;
                uniform float outer_level;

                void main() {
                    tc_position[gl_InvocationID] = v_position[gl_InvocationID];
                    tc_normal[gl_InvocationID]   = v_normal[gl_InvocationID];
                    tc_tex_coords[gl_InvocationID] = v_tex_coords[gl_InvocationID];

                    gl_TessLevelOuter[0] = outer_level;
                    gl_TessLevelOuter[1] = outer_level;
                    gl_TessLevelOuter[2] = outer_level;
                    gl_TessLevelOuter[3] = outer_level;
                    gl_TessLevelInner[0] = inner_level;
                    gl_TessLevelInner[1] = inner_level;
                }
            "),
            tessellation_evaluation_shader: Some("
                #version 400

                layout(triangles, equal_spacing, ccw) in;

                in vec3 tc_position[];
                in vec3 tc_normal[];
                in vec2 tc_tex_coords[];

                out vec4 te_position;
                out vec3 te_normal;
                out vec2 te_tex_coords;

                uniform mat4 projection_matrix;
                uniform mat4 view_matrix;

                uniform sampler2D height_texture;
                uniform float elevation;

                void main() {
                    vec3 pos = gl_TessCoord.x * tc_position[0] +
                               gl_TessCoord.y * tc_position[1] +
                               gl_TessCoord.z * tc_position[2];

                    vec3 normal = normalize(gl_TessCoord.x * tc_normal[0] +
                                            gl_TessCoord.y * tc_normal[1] +
                                            gl_TessCoord.z * tc_normal[2]);

                    vec2 tex_coords = gl_TessCoord.x * tc_tex_coords[0] +
                                      gl_TessCoord.y * tc_tex_coords[1] +
                                      gl_TessCoord.z * tc_tex_coords[2];

                    float height = length(texture(height_texture, tex_coords));
                    pos += normal * (height * elevation);

                    te_position = projection_matrix * view_matrix * vec4(pos, 1.0);
                    te_normal = vec3(view_matrix * vec4(normal, 1.0)).xyz;
                    te_tex_coords = tex_coords;
                }
            "),
            geometry_shader: Some("
                #version 400

                layout(triangles) in;
                layout(triangle_strip, max_vertices = 3) out;

                uniform mat4 view_matrix;

                in vec4 te_position[3];
                in vec3 te_normal[3];
                in vec2 te_tex_coords[3];

                out vec3 g_normal;
                out vec2 g_tex_coords;

                void main() {
                    g_normal = te_normal[0];
                    g_tex_coords = te_tex_coords[0];
                    gl_Position = te_position[0];
                    EmitVertex();

                    g_normal = te_normal[1];
                    g_tex_coords = te_tex_coords[1];
                    gl_Position = te_position[1];
                    EmitVertex();

                    g_normal = te_normal[2];
                    g_tex_coords = te_tex_coords[2];
                    gl_Position = te_position[2];
                    EmitVertex();

                    EndPrimitive();
                }
            "),
            fragment_shader: "
                #version 400

                in vec3 g_normal;
                in vec2 g_tex_coords;

                uniform sampler2D color_texture;

                const vec3 LIGHT = vec3(-0.2, 0.1, 0.8);

                void main() {
                    float lum = max(dot(normalize(g_normal), normalize(LIGHT)), 0.0);
                    vec3 tex_color = texture(color_texture, g_tex_coords).rgb;
                    vec3 color = (0.6 + 0.4 * lum) * tex_color;
                    gl_FragColor = vec4(color, 1.0);
                }
            ",
        }).unwrap();

    let camera = support::camera::CameraState::new();

    // the main loop
    support::start_loop(|| {
        // building the uniforms
        let uniforms = uniform! {
            inner_level: 64.0f32,
            outer_level: 64.0f32,
            projection_matrix: camera.get_perspective(),
            view_matrix: [
                [1.0, 0.0, 0.0, 0.0],
                [0.0, 1.0, 0.0, 0.0],
                [0.0, 0.0, 1.0, 0.0],
                [0.0, 0.0, 0.0, 1.0f32]
            ],
            height_texture: &opengl_texture,
            elevation: 0.3f32,
            color_texture: &opengl_texture
        };

        // drawing a frame
        let mut target = display.draw();
        target.clear_color(0.0, 0.0, 0.0, 1.0);
        target.draw(&vertex_buffer,
                    &glium::index::NoIndices(glium::index::PrimitiveType::Patches {
                        vertices_per_patch: 3
                    }),
                    &program, &uniforms,
                    &std::default::Default::default()).unwrap();
        target.finish();

        // polling and handling the events received by the window
        for event in display.poll_events() {
            match event {
                glutin::Event::Closed => return support::Action::Stop,
                _ => ()
            }
        }

        support::Action::Continue
    });
}
<commit_msg>Fix example shader using deprecated builtin variable<commit_after>#[cfg(feature = "image")]
extern crate image;

#[macro_use]
extern crate glium;

use glium::glutin;
#[cfg(feature = "image")]
use std::io::Cursor;
#[cfg(feature = "image")]
use glium::Surface;

mod support;

#[cfg(not(all(feature = "image", feature = "nalgebra")))]
fn main() {
    println!("This example requires the `image` feature to be enabled");
}

#[cfg(all(feature = "image", feature = "nalgebra"))]
fn main() {
    use glium::DisplayBuild;

    // building the display, ie. the main object
    let display = glutin::WindowBuilder::new()
        .build_glium()
        .unwrap();

    let image = image::load(Cursor::new(&include_bytes!("../tests/fixture/opengl.png")[..]),
        image::PNG).unwrap();
    let opengl_texture = glium::texture::CompressedSrgbTexture2d::new(&display, image);

    // building the vertex buffer, which contains all the vertices that we will draw
    let vertex_buffer = {
        #[derive(Copy, Clone)]
        struct Vertex {
            position: [f32; 3],
            tex_coords: [f32; 2],
        }

        implement_vertex!(Vertex, position, tex_coords);

        glium::VertexBuffer::new(&display,
            vec![
                Vertex { position: [-0.5,  0.5, 3.0], tex_coords: [1.0, 1.0] },
                Vertex { position: [ 0.5,  0.5, 3.0], tex_coords: [0.0, 1.0] },
                Vertex { position: [-0.5, -0.5, 3.0], tex_coords: [1.0, 0.0] },
                Vertex { position: [ 0.5,  0.5, 3.0], tex_coords: [0.0, 1.0] },
                Vertex { position: [ 0.5, -0.5, 3.0], tex_coords: [0.0, 0.0] },
                Vertex { position: [-0.5, -0.5, 3.0], tex_coords: [1.0, 0.0] },
            ]
        )
    };

    // compiling shaders and linking them together
    let program = glium::Program::new(&display,
        glium::program::SourceCode {
            vertex_shader: "
                #version 400

                in vec3 position;
                in vec2 tex_coords;

                out vec3 v_position;
                out vec3 v_normal;
                out vec2 v_tex_coords;

                void main() {
                    v_position = position;
                    v_normal = vec3(0.0, 0.0, -1.0);
                    v_tex_coords = tex_coords;
                }
            ",
            tessellation_control_shader: Some("
                #version 400

                layout(vertices = 3) out;

                in vec3 v_position[];
                in vec3 v_normal[];
                in vec2 v_tex_coords[];

                out vec3 tc_position[];
                out vec3 tc_normal[];
                out vec2 tc_tex_coords[];

                uniform float inner_level;
                uniform float outer_level;

                void main() {
                    tc_position[gl_InvocationID] = v_position[gl_InvocationID];
                    tc_normal[gl_InvocationID]   = v_normal[gl_InvocationID];
                    tc_tex_coords[gl_InvocationID] = v_tex_coords[gl_InvocationID];

                    gl_TessLevelOuter[0] = outer_level;
                    gl_TessLevelOuter[1] = outer_level;
                    gl_TessLevelOuter[2] = outer_level;
                    gl_TessLevelOuter[3] = outer_level;
                    gl_TessLevelInner[0] = inner_level;
                    gl_TessLevelInner[1] = inner_level;
                }
            "),
            tessellation_evaluation_shader: Some("
                #version 400

                layout(triangles, equal_spacing, ccw) in;

                in vec3 tc_position[];
                in vec3 tc_normal[];
                in vec2 tc_tex_coords[];

                out vec4 te_position;
                out vec3 te_normal;
                out vec2 te_tex_coords;

                uniform mat4 projection_matrix;
                uniform mat4 view_matrix;

                uniform sampler2D height_texture;
                uniform float elevation;

                void main() {
                    vec3 pos = gl_TessCoord.x * tc_position[0] +
                               gl_TessCoord.y * tc_position[1] +
                               gl_TessCoord.z * tc_position[2];

                    vec3 normal = normalize(gl_TessCoord.x * tc_normal[0] +
                                            gl_TessCoord.y * tc_normal[1] +
                                            gl_TessCoord.z * tc_normal[2]);

                    vec2 tex_coords = gl_TessCoord.x * tc_tex_coords[0] +
                                      gl_TessCoord.y * tc_tex_coords[1] +
                                      gl_TessCoord.z * tc_tex_coords[2];

                    float height = length(texture(height_texture, tex_coords));
                    pos += normal * (height * elevation);

                    te_position = projection_matrix * view_matrix * vec4(pos, 1.0);
                    te_normal = vec3(view_matrix * vec4(normal, 1.0)).xyz;
                    te_tex_coords = tex_coords;
                }
            "),
            geometry_shader: Some("
                #version 400

                layout(triangles) in;
                layout(triangle_strip, max_vertices = 3) out;

                uniform mat4 view_matrix;

                in vec4 te_position[3];
                in vec3 te_normal[3];
                in vec2 te_tex_coords[3];

                out vec3 g_normal;
                out vec2 g_tex_coords;

                void main() {
                    g_normal = te_normal[0];
                    g_tex_coords = te_tex_coords[0];
                    gl_Position = te_position[0];
                    EmitVertex();

                    g_normal = te_normal[1];
                    g_tex_coords = te_tex_coords[1];
                    gl_Position = te_position[1];
                    EmitVertex();

                    g_normal = te_normal[2];
                    g_tex_coords = te_tex_coords[2];
                    gl_Position = te_position[2];
                    EmitVertex();

                    EndPrimitive();
                }
            "),
            fragment_shader: "
                #version 400

                in vec3 g_normal;
                in vec2 g_tex_coords;

                out vec4 o_color;

                uniform sampler2D color_texture;

                const vec3 LIGHT = vec3(-0.2, 0.1, 0.8);

                void main() {
                    float lum = max(dot(normalize(g_normal), normalize(LIGHT)), 0.0);
                    vec3 tex_color = texture(color_texture, g_tex_coords).rgb;
                    vec3 color = (0.6 + 0.4 * lum) * tex_color;
                    o_color = vec4(1.0, 0.0, 0.0, 1.0);
                }
            ",
        }).unwrap();

    let camera = support::camera::CameraState::new();

    // the main loop
    support::start_loop(|| {
        // building the uniforms
        let uniforms = uniform! {
            inner_level: 64.0f32,
            outer_level: 64.0f32,
            projection_matrix: camera.get_perspective(),
            view_matrix: [
                [1.0, 0.0, 0.0, 0.0],
                [0.0, 1.0, 0.0, 0.0],
                [0.0, 0.0, 1.0, 0.0],
                [0.0, 0.0, 0.0, 1.0f32]
            ],
            height_texture: &opengl_texture,
            elevation: 0.3f32,
            color_texture: &opengl_texture
        };

        // drawing a frame
        let mut target = display.draw();
        target.clear_color(0.0, 0.0, 0.0, 1.0);
        target.draw(&vertex_buffer,
                    &glium::index::NoIndices(glium::index::PrimitiveType::Patches {
                        vertices_per_patch: 3
                    }),
                    &program, &uniforms,
                    &std::default::Default::default()).unwrap();
        target.finish();

        // polling and handling the events received by the window
        for event in display.poll_events() {
            match event {
                glutin::Event::Closed => return support::Action::Stop,
                _ => ()
            }
        }

        support::Action::Continue
    });
}
<|endoftext|>


<commit_before>use std::ops::Mul;
use std::io;
use std::net;
use std::string::FromUtf8Error;
use uuid;
use super::*;
use FromCursor;

// https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v4.spec#L813

// Decodes Cassandra `ascii` data (bytes) into Rust's `Result<String, FromUtf8Error>`.
pub fn decode_custom(bytes: Vec<u8>) -> Result<String, FromUtf8Error> {
     String::from_utf8(bytes)
}

// Decodes Cassandra `ascii` data (bytes) into Rust's `Result<String, FromUtf8Error>`.
pub fn decode_ascii(bytes: Vec<u8>) -> Result<String, FromUtf8Error> {
    String::from_utf8(bytes)
}

// Decodes Cassandra `varchar` data (bytes) into Rust's `Result<String, FromUtf8Error>`.
pub fn decode_varchar(bytes: Vec<u8>) -> Result<String, FromUtf8Error> {
     String::from_utf8(bytes)
}

// Decodes Cassandra `bigint` data (bytes) into Rust's `Result<i32, io::Error>`
pub fn decode_bigint(bytes: Vec<u8>) -> Result<i64, io::Error> {
     try_from_bytes(bytes).map(|i| i as i64)
}

// Decodes Cassandra `blob` data (bytes) into Rust's `Result<Vec<u8>, io::Error>`
pub fn decode_blob(bytes: Vec<u8>) -> Result<Vec<u8>, io::Error> {
    // in fact we just pass it through.
     Ok(bytes)
}

// Decodes Cassandra `boolean` data (bytes) into Rust's `Result<i32, io::Error>`
pub fn decode_boolean(bytes: Vec<u8>) -> Result<bool, io::Error> {
    let false_byte: u8 = 0;
    bytes.first()
        .ok_or(io::Error::new(io::ErrorKind::UnexpectedEof, "no bytes were found"))
        .map(|b| b != &false_byte)
}

// Decodes Cassandra `int` data (bytes) into Rust's `Result<i32, io::Error>`
pub fn decode_int(bytes: Vec<u8>) -> Result<i32, io::Error> {
    try_from_bytes(bytes).map(|i| i as i32)
}

// Decodes Cassandra `date` data (bytes) into Rust's `Result<i32, io::Error>` in following way
//    0: -5877641-06-23
// 2^31: 1970-1-1
// 2^32: 5881580-07-11
pub fn decode_date(bytes: Vec<u8>) -> Result<i32, io::Error> {
    try_from_bytes(bytes).map(|i| i as i32)
}

// TODO: make sure this method meets the specification.
// Decodes Cassandra `decimal` data (bytes) into Rust's `Result<f32, io::Error>`
pub fn decode_decimal(bytes: Vec<u8>) -> Result<f32, io::Error> {
    let ref separator = b'E';
    let lr: Vec<Vec<u8>> = bytes.split(|ch| ch == separator).map(|p| p.to_vec()).collect();
    let unscaled = try_i_from_bytes(lr[0].clone());
    if unscaled.is_err() {
        return Err(unscaled.unwrap_err());
    }
    let scaled = try_i_from_bytes(lr[1].clone());
    if scaled.is_err() {
        return Err(unscaled.unwrap_err());
    }

    let unscaled_unwrapped: f32 = unscaled.unwrap() as f32;
    let scaled_unwrapped: i32 = scaled.unwrap() as i32;
    let dec: f32 = 10.0;
    Ok(unscaled_unwrapped.mul(dec.powi(scaled_unwrapped)))
}

// Decodes Cassandra `double` data (bytes) into Rust's `Result<f32, io::Error>`
pub fn decode_double(bytes: Vec<u8>) -> Result<f64, io::Error> {
    try_f64_from_bytes(bytes)
}

// Decodes Cassandra `float` data (bytes) into Rust's `Result<f32, io::Error>`
pub fn decode_float(bytes: Vec<u8>) -> Result<f32, io::Error> {
    try_f32_from_bytes(bytes)
}

// Decodes Cassandra `inet` data (bytes) into Rust's `Result<net::IpAddr, io::Error>`
pub fn decode_inet(bytes: Vec<u8>) -> Result<net::IpAddr, io::Error> {
    match bytes.len() {
        // v4
        4 => {
            Ok(net::IpAddr::V4(net::Ipv4Addr::new(bytes[0], bytes[1], bytes[2], bytes[3])))
        },
        // v6
        16 => {
            let a = from_u16_bytes(bytes[0..2].to_vec());
            let b = from_u16_bytes(bytes[2..4].to_vec());
            let c = from_u16_bytes(bytes[4..6].to_vec());
            let d = from_u16_bytes(bytes[6..8].to_vec());
            let e = from_u16_bytes(bytes[8..10].to_vec());
            let f = from_u16_bytes(bytes[10..12].to_vec());
            let g = from_u16_bytes(bytes[12..14].to_vec());
            let h = from_u16_bytes(bytes[14..16].to_vec());
            Ok(net::IpAddr::V6(net::Ipv6Addr::new(a, b, c, d, e, f, g, h)))
        },
        _ => unreachable!()
    }
}

// Decodes Cassandra `timestamp` data (bytes) into Rust's `Result<i32, io::Error>`
// `i32` represets a millisecond-precision
//  offset from the unix epoch (00:00:00, January 1st, 1970).  Negative values
//  represent a negative offset from the epoch.
pub fn decode_timestamp(bytes: Vec<u8>) -> Result<i64, io::Error> {
    try_from_bytes(bytes).map(|i| i as i64)
}

// Decodes Cassandra `list` data (bytes) into Rust's `Result<Vec<CBytes>, io::Error>`
pub fn decode_list(bytes: Vec<u8>) -> Result<Vec<CBytes>, io::Error> {
    let mut cursor: io::Cursor<Vec<u8>> = io::Cursor::new(bytes);
    let l = CInt::from_cursor(&mut cursor);
    let list = (0..l).map(|_| CBytes::from_cursor(&mut cursor)).collect();
    Ok(list)
}

// Decodes Cassandra `set` data (bytes) into Rust's `Result<Vec<CBytes>, io::Error>`
pub fn decode_set(bytes: Vec<u8>) -> Result<Vec<CBytes>, io::Error> {
    let mut cursor: io::Cursor<Vec<u8>> = io::Cursor::new(bytes);
    let l = CInt::from_cursor(&mut cursor);
    let list = (0..l).map(|_| CBytes::from_cursor(&mut cursor)).collect();
    Ok(list)
}

// Decodes Cassandra `map` data (bytes) into Rust's `Result<Vec<(CBytes, CBytes)>, io::Error>`
pub fn decode_map(bytes: Vec<u8>) -> Result<Vec<(CBytes, CBytes)>, io::Error> {
    let mut cursor: io::Cursor<Vec<u8>> = io::Cursor::new(bytes);
    let l = CInt::from_cursor(&mut cursor);
    let list = (0..l).map(|_| {
        return (CBytes::from_cursor(&mut cursor), CBytes::from_cursor(&mut cursor));
    }).collect();
    Ok(list)
}

// Decodes Cassandra `smallint` data (bytes) into Rust's `Result<i16, io::Error>`
pub fn decode_smallint(bytes: Vec<u8>) -> Result<i16, io::Error> {
    try_from_bytes(bytes).map(|i| i as i16)
}

// Decodes Cassandra `text` data (bytes) into Rust's `Result<String, FromUtf8Error>`.
pub fn decode_text(bytes: Vec<u8>) -> Result<String, FromUtf8Error> {
    String::from_utf8(bytes)
}

// Decodes Cassandra `time` data (bytes) into Rust's `Result<String, FromUtf8Error>`.
pub fn decode_time(bytes: Vec<u8>) -> Result<i64, io::Error> {
    try_i_from_bytes(bytes)
}

// Decodes Cassandra `timeuuid` data (bytes) into Rust's `Result<uuid::Uuid, uuid::ParseError>`
pub fn decode_timeuuid(bytes: Vec<u8>) -> Result<uuid::Uuid, uuid::ParseError> {
    uuid::Uuid::from_bytes(bytes.as_slice())
}

// Decodes Cassandra `varint` data (bytes) into Rust's `Result<i64, io::Error>`
pub fn decode_varint(bytes: Vec<u8>) -> Result<i64, io::Error> {
    try_i_from_bytes(bytes)
}

// Decodes Cassandra `Udt` data (bytes) into Rust's `Result<Vec<CBytes>, io::Error>`
// each `CBytes` is encoded type of field of user defined type
pub fn decode_udt(bytes: Vec<u8>) -> Result<Vec<CBytes>, io::Error> {
    let mut cursor: io::Cursor<Vec<u8>> = io::Cursor::new(bytes);
    let l = CInt::from_cursor(&mut cursor);
    let list = (0..l).map(|_| CBytes::from_cursor(&mut cursor)).collect();
    Ok(list)
}
<commit_msg>review comment<commit_after>use std::ops::Mul;
use std::io;
use std::net;
use std::string::FromUtf8Error;
use uuid;
use super::*;
use FromCursor;

// https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v4.spec#L813

// Decodes Cassandra `ascii` data (bytes) into Rust's `Result<String, FromUtf8Error>`.
pub fn decode_custom(bytes: Vec<u8>) -> Result<String, FromUtf8Error> {
     String::from_utf8(bytes)
}

// Decodes Cassandra `ascii` data (bytes) into Rust's `Result<String, FromUtf8Error>`.
pub fn decode_ascii(bytes: Vec<u8>) -> Result<String, FromUtf8Error> {
    String::from_utf8(bytes)
}

// Decodes Cassandra `varchar` data (bytes) into Rust's `Result<String, FromUtf8Error>`.
pub fn decode_varchar(bytes: Vec<u8>) -> Result<String, FromUtf8Error> {
     String::from_utf8(bytes)
}

// Decodes Cassandra `bigint` data (bytes) into Rust's `Result<i32, io::Error>`
pub fn decode_bigint(bytes: Vec<u8>) -> Result<i64, io::Error> {
     try_from_bytes(bytes).map(|i| i as i64)
}

// Decodes Cassandra `blob` data (bytes) into Rust's `Result<Vec<u8>, io::Error>`
pub fn decode_blob(bytes: Vec<u8>) -> Result<Vec<u8>, io::Error> {
    // in fact we just pass it through.
     Ok(bytes)
}

// Decodes Cassandra `boolean` data (bytes) into Rust's `Result<i32, io::Error>`
pub fn decode_boolean(bytes: Vec<u8>) -> Result<bool, io::Error> {
    let false_byte: u8 = 0;
    bytes.first()
        .ok_or(io::Error::new(io::ErrorKind::UnexpectedEof, "no bytes were found"))
        .map(|b| b != &false_byte)
}

// Decodes Cassandra `int` data (bytes) into Rust's `Result<i32, io::Error>`
pub fn decode_int(bytes: Vec<u8>) -> Result<i32, io::Error> {
    try_from_bytes(bytes).map(|i| i as i32)
}

// Decodes Cassandra `date` data (bytes) into Rust's `Result<i32, io::Error>` in following way
//    0: -5877641-06-23
// 2^31: 1970-1-1
// 2^32: 5881580-07-11
pub fn decode_date(bytes: Vec<u8>) -> Result<i32, io::Error> {
    try_from_bytes(bytes).map(|i| i as i32)
}

// TODO: make sure this method meets the specification.
// Decodes Cassandra `decimal` data (bytes) into Rust's `Result<f32, io::Error>`
pub fn decode_decimal(bytes: Vec<u8>) -> Result<f32, io::Error> {
    let ref separator = b'E';
    let lr: Vec<Vec<u8>> = bytes.split(|ch| ch == separator).map(|p| p.to_vec()).collect();
    let unscaled = try_i_from_bytes(lr[0].clone());
    if unscaled.is_err() {
        return Err(unscaled.unwrap_err());
    }
    let scaled = try_i_from_bytes(lr[1].clone());
    if scaled.is_err() {
        return Err(scaled.unwrap_err());
    }

    let unscaled_unwrapped: f32 = unscaled.unwrap() as f32;
    let scaled_unwrapped: i32 = scaled.unwrap() as i32;
    let dec: f32 = 10.0;
    Ok(unscaled_unwrapped.mul(dec.powi(scaled_unwrapped)))
}

// Decodes Cassandra `double` data (bytes) into Rust's `Result<f32, io::Error>`
pub fn decode_double(bytes: Vec<u8>) -> Result<f64, io::Error> {
    try_f64_from_bytes(bytes)
}

// Decodes Cassandra `float` data (bytes) into Rust's `Result<f32, io::Error>`
pub fn decode_float(bytes: Vec<u8>) -> Result<f32, io::Error> {
    try_f32_from_bytes(bytes)
}

// Decodes Cassandra `inet` data (bytes) into Rust's `Result<net::IpAddr, io::Error>`
pub fn decode_inet(bytes: Vec<u8>) -> Result<net::IpAddr, io::Error> {
    match bytes.len() {
        // v4
        4 => {
            Ok(net::IpAddr::V4(net::Ipv4Addr::new(bytes[0], bytes[1], bytes[2], bytes[3])))
        },
        // v6
        16 => {
            let a = from_u16_bytes(bytes[0..2].to_vec());
            let b = from_u16_bytes(bytes[2..4].to_vec());
            let c = from_u16_bytes(bytes[4..6].to_vec());
            let d = from_u16_bytes(bytes[6..8].to_vec());
            let e = from_u16_bytes(bytes[8..10].to_vec());
            let f = from_u16_bytes(bytes[10..12].to_vec());
            let g = from_u16_bytes(bytes[12..14].to_vec());
            let h = from_u16_bytes(bytes[14..16].to_vec());
            Ok(net::IpAddr::V6(net::Ipv6Addr::new(a, b, c, d, e, f, g, h)))
        },
        _ => unreachable!()
    }
}

// Decodes Cassandra `timestamp` data (bytes) into Rust's `Result<i32, io::Error>`
// `i32` represets a millisecond-precision
//  offset from the unix epoch (00:00:00, January 1st, 1970).  Negative values
//  represent a negative offset from the epoch.
pub fn decode_timestamp(bytes: Vec<u8>) -> Result<i64, io::Error> {
    try_from_bytes(bytes).map(|i| i as i64)
}

// Decodes Cassandra `list` data (bytes) into Rust's `Result<Vec<CBytes>, io::Error>`
pub fn decode_list(bytes: Vec<u8>) -> Result<Vec<CBytes>, io::Error> {
    let mut cursor: io::Cursor<Vec<u8>> = io::Cursor::new(bytes);
    let l = CInt::from_cursor(&mut cursor);
    let list = (0..l).map(|_| CBytes::from_cursor(&mut cursor)).collect();
    Ok(list)
}

// Decodes Cassandra `set` data (bytes) into Rust's `Result<Vec<CBytes>, io::Error>`
pub fn decode_set(bytes: Vec<u8>) -> Result<Vec<CBytes>, io::Error> {
    let mut cursor: io::Cursor<Vec<u8>> = io::Cursor::new(bytes);
    let l = CInt::from_cursor(&mut cursor);
    let list = (0..l).map(|_| CBytes::from_cursor(&mut cursor)).collect();
    Ok(list)
}

// Decodes Cassandra `map` data (bytes) into Rust's `Result<Vec<(CBytes, CBytes)>, io::Error>`
pub fn decode_map(bytes: Vec<u8>) -> Result<Vec<(CBytes, CBytes)>, io::Error> {
    let mut cursor: io::Cursor<Vec<u8>> = io::Cursor::new(bytes);
    let l = CInt::from_cursor(&mut cursor);
    let list = (0..l).map(|_| {
        return (CBytes::from_cursor(&mut cursor), CBytes::from_cursor(&mut cursor));
    }).collect();
    Ok(list)
}

// Decodes Cassandra `smallint` data (bytes) into Rust's `Result<i16, io::Error>`
pub fn decode_smallint(bytes: Vec<u8>) -> Result<i16, io::Error> {
    try_from_bytes(bytes).map(|i| i as i16)
}

// Decodes Cassandra `text` data (bytes) into Rust's `Result<String, FromUtf8Error>`.
pub fn decode_text(bytes: Vec<u8>) -> Result<String, FromUtf8Error> {
    String::from_utf8(bytes)
}

// Decodes Cassandra `time` data (bytes) into Rust's `Result<String, FromUtf8Error>`.
pub fn decode_time(bytes: Vec<u8>) -> Result<i64, io::Error> {
    try_i_from_bytes(bytes)
}

// Decodes Cassandra `timeuuid` data (bytes) into Rust's `Result<uuid::Uuid, uuid::ParseError>`
pub fn decode_timeuuid(bytes: Vec<u8>) -> Result<uuid::Uuid, uuid::ParseError> {
    uuid::Uuid::from_bytes(bytes.as_slice())
}

// Decodes Cassandra `varint` data (bytes) into Rust's `Result<i64, io::Error>`
pub fn decode_varint(bytes: Vec<u8>) -> Result<i64, io::Error> {
    try_i_from_bytes(bytes)
}

// Decodes Cassandra `Udt` data (bytes) into Rust's `Result<Vec<CBytes>, io::Error>`
// each `CBytes` is encoded type of field of user defined type
pub fn decode_udt(bytes: Vec<u8>) -> Result<Vec<CBytes>, io::Error> {
    let mut cursor: io::Cursor<Vec<u8>> = io::Cursor::new(bytes);
    let l = CInt::from_cursor(&mut cursor);
    let list = (0..l).map(|_| CBytes::from_cursor(&mut cursor)).collect();
    Ok(list)
}
<|endoftext|>


<commit_before>///
/// This example parses, sorts and groups the iris dataset
/// and does some simple manipulations.
///
/// Iterators and itertools functionality are used throughout.
///
///

extern crate itertools;

use itertools::Itertools;
use std::str::FromStr;
use std::collections::HashMap;

static DATA: &'static str = include_str!("iris.data");

#[derive(Clone, Debug)]
struct Iris {
    name: String,
    data: [f32; 4],
}

#[derive(Clone, Debug)]
enum ParseError {
    Numeric(<f32 as FromStr>::Err),
    Other(&'static str),
}

/// Parse an Iris from a comma-separated line
impl FromStr for Iris {
    type Err = ParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut iris = Iris { name: "".into(), data: [0.; 4] };
        let mut parts = s.split(",").map(str::trim);

        // using Iterator::by_ref()
        for (index, part) in parts.by_ref().take(4).enumerate() {
            iris.data[index] = try!(part.parse::<f32>().map_err(ParseError::Numeric));
        }
        if let Some(name) = parts.next() {
            iris.name = name.into();
        } else {
            return Err(ParseError::Other("Missing name"))
        }
        Ok(iris)
    }
}

fn main() {
    // using itertools::Itertools::fold_results to create the result of parsing
    let irises = DATA.lines()
                     .map(str::parse)
                     .fold_results(Vec::new(), |mut v, iris: Iris| {
                         v.push(iris);
                         v
                     }).unwrap();

    // Sort them and group them
    let mut irises = irises;
    irises.sort_by(|a, b| Ord::cmp(&a.name, &b.name));

    // using Iterator::cycle()
    let mut plot_symbols = "+ox".chars().cycle();
    let mut symbolmap = HashMap::new();

    // using itertools::Itertools::group_by
    for (species, species_data) in irises.iter().group_by(|iris| &iris.name) {
        // assign a plot symbol
        symbolmap.entry(species).or_insert_with(|| {
            plot_symbols.next().unwrap()
        });

        println!("Species = {} has symbol {}", species, symbolmap[species]);

        for column in 0..4 {
            for &iris in &species_data {
                print!("{:>3.1}, ", iris.data[column]);
            }
            println!("");
        }

    }

    // Look at all combinations of the four columns
    //
    // using itertools::Itertools::combinations
    for (a, b) in (0..4).combinations() {
        println!("Column {} vs {}:", a, b);
        let n = 30;
        let mut plot = vec![' '; n * n];

        // using itertools::Itertools::fold1
        let min_max = |vec: &[Iris], col| {
            vec.iter()
               .map(move |iris| iris.data[col])
               .map(|x| (x, x))
               .fold1(|(min, max), (elt, _)|
                   (f32::min(min, elt), f32::max(max, elt))
               ).expect("Can't find min/max of empty iterator")
        };
        let (min_x, max_x) = min_max(&irises, a);
        let (min_y, max_y) = min_max(&irises, b);

        for (symbol, x, y) in irises.iter()
            .map(|ir| (symbolmap[&ir.name], ir.data[a], ir.data[b]))
        {
            // round to the grid
            let ix = ((x - min_x) / (max_x - min_x) * ((n - 1) as f32)) as usize;
            let iy = ((y - min_y) / (max_y - min_y) * ((n - 1) as f32)) as usize;

            plot[n * ix + iy] = symbol;
        }

        // render plot
        //
        // using itertools::Itertools::join
        for line in plot.chunks(n) {
            println!("{}", line.iter().join(" "))
        }
    }
}
<commit_msg>Examples: Fix the orientation of the x / y axes<commit_after>///
/// This example parses, sorts and groups the iris dataset
/// and does some simple manipulations.
///
/// Iterators and itertools functionality are used throughout.
///
///

extern crate itertools;

use itertools::Itertools;
use std::str::FromStr;
use std::collections::HashMap;

static DATA: &'static str = include_str!("iris.data");

#[derive(Clone, Debug)]
struct Iris {
    name: String,
    data: [f32; 4],
}

#[derive(Clone, Debug)]
enum ParseError {
    Numeric(<f32 as FromStr>::Err),
    Other(&'static str),
}

/// Parse an Iris from a comma-separated line
impl FromStr for Iris {
    type Err = ParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut iris = Iris { name: "".into(), data: [0.; 4] };
        let mut parts = s.split(",").map(str::trim);

        // using Iterator::by_ref()
        for (index, part) in parts.by_ref().take(4).enumerate() {
            iris.data[index] = try!(part.parse::<f32>().map_err(ParseError::Numeric));
        }
        if let Some(name) = parts.next() {
            iris.name = name.into();
        } else {
            return Err(ParseError::Other("Missing name"))
        }
        Ok(iris)
    }
}

fn main() {
    // using itertools::Itertools::fold_results to create the result of parsing
    let irises = DATA.lines()
                     .map(str::parse)
                     .fold_results(Vec::new(), |mut v, iris: Iris| {
                         v.push(iris);
                         v
                     }).unwrap();

    // Sort them and group them
    let mut irises = irises;
    irises.sort_by(|a, b| Ord::cmp(&a.name, &b.name));

    // using Iterator::cycle()
    let mut plot_symbols = "+ox".chars().cycle();
    let mut symbolmap = HashMap::new();

    // using itertools::Itertools::group_by
    for (species, species_data) in irises.iter().group_by(|iris| &iris.name) {
        // assign a plot symbol
        symbolmap.entry(species).or_insert_with(|| {
            plot_symbols.next().unwrap()
        });

        println!("Species = {} has symbol {}", species, symbolmap[species]);

        for column in 0..4 {
            for &iris in &species_data {
                print!("{:>3.1}, ", iris.data[column]);
            }
            println!("");
        }

    }

    // Look at all combinations of the four columns
    //
    // See https://en.wikipedia.org/wiki/Iris_flower_data_set
    //
    // using itertools::Itertools::combinations
    for (a, b) in (0..4).combinations() {
        println!("Column {} vs {}:", a, b);
        let n = 30;
        let mut plot = vec![' '; n * n];

        // using itertools::Itertools::fold1
        let min_max = |vec: &[Iris], col| {
            vec.iter()
               .map(move |iris| iris.data[col])
               .map(|x| (x, x))
               .fold1(|(min, max), (elt, _)|
                   (f32::min(min, elt), f32::max(max, elt))
               ).expect("Can't find min/max of empty iterator")
        };
        let (min_x, max_x) = min_max(&irises, a);
        let (min_y, max_y) = min_max(&irises, b);

        for (symbol, x, y) in irises.iter()
            .map(|ir| (symbolmap[&ir.name], ir.data[a], ir.data[b]))
        {
            // round to the grid
            let ix = ((x - min_x) / (max_x - min_x) * ((n - 1) as f32)) as usize;
            let iy = ((y - min_y) / (max_y - min_y) * ((n - 1) as f32)) as usize;
            let iy = n - 1 - iy; // reverse y axis' direction

            plot[n * iy + ix] = symbol;
        }

        // render plot
        //
        // using itertools::Itertools::join
        for line in plot.chunks(n) {
            println!("{}", line.iter().join(" "))
        }
    }
}
<|endoftext|>


<commit_before>enum NestedList<T> {
    Nil,
    One(T, ~NestedList<T>),
    Many(~NestedList<T>, ~NestedList<T>)
}

fn rev<T>(list: NestedList<T>) -> NestedList<T> {
    fn rev_aux<T>(list: NestedList<T>, acc: NestedList<T>) -> NestedList<T> {
        match list {
            Nil => acc,
            One(elem, ~rest) => rev_aux(rest, One(elem, ~acc)),
            Many(~node, ~rest) => rev_aux(rest, Many(~rev(node), ~acc))
        }
    }
    rev_aux(list, Nil)
}

fn flatten<T: Clone>(list: &NestedList<T>) -> NestedList<T> {
    fn aux<T: Clone>(list: &NestedList<T>, acc: NestedList<T>) -> NestedList<T> {
        match *list {
            Nil => acc,
            One(ref elem, ~ref rest) => aux(rest, One(elem.clone(), ~acc)),
            Many(~ref node, ~ref rest) => aux(rest, aux(node, acc))
        }
    }

    rev(aux(list, Nil))
}

fn main() {
    let list: NestedList<char> =
        One('a', ~Many(
                ~One('b', ~Many(
                        ~One('c', ~One('d', ~Nil)),
                        ~One('e', ~Nil)
                    )),
            ~Nil));

    println!("{:?}", flatten(&list));
}
<commit_msg>Redo Problem 07 with vectors<commit_after>enum Node<T> {
    One(T),
    Many(~[Node<T>])
}

fn flatten<T: Clone>(nlist: &~[Node<T>]) -> ~[T] {
    nlist.flat_map(|n|
                   match *n {
                       One(ref e) => ~[e.clone()],
                       Many(ref el) => flatten(el)
                   } )
}

fn main() {
    let nlist =
        ~[One('a'), Many(~[One('b'), Many(~[One('c'), One('d')]), One('e')])];

    println!("{:?}", flatten(&nlist));
}
<|endoftext|>


<commit_before>
use std;
import std::io;
import std::io::{writer_util, reader_util};
import result;

tag state {
    fieldstart(bool);
    infield(uint, uint);
    inescapedfield(uint, uint);
    inquote(uint, uint);
}

type rowreader = {
    delim: char,
    quote: char,
    f : io::reader,
    mutable offset : uint,
    mutable buffers : [@[char]],
    mutable state : state
};

type row = {
    fields : [ fieldtype ]
};

type field = {
    escaped: bool,
    buffers: [@[char]],
    start: uint, // offset into first buffer
    end: uint // offset into last buffer
};

enum fieldtype {
    bufferfield(field);
    emptyfield();
}

iface rowiter {
    fn readrow() -> result::t<row, str>;
}

iface rowaccess {
    fn len() -> uint;
    fn getchars(uint) -> [char];
    fn getstr(uint) -> str;
}

fn new_reader(+f: io::reader, +delim: char, +quote: char) -> rowreader {
    let r : rowreader = {
        delim: delim,
        quote: quote,
        f: f,
        mutable offset : 0u,
        mutable buffers : [],
        mutable state : fieldstart(false)
    };
    ret r;
}

impl of rowaccess for row {
    fn len() -> uint {
        vec::len(self.fields)
    }
    fn getchars(field: uint) -> [char] {
        fn extract_field(field: field, &r: [char]) {
            let i = 0u;
            while i < vec::len(field.buffers) {
                let from = i == 0u ? field.start : 0u;
                let to = (i == vec::len(field.buffers) - 1u) ?
                         field.end : vec::len(*field.buffers[i]);
                r += vec::slice(*field.buffers[i], from, to);
                i = i + 1u;
            }
        }
        fn unescape(escaped: [char]) -> [char] {
            io::println("unescape");
            let r : [char] = [];
            vec::reserve(r, vec::len(escaped));
            let in_q = false;
            for c in escaped {
                if in_q {
                    assert(c == '"');
                    in_q = false;
                } else {
                    in_q = c == '"';
                    r += [c];
                }
            }
            ret r;
        }
        alt self.fields[field] {
            emptyfield() { ret []; }
            bufferfield(field) {
                let buf = [];
                extract_field(field, buf);
                if field.escaped {
                    buf = unescape(buf);
                }
                ret buf;
            }
        };
    }
    fn getstr(field: uint) -> str {
        ret str::from_chars(self.getchars(field));
    }
}

impl of rowiter for rowreader {
    fn readrow() -> result::t<row, str> {
        fn row_from_buf(self: rowreader, &fields: [fieldtype]) -> bool {
            fn new_bufferfield(self: rowreader, escaped: bool, sb: uint, so: uint, eo: uint) -> fieldtype {
                let eb = vec::len(self.buffers);
                let sb = sb, so = so, eo = eo;
                if escaped {
                    so += 1u;
                    if so >= vec::len(*self.buffers[sb]) {
                        sb += 1u;
                        so = vec::len(*self.buffers[sb]) - 1u;
                    }
                    if eo > 0u {
                        eo -= 1u;
                    } else {
                        eb -= 1u;
                        eo = vec::len(*self.buffers[sb]) - 1u;
                    }
                }
                bufferfield({escaped: escaped, buffers: vec::slice(self.buffers, sb, eb),
                    start: so, end: eo})
            }
            let cbuffer = vec::len(self.buffers) - 1u;
            let buf: @[char] = self.buffers[cbuffer];
            while self.offset < vec::len(*buf) {
                let coffset = self.offset;
                let c : char = buf[coffset];
                self.offset += 1u;
                alt self.state {
                    fieldstart(after_delim) {
                        //io::println(#fmt("fieldstart : after_delim %b", after_delim));
                        if c == self.quote {
                            self.state = inescapedfield(cbuffer, coffset);
                        } else if c == '\n' {
                            if after_delim {
                                fields += [emptyfield];
                            }
                            ret true;
                        } else if c == self.delim {
                            self.state = fieldstart(true);
                            fields += [emptyfield];
                        } else {
                            self.state = infield(cbuffer, coffset);
                        }
                    }
                    infield(b,o) {
                        //io::println(#fmt("field : %u %u", b, o));
                        if c == '\n' {
                            fields += [new_bufferfield(self, false, b, o, coffset)];
                            ret true;
                        } else if c == self.delim {
                            self.state = fieldstart(true);
                            fields += [new_bufferfield(self, false, b, o, coffset)];
                        }
                    }
                    inescapedfield(b, o) {
                        //io::println(#fmt("inescapedfield : %u %u", b, o));
                        if c == self.quote {
                            self.state = inquote(b, o);
                        } else if c == self.delim {
                            self.state = fieldstart(true);
                            fields += [new_bufferfield(self, true, b, o, coffset)];
                        }
                    }
                    inquote(b, o) {
                        //io::println(#fmt("inquote : %u %u", b, o));
                        if c == '\n' {
                            fields += [new_bufferfield(self, true, b, o, coffset)];
                            ret true;
                        } else if c == self.quote {
                            self.state = inescapedfield(b, o);
                        } else if c == self.delim {
                            self.state = fieldstart(true);
                            fields += [new_bufferfield(self, true, b, o, coffset)];
                        }
                        // swallow odd chars, eg. space between field and "
                    }
                }
            }
            ret false;
        }

        self.state = fieldstart(false);
        let do_read = vec::len(self.buffers) == 0u;
        let fields = [];
        while true {
            if do_read {
                let data: @[char] = @self.f.read_chars(1u);
                //io::println(#fmt("len %u '%s'", vec::len(*data), str::from_chars(*data)));
                if vec::len(*data) == 0u {
                    ret result::err("EOF");
                }
                self.buffers += [data];
                self.offset = 0u;
            }

            if row_from_buf(self, fields) {
                let r: row = { fields: fields };
                fields = [];
                if vec::len(self.buffers) > 1u {
                    self.buffers = vec::slice(self.buffers, vec::len(self.buffers) - 1u, vec::len(self.buffers));
                }
                ret result::ok(r);
            }
            do_read = true;
        }
        ret result::err("unreachable");
    }
}

fn main(args : [str])
{
    if (vec::len(args) != 2u) {
        ret;
    }
    let f : io::reader = result::get(io::file_reader(args[1]));
    let reader = new_reader(f, ',', '"');
    while true {
        let res = reader.readrow();
        if result::failure(res) {
            break;
        }
        let row = result::get(res);
        io::println(#fmt("---- ROW %u fields -----", row.len()));
        let i = 0u;
        while i < row.len() {
            io::println(row.getstr(i));
            i = i + 1u;
        }
    }
}

<commit_msg>print<commit_after>
use std;
import std::io;
import std::io::{writer_util, reader_util};
import result;

tag state {
    fieldstart(bool);
    infield(uint, uint);
    inescapedfield(uint, uint);
    inquote(uint, uint);
}

type rowreader = {
    delim: char,
    quote: char,
    f : io::reader,
    mutable offset : uint,
    mutable buffers : [@[char]],
    mutable state : state
};

type row = {
    fields : [ fieldtype ]
};

type field = {
    escaped: bool,
    buffers: [@[char]],
    start: uint, // offset into first buffer
    end: uint // offset into last buffer
};

enum fieldtype {
    bufferfield(field);
    emptyfield();
}

iface rowiter {
    fn readrow() -> result::t<row, str>;
}

iface rowaccess {
    fn len() -> uint;
    fn getchars(uint) -> [char];
    fn getstr(uint) -> str;
}

fn new_reader(+f: io::reader, +delim: char, +quote: char) -> rowreader {
    let r : rowreader = {
        delim: delim,
        quote: quote,
        f: f,
        mutable offset : 0u,
        mutable buffers : [],
        mutable state : fieldstart(false)
    };
    ret r;
}

impl of rowaccess for row {
    fn len() -> uint {
        vec::len(self.fields)
    }
    fn getchars(field: uint) -> [char] {
        fn extract_field(field: field, &r: [char]) {
            let i = 0u;
            while i < vec::len(field.buffers) {
                let from = i == 0u ? field.start : 0u;
                let to = (i == vec::len(field.buffers) - 1u) ?
                         field.end : vec::len(*field.buffers[i]);
                r += vec::slice(*field.buffers[i], from, to);
                i = i + 1u;
            }
        }
        fn unescape(escaped: [char]) -> [char] {
            let r : [char] = [];
            vec::reserve(r, vec::len(escaped));
            let in_q = false;
            for c in escaped {
                if in_q {
                    assert(c == '"');
                    in_q = false;
                } else {
                    in_q = c == '"';
                    r += [c];
                }
            }
            ret r;
        }
        alt self.fields[field] {
            emptyfield() { ret []; }
            bufferfield(field) {
                let buf = [];
                extract_field(field, buf);
                if field.escaped {
                    buf = unescape(buf);
                }
                ret buf;
            }
        };
    }
    fn getstr(field: uint) -> str {
        ret str::from_chars(self.getchars(field));
    }
}

impl of rowiter for rowreader {
    fn readrow() -> result::t<row, str> {
        fn row_from_buf(self: rowreader, &fields: [fieldtype]) -> bool {
            fn new_bufferfield(self: rowreader, escaped: bool, sb: uint, so: uint, eo: uint) -> fieldtype {
                let eb = vec::len(self.buffers);
                let sb = sb, so = so, eo = eo;
                if escaped {
                    so += 1u;
                    if so >= vec::len(*self.buffers[sb]) {
                        sb += 1u;
                        so = vec::len(*self.buffers[sb]) - 1u;
                    }
                    if eo > 0u {
                        eo -= 1u;
                    } else {
                        eb -= 1u;
                        eo = vec::len(*self.buffers[sb]) - 1u;
                    }
                }
                bufferfield({escaped: escaped, buffers: vec::slice(self.buffers, sb, eb),
                    start: so, end: eo})
            }
            let cbuffer = vec::len(self.buffers) - 1u;
            let buf: @[char] = self.buffers[cbuffer];
            while self.offset < vec::len(*buf) {
                let coffset = self.offset;
                let c : char = buf[coffset];
                self.offset += 1u;
                alt self.state {
                    fieldstart(after_delim) {
                        //io::println(#fmt("fieldstart : after_delim %b", after_delim));
                        if c == self.quote {
                            self.state = inescapedfield(cbuffer, coffset);
                        } else if c == '\n' {
                            if after_delim {
                                fields += [emptyfield];
                            }
                            ret true;
                        } else if c == self.delim {
                            self.state = fieldstart(true);
                            fields += [emptyfield];
                        } else {
                            self.state = infield(cbuffer, coffset);
                        }
                    }
                    infield(b,o) {
                        //io::println(#fmt("field : %u %u", b, o));
                        if c == '\n' {
                            fields += [new_bufferfield(self, false, b, o, coffset)];
                            ret true;
                        } else if c == self.delim {
                            self.state = fieldstart(true);
                            fields += [new_bufferfield(self, false, b, o, coffset)];
                        }
                    }
                    inescapedfield(b, o) {
                        //io::println(#fmt("inescapedfield : %u %u", b, o));
                        if c == self.quote {
                            self.state = inquote(b, o);
                        } else if c == self.delim {
                            self.state = fieldstart(true);
                            fields += [new_bufferfield(self, true, b, o, coffset)];
                        }
                    }
                    inquote(b, o) {
                        //io::println(#fmt("inquote : %u %u", b, o));
                        if c == '\n' {
                            fields += [new_bufferfield(self, true, b, o, coffset)];
                            ret true;
                        } else if c == self.quote {
                            self.state = inescapedfield(b, o);
                        } else if c == self.delim {
                            self.state = fieldstart(true);
                            fields += [new_bufferfield(self, true, b, o, coffset)];
                        }
                        // swallow odd chars, eg. space between field and "
                    }
                }
            }
            ret false;
        }

        self.state = fieldstart(false);
        let do_read = vec::len(self.buffers) == 0u;
        let fields = [];
        while true {
            if do_read {
                let data: @[char] = @self.f.read_chars(1u);
                //io::println(#fmt("len %u '%s'", vec::len(*data), str::from_chars(*data)));
                if vec::len(*data) == 0u {
                    ret result::err("EOF");
                }
                self.buffers += [data];
                self.offset = 0u;
            }

            if row_from_buf(self, fields) {
                let r: row = { fields: fields };
                fields = [];
                if vec::len(self.buffers) > 1u {
                    self.buffers = vec::slice(self.buffers, vec::len(self.buffers) - 1u, vec::len(self.buffers));
                }
                ret result::ok(r);
            }
            do_read = true;
        }
        ret result::err("unreachable");
    }
}

fn main(args : [str])
{
    if (vec::len(args) != 2u) {
        ret;
    }
    let f : io::reader = result::get(io::file_reader(args[1]));
    let reader = new_reader(f, ',', '"');
    while true {
        let res = reader.readrow();
        if result::failure(res) {
            break;
        }
        let row = result::get(res);
        io::println(#fmt("---- ROW %u fields -----", row.len()));
        let i = 0u;
        while i < row.len() {
            io::println(row.getstr(i));
            i = i + 1u;
        }
    }
}

<|endoftext|>


<commit_before>struct Hailstone {
  priv current: uint
}

impl Hailstone {
  fn new(start: uint) -> Hailstone {
    Hailstone { current: start }
  }
}

impl Iterator<uint> for Hailstone {
  fn next(&mut self) -> Option<uint> {
    let current = self.current;
    match current {
      0               => None,
      1               => {
        self.current = 0;
        Some(1)
      },
      x if x % 2 == 0 => {
        self.current = x / 2;
        Some(current)
      },
      x if x % 2 == 1 => {
        self.current = (3 * x) + 1;
        Some(current)
      },
      _               => None
    }
  }
}

fn check_hailstone(n: uint) {
  let mut hail = Hailstone::new(n);
  let result: ~[uint] = hail.collect();
  println!("Testing: {}, Length: {}, Values: {}...{}", n, result.len(), result.slice(0,4).to_str(), result.slice(result.len()-4, result.len()).to_str())
}

fn main() {
  check_hailstone(27);
}
<commit_msg>Hailstone works.<commit_after>struct Hailstone {
  priv current: int
}

impl Hailstone {
  fn new(start: int) -> Hailstone {
    Hailstone { current: start }
  }
}

impl Iterator<int> for Hailstone {
  fn next(&mut self) -> Option<int> {
    let current = self.current;
    match current {
      0               => None,
      1               => {
        self.current = 0;
        Some(1)
      },
      x if x % 2 == 0 => {
        self.current = x / 2;
        Some(current)
      },
      x if x % 2 == 1 => {
        self.current = (3 * x) + 1;
        Some(current)
      },
      _               => None
    }
  }
}

fn get_hailstone(n: int) -> ~[int] {
  let mut hail = Hailstone::new(n);
  hail.collect()
}

fn main() {
  // Find the hailstone for 27.
  let test_value = 27;
  let two_seven = get_hailstone(test_value);
  println!("Testing: {}, Length: {}, Values: {}...{}", test_value, two_seven.len(), two_seven.slice(0,4).to_str(), two_seven.slice(two_seven.len()-4, two_seven.len()).to_str());
  // Find the longest.
  let mut biggest = ~[];
  for x in range(0, 100000) {
    let result = get_hailstone(x);
    if result.len() > biggest.len() {
      biggest = result;
    }
  };
  println!("Largest: {}, Length: {}, Values: {}...{}", biggest[0], biggest.len(), biggest.slice(0,4).to_str(), biggest.slice(biggest.len()-4, biggest.len()).to_str());
}
<|endoftext|>


<commit_before>struct Hailstone {
  priv current: int
}

impl Hailstone {
  fn new(start: int) -> Hailstone {
    Hailstone { current: start }
  }
}

impl Iterator<int> for Hailstone {
  fn next(&mut self) -> Option<int> {
    let current = self.current;
    match current {
      0               => None,
      1               => {
        self.current = 0;
        Some(1)
      },
      x if x % 2 == 0 => {
        self.current = x / 2;
        Some(current)
      },
      x if x % 2 == 1 => {
        self.current = (3 * x) + 1;
        Some(current)
      },
      _               => None
    }
  }
}

fn get_hailstone(n: int) -> ~[int] {
  let mut hail = Hailstone::new(n);
  hail.collect()
}

fn main() {
  // Find the hailstone for 27.
  let test_value = 27;
  let two_seven = get_hailstone(test_value);
  println!("Testing: {}, Length: {}, Values: {}...{}", test_value, two_seven.len(), two_seven.slice(0,4).to_str(), two_seven.slice(two_seven.len()-4, two_seven.len()).to_str());
  // Find the longest.
  let mut biggest = ~[];
  for x in range(0, 100000) {
    let result = get_hailstone(x);
    if result.len() > biggest.len() {
      biggest = result;
    }
  };
  println!("Largest: {}, Length: {}, Values: {}...{}", biggest[0], biggest.len(), biggest.slice(0,4).to_str(), biggest.slice(biggest.len()-4, biggest.len()).to_str());
}
<commit_msg>Better comments, cleaner.<commit_after>// Implements http://rosettacode.org/wiki/Hailstone_sequence
struct Hailstone {
  priv current: int
}

impl Hailstone {
  fn new(start: int) -> Hailstone {
    Hailstone { current: start }
  }
}

impl Iterator<int> for Hailstone {
  fn next(&mut self) -> Option<int> {
    let current = self.current;
    match current {
      0               => None,
      1               => {
        self.current = 0;
        Some(1)
      },
      x if x % 2 == 0 => {
        self.current = x / 2;
        Some(current)
      },
      x if x % 2 == 1 => {
        self.current = (3 * x) + 1;
        Some(current)
      },
      _               => None
    }
  }
}

fn get_hailstone(n: int) -> ~[int] {
  let mut hail = Hailstone::new(n);
  hail.collect()
}

fn main() {
  // Find the hailstone for 27.
  let two_seven = get_hailstone(27);
  println!("Testing: {}, Length: {}, Values: {}...{}", two_seven[0], two_seven.len(), two_seven.slice(0,4).to_str(), two_seven.slice(two_seven.len()-4, two_seven.len()).to_str());
  // Find the longest.
  let mut biggest = ~[];
  for x in range(0, 100000) {
    let result = get_hailstone(x);
    if result.len() > biggest.len() {
      biggest = result;
    }
  };
  println!("Largest: {}, Length: {}, Values: {}...{}", biggest[0], biggest.len(), biggest.slice(0,4).to_str(), biggest.slice(biggest.len()-4, biggest.len()).to_str());
}
<|endoftext|>