<commit_before>// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! A type-checked scaling factor between units.

use num::One;

use num_traits::NumCast;
#[cfg(feature = "serde")]
use serde;
use core::fmt;
use core::ops::{Add, Div, Mul, Neg, Sub};
use core::marker::PhantomData;
use {Point2D, Rect, Size2D, Vector2D};

/// A scaling factor between two different units of measurement.
///
/// This is effectively a type-safe float, intended to be used in combination with other types like
/// `length::Length` to enforce conversion between systems of measurement at compile time.
///
/// `Src` and `Dst` represent the units before and after multiplying a value by a `Scale`. They
/// may be types without values, such as empty enums.  For example:
///
/// ```rust
/// use euclid::Scale;
/// use euclid::Length;
/// enum Mm {};
/// enum Inch {};
///
/// let mm_per_inch: Scale<f32, Inch, Mm> = Scale::new(25.4);
///
/// let one_foot: Length<f32, Inch> = Length::new(12.0);
/// let one_foot_in_mm: Length<f32, Mm> = one_foot * mm_per_inch;
/// ```
#[repr(C)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(bound(serialize = "T: serde::Serialize", deserialize = "T: serde::Deserialize<'de>")))]
pub struct Scale<T, Src, Dst>(pub T, #[doc(hidden)] pub PhantomData<(Src, Dst)>);

impl<T, Src, Dst> Scale<T, Src, Dst> {
    #[inline]
    pub const fn new(x: T) -> Self {
        Scale(x, PhantomData)
    }

    /// Returns the given point transformed by this scale.
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::{Scale, point2};
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
    ///
    /// assert_eq!(to_mm.transform_point(point2(42, -42)), point2(420, -420));
    /// ```
    #[inline]
    pub fn transform_point(&self, point: Point2D<T, Src>) -> Point2D<T::Output, Dst>
        where T: Clone + Mul
    {
        Point2D::new(point.x * self.get(), point.y * self.get())
    }

    /// Returns the given vector transformed by this scale.
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::{Scale, vec2};
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
    ///
    /// assert_eq!(to_mm.transform_vector(vec2(42, -42)), vec2(420, -420));
    /// ```
    #[inline]
    pub fn transform_vector(&self, vec: Vector2D<T, Src>) -> Vector2D<T::Output, Dst>
        where T: Clone + Mul
    {
        Vector2D::new(vec.x * self.get(), vec.y * self.get())
    }

    /// Returns the given vector transformed by this scale.
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::{Scale, size2};
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
    ///
    /// assert_eq!(to_mm.transform_size(size2(42, -42)), size2(420, -420));
    /// ```
    #[inline]
    pub fn transform_size(&self, size: Size2D<T, Src>) -> Size2D<T::Output, Dst>
        where T: Clone + Mul
    {
        Size2D::new(size.width * self.get(), size.height * self.get())
    }

    /// Returns the given rect transformed by this scale.
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::{Scale, rect};
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
    ///
    /// assert_eq!(to_mm.transform_rect(&rect(1, 2, 42, -42)), rect(10, 20, 420, -420));
    /// ```
    #[inline]
    pub fn transform_rect(&self, rect: &Rect<T, Src>) -> Rect<T::Output, Dst>
        where T: Copy + Mul
    {
        Rect::new(
            self.transform_point(rect.origin),
            self.transform_size(rect.size),
        )
    }

    /// Returns the inverse of this scale.
    #[inline]
    pub fn inverse(&self) -> Scale<T::Output, Dst, Src>
        where T: Clone + Neg
    {
        Scale::new(-self.get())
    }

    /// Returns `true` if this scale has no effect.
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::Scale;
    /// use euclid::num::One;
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
    /// let mm_per_mm: Scale<f32, Mm, Mm> = Scale::new(1.0);
    ///
    /// assert_eq!(cm_per_mm.is_identity(), false);
    /// assert_eq!(mm_per_mm.is_identity(), true);
    /// ```
    #[inline]
    pub fn is_identity(&self) -> bool
        where T: PartialEq + One
    {
        self.0 == T::one()
    }
}

impl<T: Clone, Src, Dst> Scale<T, Src, Dst> {
    #[inline]
    pub fn get(&self) -> T {
        self.0.clone()
    }

    /// The inverse Scale (1.0 / self).
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::Scale;
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let cm_per_mm: Scale<f32, Cm, Mm> = Scale::new(0.1);
    ///
    /// assert_eq!(cm_per_mm.inv(), Scale::new(10.0));
    /// ```
    pub fn inv(&self) -> Scale<T::Output, Dst, Src>
    where
        T: One + Div
    {
        let one: T = One::one();
        Scale::new(one / self.0.clone())
    }
}

impl<Src, Dst> Scale<f32, Src, Dst> {
    /// Identity scaling, could be used to safely transit from one space to another.
    pub const ONE: Self = Scale(1.0, PhantomData);
}

// scale0 * scale1
impl<T: Mul<T, Output = T>, A, B, C> Mul<Scale<T, B, C>> for Scale<T, A, B> {
    type Output = Scale<T, A, C>;
    #[inline]
    fn mul(self, other: Scale<T, B, C>) -> Scale<T, A, C> {
        Scale::new(self.0 * other.0)
    }
}

// scale0 + scale1
impl<T: Add<T, Output = T>, Src, Dst> Add for Scale<T, Src, Dst> {
    type Output = Scale<T, Src, Dst>;
    #[inline]
    fn add(self, other: Scale<T, Src, Dst>) -> Scale<T, Src, Dst> {
        Scale::new(self.0 + other.0)
    }
}

// scale0 - scale1
impl<T: Sub<T, Output = T>, Src, Dst> Sub for Scale<T, Src, Dst> {
    type Output = Scale<T, Src, Dst>;
    #[inline]
    fn sub(self, other: Scale<T, Src, Dst>) -> Scale<T, Src, Dst> {
        Scale::new(self.0 - other.0)
    }
}

impl<T: NumCast + Clone, Src, Dst> Scale<T, Src, Dst> {
    /// Cast from one numeric representation to another, preserving the units.
    ///
    /// # Panics
    ///
    /// If the source value cannot be represented by the target type `NewT`, then
    /// method panics. Use `try_cast` if that must be case.
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::Scale;
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
    ///
    /// assert_eq!(to_mm.cast::<f32>(), Scale::new(10.0));
    /// ```
    /// That conversion will panic, because `i32` not enough to store such big numbers:
    /// ```rust,should_panic
    /// use euclid::Scale;
    /// enum Mm {};// millimeter = 10^-2 meters
    /// enum Em {};// exameter   = 10^18 meters
    ///
    /// // Panics
    /// let to_em: Scale<i32, Mm, Em> = Scale::new(10e20).cast();
    /// ```
    #[inline]
    pub fn cast<NewT: NumCast>(&self) -> Scale<NewT, Src, Dst> {
        self.try_cast().unwrap()
    }

    /// Fallible cast from one numeric representation to another, preserving the units.
    /// If the source value cannot be represented by the target type `NewT`, then `None`
    /// is returned.
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::Scale;
    /// enum Mm {};
    /// enum Cm {};
    /// enum Em {};// Exameter = 10^18 meters
    ///
    /// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
    /// let to_em: Scale<f32, Mm, Em> = Scale::new(10e20);
    ///
    /// assert_eq!(to_mm.try_cast::<f32>(), Some(Scale::new(10.0)));
    /// // Integer to small to store that number
    /// assert_eq!(to_em.try_cast::<i32>(), None);
    /// ```
    pub fn try_cast<NewT: NumCast>(&self) -> Option<Scale<NewT, Src, Dst>> {
        NumCast::from(self.get()).map(Scale::new)
    }
}

// FIXME: Switch to `derive(PartialEq, Clone)` after this Rust issue is fixed:
// https://github.com/rust-lang/rust/issues/26925

impl<T: PartialEq, Src, Dst> PartialEq for Scale<T, Src, Dst> {
    fn eq(&self, other: &Scale<T, Src, Dst>) -> bool {
        self.0 == other.0
    }
}

impl<T: Clone, Src, Dst> Clone for Scale<T, Src, Dst> {
    fn clone(&self) -> Scale<T, Src, Dst> {
        Scale::new(self.get())
    }
}

impl<T: Copy, Src, Dst> Copy for Scale<T, Src, Dst> {}

impl<T: fmt::Debug, Src, Dst> fmt::Debug for Scale<T, Src, Dst> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl<T: fmt::Display, Src, Dst> fmt::Display for Scale<T, Src, Dst> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

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

    enum Inch {}
    enum Cm {}
    enum Mm {}

    #[test]
    fn test_scale() {
        let mm_per_inch: Scale<f32, Inch, Mm> = Scale::new(25.4);
        let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);

        let mm_per_cm: Scale<f32, Cm, Mm> = cm_per_mm.inv();
        assert_eq!(mm_per_cm.get(), 10.0);

        let cm_per_inch: Scale<f32, Inch, Cm> = mm_per_inch * cm_per_mm;
        assert_eq!(cm_per_inch, Scale::new(2.54));

        let a: Scale<isize, Inch, Inch> = Scale::new(2);
        let b: Scale<isize, Inch, Inch> = Scale::new(3);
        assert!(a != b);
        assert_eq!(a, a.clone());
        assert_eq!(a.clone() + b.clone(), Scale::new(5));
        assert_eq!(a - b, Scale::new(-1));
    }
}
<commit_msg>Scale: group NumCast impl block with other type impl blocks<commit_after>// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! A type-checked scaling factor between units.

use num::One;

use num_traits::NumCast;
#[cfg(feature = "serde")]
use serde;
use core::fmt;
use core::ops::{Add, Div, Mul, Neg, Sub};
use core::marker::PhantomData;
use {Point2D, Rect, Size2D, Vector2D};

/// A scaling factor between two different units of measurement.
///
/// This is effectively a type-safe float, intended to be used in combination with other types like
/// `length::Length` to enforce conversion between systems of measurement at compile time.
///
/// `Src` and `Dst` represent the units before and after multiplying a value by a `Scale`. They
/// may be types without values, such as empty enums.  For example:
///
/// ```rust
/// use euclid::Scale;
/// use euclid::Length;
/// enum Mm {};
/// enum Inch {};
///
/// let mm_per_inch: Scale<f32, Inch, Mm> = Scale::new(25.4);
///
/// let one_foot: Length<f32, Inch> = Length::new(12.0);
/// let one_foot_in_mm: Length<f32, Mm> = one_foot * mm_per_inch;
/// ```
#[repr(C)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(bound(serialize = "T: serde::Serialize", deserialize = "T: serde::Deserialize<'de>")))]
pub struct Scale<T, Src, Dst>(pub T, #[doc(hidden)] pub PhantomData<(Src, Dst)>);

impl<T, Src, Dst> Scale<T, Src, Dst> {
    #[inline]
    pub const fn new(x: T) -> Self {
        Scale(x, PhantomData)
    }

    /// Returns the given point transformed by this scale.
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::{Scale, point2};
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
    ///
    /// assert_eq!(to_mm.transform_point(point2(42, -42)), point2(420, -420));
    /// ```
    #[inline]
    pub fn transform_point(&self, point: Point2D<T, Src>) -> Point2D<T::Output, Dst>
        where T: Clone + Mul
    {
        Point2D::new(point.x * self.get(), point.y * self.get())
    }

    /// Returns the given vector transformed by this scale.
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::{Scale, vec2};
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
    ///
    /// assert_eq!(to_mm.transform_vector(vec2(42, -42)), vec2(420, -420));
    /// ```
    #[inline]
    pub fn transform_vector(&self, vec: Vector2D<T, Src>) -> Vector2D<T::Output, Dst>
        where T: Clone + Mul
    {
        Vector2D::new(vec.x * self.get(), vec.y * self.get())
    }

    /// Returns the given vector transformed by this scale.
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::{Scale, size2};
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
    ///
    /// assert_eq!(to_mm.transform_size(size2(42, -42)), size2(420, -420));
    /// ```
    #[inline]
    pub fn transform_size(&self, size: Size2D<T, Src>) -> Size2D<T::Output, Dst>
        where T: Clone + Mul
    {
        Size2D::new(size.width * self.get(), size.height * self.get())
    }

    /// Returns the given rect transformed by this scale.
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::{Scale, rect};
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
    ///
    /// assert_eq!(to_mm.transform_rect(&rect(1, 2, 42, -42)), rect(10, 20, 420, -420));
    /// ```
    #[inline]
    pub fn transform_rect(&self, rect: &Rect<T, Src>) -> Rect<T::Output, Dst>
        where T: Copy + Mul
    {
        Rect::new(
            self.transform_point(rect.origin),
            self.transform_size(rect.size),
        )
    }

    /// Returns the inverse of this scale.
    #[inline]
    pub fn inverse(&self) -> Scale<T::Output, Dst, Src>
        where T: Clone + Neg
    {
        Scale::new(-self.get())
    }

    /// Returns `true` if this scale has no effect.
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::Scale;
    /// use euclid::num::One;
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
    /// let mm_per_mm: Scale<f32, Mm, Mm> = Scale::new(1.0);
    ///
    /// assert_eq!(cm_per_mm.is_identity(), false);
    /// assert_eq!(mm_per_mm.is_identity(), true);
    /// ```
    #[inline]
    pub fn is_identity(&self) -> bool
        where T: PartialEq + One
    {
        self.0 == T::one()
    }
}

impl<T: Clone, Src, Dst> Scale<T, Src, Dst> {
    #[inline]
    pub fn get(&self) -> T {
        self.0.clone()
    }

    /// The inverse Scale (1.0 / self).
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::Scale;
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let cm_per_mm: Scale<f32, Cm, Mm> = Scale::new(0.1);
    ///
    /// assert_eq!(cm_per_mm.inv(), Scale::new(10.0));
    /// ```
    pub fn inv(&self) -> Scale<T::Output, Dst, Src>
    where
        T: One + Div
    {
        let one: T = One::one();
        Scale::new(one / self.0.clone())
    }
}

impl<T: NumCast + Clone, Src, Dst> Scale<T, Src, Dst> {
    /// Cast from one numeric representation to another, preserving the units.
    ///
    /// # Panics
    ///
    /// If the source value cannot be represented by the target type `NewT`, then
    /// method panics. Use `try_cast` if that must be case.
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::Scale;
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
    ///
    /// assert_eq!(to_mm.cast::<f32>(), Scale::new(10.0));
    /// ```
    /// That conversion will panic, because `i32` not enough to store such big numbers:
    /// ```rust,should_panic
    /// use euclid::Scale;
    /// enum Mm {};// millimeter = 10^-2 meters
    /// enum Em {};// exameter   = 10^18 meters
    ///
    /// // Panics
    /// let to_em: Scale<i32, Mm, Em> = Scale::new(10e20).cast();
    /// ```
    #[inline]
    pub fn cast<NewT: NumCast>(&self) -> Scale<NewT, Src, Dst> {
        self.try_cast().unwrap()
    }

    /// Fallible cast from one numeric representation to another, preserving the units.
    /// If the source value cannot be represented by the target type `NewT`, then `None`
    /// is returned.
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::Scale;
    /// enum Mm {};
    /// enum Cm {};
    /// enum Em {};// Exameter = 10^18 meters
    ///
    /// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
    /// let to_em: Scale<f32, Mm, Em> = Scale::new(10e20);
    ///
    /// assert_eq!(to_mm.try_cast::<f32>(), Some(Scale::new(10.0)));
    /// // Integer to small to store that number
    /// assert_eq!(to_em.try_cast::<i32>(), None);
    /// ```
    pub fn try_cast<NewT: NumCast>(&self) -> Option<Scale<NewT, Src, Dst>> {
        NumCast::from(self.get()).map(Scale::new)
    }
}

impl<Src, Dst> Scale<f32, Src, Dst> {
    /// Identity scaling, could be used to safely transit from one space to another.
    pub const ONE: Self = Scale(1.0, PhantomData);
}

// scale0 * scale1
impl<T: Mul<T, Output = T>, A, B, C> Mul<Scale<T, B, C>> for Scale<T, A, B> {
    type Output = Scale<T, A, C>;
    #[inline]
    fn mul(self, other: Scale<T, B, C>) -> Scale<T, A, C> {
        Scale::new(self.0 * other.0)
    }
}

// scale0 + scale1
impl<T: Add<T, Output = T>, Src, Dst> Add for Scale<T, Src, Dst> {
    type Output = Scale<T, Src, Dst>;
    #[inline]
    fn add(self, other: Scale<T, Src, Dst>) -> Scale<T, Src, Dst> {
        Scale::new(self.0 + other.0)
    }
}

// scale0 - scale1
impl<T: Sub<T, Output = T>, Src, Dst> Sub for Scale<T, Src, Dst> {
    type Output = Scale<T, Src, Dst>;
    #[inline]
    fn sub(self, other: Scale<T, Src, Dst>) -> Scale<T, Src, Dst> {
        Scale::new(self.0 - other.0)
    }
}

// FIXME: Switch to `derive(PartialEq, Clone)` after this Rust issue is fixed:
// https://github.com/rust-lang/rust/issues/26925

impl<T: PartialEq, Src, Dst> PartialEq for Scale<T, Src, Dst> {
    fn eq(&self, other: &Scale<T, Src, Dst>) -> bool {
        self.0 == other.0
    }
}

impl<T: Clone, Src, Dst> Clone for Scale<T, Src, Dst> {
    fn clone(&self) -> Scale<T, Src, Dst> {
        Scale::new(self.get())
    }
}

impl<T: Copy, Src, Dst> Copy for Scale<T, Src, Dst> {}

impl<T: fmt::Debug, Src, Dst> fmt::Debug for Scale<T, Src, Dst> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl<T: fmt::Display, Src, Dst> fmt::Display for Scale<T, Src, Dst> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

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

    enum Inch {}
    enum Cm {}
    enum Mm {}

    #[test]
    fn test_scale() {
        let mm_per_inch: Scale<f32, Inch, Mm> = Scale::new(25.4);
        let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);

        let mm_per_cm: Scale<f32, Cm, Mm> = cm_per_mm.inv();
        assert_eq!(mm_per_cm.get(), 10.0);

        let cm_per_inch: Scale<f32, Inch, Cm> = mm_per_inch * cm_per_mm;
        assert_eq!(cm_per_inch, Scale::new(2.54));

        let a: Scale<isize, Inch, Inch> = Scale::new(2);
        let b: Scale<isize, Inch, Inch> = Scale::new(3);
        assert!(a != b);
        assert_eq!(a, a.clone());
        assert_eq!(a.clone() + b.clone(), Scale::new(5));
        assert_eq!(a - b, Scale::new(-1));
    }
}
<|endoftext|>


<commit_before>use quote::{Tokens, Ident};
use structs::Struct;

pub fn derive_slice(input: &Struct) -> Tokens {
    let derives = &input.derive_no_clone;
    let visibility = &input.visibility;
    let slice_name = &input.slice_name();
    let ref_name = &input.ref_name();

    let slice_name_str = format!("[{}]", input.name);
    let doc_url = format!("[`{0}`](struct.{0}.html)", input.name);
    let vec_doc_url = format!("[`{0}`](struct.{0}.html)", input.vec_name());

    let fields_names = input.fields.iter()
                                   .map(|field| field.ident.clone().unwrap())
                                   .collect::<Vec<_>>();
    let fields_names_1 = &fields_names;
    let fields_names_2 = &fields_names;
    let first_field = &fields_names[0];
    let slice_names_1 = &input.fields.iter().map(|field|
        Ident::from(format!("{}_slice_1", field.ident.as_ref().unwrap())))
        .collect::<Vec<_>>();
    let slice_names_2 = &input.fields.iter().map(|field|
        Ident::from(format!("{}_slice_2", field.ident.as_ref().unwrap())))
        .collect::<Vec<_>>();

    let fields_types = &input.fields.iter()
                                    .map(|field| &field.ty)
                                    .collect::<Vec<_>>();

    quote! {
        /// A slice of
        #[doc = #doc_url]
        /// inside a
        #[doc = #vec_doc_url]
        /// .
        #[allow(dead_code)]
        #derives
        #visibility struct #slice_name<'a> {
            #(pub #fields_names_1: &'a [#fields_types],)*
        }

        #[allow(dead_code)]
        impl<'a> #slice_name<'a> {
            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::len()`](https://doc.rust-lang.org/std/primitive.slice.html#method.len),
            /// the length of all fields should be the same.
            pub fn len(&self) -> usize {
                let len = self.#first_field.len();
                #(debug_assert_eq!(self.#fields_names_1.len(), len);)*
                len
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::is_empty()`](https://doc.rust-lang.org/std/primitive.slice.html#method.is_empty),
            /// the length of all fields should be the same.
            pub fn is_empty(&self) -> bool {
                let empty = self.#first_field.is_empty();
                #(debug_assert_eq!(self.#fields_names_1.is_empty(), empty);)*
                empty
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::first()`](https://doc.rust-lang.org/std/primitive.slice.html#method.first).
            pub fn first(&self) -> Option<#ref_name> {
                if self.is_empty() {
                    None
                } else {
                    #(
                        let #fields_names_1 = self.#fields_names_2.first().unwrap();
                    )*
                    Some(#ref_name{#(#fields_names_1: #fields_names_2),*})
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::split_first()`](https://doc.rust-lang.org/std/primitive.slice.html#method.split_first).
            pub fn split_first(&self) -> Option<(#ref_name, #slice_name)> {
                if self.is_empty() {
                    None
                } else {
                    #(
                        let (#fields_names_1, #slice_names_1) = self.#fields_names_2.split_first().unwrap();
                    )*
                    let ref_ = #ref_name{#(#fields_names_1: #fields_names_2),*};
                    let slice = #slice_name{#(#fields_names_1: #slice_names_1),*};
                    Some((ref_, slice))
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::last()`](https://doc.rust-lang.org/std/primitive.slice.html#method.last).
            pub fn last(&self) -> Option<#ref_name> {
                if self.is_empty() {
                    None
                } else {
                    #(
                        let #fields_names_1 = self.#fields_names_2.last().unwrap();
                    )*
                    Some(#ref_name{#(#fields_names_1: #fields_names_2),*})
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::split_last()`](https://doc.rust-lang.org/std/primitive.slice.html#method.split_last).
            pub fn split_last(&self) -> Option<(#ref_name, #slice_name)> {
                if self.is_empty() {
                    None
                } else {
                    #(
                        let (#fields_names_1, #slice_names_1) = self.#fields_names_2.split_last().unwrap();
                    )*
                    let ref_ = #ref_name{#(#fields_names_1: #fields_names_2),*};
                    let slice = #slice_name{#(#fields_names_1: #slice_names_1),*};
                    Some((ref_, slice))
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::split_at()`](https://doc.rust-lang.org/std/primitive.slice.html#method.split_at).
            pub fn split_at(&self, mid: usize) -> (#slice_name, #slice_name) {
                #(
                    let (#slice_names_1, #slice_names_2) = self.#fields_names_2.split_at(mid);
                )*
                let left = #slice_name{#(#fields_names_1: #slice_names_1),*};
                let right = #slice_name{#(#fields_names_1: #slice_names_2),*};
                (left, right)
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::get()`](https://doc.rust-lang.org/std/primitive.slice.html#method.get).
            pub fn get(&self, i: usize) -> Option<#ref_name> {
                if self.is_empty() || i >= self.len() {
                    None
                } else {
                    Some(#ref_name {
                        #(#fields_names_1: self.#fields_names_2.get(i).unwrap(),)*
                    })
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::get_unchecked()`](https://doc.rust-lang.org/std/primitive.slice.html#method.get_unchecked).
            pub unsafe fn get_unchecked(&self, i: usize) -> #ref_name {
                #ref_name {
                    #(#fields_names_1: self.#fields_names_2.get_unchecked(i),)*
                }
            }
        }
    }
}

pub fn derive_slice_mut(input: &Struct) -> Tokens {
    let derives = &input.derive_no_clone;
    let visibility = &input.visibility;
    let slice_name = &input.slice_name();
    let slice_mut_name = &input.slice_mut_name();
    let ref_name = &input.ref_name();
    let ref_mut_name = &input.ref_mut_name();

    let slice_name_str = format!("[{}]", input.name);
    let doc_url = format!("[`{0}`](struct.{0}.html)", input.name);
    let slice_doc_url = format!("[`{0}`](struct.{0}.html)", slice_name);
    let slice_mut_doc_url = format!("[`{0}`](struct.{0}.html)", slice_mut_name);
    let vec_doc_url = format!("[`{0}`](struct.{0}.html)", input.vec_name());

    let fields_names = input.fields.iter()
                                   .map(|field| field.ident.clone().unwrap())
                                   .collect::<Vec<_>>();
    let fields_names_1 = &fields_names;
    let fields_names_2 = &fields_names;
    let first_field = &fields_names[0];
    let slice_names_1 = &input.fields.iter().map(|field|
        Ident::from(format!("{}_slice_1", field.ident.as_ref().unwrap())))
        .collect::<Vec<_>>();
    let slice_names_2 = &input.fields.iter().map(|field|
        Ident::from(format!("{}_slice_2", field.ident.as_ref().unwrap())))
        .collect::<Vec<_>>();

    let fields_types = &input.fields.iter()
                                    .map(|field| &field.ty)
                                    .collect::<Vec<_>>();

    quote! {
        /// A mutable slice of
        #[doc = #doc_url]
        /// inside a
        #[doc = #vec_doc_url]
        /// .
        #[allow(dead_code)]
        #derives
        #visibility struct #slice_mut_name<'a> {
            #(pub #fields_names_1: &'a mut [#fields_types],)*
        }

        #[allow(dead_code)]
        impl<'a> #slice_mut_name<'a> {
            /// Convert a
            #[doc = #slice_mut_doc_url]
            /// to a
            #[doc = #slice_doc_url]
            /// in order to be able to use the methods on the non mutable
            /// version of the slices.
            pub fn as_ref(&self) -> #slice_name {
                #slice_name {
                    #(#fields_names_1: self.#fields_names_2,)*
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::len()`](https://doc.rust-lang.org/std/primitive.slice.html#method.len),
            /// the length of all fields should be the same.
            pub fn len(&self) -> usize {
                let len = self.#first_field.len();
                #(debug_assert_eq!(self.#fields_names_1.len(), len);)*
                len
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::is_empty()`](https://doc.rust-lang.org/std/primitive.slice.html#method.is_empty),
            /// the length of all fields should be the same.
            pub fn is_empty(&self) -> bool {
                let empty = self.#first_field.is_empty();
                #(debug_assert_eq!(self.#fields_names_1.is_empty(), empty);)*
                empty
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::first_mut()`](https://doc.rust-lang.org/std/primitive.slice.html#method.first_mut).
            pub fn first_mut(&mut self) -> Option<#ref_mut_name> {
                if self.is_empty() {
                    None
                } else {
                    #(
                        let #fields_names_1 = self.#fields_names_2.first_mut().unwrap();
                    )*
                    Some(#ref_mut_name{#(#fields_names_1: #fields_names_2),*})
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::split_first_mut()`](https://doc.rust-lang.org/std/primitive.slice.html#method.split_first_mut).
            pub fn split_first_mut(&mut self) -> Option<(#ref_mut_name, #slice_mut_name)> {
                if self.is_empty() {
                    None
                } else {
                    #(
                        let (#fields_names_1, #slice_names_1) = self.#fields_names_2.split_first_mut().unwrap();
                    )*
                    let ref_ = #ref_mut_name{#(#fields_names_1: #fields_names_2),*};
                    let slice = #slice_mut_name{#(#fields_names_1: #slice_names_1),*};
                    Some((ref_, slice))
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::last_mut()`](https://doc.rust-lang.org/std/primitive.slice.html#method.last_mut).
            pub fn last_mut(&mut self) -> Option<#ref_mut_name> {
                if self.is_empty() {
                    None
                } else {
                    #(
                        let #fields_names_1 = self.#fields_names_2.last_mut().unwrap();
                    )*
                    Some(#ref_mut_name{#(#fields_names_1: #fields_names_2),*})
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::last_mut()`](https://doc.rust-lang.org/std/primitive.slice.html#method.last_mut).
            pub fn split_last_mut(&mut self) -> Option<(#ref_mut_name, #slice_mut_name)> {
                if self.is_empty() {
                    None
                } else {
                    #(
                        let (#fields_names_1, #slice_names_1) = self.#fields_names_2.split_last_mut().unwrap();
                    )*
                    let ref_ = #ref_mut_name{#(#fields_names_1: #fields_names_2),*};
                    let slice = #slice_mut_name{#(#fields_names_1: #slice_names_1),*};
                    Some((ref_, slice))
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::split_at_mut()`](https://doc.rust-lang.org/std/primitive.slice.html#method.split_at_mut).
            pub fn split_at_mut(&mut self, mid: usize) -> (#slice_mut_name, #slice_mut_name) {
                #(
                    let (#slice_names_1, #slice_names_2) = self.#fields_names_2.split_at_mut(mid);
                )*
                let left = #slice_mut_name{#(#fields_names_1: #slice_names_1),*};
                let right = #slice_mut_name{#(#fields_names_1: #slice_names_2),*};
                (left, right)
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::swap()`](https://doc.rust-lang.org/std/primitive.slice.html#method.swap).
            pub fn swap(&mut self, a: usize, b: usize) {
                #(
                    self.#fields_names_1.swap(a, b);
                )*
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::get()`](https://doc.rust-lang.org/std/primitive.slice.html#method.get).
            pub fn get(&self, i: usize) -> Option<#ref_name> {
                if self.is_empty() || i >= self.len() {
                    None
                } else {
                    Some(#ref_name {
                        #(#fields_names_1: self.#fields_names_2.get(i).unwrap(),)*
                    })
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::get_unchecked()`](https://doc.rust-lang.org/std/primitive.slice.html#method.get_unchecked).
            pub unsafe fn get_unchecked(&self, i: usize) -> #ref_name {
                #ref_name {
                    #(#fields_names_1: self.#fields_names_2.get_unchecked(i),)*
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::get_mut()`](https://doc.rust-lang.org/std/primitive.slice.html#method.get_mut).
            pub fn get_mut(&mut self, i: usize) -> Option<#ref_mut_name> {
                if self.is_empty() || i >= self.len() {
                    None
                } else {
                    Some(#ref_mut_name {
                        #(#fields_names_1: self.#fields_names_2.get_mut(i).unwrap(),)*
                    })
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::get_unchecked_mut()`](https://doc.rust-lang.org/std/primitive.slice.html#method.get_unchecked_mut).
            pub unsafe fn get_unchecked_mut(&mut self, i: usize) -> #ref_mut_name {
                #ref_mut_name {
                    #(#fields_names_1: self.#fields_names_2.get_unchecked_mut(i),)*
                }
            }
        }
    }
}
<commit_msg>Add slice::to_vec function<commit_after>use quote::{Tokens, Ident};
use structs::Struct;

pub fn derive_slice(input: &Struct) -> Tokens {
    let derives = &input.derive_no_clone;
    let visibility = &input.visibility;
    let slice_name = &input.slice_name();
    let vec_name = &input.vec_name();
    let ref_name = &input.ref_name();

    let slice_name_str = format!("[{}]", input.name);
    let doc_url = format!("[`{0}`](struct.{0}.html)", input.name);
    let vec_doc_url = format!("[`{0}`](struct.{0}.html)", input.vec_name());

    let fields_names = input.fields.iter()
                                   .map(|field| field.ident.clone().unwrap())
                                   .collect::<Vec<_>>();
    let fields_names_1 = &fields_names;
    let fields_names_2 = &fields_names;
    let first_field = &fields_names[0];
    let slice_names_1 = &input.fields.iter().map(|field|
        Ident::from(format!("{}_slice_1", field.ident.as_ref().unwrap())))
        .collect::<Vec<_>>();
    let slice_names_2 = &input.fields.iter().map(|field|
        Ident::from(format!("{}_slice_2", field.ident.as_ref().unwrap())))
        .collect::<Vec<_>>();

    let fields_types = &input.fields.iter()
                                    .map(|field| &field.ty)
                                    .collect::<Vec<_>>();

    quote! {
        /// A slice of
        #[doc = #doc_url]
        /// inside a
        #[doc = #vec_doc_url]
        /// .
        #[allow(dead_code)]
        #derives
        #visibility struct #slice_name<'a> {
            #(pub #fields_names_1: &'a [#fields_types],)*
        }

        #[allow(dead_code)]
        impl<'a> #slice_name<'a> {
            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::len()`](https://doc.rust-lang.org/std/primitive.slice.html#method.len),
            /// the length of all fields should be the same.
            pub fn len(&self) -> usize {
                let len = self.#first_field.len();
                #(debug_assert_eq!(self.#fields_names_1.len(), len);)*
                len
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::is_empty()`](https://doc.rust-lang.org/std/primitive.slice.html#method.is_empty),
            /// the length of all fields should be the same.
            pub fn is_empty(&self) -> bool {
                let empty = self.#first_field.is_empty();
                #(debug_assert_eq!(self.#fields_names_1.is_empty(), empty);)*
                empty
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::first()`](https://doc.rust-lang.org/std/primitive.slice.html#method.first).
            pub fn first(&self) -> Option<#ref_name> {
                if self.is_empty() {
                    None
                } else {
                    #(
                        let #fields_names_1 = self.#fields_names_2.first().unwrap();
                    )*
                    Some(#ref_name{#(#fields_names_1: #fields_names_2),*})
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::split_first()`](https://doc.rust-lang.org/std/primitive.slice.html#method.split_first).
            pub fn split_first(&self) -> Option<(#ref_name, #slice_name)> {
                if self.is_empty() {
                    None
                } else {
                    #(
                        let (#fields_names_1, #slice_names_1) = self.#fields_names_2.split_first().unwrap();
                    )*
                    let ref_ = #ref_name{#(#fields_names_1: #fields_names_2),*};
                    let slice = #slice_name{#(#fields_names_1: #slice_names_1),*};
                    Some((ref_, slice))
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::last()`](https://doc.rust-lang.org/std/primitive.slice.html#method.last).
            pub fn last(&self) -> Option<#ref_name> {
                if self.is_empty() {
                    None
                } else {
                    #(
                        let #fields_names_1 = self.#fields_names_2.last().unwrap();
                    )*
                    Some(#ref_name{#(#fields_names_1: #fields_names_2),*})
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::split_last()`](https://doc.rust-lang.org/std/primitive.slice.html#method.split_last).
            pub fn split_last(&self) -> Option<(#ref_name, #slice_name)> {
                if self.is_empty() {
                    None
                } else {
                    #(
                        let (#fields_names_1, #slice_names_1) = self.#fields_names_2.split_last().unwrap();
                    )*
                    let ref_ = #ref_name{#(#fields_names_1: #fields_names_2),*};
                    let slice = #slice_name{#(#fields_names_1: #slice_names_1),*};
                    Some((ref_, slice))
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::split_at()`](https://doc.rust-lang.org/std/primitive.slice.html#method.split_at).
            pub fn split_at(&self, mid: usize) -> (#slice_name, #slice_name) {
                #(
                    let (#slice_names_1, #slice_names_2) = self.#fields_names_2.split_at(mid);
                )*
                let left = #slice_name{#(#fields_names_1: #slice_names_1),*};
                let right = #slice_name{#(#fields_names_1: #slice_names_2),*};
                (left, right)
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::get()`](https://doc.rust-lang.org/std/primitive.slice.html#method.get).
            pub fn get(&self, i: usize) -> Option<#ref_name> {
                if self.is_empty() || i >= self.len() {
                    None
                } else {
                    Some(#ref_name {
                        #(#fields_names_1: self.#fields_names_2.get(i).unwrap(),)*
                    })
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::get_unchecked()`](https://doc.rust-lang.org/std/primitive.slice.html#method.get_unchecked).
            pub unsafe fn get_unchecked(&self, i: usize) -> #ref_name {
                #ref_name {
                    #(#fields_names_1: self.#fields_names_2.get_unchecked(i),)*
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::to_vec()`](https://doc.rust-lang.org/std/primitive.slice.html#method.to_vec).
            pub fn to_vec(&self) -> #vec_name {
                #vec_name {
                    #(#fields_names_1: self.#fields_names_2.to_vec(),)*
                }
            }
        }
    }
}

pub fn derive_slice_mut(input: &Struct) -> Tokens {
    let derives = &input.derive_no_clone;
    let visibility = &input.visibility;
    let slice_name = &input.slice_name();
    let slice_mut_name = &input.slice_mut_name();
    let ref_name = &input.ref_name();
    let ref_mut_name = &input.ref_mut_name();

    let slice_name_str = format!("[{}]", input.name);
    let doc_url = format!("[`{0}`](struct.{0}.html)", input.name);
    let slice_doc_url = format!("[`{0}`](struct.{0}.html)", slice_name);
    let slice_mut_doc_url = format!("[`{0}`](struct.{0}.html)", slice_mut_name);
    let vec_doc_url = format!("[`{0}`](struct.{0}.html)", input.vec_name());

    let fields_names = input.fields.iter()
                                   .map(|field| field.ident.clone().unwrap())
                                   .collect::<Vec<_>>();
    let fields_names_1 = &fields_names;
    let fields_names_2 = &fields_names;
    let first_field = &fields_names[0];
    let slice_names_1 = &input.fields.iter().map(|field|
        Ident::from(format!("{}_slice_1", field.ident.as_ref().unwrap())))
        .collect::<Vec<_>>();
    let slice_names_2 = &input.fields.iter().map(|field|
        Ident::from(format!("{}_slice_2", field.ident.as_ref().unwrap())))
        .collect::<Vec<_>>();

    let fields_types = &input.fields.iter()
                                    .map(|field| &field.ty)
                                    .collect::<Vec<_>>();

    quote! {
        /// A mutable slice of
        #[doc = #doc_url]
        /// inside a
        #[doc = #vec_doc_url]
        /// .
        #[allow(dead_code)]
        #derives
        #visibility struct #slice_mut_name<'a> {
            #(pub #fields_names_1: &'a mut [#fields_types],)*
        }

        #[allow(dead_code)]
        impl<'a> #slice_mut_name<'a> {
            /// Convert a
            #[doc = #slice_mut_doc_url]
            /// to a
            #[doc = #slice_doc_url]
            /// in order to be able to use the methods on the non mutable
            /// version of the slices.
            pub fn as_ref(&self) -> #slice_name {
                #slice_name {
                    #(#fields_names_1: self.#fields_names_2,)*
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::len()`](https://doc.rust-lang.org/std/primitive.slice.html#method.len),
            /// the length of all fields should be the same.
            pub fn len(&self) -> usize {
                let len = self.#first_field.len();
                #(debug_assert_eq!(self.#fields_names_1.len(), len);)*
                len
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::is_empty()`](https://doc.rust-lang.org/std/primitive.slice.html#method.is_empty),
            /// the length of all fields should be the same.
            pub fn is_empty(&self) -> bool {
                let empty = self.#first_field.is_empty();
                #(debug_assert_eq!(self.#fields_names_1.is_empty(), empty);)*
                empty
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::first_mut()`](https://doc.rust-lang.org/std/primitive.slice.html#method.first_mut).
            pub fn first_mut(&mut self) -> Option<#ref_mut_name> {
                if self.is_empty() {
                    None
                } else {
                    #(
                        let #fields_names_1 = self.#fields_names_2.first_mut().unwrap();
                    )*
                    Some(#ref_mut_name{#(#fields_names_1: #fields_names_2),*})
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::split_first_mut()`](https://doc.rust-lang.org/std/primitive.slice.html#method.split_first_mut).
            pub fn split_first_mut(&mut self) -> Option<(#ref_mut_name, #slice_mut_name)> {
                if self.is_empty() {
                    None
                } else {
                    #(
                        let (#fields_names_1, #slice_names_1) = self.#fields_names_2.split_first_mut().unwrap();
                    )*
                    let ref_ = #ref_mut_name{#(#fields_names_1: #fields_names_2),*};
                    let slice = #slice_mut_name{#(#fields_names_1: #slice_names_1),*};
                    Some((ref_, slice))
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::last_mut()`](https://doc.rust-lang.org/std/primitive.slice.html#method.last_mut).
            pub fn last_mut(&mut self) -> Option<#ref_mut_name> {
                if self.is_empty() {
                    None
                } else {
                    #(
                        let #fields_names_1 = self.#fields_names_2.last_mut().unwrap();
                    )*
                    Some(#ref_mut_name{#(#fields_names_1: #fields_names_2),*})
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::last_mut()`](https://doc.rust-lang.org/std/primitive.slice.html#method.last_mut).
            pub fn split_last_mut(&mut self) -> Option<(#ref_mut_name, #slice_mut_name)> {
                if self.is_empty() {
                    None
                } else {
                    #(
                        let (#fields_names_1, #slice_names_1) = self.#fields_names_2.split_last_mut().unwrap();
                    )*
                    let ref_ = #ref_mut_name{#(#fields_names_1: #fields_names_2),*};
                    let slice = #slice_mut_name{#(#fields_names_1: #slice_names_1),*};
                    Some((ref_, slice))
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::split_at_mut()`](https://doc.rust-lang.org/std/primitive.slice.html#method.split_at_mut).
            pub fn split_at_mut(&mut self, mid: usize) -> (#slice_mut_name, #slice_mut_name) {
                #(
                    let (#slice_names_1, #slice_names_2) = self.#fields_names_2.split_at_mut(mid);
                )*
                let left = #slice_mut_name{#(#fields_names_1: #slice_names_1),*};
                let right = #slice_mut_name{#(#fields_names_1: #slice_names_2),*};
                (left, right)
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::swap()`](https://doc.rust-lang.org/std/primitive.slice.html#method.swap).
            pub fn swap(&mut self, a: usize, b: usize) {
                #(
                    self.#fields_names_1.swap(a, b);
                )*
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::get()`](https://doc.rust-lang.org/std/primitive.slice.html#method.get).
            pub fn get(&self, i: usize) -> Option<#ref_name> {
                if self.is_empty() || i >= self.len() {
                    None
                } else {
                    Some(#ref_name {
                        #(#fields_names_1: self.#fields_names_2.get(i).unwrap(),)*
                    })
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::get_unchecked()`](https://doc.rust-lang.org/std/primitive.slice.html#method.get_unchecked).
            pub unsafe fn get_unchecked(&self, i: usize) -> #ref_name {
                #ref_name {
                    #(#fields_names_1: self.#fields_names_2.get_unchecked(i),)*
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::get_mut()`](https://doc.rust-lang.org/std/primitive.slice.html#method.get_mut).
            pub fn get_mut(&mut self, i: usize) -> Option<#ref_mut_name> {
                if self.is_empty() || i >= self.len() {
                    None
                } else {
                    Some(#ref_mut_name {
                        #(#fields_names_1: self.#fields_names_2.get_mut(i).unwrap(),)*
                    })
                }
            }

            /// Similar to [`
            #[doc = #slice_name_str]
            /// ::get_unchecked_mut()`](https://doc.rust-lang.org/std/primitive.slice.html#method.get_unchecked_mut).
            pub unsafe fn get_unchecked_mut(&mut self, i: usize) -> #ref_mut_name {
                #ref_mut_name {
                    #(#fields_names_1: self.#fields_names_2.get_unchecked_mut(i),)*
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use libc;
use platform;
use std::ptr;
use std::os::{errno, page_size, MemoryMap, MapReadable, MapWritable,
              MapNonStandardFlags};

const STACK_FLAGS: libc::c_int = libc::MAP_STACK
                               | libc::MAP_PRIVATE
                               | libc::MAP_ANON;

pub enum Stack {
  Native {
    sp_limit: *const u8
  },
  Managed {
    buf: MemoryMap,
    valgrind_id: libc::c_uint
  }
}

impl Stack {
  pub fn new(size: uint) -> Stack {
    let buf = match MemoryMap::new(size, &[MapReadable, MapWritable,
                                   MapNonStandardFlags(STACK_FLAGS)]) {
      Ok(map) => map,
      Err(e) => panic!("mmap for stack of size {} failed: {}", size, e)
    };

    if !protect_last_page(&buf) {
      panic!("Could not memory-protect guard page. stack={}, errno={}",
             buf.data(), errno());
    }

    let valgrind_id = unsafe {
      platform::stack_register(buf.data().offset(buf.len() as int) as *const _,
                               buf.data() as *const _)
    };

    let stk = Stack::Managed {
      buf: buf,
      valgrind_id: valgrind_id
    };

    stk
  }

  pub unsafe fn native(limit: *const u8) -> Stack {
    Stack::Native {
      sp_limit: limit
    }
  }

  pub fn top(&self) -> *mut u8 {
    unsafe {
      match *self {
        Stack::Native { .. } => ptr::null_mut(),
        Stack::Managed { ref buf, .. } => {
          buf.data().offset(buf.len() as int)
        }
      }
    }
  }

  pub fn limit(&self) -> *const u8 {
    unsafe {
      match *self {
        Stack::Native { sp_limit, .. } => sp_limit,
        Stack::Managed { ref buf, .. } => {
          buf.data().offset(page_size() as int) as *const _
        }
      }
    }
  }
}

fn protect_last_page(stack: &MemoryMap) -> bool {
  unsafe {
    let last_page = stack.data() as *mut libc::c_void;
    libc::mprotect(last_page, page_size() as libc::size_t,
                   libc::PROT_NONE) != -1
  }
}

impl Drop for Stack {
  fn drop(&mut self) {
    match *self {
      Stack::Native { .. } => {},
      Stack::Managed { valgrind_id, .. } => unsafe {
        platform::stack_deregister(valgrind_id);
      }
    }
  }
}
<commit_msg>Stack.top returns a mutable pointer, so it should take &mut self<commit_after>use libc;
use platform;
use std::ptr;
use std::os::{errno, page_size, MemoryMap, MapReadable, MapWritable,
              MapNonStandardFlags};

const STACK_FLAGS: libc::c_int = libc::MAP_STACK
                               | libc::MAP_PRIVATE
                               | libc::MAP_ANON;

pub enum Stack {
  Native {
    sp_limit: *const u8
  },
  Managed {
    buf: MemoryMap,
    valgrind_id: libc::c_uint
  }
}

impl Stack {
  pub fn new(size: uint) -> Stack {
    let buf = match MemoryMap::new(size, &[MapReadable, MapWritable,
                                   MapNonStandardFlags(STACK_FLAGS)]) {
      Ok(map) => map,
      Err(e) => panic!("mmap for stack of size {} failed: {}", size, e)
    };

    if !protect_last_page(&buf) {
      panic!("Could not memory-protect guard page. stack={}, errno={}",
             buf.data(), errno());
    }

    let valgrind_id = unsafe {
      platform::stack_register(buf.data().offset(buf.len() as int) as *const _,
                               buf.data() as *const _)
    };

    let stk = Stack::Managed {
      buf: buf,
      valgrind_id: valgrind_id
    };

    stk
  }

  pub unsafe fn native(limit: *const u8) -> Stack {
    Stack::Native {
      sp_limit: limit
    }
  }

  pub fn top(&mut self) -> *mut u8 {
    unsafe {
      match *self {
        Stack::Native { .. } => ptr::null_mut(),
        Stack::Managed { ref buf, .. } => {
          buf.data().offset(buf.len() as int)
        }
      }
    }
  }

  pub fn limit(&self) -> *const u8 {
    unsafe {
      match *self {
        Stack::Native { sp_limit, .. } => sp_limit,
        Stack::Managed { ref buf, .. } => {
          buf.data().offset(page_size() as int) as *const _
        }
      }
    }
  }
}

fn protect_last_page(stack: &MemoryMap) -> bool {
  unsafe {
    let last_page = stack.data() as *mut libc::c_void;
    libc::mprotect(last_page, page_size() as libc::size_t,
                   libc::PROT_NONE) != -1
  }
}

impl Drop for Stack {
  fn drop(&mut self) {
    match *self {
      Stack::Native { .. } => {},
      Stack::Managed { valgrind_id, .. } => unsafe {
        platform::stack_deregister(valgrind_id);
      }
    }
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, edef <edef@edef.eu>
// See the LICENSE file included in this distribution.
//! Traits for stacks.
use core::prelude::*;

/// A trait for objects that hold ownership of a stack.
pub trait Stack {
  /// Returns the top of the stack.
  /// On all modern architectures, the stack grows downwards,
  /// so this is the highest address.
  fn top(&mut self) -> *mut u8;
  /// Returns the bottom of the stack.
  /// On all modern architectures, the stack grows downwards,
  /// so this is the lowest address.
  fn limit(&self) -> *const u8;
}

/// A trait for objects that provide stacks of arbitrary size.
pub trait StackSource {
  type Output: Stack;
  type Error = ();
  fn get_stack(size: usize) -> Result<Self::Output, Self::Error>;
}
<commit_msg>require Stack::Error to implement Debug + Display<commit_after>// Copyright (c) 2015, edef <edef@edef.eu>
// See the LICENSE file included in this distribution.
//! Traits for stacks.
use core::prelude::*;
use core::fmt::{Debug, Display};

/// A trait for objects that hold ownership of a stack.
pub trait Stack {
  /// Returns the top of the stack.
  /// On all modern architectures, the stack grows downwards,
  /// so this is the highest address.
  fn top(&mut self) -> *mut u8;
  /// Returns the bottom of the stack.
  /// On all modern architectures, the stack grows downwards,
  /// so this is the lowest address.
  fn limit(&self) -> *const u8;
}

/// A trait for objects that provide stacks of arbitrary size.
pub trait StackSource {
  type Output: Stack;
  type Error: Debug + Display = ();
  fn get_stack(size: usize) -> Result<Self::Output, Self::Error>;
}
<|endoftext|>


<commit_before>use std::collections::Bound::Included;
use std::collections::BTreeMap;
use std::u64;

pub struct Store<'a> {
  max_offset: u64,
  data: Box<BTreeMap<&'a str, Box<BTreeMap<u64, &'a [u8]>>>>
}

impl<'a> Store<'a> {
  pub fn new<'b>() -> Store<'b> {
    Store {
      max_offset: 0,
      data: Box::new(BTreeMap::new())
    }
  }

  pub fn add(&'a mut self, key: &'a str, value: &'a [u8]) {
    self.max_offset += 1;
    if self.data.get_mut(&key).is_none() {
      if self.data.insert(key, Box::new(BTreeMap::new())).is_some() {
        panic!("Invariant violation; duplicate version tree detected");
      }
    }

    if self.data.get_mut(&key).unwrap().insert(self.max_offset, value).is_some() {
      panic!("Invariant violation; duplicate offset detected");
    }
  }

  pub fn get(&'a mut self, key: &'a str) -> Option<&'a [u8]> {
    self.data.get(&key).map( |version_tree| {
      version_tree.range(Included(&u64::MAX), Included(&u64::MAX)).last().unwrap()
    })
  }
}

#[test]
fn add_something() {
  let mut store = Store::new();
  store.add("yo", b"ok");
}

#[test]
fn get_something() {
  let mut store = Store::new();
  store.add("spaghetti", b"I'm");
  store.add("spaghetti", b"James");
  store.add("spaghetti", b"Quall");
  store.add("spaghetti", b"spaghetti");
  store.add("spaghetti", b"and");
  store.add("spaghetti", b"meatballs");
  assert!(store.get("spaghetti") == Some(b"meatballs"));
}
<commit_msg>Whispering sweet nothings to rustc<commit_after>use std::collections::Bound::Included;
use std::collections::BTreeMap;
use std::u64;

pub struct Store<'a> {
  max_offset: u64,
  data: Box<BTreeMap<&'a str, Box<BTreeMap<u64, &'a [u8]>>>>
}

impl<'a> Store<'a> {
  pub fn new<'b>() -> Store<'b> {
    Store {
      max_offset: 0,
      data: Box::new(BTreeMap::new())
    }
  }

  pub fn add(&'a mut self, key: &'a str, value: &'a [u8]) {
    self.max_offset += 1;
    if self.data.get_mut(&key).is_none() {
      if self.data.insert(key, Box::new(BTreeMap::new())).is_some() {
        panic!("Invariant violation; duplicate version tree detected");
      }
    }

    if self.data.get_mut(&key).unwrap().insert(self.max_offset, value).is_some() {
      panic!("Invariant violation; duplicate offset detected");
    }
  }

  pub fn get(&'a mut self, key: &'a str) -> Option<&'a [u8]> {
    self.data.get(&key).map( |version_tree| {
      let (k, v) = version_tree.range(Included(&0), Included(&u64::MAX)).last().unwrap();
      *v
    })
  }
}

#[test]
fn add_something() {
  let mut store = Store::new();
  store.add("yo", b"ok");
}

#[test]
fn get_something() {
  let mut store = Store::new();
  store.add("spaghetti", b"I'm");
  store.add("spaghetti", b"James");
  store.add("spaghetti", b"Quall");
  store.add("spaghetti", b"spaghetti");
  store.add("spaghetti", b"and");
  store.add("spaghetti", b"meatballs");
  assert!(store.get("spaghetti") == Some(b"meatballs"));
}
<|endoftext|>


<commit_before>use definitions::{LiteralValue, ColumnDef, ColumnConstraint};

use std::collections::BTreeMap;
use std::fmt;

pub type TableRow = Vec<LiteralValue>;
pub type TableHeader = Vec<ColumnDef>;
pub type PkType = uint;

pub struct RowFormat<'a>(pub &'a TableRow);
pub struct HeaderFormat<'a>(pub &'a TableHeader);

pub struct Table {
    pub name: String,
    pub header: TableHeader,
    pub data: BTreeMap<PkType, TableRow>,
    pub pk: Option<PkType>,
}

impl Table {
    pub fn new_result_table(header: TableHeader) -> Table {
        Table {
            name: "".to_string(),
            header: header,
            data: BTreeMap::new(),
            pk: None,
        }
    }
    pub fn get_column_def_by_name(&self, name: &String) -> Option<&ColumnDef> {
        self.header.iter().find(|&cols| &cols.name == name)
    }

    pub fn get_column_index(&self, name: &String) -> Option<uint> {
        self.header.iter().position(|ref cols| &cols.name == name)
    }

    pub fn has_row(&self, pk: PkType) -> bool {
        self.data.contains_key(&pk)
    }

    pub fn assert_size(&self) {
        let header_size = self.header.len();

        for row in self.data.values() {
            assert!(row.len() == header_size);
        }
    }

    pub fn add_column(&mut self, column_def: ColumnDef) {
        self.header.push(column_def);

        for (_, row) in self.data.iter_mut() {
            row.push(LiteralValue::Null);
        }
    }

    pub fn add_columns(&mut self, column_defs: Vec<ColumnDef>) {
        for def in column_defs.into_iter() {
            self.add_column(def);
        }
    }

    pub fn insert(&mut self, column_data: Vec<TableRow>,
                  specified_columns: &Option<Vec<String>>) {
        for column_data in column_data.into_iter() {
            if let &Some(ref column_names) = specified_columns {
                assert!(column_names.len() == column_data.len());
                let mut row = Vec::from_elem(self.header.len(), LiteralValue::Null);

                for (name, data) in column_names.iter().zip(column_data.into_iter()) {
                    row[self.get_column_index(name).unwrap()] = data;
                }

                self.push_row(row);
            } else {
                self.push_row(column_data);
            }
        }
    }

    pub fn push_row(&mut self, row: TableRow) {
        if let Some(i) = self.pk {
            let pk = row[i].clone().to_uint();
            self.data.insert(pk, row);
        } else {
            let len = self.data.len();
            self.data.insert(len, row);
        }
    }

    pub fn delete_where(&mut self, f: |row: &TableRow| -> bool) {
        let mut keys: Vec<PkType> = Vec::new();

        for (key, row) in self.data.iter() {
            if !f(row) {
                continue;
            }
            keys.push(key.clone());
        }

        for key in keys.iter() {
            self.data.remove(key);
        }
    }

    pub fn clear(&mut self) {
        self.data.clear();
    }

    pub fn process_constraints(&mut self) {
        for (i, column) in self.header.iter().enumerate() {
            for constraint in column.column_constraints.iter() {
                match constraint {
                    &ColumnConstraint::PrimaryKey => self.pk = Some(i),
                }
            }
        }
    }
}

impl<'a> fmt::Show for RowFormat<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for column in self.0.iter() {
            write!(f, "{} | ", column).ok();
        }
        Ok(())
    }
}

impl<'a> fmt::Show for HeaderFormat<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for def in self.0.iter() {
            write!(f, "{} | ", def.name).ok();
        }
        Ok(())
    }
}

impl fmt::Show for Table {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.header.len() > 0 {
            writeln!(f, "{}", HeaderFormat(&self.header)).ok();
        }
        for row in self.data.values() {
            writeln!(f, "{}", RowFormat(row)).ok();
        }
        Ok(())
    }
}

pub fn get_column(name: &String, row: &TableRow, head: &TableHeader, offset: Option<uint>) -> LiteralValue {
    let x = if let Some(x) = offset { x } else { 0 };
    row[head.iter().position(|ref def| def.name == *name).unwrap() + x].clone()
}
<commit_msg>Fix deprecated warning on latest nightly<commit_after>use definitions::{LiteralValue, ColumnDef, ColumnConstraint};

use std::collections::BTreeMap;
use std::fmt;
use std::iter::repeat;

pub type TableRow = Vec<LiteralValue>;
pub type TableHeader = Vec<ColumnDef>;
pub type PkType = uint;

pub struct RowFormat<'a>(pub &'a TableRow);
pub struct HeaderFormat<'a>(pub &'a TableHeader);

pub struct Table {
    pub name: String,
    pub header: TableHeader,
    pub data: BTreeMap<PkType, TableRow>,
    pub pk: Option<PkType>,
}

impl Table {
    pub fn new_result_table(header: TableHeader) -> Table {
        Table {
            name: "".to_string(),
            header: header,
            data: BTreeMap::new(),
            pk: None,
        }
    }
    pub fn get_column_def_by_name(&self, name: &String) -> Option<&ColumnDef> {
        self.header.iter().find(|&cols| &cols.name == name)
    }

    pub fn get_column_index(&self, name: &String) -> Option<uint> {
        self.header.iter().position(|ref cols| &cols.name == name)
    }

    pub fn has_row(&self, pk: PkType) -> bool {
        self.data.contains_key(&pk)
    }

    pub fn assert_size(&self) {
        let header_size = self.header.len();

        for row in self.data.values() {
            assert!(row.len() == header_size);
        }
    }

    pub fn add_column(&mut self, column_def: ColumnDef) {
        self.header.push(column_def);

        for (_, row) in self.data.iter_mut() {
            row.push(LiteralValue::Null);
        }
    }

    pub fn add_columns(&mut self, column_defs: Vec<ColumnDef>) {
        for def in column_defs.into_iter() {
            self.add_column(def);
        }
    }

    pub fn insert(&mut self, column_data: Vec<TableRow>,
                  specified_columns: &Option<Vec<String>>) {
        for column_data in column_data.into_iter() {
            if let &Some(ref column_names) = specified_columns {
                assert!(column_names.len() == column_data.len());
                let mut row: TableRow = repeat(LiteralValue::Null).take(self.header.len()).collect();

                for (name, data) in column_names.iter().zip(column_data.into_iter()) {
                    row[self.get_column_index(name).unwrap()] = data;
                }

                self.push_row(row);
            } else {
                self.push_row(column_data);
            }
        }
    }

    pub fn push_row(&mut self, row: TableRow) {
        if let Some(i) = self.pk {
            let pk = row[i].clone().to_uint();
            self.data.insert(pk, row);
        } else {
            let len = self.data.len();
            self.data.insert(len, row);
        }
    }

    pub fn delete_where(&mut self, f: |row: &TableRow| -> bool) {
        let mut keys: Vec<PkType> = Vec::new();

        for (key, row) in self.data.iter() {
            if !f(row) {
                continue;
            }
            keys.push(key.clone());
        }

        for key in keys.iter() {
            self.data.remove(key);
        }
    }

    pub fn clear(&mut self) {
        self.data.clear();
    }

    pub fn process_constraints(&mut self) {
        for (i, column) in self.header.iter().enumerate() {
            for constraint in column.column_constraints.iter() {
                match constraint {
                    &ColumnConstraint::PrimaryKey => self.pk = Some(i),
                }
            }
        }
    }
}

impl<'a> fmt::Show for RowFormat<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for column in self.0.iter() {
            write!(f, "{} | ", column).ok();
        }
        Ok(())
    }
}

impl<'a> fmt::Show for HeaderFormat<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for def in self.0.iter() {
            write!(f, "{} | ", def.name).ok();
        }
        Ok(())
    }
}

impl fmt::Show for Table {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.header.len() > 0 {
            writeln!(f, "{}", HeaderFormat(&self.header)).ok();
        }
        for row in self.data.values() {
            writeln!(f, "{}", RowFormat(row)).ok();
        }
        Ok(())
    }
}

pub fn get_column(name: &String, row: &TableRow, head: &TableHeader, offset: Option<uint>) -> LiteralValue {
    let x = if let Some(x) = offset { x } else { 0 };
    row[head.iter().position(|ref def| def.name == *name).unwrap() + x].clone()
}
<|endoftext|>


<commit_before>use std::path::PathBuf;
use std::io::Read;

use error::RefErrorKind as REK;
use error::MapErrInto;

use crypto::sha1::Sha1;
use crypto::digest::Digest;

use result::Result;

/// The Hasher trait is used to implement custom hashing functions for the ref library.
/// This means that one can define how the hash of a reference is constructed from the content of
/// the file to ref to.
pub trait Hasher {

    fn hash_name(&self) -> &'static str;
    fn create_hash<R: Read>(&mut self, pb: &PathBuf, contents: &mut R) -> Result<String>;

}

pub struct DefaultHasher {
    hasher: Sha1,
}

impl DefaultHasher {

    pub fn new() -> DefaultHasher {
        DefaultHasher { hasher: Sha1::new() }
    }

}

impl Hasher for DefaultHasher {

    fn hash_name(&self) -> &'static str {
        "default"
    }

    fn create_hash<R: Read>(&mut self, _: &PathBuf, contents: &mut R) -> Result<String> {
        let mut s = String::new();
        try!(contents.read_to_string(&mut s).map_err_into(REK::IOError));
        self.hasher.input_str(&s[..]);
        Ok(self.hasher.result_str())
    }

}

<commit_msg>Use UTF8Error in default hasher impl<commit_after>use std::path::PathBuf;
use std::io::Read;

use error::RefErrorKind as REK;
use error::MapErrInto;

use crypto::sha1::Sha1;
use crypto::digest::Digest;

use result::Result;

/// The Hasher trait is used to implement custom hashing functions for the ref library.
/// This means that one can define how the hash of a reference is constructed from the content of
/// the file to ref to.
pub trait Hasher {

    fn hash_name(&self) -> &'static str;
    fn create_hash<R: Read>(&mut self, pb: &PathBuf, contents: &mut R) -> Result<String>;

}

pub struct DefaultHasher {
    hasher: Sha1,
}

impl DefaultHasher {

    pub fn new() -> DefaultHasher {
        DefaultHasher { hasher: Sha1::new() }
    }

}

impl Hasher for DefaultHasher {

    fn hash_name(&self) -> &'static str {
        "default"
    }

    fn create_hash<R: Read>(&mut self, _: &PathBuf, c: &mut R) -> Result<String> {
        let mut s = String::new();
        try!(c.read_to_string(&mut s).map_err_into(REK::UTF8Error).map_err_into(REK::IOError));
        self.hasher.input_str(&s[..]);
        Ok(self.hasher.result_str())
    }

}

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

use libimagstore::store::Store;
use libimagerror::trace::trace_error;
use std::error::Error;
use std::ops::Deref;
use std::ops::DerefMut;

use ruru::{Class, Object, AnyObject, Boolean, RString, VM, Hash, NilClass, VerifiedObject};

use ruby_utils::IntoToml;
use toml_utils::IntoRuby;
use util::Wrap;
use util::Unwrap;

use storeid::RStoreId;
use entry::RFileLockEntry;
use cache::StoreHandle;

wrappable_struct!(StoreHandle, StoreWrapper, STORE_WRAPPER);
class!(RStore);
impl_wrap!(StoreHandle, STORE_WRAPPER);
impl_unwrap!(RStore, StoreHandle, STORE_WRAPPER);
impl_verified_object!(RStore);

macro_rules! call_on_store_by_handle {
    ($store_handle:ident -> $name:ident -> $operation:block) => {{
        call_on_store_by_handle!($store_handle -> $name -> $operation on fail return NilClass::new().to_any_object())
    }};

    ($store_handle:ident -> $name:ident -> $operation:block on fail return $ex:expr) => {{
        use cache::RUBY_STORE_CACHE;

        let arc = RUBY_STORE_CACHE.clone();
        {
            let lock = arc.lock();
            match lock {
                Ok(mut hm) => {
                    match hm.get($store_handle) {
                        Some($name) => { $operation },
                        None => {
                            VM::raise(Class::from_existing("RuntimeError"),
                                    "Tried to operate on non-existing object");
                            $ex
                        }
                    }
                },
                Err(e) => {
                    VM::raise(Class::from_existing("RuntimeError"), e.description());
                    $ex
                }
            }
        }
    }};
}

macro_rules! call_on_store {
    ($itself:ident ($wrapper:ident) -> $name:ident -> $operation:block on fail return $ex:expr) => {{
        let handle = $itself.get_data(&*$wrapper);
        call_on_store_by_handle!(handle -> $name -> $operation on fail return $ex)
    }};
    ($itself:ident ($wrapper:ident) -> $name:ident -> $operation:block) => {{
        let handle = $itself.get_data(&*$wrapper);
        call_on_store_by_handle!(handle -> $name -> $operation)
    }};
}

methods!(
    RStore,
    itself,

    // Create an FileLockEntry in the store
    //
    // # Returns:
    //
    // On success: A RFileLockEntry
    // On failure: Nil
    // On error: Nil + Exception
    //
    fn create(id: RStoreId) -> AnyObject {
        unimplemented!()
    }

    // Retrieve an FileLockEntry from the store
    //
    // # Returns:
    //
    // On success: A RFileLockEntry
    // On error: Nil + Exception
    //
    fn retrieve(id: RStoreId) -> AnyObject {
        unimplemented!()
    }

    // Get an FileLockEntry from the store
    //
    // # Returns:
    //
    // On success, if there is some: A RFileLockEntry
    // On success, if there is none: Nil
    // On error: Nil + Exception
    //
    fn get(sid: RStoreId) -> AnyObject {
        unimplemented!()
    }

    // Get all FileLockEntry of a module from the store
    //
    // # Returns:
    //
    // On success: A Array[RFileLockEntry]
    // On error: Nil + Exception
    //
    fn retrieve_for_module(name: RString) -> AnyObject {
        unimplemented!()
    }

    // Update a FileLockEntry in the store
    //
    // # Returns:
    //
    // On success: Nil
    // On error: Nil + Exception
    //
    fn update(fle: RFileLockEntry) -> NilClass {
        unimplemented!()
    }

    // Delete a FileLockEntry from the store
    //
    // # Returns:
    //
    // On success: Nil
    // On error: Nil + Exception
    //
    fn delete(sid: RStoreId) -> NilClass {
        unimplemented!()
    }

    // Save a FileLockEntry in a new path inside the store, keep the RFileLockEntry
    //
    // # Returns:
    //
    // On success: Nil
    // On error: Nil + Exception
    //
    fn save_to(fle: RFileLockEntry, sid: RStoreId) -> NilClass {
        unimplemented!()
    }

    // Save a FileLockEntry in a new path inside the store, move the RFileLockEntry
    //
    // # Returns:
    //
    // On success: Nil
    // On error: Nil + Exception
    //
    fn save_as(fle: RFileLockEntry, sid: RStoreId) -> NilClass {
        unimplemented!()
    }

    // Move one entry in the store to another place, by its ID
    //
    // # Returns:
    //
    // On success: Nil
    // On error: Nil + Exception
    //
    fn move_by_id(old: RStoreId, nw: RStoreId) -> NilClass {
        let old = typecheck!(old).unwrap().clone();
        let nw  = typecheck!(nw).unwrap().clone();

        call_on_store!(itself (STORE_WRAPPER) -> store -> {
            if let Err(e) = store.move_by_id(old, nw) {
                trace_error(&e);
                VM::raise(Class::from_existing("RuntimeError"), e.description());
            }
            NilClass::new()
        } on fail return NilClass::new())
    }

    // Get the path of the store object
    //
    // # Returns:
    //
    // A RString
    //
    fn path() -> RString {
        call_on_store!(itself (STORE_WRAPPER) -> store -> {
            store.path()
                .clone()
                .to_str()
                .map(RString::new)
                .unwrap_or(RString::new(""))
        } on fail return RString::new(""))
    }

);

pub fn setup() {
    unimplemented!()
}
<commit_msg>Make macro more advanced, to be able to impl Store::save_{as,to}() interfaces<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
//

use libimagstore::store::Store;
use libimagerror::trace::trace_error;
use std::error::Error;
use std::ops::Deref;
use std::ops::DerefMut;

use ruru::{Class, Object, AnyObject, Boolean, RString, VM, Hash, NilClass, VerifiedObject};

use ruby_utils::IntoToml;
use toml_utils::IntoRuby;
use util::Wrap;
use util::Unwrap;

use storeid::RStoreId;
use entry::RFileLockEntry;
use cache::StoreHandle;

wrappable_struct!(StoreHandle, StoreWrapper, STORE_WRAPPER);
class!(RStore);
impl_wrap!(StoreHandle, STORE_WRAPPER);
impl_unwrap!(RStore, StoreHandle, STORE_WRAPPER);
impl_verified_object!(RStore);

macro_rules! call_on_store_by_handle {
    ($store_handle:ident -> $name:ident -> $operation:block) => {{
        call_on_store_by_handle!($store_handle -> $name -> $operation on fail return NilClass::new().to_any_object())
    }};

    ($store_handle:ident -> $name:ident -> $operation:block on fail return $ex:expr) => {{
        use cache::RUBY_STORE_CACHE;

        let arc = RUBY_STORE_CACHE.clone();
        {
            let lock = arc.lock();
            match lock {
                Ok(mut hm) => {
                    match hm.get($store_handle) {
                        Some($name) => { $operation },
                        None => {
                            VM::raise(Class::from_existing("RuntimeError"),
                                    "Tried to operate on non-existing object");
                            $ex
                        }
                    }
                },
                Err(e) => {
                    VM::raise(Class::from_existing("RuntimeError"), e.description());
                    $ex
                }
            }
        }
    }};
}

macro_rules! call_on_store {
    ($itself:ident ($wrapper:ident) -> $name:ident fetch $fle_handle_name:ident -> $fle_name:ident -> $operation:block) => {{
        call_on_store!($itself ($wrapper) -> $name fetch $fle_handle_name -> $fle_name -> $operation on fail return NilClass::new())
    }};
    ($itself:ident ($wrapper:ident) -> $name:ident fetch $fle_handle_name:ident -> $fle_name:ident -> $operation:block on fail return $ex:expr) => {{
        let handle = $itself.get_data(&*$wrapper);
        call_on_store_by_handle!(handle -> $name -> {
            let $fle_name = match $name.get($fle_handle_name) {
                Ok(Some(fle)) => fle,
                Ok(None) => {
                    VM::raise(Class::from_existing("RuntimeError"), "Obj does not exist");
                    return $ex
                },
                Err(e) => {
                    VM::raise(Class::from_existing("RuntimeError"), e.description());
                    return $ex
                },
            };
            $operation
        } on fail return $ex)
    }};

    ($itself:ident ($wrapper:ident) -> $name:ident -> $operation:block on fail return $ex:expr) => {{
        let handle = $itself.get_data(&*$wrapper);
        call_on_store_by_handle!(handle -> $name -> $operation on fail return $ex)
    }};
    ($itself:ident ($wrapper:ident) -> $name:ident -> $operation:block) => {{
        let handle = $itself.get_data(&*$wrapper);
        call_on_store_by_handle!(handle -> $name -> $operation)
    }};
}

methods!(
    RStore,
    itself,

    // Create an FileLockEntry in the store
    //
    // # Returns:
    //
    // On success: A RFileLockEntry
    // On failure: Nil
    // On error: Nil + Exception
    //
    fn create(id: RStoreId) -> AnyObject {
        unimplemented!()
    }

    // Retrieve an FileLockEntry from the store
    //
    // # Returns:
    //
    // On success: A RFileLockEntry
    // On error: Nil + Exception
    //
    fn retrieve(id: RStoreId) -> AnyObject {
        unimplemented!()
    }

    // Get an FileLockEntry from the store
    //
    // # Returns:
    //
    // On success, if there is some: A RFileLockEntry
    // On success, if there is none: Nil
    // On error: Nil + Exception
    //
    fn get(sid: RStoreId) -> AnyObject {
        unimplemented!()
    }

    // Get all FileLockEntry of a module from the store
    //
    // # Returns:
    //
    // On success: A Array[RFileLockEntry]
    // On error: Nil + Exception
    //
    fn retrieve_for_module(name: RString) -> AnyObject {
        unimplemented!()
    }

    // Update a FileLockEntry in the store
    //
    // # Returns:
    //
    // On success: Nil
    // On error: Nil + Exception
    //
    fn update(fle: RFileLockEntry) -> NilClass {
        unimplemented!()
    }

    // Delete a FileLockEntry from the store
    //
    // # Returns:
    //
    // On success: Nil
    // On error: Nil + Exception
    //
    fn delete(sid: RStoreId) -> NilClass {
        unimplemented!()
    }

    // Save a FileLockEntry in a new path inside the store, keep the RFileLockEntry
    //
    // # Returns:
    //
    // On success: Nil
    // On error: Nil + Exception
    //
    fn save_to(fle: RFileLockEntry, sid: RStoreId) -> NilClass {
        let fle = typecheck!(fle).unwrap().clone();
        let sid = typecheck!(sid).unwrap().clone();

        call_on_store!(itself (STORE_WRAPPER) -> store fetch fle -> real_fle -> {
            if let Err(e) = store.save_to(&real_fle, sid) {
                trace_error(&e);
                VM::raise(Class::from_existing("RuntimeError"), e.description());
            }
            NilClass::new()
        } on fail return NilClass::new())
    }

    // Save a FileLockEntry in a new path inside the store, move the RFileLockEntry
    //
    // # Returns:
    //
    // On success: Nil
    // On error: Nil + Exception
    //
    fn save_as(fle: RFileLockEntry, sid: RStoreId) -> NilClass {
        let fle = typecheck!(fle).unwrap().clone();
        let sid = typecheck!(sid).unwrap().clone();

        call_on_store!(itself (STORE_WRAPPER) -> store fetch fle -> real_fle -> {
            if let Err(e) = store.save_as(real_fle, sid) {
                trace_error(&e);
                VM::raise(Class::from_existing("RuntimeError"), e.description());
            }
            NilClass::new()
        } on fail return NilClass::new())
    }

    // Move one entry in the store to another place, by its ID
    //
    // # Returns:
    //
    // On success: Nil
    // On error: Nil + Exception
    //
    fn move_by_id(old: RStoreId, nw: RStoreId) -> NilClass {
        let old = typecheck!(old).unwrap().clone();
        let nw  = typecheck!(nw).unwrap().clone();

        call_on_store!(itself (STORE_WRAPPER) -> store -> {
            if let Err(e) = store.move_by_id(old, nw) {
                trace_error(&e);
                VM::raise(Class::from_existing("RuntimeError"), e.description());
            }
            NilClass::new()
        } on fail return NilClass::new())
    }

    // Get the path of the store object
    //
    // # Returns:
    //
    // A RString
    //
    fn path() -> RString {
        call_on_store!(itself (STORE_WRAPPER) -> store -> {
            store.path()
                .clone()
                .to_str()
                .map(RString::new)
                .unwrap_or(RString::new(""))
        } on fail return RString::new(""))
    }

);

pub fn setup() {
    unimplemented!()
}
<|endoftext|>