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

#![deny(missing_docs)]

extern crate serde_bytes;

use font::{FontInstanceKey, FontInstanceData, FontKey, FontTemplate};
use std::sync::Arc;
use {DevicePoint, DeviceUintPoint, DeviceUintRect, DeviceUintSize};
use {IdNamespace, TileOffset, TileSize};
use euclid::size2;

/// An opaque identifier describing an image registered with WebRender.
/// This is used as a handle to reference images, and is used as the
/// hash map key for the actual image storage in the `ResourceCache`.
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct ImageKey(pub IdNamespace, pub u32);

impl ImageKey {
    /// Placeholder Image key, used to represent None.
    pub const DUMMY: Self = ImageKey(IdNamespace(0), 0);

    /// Mints a new ImageKey. The given ID must be unique.
    pub fn new(namespace: IdNamespace, key: u32) -> Self {
        ImageKey(namespace, key)
    }
}

/// An arbitrary identifier for an external image provided by the
/// application. It must be a unique identifier for each external
/// image.
#[repr(C)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct ExternalImageId(pub u64);

/// Specifies the type of texture target in driver terms.
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub enum TextureTarget {
    /// Standard texture. This maps to GL_TEXTURE_2D in OpenGL.
    Default = 0,
    /// Array texture. This maps to GL_TEXTURE_2D_ARRAY in OpenGL. See
    /// https://www.khronos.org/opengl/wiki/Array_Texture for background
    /// on Array textures.
    Array = 1,
    /// Rectange texture. This maps to GL_TEXTURE_RECTANGLE in OpenGL. This
    /// is similar to a standard texture, with a few subtle differences
    /// (no mipmaps, non-power-of-two dimensions, different coordinate space)
    /// that make it useful for representing the kinds of textures we use
    /// in WebRender. See https://www.khronos.org/opengl/wiki/Rectangle_Texture
    /// for background on Rectangle textures.
    Rect = 2,
    /// External texture. This maps to GL_TEXTURE_EXTERNAL_OES in OpenGL, which
    /// is an extension. This is used for image formats that OpenGL doesn't
    /// understand, particularly YUV. See
    /// https://www.khronos.org/registry/OpenGL/extensions/OES/OES_EGL_image_external.txt
    External = 3,
}

/// Storage format identifier for externally-managed images.
#[repr(u32)]
#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub enum ExternalImageType {
    /// The image is texture-backed.
    TextureHandle(TextureTarget),
    /// The image is heap-allocated by the embedding.
    Buffer,
}

/// Descriptor for external image resources. See `ImageData`.
#[repr(C)]
#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub struct ExternalImageData {
    /// The identifier of this external image, provided by the embedding.
    pub id: ExternalImageId,
    /// For multi-plane images (i.e. YUV), indicates the plane of the
    /// original image that this struct represents. 0 for single-plane images.
    pub channel_index: u8,
    /// Storage format identifier.
    pub image_type: ExternalImageType,
}

/// Specifies the format of a series of pixels, in driver terms.
#[repr(u32)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum ImageFormat {
    /// One-channel, byte storage. The "red" doesn't map to the color
    /// red per se, and is just the way that OpenGL has historically referred
    /// to single-channel buffers.
    R8 = 1,
    /// One-channel, short storage
    R16 = 2,
    /// Four channels, byte storage.
    BGRA8 = 3,
    /// Four channels, float storage.
    RGBAF32 = 4,
    /// Two-channels, byte storage. Similar to `R8`, this just means
    /// "two channels" rather than "red and green".
    RG8 = 5,
    /// Four channels, signed integer storage.
    RGBAI32 = 6,
}

impl ImageFormat {
    /// Returns the number of bytes per pixel for the given format.
    pub fn bytes_per_pixel(self) -> u32 {
        match self {
            ImageFormat::R8 => 1,
            ImageFormat::R16 => 2,
            ImageFormat::BGRA8 => 4,
            ImageFormat::RGBAF32 => 16,
            ImageFormat::RG8 => 2,
            ImageFormat::RGBAI32 => 16,
        }
    }
}

/// Specifies the color depth of an image. Currently only used for YUV images.
#[repr(u8)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum ColorDepth {
    /// 8 bits image (most common)
    Color8,
    /// 10 bits image
    Color10,
    /// 12 bits image
    Color12,
}

impl ColorDepth {
    /// Return the numerical bit depth value for the type.
    pub fn bit_depth(self) -> u32 {
        match self {
            ColorDepth::Color8 => 8,
            ColorDepth::Color10 => 10,
            ColorDepth::Color12 => 12,
        }
    }
    /// 10 and 12 bits images are encoded using 16 bits integer, we need to
    /// rescale the 10 or 12 bits value to extend to 16 bits.
    pub fn rescaling_factor(self) -> f32 {
        match self {
            ColorDepth::Color8 => 1.0,
            ColorDepth::Color10 => 64.0,
            ColorDepth::Color12 => 16.0,
        }
    }
}

/// Metadata (but not storage) describing an image In WebRender.
#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct ImageDescriptor {
    /// Format of the image data.
    pub format: ImageFormat,
    /// Width and length of the image data, in pixels.
    pub size: DeviceUintSize,
    /// The number of bytes from the start of one row to the next. If non-None,
    /// `compute_stride` will return this value, otherwise it returns
    /// `width * bpp`. Different source of images have different alignment
    /// constraints for rows, so the stride isn't always equal to width * bpp.
    pub stride: Option<u32>,
    /// Offset in bytes of the first pixel of this image in its backing buffer.
    /// This is used for tiling, wherein WebRender extracts chunks of input images
    /// in order to cache, manipulate, and render them individually. This offset
    /// tells the texture upload machinery where to find the bytes to upload for
    /// this tile. Non-tiled images generally set this to zero.
    pub offset: u32,
    /// Whether this image is opaque, or has an alpha channel. Avoiding blending
    /// for opaque surfaces is an important optimization.
    pub is_opaque: bool,
    /// Whether to allow the driver to automatically generate mipmaps. If images
    /// are already downscaled appropriately, mipmap generation can be wasted
    /// work, and cause performance problems on some cards/drivers.
    ///
    /// See https://github.com/servo/webrender/pull/2555/
    pub allow_mipmaps: bool,
}

impl ImageDescriptor {
    /// Mints a new ImageDescriptor.
    pub fn new(
        width: u32,
        height: u32,
        format: ImageFormat,
        is_opaque: bool,
        allow_mipmaps: bool,
    ) -> Self {
        ImageDescriptor {
            size: size2(width, height),
            format,
            stride: None,
            offset: 0,
            is_opaque,
            allow_mipmaps,
        }
    }

    /// Returns the stride, either via an explicit stride stashed on the object
    /// or by the default computation.
    pub fn compute_stride(&self) -> u32 {
        self.stride.unwrap_or(self.size.width * self.format.bytes_per_pixel())
    }

    /// Computes the total size of the image, in bytes.
    pub fn compute_total_size(&self) -> u32 {
        self.compute_stride() * self.size.height
    }

    /// Computes the bounding rectangle for the image, rooted at (0, 0).
    pub fn full_rect(&self) -> DeviceUintRect {
        DeviceUintRect::new(
            DeviceUintPoint::zero(),
            self.size,
        )
    }
}

/// Represents the backing store of an arbitrary series of pixels for display by
/// WebRender. This storage can take several forms.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ImageData {
    /// A simple series of bytes, provided by the embedding and owned by WebRender.
    /// The format is stored out-of-band, currently in ImageDescriptor.
    Raw(#[serde(with = "serde_image_data_raw")] Arc<Vec<u8>>),
    /// An series of commands that can be rasterized into an image via an
    /// embedding-provided callback.
    Blob(#[serde(with = "serde_image_data_raw")] Arc<BlobImageData>),
    /// An image owned by the embedding, and referenced by WebRender. This may
    /// take the form of a texture or a heap-allocated buffer.
    External(ExternalImageData),
}

mod serde_image_data_raw {
    extern crate serde_bytes;

    use std::sync::Arc;
    use serde::{Deserializer, Serializer};

    pub fn serialize<S: Serializer>(bytes: &Arc<Vec<u8>>, serializer: S) -> Result<S::Ok, S::Error> {
        serde_bytes::serialize(bytes.as_slice(), serializer)
    }

    pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Arc<Vec<u8>>, D::Error> {
        serde_bytes::deserialize(deserializer).map(Arc::new)
    }
}

impl ImageData {
    /// Mints a new raw ImageData, taking ownership of the bytes.
    pub fn new(bytes: Vec<u8>) -> Self {
        ImageData::Raw(Arc::new(bytes))
    }

    /// Mints a new raw ImageData from Arc-ed bytes.
    pub fn new_shared(bytes: Arc<Vec<u8>>) -> Self {
        ImageData::Raw(bytes)
    }

    /// Mints a new Blob ImageData.
    pub fn new_blob_image(commands: BlobImageData) -> Self {
        ImageData::Blob(Arc::new(commands))
    }

    /// Returns true if this ImageData represents a blob.
    #[inline]
    pub fn is_blob(&self) -> bool {
        match *self {
            ImageData::Blob(_) => true,
            _ => false,
        }
    }

    /// Returns true if this variant of ImageData should go through the texture
    /// cache.
    #[inline]
    pub fn uses_texture_cache(&self) -> bool {
        match *self {
            ImageData::External(ref ext_data) => match ext_data.image_type {
                ExternalImageType::TextureHandle(_) => false,
                ExternalImageType::Buffer => true,
            },
            ImageData::Blob(_) => true,
            ImageData::Raw(_) => true,
        }
    }
}

/// The resources exposed by the resource cache available for use by the blob rasterizer.
pub trait BlobImageResources {
    /// Returns the `FontTemplate` for the given key.
    fn get_font_data(&self, key: FontKey) -> &FontTemplate;
    /// Returns the `FontInstanceData` for the given key, if found.
    fn get_font_instance_data(&self, key: FontInstanceKey) -> Option<FontInstanceData>;
    /// Returns the image metadata and backing store for the given key, if found.
    fn get_image(&self, key: ImageKey) -> Option<(&ImageData, &ImageDescriptor)>;
}

/// A handler on the render backend that can create rasterizer objects which will
/// be sent to the scene builder thread to execute the rasterization.
///
/// The handler is responsible for collecting resources, managing/updating blob commands
/// and creating the rasterizer objects, but isn't expected to do any rasterization itself.
pub trait BlobImageHandler: Send {
    /// Creates a snapshot of the current state of blob images in the handler.
    fn create_blob_rasterizer(&mut self) -> Box<AsyncBlobImageRasterizer>;

    /// A hook to let the blob image handler update any state related to resources that
    /// are not bundled in the blob recording itself.
    fn prepare_resources(
        &mut self,
        services: &BlobImageResources,
        requests: &[BlobImageParams],
    );

    /// Register a blob image.
    fn add(&mut self, key: ImageKey, data: Arc<BlobImageData>, tiling: Option<TileSize>);

    /// Update an already registered blob image.
    fn update(&mut self, key: ImageKey, data: Arc<BlobImageData>, dirty_rect: Option<DeviceUintRect>);

    /// Delete an already registered blob image.
    fn delete(&mut self, key: ImageKey);

    /// A hook to let the handler clean up any state related to a font which the resource
    /// cache is about to delete.
    fn delete_font(&mut self, key: FontKey);

    /// A hook to let the handler clean up any state related to a font instance which the
    /// resource cache is about to delete.
    fn delete_font_instance(&mut self, key: FontInstanceKey);

    /// A hook to let the handler clean up any state related a given namespace before the
    /// resource cache deletes them.
    fn clear_namespace(&mut self, namespace: IdNamespace);
}

/// A group of rasterization requests to execute synchronously on the scene builder thread.
pub trait AsyncBlobImageRasterizer : Send {
    /// Rasterize the requests.
    fn rasterize(&mut self, requests: &[BlobImageParams]) -> Vec<(BlobImageRequest, BlobImageResult)>;
}

/// Input parameters for the BlobImageRasterizer.
#[derive(Copy, Clone, Debug)]
pub struct BlobImageParams {
    /// A key that identifies the blob image rasterization request.
    pub request: BlobImageRequest,
    /// Description of the format of the blob's output image.
    pub descriptor: BlobImageDescriptor,
    /// An optional sub-rectangle of the image to avoid re-rasterizing
    /// the entire image when only a portion is updated.
    ///
    /// If set to None the entire image is rasterized.
    pub dirty_rect: Option<DeviceUintRect>,
}

/// Backing store for blob image command streams.
pub type BlobImageData = Vec<u8>;

/// Result type for blob raserization.
pub type BlobImageResult = Result<RasterizedBlobImage, BlobImageError>;

/// Metadata (but not storage) for a blob image.
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct BlobImageDescriptor {
    /// Size in device pixels of the blob's output image.
    pub size: DeviceUintSize,
    /// When tiling, offset point in device pixels of this tile in the full
    /// image. Generally (0, 0) outside of tiling.
    pub offset: DevicePoint,
    /// Format for the data in the backing store.
    pub format: ImageFormat,
}

/// Representation of a rasterized blob image. This is obtained by passing
/// `BlobImageData` to the embedding via the rasterization callback.
pub struct RasterizedBlobImage {
    /// The bounding rectangle for this blob image.
    pub rasterized_rect: DeviceUintRect,
    /// Backing store. The format is stored out of band in `BlobImageDescriptor`.
    pub data: Arc<Vec<u8>>,
}

/// Error code for when blob rasterization failed.
#[derive(Clone, Debug)]
pub enum BlobImageError {
    /// Out of memory.
    Oom,
    /// Other failure, embedding-specified.
    Other(String),
}

/// A key identifying blob image rasterization work requested from the blob
/// image rasterizer.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct BlobImageRequest {
    /// Unique handle to the image.
    pub key: ImageKey,
    /// Tiling offset in number of tiles, if applicable.
    ///
    /// `None` if the image will not be tiled.
    pub tile: Option<TileOffset>,
}
<commit_msg>Add 16 bits YUV support<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![deny(missing_docs)]

extern crate serde_bytes;

use font::{FontInstanceKey, FontInstanceData, FontKey, FontTemplate};
use std::sync::Arc;
use {DevicePoint, DeviceUintPoint, DeviceUintRect, DeviceUintSize};
use {IdNamespace, TileOffset, TileSize};
use euclid::size2;

/// An opaque identifier describing an image registered with WebRender.
/// This is used as a handle to reference images, and is used as the
/// hash map key for the actual image storage in the `ResourceCache`.
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct ImageKey(pub IdNamespace, pub u32);

impl ImageKey {
    /// Placeholder Image key, used to represent None.
    pub const DUMMY: Self = ImageKey(IdNamespace(0), 0);

    /// Mints a new ImageKey. The given ID must be unique.
    pub fn new(namespace: IdNamespace, key: u32) -> Self {
        ImageKey(namespace, key)
    }
}

/// An arbitrary identifier for an external image provided by the
/// application. It must be a unique identifier for each external
/// image.
#[repr(C)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct ExternalImageId(pub u64);

/// Specifies the type of texture target in driver terms.
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub enum TextureTarget {
    /// Standard texture. This maps to GL_TEXTURE_2D in OpenGL.
    Default = 0,
    /// Array texture. This maps to GL_TEXTURE_2D_ARRAY in OpenGL. See
    /// https://www.khronos.org/opengl/wiki/Array_Texture for background
    /// on Array textures.
    Array = 1,
    /// Rectange texture. This maps to GL_TEXTURE_RECTANGLE in OpenGL. This
    /// is similar to a standard texture, with a few subtle differences
    /// (no mipmaps, non-power-of-two dimensions, different coordinate space)
    /// that make it useful for representing the kinds of textures we use
    /// in WebRender. See https://www.khronos.org/opengl/wiki/Rectangle_Texture
    /// for background on Rectangle textures.
    Rect = 2,
    /// External texture. This maps to GL_TEXTURE_EXTERNAL_OES in OpenGL, which
    /// is an extension. This is used for image formats that OpenGL doesn't
    /// understand, particularly YUV. See
    /// https://www.khronos.org/registry/OpenGL/extensions/OES/OES_EGL_image_external.txt
    External = 3,
}

/// Storage format identifier for externally-managed images.
#[repr(u32)]
#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub enum ExternalImageType {
    /// The image is texture-backed.
    TextureHandle(TextureTarget),
    /// The image is heap-allocated by the embedding.
    Buffer,
}

/// Descriptor for external image resources. See `ImageData`.
#[repr(C)]
#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub struct ExternalImageData {
    /// The identifier of this external image, provided by the embedding.
    pub id: ExternalImageId,
    /// For multi-plane images (i.e. YUV), indicates the plane of the
    /// original image that this struct represents. 0 for single-plane images.
    pub channel_index: u8,
    /// Storage format identifier.
    pub image_type: ExternalImageType,
}

/// Specifies the format of a series of pixels, in driver terms.
#[repr(u32)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum ImageFormat {
    /// One-channel, byte storage. The "red" doesn't map to the color
    /// red per se, and is just the way that OpenGL has historically referred
    /// to single-channel buffers.
    R8 = 1,
    /// One-channel, short storage
    R16 = 2,
    /// Four channels, byte storage.
    BGRA8 = 3,
    /// Four channels, float storage.
    RGBAF32 = 4,
    /// Two-channels, byte storage. Similar to `R8`, this just means
    /// "two channels" rather than "red and green".
    RG8 = 5,
    /// Four channels, signed integer storage.
    RGBAI32 = 6,
}

impl ImageFormat {
    /// Returns the number of bytes per pixel for the given format.
    pub fn bytes_per_pixel(self) -> u32 {
        match self {
            ImageFormat::R8 => 1,
            ImageFormat::R16 => 2,
            ImageFormat::BGRA8 => 4,
            ImageFormat::RGBAF32 => 16,
            ImageFormat::RG8 => 2,
            ImageFormat::RGBAI32 => 16,
        }
    }
}

/// Specifies the color depth of an image. Currently only used for YUV images.
#[repr(u8)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum ColorDepth {
    /// 8 bits image (most common)
    Color8,
    /// 10 bits image
    Color10,
    /// 12 bits image
    Color12,
    /// 16 bits image
    Color16,
}

impl ColorDepth {
    /// Return the numerical bit depth value for the type.
    pub fn bit_depth(self) -> u32 {
        match self {
            ColorDepth::Color8 => 8,
            ColorDepth::Color10 => 10,
            ColorDepth::Color12 => 12,
            ColorDepth::Color16 => 16,
        }
    }
    /// 10 and 12 bits images are encoded using 16 bits integer, we need to
    /// rescale the 10 or 12 bits value to extend to 16 bits.
    pub fn rescaling_factor(self) -> f32 {
        match self {
            ColorDepth::Color8 => 1.0,
            ColorDepth::Color10 => 64.0,
            ColorDepth::Color12 => 16.0,
            ColorDepth::Color16 => 1.0,
        }
    }
}

/// Metadata (but not storage) describing an image In WebRender.
#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct ImageDescriptor {
    /// Format of the image data.
    pub format: ImageFormat,
    /// Width and length of the image data, in pixels.
    pub size: DeviceUintSize,
    /// The number of bytes from the start of one row to the next. If non-None,
    /// `compute_stride` will return this value, otherwise it returns
    /// `width * bpp`. Different source of images have different alignment
    /// constraints for rows, so the stride isn't always equal to width * bpp.
    pub stride: Option<u32>,
    /// Offset in bytes of the first pixel of this image in its backing buffer.
    /// This is used for tiling, wherein WebRender extracts chunks of input images
    /// in order to cache, manipulate, and render them individually. This offset
    /// tells the texture upload machinery where to find the bytes to upload for
    /// this tile. Non-tiled images generally set this to zero.
    pub offset: u32,
    /// Whether this image is opaque, or has an alpha channel. Avoiding blending
    /// for opaque surfaces is an important optimization.
    pub is_opaque: bool,
    /// Whether to allow the driver to automatically generate mipmaps. If images
    /// are already downscaled appropriately, mipmap generation can be wasted
    /// work, and cause performance problems on some cards/drivers.
    ///
    /// See https://github.com/servo/webrender/pull/2555/
    pub allow_mipmaps: bool,
}

impl ImageDescriptor {
    /// Mints a new ImageDescriptor.
    pub fn new(
        width: u32,
        height: u32,
        format: ImageFormat,
        is_opaque: bool,
        allow_mipmaps: bool,
    ) -> Self {
        ImageDescriptor {
            size: size2(width, height),
            format,
            stride: None,
            offset: 0,
            is_opaque,
            allow_mipmaps,
        }
    }

    /// Returns the stride, either via an explicit stride stashed on the object
    /// or by the default computation.
    pub fn compute_stride(&self) -> u32 {
        self.stride.unwrap_or(self.size.width * self.format.bytes_per_pixel())
    }

    /// Computes the total size of the image, in bytes.
    pub fn compute_total_size(&self) -> u32 {
        self.compute_stride() * self.size.height
    }

    /// Computes the bounding rectangle for the image, rooted at (0, 0).
    pub fn full_rect(&self) -> DeviceUintRect {
        DeviceUintRect::new(
            DeviceUintPoint::zero(),
            self.size,
        )
    }
}

/// Represents the backing store of an arbitrary series of pixels for display by
/// WebRender. This storage can take several forms.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ImageData {
    /// A simple series of bytes, provided by the embedding and owned by WebRender.
    /// The format is stored out-of-band, currently in ImageDescriptor.
    Raw(#[serde(with = "serde_image_data_raw")] Arc<Vec<u8>>),
    /// An series of commands that can be rasterized into an image via an
    /// embedding-provided callback.
    Blob(#[serde(with = "serde_image_data_raw")] Arc<BlobImageData>),
    /// An image owned by the embedding, and referenced by WebRender. This may
    /// take the form of a texture or a heap-allocated buffer.
    External(ExternalImageData),
}

mod serde_image_data_raw {
    extern crate serde_bytes;

    use std::sync::Arc;
    use serde::{Deserializer, Serializer};

    pub fn serialize<S: Serializer>(bytes: &Arc<Vec<u8>>, serializer: S) -> Result<S::Ok, S::Error> {
        serde_bytes::serialize(bytes.as_slice(), serializer)
    }

    pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Arc<Vec<u8>>, D::Error> {
        serde_bytes::deserialize(deserializer).map(Arc::new)
    }
}

impl ImageData {
    /// Mints a new raw ImageData, taking ownership of the bytes.
    pub fn new(bytes: Vec<u8>) -> Self {
        ImageData::Raw(Arc::new(bytes))
    }

    /// Mints a new raw ImageData from Arc-ed bytes.
    pub fn new_shared(bytes: Arc<Vec<u8>>) -> Self {
        ImageData::Raw(bytes)
    }

    /// Mints a new Blob ImageData.
    pub fn new_blob_image(commands: BlobImageData) -> Self {
        ImageData::Blob(Arc::new(commands))
    }

    /// Returns true if this ImageData represents a blob.
    #[inline]
    pub fn is_blob(&self) -> bool {
        match *self {
            ImageData::Blob(_) => true,
            _ => false,
        }
    }

    /// Returns true if this variant of ImageData should go through the texture
    /// cache.
    #[inline]
    pub fn uses_texture_cache(&self) -> bool {
        match *self {
            ImageData::External(ref ext_data) => match ext_data.image_type {
                ExternalImageType::TextureHandle(_) => false,
                ExternalImageType::Buffer => true,
            },
            ImageData::Blob(_) => true,
            ImageData::Raw(_) => true,
        }
    }
}

/// The resources exposed by the resource cache available for use by the blob rasterizer.
pub trait BlobImageResources {
    /// Returns the `FontTemplate` for the given key.
    fn get_font_data(&self, key: FontKey) -> &FontTemplate;
    /// Returns the `FontInstanceData` for the given key, if found.
    fn get_font_instance_data(&self, key: FontInstanceKey) -> Option<FontInstanceData>;
    /// Returns the image metadata and backing store for the given key, if found.
    fn get_image(&self, key: ImageKey) -> Option<(&ImageData, &ImageDescriptor)>;
}

/// A handler on the render backend that can create rasterizer objects which will
/// be sent to the scene builder thread to execute the rasterization.
///
/// The handler is responsible for collecting resources, managing/updating blob commands
/// and creating the rasterizer objects, but isn't expected to do any rasterization itself.
pub trait BlobImageHandler: Send {
    /// Creates a snapshot of the current state of blob images in the handler.
    fn create_blob_rasterizer(&mut self) -> Box<AsyncBlobImageRasterizer>;

    /// A hook to let the blob image handler update any state related to resources that
    /// are not bundled in the blob recording itself.
    fn prepare_resources(
        &mut self,
        services: &BlobImageResources,
        requests: &[BlobImageParams],
    );

    /// Register a blob image.
    fn add(&mut self, key: ImageKey, data: Arc<BlobImageData>, tiling: Option<TileSize>);

    /// Update an already registered blob image.
    fn update(&mut self, key: ImageKey, data: Arc<BlobImageData>, dirty_rect: Option<DeviceUintRect>);

    /// Delete an already registered blob image.
    fn delete(&mut self, key: ImageKey);

    /// A hook to let the handler clean up any state related to a font which the resource
    /// cache is about to delete.
    fn delete_font(&mut self, key: FontKey);

    /// A hook to let the handler clean up any state related to a font instance which the
    /// resource cache is about to delete.
    fn delete_font_instance(&mut self, key: FontInstanceKey);

    /// A hook to let the handler clean up any state related a given namespace before the
    /// resource cache deletes them.
    fn clear_namespace(&mut self, namespace: IdNamespace);
}

/// A group of rasterization requests to execute synchronously on the scene builder thread.
pub trait AsyncBlobImageRasterizer : Send {
    /// Rasterize the requests.
    fn rasterize(&mut self, requests: &[BlobImageParams]) -> Vec<(BlobImageRequest, BlobImageResult)>;
}

/// Input parameters for the BlobImageRasterizer.
#[derive(Copy, Clone, Debug)]
pub struct BlobImageParams {
    /// A key that identifies the blob image rasterization request.
    pub request: BlobImageRequest,
    /// Description of the format of the blob's output image.
    pub descriptor: BlobImageDescriptor,
    /// An optional sub-rectangle of the image to avoid re-rasterizing
    /// the entire image when only a portion is updated.
    ///
    /// If set to None the entire image is rasterized.
    pub dirty_rect: Option<DeviceUintRect>,
}

/// Backing store for blob image command streams.
pub type BlobImageData = Vec<u8>;

/// Result type for blob raserization.
pub type BlobImageResult = Result<RasterizedBlobImage, BlobImageError>;

/// Metadata (but not storage) for a blob image.
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct BlobImageDescriptor {
    /// Size in device pixels of the blob's output image.
    pub size: DeviceUintSize,
    /// When tiling, offset point in device pixels of this tile in the full
    /// image. Generally (0, 0) outside of tiling.
    pub offset: DevicePoint,
    /// Format for the data in the backing store.
    pub format: ImageFormat,
}

/// Representation of a rasterized blob image. This is obtained by passing
/// `BlobImageData` to the embedding via the rasterization callback.
pub struct RasterizedBlobImage {
    /// The bounding rectangle for this blob image.
    pub rasterized_rect: DeviceUintRect,
    /// Backing store. The format is stored out of band in `BlobImageDescriptor`.
    pub data: Arc<Vec<u8>>,
}

/// Error code for when blob rasterization failed.
#[derive(Clone, Debug)]
pub enum BlobImageError {
    /// Out of memory.
    Oom,
    /// Other failure, embedding-specified.
    Other(String),
}

/// A key identifying blob image rasterization work requested from the blob
/// image rasterizer.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct BlobImageRequest {
    /// Unique handle to the image.
    pub key: ImageKey,
    /// Tiling offset in number of tiles, if applicable.
    ///
    /// `None` if the image will not be tiled.
    pub tile: Option<TileOffset>,
}
<|endoftext|>


<commit_before>// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::U64Le;
use bytemuck::{Pod, Zeroable};
use core::fmt::{self, Display, Formatter};
use core::num::{NonZeroU32, TryFromIntError};
use core::ops::RangeInclusive;

/// Logical block address.
#[derive(
    Clone,
    Copy,
    Debug,
    Default,
    Eq,
    PartialEq,
    Hash,
    Ord,
    PartialOrd,
    Pod,
    Zeroable,
)]
#[repr(transparent)]
pub struct Lba(pub u64);

impl Lba {
    /// Convert to a plain [`u64`].
    #[must_use]
    pub fn to_u64(self) -> u64 {
        self.0
    }
}

impl PartialEq<u64> for Lba {
    fn eq(&self, other: &u64) -> bool {
        self.0 == *other
    }
}

impl Display for Lba {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl TryFrom<Lba> for usize {
    type Error = TryFromIntError;

    fn try_from(lba: Lba) -> Result<Self, Self::Error> {
        lba.0.try_into()
    }
}

impl From<LbaLe> for Lba {
    fn from(lba: LbaLe) -> Self {
        Self(lba.to_u64())
    }
}

/// Logical block address stored as a [`U64Le`].
#[derive(
    Clone,
    Copy,
    Debug,
    Default,
    Eq,
    PartialEq,
    Hash,
    Ord,
    PartialOrd,
    Pod,
    Zeroable,
)]
#[repr(transparent)]
pub struct LbaLe(pub U64Le);

impl LbaLe {
    /// Create a logical block address from a [`u64`].
    #[must_use]
    pub const fn from_u64(v: u64) -> Self {
        Self(U64Le::from_u64(v))
    }

    /// Get the logical block address as a [`u64`].
    #[must_use]
    pub const fn to_u64(self) -> u64 {
        self.0.to_u64()
    }
}

impl Display for LbaLe {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        self.to_u64().fmt(f)
    }
}

impl From<Lba> for LbaLe {
    fn from(lba: Lba) -> Self {
        Self::from_u64(lba.0)
    }
}

/// Inclusive range of logical block addresses.
#[derive(
    Clone,
    Copy,
    Debug,
    Default,
    Eq,
    PartialEq,
    Hash,
    Ord,
    PartialOrd,
    Pod,
    Zeroable,
)]
#[repr(C)]
pub struct LbaRangeInclusive {
    start: Lba,
    end: Lba,
}

impl LbaRangeInclusive {
    /// Create an LBA range. The end address must be greater than or
    /// equal to the start address.
    #[must_use]
    pub const fn new(start: Lba, end: Lba) -> Option<LbaRangeInclusive> {
        if end.0 >= start.0 {
            Some(LbaRangeInclusive { start, end })
        } else {
            None
        }
    }

    /// Starting LBA (inclusive).
    #[must_use]
    pub const fn start(self) -> Lba {
        self.start
    }

    /// Ending LBA (inclusive).
    #[must_use]
    pub const fn end(self) -> Lba {
        self.end
    }

    /// Create an LBA range from the corresponding byte range for the
    /// given block size.
    ///
    /// The byte range must correspond precisely to block bounds, with
    /// the start byte at the beginning of a block and the end byte at
    /// the end of a block
    ///
    /// # Examples
    ///
    /// ```
    /// use gpt_disk_types::{BlockSize, LbaRangeInclusive};
    ///
    /// # fn t() -> Option<()> {
    /// let block_size = BlockSize::new(4)?;
    /// let r = LbaRangeInclusive::from_byte_range(4..=11, block_size)?;
    /// assert_eq!(r.start().0, 1);
    /// assert_eq!(r.end().0, 2);
    /// # None
    /// # }
    /// #
    /// # fn main() { t(); }
    #[must_use]
    pub fn from_byte_range(
        byte_range: RangeInclusive<u64>,
        block_size: BlockSize,
    ) -> Option<Self> {
        let start_byte = byte_range.start();
        let end_byte_plus_1 = byte_range.end().checked_add(1)?;
        let block_size = block_size.to_u64();

        if (start_byte % block_size) != 0 {
            return None;
        }
        if (end_byte_plus_1 % block_size) != 0 {
            return None;
        }

        let end_lba = (end_byte_plus_1 / block_size).checked_sub(1)?;

        LbaRangeInclusive::new(Lba(start_byte / block_size), Lba(end_lba))
    }

    /// Convert the LBA range to the corresponding byte range for the
    /// given block size.
    ///
    /// # Examples
    ///
    /// ```
    /// use gpt_disk_types::{BlockSize, Lba, LbaRangeInclusive};
    ///
    /// # fn t() -> Option<()> {
    /// let r = LbaRangeInclusive::new(Lba(1), Lba(2))?;
    /// let block_size = BlockSize::new(4)?;
    /// assert_eq!(r.to_byte_range(block_size)?, 4..=11);
    /// # None
    /// # }
    /// #
    /// # fn main() { t(); }
    /// ```
    #[must_use]
    pub fn to_byte_range(
        self,
        block_size: BlockSize,
    ) -> Option<RangeInclusive<u64>> {
        let block_size = block_size.to_u64();
        let start_byte = self.start.0.checked_mul(block_size)?;
        let end_byte = self
            .end
            .0
            .checked_mul(block_size)?
            .checked_add(block_size - 1)?;
        Some(start_byte..=end_byte)
    }
}

impl Display for LbaRangeInclusive {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        write!(f, "{}..={}", self.start, self.end)
    }
}

/// Size of a block in bytes.
///
/// This type enforces some restrictions on the block size: it must be
/// at least 512 bytes and fit within a [`u32`].
///
/// # Minimum size
///
/// The [`MasterBootRecord`] size is 512 bytes and must fit within a
/// block, so the block size must be at least that large.
///
/// [`MasterBootRecord`]: crate::MasterBootRecord
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
#[repr(transparent)]
pub struct BlockSize(NonZeroU32);

impl BlockSize {
    /// 512-byte block size.
    pub const BS_512: Self = Self(if let Some(nz) = NonZeroU32::new(512) {
        nz
    } else {
        unreachable!()
    });

    /// 4096-byte block size.
    pub const BS_4096: Self = Self(if let Some(nz) = NonZeroU32::new(4096) {
        nz
    } else {
        unreachable!()
    });

    /// Create a `BlockSize`.
    #[must_use]
    pub const fn new(num_bytes: u32) -> Option<Self> {
        if let Some(nz) = NonZeroU32::new(num_bytes) {
            if num_bytes >= 512 {
                Some(Self(nz))
            } else {
                None
            }
        } else {
            None
        }
    }

    /// Create a `BlockSize`.
    #[must_use]
    pub fn from_usize(num_bytes: usize) -> Option<Self> {
        Self::new(u32::try_from(num_bytes).ok()?)
    }

    /// Get the size in bytes as a [`u32`].
    #[must_use]
    pub const fn to_u32(self) -> u32 {
        self.0.get()
    }

    /// Get the size in bytes as a [`u64`].
    #[allow(clippy::as_conversions)]
    #[must_use]
    pub const fn to_u64(self) -> u64 {
        self.0.get() as u64
    }

    /// Get the size in bytes as a [`usize`].
    #[must_use]
    pub fn to_usize(self) -> Option<usize> {
        self.0.get().try_into().ok()
    }
}

impl Default for BlockSize {
    fn default() -> Self {
        BlockSize::BS_512
    }
}

impl Display for BlockSize {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}
<commit_msg>Fix LbaRangeInclusive docstring tests<commit_after>// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::U64Le;
use bytemuck::{Pod, Zeroable};
use core::fmt::{self, Display, Formatter};
use core::num::{NonZeroU32, TryFromIntError};
use core::ops::RangeInclusive;

/// Logical block address.
#[derive(
    Clone,
    Copy,
    Debug,
    Default,
    Eq,
    PartialEq,
    Hash,
    Ord,
    PartialOrd,
    Pod,
    Zeroable,
)]
#[repr(transparent)]
pub struct Lba(pub u64);

impl Lba {
    /// Convert to a plain [`u64`].
    #[must_use]
    pub fn to_u64(self) -> u64 {
        self.0
    }
}

impl PartialEq<u64> for Lba {
    fn eq(&self, other: &u64) -> bool {
        self.0 == *other
    }
}

impl Display for Lba {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl TryFrom<Lba> for usize {
    type Error = TryFromIntError;

    fn try_from(lba: Lba) -> Result<Self, Self::Error> {
        lba.0.try_into()
    }
}

impl From<LbaLe> for Lba {
    fn from(lba: LbaLe) -> Self {
        Self(lba.to_u64())
    }
}

/// Logical block address stored as a [`U64Le`].
#[derive(
    Clone,
    Copy,
    Debug,
    Default,
    Eq,
    PartialEq,
    Hash,
    Ord,
    PartialOrd,
    Pod,
    Zeroable,
)]
#[repr(transparent)]
pub struct LbaLe(pub U64Le);

impl LbaLe {
    /// Create a logical block address from a [`u64`].
    #[must_use]
    pub const fn from_u64(v: u64) -> Self {
        Self(U64Le::from_u64(v))
    }

    /// Get the logical block address as a [`u64`].
    #[must_use]
    pub const fn to_u64(self) -> u64 {
        self.0.to_u64()
    }
}

impl Display for LbaLe {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        self.to_u64().fmt(f)
    }
}

impl From<Lba> for LbaLe {
    fn from(lba: Lba) -> Self {
        Self::from_u64(lba.0)
    }
}

/// Inclusive range of logical block addresses.
#[derive(
    Clone,
    Copy,
    Debug,
    Default,
    Eq,
    PartialEq,
    Hash,
    Ord,
    PartialOrd,
    Pod,
    Zeroable,
)]
#[repr(C)]
pub struct LbaRangeInclusive {
    start: Lba,
    end: Lba,
}

impl LbaRangeInclusive {
    /// Create an LBA range. The end address must be greater than or
    /// equal to the start address.
    #[must_use]
    pub const fn new(start: Lba, end: Lba) -> Option<LbaRangeInclusive> {
        if end.0 >= start.0 {
            Some(LbaRangeInclusive { start, end })
        } else {
            None
        }
    }

    /// Starting LBA (inclusive).
    #[must_use]
    pub const fn start(self) -> Lba {
        self.start
    }

    /// Ending LBA (inclusive).
    #[must_use]
    pub const fn end(self) -> Lba {
        self.end
    }

    /// Create an LBA range from the corresponding byte range for the
    /// given block size.
    ///
    /// The byte range must correspond precisely to block bounds, with
    /// the start byte at the beginning of a block and the end byte at
    /// the end of a block
    ///
    /// # Examples
    ///
    /// ```
    /// use gpt_disk_types::{BlockSize, LbaRangeInclusive};
    ///
    /// let bs = BlockSize::BS_512;
    /// let r = LbaRangeInclusive::from_byte_range(512..=1535, bs).unwrap();
    /// assert_eq!(r.start().0, 1);
    /// assert_eq!(r.end().0, 2);
    #[must_use]
    pub fn from_byte_range(
        byte_range: RangeInclusive<u64>,
        block_size: BlockSize,
    ) -> Option<Self> {
        let start_byte = byte_range.start();
        let end_byte_plus_1 = byte_range.end().checked_add(1)?;
        let block_size = block_size.to_u64();

        if (start_byte % block_size) != 0 {
            return None;
        }
        if (end_byte_plus_1 % block_size) != 0 {
            return None;
        }

        let end_lba = (end_byte_plus_1 / block_size).checked_sub(1)?;

        LbaRangeInclusive::new(Lba(start_byte / block_size), Lba(end_lba))
    }

    /// Convert the LBA range to the corresponding byte range for the
    /// given block size.
    ///
    /// # Examples
    ///
    /// ```
    /// use gpt_disk_types::{BlockSize, Lba, LbaRangeInclusive};
    ///
    /// let r = LbaRangeInclusive::new(Lba(1), Lba(2)).unwrap();
    /// let bs = BlockSize::BS_512;
    /// assert_eq!(r.to_byte_range(bs).unwrap(), 512..=1535);
    /// ```
    #[must_use]
    pub fn to_byte_range(
        self,
        block_size: BlockSize,
    ) -> Option<RangeInclusive<u64>> {
        let block_size = block_size.to_u64();
        let start_byte = self.start.0.checked_mul(block_size)?;
        let end_byte = self
            .end
            .0
            .checked_mul(block_size)?
            .checked_add(block_size - 1)?;
        Some(start_byte..=end_byte)
    }
}

impl Display for LbaRangeInclusive {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        write!(f, "{}..={}", self.start, self.end)
    }
}

/// Size of a block in bytes.
///
/// This type enforces some restrictions on the block size: it must be
/// at least 512 bytes and fit within a [`u32`].
///
/// # Minimum size
///
/// The [`MasterBootRecord`] size is 512 bytes and must fit within a
/// block, so the block size must be at least that large.
///
/// [`MasterBootRecord`]: crate::MasterBootRecord
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
#[repr(transparent)]
pub struct BlockSize(NonZeroU32);

impl BlockSize {
    /// 512-byte block size.
    pub const BS_512: Self = Self(if let Some(nz) = NonZeroU32::new(512) {
        nz
    } else {
        unreachable!()
    });

    /// 4096-byte block size.
    pub const BS_4096: Self = Self(if let Some(nz) = NonZeroU32::new(4096) {
        nz
    } else {
        unreachable!()
    });

    /// Create a `BlockSize`.
    #[must_use]
    pub const fn new(num_bytes: u32) -> Option<Self> {
        if let Some(nz) = NonZeroU32::new(num_bytes) {
            if num_bytes >= 512 {
                Some(Self(nz))
            } else {
                None
            }
        } else {
            None
        }
    }

    /// Create a `BlockSize`.
    #[must_use]
    pub fn from_usize(num_bytes: usize) -> Option<Self> {
        Self::new(u32::try_from(num_bytes).ok()?)
    }

    /// Get the size in bytes as a [`u32`].
    #[must_use]
    pub const fn to_u32(self) -> u32 {
        self.0.get()
    }

    /// Get the size in bytes as a [`u64`].
    #[allow(clippy::as_conversions)]
    #[must_use]
    pub const fn to_u64(self) -> u64 {
        self.0.get() as u64
    }

    /// Get the size in bytes as a [`usize`].
    #[must_use]
    pub fn to_usize(self) -> Option<usize> {
        self.0.get().try_into().ok()
    }
}

impl Default for BlockSize {
    fn default() -> Self {
        BlockSize::BS_512
    }
}

impl Display for BlockSize {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}
<|endoftext|>


<commit_before>#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum HeadingLevel {
    Level1,
    Level2,
    Level3,
}

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum ListType {
    Unordered,
    Ordered,
}

#[derive(Debug, Eq, PartialEq)]
pub enum Block {
    Heading {
        level: HeadingLevel,
        content: String,
    },
    Text { content: String },
    Quote { content: String },
    FencedBlock {
        decorator: Option<String>,
        content: String,
    },
    List {
        list_type: ListType,
        items: Vec<String>,
    },
}<commit_msg>Make heading levels non exhaustive<commit_after>#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum HeadingLevel {
    Level1,
    Level2,
    Level3,
    #[doc(hidden)]
    __NonExhaustive,
}

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum ListType {
    Unordered,
    Ordered,
}

#[derive(Debug, Eq, PartialEq)]
pub enum Block {
    Heading {
        level: HeadingLevel,
        content: String,
    },
    Text { content: String },
    Quote { content: String },
    FencedBlock {
        decorator: Option<String>,
        content: String,
    },
    List {
        list_type: ListType,
        items: Vec<String>,
    },
}<|endoftext|>


<commit_before>use std::fmt;

use name::{Name, OwnedName};
use escape::escape_str;

/// A borrowed version of an XML attribute.
///
/// Consists of a borrowed qualified name and a borrowed string value.
#[deriving(Copy, Clone, Eq, PartialEq, Hash)]
pub struct Attribute<'a> {
    /// Attribute name.
    pub name: Name<'a>,

    /// Attribute value.
    pub value: &'a str
}

impl<'a> fmt::Show for Attribute<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}=\"{}\"", self.name, escape_str(self.value))
    }
}

impl<'a> Attribute<'a> {
    #[inline]
    pub fn to_owned(&self) -> OwnedAttribute {
        OwnedAttribute {
            name: self.name.to_owned(),
            value: self.value.into_string()
        }
    }

    #[inline]
    pub fn new(name: Name<'a>, value: &'a str) -> Attribute<'a> {
        Attribute {
            name: name,
            value: value
        }
    }
}

#[deriving(Clone, Eq, PartialEq, Hash)]
pub struct OwnedAttribute {
    pub name: OwnedName,
    pub value: String
}

impl OwnedAttribute {
    pub fn borrow(&self) -> Attribute {
        Attribute {
            name: self.name.borrow(),
            value: &*self.value
        }
    }

    #[inline]
    pub fn new(name: OwnedName, value: String) -> OwnedAttribute {
        OwnedAttribute {
            name: name,
            value: value
        }
    }
}

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

    use name::Name;

    #[test]
    fn attribute_show() {
        let attr = Attribute::new(
            Name::qualified("attribute", "urn:namespace", Some("n")),
            "its value with > & \" ' < weird symbols"
        );

        assert_eq!(
            &*attr.to_string(),
            "{urn:namespace}n:attribute=\"its value with > & " ' < weird symbols\""
        )
    }
}
<commit_msg>impl Show for OwnedAttribute<commit_after>use std::fmt;

use name::{Name, OwnedName};
use escape::escape_str;

/// A borrowed version of an XML attribute.
///
/// Consists of a borrowed qualified name and a borrowed string value.
#[deriving(Copy, Clone, Eq, PartialEq, Hash)]
pub struct Attribute<'a> {
    /// Attribute name.
    pub name: Name<'a>,

    /// Attribute value.
    pub value: &'a str
}

impl<'a> fmt::Show for Attribute<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}=\"{}\"", self.name, escape_str(self.value))
    }
}

impl<'a> Attribute<'a> {
    #[inline]
    pub fn to_owned(&self) -> OwnedAttribute {
        OwnedAttribute {
            name: self.name.to_owned(),
            value: self.value.into_string()
        }
    }

    #[inline]
    pub fn new(name: Name<'a>, value: &'a str) -> Attribute<'a> {
        Attribute {
            name: name,
            value: value
        }
    }
}

#[deriving(Clone, Eq, PartialEq, Hash)]
pub struct OwnedAttribute {
    pub name: OwnedName,
    pub value: String
}

impl OwnedAttribute {
    pub fn borrow(&self) -> Attribute {
        Attribute {
            name: self.name.borrow(),
            value: &*self.value
        }
    }

    #[inline]
    pub fn new(name: OwnedName, value: String) -> OwnedAttribute {
        OwnedAttribute {
            name: name,
            value: value
        }
    }
}

impl fmt::Show for OwnedAttribute {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}=\"{}\"", self.name, escape_str(&*self.value))
    }
}

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

    use name::Name;

    #[test]
    fn attribute_show() {
        let attr = Attribute::new(
            Name::qualified("attribute", "urn:namespace", Some("n")),
            "its value with > & \" ' < weird symbols"
        );

        assert_eq!(
            &*attr.to_string(),
            "{urn:namespace}n:attribute=\"its value with > & " ' < weird symbols\""
        )
    }
}
<|endoftext|>


<commit_before>use ggez::audio;
use ggez::audio::SoundSource;
use ggez::event;
use ggez::graphics::{self, Color};
use ggez::timer;
use ggez::{Context, GameResult};
use std::env;
use std::path;

struct MainState {
    a: i32,
    direction: i32,
    image: graphics::Image,
    rng: oorandom::Rand32,
}

impl MainState {
    fn draw_crazy_lines(&mut self, ctx: &mut Context, canvas: &mut graphics::Canvas) -> GameResult {
        let num_lines = 100;
        let mut colors = Vec::new();
        for _ in 0..num_lines {
            let r = self.rng.rand_u32() as u8;
            let b = self.rng.rand_u32() as u8;
            let g = self.rng.rand_u32() as u8;
            colors.push(Color::from((r, g, b, 255)));
        }

        let mut last_point = glam::Vec2::new(400.0, 300.0);
        let mut mb = graphics::MeshBuilder::new();
        for color in colors {
            let x = (self.rng.rand_i32() % 50) as f32;
            let y = (self.rng.rand_i32() % 50) as f32;
            let point = glam::Vec2::new(last_point.x + x, last_point.y + y);
            mb.line(&[last_point, point], 3.0, color)?;
            last_point = point;
        }
        let mesh = graphics::Mesh::from_data(&ctx.gfx, mb.build());
        canvas.draw_mesh(mesh, None, (glam::Vec2::new(0.0, 0.0),));

        Ok(())
    }

    fn new(ctx: &mut Context) -> GameResult<MainState> {
        ctx.fs.print_all();

        let image = graphics::Image::from_path(&ctx.fs, &ctx.gfx, "/dragon1.png", true)?;

        ctx.gfx.add_font(
            "LiberationMono",
            graphics::FontData::from_path(&ctx.fs, "/LiberationMono-Regular.ttf")?,
        );
        let mut sound = audio::Source::new(&ctx.fs, &ctx.audio, "/sound.ogg")?;

        // "detached" sounds keep playing even after they are dropped
        let _ = sound.play_detached(&ctx.audio);

        let rng = oorandom::Rand32::new(271828);

        let s = MainState {
            a: 0,
            direction: 1,
            image,
            rng,
        };

        Ok(s)
    }
}

impl event::EventHandler<ggez::GameError> for MainState {
    fn update(&mut self, ctx: &mut Context) -> GameResult {
        const DESIRED_FPS: u32 = 60;
        while ctx.time.check_update_time(DESIRED_FPS) {
            self.a += self.direction;
            if self.a > 250 || self.a <= 0 {
                self.direction *= -1;

                println!("Delta frame time: {:?} ", ctx.time.delta());
                println!("Average FPS: {}", ctx.time.fps());
            }
        }
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult {
        let c = self.a as u8;
        let mut canvas = graphics::Canvas::from_frame(&ctx.gfx, Color::from([0.1, 0.2, 0.3, 1.0]));

        let color = Color::from((c, c, c, 255));
        let dest_point = glam::Vec2::new(0.0, 0.0);
        canvas.draw(self.image.clone(), (dest_point, 0.0, color));
        canvas.draw_text(
            &[graphics::Text::new()
                .font("LiberationMono")
                .text("Hello world!")
                .size(48.0)
                .color(color)],
            dest_point,
            0.0,
            graphics::TextLayout::tl_single_line(),
            0,
        );

        let dest_point2 = glam::Vec2::new(0.0, 256.0);
        let rectangle = graphics::Mesh::new_rectangle(
            &ctx.gfx,
            graphics::DrawMode::fill(),
            graphics::Rect::new(0.0, 256.0, 500.0, 32.0),
            Color::from((0, 0, 0, 255)),
        )?;
        canvas.draw_mesh(rectangle, None, (glam::Vec2::new(0.0, 0.0),));
        canvas.draw_text(
            &[graphics::Text::new()
                .font("LiberationMono")
                .text("This text is 32 pixels high")
                .size(32.0)
                .color(Color::WHITE)],
            dest_point2,
            0.0,
            graphics::TextLayout::tl_single_line(),
            0,
        );

        self.draw_crazy_lines(ctx, &mut canvas)?;
        canvas.finish(&mut ctx.gfx)?;

        timer::yield_now();
        Ok(())
    }
}

pub fn main() -> GameResult {
    let resource_dir = if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") {
        let mut path = path::PathBuf::from(manifest_dir);
        path.push("resources");
        path
    } else {
        path::PathBuf::from("./resources")
    };

    let cb = ggez::ContextBuilder::new("imageview", "ggez").add_resource_path(resource_dir);
    let (mut ctx, event_loop) = cb.build()?;

    let state = MainState::new(&mut ctx)?;
    event::run(ctx, event_loop, state)
}
<commit_msg>fixed imageview example that I missed<commit_after>use ggez::audio;
use ggez::audio::SoundSource;
use ggez::event;
use ggez::graphics::{self, Color, DrawParam};
use ggez::timer;
use ggez::{Context, GameResult};
use std::env;
use std::path;

struct MainState {
    a: i32,
    direction: i32,
    image: graphics::Image,
    rng: oorandom::Rand32,
}

impl MainState {
    fn draw_crazy_lines(&mut self, ctx: &mut Context, canvas: &mut graphics::Canvas) -> GameResult {
        let num_lines = 100;
        let mut colors = Vec::new();
        for _ in 0..num_lines {
            let r = self.rng.rand_u32() as u8;
            let b = self.rng.rand_u32() as u8;
            let g = self.rng.rand_u32() as u8;
            colors.push(Color::from((r, g, b, 255)));
        }

        let mut last_point = glam::Vec2::new(400.0, 300.0);
        let mut mb = graphics::MeshBuilder::new();
        for color in colors {
            let x = (self.rng.rand_i32() % 50) as f32;
            let y = (self.rng.rand_i32() % 50) as f32;
            let point = glam::Vec2::new(last_point.x + x, last_point.y + y);
            mb.line(&[last_point, point], 3.0, color)?;
            last_point = point;
        }
        let mesh = graphics::Mesh::from_data(&ctx.gfx, mb.build());
        canvas.draw_mesh(mesh, None, glam::Vec2::new(0.0, 0.0));

        Ok(())
    }

    fn new(ctx: &mut Context) -> GameResult<MainState> {
        ctx.fs.print_all();

        let image = graphics::Image::from_path(&ctx.fs, &ctx.gfx, "/dragon1.png", true)?;

        ctx.gfx.add_font(
            "LiberationMono",
            graphics::FontData::from_path(&ctx.fs, "/LiberationMono-Regular.ttf")?,
        );
        let mut sound = audio::Source::new(&ctx.fs, &ctx.audio, "/sound.ogg")?;

        // "detached" sounds keep playing even after they are dropped
        let _ = sound.play_detached(&ctx.audio);

        let rng = oorandom::Rand32::new(271828);

        let s = MainState {
            a: 0,
            direction: 1,
            image,
            rng,
        };

        Ok(s)
    }
}

impl event::EventHandler<ggez::GameError> for MainState {
    fn update(&mut self, ctx: &mut Context) -> GameResult {
        const DESIRED_FPS: u32 = 60;
        while ctx.time.check_update_time(DESIRED_FPS) {
            self.a += self.direction;
            if self.a > 250 || self.a <= 0 {
                self.direction *= -1;

                println!("Delta frame time: {:?} ", ctx.time.delta());
                println!("Average FPS: {}", ctx.time.fps());
            }
        }
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult {
        let c = self.a as u8;
        let mut canvas = graphics::Canvas::from_frame(&ctx.gfx, Color::from([0.1, 0.2, 0.3, 1.0]));

        let color = Color::from((c, c, c, 255));
        let dest_point = glam::Vec2::new(0.0, 0.0);
        canvas.draw(
            self.image.clone(),
            DrawParam::new().dest(dest_point).color(color),
        );
        canvas.draw_text(
            &[graphics::Text::new()
                .font("LiberationMono")
                .text("Hello world!")
                .size(48.0)
                .color(color)],
            dest_point,
            0.0,
            graphics::TextLayout::tl_single_line(),
            0,
        );

        let dest_point2 = glam::Vec2::new(0.0, 256.0);
        let rectangle = graphics::Mesh::new_rectangle(
            &ctx.gfx,
            graphics::DrawMode::fill(),
            graphics::Rect::new(0.0, 256.0, 500.0, 32.0),
            Color::from((0, 0, 0, 255)),
        )?;
        canvas.draw_mesh(rectangle, None, glam::Vec2::new(0.0, 0.0));
        canvas.draw_text(
            &[graphics::Text::new()
                .font("LiberationMono")
                .text("This text is 32 pixels high")
                .size(32.0)
                .color(Color::WHITE)],
            dest_point2,
            0.0,
            graphics::TextLayout::tl_single_line(),
            0,
        );

        self.draw_crazy_lines(ctx, &mut canvas)?;
        canvas.finish(&mut ctx.gfx)?;

        timer::yield_now();
        Ok(())
    }
}

pub fn main() -> GameResult {
    let resource_dir = if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") {
        let mut path = path::PathBuf::from(manifest_dir);
        path.push("resources");
        path
    } else {
        path::PathBuf::from("./resources")
    };

    let cb = ggez::ContextBuilder::new("imageview", "ggez").add_resource_path(resource_dir);
    let (mut ctx, event_loop) = cb.build()?;

    let state = MainState::new(&mut ctx)?;
    event::run(ctx, event_loop, state)
}
<|endoftext|>


<commit_before>// This file is part of the uutils coreutils package.
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
// spell-checker:ignore tldr

use clap::App;
use std::ffi::OsString;
use std::fs::File;
use std::io::Cursor;
use std::io::{self, Read, Seek, Write};
use zip::ZipArchive;

include!(concat!(env!("OUT_DIR"), "/uutils_map.rs"));

fn main() -> io::Result<()> {
    println!("Downloading tldr archive");
    let mut zip_reader = ureq::get("https://tldr.sh/assets/tldr.zip")
        .call()
        .unwrap()
        .into_reader();
    let mut buffer = Vec::new();
    zip_reader.read_to_end(&mut buffer).unwrap();
    let mut tldr_zip = ZipArchive::new(Cursor::new(buffer)).unwrap();

    let utils = util_map::<Box<dyn Iterator<Item = OsString>>>();
    match std::fs::create_dir("docs/src/utils/") {
        Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => Ok(()),
        x => x,
    }?;

    let mut summary = File::create("docs/src/SUMMARY.md")?;

    let _ = write!(
        summary,
        "# Summary\n\
        \n\
        [Introduction](index.md)\n\
        * [Installation](installation.md)\n\
        * [Contributing](contributing.md)\n\
        * [GNU test coverage](test_coverage.md)\n\
        \n\
        # Reference\n\
        * [Multi-call binary](multicall.md)\n",
    );

    let mut utils = utils.entries().collect::<Vec<_>>();
    utils.sort();
    for (&name, (_, app)) in utils {
        if name == "[" {
            continue;
        }
        let p = format!("docs/src/utils/{}.md", name);
        if let Ok(f) = File::create(&p) {
            write_markdown(f, &mut app(), name, &mut tldr_zip)?;
            println!("Wrote to '{}'", p);
        } else {
            println!("Error writing to {}", p);
        }
        writeln!(summary, "* [{0}](utils/{0}.md)", name)?;
    }
    Ok(())
}

fn write_markdown(
    mut w: impl Write,
    app: &mut App,
    name: &str,
    tldr_zip: &mut zip::ZipArchive<impl Read + Seek>,
) -> io::Result<()> {
    write!(w, "# {}\n\n", name)?;
    write_version(&mut w, app)?;
    write_usage(&mut w, app, name)?;
    write_description(&mut w, app)?;
    write_options(&mut w, app)?;
    write_examples(&mut w, name, tldr_zip)
}

fn write_version(w: &mut impl Write, app: &App) -> io::Result<()> {
    writeln!(
        w,
        "
version: {}
",
        app.render_version().split_once(' ').unwrap().1
    )
}

fn write_usage(w: &mut impl Write, app: &mut App, name: &str) -> io::Result<()> {
    writeln!(w, "\n```")?;
    let mut usage: String = app
        .render_usage()
        .lines()
        .skip(1)
        .map(|l| l.trim())
        .filter(|l| !l.is_empty())
        .collect::<Vec<_>>()
        .join("\n");
    usage = usage.replace(app.get_name(), name);
    writeln!(w, "{}", usage)?;
    writeln!(w, "```")
}

fn write_description(w: &mut impl Write, app: &App) -> io::Result<()> {
    if let Some(about) = app.get_long_about().or_else(|| app.get_about()) {
        writeln!(w, "{}", about)
    } else {
        Ok(())
    }
}

fn write_examples(
    w: &mut impl Write,
    name: &str,
    tldr_zip: &mut zip::ZipArchive<impl Read + Seek>,
) -> io::Result<()> {
    let content = if let Some(f) = get_zip_content(tldr_zip, &format!("pages/common/{}.md", name)) {
        f
    } else if let Some(f) = get_zip_content(tldr_zip, &format!("pages/linux/{}.md", name)) {
        f
    } else {
        return Ok(());
    };

    writeln!(w, "## Examples")?;
    writeln!(w)?;
    for line in content.lines().skip_while(|l| !l.starts_with('-')) {
        if let Some(l) = line.strip_prefix("- ") {
            writeln!(w, "{}", l)?;
        } else if line.starts_with('`') {
            writeln!(w, "```shell\n{}\n```", line.trim_matches('`'))?;
        } else if line.is_empty() {
            writeln!(w)?;
        } else {
            println!("Not sure what to do with this line:");
            println!("{}", line);
        }
    }
    writeln!(w)?;
    writeln!(
        w,
        "> The examples are provided by the [tldr-pages project](https://tldr.sh) under the [CC BY 4.0 License](https://github.com/tldr-pages/tldr/blob/main/LICENSE.md)."
    )?;
    writeln!(w, ">")?;
    writeln!(
        w,
        "> Please note that, as uutils is a work in progress, some examples might fail."
    )
}

fn get_zip_content(archive: &mut ZipArchive<impl Read + Seek>, name: &str) -> Option<String> {
    let mut s = String::new();
    archive.by_name(name).ok()?.read_to_string(&mut s).unwrap();
    Some(s)
}

fn write_options(w: &mut impl Write, app: &App) -> io::Result<()> {
    writeln!(w, "
Options
")?;
    write!(w, "
")?;
    for arg in app.get_arguments() {
        write!(w, "
")?;
        let mut first = true;
        for l in arg.get_long_and_visible_aliases().unwrap_or_default() {
            if !first {
                write!(w, ", ")?;
            } else {
                first = false;
            }
            write!(w, "")?;
            write!(w, "--{}", l)?;
            if let Some(names) = arg.get_value_names() {
                write!(
                    w,
                    "={}",
                    names
                        .iter()
                        .map(|x| format!("<{}>", x))
                        .collect::<Vec<_>>()
                        .join(" ")
                )?;
            }
            write!(w, "")?;
        }
        for s in arg.get_short_and_visible_aliases().unwrap_or_default() {
            if !first {
                write!(w, ", ")?;
            } else {
                first = false;
            }
            write!(w, "")?;
            write!(w, "-{}", s)?;
            if let Some(names) = arg.get_value_names() {
                write!(
                    w,
                    " {}",
                    names
                        .iter()
                        .map(|x| format!("<{}>", x))
                        .collect::<Vec<_>>()
                        .join(" ")
                )?;
            }
            write!(w, "")?;
        }
        writeln!(w, "
")?;
        writeln!(w, "
\n\n{}\n\n
", arg.get_help().unwrap_or_default())?;
    }
    writeln!(w, "
\n")
}
<commit_msg>when help item has an \n, translate it to a
<commit_after>// This file is part of the uutils coreutils package.
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
// spell-checker:ignore tldr

use clap::App;
use std::ffi::OsString;
use std::fs::File;
use std::io::Cursor;
use std::io::{self, Read, Seek, Write};
use zip::ZipArchive;

include!(concat!(env!("OUT_DIR"), "/uutils_map.rs"));

fn main() -> io::Result<()> {
    println!("Downloading tldr archive");
    let mut zip_reader = ureq::get("https://tldr.sh/assets/tldr.zip")
        .call()
        .unwrap()
        .into_reader();
    let mut buffer = Vec::new();
    zip_reader.read_to_end(&mut buffer).unwrap();
    let mut tldr_zip = ZipArchive::new(Cursor::new(buffer)).unwrap();

    let utils = util_map::<Box<dyn Iterator<Item = OsString>>>();
    match std::fs::create_dir("docs/src/utils/") {
        Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => Ok(()),
        x => x,
    }?;

    let mut summary = File::create("docs/src/SUMMARY.md")?;

    let _ = write!(
        summary,
        "# Summary\n\
        \n\
        [Introduction](index.md)\n\
        * [Installation](installation.md)\n\
        * [Contributing](contributing.md)\n\
        * [GNU test coverage](test_coverage.md)\n\
        \n\
        # Reference\n\
        * [Multi-call binary](multicall.md)\n",
    );

    let mut utils = utils.entries().collect::<Vec<_>>();
    utils.sort();
    for (&name, (_, app)) in utils {
        if name == "[" {
            continue;
        }
        let p = format!("docs/src/utils/{}.md", name);
        if let Ok(f) = File::create(&p) {
            write_markdown(f, &mut app(), name, &mut tldr_zip)?;
            println!("Wrote to '{}'", p);
        } else {
            println!("Error writing to {}", p);
        }
        writeln!(summary, "* [{0}](utils/{0}.md)", name)?;
    }
    Ok(())
}

fn write_markdown(
    mut w: impl Write,
    app: &mut App,
    name: &str,
    tldr_zip: &mut zip::ZipArchive<impl Read + Seek>,
) -> io::Result<()> {
    write!(w, "# {}\n\n", name)?;
    write_version(&mut w, app)?;
    write_usage(&mut w, app, name)?;
    write_description(&mut w, app)?;
    write_options(&mut w, app)?;
    write_examples(&mut w, name, tldr_zip)
}

fn write_version(w: &mut impl Write, app: &App) -> io::Result<()> {
    writeln!(
        w,
        "
version: {}
",
        app.render_version().split_once(' ').unwrap().1
    )
}

fn write_usage(w: &mut impl Write, app: &mut App, name: &str) -> io::Result<()> {
    writeln!(w, "\n```")?;
    let mut usage: String = app
        .render_usage()
        .lines()
        .skip(1)
        .map(|l| l.trim())
        .filter(|l| !l.is_empty())
        .collect::<Vec<_>>()
        .join("\n");
    usage = usage.replace(app.get_name(), name);
    writeln!(w, "{}", usage)?;
    writeln!(w, "```")
}

fn write_description(w: &mut impl Write, app: &App) -> io::Result<()> {
    if let Some(about) = app.get_long_about().or_else(|| app.get_about()) {
        writeln!(w, "{}", about)
    } else {
        Ok(())
    }
}

fn write_examples(
    w: &mut impl Write,
    name: &str,
    tldr_zip: &mut zip::ZipArchive<impl Read + Seek>,
) -> io::Result<()> {
    let content = if let Some(f) = get_zip_content(tldr_zip, &format!("pages/common/{}.md", name)) {
        f
    } else if let Some(f) = get_zip_content(tldr_zip, &format!("pages/linux/{}.md", name)) {
        f
    } else {
        return Ok(());
    };

    writeln!(w, "## Examples")?;
    writeln!(w)?;
    for line in content.lines().skip_while(|l| !l.starts_with('-')) {
        if let Some(l) = line.strip_prefix("- ") {
            writeln!(w, "{}", l)?;
        } else if line.starts_with('`') {
            writeln!(w, "```shell\n{}\n```", line.trim_matches('`'))?;
        } else if line.is_empty() {
            writeln!(w)?;
        } else {
            println!("Not sure what to do with this line:");
            println!("{}", line);
        }
    }
    writeln!(w)?;
    writeln!(
        w,
        "> The examples are provided by the [tldr-pages project](https://tldr.sh) under the [CC BY 4.0 License](https://github.com/tldr-pages/tldr/blob/main/LICENSE.md)."
    )?;
    writeln!(w, ">")?;
    writeln!(
        w,
        "> Please note that, as uutils is a work in progress, some examples might fail."
    )
}

fn get_zip_content(archive: &mut ZipArchive<impl Read + Seek>, name: &str) -> Option<String> {
    let mut s = String::new();
    archive.by_name(name).ok()?.read_to_string(&mut s).unwrap();
    Some(s)
}

fn write_options(w: &mut impl Write, app: &App) -> io::Result<()> {
    writeln!(w, "
Options
")?;
    write!(w, "
")?;
    for arg in app.get_arguments() {
        write!(w, "
")?;
        let mut first = true;
        for l in arg.get_long_and_visible_aliases().unwrap_or_default() {
            if !first {
                write!(w, ", ")?;
            } else {
                first = false;
            }
            write!(w, "")?;
            write!(w, "--{}", l)?;
            if let Some(names) = arg.get_value_names() {
                write!(
                    w,
                    "={}",
                    names
                        .iter()
                        .map(|x| format!("<{}>", x))
                        .collect::<Vec<_>>()
                        .join(" ")
                )?;
            }
            write!(w, "")?;
        }
        for s in arg.get_short_and_visible_aliases().unwrap_or_default() {
            if !first {
                write!(w, ", ")?;
            } else {
                first = false;
            }
            write!(w, "")?;
            write!(w, "-{}", s)?;
            if let Some(names) = arg.get_value_names() {
                write!(
                    w,
                    " {}",
                    names
                        .iter()
                        .map(|x| format!("<{}>", x))
                        .collect::<Vec<_>>()
                        .join(" ")
                )?;
            }
            write!(w, "")?;
        }
        writeln!(w, "
")?;
        writeln!(
            w,
            "
\n\n{}\n\n
",
            arg.get_help().unwrap_or_default().replace("\n", "
")
        )?;
    }
    writeln!(w, "
\n")
}
<|endoftext|>


<commit_before>extern crate ndarray;
extern crate autograd as ag;

use std::default::Default;
use std::time::{Duration, Instant};

// softmax regression with Adam optimizer for mnist.
// 0.92 test accuracy after 5 epochs,
// 0.26 sec/epoch on 2.7GHz Intel Core i5
//
// Run "./download_mnist.sh" beforehand if you don't have dataset

macro_rules! eval_with_time {
  ($x:expr) => {
    {
      let start = Instant::now();
      let result = $x;
      let end = start.elapsed();
      println!("{}.{:03} sec", end.as_secs(), end.subsec_nanos() / 1_000_000);
      result
    }
  };
}

#[cfg(not(test))]
fn main()
{
    let ((x_train, y_train), (x_test, y_test)) = dataset::load();

    // -- graph def --
    let ref x = ag::placeholder(&[-1, 28 * 28]);
    let ref y = ag::placeholder(&[-1, 1]);
    let ref w = ag::variable(ag::init::glorot_uniform(&[28 * 28, 10]));
    let ref b = ag::variable(ag::init::zeros(&[1, 10]));
    let ref z = ag::matmul(x, w) + b;
    let ref loss = ag::sparse_softmax_cross_entropy(z, y);
    let ref grads = ag::gradients(loss, &[w, b], None);
    let ref predictions = ag::argmax(z, -1, true);
    let ref accuracy = ag::reduce_mean(&ag::equals(predictions, y), 0, false);

    // -- actual training --
    let mut optimizer = ag::sgd::optimizers::Adam { ..Default::default() };
    let batch_size = 100;
    let num_samples = x_train.shape()[0];
    let num_batches = num_samples / batch_size;

    for epoch in 0..5 {
        eval_with_time!({
            let perm = ag::init::permutation(num_samples).to_vec();
            for i in 0..num_batches {
                let indices = perm[i..i + batch_size].to_vec();
                let x_batch = x_train.select(ndarray::Axis(0), indices.as_slice());
                let y_batch = y_train.select(ndarray::Axis(0), indices.as_slice());
                let feed_dict = ag::Input::new().add(x, x_batch).add(y, y_batch);
                ag::sgd::apply_gradients(&mut optimizer, &[w, b], grads, feed_dict);
            }
        });
        println!("finish epoch {}", epoch);
    }

    // -- test --
    let feed_dict = ag::Input::new().add(x, x_test).add(y, y_test);
    println!("test accuracy: {}", accuracy.eval_with_input(feed_dict));
}

pub mod dataset {
    extern crate ndarray;
    use std::fs::File;
    use std::io;
    use std::io::Read;
    use std::mem;
    use std::path::Path;
    use std::process;

    type NdArray = ndarray::Array<f32, ndarray::IxDyn>;

    /// load mnist dataset as "ndarray" objects.
    ///
    /// labels are sparse (vertical vector).
    pub fn load() -> ((NdArray, NdArray), (NdArray, NdArray))
    {
        // load dataset as `Vec`s
        let (train_x, num_image_train): (Vec<f32>, usize) =
            load_images("data/mnist/train-images-idx3-ubyte");
        let (train_y, num_label_train): (Vec<f32>, usize) =
            load_labels("data/mnist/train-labels-idx1-ubyte");
        let (test_x, num_image_test): (Vec<f32>, usize) =
            load_images("data/mnist/t10k-images-idx3-ubyte");
        let (test_y, num_label_test): (Vec<f32>, usize) =
            load_labels("data/mnist/t10k-labels-idx1-ubyte");

        // Vec to ndarray
        let as_arr = NdArray::from_shape_vec;
        let x_train = as_arr(ndarray::IxDyn(&[num_image_train, 28 * 28]), train_x).unwrap();
        let y_train = as_arr(ndarray::IxDyn(&[num_label_train, 1]), train_y).unwrap();
        let x_test = as_arr(ndarray::IxDyn(&[num_image_test, 28 * 28]), test_x).unwrap();
        let y_test = as_arr(ndarray::IxDyn(&[num_label_test, 1]), test_y).unwrap();
        ((x_train, y_train), (x_test, y_test))
    }

    fn load_images<P: AsRef<Path>>(path: P) -> (Vec<f32>, usize)
    {
        let ref mut buf_reader = io::BufReader::new(File::open(path).expect(
            "Please run ./download_mnist.sh beforehand",
        ));
        let magic = u32::from_be(read_u32(buf_reader));
        if magic != 2051 {
            panic!("Invalid magic number. expected 2051, got {}", magic)
        }
        let num_image = u32::from_be(read_u32(buf_reader)) as usize;
        let rows = u32::from_be(read_u32(buf_reader)) as usize;
        let cols = u32::from_be(read_u32(buf_reader)) as usize;
        assert!(rows == 28 && cols == 28);

        // read images
        let mut buf: Vec<u8> = vec![0u8; num_image * rows * cols];
        buf_reader.read_exact(buf.as_mut());
        let ret = buf.into_iter().map(|x| (x as f32) / 255.).collect();
        (ret, num_image)
    }

    fn load_labels<P: AsRef<Path>>(path: P) -> (Vec<f32>, usize)
    {
        let ref mut buf_reader = io::BufReader::new(File::open(path).unwrap());
        let magic = u32::from_be(read_u32(buf_reader));
        if magic != 2049 {
            panic!("Invalid magic number. Got expect 2049, got {}", magic);
        }
        let num_label = u32::from_be(read_u32(buf_reader)) as usize;
        // read labels
        let mut buf: Vec<u8> = vec![0u8; num_label];
        buf_reader.read_exact(buf.as_mut());
        let ret: Vec<f32> = buf.into_iter().map(|x| x as f32).collect();
        (ret, num_label)
    }

    fn read_u32<T: Read>(reader: &mut T) -> u32
    {
        let mut buf: [u8; 4] = [0, 0, 0, 0];
        reader.read_exact(&mut buf);
        unsafe { mem::transmute(buf) }
    }
}
<commit_msg>fix example<commit_after>#[macro_use(s)]
extern crate ndarray;
extern crate autograd as ag;

use std::default::Default;
use std::time::{Duration, Instant};

// softmax regression with Adam optimizer for mnist.
// 0.91 test accuracy after 2 epochs,
// 0.27 sec/epoch on 2.7GHz Intel Core i5
//
// Run "./download_mnist.sh" beforehand if you don't have dataset

macro_rules! eval_with_time {
  ($x:expr) => {
    {
      let start = Instant::now();
      let result = $x;
      let end = start.elapsed();
      println!("{}.{:03} sec", end.as_secs(), end.subsec_nanos() / 1_000_000);
      result
    }
  };
}

#[cfg(not(test))]
fn main()
{
    let ((x_train, y_train), (x_test, y_test)) = dataset::load();

    // -- graph def --
    let ref x = ag::placeholder(&[-1, 28*28]);
    let ref y = ag::placeholder(&[-1, 1]);
    let ref w = ag::variable(ag::init::glorot_uniform(&[28*28, 10]));
    let ref b = ag::variable(ag::init::zeros(&[1, 10]));
    let ref z = ag::matmul(x, w) + b;
    let ref loss = ag::sparse_softmax_cross_entropy(z, y);
    let ref grads = ag::gradients(loss, &[w, b], None);
    let ref predictions = ag::argmax(z, -1, true);
    let ref accuracy = ag::reduce_mean(&ag::equals(predictions, y), 0, false);

    // -- actual training --
    let mut optimizer = ag::sgd::optimizers::Adam { ..Default::default() };
    let max_epoch = 5;
    let batch_size = 200isize;
    let num_samples = x_train.shape()[0];
    let num_batches = num_samples / batch_size as usize;

    for epoch in 0..max_epoch {
        let perm = ag::init::permutation(num_batches) * batch_size as usize;
        for i in  perm.to_vec().into_iter() {
            let i = i as isize;
            let x_batch = x_train.slice(s![i..i+batch_size, ..]).to_owned();
            let y_batch = y_train.slice(s![i..i+batch_size, ..]).to_owned();
            let feed_dict = ag::Input::new().add(x, x_batch).add(y, y_batch);
            ag::sgd::apply_gradients(&mut optimizer, &[w, b], grads, feed_dict);
        }
        println!("finish epoch {}", epoch);
    }

    // -- test --
    let feed_dict = ag::Input::new().add(x, x_test).add(y, y_test);
    println!("test accuracy: {}", accuracy.eval_with_input(feed_dict));
}

pub mod dataset {
    extern crate ndarray;
    use std::fs::File;
    use std::io;
    use std::io::Read;
    use std::mem;
    use std::path::Path;
    use std::process;

    type NdArray = ndarray::Array<f32, ndarray::IxDyn>;

    /// load mnist dataset as "ndarray" objects.
    ///
    /// labels are sparse (vertical vector).
    pub fn load() -> ((NdArray, NdArray), (NdArray, NdArray))
    {
        // load dataset as `Vec`s
        let (train_x, num_image_train): (Vec<f32>, usize) =
            load_images("data/mnist/train-images-idx3-ubyte");
        let (train_y, num_label_train): (Vec<f32>, usize) =
            load_labels("data/mnist/train-labels-idx1-ubyte");
        let (test_x, num_image_test): (Vec<f32>, usize) =
            load_images("data/mnist/t10k-images-idx3-ubyte");
        let (test_y, num_label_test): (Vec<f32>, usize) =
            load_labels("data/mnist/t10k-labels-idx1-ubyte");

        // Vec to ndarray
        let as_arr = NdArray::from_shape_vec;
        let x_train = as_arr(ndarray::IxDyn(&[num_image_train, 28 * 28]), train_x).unwrap();
        let y_train = as_arr(ndarray::IxDyn(&[num_label_train, 1]), train_y).unwrap();
        let x_test = as_arr(ndarray::IxDyn(&[num_image_test, 28 * 28]), test_x).unwrap();
        let y_test = as_arr(ndarray::IxDyn(&[num_label_test, 1]), test_y).unwrap();
        ((x_train, y_train), (x_test, y_test))
    }

    fn load_images<P: AsRef<Path>>(path: P) -> (Vec<f32>, usize)
    {
        let ref mut buf_reader = io::BufReader::new(File::open(path).expect(
            "Please run ./download_mnist.sh beforehand",
        ));
        let magic = u32::from_be(read_u32(buf_reader));
        if magic != 2051 {
            panic!("Invalid magic number. expected 2051, got {}", magic)
        }
        let num_image = u32::from_be(read_u32(buf_reader)) as usize;
        let rows = u32::from_be(read_u32(buf_reader)) as usize;
        let cols = u32::from_be(read_u32(buf_reader)) as usize;
        assert!(rows == 28 && cols == 28);

        // read images
        let mut buf: Vec<u8> = vec![0u8; num_image * rows * cols];
        buf_reader.read_exact(buf.as_mut());
        let ret = buf.into_iter().map(|x| (x as f32) / 255.).collect();
        (ret, num_image)
    }

    fn load_labels<P: AsRef<Path>>(path: P) -> (Vec<f32>, usize)
    {
        let ref mut buf_reader = io::BufReader::new(File::open(path).unwrap());
        let magic = u32::from_be(read_u32(buf_reader));
        if magic != 2049 {
            panic!("Invalid magic number. Got expect 2049, got {}", magic);
        }
        let num_label = u32::from_be(read_u32(buf_reader)) as usize;
        // read labels
        let mut buf: Vec<u8> = vec![0u8; num_label];
        buf_reader.read_exact(buf.as_mut());
        let ret: Vec<f32> = buf.into_iter().map(|x| x as f32).collect();
        (ret, num_label)
    }

    fn read_u32<T: Read>(reader: &mut T) -> u32
    {
        let mut buf: [u8; 4] = [0, 0, 0, 0];
        reader.read_exact(&mut buf);
        unsafe { mem::transmute(buf) }
    }
}
<|endoftext|>


<commit_before>use std::iter;

pub type Domino = (usize, usize);

/// A table keeping track of available dominoes.
///
/// Effectively a 6x6 matrix. Each position denotes whether a domino is available with that column
/// dots and row dots. Positions are mirrored ((3,4) == (4,3)), except for positions with equal row
/// and column numbers.
struct AvailabilityTable {
    m: Vec<usize>
}

impl AvailabilityTable {
    fn new() -> AvailabilityTable {
        AvailabilityTable { m: iter::repeat(0).take(6 * 6).collect() }
    }

    fn get(&self, x: usize, y: usize) -> usize {
        self.m[(x-1) * 6 + (y-1)]
    }

    fn set(&mut self, x: usize, y: usize, v: usize) {
        let m = &mut self.m[..];
        m[(x-1) * 6 + (y-1)] = v;
    }

    fn add(&mut self, x: usize, y: usize) {
        if x == y {
            let n = self.get(x, y);
            self.set(x, y, n + 1) // Along the diagonal
        }
        else {
            let m = self.get(x, y);
            self.set(x, y, m + 1);
            let n = self.get(y, x);
            self.set(y, x, n + 1);
        }
    }

    fn remove(&mut self, x: usize, y: usize) {
        if self.get(x, y) > 0 {
            if x == y {
                let n = self.get(x, y);
                self.set(x, y, n - 1) // Along the diagonal
            }
            else {
                let m = self.get(x, y);
                self.set(x, y, m - 1);
                let n = self.get(y, x);
                self.set(y, x, n - 1);
            }
        }
        else {
            // For this toy code hard explicit fail is best
            panic!("remove for 0 stones: ({:?}, {:?})", x, y)
        }
    }

    fn pop_first(&mut self, x: usize) -> Option<usize> {
        for y in 1 .. 7 {
            if self.get(x, y) > 0 {
                self.remove(x, y);
                return Some(y)
            }
        }
        None
    }
}

pub fn chain(dominoes: &Vec<Domino>) -> Option<Vec<Domino>> {
    match dominoes.len() {
        0 => Some(vec!()),
        1 => Some(vec!(dominoes[0])),
        _ => {
            // First check if the total number of each amount of dots is even, if not it's not
            // possible to complete a cycle. This follows from that it's an Eulerian path.
            let mut v: Vec<usize> = vec!(0, 0, 0, 0, 0, 0);
            // Keep the mutable borrow in a small scope here to allow v.iter().
            {
                let vs = &mut v[..];
                for dom in dominoes.iter() {
                    vs[dom.0 - 1] += 1;
                    vs[dom.1 - 1] += 1;
                }
            }
            for n in v.iter() {
                if n % 2 != 0 {
                    return None
                }
            }
            Some(chain_worker(dominoes))
        }
    }
}

fn chain_worker(dominoes: &Vec<Domino>) -> Vec<Domino> {
    let mut doms = dominoes.clone();
    let first = doms.pop().unwrap();
    let mut t = AvailabilityTable::new();
    for dom in doms.iter() {
        t.add(dom.0, dom.1)

    }
    let mut v: Vec<Domino> = Vec::new();
    v.push(first);
    let mut n = first.1; // Number to connect to
    loop {
        match t.pop_first(n) {
            None => break,
            Some(m) => {
                v.push((n, m));
                n = m;
            }
        }
    }
    v
}
<commit_msg>dominoes: Check chain length, return None if mismatch<commit_after>use std::iter;

pub type Domino = (usize, usize);

/// A table keeping track of available dominoes.
///
/// Effectively a 6x6 matrix. Each position denotes whether a domino is available with that column
/// dots and row dots. Positions are mirrored ((3,4) == (4,3)), except for positions with equal row
/// and column numbers.
struct AvailabilityTable {
    m: Vec<usize>
}

impl AvailabilityTable {
    fn new() -> AvailabilityTable {
        AvailabilityTable { m: iter::repeat(0).take(6 * 6).collect() }
    }

    fn get(&self, x: usize, y: usize) -> usize {
        self.m[(x-1) * 6 + (y-1)]
    }

    fn set(&mut self, x: usize, y: usize, v: usize) {
        let m = &mut self.m[..];
        m[(x-1) * 6 + (y-1)] = v;
    }

    fn add(&mut self, x: usize, y: usize) {
        if x == y {
            let n = self.get(x, y);
            self.set(x, y, n + 1) // Along the diagonal
        }
        else {
            let m = self.get(x, y);
            self.set(x, y, m + 1);
            let n = self.get(y, x);
            self.set(y, x, n + 1);
        }
    }

    fn remove(&mut self, x: usize, y: usize) {
        if self.get(x, y) > 0 {
            if x == y {
                let n = self.get(x, y);
                self.set(x, y, n - 1) // Along the diagonal
            }
            else {
                let m = self.get(x, y);
                self.set(x, y, m - 1);
                let n = self.get(y, x);
                self.set(y, x, n - 1);
            }
        }
        else {
            // For this toy code hard explicit fail is best
            panic!("remove for 0 stones: ({:?}, {:?})", x, y)
        }
    }

    fn pop_first(&mut self, x: usize) -> Option<usize> {
        for y in 1 .. 7 {
            if self.get(x, y) > 0 {
                self.remove(x, y);
                return Some(y)
            }
        }
        None
    }
}

pub fn chain(dominoes: &Vec<Domino>) -> Option<Vec<Domino>> {
    match dominoes.len() {
        0 => Some(vec!()),
        1 => Some(vec!(dominoes[0])),
        _ => {
            // First check if the total number of each amount of dots is even, if not it's not
            // possible to complete a cycle. This follows from that it's an Eulerian path.
            let mut v: Vec<usize> = vec!(0, 0, 0, 0, 0, 0);
            // Keep the mutable borrow in a small scope here to allow v.iter().
            {
                let vs = &mut v[..];
                for dom in dominoes.iter() {
                    vs[dom.0 - 1] += 1;
                    vs[dom.1 - 1] += 1;
                }
            }
            for n in v.iter() {
                if n % 2 != 0 {
                    return None
                }
            }
            let chain = chain_worker(dominoes);
            if chain.len() == dominoes.len() {
                Some(chain)
            }
            else {
                None
            }
        }
    }
}

fn chain_worker(dominoes: &Vec<Domino>) -> Vec<Domino> {
    let mut doms = dominoes.clone();
    let first = doms.pop().unwrap();
    let mut t = AvailabilityTable::new();
    for dom in doms.iter() {
        t.add(dom.0, dom.1)

    }
    let mut v: Vec<Domino> = Vec::new();
    v.push(first);
    let mut n = first.1; // Number to connect to
    loop {
        match t.pop_first(n) {
            None => break,
            Some(m) => {
                v.push((n, m));
                n = m;
            }
        }
    }
    v
}
<|endoftext|>