<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/. */

//! Generic types for the handling of [images].
//!
//! [images]: https://drafts.csswg.org/css-images/#image-values

use Atom;
use cssparser::serialize_identifier;
use std::fmt;
use style_traits::{HasViewportPercentage, ToCss};
use values::computed::ComputedValueAsSpecified;
use values::specified::url::SpecifiedUrl;

/// An [image].
///
/// [image]: https://drafts.csswg.org/css-images/#image-values
#[derive(Clone, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum Image<Gradient, MozImageRect> {
    /// A `<url()>` image.
    Url(SpecifiedUrl),
    /// A `<gradient>` image.
    Gradient(Gradient),
    /// A `-moz-image-rect` image
    Rect(MozImageRect),
    /// A `-moz-element(# <element-id>)`
    Element(Atom),
    /// A paint worklet image.
    /// https://drafts.css-houdini.org/css-paint-api/
    #[cfg(feature = "servo")]
    PaintWorklet(PaintWorklet),
}

/// A CSS gradient.
/// https://drafts.csswg.org/css-images/#gradients
#[derive(Clone, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct Gradient<LineDirection, Length, LengthOrPercentage, Position, Color> {
    /// Gradients can be linear or radial.
    pub kind: GradientKind<LineDirection, Length, LengthOrPercentage, Position>,
    /// The color stops and interpolation hints.
    pub items: Vec<GradientItem<Color, LengthOrPercentage>>,
    /// True if this is a repeating gradient.
    pub repeating: bool,
    /// Compatibility mode.
    pub compat_mode: CompatMode,
}

#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
/// Whether we used the modern notation or the compatibility `-webkit` prefix.
pub enum CompatMode {
    /// Modern syntax.
    Modern,
    /// `-webkit` prefix.
    WebKit,
}

/// A gradient kind.
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum GradientKind<LineDirection, Length, LengthOrPercentage, Position> {
    /// A linear gradient.
    Linear(LineDirection),
    /// A radial gradient.
    Radial(EndingShape<Length, LengthOrPercentage>, Position),
}

/// A radial gradient's ending shape.
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum EndingShape<Length, LengthOrPercentage> {
    /// A circular gradient.
    Circle(Circle<Length>),
    /// An elliptic gradient.
    Ellipse(Ellipse<LengthOrPercentage>),
}

/// A circle shape.
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum Circle<Length> {
    /// A circle radius.
    Radius(Length),
    /// A circle extent.
    Extent(ShapeExtent),
}

/// An ellipse shape.
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum Ellipse<LengthOrPercentage> {
    /// An ellipse pair of radii.
    Radii(LengthOrPercentage, LengthOrPercentage),
    /// An ellipse extent.
    Extent(ShapeExtent),
}

/// https://drafts.csswg.org/css-images/#typedef-extent-keyword
define_css_keyword_enum!(ShapeExtent:
    "closest-side" => ClosestSide,
    "farthest-side" => FarthestSide,
    "closest-corner" => ClosestCorner,
    "farthest-corner" => FarthestCorner,
    "contain" => Contain,
    "cover" => Cover
);
no_viewport_percentage!(ShapeExtent);
impl ComputedValueAsSpecified for ShapeExtent {}

/// A gradient item.
/// https://drafts.csswg.org/css-images-4/#color-stop-syntax
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue, ToCss)]
pub enum GradientItem<Color, LengthOrPercentage> {
    /// A color stop.
    ColorStop(ColorStop<Color, LengthOrPercentage>),
    /// An interpolation hint.
    InterpolationHint(LengthOrPercentage),
}

/// A color stop.
/// https://drafts.csswg.org/css-images/#typedef-color-stop-list
#[derive(Clone, Copy, HasViewportPercentage, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct ColorStop<Color, LengthOrPercentage> {
    /// The color of this stop.
    pub color: Color,
    /// The position of this stop.
    pub position: Option<LengthOrPercentage>,
}

/// Specified values for a paint worklet.
/// https://drafts.css-houdini.org/css-paint-api/
#[derive(Clone, Debug, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct PaintWorklet {
    /// The name the worklet was registered with.
    pub name: Atom,
}

impl ToCss for PaintWorklet {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        dest.write_str("paint(")?;
        serialize_identifier(&*self.name.to_string(), dest)?;
        dest.write_str(")")
    }
}

/// Values for `moz-image-rect`.
///
/// `-moz-image-rect(<uri>, top, right, bottom, left)`
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[css(function)]
#[derive(Clone, Debug, PartialEq, ToComputedValue, ToCss)]
pub struct MozImageRect<NumberOrPercentage> {
    pub url: SpecifiedUrl,
    pub top: NumberOrPercentage,
    pub bottom: NumberOrPercentage,
    pub right: NumberOrPercentage,
    pub left: NumberOrPercentage,
}

impl<G, R> fmt::Debug for Image<G, R>
    where G: fmt::Debug, R: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Image::Url(ref url) => url.to_css(f),
            Image::Gradient(ref grad) => grad.fmt(f),
            Image::Rect(ref rect) => rect.fmt(f),
            #[cfg(feature = "servo")]
            Image::PaintWorklet(ref paint_worklet) => paint_worklet.fmt(f),
            Image::Element(ref selector) => {
                f.write_str("-moz-element(#")?;
                serialize_identifier(&selector.to_string(), f)?;
                f.write_str(")")
            },
        }
    }
}

impl<G, R> ToCss for Image<G, R>
    where G: ToCss, R: ToCss,
{
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        match *self {
            Image::Url(ref url) => url.to_css(dest),
            Image::Gradient(ref gradient) => gradient.to_css(dest),
            Image::Rect(ref rect) => rect.to_css(dest),
            #[cfg(feature = "servo")]
            Image::PaintWorklet(ref paint_worklet) => paint_worklet.to_css(dest),
            Image::Element(ref selector) => {
                dest.write_str("-moz-element(#")?;
                serialize_identifier(&selector.to_string(), dest)?;
                dest.write_str(")")
            },
        }
    }
}

impl<G, R> HasViewportPercentage for Image<G, R>
    where G: HasViewportPercentage
{
    fn has_viewport_percentage(&self) -> bool {
        match *self {
            Image::Gradient(ref gradient) => gradient.has_viewport_percentage(),
            _ => false,
        }
    }
}

impl<D, L, LoP, P, C> ToCss for Gradient<D, L, LoP, P, C>
    where D: LineDirection, L: ToCss, LoP: ToCss, P: ToCss, C: ToCss,
{
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        if self.compat_mode == CompatMode::WebKit {
            dest.write_str("-webkit-")?;
        }
        if self.repeating {
            dest.write_str("repeating-")?;
        }
        dest.write_str(self.kind.label())?;
        dest.write_str("-gradient(")?;
        let mut skip_comma = match self.kind {
            GradientKind::Linear(ref direction) if direction.points_downwards() => true,
            GradientKind::Linear(ref direction) => {
                direction.to_css(dest, self.compat_mode)?;
                false
            },
            GradientKind::Radial(ref shape, ref position) => {
                let omit_shape = match *shape {
                    EndingShape::Ellipse(Ellipse::Extent(ShapeExtent::Cover)) |
                    EndingShape::Ellipse(Ellipse::Extent(ShapeExtent::FarthestCorner)) => {
                        true
                    },
                    _ => false,
                };
                if self.compat_mode == CompatMode::Modern {
                    if !omit_shape {
                        shape.to_css(dest)?;
                        dest.write_str(" ")?;
                    }
                    dest.write_str("at ")?;
                    position.to_css(dest)?;
                } else {
                    position.to_css(dest)?;
                    if !omit_shape {
                        dest.write_str(", ")?;
                        shape.to_css(dest)?;
                    }
                }
                false
            },
        };
        for item in &self.items {
            if !skip_comma {
                dest.write_str(", ")?;
            }
            skip_comma = false;
            item.to_css(dest)?;
        }
        dest.write_str(")")
    }
}

impl<D, L, LoP, P> GradientKind<D, L, LoP, P> {
    fn label(&self) -> &str {
        match *self {
            GradientKind::Linear(..) => "linear",
            GradientKind::Radial(..) => "radial",
        }
    }
}

/// The direction of a linear gradient.
pub trait LineDirection {
    /// Whether this direction points towards, and thus can be omitted.
    fn points_downwards(&self) -> bool;

    /// Serialises this direction according to the compatibility mode.
    fn to_css<W>(&self, dest: &mut W, compat_mode: CompatMode) -> fmt::Result
        where W: fmt::Write;
}

impl<L, LoP> ToCss for EndingShape<L, LoP>
    where L: ToCss, LoP: ToCss,
{
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        match *self {
            EndingShape::Circle(Circle::Extent(ShapeExtent::FarthestCorner)) |
            EndingShape::Circle(Circle::Extent(ShapeExtent::Cover)) => {
                dest.write_str("circle")
            },
            EndingShape::Circle(Circle::Extent(keyword)) => {
                dest.write_str("circle ")?;
                keyword.to_css(dest)
            },
            EndingShape::Circle(Circle::Radius(ref length)) => {
                length.to_css(dest)
            },
            EndingShape::Ellipse(Ellipse::Extent(keyword)) => {
                keyword.to_css(dest)
            },
            EndingShape::Ellipse(Ellipse::Radii(ref x, ref y)) => {
                x.to_css(dest)?;
                dest.write_str(" ")?;
                y.to_css(dest)
            },
        }
    }
}

impl<C, L> fmt::Debug for ColorStop<C, L>
    where C: fmt::Debug, L: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self.color)?;
        if let Some(ref pos) = self.position {
            write!(f, " {:?}", pos)?;
        }
        Ok(())
    }
}

impl<C, L> ToCss for ColorStop<C, L>
    where C: ToCss, L: ToCss,
{
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        self.color.to_css(dest)?;
        if let Some(ref position) = self.position {
            dest.write_str(" ")?;
            position.to_css(dest)?;
        }
        Ok(())
    }
}
<commit_msg>Derive ToCss for EndingShape<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/. */

//! Generic types for the handling of [images].
//!
//! [images]: https://drafts.csswg.org/css-images/#image-values

use Atom;
use cssparser::serialize_identifier;
use std::fmt;
use style_traits::{HasViewportPercentage, ToCss};
use values::computed::ComputedValueAsSpecified;
use values::specified::url::SpecifiedUrl;

/// An [image].
///
/// [image]: https://drafts.csswg.org/css-images/#image-values
#[derive(Clone, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum Image<Gradient, MozImageRect> {
    /// A `<url()>` image.
    Url(SpecifiedUrl),
    /// A `<gradient>` image.
    Gradient(Gradient),
    /// A `-moz-image-rect` image
    Rect(MozImageRect),
    /// A `-moz-element(# <element-id>)`
    Element(Atom),
    /// A paint worklet image.
    /// https://drafts.css-houdini.org/css-paint-api/
    #[cfg(feature = "servo")]
    PaintWorklet(PaintWorklet),
}

/// A CSS gradient.
/// https://drafts.csswg.org/css-images/#gradients
#[derive(Clone, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct Gradient<LineDirection, Length, LengthOrPercentage, Position, Color> {
    /// Gradients can be linear or radial.
    pub kind: GradientKind<LineDirection, Length, LengthOrPercentage, Position>,
    /// The color stops and interpolation hints.
    pub items: Vec<GradientItem<Color, LengthOrPercentage>>,
    /// True if this is a repeating gradient.
    pub repeating: bool,
    /// Compatibility mode.
    pub compat_mode: CompatMode,
}

#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
/// Whether we used the modern notation or the compatibility `-webkit` prefix.
pub enum CompatMode {
    /// Modern syntax.
    Modern,
    /// `-webkit` prefix.
    WebKit,
}

/// A gradient kind.
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum GradientKind<LineDirection, Length, LengthOrPercentage, Position> {
    /// A linear gradient.
    Linear(LineDirection),
    /// A radial gradient.
    Radial(EndingShape<Length, LengthOrPercentage>, Position),
}

/// A radial gradient's ending shape.
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue, ToCss)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum EndingShape<Length, LengthOrPercentage> {
    /// A circular gradient.
    Circle(Circle<Length>),
    /// An elliptic gradient.
    Ellipse(Ellipse<LengthOrPercentage>),
}

/// A circle shape.
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum Circle<Length> {
    /// A circle radius.
    Radius(Length),
    /// A circle extent.
    Extent(ShapeExtent),
}

/// An ellipse shape.
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue, ToCss)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum Ellipse<LengthOrPercentage> {
    /// An ellipse pair of radii.
    Radii(LengthOrPercentage, LengthOrPercentage),
    /// An ellipse extent.
    Extent(ShapeExtent),
}

/// https://drafts.csswg.org/css-images/#typedef-extent-keyword
define_css_keyword_enum!(ShapeExtent:
    "closest-side" => ClosestSide,
    "farthest-side" => FarthestSide,
    "closest-corner" => ClosestCorner,
    "farthest-corner" => FarthestCorner,
    "contain" => Contain,
    "cover" => Cover
);
no_viewport_percentage!(ShapeExtent);
impl ComputedValueAsSpecified for ShapeExtent {}

/// A gradient item.
/// https://drafts.csswg.org/css-images-4/#color-stop-syntax
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue, ToCss)]
pub enum GradientItem<Color, LengthOrPercentage> {
    /// A color stop.
    ColorStop(ColorStop<Color, LengthOrPercentage>),
    /// An interpolation hint.
    InterpolationHint(LengthOrPercentage),
}

/// A color stop.
/// https://drafts.csswg.org/css-images/#typedef-color-stop-list
#[derive(Clone, Copy, HasViewportPercentage, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct ColorStop<Color, LengthOrPercentage> {
    /// The color of this stop.
    pub color: Color,
    /// The position of this stop.
    pub position: Option<LengthOrPercentage>,
}

/// Specified values for a paint worklet.
/// https://drafts.css-houdini.org/css-paint-api/
#[derive(Clone, Debug, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct PaintWorklet {
    /// The name the worklet was registered with.
    pub name: Atom,
}

impl ToCss for PaintWorklet {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        dest.write_str("paint(")?;
        serialize_identifier(&*self.name.to_string(), dest)?;
        dest.write_str(")")
    }
}

/// Values for `moz-image-rect`.
///
/// `-moz-image-rect(<uri>, top, right, bottom, left)`
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[css(function)]
#[derive(Clone, Debug, PartialEq, ToComputedValue, ToCss)]
pub struct MozImageRect<NumberOrPercentage> {
    pub url: SpecifiedUrl,
    pub top: NumberOrPercentage,
    pub bottom: NumberOrPercentage,
    pub right: NumberOrPercentage,
    pub left: NumberOrPercentage,
}

impl<G, R> fmt::Debug for Image<G, R>
    where G: fmt::Debug, R: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Image::Url(ref url) => url.to_css(f),
            Image::Gradient(ref grad) => grad.fmt(f),
            Image::Rect(ref rect) => rect.fmt(f),
            #[cfg(feature = "servo")]
            Image::PaintWorklet(ref paint_worklet) => paint_worklet.fmt(f),
            Image::Element(ref selector) => {
                f.write_str("-moz-element(#")?;
                serialize_identifier(&selector.to_string(), f)?;
                f.write_str(")")
            },
        }
    }
}

impl<G, R> ToCss for Image<G, R>
    where G: ToCss, R: ToCss,
{
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        match *self {
            Image::Url(ref url) => url.to_css(dest),
            Image::Gradient(ref gradient) => gradient.to_css(dest),
            Image::Rect(ref rect) => rect.to_css(dest),
            #[cfg(feature = "servo")]
            Image::PaintWorklet(ref paint_worklet) => paint_worklet.to_css(dest),
            Image::Element(ref selector) => {
                dest.write_str("-moz-element(#")?;
                serialize_identifier(&selector.to_string(), dest)?;
                dest.write_str(")")
            },
        }
    }
}

impl<G, R> HasViewportPercentage for Image<G, R>
    where G: HasViewportPercentage
{
    fn has_viewport_percentage(&self) -> bool {
        match *self {
            Image::Gradient(ref gradient) => gradient.has_viewport_percentage(),
            _ => false,
        }
    }
}

impl<D, L, LoP, P, C> ToCss for Gradient<D, L, LoP, P, C>
    where D: LineDirection, L: ToCss, LoP: ToCss, P: ToCss, C: ToCss,
{
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        if self.compat_mode == CompatMode::WebKit {
            dest.write_str("-webkit-")?;
        }
        if self.repeating {
            dest.write_str("repeating-")?;
        }
        dest.write_str(self.kind.label())?;
        dest.write_str("-gradient(")?;
        let mut skip_comma = match self.kind {
            GradientKind::Linear(ref direction) if direction.points_downwards() => true,
            GradientKind::Linear(ref direction) => {
                direction.to_css(dest, self.compat_mode)?;
                false
            },
            GradientKind::Radial(ref shape, ref position) => {
                let omit_shape = match *shape {
                    EndingShape::Ellipse(Ellipse::Extent(ShapeExtent::Cover)) |
                    EndingShape::Ellipse(Ellipse::Extent(ShapeExtent::FarthestCorner)) => {
                        true
                    },
                    _ => false,
                };
                if self.compat_mode == CompatMode::Modern {
                    if !omit_shape {
                        shape.to_css(dest)?;
                        dest.write_str(" ")?;
                    }
                    dest.write_str("at ")?;
                    position.to_css(dest)?;
                } else {
                    position.to_css(dest)?;
                    if !omit_shape {
                        dest.write_str(", ")?;
                        shape.to_css(dest)?;
                    }
                }
                false
            },
        };
        for item in &self.items {
            if !skip_comma {
                dest.write_str(", ")?;
            }
            skip_comma = false;
            item.to_css(dest)?;
        }
        dest.write_str(")")
    }
}

impl<D, L, LoP, P> GradientKind<D, L, LoP, P> {
    fn label(&self) -> &str {
        match *self {
            GradientKind::Linear(..) => "linear",
            GradientKind::Radial(..) => "radial",
        }
    }
}

/// The direction of a linear gradient.
pub trait LineDirection {
    /// Whether this direction points towards, and thus can be omitted.
    fn points_downwards(&self) -> bool;

    /// Serialises this direction according to the compatibility mode.
    fn to_css<W>(&self, dest: &mut W, compat_mode: CompatMode) -> fmt::Result
        where W: fmt::Write;
}

impl<L> ToCss for Circle<L>
where
    L: ToCss,
{
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
    where
        W: fmt::Write,
    {
        match *self {
            Circle::Extent(ShapeExtent::FarthestCorner) |
            Circle::Extent(ShapeExtent::Cover) => {
                dest.write_str("circle")
            },
            Circle::Extent(keyword) => {
                dest.write_str("circle ")?;
                keyword.to_css(dest)
            },
            Circle::Radius(ref length) => {
                length.to_css(dest)
            },
        }
    }
}

impl<C, L> fmt::Debug for ColorStop<C, L>
    where C: fmt::Debug, L: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self.color)?;
        if let Some(ref pos) = self.position {
            write!(f, " {:?}", pos)?;
        }
        Ok(())
    }
}

impl<C, L> ToCss for ColorStop<C, L>
    where C: ToCss, L: ToCss,
{
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        self.color.to_css(dest)?;
        if let Some(ref position) = self.position {
            dest.write_str(" ")?;
            position.to_css(dest)?;
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>extern crate byteorder;

use std::mem;
use std::ops;
use std::borrow::{Borrow, BorrowMut, ToOwned};
use std::io::{BufReader};
use byteorder::{ByteOrder, LittleEndian, ReadBytesExt};

use ::slice::Slice;
// use ::OggPage;

#[derive(Debug)]
pub enum VorbisHeaderCheckError {
    BadCapture,
    BadVersion,
    BadIdentificationHeader,
    BadIdentificationHeaderLength,
    NotAnIdentificationHeader,
    HeaderNotImplemented,
}

#[derive(Debug, PartialEq)]
pub enum VorbisHeaderType {
    Audio,
    IdentificationHeader,
    CommentHeader,
    SetupHeader,
}

impl VorbisHeaderType {
    pub fn from_u8(n: u8) -> Option<VorbisHeaderType> {
        match n {
            0 => Some(VorbisHeaderType::Audio),
            1 => Some(VorbisHeaderType::IdentificationHeader),
            3 => Some(VorbisHeaderType::CommentHeader),
            5 => Some(VorbisHeaderType::SetupHeader),
            _ => None
        }
    }
}

pub struct VorbisHeaderBuf {
    inner: Vec<u8>,
}

pub struct VorbisHeader {
    inner: Slice,
}

impl ops::Deref for VorbisHeaderBuf {
    type Target = VorbisHeader;

    fn deref<'a>(&'a self) -> &'a VorbisHeader {
        VorbisHeader::from_u8_slice_unchecked(&self.inner)
    }
}

impl Borrow<VorbisHeader> for VorbisHeaderBuf {
    fn borrow(&self) -> &VorbisHeader {
        VorbisHeader::from_u8_slice_unchecked(&self.inner)
    }
}

impl BorrowMut<VorbisHeader> for VorbisHeaderBuf {
    fn borrow_mut(&mut self) -> &mut VorbisHeader {
        VorbisHeader::from_u8_slice_unchecked_mut(&mut self.inner)
    }
}

impl ToOwned for VorbisHeader {
    type Owned = VorbisHeaderBuf;

    fn to_owned(&self) -> VorbisHeaderBuf {
        VorbisHeaderBuf { inner: self.inner.to_owned() }
    }
}

impl VorbisHeader {
    pub fn new(buf: &[u8]) -> Result<&VorbisHeader, VorbisHeaderCheckError> {
        try!(VorbisHeader::check(buf));
        Ok(VorbisHeader::from_u8_slice_unchecked(buf))
    }

    pub fn new_mut(buf: &mut [u8]) -> Result<&mut VorbisHeader, VorbisHeaderCheckError> {
        try!(VorbisHeader::check(buf));
        Ok(VorbisHeader::from_u8_slice_unchecked_mut(buf))
    }

    // The following (private!) function allows unchecked construction of a
    // ogg page from a u8 slice.
    fn from_u8_slice_unchecked(s: &[u8]) -> &VorbisHeader {
        unsafe { mem::transmute(s) }
    }

    // The following (private!) function allows unchecked construction of a
    // mutable ogg page from a mutable u8 slice.
    fn from_u8_slice_unchecked_mut(s: &mut [u8]) -> &mut VorbisHeader {
        unsafe { mem::transmute(s) }
    }

    pub fn as_u8_slice(&self) -> &[u8] {
        unsafe { mem::transmute(self) }
    }

    fn as_u8_slice_mut(&mut self) -> &mut [u8] {
        unsafe { mem::transmute(self) }
    }

    pub fn check(buf: &[u8]) -> Result<(), VorbisHeaderCheckError> {
        if buf.len() < 8 || &buf[1 .. 7] != b"vorbis" {
            return Err(VorbisHeaderCheckError::BadCapture)
        }

        match VorbisHeaderType::from_u8(buf[0]) {
            None => {
                return Err(VorbisHeaderCheckError::BadCapture)
            },
            Some(VorbisHeaderType::IdentificationHeader) => {
                try!(VorbisHeader::parse_identification_header(buf));
                ()
            },
            _ => {}
        }

        Ok(())
    }

    // pub fn from_page(page: &OggPage) -> Result<VorbisHeader, VorbisHeaderCheckError> {
    //     // page.packets(packets)
    //     unimplemented!();
    // }

    fn parse_identification_header(buf: &[u8]) -> Result<IdentificationHeader, VorbisHeaderCheckError> {
        if VorbisHeaderType::from_u8(buf[0]).unwrap() != VorbisHeaderType::IdentificationHeader {
            return Err(VorbisHeaderCheckError::NotAnIdentificationHeader)
        }

        if buf.len() < 30 {
            return Err(VorbisHeaderCheckError::BadIdentificationHeaderLength)
        }

        let vorbis_version = LittleEndian::read_u32(&buf[7 .. 11]);
        let audio_channels = buf[11];
        let audio_sample_rate = LittleEndian::read_u32(&buf[12 .. 16]);

        if audio_channels <= 0 || audio_sample_rate <= 0 {
            // vorbis_version should = 0 to meet Vorbis I specification but it's not checked here
            return Err(VorbisHeaderCheckError::BadIdentificationHeader)
        }

        let bitrate_maximum = LittleEndian::read_u32(&buf[16 .. 20]);
        let bitrate_nominal = LittleEndian::read_u32(&buf[20 .. 24]);
        let bitrate_minimum = LittleEndian::read_u32(&buf[24 .. 28]);

        let blocksize_byte = buf[28];
        let blocksize_0 = blocksize_byte & 0b00001111;
        let blocksize_1 = blocksize_byte >> 4;

        if blocksize_0 > blocksize_1 || buf[29] & 1 != 1 {
            // If blocksize 0 > blocksize 1 the file is undecodable
            // If framing flag is missing, the file is undecodable
            return Err(VorbisHeaderCheckError::BadIdentificationHeader)
        }

        // It appears framing_flag takes up a byte by itself so buffer is useless
        // let buffer = framing_byte & 0b01111111;

        Ok(IdentificationHeader {
            vorbis_version: vorbis_version,
            audio_channels: audio_channels,
            audio_sample_rate: audio_sample_rate,
            bitrate_maximum: bitrate_maximum,
            bitrate_nominal: bitrate_nominal,
            bitrate_minimum: bitrate_minimum,
            blocksize_0: blocksize_0,
            blocksize_1: blocksize_1,
        })
    }

    pub fn identification_header(&self) -> Option<IdentificationHeader> {
        match VorbisHeader::parse_identification_header(self.as_u8_slice()) {
            Ok(header) => Some(header),
            Err(VorbisHeaderCheckError::NotAnIdentificationHeader) => None,
            Err(_) => panic!("identification header parse error: this shouldn't happen")
        }
    }
}

struct IdentificationHeader {
    vorbis_version: u32,
    audio_channels: u8,
    audio_sample_rate: u32,
    bitrate_maximum: u32,
    bitrate_nominal: u32,
    bitrate_minimum: u32,
    blocksize_0: u8,
    blocksize_1: u8,
}

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

    #[test]
    fn test_parse_identification_header() {
        // [packettype]["vorbis"][version][channels]
        // [sample_rate]
        // [bitrate_maximum]
        // [bitrate_nominal]
        // [bitrate_minimum]
        // [blocksize_0][blocksize_1][framing_flag]
        let header_buf = [
            0x01,                               // 0     packet type, 1 = id header
            0x76, 0x6f, 0x72, 0x62, 0x69, 0x73, // 1-6   vorbis
            0x00, 0x00, 0x00, 0x00,             // 7-10  version
            0x02,                               // 11    channels
            0x80, 0xbb, 0x00, 0x00,             // 12-15 sample_rate (48000)
            0x00, 0x00, 0x00, 0x00,             // 16-19 bitrate_minimum
            0x80, 0xb5, 0x01, 0x00,             // 20-23 bitrate_nominal
            0x00, 0x00, 0x00, 0x00,             // 24-27 bitrate_maximum
            0xb8,                               // 28    [blocksize_0][blocksize_1]
            0x01                                // 29    framing_flag
        ];

        let test_header = VorbisHeader::new(&header_buf).unwrap();
        let id_header = test_header.identification_header().unwrap();

        assert_eq!(id_header.vorbis_version, 0);
        assert_eq!(id_header.audio_channels, 2);
        assert_eq!(id_header.audio_sample_rate, 48000);
        assert_eq!(id_header.bitrate_maximum, 0);
        assert_eq!(id_header.bitrate_nominal, 112000);
        assert_eq!(id_header.bitrate_minimum, 0);
        assert_eq!(id_header.blocksize_0, 0b1000);
        assert_eq!(id_header.blocksize_1, 0b1011);
    }

    #[test]
    fn test_parse_non_identification_headers() {
        let not_an_id_header_buf = [
            0x00,
            0x76, 0x6f, 0x72, 0x62, 0x69, 0x73,
            0x00, 0x00, 0x00, 0x00,
        ];

        let negative_test_header = VorbisHeader::new(&not_an_id_header_buf).unwrap();
        let negative_id_header = negative_test_header.identification_header();
        assert!(negative_id_header.is_none());
    }

    #[test]
    fn test_parse_malformed_identification_header() {
        let malformed_header_buf = [0x01, 0x76, 0x6f, 0x72, 0x62, 0x69, 0x73];
        let malformed_test_header = VorbisHeader::new(&malformed_header_buf);
        assert!(malformed_test_header.is_err());
    }
}
<commit_msg>Remove HeaderNotImplemented from VorbisHeaderCheckError enum<commit_after>extern crate byteorder;

use std::mem;
use std::ops;
use std::borrow::{Borrow, BorrowMut, ToOwned};
use std::io::{BufReader};
use byteorder::{ByteOrder, LittleEndian, ReadBytesExt};

use ::slice::Slice;
// use ::OggPage;

#[derive(Debug)]
pub enum VorbisHeaderCheckError {
    BadCapture,
    BadVersion,
    BadIdentificationHeader,
    BadIdentificationHeaderLength,
    NotAnIdentificationHeader,
}

#[derive(Debug, PartialEq)]
pub enum VorbisHeaderType {
    Audio,
    IdentificationHeader,
    CommentHeader,
    SetupHeader,
}

impl VorbisHeaderType {
    pub fn from_u8(n: u8) -> Option<VorbisHeaderType> {
        match n {
            0 => Some(VorbisHeaderType::Audio),
            1 => Some(VorbisHeaderType::IdentificationHeader),
            3 => Some(VorbisHeaderType::CommentHeader),
            5 => Some(VorbisHeaderType::SetupHeader),
            _ => None
        }
    }
}

pub struct VorbisHeaderBuf {
    inner: Vec<u8>,
}

pub struct VorbisHeader {
    inner: Slice,
}

impl ops::Deref for VorbisHeaderBuf {
    type Target = VorbisHeader;

    fn deref<'a>(&'a self) -> &'a VorbisHeader {
        VorbisHeader::from_u8_slice_unchecked(&self.inner)
    }
}

impl Borrow<VorbisHeader> for VorbisHeaderBuf {
    fn borrow(&self) -> &VorbisHeader {
        VorbisHeader::from_u8_slice_unchecked(&self.inner)
    }
}

impl BorrowMut<VorbisHeader> for VorbisHeaderBuf {
    fn borrow_mut(&mut self) -> &mut VorbisHeader {
        VorbisHeader::from_u8_slice_unchecked_mut(&mut self.inner)
    }
}

impl ToOwned for VorbisHeader {
    type Owned = VorbisHeaderBuf;

    fn to_owned(&self) -> VorbisHeaderBuf {
        VorbisHeaderBuf { inner: self.inner.to_owned() }
    }
}

impl VorbisHeader {
    pub fn new(buf: &[u8]) -> Result<&VorbisHeader, VorbisHeaderCheckError> {
        try!(VorbisHeader::check(buf));
        Ok(VorbisHeader::from_u8_slice_unchecked(buf))
    }

    pub fn new_mut(buf: &mut [u8]) -> Result<&mut VorbisHeader, VorbisHeaderCheckError> {
        try!(VorbisHeader::check(buf));
        Ok(VorbisHeader::from_u8_slice_unchecked_mut(buf))
    }

    // The following (private!) function allows unchecked construction of a
    // ogg page from a u8 slice.
    fn from_u8_slice_unchecked(s: &[u8]) -> &VorbisHeader {
        unsafe { mem::transmute(s) }
    }

    // The following (private!) function allows unchecked construction of a
    // mutable ogg page from a mutable u8 slice.
    fn from_u8_slice_unchecked_mut(s: &mut [u8]) -> &mut VorbisHeader {
        unsafe { mem::transmute(s) }
    }

    pub fn as_u8_slice(&self) -> &[u8] {
        unsafe { mem::transmute(self) }
    }

    fn as_u8_slice_mut(&mut self) -> &mut [u8] {
        unsafe { mem::transmute(self) }
    }

    pub fn check(buf: &[u8]) -> Result<(), VorbisHeaderCheckError> {
        if buf.len() < 8 || &buf[1 .. 7] != b"vorbis" {
            return Err(VorbisHeaderCheckError::BadCapture)
        }

        match VorbisHeaderType::from_u8(buf[0]) {
            None => {
                return Err(VorbisHeaderCheckError::BadCapture)
            },
            Some(VorbisHeaderType::IdentificationHeader) => {
                try!(VorbisHeader::parse_identification_header(buf));
                ()
            },
            _ => {}
        }

        Ok(())
    }

    // pub fn from_page(page: &OggPage) -> Result<VorbisHeader, VorbisHeaderCheckError> {
    //     // page.packets(packets)
    //     unimplemented!();
    // }

    fn parse_identification_header(buf: &[u8]) -> Result<IdentificationHeader, VorbisHeaderCheckError> {
        if VorbisHeaderType::from_u8(buf[0]).unwrap() != VorbisHeaderType::IdentificationHeader {
            return Err(VorbisHeaderCheckError::NotAnIdentificationHeader)
        }

        if buf.len() < 30 {
            return Err(VorbisHeaderCheckError::BadIdentificationHeaderLength)
        }

        let vorbis_version = LittleEndian::read_u32(&buf[7 .. 11]);
        let audio_channels = buf[11];
        let audio_sample_rate = LittleEndian::read_u32(&buf[12 .. 16]);

        if audio_channels <= 0 || audio_sample_rate <= 0 {
            // vorbis_version should = 0 to meet Vorbis I specification but it's not checked here
            return Err(VorbisHeaderCheckError::BadIdentificationHeader)
        }

        let bitrate_maximum = LittleEndian::read_u32(&buf[16 .. 20]);
        let bitrate_nominal = LittleEndian::read_u32(&buf[20 .. 24]);
        let bitrate_minimum = LittleEndian::read_u32(&buf[24 .. 28]);

        let blocksize_byte = buf[28];
        let blocksize_0 = blocksize_byte & 0b00001111;
        let blocksize_1 = blocksize_byte >> 4;

        if blocksize_0 > blocksize_1 || buf[29] & 1 != 1 {
            // If blocksize 0 > blocksize 1 the file is undecodable
            // If framing flag is missing, the file is undecodable
            return Err(VorbisHeaderCheckError::BadIdentificationHeader)
        }

        // It appears framing_flag takes up a byte by itself so buffer is useless
        // let buffer = framing_byte & 0b01111111;

        Ok(IdentificationHeader {
            vorbis_version: vorbis_version,
            audio_channels: audio_channels,
            audio_sample_rate: audio_sample_rate,
            bitrate_maximum: bitrate_maximum,
            bitrate_nominal: bitrate_nominal,
            bitrate_minimum: bitrate_minimum,
            blocksize_0: blocksize_0,
            blocksize_1: blocksize_1,
        })
    }

    pub fn identification_header(&self) -> Option<IdentificationHeader> {
        match VorbisHeader::parse_identification_header(self.as_u8_slice()) {
            Ok(header) => Some(header),
            Err(VorbisHeaderCheckError::NotAnIdentificationHeader) => None,
            Err(_) => panic!("identification header parse error: this shouldn't happen")
        }
    }
}

struct IdentificationHeader {
    vorbis_version: u32,
    audio_channels: u8,
    audio_sample_rate: u32,
    bitrate_maximum: u32,
    bitrate_nominal: u32,
    bitrate_minimum: u32,
    blocksize_0: u8,
    blocksize_1: u8,
}

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

    #[test]
    fn test_parse_identification_header() {
        let header_buf = [
            0x01,                               // 0     packet type, 1 = id header
            0x76, 0x6f, 0x72, 0x62, 0x69, 0x73, // 1-6   vorbis
            0x00, 0x00, 0x00, 0x00,             // 7-10  version
            0x02,                               // 11    channels
            0x80, 0xbb, 0x00, 0x00,             // 12-15 sample_rate (48000)
            0x00, 0x00, 0x00, 0x00,             // 16-19 bitrate_minimum
            0x80, 0xb5, 0x01, 0x00,             // 20-23 bitrate_nominal
            0x00, 0x00, 0x00, 0x00,             // 24-27 bitrate_maximum
            0xb8,                               // 28    [blocksize_0][blocksize_1]
            0x01                                // 29    framing_flag
        ];

        let test_header = VorbisHeader::new(&header_buf).unwrap();
        let id_header = test_header.identification_header().unwrap();

        assert_eq!(id_header.vorbis_version, 0);
        assert_eq!(id_header.audio_channels, 2);
        assert_eq!(id_header.audio_sample_rate, 48000);
        assert_eq!(id_header.bitrate_maximum, 0);
        assert_eq!(id_header.bitrate_nominal, 112000);
        assert_eq!(id_header.bitrate_minimum, 0);
        assert_eq!(id_header.blocksize_0, 0b1000);
        assert_eq!(id_header.blocksize_1, 0b1011);
    }

    #[test]
    fn test_parse_non_identification_headers() {
        let not_an_id_header_buf = [
            0x00,
            0x76, 0x6f, 0x72, 0x62, 0x69, 0x73,
            0x00, 0x00, 0x00, 0x00,
        ];

        let negative_test_header = VorbisHeader::new(&not_an_id_header_buf).unwrap();
        let negative_id_header = negative_test_header.identification_header();
        assert!(negative_id_header.is_none());
    }

    #[test]
    fn test_parse_malformed_identification_header() {
        let malformed_header_buf = [0x01, 0x76, 0x6f, 0x72, 0x62, 0x69, 0x73];
        let malformed_test_header = VorbisHeader::new(&malformed_header_buf);
        assert!(malformed_test_header.is_err());
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

#[no_mangle]
pub extern "C" fn acos(n: f64) -> f64 {
	libm::acos(n)
}

#[no_mangle]
pub extern "C" fn acosf(n: f32) -> f32 {
	libm::acosf(n)
}

#[no_mangle]
pub extern "C" fn acosh(x: f64) -> f64 {
	libm::acosh(x)
}

#[no_mangle]
pub extern "C" fn acoshf(x: f32) -> f32 {
	libm::acoshf(x)
}

#[no_mangle]
pub extern "C" fn asin(n: f64) -> f64 {
	libm::asin(n)
}

#[no_mangle]
pub extern "C" fn asinf(n: f32) -> f32 {
	libm::asinf(n)
}

#[no_mangle]
pub extern "C" fn asinh(x: f64) -> f64 {
	libm::asinh(x)
}

#[no_mangle]
pub extern "C" fn asinhf(x: f32) -> f32 {
	libm::asinhf(x)
}

#[no_mangle]
pub extern "C" fn atan(n: f64) -> f64 {
	libm::atan(n)
}

#[no_mangle]
pub extern "C" fn atan2(a: f64, b: f64) -> f64 {
	libm::atan2(a, b)
}

pub extern "C" fn atan2f(a: f32, b: f32) -> f32 {
	libm::atan2f(a, b)
}

#[no_mangle]
pub extern "C" fn atanf(n: f32) -> f32 {
	libm::atanf(n)
}

#[no_mangle]
pub extern "C" fn cbrt(n: f64) -> f64 {
	libm::cbrt(n)
}

#[no_mangle]
pub extern "C" fn cbrtf(n: f32) -> f32 {
	libm::cbrtf(n)
}

#[no_mangle]
pub extern "C" fn ceil(x: f64) -> f64 {
	libm::ceil(x)
}

#[no_mangle]
pub extern "C" fn ceilf(x: f32) -> f32 {
	libm::ceilf(x)
}

#[no_mangle]
pub extern "C" fn cos(x: f64) -> f64 {
	libm::cos(x)
}

#[no_mangle]
pub extern "C" fn cosf(x: f32) -> f32 {
	libm::cosf(x)
}

#[no_mangle]
pub extern "C" fn cosh(x: f64) -> f64 {
	libm::cosh(x)
}

#[no_mangle]
pub extern "C" fn coshf(x: f32) -> f32 {
	libm::coshf(x)
}

#[no_mangle]
pub extern "C" fn exp(x: f64) -> f64 {
	libm::exp(x)
}

#[no_mangle]
pub extern "C" fn expf(x: f32) -> f32 {
	libm::expf(x)
}

#[no_mangle]
pub extern "C" fn expm1(n: f64) -> f64 {
	libm::expm1(n)
}

#[no_mangle]
pub extern "C" fn expm1f(n: f32) -> f32 {
	libm::expm1f(n)
}

#[no_mangle]
pub extern "C" fn fdim(a: f64, b: f64) -> f64 {
	libm::fdim(a, b)
}

#[no_mangle]
pub extern "C" fn fdimf(a: f32, b: f32) -> f32 {
	libm::fdimf(a, b)
}

#[no_mangle]
pub extern "C" fn hypot(x: f64, y: f64) -> f64 {
	libm::hypot(x, y)
}

#[no_mangle]
pub extern "C" fn hypotf(x: f32, y: f32) -> f32 {
	libm::hypotf(x, y)
}

#[no_mangle]
pub extern "C" fn log(x: f64) -> f64 {
	libm::log(x)
}

pub fn logf(x: f32) -> f32 {
	libm::logf(x)
}

#[no_mangle]
pub extern "C" fn log1p(n: f64) -> f64 {
	libm::log1p(n)
}

#[no_mangle]
pub extern "C" fn log1pf(n: f32) -> f32 {
	libm::log1pf(n)
}

#[no_mangle]
pub extern "C" fn sinh(n: f64) -> f64 {
	libm::sinh(n)
}

#[no_mangle]
pub extern "C" fn sinhf(n: f32) -> f32 {
	libm::sinhf(n)
}

#[no_mangle]
pub extern "C" fn sqrt(x: f64) -> f64 {
	libm::sqrt(x)
}

#[no_mangle]
pub extern "C" fn sqrtf(x: f32) -> f32 {
	libm::sqrtf(x)
}

#[no_mangle]
pub extern "C" fn tan(n: f64) -> f64 {
	libm::tan(n)
}

#[no_mangle]
pub extern "C" fn tanf(n: f32) -> f32 {
	libm::tanf(n)
}

#[no_mangle]
pub extern "C" fn tanh(n: f64) -> f64 {
	libm::tanh(n)
}

#[no_mangle]
pub extern "C" fn tanhf(n: f32) -> f32 {
	libm::tanhf(n)
}
<commit_msg>add missing #[no_mangle]<commit_after>#![allow(dead_code)]

#[no_mangle]
pub extern "C" fn acos(n: f64) -> f64 {
	libm::acos(n)
}

#[no_mangle]
pub extern "C" fn acosf(n: f32) -> f32 {
	libm::acosf(n)
}

#[no_mangle]
pub extern "C" fn acosh(x: f64) -> f64 {
	libm::acosh(x)
}

#[no_mangle]
pub extern "C" fn acoshf(x: f32) -> f32 {
	libm::acoshf(x)
}

#[no_mangle]
pub extern "C" fn asin(n: f64) -> f64 {
	libm::asin(n)
}

#[no_mangle]
pub extern "C" fn asinf(n: f32) -> f32 {
	libm::asinf(n)
}

#[no_mangle]
pub extern "C" fn asinh(x: f64) -> f64 {
	libm::asinh(x)
}

#[no_mangle]
pub extern "C" fn asinhf(x: f32) -> f32 {
	libm::asinhf(x)
}

#[no_mangle]
pub extern "C" fn atan(n: f64) -> f64 {
	libm::atan(n)
}

#[no_mangle]
pub extern "C" fn atan2(a: f64, b: f64) -> f64 {
	libm::atan2(a, b)
}

#[no_mangle]
pub extern "C" fn atan2f(a: f32, b: f32) -> f32 {
	libm::atan2f(a, b)
}

#[no_mangle]
pub extern "C" fn atanf(n: f32) -> f32 {
	libm::atanf(n)
}

#[no_mangle]
pub extern "C" fn cbrt(n: f64) -> f64 {
	libm::cbrt(n)
}

#[no_mangle]
pub extern "C" fn cbrtf(n: f32) -> f32 {
	libm::cbrtf(n)
}

#[no_mangle]
pub extern "C" fn ceil(x: f64) -> f64 {
	libm::ceil(x)
}

#[no_mangle]
pub extern "C" fn ceilf(x: f32) -> f32 {
	libm::ceilf(x)
}

#[no_mangle]
pub extern "C" fn cos(x: f64) -> f64 {
	libm::cos(x)
}

#[no_mangle]
pub extern "C" fn cosf(x: f32) -> f32 {
	libm::cosf(x)
}

#[no_mangle]
pub extern "C" fn cosh(x: f64) -> f64 {
	libm::cosh(x)
}

#[no_mangle]
pub extern "C" fn coshf(x: f32) -> f32 {
	libm::coshf(x)
}

#[no_mangle]
pub extern "C" fn exp(x: f64) -> f64 {
	libm::exp(x)
}

#[no_mangle]
pub extern "C" fn expf(x: f32) -> f32 {
	libm::expf(x)
}

#[no_mangle]
pub extern "C" fn expm1(n: f64) -> f64 {
	libm::expm1(n)
}

#[no_mangle]
pub extern "C" fn expm1f(n: f32) -> f32 {
	libm::expm1f(n)
}

#[no_mangle]
pub extern "C" fn fdim(a: f64, b: f64) -> f64 {
	libm::fdim(a, b)
}

#[no_mangle]
pub extern "C" fn fdimf(a: f32, b: f32) -> f32 {
	libm::fdimf(a, b)
}

#[no_mangle]
pub extern "C" fn hypot(x: f64, y: f64) -> f64 {
	libm::hypot(x, y)
}

#[no_mangle]
pub extern "C" fn hypotf(x: f32, y: f32) -> f32 {
	libm::hypotf(x, y)
}

#[no_mangle]
pub extern "C" fn log(x: f64) -> f64 {
	libm::log(x)
}

#[no_mangle]
pub extern "C" fn logf(x: f32) -> f32 {
	libm::logf(x)
}

#[no_mangle]
pub extern "C" fn log1p(n: f64) -> f64 {
	libm::log1p(n)
}

#[no_mangle]
pub extern "C" fn log1pf(n: f32) -> f32 {
	libm::log1pf(n)
}

#[no_mangle]
pub extern "C" fn sinh(n: f64) -> f64 {
	libm::sinh(n)
}

#[no_mangle]
pub extern "C" fn sinhf(n: f32) -> f32 {
	libm::sinhf(n)
}

#[no_mangle]
pub extern "C" fn sqrt(x: f64) -> f64 {
	libm::sqrt(x)
}

#[no_mangle]
pub extern "C" fn sqrtf(x: f32) -> f32 {
	libm::sqrtf(x)
}

#[no_mangle]
pub extern "C" fn tan(n: f64) -> f64 {
	libm::tan(n)
}

#[no_mangle]
pub extern "C" fn tanf(n: f32) -> f32 {
	libm::tanf(n)
}

#[no_mangle]
pub extern "C" fn tanh(n: f64) -> f64 {
	libm::tanh(n)
}

#[no_mangle]
pub extern "C" fn tanhf(n: f32) -> f32 {
	libm::tanhf(n)
}
<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

#![deny(
    non_camel_case_types,
    non_snake_case,
    path_statements,
    trivial_numeric_casts,
    unstable_features,
    unused_allocation,
    unused_import_braces,
    unused_imports,
    unused_must_use,
    unused_mut,
    unused_qualifications,
    while_true,
)]

#[macro_use] extern crate log;
extern crate clap;
#[macro_use] extern crate semver;
extern crate toml;
extern crate url;
#[macro_use] extern crate version;

extern crate libimagentrylink;
extern crate libimagrt;
extern crate libimagstore;
extern crate libimagerror;
extern crate libimagutil;

use std::ops::Deref;

use libimagrt::runtime::Runtime;
use libimagrt::setup::generate_runtime_setup;
use libimagstore::error::StoreError;
use libimagstore::store::Entry;
use libimagstore::store::FileLockEntry;
use libimagstore::store::Store;
use libimagerror::trace::{MapErrTrace, trace_error, trace_error_exit};
use libimagentrylink::external::ExternalLinker;
use libimagutil::warn_result::*;
use libimagutil::warn_exit::warn_exit;
use libimagutil::info_result::*;
use clap::ArgMatches;
use url::Url;

mod ui;

use ui::build_ui;

fn main() {
    let rt = generate_runtime_setup("imag-link",
                                    &version!()[..],
                                    "Link entries",
                                    build_ui);

    rt.cli()
        .subcommand_name()
        .map(|name| {
            match name {
                "internal" => handle_internal_linking(&rt),
                "external" => handle_external_linking(&rt),
                _ => warn_exit("No commandline call", 1)
            }
        });
}

fn handle_internal_linking(rt: &Runtime) {
    use libimagentrylink::internal::InternalLinker;

    debug!("Handle internal linking call");
    let cmd = rt.cli().subcommand_matches("internal").unwrap();

    match cmd.value_of("list") {
        Some(list) => {
            debug!("List...");
            for entry in list.split(',') {
                debug!("Listing for '{}'", entry);
                match get_entry_by_name(rt, entry) {
                    Ok(Some(e)) => {
                        e.get_internal_links()
                            .map(|links| {
                                let i = links
                                    .filter_map(|l| {
                                        l.to_str()
                                            .map_warn_err(|e| format!("Failed to convert StoreId to string: {:?}", e))
                                            .ok()
                                    })
                                    .enumerate();

                                for (i, link) in i {
                                    println!("{: <3}: {}", i, link);
                                }
                            })
                            .map_err_trace()
                            .ok();
                    },

                    Ok(None) => {
                        warn!("Entry not found: {:?}", entry);
                        break;
                    }

                    Err(e) => {
                        trace_error(&e);
                        break;
                    },
                }
            }
            debug!("Listing ready!");
        },
        None => {
            let mut from = match get_from_entry(&rt) {
                None => warn_exit("No 'from' entry", 1),
                Some(s) => s,
            };
            debug!("Link from = {:?}", from.deref());

            let to = match get_to_entries(&rt) {
                None => warn_exit("No 'to' entry", 1),
                Some(to) => to,
            };
            debug!("Link to = {:?}", to.iter().map(|f| f.deref()).collect::<Vec<&Entry>>());

            match cmd.subcommand_name() {
                Some("add") => {
                    for mut to_entry in to {
                        if let Err(e) = to_entry.add_internal_link(&mut from) {
                            trace_error_exit(&e, 1);
                        }
                    }
                },

                Some("remove") => {
                    for mut to_entry in to {
                        if let Err(e) = to_entry.remove_internal_link(&mut from) {
                            trace_error_exit(&e, 1);
                        }
                    }
                },

                _ => unreachable!(),
            };
        }
    }
}

fn get_from_entry<'a>(rt: &'a Runtime) -> Option<FileLockEntry<'a>> {
    rt.cli()
        .subcommand_matches("internal")
        .unwrap() // safe, we know there is an "internal" subcommand"
        .subcommand_matches("add")
        .unwrap() // safe, we know there is an "add" subcommand
        .value_of("from")
        .and_then(|from_name| {
            match get_entry_by_name(rt, from_name) {
                Err(e) => {
                    debug!("We couldn't get the entry from name: '{:?}'", from_name);
                    trace_error(&e); None
                },
                Ok(Some(e)) => Some(e),
                Ok(None)    => None,
            }

        })
}

fn get_to_entries<'a>(rt: &'a Runtime) -> Option<Vec<FileLockEntry<'a>>> {
    rt.cli()
        .subcommand_matches("internal")
        .unwrap() // safe, we know there is an "internal" subcommand"
        .subcommand_matches("add")
        .unwrap() // safe, we know there is an "add" subcommand
        .values_of("to")
        .map(|values| {
            let mut v = vec![];
            for entry in values.map(|v| get_entry_by_name(rt, v)) {
                match entry {
                    Err(e) => trace_error(&e),
                    Ok(Some(e)) => v.push(e),
                    Ok(None) => warn!("Entry not found: {:?}", v),
                }
            }
            v
        })
}

fn get_entry_by_name<'a>(rt: &'a Runtime, name: &str) -> Result<Option<FileLockEntry<'a>>, StoreError> {
    use std::path::PathBuf;
    use libimagstore::storeid::StoreId;

    StoreId::new(Some(rt.store().path().clone()), PathBuf::from(name))
        .and_then(|id| rt.store().get(id))
}

fn handle_external_linking(rt: &Runtime) {
    let scmd       = rt.cli().subcommand_matches("external").unwrap();
    let entry_name = scmd.value_of("id").unwrap(); // enforced by clap
    let entry      = get_entry_by_name(rt, entry_name);
    if entry.is_err() {
        trace_error_exit(&entry.unwrap_err(), 1);
    }
    let entry = entry.unwrap();
    if entry.is_none() {
        warn!("Entry not found: {:?}", entry_name);
        return;
    }
    let mut entry = entry.unwrap();

    if scmd.is_present("add") {
        debug!("Adding link to entry!");
        add_link_to_entry(rt.store(), scmd, &mut entry);
        return;
    }

    if scmd.is_present("remove") {
        debug!("Removing link from entry!");
        remove_link_from_entry(rt.store(), scmd, &mut entry);
        return;
    }

    if scmd.is_present("set") {
        debug!("Setting links in entry!");
        set_links_for_entry(rt.store(), scmd, &mut entry);
        return;
    }

    if scmd.is_present("list") {
        debug!("Listing links in entry!");
        list_links_for_entry(rt.store(), &mut entry);
        return;
    }

    panic!("Clap failed to enforce one of 'add', 'remove', 'set' or 'list'");
}

fn add_link_to_entry(store: &Store, matches: &ArgMatches, entry: &mut FileLockEntry) {
    Url::parse(matches.value_of("add").unwrap())
        .map_err_trace_exit(1)
        .map(|link| entry.add_external_link(store, link).map_err_trace().map_info_str("Ok"))
        .ok();
}

fn remove_link_from_entry(store: &Store, matches: &ArgMatches, entry: &mut FileLockEntry) {
    Url::parse(matches.value_of("remove").unwrap())
        .map_err_trace_exit(1)
        .map(|link| entry.remove_external_link(store, link).map_err_trace().map_info_str("Ok"))
        .ok();
}

fn set_links_for_entry(store: &Store, matches: &ArgMatches, entry: &mut FileLockEntry) {
    let links = matches
        .value_of("links")
        .map(String::from)
        .unwrap()
        .split(',')
        .map(|uri| {
            match Url::parse(uri) {
                Err(e) => {
                    warn!("Could not parse '{}' as URL, ignoring", uri);
                    trace_error(&e);
                    None
                },
                Ok(u) => Some(u),
            }
        })
        .filter_map(|x| x)
        .collect();

    entry.set_external_links(store, links)
        .map_err_trace()
        .map_info_str("Ok")
        .ok();
}

fn list_links_for_entry(store: &Store, entry: &mut FileLockEntry) {
    entry.get_external_links(store)
        .and_then(|links| {
            for (i, link) in links.enumerate() {
                match link {
                    Ok(link) => println!("{: <3}: {}", i, link),
                    Err(e)   => trace_error(&e),
                }
            }
            Ok(())
        })
        .map_err_trace()
        .map_info_str("Ok")
        .ok();
}

<commit_msg>Rewrite external linking handler function to use less unwrap()<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

#![deny(
    non_camel_case_types,
    non_snake_case,
    path_statements,
    trivial_numeric_casts,
    unstable_features,
    unused_allocation,
    unused_import_braces,
    unused_imports,
    unused_must_use,
    unused_mut,
    unused_qualifications,
    while_true,
)]

#[macro_use] extern crate log;
extern crate clap;
#[macro_use] extern crate semver;
extern crate toml;
extern crate url;
#[macro_use] extern crate version;

extern crate libimagentrylink;
extern crate libimagrt;
extern crate libimagstore;
extern crate libimagerror;
extern crate libimagutil;

use std::ops::Deref;

use libimagrt::runtime::Runtime;
use libimagrt::setup::generate_runtime_setup;
use libimagstore::error::StoreError;
use libimagstore::store::Entry;
use libimagstore::store::FileLockEntry;
use libimagstore::store::Store;
use libimagerror::trace::{MapErrTrace, trace_error, trace_error_exit};
use libimagentrylink::external::ExternalLinker;
use libimagutil::warn_result::*;
use libimagutil::warn_exit::warn_exit;
use libimagutil::info_result::*;
use clap::ArgMatches;
use url::Url;

mod ui;

use ui::build_ui;

fn main() {
    let rt = generate_runtime_setup("imag-link",
                                    &version!()[..],
                                    "Link entries",
                                    build_ui);

    rt.cli()
        .subcommand_name()
        .map(|name| {
            match name {
                "internal" => handle_internal_linking(&rt),
                "external" => handle_external_linking(&rt),
                _ => warn_exit("No commandline call", 1)
            }
        });
}

fn handle_internal_linking(rt: &Runtime) {
    use libimagentrylink::internal::InternalLinker;

    debug!("Handle internal linking call");
    let cmd = rt.cli().subcommand_matches("internal").unwrap();

    match cmd.value_of("list") {
        Some(list) => {
            debug!("List...");
            for entry in list.split(',') {
                debug!("Listing for '{}'", entry);
                match get_entry_by_name(rt, entry) {
                    Ok(Some(e)) => {
                        e.get_internal_links()
                            .map(|links| {
                                let i = links
                                    .filter_map(|l| {
                                        l.to_str()
                                            .map_warn_err(|e| format!("Failed to convert StoreId to string: {:?}", e))
                                            .ok()
                                    })
                                    .enumerate();

                                for (i, link) in i {
                                    println!("{: <3}: {}", i, link);
                                }
                            })
                            .map_err_trace()
                            .ok();
                    },

                    Ok(None) => {
                        warn!("Entry not found: {:?}", entry);
                        break;
                    }

                    Err(e) => {
                        trace_error(&e);
                        break;
                    },
                }
            }
            debug!("Listing ready!");
        },
        None => {
            let mut from = match get_from_entry(&rt) {
                None => warn_exit("No 'from' entry", 1),
                Some(s) => s,
            };
            debug!("Link from = {:?}", from.deref());

            let to = match get_to_entries(&rt) {
                None => warn_exit("No 'to' entry", 1),
                Some(to) => to,
            };
            debug!("Link to = {:?}", to.iter().map(|f| f.deref()).collect::<Vec<&Entry>>());

            match cmd.subcommand_name() {
                Some("add") => {
                    for mut to_entry in to {
                        if let Err(e) = to_entry.add_internal_link(&mut from) {
                            trace_error_exit(&e, 1);
                        }
                    }
                },

                Some("remove") => {
                    for mut to_entry in to {
                        if let Err(e) = to_entry.remove_internal_link(&mut from) {
                            trace_error_exit(&e, 1);
                        }
                    }
                },

                _ => unreachable!(),
            };
        }
    }
}

fn get_from_entry<'a>(rt: &'a Runtime) -> Option<FileLockEntry<'a>> {
    rt.cli()
        .subcommand_matches("internal")
        .unwrap() // safe, we know there is an "internal" subcommand"
        .subcommand_matches("add")
        .unwrap() // safe, we know there is an "add" subcommand
        .value_of("from")
        .and_then(|from_name| {
            match get_entry_by_name(rt, from_name) {
                Err(e) => {
                    debug!("We couldn't get the entry from name: '{:?}'", from_name);
                    trace_error(&e); None
                },
                Ok(Some(e)) => Some(e),
                Ok(None)    => None,
            }

        })
}

fn get_to_entries<'a>(rt: &'a Runtime) -> Option<Vec<FileLockEntry<'a>>> {
    rt.cli()
        .subcommand_matches("internal")
        .unwrap() // safe, we know there is an "internal" subcommand"
        .subcommand_matches("add")
        .unwrap() // safe, we know there is an "add" subcommand
        .values_of("to")
        .map(|values| {
            let mut v = vec![];
            for entry in values.map(|v| get_entry_by_name(rt, v)) {
                match entry {
                    Err(e) => trace_error(&e),
                    Ok(Some(e)) => v.push(e),
                    Ok(None) => warn!("Entry not found: {:?}", v),
                }
            }
            v
        })
}

fn get_entry_by_name<'a>(rt: &'a Runtime, name: &str) -> Result<Option<FileLockEntry<'a>>, StoreError> {
    use std::path::PathBuf;
    use libimagstore::storeid::StoreId;

    StoreId::new(Some(rt.store().path().clone()), PathBuf::from(name))
        .and_then(|id| rt.store().get(id))
}

fn handle_external_linking(rt: &Runtime) {
    let scmd       = rt.cli().subcommand_matches("external").unwrap();
    let entry_name = scmd.value_of("id").unwrap(); // enforced by clap
    let mut entry  = match get_entry_by_name(rt, entry_name) {
        Err(e) => trace_error_exit(&e, 1),
        Ok(None) => {
            warn!("Entry not found: {:?}", entry_name);
            return;
        },
        Ok(Some(entry)) => entry
    };

    if scmd.is_present("add") {
        debug!("Adding link to entry!");
        add_link_to_entry(rt.store(), scmd, &mut entry);
        return;
    }

    if scmd.is_present("remove") {
        debug!("Removing link from entry!");
        remove_link_from_entry(rt.store(), scmd, &mut entry);
        return;
    }

    if scmd.is_present("set") {
        debug!("Setting links in entry!");
        set_links_for_entry(rt.store(), scmd, &mut entry);
        return;
    }

    if scmd.is_present("list") {
        debug!("Listing links in entry!");
        list_links_for_entry(rt.store(), &mut entry);
        return;
    }

    panic!("Clap failed to enforce one of 'add', 'remove', 'set' or 'list'");
}

fn add_link_to_entry(store: &Store, matches: &ArgMatches, entry: &mut FileLockEntry) {
    Url::parse(matches.value_of("add").unwrap())
        .map_err_trace_exit(1)
        .map(|link| entry.add_external_link(store, link).map_err_trace().map_info_str("Ok"))
        .ok();
}

fn remove_link_from_entry(store: &Store, matches: &ArgMatches, entry: &mut FileLockEntry) {
    Url::parse(matches.value_of("remove").unwrap())
        .map_err_trace_exit(1)
        .map(|link| entry.remove_external_link(store, link).map_err_trace().map_info_str("Ok"))
        .ok();
}

fn set_links_for_entry(store: &Store, matches: &ArgMatches, entry: &mut FileLockEntry) {
    let links = matches
        .value_of("links")
        .map(String::from)
        .unwrap()
        .split(',')
        .map(|uri| {
            match Url::parse(uri) {
                Err(e) => {
                    warn!("Could not parse '{}' as URL, ignoring", uri);
                    trace_error(&e);
                    None
                },
                Ok(u) => Some(u),
            }
        })
        .filter_map(|x| x)
        .collect();

    entry.set_external_links(store, links)
        .map_err_trace()
        .map_info_str("Ok")
        .ok();
}

fn list_links_for_entry(store: &Store, entry: &mut FileLockEntry) {
    entry.get_external_links(store)
        .and_then(|links| {
            for (i, link) in links.enumerate() {
                match link {
                    Ok(link) => println!("{: <3}: {}", i, link),
                    Err(e)   => trace_error(&e),
                }
            }
            Ok(())
        })
        .map_err_trace()
        .map_info_str("Ok")
        .ok();
}

<|endoftext|>


<commit_before>pub trait SafeToU8 {
    fn safe_to_u8(self) -> u8;
}

pub trait SafeToU16 {
    fn safe_to_u16(self) -> u16;
}

pub trait SafeToI32 {
    fn safe_to_i32(self) -> i32;
}

impl SafeToU8 for u16 {
    fn safe_to_u8(self) -> u8 {
        dbg_assert!(self < ::std::u8::MAX as u16);
        self as u8
    }
}

impl SafeToU8 for u32 {
    fn safe_to_u8(self) -> u8 {
        dbg_assert!(self < ::std::u8::MAX as u32);
        self as u8
    }
}

impl SafeToU8 for i32 {
    fn safe_to_u8(self) -> u8 {
        dbg_assert!(self < ::std::u8::MAX as i32);
        self as u8
    }
}

impl SafeToU8 for usize {
    fn safe_to_u8(self) -> u8 {
        dbg_assert!(self < ::std::u8::MAX as usize);
        self as u8
    }
}

impl SafeToU16 for u32 {
    fn safe_to_u16(self) -> u16 {
        dbg_assert!(self < ::std::u16::MAX as u32);
        self as u16
    }
}

impl SafeToU16 for i32 {
    fn safe_to_u16(self) -> u16 {
        dbg_assert!(self < ::std::u16::MAX as i32);
        self as u16
    }
}

impl SafeToU16 for usize {
    fn safe_to_u16(self) -> u16 {
        dbg_assert!(self < ::std::u16::MAX as usize);
        self as u16
    }
}

impl SafeToI32 for u32 {
    fn safe_to_i32(self) -> i32 {
        dbg_assert!(self < ::std::i32::MAX as u32);
        self as i32
    }
}

impl SafeToI32 for usize {
    fn safe_to_i32(self) -> i32 {
        dbg_assert!(self < ::std::i32::MAX as usize);
        self as i32
    }
}

pub fn write_leb_i32(buf: &mut Vec<u8>, mut v: i32) {
    // Super complex stuff. See the following:
    // https://en.wikipedia.org/wiki/LEB128#Encode_signed_integer
    // http://llvm.org/doxygen/LEB128_8h_source.html#l00048

    let mut more = true;
    let negative = v < 0;
    let size = 32;
    while more {
        let mut byte = (v & 0b1111111) as u8; // get last 7 bits
        v >>= 7; // shift them away from the value
        if negative {
            v |= (!0 as i32) << (size - 7); // extend sign
        }
        let sign_bit = byte & (1 << 6);
        if (v == 0 && sign_bit == 0) || (v == -1 && sign_bit != 0) {
            more = false;
        }
        else {
            byte |= 0b10000000; // turn on MSB
        }
        buf.push(byte);
    }
}

pub fn write_leb_u32(buf: &mut Vec<u8>, mut v: u32) {
    loop {
        let mut byte = v as u8 & 0b01111111; // get last 7 bits
        v >>= 7; // shift them away from the value
        if v != 0 {
            byte |= 0b10000000; // turn on MSB
        }
        buf.push(byte);
        if v == 0 {
            break;
        }
    }
}

pub fn write_fixed_leb16_at_idx(vec: &mut Vec<u8>, idx: usize, x: u16) {
    dbg_assert!(x < (1 << 14)); // we have 14 bits of available space in 2 bytes for leb
    vec[idx    ] = ((x & 0b1111111) | 0b10000000) as u8;
    vec[idx + 1] = (x >> 7) as u8;
}

pub fn write_fixed_leb32_at_idx(vec: &mut Vec<u8>, idx: usize, x: u32) {
    dbg_assert!(x < (1 << 28)); // we have 28 bits of available space in 4 bytes for leb
    vec[idx    ] = (x       & 0b1111111) as u8 | 0b10000000;
    vec[idx + 1] = (x >> 7  & 0b1111111) as u8 | 0b10000000;
    vec[idx + 2] = (x >> 14 & 0b1111111) as u8 | 0b10000000;
    vec[idx + 3] = (x >> 21 & 0b1111111) as u8;
}

pub type PackedStr = (u64, u64, u64);

#[allow(dead_code)]
pub fn pack_str(s: &str) -> PackedStr {
    assert!(s.len() <= 16);
    let mut a: [u8; 24] = [0; 24];
    for (i, ch) in s.char_indices() {
        a[i] = ch as u8;
    }

    unsafe { ::std::mem::transmute(a) }
}

pub fn unpack_str(s: PackedStr) -> String {
    let mut buf = String::with_capacity(24);
    let bytes: [u8; 24] = unsafe { ::std::mem::transmute(s) };
    for i in 0..24 {
        if bytes[i] == 0 {
            break;
        }
        buf.push(bytes[i] as char);
    }
    buf
}

#[allow(dead_code)]
pub const DEBUG: bool = cfg!(debug_assertions);

#[cfg(target_arch = "wasm32")]
extern "C" {
    pub fn log_from_wasm(ptr: *const u8, len: usize);
    pub fn abort();
}

#[cfg(target_arch = "wasm32")]
use std::string::ToString;

#[cfg(target_arch = "wasm32")]
pub fn _log_to_js_console<T: ToString>(s: T) {
    let s: String = s.to_string();
    let len = s.len();
    unsafe { log_from_wasm(s.as_bytes().as_ptr(), len); }
}

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

    #[test]
    fn packed_strs() {
        let pstr = pack_str("foo");
        assert_eq!("foo", unpack_str(pstr));

        let pstr = pack_str("abcdefghijkl");
        assert_eq!("abcdefghijkl", unpack_str(pstr));
    }

}
<commit_msg>fix bounds check in Safe* traits<commit_after>pub trait SafeToU8 { fn safe_to_u8(self) -> u8; }
pub trait SafeToU16 { fn safe_to_u16(self) -> u16; }
pub trait SafeToI32 { fn safe_to_i32(self) -> i32; }

impl SafeToU8 for u16 {
    fn safe_to_u8(self) -> u8 {
        dbg_assert!(self <= ::std::u8::MAX as u16);
        self as u8
    }
}

impl SafeToU8 for u32 {
    fn safe_to_u8(self) -> u8 {
        dbg_assert!(self <= ::std::u8::MAX as u32);
        self as u8
    }
}

impl SafeToU8 for i32 {
    fn safe_to_u8(self) -> u8 {
        dbg_assert!(self >= 0 && self <= ::std::u8::MAX as i32);
        self as u8
    }
}

impl SafeToU8 for usize {
    fn safe_to_u8(self) -> u8 {
        dbg_assert!(self <= ::std::u8::MAX as usize);
        self as u8
    }
}

impl SafeToU16 for u32 {
    fn safe_to_u16(self) -> u16 {
        dbg_assert!(self <= ::std::u16::MAX as u32);
        self as u16
    }
}

impl SafeToU16 for i32 {
    fn safe_to_u16(self) -> u16 {
        dbg_assert!(self >= 0 && self <= ::std::u16::MAX as i32);
        self as u16
    }
}

impl SafeToU16 for usize {
    fn safe_to_u16(self) -> u16 {
        dbg_assert!(self <= ::std::u16::MAX as usize);
        self as u16
    }
}

impl SafeToI32 for u32 {
    fn safe_to_i32(self) -> i32 {
        dbg_assert!(self <= ::std::i32::MAX as u32);
        self as i32
    }
}

impl SafeToI32 for usize {
    fn safe_to_i32(self) -> i32 {
        dbg_assert!(self <= ::std::i32::MAX as usize);
        self as i32
    }
}

pub fn write_leb_i32(buf: &mut Vec<u8>, mut v: i32) {
    // Super complex stuff. See the following:
    // https://en.wikipedia.org/wiki/LEB128#Encode_signed_integer
    // http://llvm.org/doxygen/LEB128_8h_source.html#l00048

    let mut more = true;
    let negative = v < 0;
    let size = 32;
    while more {
        let mut byte = (v & 0b1111111) as u8; // get last 7 bits
        v >>= 7; // shift them away from the value
        if negative {
            v |= (!0 as i32) << (size - 7); // extend sign
        }
        let sign_bit = byte & (1 << 6);
        if (v == 0 && sign_bit == 0) || (v == -1 && sign_bit != 0) {
            more = false;
        }
        else {
            byte |= 0b10000000; // turn on MSB
        }
        buf.push(byte);
    }
}

pub fn write_leb_u32(buf: &mut Vec<u8>, mut v: u32) {
    loop {
        let mut byte = v as u8 & 0b01111111; // get last 7 bits
        v >>= 7; // shift them away from the value
        if v != 0 {
            byte |= 0b10000000; // turn on MSB
        }
        buf.push(byte);
        if v == 0 {
            break;
        }
    }
}

pub fn write_fixed_leb16_at_idx(vec: &mut Vec<u8>, idx: usize, x: u16) {
    dbg_assert!(x < (1 << 14)); // we have 14 bits of available space in 2 bytes for leb
    vec[idx    ] = ((x & 0b1111111) | 0b10000000) as u8;
    vec[idx + 1] = (x >> 7) as u8;
}

pub fn write_fixed_leb32_at_idx(vec: &mut Vec<u8>, idx: usize, x: u32) {
    dbg_assert!(x < (1 << 28)); // we have 28 bits of available space in 4 bytes for leb
    vec[idx    ] = (x       & 0b1111111) as u8 | 0b10000000;
    vec[idx + 1] = (x >> 7  & 0b1111111) as u8 | 0b10000000;
    vec[idx + 2] = (x >> 14 & 0b1111111) as u8 | 0b10000000;
    vec[idx + 3] = (x >> 21 & 0b1111111) as u8;
}

pub type PackedStr = (u64, u64, u64);

#[allow(dead_code)]
pub fn pack_str(s: &str) -> PackedStr {
    assert!(s.len() <= 16);
    let mut a: [u8; 24] = [0; 24];
    for (i, ch) in s.char_indices() {
        a[i] = ch as u8;
    }

    unsafe { ::std::mem::transmute(a) }
}

pub fn unpack_str(s: PackedStr) -> String {
    let mut buf = String::with_capacity(24);
    let bytes: [u8; 24] = unsafe { ::std::mem::transmute(s) };
    for i in 0..24 {
        if bytes[i] == 0 {
            break;
        }
        buf.push(bytes[i] as char);
    }
    buf
}

#[allow(dead_code)]
pub const DEBUG: bool = cfg!(debug_assertions);

#[cfg(target_arch = "wasm32")]
extern "C" {
    pub fn log_from_wasm(ptr: *const u8, len: usize);
    pub fn abort();
}

#[cfg(target_arch = "wasm32")]
use std::string::ToString;

#[cfg(target_arch = "wasm32")]
pub fn _log_to_js_console<T: ToString>(s: T) {
    let s: String = s.to_string();
    let len = s.len();
    unsafe { log_from_wasm(s.as_bytes().as_ptr(), len); }
}

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

    #[test]
    fn packed_strs() {
        let pstr = pack_str("foo");
        assert_eq!("foo", unpack_str(pstr));

        let pstr = pack_str("abcdefghijkl");
        assert_eq!("abcdefghijkl", unpack_str(pstr));
    }

}
<|endoftext|>


<commit_before>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

//! Wire format traits.
//!
//! This module provides [`FromWire`] and [`ToWire`], a pair of traits similar
//! to the core traits in the [`serde`] library. Rather than representing a
//! generically serializeable type, they represent types that can be converted
//! to and from Cerberus's wire format, which has a unique, ad-hoc data model.
//!
//! [`FromWire`]: trait.FromWire.html
//! [`ToWire`]: trait.ToWire.html
//! [`serde`]: https://serde.rs

use crate::io;
use crate::io::LeInt;
use crate::io::Read;
use crate::io::Write;

/// A type which can be deserialized from the Cerberus wire format.
///
/// The lifetime `'wire` indicates that the type can be deserialized from a
/// buffer of lifetime `'wire`.
pub trait FromWire<'wire>: Sized {
    /// Deserializes a `Self` w of `r`.
    fn from_wire<R: Read<'wire>>(r: R) -> Result<Self, FromWireError>;
}

/// An deserialization error.
#[derive(Clone, Copy, Debug)]
pub enum FromWireError {
    /// Indicates that something went wrong in an `io` operation.
    ///
    /// [`io`]: ../../io/index.html
    Io(io::Error),

    /// Indicates that some field within the request was outside of its
    /// valid range.
    OutOfRange,
}

impl From<io::Error> for FromWireError {
    fn from(e: io::Error) -> Self {
        Self::Io(e)
    }
}

/// A type which can be serialized into the Cerberus wire format.
pub trait ToWire: Sized {
    /// Serializes `self` into `w`.
    fn to_wire<W: Write>(&self, w: W) -> Result<(), ToWireError>;
}

/// A serializerion error.
#[derive(Clone, Copy, Debug)]
pub enum ToWireError {
    /// Indicates that something went wrong in an [`io`] operation.
    ///
    /// [`io`]: ../../io/index.html
    Io(io::Error),
}

impl From<io::Error> for ToWireError {
    fn from(e: io::Error) -> Self {
        Self::Io(e)
    }
}

/// Represents a C-like enum that can be converted to and from a wire
/// representation as well as to and from a string representation.
///
/// An implementation of this trait can be thought of as an unsigned
/// integer with a limited range: every enum variant can be converted
/// to the wire format and back, though not every value of the wire
/// representation can be converted into an enum variant.
///
/// In particular the following identity must hold for all types T:
/// ```
/// # use manticore::protocol::wire::WireEnum;
/// # fn test<T: WireEnum + Copy + PartialEq + std::fmt::Debug>(x: T) {
/// assert_eq!(T::from_wire_value(T::to_wire_value(x)), Some(x));
/// # }
/// ```
///
/// Also, the following identity must hold for all types T:
/// ```
/// # use manticore::protocol::wire::WireEnum;
/// # fn test<T: WireEnum + Copy + PartialEq + std::fmt::Debug>(x: T) {
/// assert_eq!(T::from_name(T::name(x)), Some(x));
/// # }
/// ```
pub trait WireEnum: Sized + Copy {
    /// The unrelying "wire type". This is almost always some kind of
    /// unsigned integer.
    type Wire: LeInt;

    /// Converts `self` into its underlying wire representation.
    fn to_wire_value(self) -> Self::Wire;

    /// Attempts to parse a value of `Self` from the underlying wire
    /// representation.
    fn from_wire_value(wire: Self::Wire) -> Option<Self>;

    /// Converts `self` into a string representation.
    fn name(self) -> &'static str;

    /// Attempts to convert a value of `Self` from a string representation.
    fn from_name(str: &str) -> Option<Self>;
}

impl<'wire, E> FromWire<'wire> for E
where
    E: WireEnum,
{
    fn from_wire<R: Read<'wire>>(mut r: R) -> Result<Self, FromWireError> {
        let wire = <Self as WireEnum>::Wire::read_from(&mut r)?;
        Self::from_wire_value(wire).ok_or(FromWireError::OutOfRange)
    }
}

impl<E> ToWire for E
where
    E: WireEnum,
{
    fn to_wire<W: Write>(&self, mut w: W) -> Result<(), ToWireError> {
        self.to_wire_value().write_to(&mut w)?;
        Ok(())
    }
}

/// A conveinence macro for generating `WireEnum`-implementing enums.
///
///
/// Syntax is as follows:
/// ```text
/// wire_enum! {
///     /// This is my enum.
///     pub enum MyEnum : u8 {
///         /// Variant `A`.
///         A = 0x00,
///         /// Variant `B`.
///         B = 0x01,
///     }
/// }
/// ```
/// This macro will generate an implementation of `WireEnum<Wire=u8>` for
/// the above enum.
macro_rules! wire_enum {
    ($(#[$meta:meta])* $vis:vis enum $name:ident : $wire:ident {
        $($(#[$meta_variant:meta])* $variant:ident = $value:literal,)*
    }) => {
        $(#[$meta])*
        #[repr($wire)]
        #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
        $vis enum $name {
           $(
               $(#[$meta_variant])*
               $variant = $value,
           )*
        }

        impl $crate::protocol::wire::WireEnum for $name {
            type Wire = $wire;
            fn to_wire_value(self) -> Self::Wire {
                self as $wire
            }
            fn from_wire_value(wire: Self::Wire) -> Option<Self> {
                match wire {
                    $(
                        $value => Some(Self::$variant),
                    )*
                    _ => None,
                }
            }

            fn name(self) -> &'static str {
                match self {
                    $(
                        Self::$variant => stringify!($variant),
                    )*
                }
            }

            fn from_name(name: &str) -> Option<Self> {
                match name {
                    $(
                        stringify!($variant) => Some(Self::$variant),
                    )*
                    _ => None,
                }
            }
        }

        impl core::fmt::Display for $name {
            fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
                use $crate::protocol::wire::WireEnum;

                write!(f, "{}", self.name())
            }
        }

        impl core::str::FromStr for $name {
            type Err = ();

            fn from_str(s: &str) -> Result<Self, ()> {
                use $crate::protocol::wire::WireEnum;

                match $name::from_name(s) {
                    Some(val) => Ok(val),
                    None => Err(()),
                }
            }
        }
    }
}

#[cfg(test)]
mod test {
    wire_enum! {
        /// An enum for testing.
        #[cfg_attr(feature = "arbitrary-derive", derive(Arbitrary))]
        #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
        pub enum DemoEnum: u8 {
            /// Unknown value
            Unknown = 0x00,

            /// First enum value
            First = 0x01,

            /// Second enum value
            Second = 0x02,
        }
    }

    #[test]
    fn from_name() {
        use crate::protocol::wire::*;

        let value = DemoEnum::from_name("Second").expect("from_name failed");
        assert_eq!(value, DemoEnum::Second);

        let value = DemoEnum::from_name("First").expect("from_name failed");
        assert_eq!(value, DemoEnum::First);

        assert_eq!(None, DemoEnum::from_name("does not exist"));
    }

    #[test]
    fn name() {
        use crate::protocol::wire::*;

        assert_eq!(DemoEnum::First.name(), "First");
        assert_eq!(DemoEnum::Second.name(), "Second");
    }
}
<commit_msg>Add WireEnumFromStrError.<commit_after>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

//! Wire format traits.
//!
//! This module provides [`FromWire`] and [`ToWire`], a pair of traits similar
//! to the core traits in the [`serde`] library. Rather than representing a
//! generically serializeable type, they represent types that can be converted
//! to and from Cerberus's wire format, which has a unique, ad-hoc data model.
//!
//! [`FromWire`]: trait.FromWire.html
//! [`ToWire`]: trait.ToWire.html
//! [`serde`]: https://serde.rs

use crate::io;
use crate::io::LeInt;
use crate::io::Read;
use crate::io::Write;

/// A type which can be deserialized from the Cerberus wire format.
///
/// The lifetime `'wire` indicates that the type can be deserialized from a
/// buffer of lifetime `'wire`.
pub trait FromWire<'wire>: Sized {
    /// Deserializes a `Self` w of `r`.
    fn from_wire<R: Read<'wire>>(r: R) -> Result<Self, FromWireError>;
}

/// An deserialization error.
#[derive(Clone, Copy, Debug)]
pub enum FromWireError {
    /// Indicates that something went wrong in an `io` operation.
    ///
    /// [`io`]: ../../io/index.html
    Io(io::Error),

    /// Indicates that some field within the request was outside of its
    /// valid range.
    OutOfRange,
}

impl From<io::Error> for FromWireError {
    fn from(e: io::Error) -> Self {
        Self::Io(e)
    }
}

/// A type which can be serialized into the Cerberus wire format.
pub trait ToWire: Sized {
    /// Serializes `self` into `w`.
    fn to_wire<W: Write>(&self, w: W) -> Result<(), ToWireError>;
}

/// A serializerion error.
#[derive(Clone, Copy, Debug)]
pub enum ToWireError {
    /// Indicates that something went wrong in an [`io`] operation.
    ///
    /// [`io`]: ../../io/index.html
    Io(io::Error),
}

impl From<io::Error> for ToWireError {
    fn from(e: io::Error) -> Self {
        Self::Io(e)
    }
}

/// Represents a C-like enum that can be converted to and from a wire
/// representation as well as to and from a string representation.
///
/// An implementation of this trait can be thought of as an unsigned
/// integer with a limited range: every enum variant can be converted
/// to the wire format and back, though not every value of the wire
/// representation can be converted into an enum variant.
///
/// In particular the following identity must hold for all types T:
/// ```
/// # use manticore::protocol::wire::WireEnum;
/// # fn test<T: WireEnum + Copy + PartialEq + std::fmt::Debug>(x: T) {
/// assert_eq!(T::from_wire_value(T::to_wire_value(x)), Some(x));
/// # }
/// ```
///
/// Also, the following identity must hold for all types T:
/// ```
/// # use manticore::protocol::wire::WireEnum;
/// # fn test<T: WireEnum + Copy + PartialEq + std::fmt::Debug>(x: T) {
/// assert_eq!(T::from_name(T::name(x)), Some(x));
/// # }
/// ```
pub trait WireEnum: Sized + Copy {
    /// The unrelying "wire type". This is almost always some kind of
    /// unsigned integer.
    type Wire: LeInt;

    /// Converts `self` into its underlying wire representation.
    fn to_wire_value(self) -> Self::Wire;

    /// Attempts to parse a value of `Self` from the underlying wire
    /// representation.
    fn from_wire_value(wire: Self::Wire) -> Option<Self>;

    /// Converts `self` into a string representation.
    fn name(self) -> &'static str;

    /// Attempts to convert a value of `Self` from a string representation.
    fn from_name(str: &str) -> Option<Self>;
}

impl<'wire, E> FromWire<'wire> for E
where
    E: WireEnum,
{
    fn from_wire<R: Read<'wire>>(mut r: R) -> Result<Self, FromWireError> {
        let wire = <Self as WireEnum>::Wire::read_from(&mut r)?;
        Self::from_wire_value(wire).ok_or(FromWireError::OutOfRange)
    }
}

impl<E> ToWire for E
where
    E: WireEnum,
{
    fn to_wire<W: Write>(&self, mut w: W) -> Result<(), ToWireError> {
        self.to_wire_value().write_to(&mut w)?;
        Ok(())
    }
}

/// A deserialization-from-string error.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct WireEnumFromStrError;

/// A conveinence macro for generating `WireEnum`-implementing enums.
///
///
/// Syntax is as follows:
/// ```text
/// wire_enum! {
///     /// This is my enum.
///     pub enum MyEnum : u8 {
///         /// Variant `A`.
///         A = 0x00,
///         /// Variant `B`.
///         B = 0x01,
///     }
/// }
/// ```
/// This macro will generate an implementation of `WireEnum<Wire=u8>` for
/// the above enum.
macro_rules! wire_enum {
    ($(#[$meta:meta])* $vis:vis enum $name:ident : $wire:ident {
        $($(#[$meta_variant:meta])* $variant:ident = $value:literal,)*
    }) => {
        $(#[$meta])*
        #[repr($wire)]
        #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
        $vis enum $name {
           $(
               $(#[$meta_variant])*
               $variant = $value,
           )*
        }

        impl $crate::protocol::wire::WireEnum for $name {
            type Wire = $wire;
            fn to_wire_value(self) -> Self::Wire {
                self as $wire
            }
            fn from_wire_value(wire: Self::Wire) -> Option<Self> {
                match wire {
                    $(
                        $value => Some(Self::$variant),
                    )*
                    _ => None,
                }
            }

            fn name(self) -> &'static str {
                match self {
                    $(
                        Self::$variant => stringify!($variant),
                    )*
                }
            }

            fn from_name(name: &str) -> Option<Self> {
                match name {
                    $(
                        stringify!($variant) => Some(Self::$variant),
                    )*
                    _ => None,
                }
            }
        }

        impl core::fmt::Display for $name {
            fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
                use $crate::protocol::wire::WireEnum;

                write!(f, "{}", self.name())
            }
        }

        impl core::str::FromStr for $name {
            type Err = $crate::protocol::wire::WireEnumFromStrError;

            fn from_str(s: &str) -> Result<Self, $crate::protocol::wire::WireEnumFromStrError> {
                use $crate::protocol::wire::WireEnum;

                match $name::from_name(s) {
                    Some(val) => Ok(val),
                    None => Err($crate::protocol::wire::WireEnumFromStrError),
                }
            }
        }
    }
}

#[cfg(test)]
mod test {
    wire_enum! {
        /// An enum for testing.
        #[cfg_attr(feature = "arbitrary-derive", derive(Arbitrary))]
        #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
        pub enum DemoEnum: u8 {
            /// Unknown value
            Unknown = 0x00,

            /// First enum value
            First = 0x01,

            /// Second enum value
            Second = 0x02,
        }
    }

    #[test]
    fn from_name() {
        use crate::protocol::wire::*;

        let value = DemoEnum::from_name("Second").expect("from_name failed");
        assert_eq!(value, DemoEnum::Second);

        let value = DemoEnum::from_name("First").expect("from_name failed");
        assert_eq!(value, DemoEnum::First);

        assert_eq!(None, DemoEnum::from_name("does not exist"));
    }

    #[test]
    fn name() {
        use crate::protocol::wire::*;

        assert_eq!(DemoEnum::First.name(), "First");
        assert_eq!(DemoEnum::Second.name(), "Second");
    }
}
<|endoftext|>


<commit_before>use screen::*;
use context::Context;
use resource_manager::Textures;
use graphics::Texture;
use piston_window::{self, PistonWindow, ImageSize, Transformed};

pub struct Battle {
    empty_tile: Texture,
}

impl Battle {
    pub fn new(window: &PistonWindow, context: &mut Context) -> Self {
        Battle { empty_tile: context.resource_manager.load_texture(window, Textures::EmptyTile) }
    }
}

impl Screen for Battle {
    fn on_input(&mut self, input: &piston_window::Input, window: &PistonWindow, context: &mut Context) -> InputResults {
        use piston_window::{Input, Button, Key};

        let mut result = Vec::new();

        match input {
            &Input::Press(button) => {
                match button {
                    Button::Keyboard(Key::Escape) => {
                        result.push(InputResult::PushScreen(Box::new(MainMenu::new(&window, context))));
                    }
                    _ => {}
                }
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, _args: &piston_window::RenderArgs, window: &PistonWindow) {
        window.draw_2d(|context, graphics| {
            piston_window::clear([0.0, 0.0, 0.0, 1.0], graphics);

            // Draw grid.
            let tiles_count = 4;
            let (height, width) = self.empty_tile.get_size();
            for x in 0..tiles_count {
                for y in 0..tiles_count {
                    // TODO: draw_many?
                    piston_window::image(&self.empty_tile, context.transform.trans((x * height + 5) as f64, (y * width + 5) as f64), graphics);
                }
            }
        });
    }

    fn on_update(&mut self, _args: &piston_window::UpdateArgs) {}
}
<commit_msg>Grid offset<commit_after>use screen::*;
use context::Context;
use resource_manager::Textures;
use graphics::Texture;
use piston_window::{self, PistonWindow, ImageSize, Transformed};

pub struct Battle {
    empty_tile: Texture,
}

impl Battle {
    pub fn new(window: &PistonWindow, context: &mut Context) -> Self {
        Battle { empty_tile: context.resource_manager.load_texture(window, Textures::EmptyTile) }
    }
}

impl Screen for Battle {
    fn on_input(&mut self, input: &piston_window::Input, window: &PistonWindow, context: &mut Context) -> InputResults {
        use piston_window::{Input, Button, Key};

        let mut result = Vec::new();

        match input {
            &Input::Press(button) => {
                match button {
                    Button::Keyboard(Key::Escape) => {
                        result.push(InputResult::PushScreen(Box::new(MainMenu::new(&window, context))));
                    }
                    _ => {}
                }
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, _args: &piston_window::RenderArgs, window: &PistonWindow) {
        window.draw_2d(|context, graphics| {
            piston_window::clear([0.0, 0.0, 0.0, 1.0], graphics);

            // Draw grid.
            let tiles_count = 4;
            let offset = 5;
            let (height, width) = self.empty_tile.get_size();
            for x in 0..tiles_count {
                for y in 0..tiles_count {
                    // TODO: draw_many?
                    //piston_window::image(&self.empty_tile, context.transform.trans((x * height + (5 * if x == 0 { 1 } else { 2 })) as f64, (y * width + (5 * if y == 0 { 1 } else { 2 })) as f64), graphics);
                    piston_window::image(&self.empty_tile, context.transform.trans((x * (height + offset)) as f64, (y * (width + offset)) as  f64), graphics);
                }
            }
        });
    }

    fn on_update(&mut self, _args: &piston_window::UpdateArgs) {}
}
<|endoftext|>