<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::iter::Empty;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;

use device::Device;
use device::Queue;
use format::ClearValue;
use format::Format;
use format::FormatDesc;
use format::FormatTy;
use image::Dimensions;
use image::ImageDimensions;
use image::ViewType;
use image::sys::ImageCreationError;
use image::sys::Layout;
use image::sys::UnsafeImage;
use image::sys::UnsafeImageView;
use image::sys::Usage;
use image::traits::ImageAccess;
use image::traits::ImageClearValue;
use image::traits::ImageContent;
use image::traits::ImageViewAccess;
use image::traits::Image;
use image::traits::ImageView;
use memory::pool::AllocLayout;
use memory::pool::MemoryPool;
use memory::pool::MemoryPoolAlloc;
use memory::pool::StdMemoryPoolAlloc;
use sync::Sharing;

/// ImageAccess whose purpose is to be used as a framebuffer attachment.
///
/// The image is always two-dimensional and has only one mipmap, but it can have any kind of
/// format. Trying to use a format that the backend doesn't support for rendering will result in
/// an error being returned when creating the image. Once you have an `AttachmentImage`, you are
/// guaranteed that you will be able to draw on it.
///
/// The template parameter of `AttachmentImage` is a type that describes the format of the image.
///
/// # Regular vs transient
///
/// Calling `AttachmentImage::new` will create a regular image, while calling
/// `AttachmentImage::transient` will create a *transient* image. Transient image are only
/// relevant for images that serve as attachments, so `AttachmentImage` is the only type of
/// image in vulkano that provides a shortcut for this.
///
/// A transient image is a special kind of image whose content is undefined outside of render
/// passes. Once you finish drawing, reading from it will returned undefined data (which can be
/// either valid or garbage, depending on the implementation).
///
/// This gives a hint to the Vulkan implementation that it is possible for the image's content to
/// live exclusively in some cache memory, and that no real memory has to be allocated for it.
///
/// In other words, if you are going to read from the image after drawing to it, use a regular
/// image. If you don't need to read from it (for example if it's some kind of intermediary color,
/// or a depth buffer that is only used once) then use a transient image as it may improve
/// performances.
///
// TODO: forbid reading transient images outside render passes?
#[derive(Debug)]
pub struct AttachmentImage<F, A = StdMemoryPoolAlloc> {
    // Inner implementation.
    image: UnsafeImage,

    // We maintain a view of the whole image since we will need it when rendering.
    view: UnsafeImageView,

    // Memory used to back the image.
    memory: A,

    // Format.
    format: F,

    // Layout to use when the image is used as a framebuffer attachment.
    // Must be either "depth-stencil optimal" or "color optimal".
    attachment_layout: Layout,

    // Number of times this image is locked on the GPU side.
    gpu_lock: AtomicUsize,
}

impl<F> AttachmentImage<F> {
    /// Creates a new image with the given dimensions and format.
    ///
    /// Returns an error if the dimensions are too large or if the backend doesn't support this
    /// format as a framebuffer attachment.
    #[inline]
    pub fn new(device: &Arc<Device>, dimensions: [u32; 2], format: F)
               -> Result<Arc<AttachmentImage<F>>, ImageCreationError>
        where F: FormatDesc
    {
        AttachmentImage::new_impl(device, dimensions, format, Usage::none())
    }

    /// Same as `new`, but lets you specify additional usages.
    #[inline]
    pub fn with_usage(device: &Arc<Device>, dimensions: [u32; 2], format: F, usage: Usage)
                      -> Result<Arc<AttachmentImage<F>>, ImageCreationError>
        where F: FormatDesc
    {
        AttachmentImage::new_impl(device, dimensions, format, usage)
    }

    /// Same as `new`, except that the image will be transient.
    ///
    /// A transient image is special because its content is undefined outside of a render pass.
    /// This means that the implementation has the possibility to not allocate any memory for it.
    #[inline]
    pub fn transient(device: &Arc<Device>, dimensions: [u32; 2], format: F)
                     -> Result<Arc<AttachmentImage<F>>, ImageCreationError>
        where F: FormatDesc
    {
        let base_usage = Usage {
            transient_attachment: true,
            .. Usage::none()
        };

        AttachmentImage::new_impl(device, dimensions, format, base_usage)
    }

    fn new_impl(device: &Arc<Device>, dimensions: [u32; 2], format: F, base_usage: Usage)
                -> Result<Arc<AttachmentImage<F>>, ImageCreationError>
        where F: FormatDesc
    {
        // TODO: check dimensions against the max_framebuffer_width/height/layers limits

        let is_depth = match format.format().ty() {
            FormatTy::Depth => true,
            FormatTy::DepthStencil => true,
            FormatTy::Stencil => true,
            FormatTy::Compressed => panic!(),
            _ => false
        };

        let usage = Usage {
            color_attachment: !is_depth,
            depth_stencil_attachment: is_depth,
            .. base_usage
        };

        let (image, mem_reqs) = unsafe {
            try!(UnsafeImage::new(device, &usage, format.format(),
                                  ImageDimensions::Dim2d { width: dimensions[0], height: dimensions[1], array_layers: 1, cubemap_compatible: false },
                                  1, 1, Sharing::Exclusive::<Empty<u32>>, false, false))
        };

        let mem_ty = {
            let device_local = device.physical_device().memory_types()
                                     .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0)
                                     .filter(|t| t.is_device_local());
            let any = device.physical_device().memory_types()
                            .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0);
            device_local.chain(any).next().unwrap()
        };

        let mem = try!(MemoryPool::alloc(&Device::standard_pool(device), mem_ty,
                                         mem_reqs.size, mem_reqs.alignment, AllocLayout::Optimal));
        debug_assert!((mem.offset() % mem_reqs.alignment) == 0);
        unsafe { try!(image.bind_memory(mem.memory(), mem.offset())); }

        let view = unsafe {
            try!(UnsafeImageView::raw(&image, ViewType::Dim2d, 0 .. 1, 0 .. 1))
        };

        Ok(Arc::new(AttachmentImage {
            image: image,
            view: view,
            memory: mem,
            format: format,
            attachment_layout: if is_depth { Layout::DepthStencilAttachmentOptimal }
                               else { Layout::ColorAttachmentOptimal },
            gpu_lock: AtomicUsize::new(0),
        }))
    }
}

impl<F, A> AttachmentImage<F, A> {
    /// Returns the dimensions of the image.
    #[inline]
    pub fn dimensions(&self) -> [u32; 2] {
        let dims = self.image.dimensions();
        [dims.width(), dims.height()]
    }
}

/// GPU access to an attachment image.
pub struct AttachmentImageAccess<F, A> {
    img: Arc<AttachmentImage<F, A>>,
    // True if `try_gpu_lock` was already called on it.
    already_locked: AtomicBool,
}

impl<F, A> Clone for AttachmentImageAccess<F, A> {
    #[inline]
    fn clone(&self) -> AttachmentImageAccess<F, A> {
        AttachmentImageAccess {
            img: self.img.clone(),
            already_locked: AtomicBool::new(self.already_locked.load(Ordering::SeqCst))
        }
    }
}

unsafe impl<F, A> ImageAccess for AttachmentImageAccess<F, A>
    where F: 'static + Send + Sync
{
    #[inline]
    fn inner(&self) -> &UnsafeImage {
        &self.img.image
    }

    #[inline]
    fn initial_layout_requirement(&self) -> Layout {
        self.img.attachment_layout
    }

    #[inline]
    fn final_layout_requirement(&self) -> Layout {
        self.img.attachment_layout
    }

    #[inline]
    fn conflict_key(&self, _: u32, _: u32, _: u32, _: u32) -> u64 {
        self.img.image.key()
    }

    #[inline]
    fn try_gpu_lock(&self, _: bool, _: &Queue) -> bool {
        if self.already_locked.swap(true, Ordering::SeqCst) == true {
            return false;
        }

        self.img.gpu_lock.compare_and_swap(0, 1, Ordering::SeqCst) == 0
    }

    #[inline]
    unsafe fn increase_gpu_lock(&self) {
        debug_assert!(self.already_locked.load(Ordering::SeqCst));
        let val = self.img.gpu_lock.fetch_add(1, Ordering::SeqCst);
        debug_assert!(val >= 1);
    }
}

impl<F, A> Drop for AttachmentImageAccess<F, A> {
    fn drop(&mut self) {
        if self.already_locked.load(Ordering::SeqCst) {
            let prev_val = self.img.gpu_lock.fetch_sub(1, Ordering::SeqCst);
            debug_assert!(prev_val >= 1);
        }
    }
}

unsafe impl<F, A> ImageClearValue<F::ClearValue> for AttachmentImageAccess<F, A>
    where F: FormatDesc + 'static + Send + Sync
{
    #[inline]
    fn decode(&self, value: F::ClearValue) -> Option<ClearValue> {
        Some(self.img.format.decode_clear_value(value))
    }
}

unsafe impl<P, F, A> ImageContent<P> for AttachmentImageAccess<F, A>
    where F: 'static + Send + Sync
{
    #[inline]
    fn matches_format(&self) -> bool {
        true        // FIXME:
    }
}

unsafe impl<F, A> Image for Arc<AttachmentImage<F, A>>
    where F: 'static + Send + Sync
{
    type Access = AttachmentImageAccess<F, A>;

    #[inline]
    fn access(self) -> AttachmentImageAccess<F, A> {
        AttachmentImageAccess {
            img: self,
            already_locked: AtomicBool::new(false),
        }
    }

    #[inline]
    fn format(&self) -> Format {
        self.image.format()
    }

    #[inline]
    fn samples(&self) -> u32 {
        self.image.samples()
    }

    #[inline]
    fn dimensions(&self) -> ImageDimensions {
        self.image.dimensions()
    }
}

unsafe impl<F, A> ImageView for Arc<AttachmentImage<F, A>>
    where F: 'static + Send + Sync
{
    type Access = AttachmentImageAccess<F, A>;

    #[inline]
    fn access(self) -> AttachmentImageAccess<F, A> {
        AttachmentImageAccess {
            img: self,
            already_locked: AtomicBool::new(false),
        }
    }
}

unsafe impl<F, A> ImageViewAccess for AttachmentImageAccess<F, A>
    where F: 'static + Send + Sync
{
    #[inline]
    fn parent(&self) -> &ImageAccess {
        self
    }

    #[inline]
    fn dimensions(&self) -> Dimensions {
        let dims = self.img.image.dimensions();
        Dimensions::Dim2d { width: dims.width(), height: dims.height() }
    }

    #[inline]
    fn inner(&self) -> &UnsafeImageView {
        &self.img.view
    }

    #[inline]
    fn descriptor_set_storage_image_layout(&self) -> Layout {
        Layout::ShaderReadOnlyOptimal
    }

    #[inline]
    fn descriptor_set_combined_image_sampler_layout(&self) -> Layout {
        Layout::ShaderReadOnlyOptimal
    }

    #[inline]
    fn descriptor_set_sampled_image_layout(&self) -> Layout {
        Layout::ShaderReadOnlyOptimal
    }

    #[inline]
    fn descriptor_set_input_attachment_layout(&self) -> Layout {
        Layout::ShaderReadOnlyOptimal
    }

    #[inline]
    fn identity_swizzle(&self) -> bool {
        true
    }
}

#[cfg(test)]
mod tests {
    use super::AttachmentImage;
    use format::Format;

    #[test]
    fn create_regular() {
        let (device, _) = gfx_dev_and_queue!();
        let _img = AttachmentImage::new(&device, [32, 32], Format::R8G8B8A8Unorm).unwrap();
    }

    #[test]
    fn create_transient() {
        let (device, _) = gfx_dev_and_queue!();
        let _img = AttachmentImage::transient(&device, [32, 32], Format::R8G8B8A8Unorm).unwrap();
    }

    #[test]
    fn d16_unorm_always_supported() {
        let (device, _) = gfx_dev_and_queue!();
        let _img = AttachmentImage::new(&device, [32, 32], Format::D16Unorm).unwrap();
    }
}
<commit_msg>Disable attachment image checking for now<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::iter::Empty;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;

use device::Device;
use device::Queue;
use format::ClearValue;
use format::Format;
use format::FormatDesc;
use format::FormatTy;
use image::Dimensions;
use image::ImageDimensions;
use image::ViewType;
use image::sys::ImageCreationError;
use image::sys::Layout;
use image::sys::UnsafeImage;
use image::sys::UnsafeImageView;
use image::sys::Usage;
use image::traits::ImageAccess;
use image::traits::ImageClearValue;
use image::traits::ImageContent;
use image::traits::ImageViewAccess;
use image::traits::Image;
use image::traits::ImageView;
use memory::pool::AllocLayout;
use memory::pool::MemoryPool;
use memory::pool::MemoryPoolAlloc;
use memory::pool::StdMemoryPoolAlloc;
use sync::Sharing;

/// ImageAccess whose purpose is to be used as a framebuffer attachment.
///
/// The image is always two-dimensional and has only one mipmap, but it can have any kind of
/// format. Trying to use a format that the backend doesn't support for rendering will result in
/// an error being returned when creating the image. Once you have an `AttachmentImage`, you are
/// guaranteed that you will be able to draw on it.
///
/// The template parameter of `AttachmentImage` is a type that describes the format of the image.
///
/// # Regular vs transient
///
/// Calling `AttachmentImage::new` will create a regular image, while calling
/// `AttachmentImage::transient` will create a *transient* image. Transient image are only
/// relevant for images that serve as attachments, so `AttachmentImage` is the only type of
/// image in vulkano that provides a shortcut for this.
///
/// A transient image is a special kind of image whose content is undefined outside of render
/// passes. Once you finish drawing, reading from it will returned undefined data (which can be
/// either valid or garbage, depending on the implementation).
///
/// This gives a hint to the Vulkan implementation that it is possible for the image's content to
/// live exclusively in some cache memory, and that no real memory has to be allocated for it.
///
/// In other words, if you are going to read from the image after drawing to it, use a regular
/// image. If you don't need to read from it (for example if it's some kind of intermediary color,
/// or a depth buffer that is only used once) then use a transient image as it may improve
/// performances.
///
// TODO: forbid reading transient images outside render passes?
#[derive(Debug)]
pub struct AttachmentImage<F, A = StdMemoryPoolAlloc> {
    // Inner implementation.
    image: UnsafeImage,

    // We maintain a view of the whole image since we will need it when rendering.
    view: UnsafeImageView,

    // Memory used to back the image.
    memory: A,

    // Format.
    format: F,

    // Layout to use when the image is used as a framebuffer attachment.
    // Must be either "depth-stencil optimal" or "color optimal".
    attachment_layout: Layout,

    // Number of times this image is locked on the GPU side.
    gpu_lock: AtomicUsize,
}

impl<F> AttachmentImage<F> {
    /// Creates a new image with the given dimensions and format.
    ///
    /// Returns an error if the dimensions are too large or if the backend doesn't support this
    /// format as a framebuffer attachment.
    #[inline]
    pub fn new(device: &Arc<Device>, dimensions: [u32; 2], format: F)
               -> Result<Arc<AttachmentImage<F>>, ImageCreationError>
        where F: FormatDesc
    {
        AttachmentImage::new_impl(device, dimensions, format, Usage::none())
    }

    /// Same as `new`, but lets you specify additional usages.
    #[inline]
    pub fn with_usage(device: &Arc<Device>, dimensions: [u32; 2], format: F, usage: Usage)
                      -> Result<Arc<AttachmentImage<F>>, ImageCreationError>
        where F: FormatDesc
    {
        AttachmentImage::new_impl(device, dimensions, format, usage)
    }

    /// Same as `new`, except that the image will be transient.
    ///
    /// A transient image is special because its content is undefined outside of a render pass.
    /// This means that the implementation has the possibility to not allocate any memory for it.
    #[inline]
    pub fn transient(device: &Arc<Device>, dimensions: [u32; 2], format: F)
                     -> Result<Arc<AttachmentImage<F>>, ImageCreationError>
        where F: FormatDesc
    {
        let base_usage = Usage {
            transient_attachment: true,
            .. Usage::none()
        };

        AttachmentImage::new_impl(device, dimensions, format, base_usage)
    }

    fn new_impl(device: &Arc<Device>, dimensions: [u32; 2], format: F, base_usage: Usage)
                -> Result<Arc<AttachmentImage<F>>, ImageCreationError>
        where F: FormatDesc
    {
        // TODO: check dimensions against the max_framebuffer_width/height/layers limits

        let is_depth = match format.format().ty() {
            FormatTy::Depth => true,
            FormatTy::DepthStencil => true,
            FormatTy::Stencil => true,
            FormatTy::Compressed => panic!(),
            _ => false
        };

        let usage = Usage {
            color_attachment: !is_depth,
            depth_stencil_attachment: is_depth,
            .. base_usage
        };

        let (image, mem_reqs) = unsafe {
            try!(UnsafeImage::new(device, &usage, format.format(),
                                  ImageDimensions::Dim2d { width: dimensions[0], height: dimensions[1], array_layers: 1, cubemap_compatible: false },
                                  1, 1, Sharing::Exclusive::<Empty<u32>>, false, false))
        };

        let mem_ty = {
            let device_local = device.physical_device().memory_types()
                                     .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0)
                                     .filter(|t| t.is_device_local());
            let any = device.physical_device().memory_types()
                            .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0);
            device_local.chain(any).next().unwrap()
        };

        let mem = try!(MemoryPool::alloc(&Device::standard_pool(device), mem_ty,
                                         mem_reqs.size, mem_reqs.alignment, AllocLayout::Optimal));
        debug_assert!((mem.offset() % mem_reqs.alignment) == 0);
        unsafe { try!(image.bind_memory(mem.memory(), mem.offset())); }

        let view = unsafe {
            try!(UnsafeImageView::raw(&image, ViewType::Dim2d, 0 .. 1, 0 .. 1))
        };

        Ok(Arc::new(AttachmentImage {
            image: image,
            view: view,
            memory: mem,
            format: format,
            attachment_layout: if is_depth { Layout::DepthStencilAttachmentOptimal }
                               else { Layout::ColorAttachmentOptimal },
            gpu_lock: AtomicUsize::new(0),
        }))
    }
}

impl<F, A> AttachmentImage<F, A> {
    /// Returns the dimensions of the image.
    #[inline]
    pub fn dimensions(&self) -> [u32; 2] {
        let dims = self.image.dimensions();
        [dims.width(), dims.height()]
    }
}

/// GPU access to an attachment image.
pub struct AttachmentImageAccess<F, A> {
    img: Arc<AttachmentImage<F, A>>,
    // True if `try_gpu_lock` was already called on it.
    already_locked: AtomicBool,
}

impl<F, A> Clone for AttachmentImageAccess<F, A> {
    #[inline]
    fn clone(&self) -> AttachmentImageAccess<F, A> {
        AttachmentImageAccess {
            img: self.img.clone(),
            already_locked: AtomicBool::new(self.already_locked.load(Ordering::SeqCst))
        }
    }
}

unsafe impl<F, A> ImageAccess for AttachmentImageAccess<F, A>
    where F: 'static + Send + Sync
{
    #[inline]
    fn inner(&self) -> &UnsafeImage {
        &self.img.image
    }

    #[inline]
    fn initial_layout_requirement(&self) -> Layout {
        self.img.attachment_layout
    }

    #[inline]
    fn final_layout_requirement(&self) -> Layout {
        self.img.attachment_layout
    }

    #[inline]
    fn conflict_key(&self, _: u32, _: u32, _: u32, _: u32) -> u64 {
        self.img.image.key()
    }

    #[inline]
    fn try_gpu_lock(&self, _: bool, _: &Queue) -> bool {
        // FIXME: uncomment when it's working
        true
        /*if self.already_locked.swap(true, Ordering::SeqCst) == true {
            return false;
        }

        self.img.gpu_lock.compare_and_swap(0, 1, Ordering::SeqCst) == 0*/
    }

    #[inline]
    unsafe fn increase_gpu_lock(&self) {
        // FIXME: uncomment when it's working
        /*debug_assert!(self.already_locked.load(Ordering::SeqCst));
        let val = self.img.gpu_lock.fetch_add(1, Ordering::SeqCst);
        debug_assert!(val >= 1);*/
    }
}

impl<F, A> Drop for AttachmentImageAccess<F, A> {
    fn drop(&mut self) {
        if self.already_locked.load(Ordering::SeqCst) {
            let prev_val = self.img.gpu_lock.fetch_sub(1, Ordering::SeqCst);
            debug_assert!(prev_val >= 1);
        }
    }
}

unsafe impl<F, A> ImageClearValue<F::ClearValue> for AttachmentImageAccess<F, A>
    where F: FormatDesc + 'static + Send + Sync
{
    #[inline]
    fn decode(&self, value: F::ClearValue) -> Option<ClearValue> {
        Some(self.img.format.decode_clear_value(value))
    }
}

unsafe impl<P, F, A> ImageContent<P> for AttachmentImageAccess<F, A>
    where F: 'static + Send + Sync
{
    #[inline]
    fn matches_format(&self) -> bool {
        true        // FIXME:
    }
}

unsafe impl<F, A> Image for Arc<AttachmentImage<F, A>>
    where F: 'static + Send + Sync
{
    type Access = AttachmentImageAccess<F, A>;

    #[inline]
    fn access(self) -> AttachmentImageAccess<F, A> {
        AttachmentImageAccess {
            img: self,
            already_locked: AtomicBool::new(false),
        }
    }

    #[inline]
    fn format(&self) -> Format {
        self.image.format()
    }

    #[inline]
    fn samples(&self) -> u32 {
        self.image.samples()
    }

    #[inline]
    fn dimensions(&self) -> ImageDimensions {
        self.image.dimensions()
    }
}

unsafe impl<F, A> ImageView for Arc<AttachmentImage<F, A>>
    where F: 'static + Send + Sync
{
    type Access = AttachmentImageAccess<F, A>;

    #[inline]
    fn access(self) -> AttachmentImageAccess<F, A> {
        AttachmentImageAccess {
            img: self,
            already_locked: AtomicBool::new(false),
        }
    }
}

unsafe impl<F, A> ImageViewAccess for AttachmentImageAccess<F, A>
    where F: 'static + Send + Sync
{
    #[inline]
    fn parent(&self) -> &ImageAccess {
        self
    }

    #[inline]
    fn dimensions(&self) -> Dimensions {
        let dims = self.img.image.dimensions();
        Dimensions::Dim2d { width: dims.width(), height: dims.height() }
    }

    #[inline]
    fn inner(&self) -> &UnsafeImageView {
        &self.img.view
    }

    #[inline]
    fn descriptor_set_storage_image_layout(&self) -> Layout {
        Layout::ShaderReadOnlyOptimal
    }

    #[inline]
    fn descriptor_set_combined_image_sampler_layout(&self) -> Layout {
        Layout::ShaderReadOnlyOptimal
    }

    #[inline]
    fn descriptor_set_sampled_image_layout(&self) -> Layout {
        Layout::ShaderReadOnlyOptimal
    }

    #[inline]
    fn descriptor_set_input_attachment_layout(&self) -> Layout {
        Layout::ShaderReadOnlyOptimal
    }

    #[inline]
    fn identity_swizzle(&self) -> bool {
        true
    }
}

#[cfg(test)]
mod tests {
    use super::AttachmentImage;
    use format::Format;

    #[test]
    fn create_regular() {
        let (device, _) = gfx_dev_and_queue!();
        let _img = AttachmentImage::new(&device, [32, 32], Format::R8G8B8A8Unorm).unwrap();
    }

    #[test]
    fn create_transient() {
        let (device, _) = gfx_dev_and_queue!();
        let _img = AttachmentImage::transient(&device, [32, 32], Format::R8G8B8A8Unorm).unwrap();
    }

    #[test]
    fn d16_unorm_always_supported() {
        let (device, _) = gfx_dev_and_queue!();
        let _img = AttachmentImage::new(&device, [32, 32], Format::D16Unorm).unwrap();
    }
}
<|endoftext|>


<commit_before>use std::ops::{Index, IndexMut};
use std::slice;
use std::vec;
use std::fmt;

use Dimension;

/// A multi-dimensional array.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Array<T> {
    dims: Vec<Dimension>,
    data: Vec<T>,
}

impl<T: fmt::Display> fmt::Display for Array<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        if self.dims.iter().any(|dim| dim.lower_bound != 1) {
            for dim in &self.dims {
                try!(write!(fmt, "[{}:{}]", dim.lower_bound,
                            dim.lower_bound + dim.len as isize - 1));
            }
            try!(write!(fmt, "="));
        }
        fmt_helper(0, &self.dims, &mut self.data.iter(), fmt)
    }
}

fn fmt_helper<'a, T, I>(depth: usize,
                        dims: &[Dimension],
                        mut data: &mut I,
                        fmt: &mut fmt::Formatter)
                        -> fmt::Result
        where I: Iterator<Item=&'a T>, T: 'a + fmt::Display {
    if depth == dims.len() {
        return write!(fmt, "{}", data.next().unwrap());
    }

    try!(write!(fmt, "{{"));
    for i in 0..dims[depth].len {
        if i != 0 {
            try!(write!(fmt, ","));
        }
        try!(fmt_helper(depth + 1, dims, data, fmt));
    }
    write!(fmt, "}}")
}

impl<T> Array<T> {
    /// Creates a new `Array` from its underlying components.
    ///
    /// The data array should be provided in the higher-dimensional equivalent
    /// of row-major order.
    ///
    /// # Panics
    ///
    /// Panics if the number of elements provided does not match the number of
    /// elements specified by the dimensions.
    pub fn from_parts(data: Vec<T>, dimensions: Vec<Dimension>) -> Array<T> {
        assert!((data.is_empty() && dimensions.is_empty()) ||
                data.len() == dimensions.iter().fold(1, |acc, i| acc * i.len),
                "size mismatch");
        Array {
            dims: dimensions,
            data: data,
        }
    }

    /// Creates a new one-dimensional array.
    pub fn from_vec(data: Vec<T>, lower_bound: isize) -> Array<T> {
        Array {
            dims: vec![Dimension {
                len: data.len(),
                lower_bound: lower_bound
            }],
            data: data,
        }
    }

    /// Wraps this array in a new dimension of size 1.
    ///
    /// For example, the one dimensional array `[1, 2]` would turn into the
    /// two-dimensional array `[[1, 2]]`.
    pub fn wrap(&mut self, lower_bound: isize) {
        self.dims.insert(0, Dimension {
            len: 1,
            lower_bound: lower_bound,
        });
    }

    /// Consumes another array, appending it to the top level dimension of this
    /// array.
    ///
    /// The dimensions of the other array must be the same as the dimensions
    /// of this array with the first dimension removed. This includes lower
    /// bounds as well as lengths.
    ///
    /// For example, if `[3, 4]` is pushed onto `[[1, 2]]`, the result is
    /// `[[1, 2], [3, 4]]`.
    ///
    /// # Panics
    ///
    /// Panics if the dimensions of the two arrays do not match.
    pub fn push(&mut self, other: Array<T>) {
        assert!(self.dims.len() - 1 == other.dims.len(),
                "cannot append differently shaped arrays");
        for (dim1, dim2) in self.dims.iter().skip(1).zip(other.dims.iter()) {
            assert!(dim1 == dim2, "cannot append differently shaped arrays");
        }
        self.dims[0].len += 1;
        self.data.extend(other.data);
    }

    /// Returns the dimensions of this array.
    pub fn dimensions(&self) -> &[Dimension] {
        &self.dims
    }

    fn shift_idx(&self, indices: &[isize]) -> usize {
        assert_eq!(self.dims.len(), indices.len());
        self.dims
            .iter()
            .zip(indices.iter().cloned())
            .rev()
            .fold((0, 1), |(acc, stride), (dim, idx)| {
                let shifted = dim.shift(idx);
                (acc + shifted * stride, dim.len * stride)
            })
            .0
    }

    /// Returns an iterator over references to the elements of the array in the
    /// higher-dimensional equivalent of row-major order.
    pub fn iter<'a>(&'a self) -> Iter<'a, T> {
        Iter {
            inner: self.data.iter(),
        }
    }

    /// Returns an iterator over mutable references to the elements of the
    /// array in the higher-dimensional equivalent of row-major order.
    pub fn iter_mut<'a>(&'a mut self) -> IterMut<'a, T> {
        IterMut {
            inner: self.data.iter_mut(),
        }
    }
}

/// A trait implemented by types that can index into an `Array`.
pub trait ArrayIndex {
    /// Calculates the index into the `Array`'s underlying storage specified
    /// by the value of `self`.
    ///
    /// # Panics
    ///
    /// Panics if the value of `self` does not correspond to an in-bounds
    /// element of the `Array`.
    fn index<T>(&self, array: &Array<T>) -> usize;
}

impl<'a> ArrayIndex for &'a [isize] {
    fn index<T>(&self, array: &Array<T>) -> usize {
        array.shift_idx(*self)
    }
}

impl ArrayIndex for isize {
    fn index<T>(&self, array: &Array<T>) -> usize {
        let slice: &[isize] = &[*self];
        ArrayIndex::index(&slice, array)
    }
}

macro_rules! tuple_impl {
    ($($name:ident : $t:ty),+) => {
        impl ArrayIndex for ($($t,)+) {
            fn index<T>(&self, array: &Array<T>) -> usize {
                let ($($name,)+) = *self;
                let slice: &[isize] = &[$($name),+];
                ArrayIndex::index(&slice, array)
            }
        }
    }
}

tuple_impl!(a: isize);
tuple_impl!(a: isize, b: isize);
tuple_impl!(a: isize, b: isize, c: isize);
tuple_impl!(a: isize, b: isize, c: isize, d: isize);
tuple_impl!(a: isize, b: isize, c: isize, d: isize, e: isize);
tuple_impl!(a: isize, b: isize, c: isize, d: isize, e: isize, f: isize);
tuple_impl!(a: isize, b: isize, c: isize, d: isize, e: isize, f: isize, g: isize);
tuple_impl!(a: isize, b: isize, c: isize, d: isize, e: isize, f: isize, g: isize, h: isize);
tuple_impl!(a: isize, b: isize, c: isize, d: isize, e: isize, f: isize, g: isize, h: isize, i: isize);

impl<T, I: ArrayIndex> Index<I> for Array<T> {
    type Output = T;

    /// Indexes into the `Array`, retrieving a reference to the contained
    /// value.
    ///
    /// Since `Array`s can be multi-dimensional, the `Index` trait is
    /// implemented for a variety of index types. In the most generic case, a
    /// `&[isize]` can be used. In addition, a bare `isize` as well as tuples
    /// of up to 10 `isize` values may be used for convenience.
    ///
    /// # Panics
    ///
    /// Panics if the index does not correspond to an in-bounds element of the
    /// `Array`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use postgres_array::Array;
    /// let mut array = Array::from_vec(vec![0i32, 1, 2, 3], 0);
    /// assert_eq!(2, array[2]);
    ///
    /// array.wrap(0);
    /// array.push(Array::from_vec(vec![4, 5, 6, 7], 0));
    ///
    /// assert_eq!(6, array[(1, 2)]);
    /// ```
    fn index(&self, idx: I) -> &T {
        let idx = idx.index(self);
        &self.data[idx]
    }
}

impl<T, I: ArrayIndex> IndexMut<I> for Array<T> {
    fn index_mut(&mut self, idx: I) -> &mut T {
        let idx = idx.index(self);
        &mut self.data[idx]
    }
}

impl<'a, T: 'a> IntoIterator for &'a Array<T> {
    type Item = &'a T;
    type IntoIter = Iter<'a, T>;

    fn into_iter(self) -> Iter<'a, T> {
        self.iter()
    }
}

impl<'a, T: 'a> IntoIterator for &'a mut Array<T> {
    type Item = &'a mut T;
    type IntoIter = IterMut<'a, T>;

    fn into_iter(self) -> IterMut<'a, T> {
        self.iter_mut()
    }
}

impl<T> IntoIterator for Array<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;

    fn into_iter(self) -> IntoIter<T> {
        IntoIter {
            inner: self.data.into_iter()
        }
    }
}

/// An iterator over references to values of an `Array` in the
/// higher-dimensional equivalent of row-major order.
pub struct Iter<'a, T: 'a> {
    inner: slice::Iter<'a, T>,
}

impl<'a, T: 'a> Iterator for Iter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        self.inner.next()
    }
}

impl<'a, T: 'a> DoubleEndedIterator for Iter<'a, T> {
    fn next_back(&mut self) -> Option<&'a T> {
        self.inner.next_back()
    }
}

/// An iterator over mutable references to values of an `Array` in the
/// higher-dimensional equivalent of row-major order.
pub struct IterMut<'a, T: 'a> {
    inner: slice::IterMut<'a, T>,
}

impl<'a, T: 'a> Iterator for IterMut<'a, T> {
    type Item = &'a mut T;

    fn next(&mut self) -> Option<&'a mut T> {
        self.inner.next()
    }
}

impl<'a, T: 'a> DoubleEndedIterator for IterMut<'a, T> {
    fn next_back(&mut self) -> Option<&'a mut T> {
        self.inner.next_back()
    }
}

/// An iterator over values of an `Array` in the higher-dimensional
/// equivalent of row-major order.
pub struct IntoIter<T> {
    inner: vec::IntoIter<T>,
}

impl<T> Iterator for IntoIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        self.inner.next()
    }
}

impl<T> DoubleEndedIterator for IntoIter<T> {
    fn next_back(&mut self) -> Option<T> {
        self.inner.next_back()
    }
}
<commit_msg>Make Index docs actually render<commit_after>use std::ops::{Index, IndexMut};
use std::slice;
use std::vec;
use std::fmt;

use Dimension;

/// A multi-dimensional array.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Array<T> {
    dims: Vec<Dimension>,
    data: Vec<T>,
}

impl<T: fmt::Display> fmt::Display for Array<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        if self.dims.iter().any(|dim| dim.lower_bound != 1) {
            for dim in &self.dims {
                try!(write!(fmt, "[{}:{}]", dim.lower_bound,
                            dim.lower_bound + dim.len as isize - 1));
            }
            try!(write!(fmt, "="));
        }
        fmt_helper(0, &self.dims, &mut self.data.iter(), fmt)
    }
}

fn fmt_helper<'a, T, I>(depth: usize,
                        dims: &[Dimension],
                        mut data: &mut I,
                        fmt: &mut fmt::Formatter)
                        -> fmt::Result
        where I: Iterator<Item=&'a T>, T: 'a + fmt::Display {
    if depth == dims.len() {
        return write!(fmt, "{}", data.next().unwrap());
    }

    try!(write!(fmt, "{{"));
    for i in 0..dims[depth].len {
        if i != 0 {
            try!(write!(fmt, ","));
        }
        try!(fmt_helper(depth + 1, dims, data, fmt));
    }
    write!(fmt, "}}")
}

impl<T> Array<T> {
    /// Creates a new `Array` from its underlying components.
    ///
    /// The data array should be provided in the higher-dimensional equivalent
    /// of row-major order.
    ///
    /// # Panics
    ///
    /// Panics if the number of elements provided does not match the number of
    /// elements specified by the dimensions.
    pub fn from_parts(data: Vec<T>, dimensions: Vec<Dimension>) -> Array<T> {
        assert!((data.is_empty() && dimensions.is_empty()) ||
                data.len() == dimensions.iter().fold(1, |acc, i| acc * i.len),
                "size mismatch");
        Array {
            dims: dimensions,
            data: data,
        }
    }

    /// Creates a new one-dimensional array.
    pub fn from_vec(data: Vec<T>, lower_bound: isize) -> Array<T> {
        Array {
            dims: vec![Dimension {
                len: data.len(),
                lower_bound: lower_bound
            }],
            data: data,
        }
    }

    /// Wraps this array in a new dimension of size 1.
    ///
    /// For example, the one dimensional array `[1, 2]` would turn into the
    /// two-dimensional array `[[1, 2]]`.
    pub fn wrap(&mut self, lower_bound: isize) {
        self.dims.insert(0, Dimension {
            len: 1,
            lower_bound: lower_bound,
        });
    }

    /// Consumes another array, appending it to the top level dimension of this
    /// array.
    ///
    /// The dimensions of the other array must be the same as the dimensions
    /// of this array with the first dimension removed. This includes lower
    /// bounds as well as lengths.
    ///
    /// For example, if `[3, 4]` is pushed onto `[[1, 2]]`, the result is
    /// `[[1, 2], [3, 4]]`.
    ///
    /// # Panics
    ///
    /// Panics if the dimensions of the two arrays do not match.
    pub fn push(&mut self, other: Array<T>) {
        assert!(self.dims.len() - 1 == other.dims.len(),
                "cannot append differently shaped arrays");
        for (dim1, dim2) in self.dims.iter().skip(1).zip(other.dims.iter()) {
            assert!(dim1 == dim2, "cannot append differently shaped arrays");
        }
        self.dims[0].len += 1;
        self.data.extend(other.data);
    }

    /// Returns the dimensions of this array.
    pub fn dimensions(&self) -> &[Dimension] {
        &self.dims
    }

    fn shift_idx(&self, indices: &[isize]) -> usize {
        assert_eq!(self.dims.len(), indices.len());
        self.dims
            .iter()
            .zip(indices.iter().cloned())
            .rev()
            .fold((0, 1), |(acc, stride), (dim, idx)| {
                let shifted = dim.shift(idx);
                (acc + shifted * stride, dim.len * stride)
            })
            .0
    }

    /// Returns an iterator over references to the elements of the array in the
    /// higher-dimensional equivalent of row-major order.
    pub fn iter<'a>(&'a self) -> Iter<'a, T> {
        Iter {
            inner: self.data.iter(),
        }
    }

    /// Returns an iterator over mutable references to the elements of the
    /// array in the higher-dimensional equivalent of row-major order.
    pub fn iter_mut<'a>(&'a mut self) -> IterMut<'a, T> {
        IterMut {
            inner: self.data.iter_mut(),
        }
    }
}

/// A trait implemented by types that can index into an `Array`.
pub trait ArrayIndex {
    /// Calculates the index into the `Array`'s underlying storage specified
    /// by the value of `self`.
    ///
    /// # Panics
    ///
    /// Panics if the value of `self` does not correspond to an in-bounds
    /// element of the `Array`.
    fn index<T>(&self, array: &Array<T>) -> usize;
}

impl<'a> ArrayIndex for &'a [isize] {
    fn index<T>(&self, array: &Array<T>) -> usize {
        array.shift_idx(*self)
    }
}

impl ArrayIndex for isize {
    fn index<T>(&self, array: &Array<T>) -> usize {
        let slice: &[isize] = &[*self];
        ArrayIndex::index(&slice, array)
    }
}

macro_rules! tuple_impl {
    ($($name:ident : $t:ty),+) => {
        impl ArrayIndex for ($($t,)+) {
            fn index<T>(&self, array: &Array<T>) -> usize {
                let ($($name,)+) = *self;
                let slice: &[isize] = &[$($name),+];
                ArrayIndex::index(&slice, array)
            }
        }
    }
}

tuple_impl!(a: isize);
tuple_impl!(a: isize, b: isize);
tuple_impl!(a: isize, b: isize, c: isize);
tuple_impl!(a: isize, b: isize, c: isize, d: isize);
tuple_impl!(a: isize, b: isize, c: isize, d: isize, e: isize);
tuple_impl!(a: isize, b: isize, c: isize, d: isize, e: isize, f: isize);
tuple_impl!(a: isize, b: isize, c: isize, d: isize, e: isize, f: isize, g: isize);
tuple_impl!(a: isize, b: isize, c: isize, d: isize, e: isize, f: isize, g: isize, h: isize);
tuple_impl!(a: isize, b: isize, c: isize, d: isize, e: isize, f: isize, g: isize, h: isize, i: isize);

/// Indexes into the `Array`, retrieving a reference to the contained
/// value.
///
/// Since `Array`s can be multi-dimensional, the `Index` trait is
/// implemented for a variety of index types. In the most generic case, a
/// `&[isize]` can be used. In addition, a bare `isize` as well as tuples
/// of up to 10 `isize` values may be used for convenience.
///
/// # Panics
///
/// Panics if the index does not correspond to an in-bounds element of the
/// `Array`.
///
/// # Examples
///
/// ```rust
/// # use postgres_array::Array;
/// let mut array = Array::from_vec(vec![0i32, 1, 2, 3], 0);
/// assert_eq!(2, array[2]);
///
/// array.wrap(0);
/// array.push(Array::from_vec(vec![4, 5, 6, 7], 0));
///
/// assert_eq!(6, array[(1, 2)]);
/// ```
impl<T, I: ArrayIndex> Index<I> for Array<T> {
    type Output = T;
    fn index(&self, idx: I) -> &T {
        let idx = idx.index(self);
        &self.data[idx]
    }
}

impl<T, I: ArrayIndex> IndexMut<I> for Array<T> {
    fn index_mut(&mut self, idx: I) -> &mut T {
        let idx = idx.index(self);
        &mut self.data[idx]
    }
}

impl<'a, T: 'a> IntoIterator for &'a Array<T> {
    type Item = &'a T;
    type IntoIter = Iter<'a, T>;

    fn into_iter(self) -> Iter<'a, T> {
        self.iter()
    }
}

impl<'a, T: 'a> IntoIterator for &'a mut Array<T> {
    type Item = &'a mut T;
    type IntoIter = IterMut<'a, T>;

    fn into_iter(self) -> IterMut<'a, T> {
        self.iter_mut()
    }
}

impl<T> IntoIterator for Array<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;

    fn into_iter(self) -> IntoIter<T> {
        IntoIter {
            inner: self.data.into_iter()
        }
    }
}

/// An iterator over references to values of an `Array` in the
/// higher-dimensional equivalent of row-major order.
pub struct Iter<'a, T: 'a> {
    inner: slice::Iter<'a, T>,
}

impl<'a, T: 'a> Iterator for Iter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        self.inner.next()
    }
}

impl<'a, T: 'a> DoubleEndedIterator for Iter<'a, T> {
    fn next_back(&mut self) -> Option<&'a T> {
        self.inner.next_back()
    }
}

/// An iterator over mutable references to values of an `Array` in the
/// higher-dimensional equivalent of row-major order.
pub struct IterMut<'a, T: 'a> {
    inner: slice::IterMut<'a, T>,
}

impl<'a, T: 'a> Iterator for IterMut<'a, T> {
    type Item = &'a mut T;

    fn next(&mut self) -> Option<&'a mut T> {
        self.inner.next()
    }
}

impl<'a, T: 'a> DoubleEndedIterator for IterMut<'a, T> {
    fn next_back(&mut self) -> Option<&'a mut T> {
        self.inner.next_back()
    }
}

/// An iterator over values of an `Array` in the higher-dimensional
/// equivalent of row-major order.
pub struct IntoIter<T> {
    inner: vec::IntoIter<T>,
}

impl<T> Iterator for IntoIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        self.inner.next()
    }
}

impl<T> DoubleEndedIterator for IntoIter<T> {
    fn next_back(&mut self) -> Option<T> {
        self.inner.next_back()
    }
}
<|endoftext|>


<commit_before>
use piston_window::{Context, G2d, Line, Transformed, types};
use piston_window::grid::Grid;

use colors::GREY;
use game::{Renderer, GridRenderer, render_square_in_grid};
use tetromino::{Piece, Block};
use settings::*;

pub struct Board {
    grid: [[CellState; HEIGHT_IN_BLOCKS as usize]; WIDTH_IN_BLOCKS as usize]
}
impl Board {
    pub fn new() -> Board {
        Board {
            grid: [[CellState::Empty; HEIGHT_IN_BLOCKS as usize]; WIDTH_IN_BLOCKS as usize]
        }
    }

    pub fn set_piece(&mut self, piece: &Piece) {
        for block in piece.blocks_iter() {
            self.set_cell_state(block, CellState::Block(piece.get_color()));
        }
    }

    pub fn is_space_occupied(&self, block: Block) -> bool {
        match self.get_cell_state(block.x, block.y) {
            CellState::Block(_) => true,
            CellState::Empty => false
        }
    }

    // Removes completed rows from the board and returns the number
    // of rows completed.
    pub fn remove_completed_rows(&mut self) -> i32 {
        0
    }

    fn get_cell_state(&self, x: i32, y: i32) -> CellState {
        self.grid[x as usize][y as usize]
    }

    fn set_cell_state(&mut self, block: Block, cell_state: CellState) {
        self.grid[block.x as usize][block.y as usize] = cell_state;
    }
}
impl Renderer for Board {
    fn render(&self, context: Context, graphics: &mut G2d) {
        let grid = Grid {
            cols: WIDTH_IN_BLOCKS as u32,
            rows: HEIGHT_IN_BLOCKS as u32,
            units: BLOCK_SIZE
        };
        let line = Line::new(GREY, GRID_LINE_WIDTH);
        let transform = context.transform.trans(GRID_X_OFFSET, GRID_Y_OFFSET);
        grid.draw(&line, &Default::default(), transform, graphics);
        for x in 0..WIDTH_IN_BLOCKS {
            for y in 0..HEIGHT_IN_BLOCKS {
                self.get_cell_state(x, y).render(x, y, context, graphics);
            }
        }
    }
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum CellState {
    Empty,
    Block(types::Color)
}
impl GridRenderer for CellState {
    fn render(&self, x: i32, y: i32, context: Context, graphics: &mut G2d) {
        match *self {
            CellState::Block(color) => {
                render_square_in_grid(x, y, color, context, graphics);
            },
            CellState::Empty => {}
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use colors::{RED, CYAN};
    use tetromino::{Block, Piece, I};

    #[test]
    fn test_set_piece() {
        let mut board = Board::new();
        let piece = Piece::create(&I);
        board.set_piece(&piece);
        assert_eq!(board.get_cell_state(2, 1), CellState::Empty);
        assert_eq!(board.get_cell_state(3, 1), CellState::Block(CYAN));
        assert_eq!(board.get_cell_state(4, 1), CellState::Block(CYAN));
        assert_eq!(board.get_cell_state(5, 1), CellState::Block(CYAN));
        assert_eq!(board.get_cell_state(6, 1), CellState::Block(CYAN));
        assert_eq!(board.get_cell_state(7, 1), CellState::Empty);
    }

    #[test]
    fn test_is_space_occupied() {
        let mut board = Board::new();
        let block = Block{x: 2, y: 2};
        board.set_cell_state(block, CellState::Block(RED));
        assert!(board.is_space_occupied(block));
        assert!(!board.is_space_occupied(Block{x: 0, y: 0}));
    }

    #[test]
    fn test_set_cell_state() {
        let mut board = Board::new();
        assert_eq!(board.get_cell_state(0, 0), CellState::Empty);
        board.set_cell_state(Block{x: 2, y: 2}, CellState::Block(RED));
        assert_eq!(board.get_cell_state(2, 2), CellState::Block(RED));
    }
}
<commit_msg>swap the order with which I'm storing the rows and cols in the grid. Makes far more sense this way<commit_after>
use piston_window::{Context, G2d, Line, Transformed, types};
use piston_window::grid::Grid;

use colors::GREY;
use game::{Renderer, GridRenderer, render_square_in_grid};
use tetromino::{Piece, Block};
use settings::*;

pub struct Board {
    grid: [[CellState; WIDTH_IN_BLOCKS as usize]; HEIGHT_IN_BLOCKS as usize]
}
impl Board {
    pub fn new() -> Board {
        Board {
            grid: [[CellState::Empty; WIDTH_IN_BLOCKS as usize]; HEIGHT_IN_BLOCKS as usize]
        }
    }

    pub fn set_piece(&mut self, piece: &Piece) {
        for block in piece.blocks_iter() {
            self.set_cell_state(block, CellState::Block(piece.get_color()));
        }
    }

    pub fn is_space_occupied(&self, block: Block) -> bool {
        match self.get_cell_state(block.x, block.y) {
            CellState::Block(_) => true,
            CellState::Empty => false
        }
    }

    // Removes completed rows from the board and returns the number
    // of rows completed.
    pub fn remove_completed_rows(&mut self) -> i32 {
        0
    }

    fn get_cell_state(&self, x: i32, y: i32) -> CellState {
        self.grid[y as usize][x as usize]
    }

    fn set_cell_state(&mut self, block: Block, cell_state: CellState) {
        self.grid[block.y as usize][block.x as usize] = cell_state;
    }
}
impl Renderer for Board {
    fn render(&self, context: Context, graphics: &mut G2d) {
        let grid = Grid {
            cols: WIDTH_IN_BLOCKS as u32,
            rows: HEIGHT_IN_BLOCKS as u32,
            units: BLOCK_SIZE
        };
        let line = Line::new(GREY, GRID_LINE_WIDTH);
        let transform = context.transform.trans(GRID_X_OFFSET, GRID_Y_OFFSET);
        grid.draw(&line, &Default::default(), transform, graphics);
        for x in 0..WIDTH_IN_BLOCKS {
            for y in 0..HEIGHT_IN_BLOCKS {
                self.get_cell_state(x, y).render(x, y, context, graphics);
            }
        }
    }
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum CellState {
    Empty,
    Block(types::Color)
}
impl GridRenderer for CellState {
    fn render(&self, x: i32, y: i32, context: Context, graphics: &mut G2d) {
        match *self {
            CellState::Block(color) => {
                render_square_in_grid(x, y, color, context, graphics);
            },
            CellState::Empty => {}
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use colors::{RED, CYAN};
    use tetromino::{Block, Piece, I};

    #[test]
    fn test_set_piece() {
        let mut board = Board::new();
        let piece = Piece::create(&I);
        board.set_piece(&piece);
        assert_eq!(board.get_cell_state(2, 1), CellState::Empty);
        assert_eq!(board.get_cell_state(3, 1), CellState::Block(CYAN));
        assert_eq!(board.get_cell_state(4, 1), CellState::Block(CYAN));
        assert_eq!(board.get_cell_state(5, 1), CellState::Block(CYAN));
        assert_eq!(board.get_cell_state(6, 1), CellState::Block(CYAN));
        assert_eq!(board.get_cell_state(7, 1), CellState::Empty);
    }

    #[test]
    fn test_is_space_occupied() {
        let mut board = Board::new();
        let block = Block{x: 2, y: 2};
        board.set_cell_state(block, CellState::Block(RED));
        assert!(board.is_space_occupied(block));
        assert!(!board.is_space_occupied(Block{x: 0, y: 0}));
    }

    #[test]
    fn test_set_cell_state() {
        let mut board = Board::new();
        assert_eq!(board.get_cell_state(0, 0), CellState::Empty);
        board.set_cell_state(Block{x: 2, y: 2}, CellState::Block(RED));
        assert_eq!(board.get_cell_state(2, 2), CellState::Block(RED));
    }
}
<|endoftext|>


<commit_before>/*!

This crate provides wrappers and convenience functions to make rust-url
and Serde work hand in hand.

The supported types are:

* `url::Url`

# How do I use a data type with a `Url` member with Serde?

Use the serde attributes `deserialize_with` and `serialize_with`.

```
#[derive(serde::Serialize, serde::Deserialize)]
struct MyStruct {
    #[serde(deserialize_with = "url_serde::deserialize",
    serialize_with = "url_serde::serialize")]
    url: Url,
}
```

# How do I encode a `Url` value with `serde_json::to_string`?

Use the `Ser` wrapper.

```
serde_json::to_string(&Ser::new(&url))
```

# How do I decode a `Url` value with `serde_json::parse`?

Use the `De` wrapper.

```
serde_json::from_str(r"http:://www.rust-lang.org").map(De::into_inner)
```

# How do I send `Url` values as part of an IPC channel?

Use the `Serde` wrapper. It implements `Deref` and `DerefMut` for convenience.

```
ipc::channel::<Serde<Url>>()
```
*/

#![deny(missing_docs)]
#![deny(unsafe_code)]

extern crate serde;
extern crate url;

#[cfg(test)]
#[macro_use]
extern crate serde_derive;

use std::cmp::PartialEq;
use std::fmt;
use std::ops::{Deref, DerefMut};
use std::error::Error;
use serde::{Deserialize, Serialize, Serializer, Deserializer};
use url::{Url};

/// Serialises `value` with a given serializer.
///
/// This is useful to serialize `rust-url` types used in structure fields or
/// tuple members with `#[serde(serialize_with = "url_serde::serialize")]`.
pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
    where S: Serializer, for<'a> Ser<'a, T>: Serialize
{
    Ser::new(value).serialize(serializer)
}

/// A wrapper to serialize `rust-url` types.
///
/// This is useful with functions such as `serde_json::to_string`.
///
/// Values of this type can only be passed to the `serde::Serialize` trait.
#[derive(Debug)]
pub struct Ser<'a, T: 'a>(&'a T);

impl<'a, T> Ser<'a, T> where Ser<'a, T>: Serialize {
    /// Returns a new `Ser` wrapper.
    #[inline(always)]
    pub fn new(value: &'a T) -> Self {
        Ser(value)
    }
}

/// Serializes this URL into a `serde` stream.
impl<'a> Serialize for Ser<'a, Url> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        serializer.serialize_str(self.0.as_str())
    }
}

/// Serializes this Option<URL> into a `serde` stream.
impl<'a> Serialize for Ser<'a, Option<Url>> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        if let Some(url) = self.0.as_ref() {
            serializer.serialize_some(url.as_str())
        } else {
            serializer.serialize_none()
        }
    }
}

/// Deserialises a `T` value with a given deserializer.
///
/// This is useful to deserialize Url types used in structure fields or
/// tuple members with `#[serde(deserialize_with = "url_serde::deserialize")]`.
pub fn deserialize<T, D>(deserializer: D) -> Result<T, D::Error>
    where D: Deserializer, De<T>: Deserialize
{
    De::deserialize(deserializer).map(De::into_inner)
}

/// A wrapper to deserialize `rust-url` types.
///
/// This is useful with functions such as `serde_json::from_str`.
///
/// Values of this type can only be obtained through
/// the `serde::Deserialize` trait.
#[derive(Debug)]
pub struct De<T>(T);

impl<T> De<T> where De<T>: serde::Deserialize {
    /// Consumes this wrapper, returning the deserialized value.
    #[inline(always)]
    pub fn into_inner(self) -> T {
        self.0
    }
}

/// Deserializes this URL from a `serde` stream.
impl Deserialize for De<Url> {
    fn deserialize<D>(deserializer: D) -> Result<De<Url>, D::Error> where D: Deserializer {
        let string_representation: String = Deserialize::deserialize(deserializer)?;
        Url::parse(&string_representation).map(De).map_err(|err| {
            serde::de::Error::custom(err.description())
        })
    }
}

/// Deserializes this Option<URL> from a `serde` stream.
impl Deserialize for De<Option<Url>> {
    fn deserialize<D>(deserializer: D) -> Result<De<Option<Url>>, D::Error> where D: Deserializer {
        let option_representation: Option<String> = Deserialize::deserialize(deserializer)?;
        if let Some(s) = option_representation {
            return Url::parse(&s)
                .map(Some)
                .map(De)
                .map_err(|err| {serde::de::Error::custom(err.description())});
        }
        Ok(De(None))

    }
}

/// A convenience wrapper to be used as a type parameter, for example when
/// a `Vec<T>` or an `HashMap<K, V>` need to be passed to serde.
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct Serde<T>(pub T)
    where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize;

/// A convenience type alias for Serde<Url>.
pub type SerdeUrl = Serde<Url>;

impl<T> Serde<T>
where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    /// Consumes this wrapper, returning the inner value.
    #[inline(always)]
    pub fn into_inner(self) -> T {
        self.0
    }
}

impl<T> fmt::Debug for Serde<T>
where T: fmt::Debug, De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.0.fmt(formatter)
    }
}

impl<T> Deref for Serde<T>
where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    type Target = T;

    fn deref(&self) -> &T {
        &self.0
    }
}

impl<T> DerefMut for Serde<T>
where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    fn deref_mut(&mut self) -> &mut T {
        &mut self.0
    }
}

impl<T: PartialEq> PartialEq<T> for Serde<T>
where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    fn eq(&self, other: &T) -> bool {
        self.0 == *other
    }
}

impl<T> Deserialize for Serde<T>
where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer
    {
        De::deserialize(deserializer).map(De::into_inner).map(Serde)
    }
}

impl<T> Serialize for Serde<T>
where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        Ser(&self.0).serialize(serializer)
    }
}

#[test]
fn test_ser_de_url() {
    extern crate serde_json;
    let url = Url::parse("http://www.test.com/foo/bar?$param=bazz").unwrap();
    let s = serde_json::to_string(&Ser::new(&url)).unwrap();
    let new_url: Url = serde_json::from_str(&s).map(De::into_inner).unwrap();
    assert_eq!(url, new_url);
}

#[test]
fn test_derive_deserialize_with_for_url() {
    extern crate serde_json;

    #[derive(Deserialize, Debug, Eq, PartialEq)]
    struct Test {
        #[serde(deserialize_with = "deserialize", rename = "_url_")]
        url: Url
    }

    let url_str = "http://www.test.com/foo/bar?$param=bazz";

    let expected = Test {
        url: Url::parse(url_str).unwrap()
    };
    let json_string = format!(r#"{{"_url_": "{}"}}"#, url_str);
    let got: Test = serde_json::from_str(&json_string).unwrap();
    assert_eq!(expected, got);

}

#[test]
fn test_derive_deserialize_with_for_option_url() {
    extern crate serde_json;

    #[derive(Deserialize, Debug, Eq, PartialEq)]
    struct Test {
        #[serde(deserialize_with = "deserialize", rename = "_url_")]
        url: Option<Url>
    }

    let url_str = "http://www.test.com/foo/bar?$param=bazz";

    let expected = Test {
        url: Some(Url::parse(url_str).unwrap())
    };
    let json_string = format!(r#"{{"_url_": "{}"}}"#, url_str);
    let got: Test = serde_json::from_str(&json_string).unwrap();
    assert_eq!(expected, got);

    let expected = Test {
        url: None
    };
    let json_string = r#"{"_url_": null}"#;
    let got: Test = serde_json::from_str(&json_string).unwrap();
    assert_eq!(expected, got);
}

#[test]
fn test_derive_serialize_with_for_url() {
    extern crate serde_json;

    #[derive(Serialize, Debug, Eq, PartialEq)]
    struct Test {
        #[serde(serialize_with = "serialize", rename = "_url_")]
        url: Url
    }

    let url_str = "http://www.test.com/foo/bar?$param=bazz";

    let expected = format!(r#"{{"_url_":"{}"}}"#, url_str);
    let input = Test {url: Url::parse(url_str).unwrap()};
    let got = serde_json::to_string(&input).unwrap();
    assert_eq!(expected, got);
}

#[test]
fn test_derive_serialize_with_for_option_url() {
    extern crate serde_json;

    #[derive(Serialize, Debug, Eq, PartialEq)]
    struct Test {
        #[serde(serialize_with = "serialize", rename = "_url_")]
        url: Option<Url>
    }

    let url_str = "http://www.test.com/foo/bar?$param=bazz";

    let expected = format!(r#"{{"_url_":"{}"}}"#, url_str);
    let input = Test {url: Some(Url::parse(url_str).unwrap())};
    let got = serde_json::to_string(&input).unwrap();
    assert_eq!(expected, got);

    let expected = format!(r#"{{"_url_":null}}"#);
    let input = Test {url: None};
    let got = serde_json::to_string(&input).unwrap();
    assert_eq!(expected, got);
}
<commit_msg>Add support for Host in url_serde<commit_after>// Copyright 2017 The rust-url 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. This file may not be copied, modified, or distributed
// except according to those terms.

/*!

This crate provides wrappers and convenience functions to make rust-url
and Serde work hand in hand.

The supported types are:

* `url::Url`

# How do I use a data type with a `Url` member with Serde?

Use the serde attributes `deserialize_with` and `serialize_with`.

```
#[derive(serde::Serialize, serde::Deserialize)]
struct MyStruct {
    #[serde(deserialize_with = "url_serde::deserialize",
    serialize_with = "url_serde::serialize")]
    url: Url,
}
```

# How do I encode a `Url` value with `serde_json::to_string`?

Use the `Ser` wrapper.

```
serde_json::to_string(&Ser::new(&url))
```

# How do I decode a `Url` value with `serde_json::parse`?

Use the `De` wrapper.

```
serde_json::from_str(r"http:://www.rust-lang.org").map(De::into_inner)
```

# How do I send `Url` values as part of an IPC channel?

Use the `Serde` wrapper. It implements `Deref` and `DerefMut` for convenience.

```
ipc::channel::<Serde<Url>>()
```
*/

#![deny(missing_docs)]
#![deny(unsafe_code)]

extern crate serde;
#[cfg(test)] #[macro_use] extern crate serde_derive;
#[cfg(test)] extern crate serde_json;
extern crate url;

use serde::{Deserialize, Serialize, Serializer, Deserializer};
use std::cmp::PartialEq;
use std::error::Error;
use std::fmt;
use std::io::Write;
use std::ops::{Deref, DerefMut};
use std::str;
use url::{Url, Host};

/// Serialises `value` with a given serializer.
///
/// This is useful to serialize `rust-url` types used in structure fields or
/// tuple members with `#[serde(serialize_with = "url_serde::serialize")]`.
pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
    where S: Serializer, for<'a> Ser<'a, T>: Serialize
{
    Ser::new(value).serialize(serializer)
}

/// A wrapper to serialize `rust-url` types.
///
/// This is useful with functions such as `serde_json::to_string`.
///
/// Values of this type can only be passed to the `serde::Serialize` trait.
#[derive(Debug)]
pub struct Ser<'a, T: 'a>(&'a T);

impl<'a, T> Ser<'a, T> where Ser<'a, T>: Serialize {
    /// Returns a new `Ser` wrapper.
    #[inline(always)]
    pub fn new(value: &'a T) -> Self {
        Ser(value)
    }
}

/// Serializes this URL into a `serde` stream.
impl<'a> Serialize for Ser<'a, Url> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        serializer.serialize_str(self.0.as_str())
    }
}

/// Serializes this Option<URL> into a `serde` stream.
impl<'a> Serialize for Ser<'a, Option<Url>> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        if let Some(url) = self.0.as_ref() {
            serializer.serialize_some(url.as_str())
        } else {
            serializer.serialize_none()
        }
    }
}

impl<'a, String> Serialize for Ser<'a, Host<String>> where String: AsRef<str> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        match *self.0 {
            Host::Domain(ref s) => serializer.serialize_str(s.as_ref()),
            Host::Ipv4(_) | Host::Ipv6(_) => {
                // max("101.102.103.104".len(),
                //     "[1000:1002:1003:1004:1005:1006:101.102.103.104]".len())
                const MAX_LEN: usize = 47;
                let mut buffer = [0; MAX_LEN];
                serializer.serialize_str(display_into_buffer(&self.0, &mut buffer))
            }
        }
    }
}

/// Like .to_string(), but doesn’t allocate memory for a `String`.
///
/// Panics if `buffer` is too small.
fn display_into_buffer<'a, T: fmt::Display>(value: &T, buffer: &'a mut [u8]) -> &'a str {
    let remaining_len;
    {
        let mut remaining = &mut *buffer;
        write!(remaining, "{}", value).unwrap();
        remaining_len = remaining.len()
    }
    let written_len = buffer.len() - remaining_len;
    let written = &buffer[..written_len];

    // write! only provides std::fmt::Formatter to Display implementations,
    // which has methods write_str and write_char but no method to write arbitrary bytes.
    // Therefore, `written` is well-formed in UTF-8.
    #[allow(unsafe_code)]
    unsafe {
        str::from_utf8_unchecked(written)
    }
}

/// Deserialises a `T` value with a given deserializer.
///
/// This is useful to deserialize Url types used in structure fields or
/// tuple members with `#[serde(deserialize_with = "url_serde::deserialize")]`.
pub fn deserialize<T, D>(deserializer: D) -> Result<T, D::Error>
    where D: Deserializer, De<T>: Deserialize
{
    De::deserialize(deserializer).map(De::into_inner)
}

/// A wrapper to deserialize `rust-url` types.
///
/// This is useful with functions such as `serde_json::from_str`.
///
/// Values of this type can only be obtained through
/// the `serde::Deserialize` trait.
#[derive(Debug)]
pub struct De<T>(T);

impl<T> De<T> where De<T>: serde::Deserialize {
    /// Consumes this wrapper, returning the deserialized value.
    #[inline(always)]
    pub fn into_inner(self) -> T {
        self.0
    }
}

/// Deserializes this URL from a `serde` stream.
impl Deserialize for De<Url> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer {
        let string_representation: String = Deserialize::deserialize(deserializer)?;
        Url::parse(&string_representation).map(De).map_err(|err| {
            serde::de::Error::custom(err.description())
        })
    }
}

/// Deserializes this Option<URL> from a `serde` stream.
impl Deserialize for De<Option<Url>> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer {
        let option_representation: Option<String> = Deserialize::deserialize(deserializer)?;
        if let Some(s) = option_representation {
            return Url::parse(&s)
                .map(Some)
                .map(De)
                .map_err(|err| {serde::de::Error::custom(err.description())});
        }
        Ok(De(None))

    }
}

impl Deserialize for De<Host> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer {
        let string_representation: String = Deserialize::deserialize(deserializer)?;
        Host::parse(&string_representation).map(De).map_err(|err| {
            serde::de::Error::custom(err.description())
        })
    }
}

/// A convenience wrapper to be used as a type parameter, for example when
/// a `Vec<T>` or an `HashMap<K, V>` need to be passed to serde.
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct Serde<T>(pub T)
    where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize;

/// A convenience type alias for Serde<Url>.
pub type SerdeUrl = Serde<Url>;

impl<T> Serde<T>
where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    /// Consumes this wrapper, returning the inner value.
    #[inline(always)]
    pub fn into_inner(self) -> T {
        self.0
    }
}

impl<T> fmt::Debug for Serde<T>
where T: fmt::Debug, De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.0.fmt(formatter)
    }
}

impl<T> Deref for Serde<T>
where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    type Target = T;

    fn deref(&self) -> &T {
        &self.0
    }
}

impl<T> DerefMut for Serde<T>
where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    fn deref_mut(&mut self) -> &mut T {
        &mut self.0
    }
}

impl<T: PartialEq> PartialEq<T> for Serde<T>
where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    fn eq(&self, other: &T) -> bool {
        self.0 == *other
    }
}

impl<T> Deserialize for Serde<T>
where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer
    {
        De::deserialize(deserializer).map(De::into_inner).map(Serde)
    }
}

impl<T> Serialize for Serde<T>
where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        Ser(&self.0).serialize(serializer)
    }
}

#[test]
fn test_ser_de_url() {
    let url = Url::parse("http://www.test.com/foo/bar?$param=bazz").unwrap();
    let s = serde_json::to_string(&Ser::new(&url)).unwrap();
    let new_url: Url = serde_json::from_str(&s).map(De::into_inner).unwrap();
    assert_eq!(url, new_url);
}

#[test]
fn test_derive_deserialize_with_for_url() {
    #[derive(Deserialize, Debug, Eq, PartialEq)]
    struct Test {
        #[serde(deserialize_with = "deserialize", rename = "_url_")]
        url: Url
    }

    let url_str = "http://www.test.com/foo/bar?$param=bazz";

    let expected = Test {
        url: Url::parse(url_str).unwrap()
    };
    let json_string = format!(r#"{{"_url_": "{}"}}"#, url_str);
    let got: Test = serde_json::from_str(&json_string).unwrap();
    assert_eq!(expected, got);

}

#[test]
fn test_derive_deserialize_with_for_option_url() {
    #[derive(Deserialize, Debug, Eq, PartialEq)]
    struct Test {
        #[serde(deserialize_with = "deserialize", rename = "_url_")]
        url: Option<Url>
    }

    let url_str = "http://www.test.com/foo/bar?$param=bazz";

    let expected = Test {
        url: Some(Url::parse(url_str).unwrap())
    };
    let json_string = format!(r#"{{"_url_": "{}"}}"#, url_str);
    let got: Test = serde_json::from_str(&json_string).unwrap();
    assert_eq!(expected, got);

    let expected = Test {
        url: None
    };
    let json_string = r#"{"_url_": null}"#;
    let got: Test = serde_json::from_str(&json_string).unwrap();
    assert_eq!(expected, got);
}

#[test]
fn test_derive_serialize_with_for_url() {
    #[derive(Serialize, Debug, Eq, PartialEq)]
    struct Test {
        #[serde(serialize_with = "serialize", rename = "_url_")]
        url: Url
    }

    let url_str = "http://www.test.com/foo/bar?$param=bazz";

    let expected = format!(r#"{{"_url_":"{}"}}"#, url_str);
    let input = Test {url: Url::parse(url_str).unwrap()};
    let got = serde_json::to_string(&input).unwrap();
    assert_eq!(expected, got);
}

#[test]
fn test_derive_serialize_with_for_option_url() {
    #[derive(Serialize, Debug, Eq, PartialEq)]
    struct Test {
        #[serde(serialize_with = "serialize", rename = "_url_")]
        url: Option<Url>
    }

    let url_str = "http://www.test.com/foo/bar?$param=bazz";

    let expected = format!(r#"{{"_url_":"{}"}}"#, url_str);
    let input = Test {url: Some(Url::parse(url_str).unwrap())};
    let got = serde_json::to_string(&input).unwrap();
    assert_eq!(expected, got);

    let expected = format!(r#"{{"_url_":null}}"#);
    let input = Test {url: None};
    let got = serde_json::to_string(&input).unwrap();
    assert_eq!(expected, got);
}

#[test]
fn test_host() {
    for host in &[
        Host::Domain("foo.com".to_owned()),
        Host::Ipv4("127.0.0.1".parse().unwrap()),
        Host::Ipv6("::1".parse().unwrap()),
    ] {
        let json = serde_json::to_string(&Ser(host)).unwrap();
        let de: De<Host> = serde_json::from_str(&json).unwrap();
        assert_eq!(de.into_inner(), *host)
    }
}
<|endoftext|>


<commit_before>use std::cmp::Ordering;
use std::cmp::Reverse;
use std::collections::BinaryHeap;
use std::collections::HashMap;
use std::collections::HashSet;
use std::io::BufRead;
use std::io::BufReader;
use std::io::Read;

use regex::Regex;

use common::Solution;

fn append_edge(target: &mut HashMap<char, Vec<char>>, source: char, dest: char) {
    target.entry(source).or_insert(Vec::new()).push(dest);
}

#[derive(Debug, Eq, PartialEq)]
struct Worker {
    time: usize,
    work: char,
}

impl Ord for Worker {
    fn cmp(&self, other: &Self) -> Ordering {
        other.time.cmp(&self.time)
            .then(other.work.cmp(&self.work))
    }
}

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

#[derive(Default, Debug)]
pub struct Day07 {
    forward: HashMap<char, Vec<char>>,
    backward: HashMap<char, Vec<char>>,
}

impl Day07 {
    pub fn new() -> Self {
        Default::default()
    }

    fn read_edges(&mut self, input: &mut Read) {
        let reader = BufReader::new(input);
        let regex = Regex::new(r"Step (\w) must be finished before step (\w) can begin").unwrap();

        for line in reader.lines() {
            let line = line.unwrap();
            let groups = regex.captures(&line).unwrap();
            let a = groups[1].chars().next().unwrap();
            let b = groups[2].chars().next().unwrap();

            append_edge(&mut self.forward, a, b);
            append_edge(&mut self.backward, b, a);
        }
    }

    fn part2_parametrized(&mut self, input: &mut Read, base_time: usize, max_workers: usize) -> usize {
        self.read_edges(input);
        let mut starting_points: BinaryHeap<Reverse<char>> = self.forward.keys()
            .filter(|&x| !self.backward.contains_key(x))
            .map(|&x| Reverse(x)).collect();

        let mut workers: BinaryHeap<Worker> = BinaryHeap::new();
        let mut finished = HashSet::new();
        let mut time = 0;

        while !starting_points.is_empty() || !workers.is_empty() {
            while workers.len() < max_workers && !starting_points.is_empty() {
                let Reverse(to_start) = starting_points.pop().unwrap();
                workers.push(Worker {
                    time: time + base_time + ((to_start as u8) - b'A' + 1) as usize,
                    work: to_start,
                });
            }

            time = workers.peek().unwrap().time;

            while let Some(worker) = workers.pop() {
                if worker.time == time {
                    let c = worker.work;
                    finished.insert(c);

                    if let Some(dependents) = self.forward.get(&c) {
                        for d in dependents {
                            if self.backward.get(d).unwrap().iter().all(|x| finished.contains(x)) {
                                starting_points.push(Reverse(*d));
                            }
                        }
                    }
                } else {
                    workers.push(worker);
                    break;
                }
            }
        }

        time
    }
}

impl Solution for Day07 {
    fn part1(&mut self, input: &mut Read) -> String {
        self.read_edges(input);

        let mut result = String::new();
        let mut finished = HashSet::new();

        let mut starting_points: BinaryHeap<_> = self.forward.keys().filter(|&x| !self.backward.contains_key(x))
            .map(|&x| Reverse(x)).collect();

        while let Some(Reverse(c)) = starting_points.pop() {
            result.push(c);
            finished.insert(c);

            if let Some(dependents) = self.forward.get(&c) {
                for d in dependents {
                    if self.backward.get(d).unwrap().iter().all(|x| finished.contains(x)) {
                        starting_points.push(Reverse(*d));
                    }
                }
            }
        }

        result
    }

    fn part2(&mut self, input: &mut Read) -> String {
        format!("{}", self.part2_parametrized(input, 60, 5))
    }
}

#[cfg(test)]
mod tests {
    use common::Solution;
    use day07::Day07;

    const SAMPLE_INPUT: &[u8] = include_bytes!("samples/07.txt");

    #[test]
    pub fn sample_part1() {
        let mut instance = Day07::new();
        assert_eq!("CABDFE", instance.part1(&mut SAMPLE_INPUT));
    }

    #[test]
    pub fn sample_part2() {
        let mut instance = Day07::new();
        assert_eq!(15, instance.part2_parametrized(&mut SAMPLE_INPUT, 0, 2));
    }
}
<commit_msg>Replace backwards edges with dependency count.<commit_after>use std::cmp::Ordering;
use std::cmp::Reverse;
use std::collections::BinaryHeap;
use std::collections::HashMap;
use std::collections::HashSet;
use std::io::BufRead;
use std::io::BufReader;
use std::io::Read;

use regex::Regex;

use common::Solution;

#[derive(Debug, Eq, PartialEq)]
struct Worker {
    time: usize,
    work: char,
}

impl Ord for Worker {
    fn cmp(&self, other: &Self) -> Ordering {
        other.time.cmp(&self.time)
            .then(other.work.cmp(&self.work))
    }
}

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

#[derive(Default, Debug)]
pub struct Day07 {
    forward: HashMap<char, Vec<char>>,
    dep_count: HashMap<char, usize>,
}

impl Day07 {
    pub fn new() -> Self {
        Default::default()
    }

    fn read_edges(&mut self, input: &mut Read) {
        let reader = BufReader::new(input);
        let regex = Regex::new(r"Step (\w) must be finished before step (\w) can begin").unwrap();

        for line in reader.lines() {
            let line = line.unwrap();
            let groups = regex.captures(&line).unwrap();
            let a = groups[1].chars().next().unwrap();
            let b = groups[2].chars().next().unwrap();

            self.forward.entry(a).or_insert(Vec::new()).push(b);
            *self.dep_count.entry(b).or_insert(0) += 1;
        }
    }

    fn part2_parametrized(&mut self, input: &mut Read, base_time: usize, max_workers: usize) -> usize {
        self.read_edges(input);
        let mut starting_points: BinaryHeap<Reverse<char>> = self.forward.keys()
            .filter(|&x| !self.dep_count.contains_key(x))
            .map(|&x| Reverse(x)).collect();

        let mut workers: BinaryHeap<Worker> = BinaryHeap::new();
        let mut finished = HashSet::new();
        let mut time = 0;

        while !starting_points.is_empty() || !workers.is_empty() {
            while workers.len() < max_workers && !starting_points.is_empty() {
                let Reverse(to_start) = starting_points.pop().unwrap();
                workers.push(Worker {
                    time: time + base_time + ((to_start as u8) - b'A' + 1) as usize,
                    work: to_start,
                });
            }

            time = workers.peek().unwrap().time;

            while let Some(worker) = workers.pop() {
                if worker.time == time {
                    let c = worker.work;
                    finished.insert(c);

                    if let Some(dependents) = self.forward.get(&c) {
                        for d in dependents {
                            let mut entry = self.dep_count.get_mut(d).unwrap();
                            if *entry == 1 {
                                starting_points.push(Reverse(*d));
                            } else {
                                *entry -= 1;
                            }
                        }
                    }
                } else {
                    workers.push(worker);
                    break;
                }
            }
        }

        time
    }
}

impl Solution for Day07 {
    fn part1(&mut self, input: &mut Read) -> String {
        self.read_edges(input);

        let mut result = String::new();
        let mut finished = HashSet::new();

        let mut starting_points: BinaryHeap<_> = self.forward.keys().filter(|&x| !self.dep_count.contains_key(x))
            .map(|&x| Reverse(x)).collect();

        while let Some(Reverse(c)) = starting_points.pop() {
            result.push(c);
            finished.insert(c);

            if let Some(dependents) = self.forward.get(&c) {
                for d in dependents {
                    let mut entry = self.dep_count.get_mut(d).unwrap();
                    if *entry == 1 {
                        starting_points.push(Reverse(*d));
                    } else {
                        *entry -= 1;
                    }
                }
            }
        }

        result
    }

    fn part2(&mut self, input: &mut Read) -> String {
        format!("{}", self.part2_parametrized(input, 60, 5))
    }
}

#[cfg(test)]
mod tests {
    use common::Solution;
    use day07::Day07;

    const SAMPLE_INPUT: &[u8] = include_bytes!("samples/07.txt");

    #[test]
    pub fn sample_part1() {
        let mut instance = Day07::new();
        assert_eq!("CABDFE", instance.part1(&mut SAMPLE_INPUT));
    }

    #[test]
    pub fn sample_part2() {
        let mut instance = Day07::new();
        assert_eq!(15, instance.part2_parametrized(&mut SAMPLE_INPUT, 0, 2));
    }
}
<|endoftext|>


<commit_before>extern crate crypto;

use std::fs::File;
use std::io::{BufReader, BufRead};

use crypto::aessafe::{AesSafe128Decryptor, AesSafe128Encryptor};
use crypto::symmetriccipher::{BlockDecryptor, BlockEncryptor};

fn hex_to_u8(a: u8) -> u8 {
    match a {
        b'0'...b'9' => a - b'0',
        b'a'...b'h' => a - b'a' + 10,
        _           => 0
    }
}

fn vec_u8_from_hex_string(s: &String) -> Vec<u8> {
    s.as_bytes().chunks(2).map(|a| hex_to_u8(a[0]) * 16 + hex_to_u8(a[1])).collect()
}

fn cbc_decrypt(key: &Vec<u8>, msg: &Vec<u8>) -> Vec<u8> {
    let mut v = Vec::with_capacity(msg.len());
    let (iv, msg) = msg.split_at(16);
    // TODO: find better way to copy arrays
    let mut prev = &mut [0; 16];

    for i in 0..16 {
        prev[i] = iv[i];
    }

    let mut m_i = &mut [0; 16];
    let decryptor = AesSafe128Decryptor::new(&key[..]);

    for c_i in msg.chunks(16) {
        decryptor.decrypt_block(c_i, &mut m_i[..]);

        for i in 0..m_i.len() {
            v.push(m_i[i] ^ prev[i]);
        }

        for i in 0..prev.len() {
            prev[i] = c_i[i];
        }
    }

    let pad = v.pop().unwrap();

    for _ in 1..pad {
        v.pop();
    }

    v
}

fn main() {
    let input_file = File::open("in.txt").unwrap();
    let input = BufReader::new(input_file);
    let input: Vec<_> = input.lines().filter_map(|res| res.ok())
        .filter(|s| s.len() > 0)
        .map(|s| vec_u8_from_hex_string(&s))
        .collect();
    let input: Vec<_> = input.chunks(2).collect();

    for v in input {
        println!("key: {:?}", v[0]);
        println!("cpt: {:?}", v[1]);

        let msg = cbc_decrypt(&v[0], &v[1]);
        println!("msg: {:?}", msg);

        let pt = String::from_utf8(msg).unwrap();
        println!("pt: {:?}", pt);

        println!("");
    }
}

<commit_msg>add encryption to cbc<commit_after>extern crate crypto;

use std::fs::File;
use std::io::{BufReader, BufRead};

use crypto::aessafe::{AesSafe128Decryptor, AesSafe128Encryptor};
use crypto::symmetriccipher::{BlockDecryptor, BlockEncryptor};

fn hex_to_u8(a: u8) -> u8 {
    match a {
        b'0'...b'9' => a - b'0',
        b'a'...b'h' => a - b'a' + 10,
        _           => 0
    }
}

fn u8_to_hex(a: u8) -> u8 {
    match a {
        0...9   => a + b'0',
        10...15 => a + b'a' - 10,
        _       => 0
    }
}

fn vec_u8_from_hex_string(s: &String) -> Vec<u8> {
    s.as_bytes().chunks(2).map(|a| hex_to_u8(a[0]) * 16 + hex_to_u8(a[1])).collect()
}

fn vec_u8_to_hex_string(v: &Vec<u8>) -> String {
    v.iter().map(|u| [u8_to_hex(u / 16), u8_to_hex(u % 16)])
        .fold(String::from(""), |mut acc, item| {acc.push(item[0] as char); acc.push(item[1] as char); acc})
}

fn cbc_decrypt(key: &Vec<u8>, msg: &Vec<u8>) -> Vec<u8> {
    let decryptor = AesSafe128Decryptor::new(&key[..]);
    let mut v = Vec::with_capacity(msg.len());
    let (iv, msg) = msg.split_at(16);
    // TODO: find better way to copy arrays
    let mut prev = &mut [0; 16];

    for i in 0..16 {
        prev[i] = iv[i];
    }

    let mut m_i = &mut [0; 16];

    for c_i in msg.chunks(16) {
        decryptor.decrypt_block(c_i, &mut m_i[..]);

        for i in 0..m_i.len() {
            m_i[i] ^= prev[i];
        }

        v.extend(m_i.iter().cloned());

        for i in 0..prev.len() {
            prev[i] = c_i[i];
        }
    }

    let pad = v.pop().unwrap();

    for _ in 1..pad {
        v.pop();
    }

    v
}

fn cbc_encrypt(key: &Vec<u8>, iv: &Vec<u8>, msg: &Vec<u8>) -> Vec<u8> {
    let encryptor = AesSafe128Encryptor::new(&key[..]);
    // TODO: find better way to copy arrays
    let mut prev = &mut [0; 16];

    for i in 0..16 {
        prev[i] = iv[i];
    }

    let mut v = Vec::with_capacity(msg.len());
    v.extend(iv.iter().cloned());

    let mut m_i = &mut [0; 16];
    let mut c_i = &mut [0; 16];
    let msg_padded = {
        let pad = 16 - (msg.len() % 16) as u8;
        let mut t = Vec::with_capacity(msg.len() + pad as usize);
        t.extend(msg.iter().cloned());

        for _ in 0..pad {
            t.push(pad);
        }

        t
    };

    for m in msg_padded.chunks(16) {
        for i in 0..m.len() {
            m_i[i] = m[i] ^ prev[i];
        }

        encryptor.encrypt_block(m_i, &mut c_i[..]);
        v.extend(c_i.iter().cloned());

        for i in 0..prev.len() {
            prev[i] = c_i[i];
        }
    }

    v
}

fn main() {
    // decrypt
    let input_file = File::open("in.txt").unwrap();
    let input = BufReader::new(input_file);
    let input: Vec<_> = input.lines().filter_map(|res| res.ok())
        .filter(|s| s.len() > 0)
        .map(|s| vec_u8_from_hex_string(&s))
        .collect();
    let input: Vec<_> = input.chunks(2).collect();

    for v in input {
        println!("key: {:?}", v[0]);
        println!("cpt: {:?}", v[1]);

        let msg = cbc_decrypt(&v[0], &v[1]);
        println!("msg: {:?}", msg);

        let pt = String::from_utf8(msg).unwrap();
        println!("pt: {:?}", pt);

        println!("");
    }

    // encrypt
    let input_file = File::open("in_clear.txt").unwrap();
    let input = BufReader::new(input_file);
    let input: Vec<_> = input.lines().filter_map(|res| res.ok())
        .filter(|s| s.len() > 0)
        .collect();
    let input: Vec<_> = input.chunks(3).collect();

    for v in input {
        let key = vec_u8_from_hex_string(&v[0]);
        let iv = vec_u8_from_hex_string(&v[1]);
        let pt = &v[2];

        println!("key: {:?}", key);
        println!("IV: {:?}", iv);
        println!("pt: {:?}", pt);

        let ct = cbc_encrypt(&key, &iv, &pt.as_bytes().iter().cloned().collect());
        println!("msg: {:?}", ct);

        let hex = vec_u8_to_hex_string(&ct);
        println!("ct: {:?}", hex);

        println!("");
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::mem;

use bytes::{MutByteBuf, ByteBuf, Buf, MutBuf};
use mio::{TryWrite, TryRead};

pub trait Codec {
    type Item;
    fn new() -> Self;
    fn decode(&mut self, buf: &mut ByteBuf) -> Option<Self::Item>;
    fn encode(a: Self::Item) -> ByteBuf;
}

pub struct Framed {
    msg: Option<MutByteBuf>,
    size: usize,
}

impl Codec for Framed {
    type Item = ByteBuf;

    fn new() -> Framed {
        Framed {
            msg: None,
            size: 0,
        }
    }

    fn decode(&mut self, buf: &mut ByteBuf) -> Option<Self::Item> {
        // we haven't received enough bytes for the size, don't consume any
        if self.msg.is_none() && buf.bytes().len() < 4 {
            return None;
        }

        // read the size if we need to
        if self.msg.is_none() {
            let mut sz = [0u8;4];
            assert!(buf.read_slice(&mut sz) == 4);
            let size = array_to_usize(sz);
            self.size = size;
            self.msg = Some(ByteBuf::mut_with_capacity(size));
        }

        let mut msg = self.msg.take().unwrap();

        // read actual message
        buf.try_read_buf(&mut msg);

        // if we're done, return our Item
        match msg.bytes().len() == self.size {
            true => {
                Some(msg.flip())
            },
            false => {
                self.msg = Some(msg);
                None
            },
        }
    }

    fn encode(item: Self::Item) -> ByteBuf {
        let b = item.bytes();
        let mut res = ByteBuf::mut_with_capacity(4 + b.len());
        res.write_slice(&usize_to_array(b.len()));
        res.write_slice(b);
        res.flip()
    }
}

pub fn usize_to_array(u: usize) -> [u8;4] {
    [(u >> 24) as u8, (u >> 16) as u8, (u >> 8) as u8, u as u8]
}

pub fn array_to_usize(ip: [u8;4]) -> usize {
    ((ip[0] as usize) << 24) as usize +
        ((ip[1] as usize) << 16) as usize +
        ((ip[2] as usize) << 8) as usize +
        (ip[3] as usize)
}

#[cfg(test)]
mod tests {
    extern crate quickcheck;
    extern crate rand;
    use self::rand::thread_rng;
    use self::rand::Rng;

    use codec;
    use codec::Codec;
    use bytes::{MutByteBuf, ByteBuf, Buf};

    fn array_prop(u: usize) -> bool {
        codec::array_to_usize(codec::usize_to_array(u)) == u
    }

    #[test]
    fn test_usize_to_array_to_usize() {
        quickcheck::quickcheck(array_prop as fn(usize)->bool);
        let ip = [250,1,2,3];
        assert!(codec::usize_to_array(codec::array_to_usize(ip)) == ip);
    }

    fn framed_prop(sz: usize) -> bool {
        if sz == 0 {
            // TODO(tyler) currently, feeding an empty slice to
            // ByteBuf::from_slice causes a segfault...
            return true;
        }
        let mut rng = thread_rng();
        let mut v: Vec<u8> = rng.gen_iter::<u8>().take(sz).collect();
        let mut c = codec::Framed::new();
        let mut bytes = ByteBuf::from_slice(&*v);
        let mut encoded = codec::Framed::encode(bytes);
        let decoded = c.decode(&mut encoded).unwrap();
        decoded.bytes() == &*v
    }

    #[test]
    fn test_framed_codec() {
        quickcheck::quickcheck(framed_prop as fn(usize)->bool);
    }
}
<commit_msg>fix bug with codec deframing<commit_after>use std::io;
use std::mem;

use bytes::{MutByteBuf, ByteBuf, Buf, MutBuf};
use mio::{TryWrite, TryRead};

pub trait Codec {
    type Item;
    fn new() -> Self;
    fn decode(&mut self, buf: &mut ByteBuf) -> Option<Self::Item>;
    fn encode(a: Self::Item) -> ByteBuf;
}

pub struct Framed {
    msg: Option<MutByteBuf>,
    remaining: usize,
}

impl Codec for Framed {
    type Item = ByteBuf;

    fn new() -> Framed {
        Framed {
            msg: None,
            remaining: 0,
        }
    }

    fn decode(&mut self, buf: &mut ByteBuf) -> Option<Self::Item> {
        // we haven't received enough bytes for the size, don't consume any
        if self.msg.is_none() && buf.bytes().len() < 4 {
            return None;
        }

        // read the size if we need to
        if self.msg.is_none() {
            let mut sz = [0u8;4];
            assert!(buf.read_slice(&mut sz) == 4);
            let size = array_to_usize(sz);
            self.remaining = size;
            self.msg = Some(ByteBuf::mut_with_capacity(size));
        }

        let mut msg = self.msg.take().unwrap();

        // read actual message
        match buf.try_read_buf(&mut msg) {
            Ok(Some(read)) => {
                self.remaining -= read;
                // if we're done, return our Item
                if self.remaining == 0 {
                    Some(msg.flip())
                } else {
                    self.msg = Some(msg);
                    None
                }
            },
            _ => None,
        }
    }

    fn encode(item: Self::Item) -> ByteBuf {
        let b = item.bytes();
        let mut res = ByteBuf::mut_with_capacity(4 + b.len());
        res.write_slice(&usize_to_array(b.len()));
        res.write_slice(b);
        res.flip()
    }
}

pub fn usize_to_array(u: usize) -> [u8;4] {
    [(u >> 24) as u8, (u >> 16) as u8, (u >> 8) as u8, u as u8]
}

pub fn array_to_usize(ip: [u8;4]) -> usize {
    ((ip[0] as usize) << 24) as usize +
        ((ip[1] as usize) << 16) as usize +
        ((ip[2] as usize) << 8) as usize +
        (ip[3] as usize)
}

#[cfg(test)]
mod tests {
    extern crate quickcheck;
    extern crate rand;
    use self::rand::thread_rng;
    use self::rand::Rng;

    use codec;
    use codec::Codec;
    use bytes::{MutByteBuf, ByteBuf, Buf};

    fn array_prop(u: usize) -> bool {
        codec::array_to_usize(codec::usize_to_array(u)) == u
    }

    #[test]
    fn test_usize_to_array_to_usize() {
        quickcheck::quickcheck(array_prop as fn(usize)->bool);
        let ip = [250,1,2,3];
        assert!(codec::usize_to_array(codec::array_to_usize(ip)) == ip);
    }

    fn framed_prop(sz: usize) -> bool {
        if sz == 0 {
            // TODO(tyler) currently, feeding an empty slice to
            // ByteBuf::from_slice causes a segfault...
            return true;
        }
        let mut rng = thread_rng();
        let mut v: Vec<u8> = rng.gen_iter::<u8>().take(sz).collect();
        let mut c = codec::Framed::new();
        let mut bytes = ByteBuf::from_slice(&*v);
        let mut encoded = codec::Framed::encode(bytes);
        let decoded = c.decode(&mut encoded).unwrap();
        decoded.bytes() == &*v
    }

    #[test]
    fn test_framed_codec() {
        quickcheck::quickcheck(framed_prop as fn(usize)->bool);
    }
}
<|endoftext|>