<commit_before>//! Shared access to Cairo image surfaces.
use std::ptr::NonNull;

use cairo::prelude::SurfaceExt;
use cairo::{self, ImageSurface};
use cairo_sys;
use glib::translate::{Stash, ToGlibPtr};
use rulinalg::matrix::{BaseMatrix, Matrix};

use filters::context::IRect;
use util::clamp;

use super::{
    iterators::{PixelRectangle, Pixels},
    EdgeMode,
    ImageSurfaceDataExt,
    Pixel,
};

/// Wrapper for a Cairo image surface that allows shared access.
///
/// There doesn't seem to be any good way of making safe shared access to `ImageSurface` pixel
/// data, since a read-only borrowed reference can still be cloned and then modified (for example,
/// via a `Context`). We can't simply use `ImageSurface::get_data()` because in the filter code we
/// have surfaces referenced from multiple places and it would probably add more complexity to
/// remove that and start passing around references.
///
/// This wrapper asserts the uniqueness of its image surface and doesn't permit modifying it.
///
/// Note: originally I had an idea of using `Rc<RefCell<ImageSurface>>` here which allows to create
/// both read-only and unique read-write accessors safely, however then I realized a read-write
/// accessor isn't of much use if it can't expose a Cairo context interface. Cairo contexts have
/// the very same issue that they can be cloned from a read-only reference and break all safety
/// constraints in this way. Thus the only safe way of exposing a Cairo context seemed to be to
/// manually add all Cairo context methods on the accessor forwarding to the underlying Cairo
/// context (without exposing the context itself to prevent cloning), which would result in too
/// much code. Unless it's absolutely required, I'd like to avoid that.
///
/// Having just read-only access simplifies things further dropping the need for `Rc<RefCell<>>`
/// altogether.
#[derive(Debug, Clone)]
pub struct SharedImageSurface {
    surface: ImageSurface,

    data_ptr: NonNull<u8>, // *const.
    width: i32,
    height: i32,
    stride: isize,
}

impl SharedImageSurface {
    /// Creates a `SharedImageSurface` from a unique `ImageSurface`.
    ///
    /// # Panics
    /// Panics if the `ImageSurface` is not unique, that is, its reference count isn't 1.
    #[inline]
    pub fn new(surface: ImageSurface) -> Result<Self, cairo::Status> {
        let reference_count =
            unsafe { cairo_sys::cairo_surface_get_reference_count(surface.to_raw_none()) };
        assert_eq!(reference_count, 1);

        surface.flush();
        if surface.status() != cairo::Status::Success {
            return Err(surface.status());
        }

        let data_ptr = NonNull::new(unsafe {
            cairo_sys::cairo_image_surface_get_data(surface.to_raw_none())
        }).unwrap();

        let width = surface.get_width();
        let height = surface.get_height();
        let stride = surface.get_stride() as isize;

        Ok(Self {
            surface,
            data_ptr,
            width,
            height,
            stride,
        })
    }

    /// Converts this `SharedImageSurface` back into a Cairo image surface.
    ///
    /// # Panics
    /// Panics if the underlying Cairo image surface is not unique, that is, there are other
    /// instances of `SharedImageSurface` pointing at the same Cairo image surface.
    #[inline]
    pub fn into_image_surface(self) -> ImageSurface {
        let reference_count =
            unsafe { cairo_sys::cairo_surface_get_reference_count(self.surface.to_raw_none()) };
        assert_eq!(reference_count, 1);

        self.surface
    }

    /// Returns the surface width.
    #[inline]
    pub fn width(&self) -> i32 {
        self.width
    }

    /// Returns the surface height.
    #[inline]
    pub fn height(&self) -> i32 {
        self.height
    }

    /// Retrieves the pixel value at the given coordinates.
    #[inline]
    pub fn get_pixel(&self, x: u32, y: u32) -> Pixel {
        assert!(x < self.width as u32);
        assert!(y < self.height as u32);

        let value = unsafe {
            *(self
                .data_ptr
                .as_ptr()
                .offset(y as isize * self.stride + x as isize * 4) as *const u32)
        };

        Pixel {
            r: ((value >> 16) & 0xFF) as u8,
            g: ((value >> 8) & 0xFF) as u8,
            b: (value & 0xFF) as u8,
            a: ((value >> 24) & 0xFF) as u8,
        }
    }

    /// Calls `set_source_surface()` on the given Cairo context.
    #[inline]
    pub fn set_as_source_surface(&self, cr: &cairo::Context, x: f64, y: f64) {
        cr.set_source_surface(&self.surface, x, y);
    }

    /// Returns a new `ImageSurface` with the same contents as the one stored in this
    /// `SharedImageSurface` within the given bounds.
    pub fn copy_surface(&self, bounds: IRect) -> Result<ImageSurface, cairo::Status> {
        let output_surface = ImageSurface::create(cairo::Format::ARgb32, self.width, self.height)?;

        let cr = cairo::Context::new(&output_surface);
        cr.rectangle(
            bounds.x0 as f64,
            bounds.y0 as f64,
            (bounds.x1 - bounds.x0) as f64,
            (bounds.y1 - bounds.y0) as f64,
        );
        cr.clip();

        cr.set_source_surface(&self.surface, 0f64, 0f64);
        cr.paint();

        Ok(output_surface)
    }

    /// Scales the given surface by `x` and `y` into a surface `width`×`height` in size, clipped by
    /// `bounds`.
    pub fn scale_to(
        &self,
        width: i32,
        height: i32,
        bounds: IRect,
        x: f64,
        y: f64,
    ) -> Result<ImageSurface, cairo::Status> {
        let output_surface = ImageSurface::create(cairo::Format::ARgb32, width, height)?;

        {
            let cr = cairo::Context::new(&output_surface);
            cr.rectangle(
                bounds.x0 as f64,
                bounds.y0 as f64,
                (bounds.x1 - bounds.x0) as f64,
                (bounds.y1 - bounds.y0) as f64,
            );
            cr.clip();

            cr.scale(x, y);
            self.set_as_source_surface(&cr, 0.0, 0.0);
            cr.paint();
        }

        Ok(output_surface)
    }

    /// Returns a scaled version of a surface and bounds.
    #[inline]
    pub fn scale(
        &self,
        bounds: IRect,
        x: f64,
        y: f64,
    ) -> Result<(ImageSurface, IRect), cairo::Status> {
        let new_width = (f64::from(self.width) * x).ceil() as i32;
        let new_height = (f64::from(self.height) * y).ceil() as i32;
        let new_bounds = bounds.scale(x, y);

        Ok((
            self.scale_to(new_width, new_height, new_bounds, x, y)?,
            new_bounds,
        ))
    }

    /// Returns a surface with black background and alpha channel matching this surface.
    pub fn extract_alpha(&self, bounds: IRect) -> Result<ImageSurface, cairo::Status> {
        let mut output_surface =
            ImageSurface::create(cairo::Format::ARgb32, self.width, self.height)?;

        let output_stride = output_surface.get_stride() as usize;
        {
            let mut output_data = output_surface.get_data().unwrap();

            for (x, y, Pixel { a, .. }) in Pixels::new(self, bounds) {
                let output_pixel = Pixel {
                    r: 0,
                    g: 0,
                    b: 0,
                    a,
                };
                output_data.set_pixel(output_stride, output_pixel, x, y);
            }
        }

        Ok(output_surface)
    }

    /// Returns a surface with pre-multiplication of color values undone.
    ///
    /// HACK: this is storing unpremultiplied pixels in an ARGB32 image surface (which is supposed
    /// to be premultiplied pixels).
    pub fn unpremultiply(&self, bounds: IRect) -> Result<ImageSurface, cairo::Status> {
        let mut output_surface =
            ImageSurface::create(cairo::Format::ARgb32, self.width, self.height)?;

        let stride = output_surface.get_stride() as usize;
        {
            let mut data = output_surface.get_data().unwrap();

            for (x, y, pixel) in Pixels::new(self, bounds) {
                data.set_pixel(stride, pixel.unpremultiply(), x, y);
            }
        }

        Ok(output_surface)
    }

    /// Performs a convolution.
    ///
    /// Note that `kernel` is rotated 180 degrees.
    ///
    /// The `target` parameter determines the position of the kernel relative to each pixel of the
    /// image. The value of `(0, 0)` indicates that the top left pixel of the (180-degrees-rotated)
    /// kernel corresponds to the current pixel, and the rest of the kernel is to the right and
    /// bottom of the pixel. The value of `(cols / 2, rows / 2)` centers a kernel with an odd
    /// number of rows and columns.
    ///
    /// # Panics
    /// Panics if `kernel` has zero rows or columns.
    pub fn convolve(
        &self,
        bounds: IRect,
        target: (i32, i32),
        kernel: &Matrix<f64>,
        edge_mode: EdgeMode,
    ) -> Result<ImageSurface, cairo::Status> {
        assert!(kernel.rows() >= 1);
        assert!(kernel.cols() >= 1);

        let mut output_surface =
            ImageSurface::create(cairo::Format::ARgb32, self.width, self.height)?;

        let output_stride = output_surface.get_stride() as usize;
        {
            let mut output_data = output_surface.get_data().unwrap();

            for (x, y, _pixel) in Pixels::new(self, bounds) {
                let kernel_bounds = IRect {
                    x0: x as i32 - target.0,
                    y0: y as i32 - target.1,
                    x1: x as i32 - target.0 + kernel.cols() as i32,
                    y1: y as i32 - target.1 + kernel.rows() as i32,
                };

                let mut r = 0.0;
                let mut g = 0.0;
                let mut b = 0.0;
                let mut a = 0.0;

                for (x, y, pixel) in PixelRectangle::new(self, bounds, kernel_bounds, edge_mode) {
                    let kernel_x = (kernel_bounds.x1 - x - 1) as usize;
                    let kernel_y = (kernel_bounds.y1 - y - 1) as usize;
                    let factor = kernel[[kernel_y, kernel_x]];

                    r += f64::from(pixel.r) * factor;
                    g += f64::from(pixel.g) * factor;
                    b += f64::from(pixel.b) * factor;
                    a += f64::from(pixel.a) * factor;
                }

                let convert = |x: f64| clamp(x, 0.0, 255.0).round() as u8;

                let output_pixel = Pixel {
                    r: convert(r),
                    g: convert(g),
                    b: convert(b),
                    a: convert(a),
                };

                output_data.set_pixel(output_stride, output_pixel, x, y);
            }
        }

        Ok(output_surface)
    }

    /// Returns a raw pointer to the underlying surface.
    ///
    /// # Safety
    /// The returned pointer must not be used to modify the surface.
    #[inline]
    pub unsafe fn to_glib_none(&self) -> Stash<*mut cairo_sys::cairo_surface_t, ImageSurface> {
        self.surface.to_glib_none()
    }
}
<commit_msg>Add a format check to SharedImageSurface::new()<commit_after>//! Shared access to Cairo image surfaces.
use std::ptr::NonNull;

use cairo::prelude::SurfaceExt;
use cairo::{self, ImageSurface};
use cairo_sys;
use glib::translate::{Stash, ToGlibPtr};
use rulinalg::matrix::{BaseMatrix, Matrix};

use filters::context::IRect;
use util::clamp;

use super::{
    iterators::{PixelRectangle, Pixels},
    EdgeMode,
    ImageSurfaceDataExt,
    Pixel,
};

/// Wrapper for a Cairo image surface that allows shared access.
///
/// There doesn't seem to be any good way of making safe shared access to `ImageSurface` pixel
/// data, since a read-only borrowed reference can still be cloned and then modified (for example,
/// via a `Context`). We can't simply use `ImageSurface::get_data()` because in the filter code we
/// have surfaces referenced from multiple places and it would probably add more complexity to
/// remove that and start passing around references.
///
/// This wrapper asserts the uniqueness of its image surface and doesn't permit modifying it.
///
/// Note: originally I had an idea of using `Rc<RefCell<ImageSurface>>` here which allows to create
/// both read-only and unique read-write accessors safely, however then I realized a read-write
/// accessor isn't of much use if it can't expose a Cairo context interface. Cairo contexts have
/// the very same issue that they can be cloned from a read-only reference and break all safety
/// constraints in this way. Thus the only safe way of exposing a Cairo context seemed to be to
/// manually add all Cairo context methods on the accessor forwarding to the underlying Cairo
/// context (without exposing the context itself to prevent cloning), which would result in too
/// much code. Unless it's absolutely required, I'd like to avoid that.
///
/// Having just read-only access simplifies things further dropping the need for `Rc<RefCell<>>`
/// altogether.
#[derive(Debug, Clone)]
pub struct SharedImageSurface {
    surface: ImageSurface,

    data_ptr: NonNull<u8>, // *const.
    width: i32,
    height: i32,
    stride: isize,
}

impl SharedImageSurface {
    /// Creates a `SharedImageSurface` from a unique `ImageSurface`.
    ///
    /// # Panics
    /// Panics if the surface format isn't `ARgb32` and if the surface is not unique, that is, its
    /// reference count isn't 1.
    #[inline]
    pub fn new(surface: ImageSurface) -> Result<Self, cairo::Status> {
        // get_pixel() assumes ARgb32.
        assert_eq!(surface.get_format(), cairo::Format::ARgb32);

        let reference_count =
            unsafe { cairo_sys::cairo_surface_get_reference_count(surface.to_raw_none()) };
        assert_eq!(reference_count, 1);

        surface.flush();
        if surface.status() != cairo::Status::Success {
            return Err(surface.status());
        }

        let data_ptr = NonNull::new(unsafe {
            cairo_sys::cairo_image_surface_get_data(surface.to_raw_none())
        }).unwrap();

        let width = surface.get_width();
        let height = surface.get_height();
        let stride = surface.get_stride() as isize;

        Ok(Self {
            surface,
            data_ptr,
            width,
            height,
            stride,
        })
    }

    /// Converts this `SharedImageSurface` back into a Cairo image surface.
    ///
    /// # Panics
    /// Panics if the underlying Cairo image surface is not unique, that is, there are other
    /// instances of `SharedImageSurface` pointing at the same Cairo image surface.
    #[inline]
    pub fn into_image_surface(self) -> ImageSurface {
        let reference_count =
            unsafe { cairo_sys::cairo_surface_get_reference_count(self.surface.to_raw_none()) };
        assert_eq!(reference_count, 1);

        self.surface
    }

    /// Returns the surface width.
    #[inline]
    pub fn width(&self) -> i32 {
        self.width
    }

    /// Returns the surface height.
    #[inline]
    pub fn height(&self) -> i32 {
        self.height
    }

    /// Retrieves the pixel value at the given coordinates.
    #[inline]
    pub fn get_pixel(&self, x: u32, y: u32) -> Pixel {
        assert!(x < self.width as u32);
        assert!(y < self.height as u32);

        let value = unsafe {
            *(self
                .data_ptr
                .as_ptr()
                .offset(y as isize * self.stride + x as isize * 4) as *const u32)
        };

        Pixel {
            r: ((value >> 16) & 0xFF) as u8,
            g: ((value >> 8) & 0xFF) as u8,
            b: (value & 0xFF) as u8,
            a: ((value >> 24) & 0xFF) as u8,
        }
    }

    /// Calls `set_source_surface()` on the given Cairo context.
    #[inline]
    pub fn set_as_source_surface(&self, cr: &cairo::Context, x: f64, y: f64) {
        cr.set_source_surface(&self.surface, x, y);
    }

    /// Returns a new `ImageSurface` with the same contents as the one stored in this
    /// `SharedImageSurface` within the given bounds.
    pub fn copy_surface(&self, bounds: IRect) -> Result<ImageSurface, cairo::Status> {
        let output_surface = ImageSurface::create(cairo::Format::ARgb32, self.width, self.height)?;

        let cr = cairo::Context::new(&output_surface);
        cr.rectangle(
            bounds.x0 as f64,
            bounds.y0 as f64,
            (bounds.x1 - bounds.x0) as f64,
            (bounds.y1 - bounds.y0) as f64,
        );
        cr.clip();

        cr.set_source_surface(&self.surface, 0f64, 0f64);
        cr.paint();

        Ok(output_surface)
    }

    /// Scales the given surface by `x` and `y` into a surface `width`×`height` in size, clipped by
    /// `bounds`.
    pub fn scale_to(
        &self,
        width: i32,
        height: i32,
        bounds: IRect,
        x: f64,
        y: f64,
    ) -> Result<ImageSurface, cairo::Status> {
        let output_surface = ImageSurface::create(cairo::Format::ARgb32, width, height)?;

        {
            let cr = cairo::Context::new(&output_surface);
            cr.rectangle(
                bounds.x0 as f64,
                bounds.y0 as f64,
                (bounds.x1 - bounds.x0) as f64,
                (bounds.y1 - bounds.y0) as f64,
            );
            cr.clip();

            cr.scale(x, y);
            self.set_as_source_surface(&cr, 0.0, 0.0);
            cr.paint();
        }

        Ok(output_surface)
    }

    /// Returns a scaled version of a surface and bounds.
    #[inline]
    pub fn scale(
        &self,
        bounds: IRect,
        x: f64,
        y: f64,
    ) -> Result<(ImageSurface, IRect), cairo::Status> {
        let new_width = (f64::from(self.width) * x).ceil() as i32;
        let new_height = (f64::from(self.height) * y).ceil() as i32;
        let new_bounds = bounds.scale(x, y);

        Ok((
            self.scale_to(new_width, new_height, new_bounds, x, y)?,
            new_bounds,
        ))
    }

    /// Returns a surface with black background and alpha channel matching this surface.
    pub fn extract_alpha(&self, bounds: IRect) -> Result<ImageSurface, cairo::Status> {
        let mut output_surface =
            ImageSurface::create(cairo::Format::ARgb32, self.width, self.height)?;

        let output_stride = output_surface.get_stride() as usize;
        {
            let mut output_data = output_surface.get_data().unwrap();

            for (x, y, Pixel { a, .. }) in Pixels::new(self, bounds) {
                let output_pixel = Pixel {
                    r: 0,
                    g: 0,
                    b: 0,
                    a,
                };
                output_data.set_pixel(output_stride, output_pixel, x, y);
            }
        }

        Ok(output_surface)
    }

    /// Returns a surface with pre-multiplication of color values undone.
    ///
    /// HACK: this is storing unpremultiplied pixels in an ARGB32 image surface (which is supposed
    /// to be premultiplied pixels).
    pub fn unpremultiply(&self, bounds: IRect) -> Result<ImageSurface, cairo::Status> {
        let mut output_surface =
            ImageSurface::create(cairo::Format::ARgb32, self.width, self.height)?;

        let stride = output_surface.get_stride() as usize;
        {
            let mut data = output_surface.get_data().unwrap();

            for (x, y, pixel) in Pixels::new(self, bounds) {
                data.set_pixel(stride, pixel.unpremultiply(), x, y);
            }
        }

        Ok(output_surface)
    }

    /// Performs a convolution.
    ///
    /// Note that `kernel` is rotated 180 degrees.
    ///
    /// The `target` parameter determines the position of the kernel relative to each pixel of the
    /// image. The value of `(0, 0)` indicates that the top left pixel of the (180-degrees-rotated)
    /// kernel corresponds to the current pixel, and the rest of the kernel is to the right and
    /// bottom of the pixel. The value of `(cols / 2, rows / 2)` centers a kernel with an odd
    /// number of rows and columns.
    ///
    /// # Panics
    /// Panics if `kernel` has zero rows or columns.
    pub fn convolve(
        &self,
        bounds: IRect,
        target: (i32, i32),
        kernel: &Matrix<f64>,
        edge_mode: EdgeMode,
    ) -> Result<ImageSurface, cairo::Status> {
        assert!(kernel.rows() >= 1);
        assert!(kernel.cols() >= 1);

        let mut output_surface =
            ImageSurface::create(cairo::Format::ARgb32, self.width, self.height)?;

        let output_stride = output_surface.get_stride() as usize;
        {
            let mut output_data = output_surface.get_data().unwrap();

            for (x, y, _pixel) in Pixels::new(self, bounds) {
                let kernel_bounds = IRect {
                    x0: x as i32 - target.0,
                    y0: y as i32 - target.1,
                    x1: x as i32 - target.0 + kernel.cols() as i32,
                    y1: y as i32 - target.1 + kernel.rows() as i32,
                };

                let mut r = 0.0;
                let mut g = 0.0;
                let mut b = 0.0;
                let mut a = 0.0;

                for (x, y, pixel) in PixelRectangle::new(self, bounds, kernel_bounds, edge_mode) {
                    let kernel_x = (kernel_bounds.x1 - x - 1) as usize;
                    let kernel_y = (kernel_bounds.y1 - y - 1) as usize;
                    let factor = kernel[[kernel_y, kernel_x]];

                    r += f64::from(pixel.r) * factor;
                    g += f64::from(pixel.g) * factor;
                    b += f64::from(pixel.b) * factor;
                    a += f64::from(pixel.a) * factor;
                }

                let convert = |x: f64| clamp(x, 0.0, 255.0).round() as u8;

                let output_pixel = Pixel {
                    r: convert(r),
                    g: convert(g),
                    b: convert(b),
                    a: convert(a),
                };

                output_data.set_pixel(output_stride, output_pixel, x, y);
            }
        }

        Ok(output_surface)
    }

    /// Returns a raw pointer to the underlying surface.
    ///
    /// # Safety
    /// The returned pointer must not be used to modify the surface.
    #[inline]
    pub unsafe fn to_glib_none(&self) -> Stash<*mut cairo_sys::cairo_surface_t, ImageSurface> {
        self.surface.to_glib_none()
    }
}
<|endoftext|>


<commit_before>extern crate itertools;

#[macro_use]
extern crate quickcheck;

use itertools::{EitherOrBoth, Itertools};

use std::fmt::Debug;
use std::ops::BitXor;

struct Unspecialized<I>(I);
impl<I> Iterator for Unspecialized<I>
where
    I: Iterator,
{
    type Item = I::Item;

    #[inline(always)]
    fn next(&mut self) -> Option<I::Item> {
        self.0.next()
    }

    #[inline(always)]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.0.size_hint()
    }
}

fn check_specialized<'a, V, IterItem, Iter, F>(iterator: &Iter, mapper: F)
where
    V: Eq + Debug,
    IterItem: 'a,
    Iter: Iterator<Item = IterItem> + Clone + 'a,
    F: Fn(Box<Iterator<Item = IterItem> + 'a>) -> V,
{
    assert_eq!(
        mapper(Box::new(Unspecialized(iterator.clone()))),
        mapper(Box::new(iterator.clone()))
    )
}

fn check_specialized_count_last_nth_sizeh<'a, IterItem, Iter>(
    it: &Iter,
    known_expected_size: Option<usize>,
) where
    IterItem: 'a + Eq + Debug,
    Iter: Iterator<Item = IterItem> + Clone + 'a,
{
    let size = it.clone().count();
    if let Some(expected_size) = known_expected_size {
        assert_eq!(size, expected_size);
    }
    check_specialized(it, |i| i.count());
    check_specialized(it, |i| i.last());
    for n in 0..size + 2 {
        check_specialized(it, |mut i| i.nth(n));
    }
    let mut it_sh = it.clone();
    for n in 0..size + 2 {
        let len = it_sh.clone().count();
        let (min, max) = it_sh.size_hint();
        assert_eq!((size - n.min(size)), len);
        assert!(min <= len);
        if let Some(max) = max {
            assert!(len <= max);
        }
        it_sh.next();
    }
}

fn check_specialized_fold_xor<'a, IterItem, Iter>(it: &Iter)
where
    IterItem: 'a
        + BitXor
        + Eq
        + Debug
        + BitXor<<IterItem as BitXor>::Output, Output = <IterItem as BitXor>::Output>
        + Clone,
    <IterItem as BitXor>::Output:
        BitXor<Output = <IterItem as BitXor>::Output> + Eq + Debug + Clone,
    Iter: Iterator<Item = IterItem> + Clone + 'a,
{
    check_specialized(it, |mut i| {
        let first = i.next().map(|f| f.clone() ^ (f.clone() ^ f));
        i.fold(first, |acc, v: IterItem| acc.map(move |a| v ^ a))
    });
}

fn put_back_test(test_vec: Vec<i32>, known_expected_size: Option<usize>) {
    {
        // Lexical lifetimes support
        let pb = itertools::put_back(test_vec.iter());
        check_specialized_count_last_nth_sizeh(&pb, known_expected_size);
        check_specialized_fold_xor(&pb);
    }

    let mut pb = itertools::put_back(test_vec.into_iter());
    pb.put_back(1);
    check_specialized_count_last_nth_sizeh(&pb, known_expected_size.map(|x| x + 1));
    check_specialized_fold_xor(&pb)
}

#[test]
fn put_back() {
    put_back_test(vec![7, 4, 1], Some(3));
}

quickcheck! {
    fn put_back_qc(test_vec: Vec<i32>) -> () {
        put_back_test(test_vec, None)
    }
}

fn merge_join_by_test(i1: Vec<usize>, i2: Vec<usize>, known_expected_size: Option<usize>) {
    let i1 = i1.into_iter();
    let i2 = i2.into_iter();
    let mjb = i1.clone().merge_join_by(i2.clone(), std::cmp::Ord::cmp);
    check_specialized_count_last_nth_sizeh(&mjb, known_expected_size);
    // Rust 1.24 compatibility:
    fn eob_left_z(eob: EitherOrBoth<usize, usize>) -> usize {
        eob.left().unwrap_or(0)
    }
    fn eob_right_z(eob: EitherOrBoth<usize, usize>) -> usize {
        eob.left().unwrap_or(0)
    }
    fn eob_both_z(eob: EitherOrBoth<usize, usize>) -> usize {
        let (a, b) = eob.both().unwrap_or((0, 0));
        assert_eq!(a, b);
        a
    }
    check_specialized_fold_xor(&mjb.clone().map(eob_left_z));
    check_specialized_fold_xor(&mjb.clone().map(eob_right_z));
    check_specialized_fold_xor(&mjb.clone().map(eob_both_z));

    // And the other way around
    let mjb = i2.merge_join_by(i1, std::cmp::Ord::cmp);
    check_specialized_count_last_nth_sizeh(&mjb, known_expected_size);
    check_specialized_fold_xor(&mjb.clone().map(eob_left_z));
    check_specialized_fold_xor(&mjb.clone().map(eob_right_z));
    check_specialized_fold_xor(&mjb.clone().map(eob_both_z));
}

#[test]
fn merge_join_by() {
    let i1 = vec![1, 3, 5, 7, 8, 9];
    let i2 = vec![0, 3, 4, 5];
    merge_join_by_test(i1, i2, Some(8));
}

quickcheck! {
    fn merge_join_by_qc(i1: Vec<usize>, i2: Vec<usize>) -> () {
        merge_join_by_test(i1, i2, None)
    }
}
<commit_msg>Fix "missing dyn" warning<commit_after>extern crate itertools;

#[macro_use]
extern crate quickcheck;

use itertools::{EitherOrBoth, Itertools};

use std::fmt::Debug;
use std::ops::BitXor;

struct Unspecialized<I>(I);
impl<I> Iterator for Unspecialized<I>
where
    I: Iterator,
{
    type Item = I::Item;

    #[inline(always)]
    fn next(&mut self) -> Option<I::Item> {
        self.0.next()
    }

    #[inline(always)]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.0.size_hint()
    }
}

fn check_specialized<'a, V, IterItem, Iter, F>(iterator: &Iter, mapper: F)
where
    V: Eq + Debug,
    IterItem: 'a,
    Iter: Iterator<Item = IterItem> + Clone + 'a,
    F: Fn(Box<dyn Iterator<Item = IterItem> + 'a>) -> V,
{
    assert_eq!(
        mapper(Box::new(Unspecialized(iterator.clone()))),
        mapper(Box::new(iterator.clone()))
    )
}

fn check_specialized_count_last_nth_sizeh<'a, IterItem, Iter>(
    it: &Iter,
    known_expected_size: Option<usize>,
) where
    IterItem: 'a + Eq + Debug,
    Iter: Iterator<Item = IterItem> + Clone + 'a,
{
    let size = it.clone().count();
    if let Some(expected_size) = known_expected_size {
        assert_eq!(size, expected_size);
    }
    check_specialized(it, |i| i.count());
    check_specialized(it, |i| i.last());
    for n in 0..size + 2 {
        check_specialized(it, |mut i| i.nth(n));
    }
    let mut it_sh = it.clone();
    for n in 0..size + 2 {
        let len = it_sh.clone().count();
        let (min, max) = it_sh.size_hint();
        assert_eq!((size - n.min(size)), len);
        assert!(min <= len);
        if let Some(max) = max {
            assert!(len <= max);
        }
        it_sh.next();
    }
}

fn check_specialized_fold_xor<'a, IterItem, Iter>(it: &Iter)
where
    IterItem: 'a
        + BitXor
        + Eq
        + Debug
        + BitXor<<IterItem as BitXor>::Output, Output = <IterItem as BitXor>::Output>
        + Clone,
    <IterItem as BitXor>::Output:
        BitXor<Output = <IterItem as BitXor>::Output> + Eq + Debug + Clone,
    Iter: Iterator<Item = IterItem> + Clone + 'a,
{
    check_specialized(it, |mut i| {
        let first = i.next().map(|f| f.clone() ^ (f.clone() ^ f));
        i.fold(first, |acc, v: IterItem| acc.map(move |a| v ^ a))
    });
}

fn put_back_test(test_vec: Vec<i32>, known_expected_size: Option<usize>) {
    {
        // Lexical lifetimes support
        let pb = itertools::put_back(test_vec.iter());
        check_specialized_count_last_nth_sizeh(&pb, known_expected_size);
        check_specialized_fold_xor(&pb);
    }

    let mut pb = itertools::put_back(test_vec.into_iter());
    pb.put_back(1);
    check_specialized_count_last_nth_sizeh(&pb, known_expected_size.map(|x| x + 1));
    check_specialized_fold_xor(&pb)
}

#[test]
fn put_back() {
    put_back_test(vec![7, 4, 1], Some(3));
}

quickcheck! {
    fn put_back_qc(test_vec: Vec<i32>) -> () {
        put_back_test(test_vec, None)
    }
}

fn merge_join_by_test(i1: Vec<usize>, i2: Vec<usize>, known_expected_size: Option<usize>) {
    let i1 = i1.into_iter();
    let i2 = i2.into_iter();
    let mjb = i1.clone().merge_join_by(i2.clone(), std::cmp::Ord::cmp);
    check_specialized_count_last_nth_sizeh(&mjb, known_expected_size);
    // Rust 1.24 compatibility:
    fn eob_left_z(eob: EitherOrBoth<usize, usize>) -> usize {
        eob.left().unwrap_or(0)
    }
    fn eob_right_z(eob: EitherOrBoth<usize, usize>) -> usize {
        eob.left().unwrap_or(0)
    }
    fn eob_both_z(eob: EitherOrBoth<usize, usize>) -> usize {
        let (a, b) = eob.both().unwrap_or((0, 0));
        assert_eq!(a, b);
        a
    }
    check_specialized_fold_xor(&mjb.clone().map(eob_left_z));
    check_specialized_fold_xor(&mjb.clone().map(eob_right_z));
    check_specialized_fold_xor(&mjb.clone().map(eob_both_z));

    // And the other way around
    let mjb = i2.merge_join_by(i1, std::cmp::Ord::cmp);
    check_specialized_count_last_nth_sizeh(&mjb, known_expected_size);
    check_specialized_fold_xor(&mjb.clone().map(eob_left_z));
    check_specialized_fold_xor(&mjb.clone().map(eob_right_z));
    check_specialized_fold_xor(&mjb.clone().map(eob_both_z));
}

#[test]
fn merge_join_by() {
    let i1 = vec![1, 3, 5, 7, 8, 9];
    let i2 = vec![0, 3, 4, 5];
    merge_join_by_test(i1, i2, Some(8));
}

quickcheck! {
    fn merge_join_by_qc(i1: Vec<usize>, i2: Vec<usize>) -> () {
        merge_join_by_test(i1, i2, None)
    }
}
<|endoftext|>


<commit_before>use self::error::HookError;

pub type HookResult<T> = Result<T, HookError>;

pub mod read {
    use storeid::StoreId;
    use store::FileLockEntry;
    use super::HookResult;

    pub trait PreReadHook {
        fn pre_read(&self, &StoreId) -> HookResult<()>;
    }

    pub trait PostReadHook {
        fn post_read<'a>(&self, FileLockEntry<'a>) -> HookResult<FileLockEntry<'a>>;
    }

}

pub mod create {
    use storeid::StoreId;
    use store::FileLockEntry;
    use super::HookResult;

    pub trait PreCreateHook {
        fn pre_create(&self, &StoreId) -> HookResult<()>;
    }

    pub trait PostCreateHook {
        fn post_create<'a>(&self, FileLockEntry<'a>) -> HookResult<FileLockEntry<'a>>;
    }

}

pub mod retrieve {
    use storeid::StoreId;
    use store::FileLockEntry;
    use super::HookResult;

    pub trait PreRetrieveHook {
        fn pre_retrieve(&self, &StoreId) -> HookResult<()>;
    }

    pub trait PostRetrieveHook {
        fn post_retrieve<'a>(&self, FileLockEntry<'a>) -> HookResult<FileLockEntry<'a>>;
    }
}

pub mod update {
    use store::FileLockEntry;
    use super::HookResult;

    pub trait PreUpdateHook {
        fn pre_update(&self, &FileLockEntry) -> HookResult<()>;
    }

    pub trait PostUpdateHook {
        fn post_update(&self, &FileLockEntry) -> HookResult<()>;
    }
}

pub mod delete {
    use storeid::StoreId;
    use store::FileLockEntry;
    use super::HookResult;

    pub trait PreDeleteHook {
        fn pre_delete(&self, &StoreId) -> HookResult<()>;
    }

    pub trait PostDeleteHook {
        fn post_delete(&self, &StoreId) -> HookResult<()>;
    }
}

pub mod error {
    use std::error::Error;
    use std::fmt::Error as FmtError;
    use std::clone::Clone;
    use std::fmt::{Display, Formatter};

    /**
     * Kind of error
     */
    #[derive(Clone, Copy, Debug, PartialEq)]
    pub enum HookErrorKind {
        // ...
    }

    fn hook_error_type_as_str(e: &HookErrorKind) -> &'static str {
        match e {
            _ => "",
        }
    }

    impl Display for HookErrorKind {

        fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
            try!(write!(fmt, "{}", hook_error_type_as_str(self)));
            Ok(())
        }

    }

    /**
     * Error type
     */
    #[derive(Debug)]
    pub struct HookError {
        err_type: HookErrorKind,
        cause: Option<Box<Error>>,
    }

    impl HookError {

        /**
         * Build a new HookError from an HookErrorKind, optionally with cause
         */
        pub fn new(errtype: HookErrorKind, cause: Option<Box<Error>>)
            -> HookError
            {
                HookError {
                    err_type: errtype,
                    cause: cause,
                }
            }

        /**
         * Get the error type of this HookError
         */
        pub fn err_type(&self) -> HookErrorKind {
            self.err_type.clone()
        }

    }

    impl Display for HookError {

        fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
            try!(write!(fmt, "[{}]", hook_error_type_as_str(&self.err_type.clone())));
            Ok(())
        }

    }

    impl Error for HookError {

        fn description(&self) -> &str {
            hook_error_type_as_str(&self.err_type.clone())
        }

        fn cause(&self) -> Option<&Error> {
            self.cause.as_ref().map(|e| &**e)
        }

    }

}

<commit_msg>Hooks must implement Debug<commit_after>use self::error::HookError;

pub type HookResult<T> = Result<T, HookError>;

pub mod read {
    use std::fmt::Debug;

    use storeid::StoreId;
    use store::FileLockEntry;
    use super::HookResult;

    pub trait PreReadHook : Debug {
        fn pre_read(&self, &StoreId) -> HookResult<()>;
    }

    pub trait PostReadHook : Debug {
        fn post_read<'a>(&self, FileLockEntry<'a>) -> HookResult<FileLockEntry<'a>>;
    }

}

pub mod create {
    use std::fmt::Debug;

    use storeid::StoreId;
    use store::FileLockEntry;
    use super::HookResult;

    pub trait PreCreateHook : Debug {
        fn pre_create(&self, &StoreId) -> HookResult<()>;
    }

    pub trait PostCreateHook : Debug {
        fn post_create<'a>(&self, FileLockEntry<'a>) -> HookResult<FileLockEntry<'a>>;
    }

}

pub mod retrieve {
    use std::fmt::Debug;

    use storeid::StoreId;
    use store::FileLockEntry;
    use super::HookResult;

    pub trait PreRetrieveHook : Debug {
        fn pre_retrieve(&self, &StoreId) -> HookResult<()>;
    }

    pub trait PostRetrieveHook : Debug {
        fn post_retrieve<'a>(&self, FileLockEntry<'a>) -> HookResult<FileLockEntry<'a>>;
    }
}

pub mod update {
    use std::fmt::Debug;

    use store::FileLockEntry;
    use super::HookResult;

    pub trait PreUpdateHook : Debug {
        fn pre_update(&self, &FileLockEntry) -> HookResult<()>;
    }

    pub trait PostUpdateHook : Debug {
        fn post_update(&self, &FileLockEntry) -> HookResult<()>;
    }
}

pub mod delete {
    use std::fmt::Debug;

    use storeid::StoreId;
    use store::FileLockEntry;
    use super::HookResult;

    pub trait PreDeleteHook : Debug {
        fn pre_delete(&self, &StoreId) -> HookResult<()>;
    }

    pub trait PostDeleteHook : Debug {
        fn post_delete(&self, &StoreId) -> HookResult<()>;
    }
}

pub mod error {
    use std::error::Error;
    use std::fmt::Error as FmtError;
    use std::clone::Clone;
    use std::fmt::{Display, Formatter};

    /**
     * Kind of error
     */
    #[derive(Clone, Copy, Debug, PartialEq)]
    pub enum HookErrorKind {
        // ...
    }

    fn hook_error_type_as_str(e: &HookErrorKind) -> &'static str {
        match e {
            _ => "",
        }
    }

    impl Display for HookErrorKind {

        fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
            try!(write!(fmt, "{}", hook_error_type_as_str(self)));
            Ok(())
        }

    }

    /**
     * Error type
     */
    #[derive(Debug)]
    pub struct HookError {
        err_type: HookErrorKind,
        cause: Option<Box<Error>>,
    }

    impl HookError {

        /**
         * Build a new HookError from an HookErrorKind, optionally with cause
         */
        pub fn new(errtype: HookErrorKind, cause: Option<Box<Error>>)
            -> HookError
            {
                HookError {
                    err_type: errtype,
                    cause: cause,
                }
            }

        /**
         * Get the error type of this HookError
         */
        pub fn err_type(&self) -> HookErrorKind {
            self.err_type.clone()
        }

    }

    impl Display for HookError {

        fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
            try!(write!(fmt, "[{}]", hook_error_type_as_str(&self.err_type.clone())));
            Ok(())
        }

    }

    impl Error for HookError {

        fn description(&self) -> &str {
            hook_error_type_as_str(&self.err_type.clone())
        }

        fn cause(&self) -> Option<&Error> {
            self.cause.as_ref().map(|e| &**e)
        }

    }

}

<|endoftext|>


<commit_before>//! impl bool {}

#[lang = "bool"]
impl bool {
    /// Returns `Some(t)` if the `bool` is [`true`](keyword.true.html), or `None` otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(bool_to_option)]
    ///
    /// assert_eq!(false.then_some(0), None);
    /// assert_eq!(true.then_some(0), Some(0));
    /// ```
    #[unstable(feature = "bool_to_option", issue = "80967")]
    #[inline]
    pub fn then_some<T>(self, t: T) -> Option<T> {
        if self { Some(t) } else { None }
    }

    /// Returns `Some` if the `bool` is [`true`](keyword.true.html), or `None` otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// assert_eq!(false.then(|| 0), None);
    /// assert_eq!(true.then(|| 0), Some(0));
    /// ```
    #[stable(feature = "lazy_bool_to_option", since = "1.50.0")]
    #[inline]
    pub fn then<T, F: FnOnce() -> T>(self, f: F) -> Option<T> {
        if self { Some(f()) } else { None }
    }
}
<commit_msg>Fix accidentally deleted part<commit_after>//! impl bool {}

#[lang = "bool"]
impl bool {
    /// Returns `Some(t)` if the `bool` is [`true`](keyword.true.html), or `None` otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(bool_to_option)]
    ///
    /// assert_eq!(false.then_some(0), None);
    /// assert_eq!(true.then_some(0), Some(0));
    /// ```
    #[unstable(feature = "bool_to_option", issue = "80967")]
    #[inline]
    pub fn then_some<T>(self, t: T) -> Option<T> {
        if self { Some(t) } else { None }
    }

    /// Returns `Some(f())` if the `bool` is [`true`](keyword.true.html), or `None` otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// assert_eq!(false.then(|| 0), None);
    /// assert_eq!(true.then(|| 0), Some(0));
    /// ```
    #[stable(feature = "lazy_bool_to_option", since = "1.50.0")]
    #[inline]
    pub fn then<T, F: FnOnce() -> T>(self, f: F) -> Option<T> {
        if self { Some(f()) } else { None }
    }
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;
extern crate csv;
extern crate utilities;
extern crate distance;

use std::collections::HashMap;
use utilities::abs_standard_deviation;
use distance::manhattan_dist;

/******************** Athletes DB ********************/
#[derive(Debug)]
#[derive(RustcDecodable)]
pub struct AthlRecord {
    class: String,
    height: f32,
    weight: f32,
}

#[derive(Debug)]
pub struct AthlDatabase {
    keys: HashMap<String, usize>,
    data: Vec<AthlRecord>,
    asd_data: Vec<(f32, f32)>,
}

impl AthlDatabase {
    pub fn from_file(path: &str) -> AthlDatabase {
        let mut rdr = csv::Reader::from_file(path)
            .unwrap()
            .delimiter(b'\t')
            .has_headers(true);

        let mut keys: HashMap<String, usize> = HashMap::new();
        let mut data: Vec<AthlRecord> = Vec::new();

        let mut indx = 0;
        for record in rdr.decode() {
            let rcrd: (String, AthlRecord) = record.unwrap();
            keys.insert(rcrd.0, indx);
            data.push(rcrd.1);

            indx += 1;
        }

        AthlDatabase {
            keys: keys,
            data: data,
            asd_data: Vec::new()
        }
    }

    pub fn standarize(&mut self) {
        println!("Standarizing DB...");
        for i in 0..2 {
            let mut feat_vec: Vec<f32> = Vec::new();
            for feat in self.data.iter() {
                feat_vec.push(match i {
                                  0 => feat.height,
                                  1 => feat.weight,
                                  _ => {
                    panic!("Out of range, fn covers only two options");
                }
                              });
            }

            let (asd, median) = abs_standard_deviation(&feat_vec);
            println!("\t{}> asd: {}\tmedian: {}", i, asd, median);

            for feat in self.data.iter_mut() {
                match i {
                    0 => {
                        feat.height = (feat.height - median) / asd;
                    }
                    1 => {
                        feat.weight = (feat.weight - median) / asd;
                    }
                    _ => {}
                }
            }

            self.asd_data.push((asd, median));
        }
    }

    fn nearest_neighbors(&self, rcrd: &AthlRecord, func: fn(&Vec<f32>, &Vec<f32>) -> f32) -> Vec<usize> {
        let feats = vec![rcrd.height, rcrd.weight];
        let mut distances: Vec<(f32, usize)> = Vec::new();
        let mut i = 0;
        for record in self.data.iter() {
            distances.push((func(&feats, &vec![record.height, record.weight]), i));
            i += 1;
        }
        distances.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());

        let mut indexes = Vec::new();
        for record in distances.iter() {
            indexes.push(record.1);
        }

        indexes
    }

    pub fn predict(&self, height: f32, weight: f32) -> AthlRecord {
        let mut rcrd = AthlRecord {
            class: String::new(),
            height: height,
            weight: weight,
        };

        for i in 0..2 {
            match i {
                0 => {
                    rcrd.height = (rcrd.height - self.asd_data[i].1) / self.asd_data[i].0;
                }
                1 => {
                    rcrd.weight = (rcrd.weight - self.asd_data[i].1) / self.asd_data[i].0;
                }
                _ => {}
            }
        }

        rcrd.class = self.data[self.nearest_neighbors(&rcrd, manhattan_dist)[0]].class.clone();
        // println!("{:?}", self.data[self.nearest_neighbors(&rcrd, manhattan_dist)[0]]);
        rcrd
    }

    pub fn test(training_path: &str, test_path: &str) {
        println!("Loading database, please wait...");
        let mut db = AthlDatabase::from_file(training_path);
        db.standarize();
        println!("Database ready!\n---------------------------------------------");

        let mut rdr = csv::Reader::from_file(test_path)
            .unwrap()
            .delimiter(b'\t')
            .has_headers(true);

        let mut n_correct = 0;
        let mut n_incorrect = 0;
        let mut count = 0;
        for record in rdr.decode() {
            let rcrd: (String, AthlRecord) = record.unwrap();
            let pred = db.predict(rcrd.1.height, rcrd.1.weight);

            println!("{} <> {}", rcrd.1.class, pred.class);
            if rcrd.1.class == pred.class {
                n_correct += 1;
            } else {
                n_incorrect += 1;
            }
            count += 1;
        }

        println!("Correct: {}%\nIncorrect: {}%",
                  n_correct as f32 * 100.0 / count as f32,
                  n_incorrect as f32 * 100.0 / count as f32);
    }
}
/*******************************************************/

/******************** Miles per Gallon DB ********************/
#[derive(Debug)]
#[derive(RustcDecodable)]
pub struct MpgRecord {
    mpg: f32,
    cylinders: f32,
    ci: f32,
    hp: f32,
    weight: f32,
    secs: f32,
}

#[derive(Debug)]
pub struct MpgDatabase {
    keys: HashMap<String, usize>,
    data: Vec<MpgRecord>,
    asd_data: Vec<(f32, f32)>,
}

impl MpgDatabase {
    pub fn from_file(path: &str) -> MpgDatabase {
        let mut rdr = csv::Reader::from_file(path)
            .unwrap()
            .delimiter(b'\t')
            .has_headers(true);

        let mut keys: HashMap<String, usize> = HashMap::new();
        let mut data: Vec<MpgRecord> = Vec::new();

        let mut indx = 0;
        for record in rdr.decode() {
            let rcrd: (MpgRecord, String) = record.unwrap();
            data.push(rcrd.0);
            keys.insert(rcrd.1, indx);

            indx += 1;
        }

        MpgDatabase {
            keys: keys,
            data: data,
            asd_data: Vec::new()
        }
    }

    pub fn standarize(&mut self) {
        println!("Standarizing DB...");
        for i in 0..6 {
            let mut feat_vec: Vec<f32> = Vec::new();
            for feat in self.data.iter() {
                feat_vec.push(match i {
                                  0 => feat.mpg,
                                  1 => feat.cylinders,
                                  2 => feat.ci,
                                  3 => feat.hp,
                                  4 => feat.weight,
                                  5 => feat.secs,
                                  _ => {
                    panic!("Out of range, fn covers only two options");
                }
                              });
            }

            let (asd, median) = abs_standard_deviation(&feat_vec);
            println!("\t{}> asd: {}\tmedian: {}", i, asd, median);

            for feat in self.data.iter_mut() {
                match i {
                    0 => {
                        feat.mpg = (feat.mpg - median) / asd;
                    }
                    1 => {
                        feat.cylinders = (feat.cylinders - median) / asd;
                    }
                    2 => {
                        feat.ci = (feat.ci - median) / asd;
                    }
                    3 => {
                        feat.hp = (feat.hp - median) / asd;
                    }
                    4 => {
                        feat.weight = (feat.weight - median) / asd;
                    }
                    5 => {
                        feat.secs = (feat.secs - median) / asd;
                    }
                    _ => {}
                }
            }

            self.asd_data.push((asd, median));
        }
    }

    fn nearest_neighbors(&self, rcrd: &MpgRecord, func: fn(&Vec<f32>, &Vec<f32>) -> f32) -> Vec<usize> {
        let feats = vec![rcrd.cylinders, rcrd.ci, rcrd.hp, rcrd.weight, rcrd.secs];
        let mut distances: Vec<(f32, usize)> = Vec::new();
        let mut i = 0;
        for record in self.data.iter() {
            distances.push((func(&feats, &vec![record.cylinders, record.ci, record.hp, record.weight, record.secs]), i));
            i += 1;
        }
        distances.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());

        let mut indexes = Vec::new();
        for record in distances.iter() {
            indexes.push(record.1);
        }

        indexes
    }

    pub fn predict(&self, cylinders: f32, ci: f32, hp: f32, weight: f32, secs: f32) -> MpgRecord {
        let mut rcrd = MpgRecord {
            mpg: 0.0,
            cylinders: cylinders,
            ci: ci,
            hp: hp,
            weight: weight,
            secs: secs
        };

        for i in 0..6 {
            match i {
                // 0 => {
                //     rcrd.mpg = (rcrd.mpg - self.asd_data[i].1) / self.asd_data[i].0;
                // }
                1 => {
                    rcrd.cylinders = (rcrd.cylinders - self.asd_data[i].1) / self.asd_data[i].0;
                }
                2 => {
                    rcrd.ci = (rcrd.ci - self.asd_data[i].1) / self.asd_data[i].0;
                }
                3 => {
                    rcrd.hp = (rcrd.hp - self.asd_data[i].1) / self.asd_data[i].0;
                }
                4 => {
                    rcrd.weight = (rcrd.weight - self.asd_data[i].1) / self.asd_data[i].0;
                }
                5 => {
                    rcrd.secs = (rcrd.secs - self.asd_data[i].1) / self.asd_data[i].0;
                }
                _ => {}
            }
        }

        rcrd.mpg = self.data[self.nearest_neighbors(&rcrd, manhattan_dist)[0]].mpg;
        // println!("{:?}", self.data[self.nearest_neighbors(&rcrd, manhattan_dist)[0]]);
        rcrd
    }

    pub fn test(training_path: &str, test_path: &str) {
        println!("Loading database, please wait...");
        let mut db = MpgDatabase::from_file(training_path);
        db.standarize();
        println!("Database ready!\n---------------------------------------------");

        println!("Pred => {:?}", db.predict(8.0, 360.0, 215.0, 4615.0, 14.0));
    }
}
/*******************************************************/

// def test(training_filename, test_filename):
//     """Test the classifier on a test set of data"""
//     classifier = Classifier(training_filename)
//     f = open(test_filename)
//     lines = f.readlines()
//     f.close()
//     numCorrect = 0.0
//     for line in lines:
//         data = line.strip().split('\t')
//         vector = []
//         classInColumn = -1
//         for i in range(len(classifier.format)):
//               if classifier.format[i] == 'num':
//                   vector.append(float(data[i]))
//               elif classifier.format[i] == 'class':
//                   classInColumn = i
//         theClass= classifier.classify(vector)
//         prefix = '-'
//         if theClass == data[classInColumn]:
//             # it is correct
//             numCorrect += 1
//             prefix = '+'
//         print("%s  %12s  %s" % (prefix, theClass, line))
//     print("%4.2f%% correct" % (numCorrect * 100/ len(lines)))
<commit_msg>Test() is working for both DBs<commit_after>extern crate rustc_serialize;
extern crate csv;
extern crate utilities;
extern crate distance;

use std::collections::HashMap;
use utilities::abs_standard_deviation;
use distance::manhattan_dist;

/******************** Athletes DB ********************/
#[derive(Debug)]
#[derive(RustcDecodable)]
pub struct AthlRecord {
    class: String,
    height: f32,
    weight: f32,
}

#[derive(Debug)]
pub struct AthlDatabase {
    keys: HashMap<String, usize>,
    data: Vec<AthlRecord>,
    asd_data: Vec<(f32, f32)>,
}

impl AthlDatabase {
    pub fn from_file(path: &str) -> AthlDatabase {
        let mut rdr = csv::Reader::from_file(path)
            .unwrap()
            .delimiter(b'\t')
            .has_headers(true);

        let mut keys: HashMap<String, usize> = HashMap::new();
        let mut data: Vec<AthlRecord> = Vec::new();

        let mut indx = 0;
        for record in rdr.decode() {
            let rcrd: (String, AthlRecord) = record.unwrap();
            keys.insert(rcrd.0, indx);
            data.push(rcrd.1);

            indx += 1;
        }

        AthlDatabase {
            keys: keys,
            data: data,
            asd_data: Vec::new()
        }
    }

    pub fn standarize(&mut self) {
        println!("Standarizing DB...");
        for i in 0..2 {
            let mut feat_vec: Vec<f32> = Vec::new();
            for feat in self.data.iter() {
                feat_vec.push(match i {
                                  0 => feat.height,
                                  1 => feat.weight,
                                  _ => {
                    panic!("Out of range, fn covers only two options");
                }
                              });
            }

            let (asd, median) = abs_standard_deviation(&feat_vec);
            println!("\t{}> asd: {}\tmedian: {}", i, asd, median);

            for feat in self.data.iter_mut() {
                match i {
                    0 => {
                        feat.height = (feat.height - median) / asd;
                    }
                    1 => {
                        feat.weight = (feat.weight - median) / asd;
                    }
                    _ => {}
                }
            }

            self.asd_data.push((asd, median));
        }
    }

    fn nearest_neighbors(&self, rcrd: &AthlRecord, func: fn(&Vec<f32>, &Vec<f32>) -> f32) -> Vec<usize> {
        let feats = vec![rcrd.height, rcrd.weight];
        let mut distances: Vec<(f32, usize)> = Vec::new();
        let mut i = 0;
        for record in self.data.iter() {
            distances.push((func(&feats, &vec![record.height, record.weight]), i));
            i += 1;
        }
        distances.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());

        let mut indexes = Vec::new();
        for record in distances.iter() {
            indexes.push(record.1);
        }

        indexes
    }

    pub fn predict(&self, height: f32, weight: f32) -> AthlRecord {
        let mut rcrd = AthlRecord {
            class: String::new(),
            height: height,
            weight: weight,
        };

        for i in 0..2 {
            match i {
                0 => {
                    rcrd.height = (rcrd.height - self.asd_data[i].1) / self.asd_data[i].0;
                }
                1 => {
                    rcrd.weight = (rcrd.weight - self.asd_data[i].1) / self.asd_data[i].0;
                }
                _ => {}
            }
        }

        rcrd.class = self.data[self.nearest_neighbors(&rcrd, manhattan_dist)[0]].class.clone();
        // println!("{:?}", self.data[self.nearest_neighbors(&rcrd, manhattan_dist)[0]]);
        rcrd
    }

    pub fn test(training_path: &str, test_path: &str) {
        println!("Loading database, please wait...");
        let mut db = AthlDatabase::from_file(training_path);
        db.standarize();
        println!("Database ready!\n---------------------------------------------");

        let mut rdr = csv::Reader::from_file(test_path)
            .unwrap()
            .delimiter(b'\t')
            .has_headers(true);

        let mut n_correct = 0;
        let mut n_incorrect = 0;
        let mut count = 0;
        for record in rdr.decode() {
            let rcrd: (String, AthlRecord) = record.unwrap();
            let pred = db.predict(rcrd.1.height, rcrd.1.weight);

            // println!("{} <> {}", rcrd.1.class, pred.class);
            if rcrd.1.class == pred.class {
                n_correct += 1;
            } else {
                n_incorrect += 1;
            }
            count += 1;
        }

        println!("Correct: {}%\nIncorrect: {}%\n",
                  n_correct as f32 * 100.0 / count as f32,
                  n_incorrect as f32 * 100.0 / count as f32);
    }
}
/*******************************************************/

/******************** Miles per Gallon DB ********************/
#[derive(Debug)]
#[derive(RustcDecodable)]
pub struct MpgRecord {
    mpg: f32,
    cylinders: f32,
    ci: f32,
    hp: f32,
    weight: f32,
    secs: f32,
}

#[derive(Debug)]
pub struct MpgDatabase {
    keys: HashMap<String, usize>,
    data: Vec<MpgRecord>,
    asd_data: Vec<(f32, f32)>,
}

impl MpgDatabase {
    pub fn from_file(path: &str) -> MpgDatabase {
        let mut rdr = csv::Reader::from_file(path)
            .unwrap()
            .delimiter(b'\t')
            .has_headers(true);

        let mut keys: HashMap<String, usize> = HashMap::new();
        let mut data: Vec<MpgRecord> = Vec::new();

        let mut indx = 0;
        for record in rdr.decode() {
            let rcrd: (MpgRecord, String) = record.unwrap();
            data.push(rcrd.0);
            keys.insert(rcrd.1, indx);

            indx += 1;
        }

        MpgDatabase {
            keys: keys,
            data: data,
            asd_data: Vec::new()
        }
    }

    pub fn standarize(&mut self) {
        println!("Standarizing DB...");
        for i in 0..6 {
            let mut feat_vec: Vec<f32> = Vec::new();
            for feat in self.data.iter() {
                feat_vec.push(match i {
                                  0 => feat.mpg,
                                  1 => feat.cylinders,
                                  2 => feat.ci,
                                  3 => feat.hp,
                                  4 => feat.weight,
                                  5 => feat.secs,
                                  _ => {
                    panic!("Out of range, fn covers only two options");
                }
                              });
            }

            let (asd, median) = abs_standard_deviation(&feat_vec);
            println!("\t{}> asd: {}\tmedian: {}", i, asd, median);

            for feat in self.data.iter_mut() {
                match i {
                    0 => {
                        feat.mpg = (feat.mpg - median) / asd;
                    }
                    1 => {
                        feat.cylinders = (feat.cylinders - median) / asd;
                    }
                    2 => {
                        feat.ci = (feat.ci - median) / asd;
                    }
                    3 => {
                        feat.hp = (feat.hp - median) / asd;
                    }
                    4 => {
                        feat.weight = (feat.weight - median) / asd;
                    }
                    5 => {
                        feat.secs = (feat.secs - median) / asd;
                    }
                    _ => {}
                }
            }

            self.asd_data.push((asd, median));
        }
    }

    fn nearest_neighbors(&self, rcrd: &MpgRecord, func: fn(&Vec<f32>, &Vec<f32>) -> f32) -> Vec<usize> {
        let feats = vec![rcrd.cylinders, rcrd.ci, rcrd.hp, rcrd.weight, rcrd.secs];
        let mut distances: Vec<(f32, usize)> = Vec::new();
        let mut i = 0;
        for record in self.data.iter() {
            distances.push((func(&feats, &vec![record.cylinders, record.ci, record.hp, record.weight, record.secs]), i));
            i += 1;
        }
        distances.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());

        let mut indexes = Vec::new();
        for record in distances.iter() {
            indexes.push(record.1);
        }

        indexes
    }

    pub fn standarize_record(&self, record: &mut MpgRecord) {
        record.mpg = (record.mpg - self.asd_data[0].1) / self.asd_data[0].0;
        record.cylinders = (record.cylinders - self.asd_data[1].1) / self.asd_data[1].0;
        record.ci = (record.ci - self.asd_data[2].1) / self.asd_data[2].0;
        record.hp = (record.hp - self.asd_data[3].1) / self.asd_data[3].0;
        record.weight = (record.weight - self.asd_data[4].1) / self.asd_data[4].0;
        record.secs = (record.secs - self.asd_data[5].1) / self.asd_data[5].0;
    }

    pub fn predict(&self, cylinders: f32, ci: f32, hp: f32, weight: f32, secs: f32) -> MpgRecord {
        let mut rcrd = MpgRecord {
            mpg: 0.0,
            cylinders: cylinders,
            ci: ci,
            hp: hp,
            weight: weight,
            secs: secs
        };

        for i in 0..6 {
            match i {
                // 0 => {
                //     rcrd.mpg = (rcrd.mpg - self.asd_data[i].1) / self.asd_data[i].0;
                // }
                1 => {
                    rcrd.cylinders = (rcrd.cylinders - self.asd_data[i].1) / self.asd_data[i].0;
                }
                2 => {
                    rcrd.ci = (rcrd.ci - self.asd_data[i].1) / self.asd_data[i].0;
                }
                3 => {
                    rcrd.hp = (rcrd.hp - self.asd_data[i].1) / self.asd_data[i].0;
                }
                4 => {
                    rcrd.weight = (rcrd.weight - self.asd_data[i].1) / self.asd_data[i].0;
                }
                5 => {
                    rcrd.secs = (rcrd.secs - self.asd_data[i].1) / self.asd_data[i].0;
                }
                _ => {}
            }
        }

        rcrd.mpg = self.data[self.nearest_neighbors(&rcrd, manhattan_dist)[0]].mpg;
        // println!("{:?}", self.data[self.nearest_neighbors(&rcrd, manhattan_dist)[0]]);
        rcrd
    }

    pub fn test(training_path: &str, test_path: &str) {
        println!("Loading database, please wait...");
        let mut db = MpgDatabase::from_file(training_path);
        db.standarize();
        println!("Database ready!\n---------------------------------------------");

        let mut rdr = csv::Reader::from_file(test_path)
            .unwrap()
            .delimiter(b'\t')
            .has_headers(true);

        let mut n_correct = 0;
        let mut n_incorrect = 0;
        let mut count = 0;
        for record in rdr.decode() {
            let mut rcrd: (MpgRecord, String) = record.unwrap();
            let pred = db.predict(rcrd.0.cylinders, rcrd.0.ci, rcrd.0.hp, rcrd.0.weight, rcrd.0.secs);

            db.standarize_record(&mut rcrd.0);
            // println!("{} <> {}", rcrd.0.mpg, pred.mpg);
            if rcrd.0.mpg == pred.mpg {
                n_correct += 1;
            } else {
                n_incorrect += 1;
            }
            count += 1;
        }

        println!("Correct: {}%\nIncorrect: {}%\n",
                  n_correct as f32 * 100.0 / count as f32,
                  n_incorrect as f32 * 100.0 / count as f32);
        // println!("Pred => {:?}", db.predict(8.0, 360.0, 215.0, 4615.0, 14.0));
    }
}
/*******************************************************/<|endoftext|>


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

use syntax::ptr::P;
use syntax::codemap::Span;
use syntax::ast::{TokenTree, TTTok};
use syntax::ast;
use syntax::ext::base::{ExtCtxt, MacResult, MacExpr};
use syntax::parse::token::{get_ident, InternedString, LIT_STR, IDENT};

use std::iter::Chain;
use std::slice::{Items, Found, NotFound};
use std::collections::HashMap;
use std::ascii::AsciiExt;

mod data;

#[path="../../../shared/static_atom.rs"]
mod static_atom;

// Build a PhfOrderedSet of static atoms.
// Takes no arguments.
pub fn expand_static_atom_set(cx: &mut ExtCtxt, sp: Span, tt: &[TokenTree]) -> Box<MacResult+'static> {
    bail_if!(tt.len() != 0, cx, sp, "Usage: static_atom_map!()");
    let tts: Vec<TokenTree> = data::atoms.iter().flat_map(|k| {
        (quote_tokens!(&mut *cx, $k,)).move_iter()
    }).collect();
    MacExpr::new(quote_expr!(&mut *cx, phf_ordered_set!($tts)))
}

fn atom_tok_to_str(t: &TokenTree) -> Option<InternedString> {
    Some(get_ident(match *t {
        TTTok(_, IDENT(s, _)) => s,
        TTTok(_, LIT_STR(s)) => s.ident(),
        _ => return None,
    }))
}

// Build a map from atoms to IDs for use in implementing the atom!() macro.
lazy_static! {
    static ref STATIC_ATOM_MAP: HashMap<&'static str, uint> = {
        let mut m = HashMap::new();
        for (i, x) in data::atoms.iter().enumerate() {
            m.insert(*x, i);
        }
        m
    };
}

// FIXME: libsyntax should provide this (rust-lang/rust#17637)
struct AtomResult {
    expr: P<ast::Expr>,
    pat: P<ast::Pat>,
}

impl MacResult for AtomResult {
    fn make_expr(self: Box<AtomResult>) -> Option<P<ast::Expr>> {
        Some(self.expr)
    }

    fn make_pat(self: Box<AtomResult>) -> Option<P<ast::Pat>> {
        Some(self.pat)
    }
}

fn make_atom_result(cx: &mut ExtCtxt, sp: Span, name: &str) -> Option<AtomResult> {
    let i = match STATIC_ATOM_MAP.find_equiv(&name) {
        Some(i) => i,
        None => return None,
    };

    let data = static_atom::add_tag(*i as u32);

    Some(AtomResult {
        expr: quote_expr!(&mut *cx, ::string_cache::atom::Atom { data: $data }),
        pat: quote_pat!(&mut *cx, ::string_cache::atom::Atom { data: $data }),
    })
}

// Translate `atom!(title)` or `atom!("font-weight")` into an `Atom` constant or pattern.
pub fn expand_atom(cx: &mut ExtCtxt, sp: Span, tt: &[TokenTree]) -> Box<MacResult+'static> {
    let usage = "Usage: atom!(html) or atom!(\"font-weight\")";
    let name = match tt {
        [ref t] => expect!(cx, sp, atom_tok_to_str(t), usage),
        _ => bail!(cx, sp, usage),
    };
    box expect!(cx, sp, make_atom_result(cx, sp, name.get()),
        format!("Unknown static atom {:s}", name.get()).as_slice())
}

// Translate `ns!(HTML)` into `Namespace { atom: atom!("http://www.w3.org/1999/xhtml") }`.
// The argument is ASCII-case-insensitive.
pub fn expand_ns(cx: &mut ExtCtxt, sp: Span, tt: &[TokenTree]) -> Box<MacResult+'static> {
    static all_ns: &'static [(&'static str, &'static str)] = [
        ("", ""),
        ("html", "http://www.w3.org/1999/xhtml"),
        ("xml", "http://www.w3.org/XML/1998/namespace"),
        ("xmlns", "http://www.w3.org/2000/xmlns/"),
        ("xlink", "http://www.w3.org/1999/xlink"),
        ("svg", "http://www.w3.org/2000/svg"),
        ("mathml", "http://www.w3.org/1998/Math/MathML"),
    ];

    fn usage() -> String {
        let ns_names: Vec<&'static str> = all_ns.slice_from(1).iter()
            .map(|&(x, _)| x).collect();
        format!("Usage: ns!(HTML), case-insensitive. \
            Known namespaces: {:s}",
            ns_names.connect(" "))
    }

    let name = expect!(cx, sp, match tt {
        [ref t] => atom_tok_to_str(t),
        _ => None,
    }, usage().as_slice());

    let &(short, url) = expect!(cx, sp,
        all_ns.iter().find(|&&(short, _)| short.eq_ignore_ascii_case(name.get())),
        usage().as_slice());

    // All of the URLs should be in the static atom table.
    let AtomResult { expr, pat } = expect!(cx, sp, make_atom_result(cx, sp, url),
        format!("internal plugin error: can't find namespace url {:s}", url).as_slice());

    box AtomResult {
        expr: quote_expr!(&mut *cx, ::string_cache::namespace::Namespace($expr)),
        pat: quote_pat!(&mut *cx, ::string_cache::namespace::Namespace($pat)),
    }
}

#[macro_export]
macro_rules! qualname (($ns:tt, $local:tt) => (
    ::string_cache::namespace::QualName {
        ns: ns!($ns),
        local: atom!($local),
    }
))
<commit_msg>Replace removed deprecated method call<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.

use syntax::ptr::P;
use syntax::codemap::Span;
use syntax::ast::{TokenTree, TTTok};
use syntax::ast;
use syntax::ext::base::{ExtCtxt, MacResult, MacExpr};
use syntax::parse::token::{get_ident, InternedString, LIT_STR, IDENT};

use std::iter::Chain;
use std::slice::{Items, Found, NotFound};
use std::collections::HashMap;
use std::ascii::AsciiExt;

mod data;

#[path="../../../shared/static_atom.rs"]
mod static_atom;

// Build a PhfOrderedSet of static atoms.
// Takes no arguments.
pub fn expand_static_atom_set(cx: &mut ExtCtxt, sp: Span, tt: &[TokenTree]) -> Box<MacResult+'static> {
    bail_if!(tt.len() != 0, cx, sp, "Usage: static_atom_map!()");
    let tts: Vec<TokenTree> = data::atoms.iter().flat_map(|k| {
        (quote_tokens!(&mut *cx, $k,)).into_iter()
    }).collect();
    MacExpr::new(quote_expr!(&mut *cx, phf_ordered_set!($tts)))
}

fn atom_tok_to_str(t: &TokenTree) -> Option<InternedString> {
    Some(get_ident(match *t {
        TTTok(_, IDENT(s, _)) => s,
        TTTok(_, LIT_STR(s)) => s.ident(),
        _ => return None,
    }))
}

// Build a map from atoms to IDs for use in implementing the atom!() macro.
lazy_static! {
    static ref STATIC_ATOM_MAP: HashMap<&'static str, uint> = {
        let mut m = HashMap::new();
        for (i, x) in data::atoms.iter().enumerate() {
            m.insert(*x, i);
        }
        m
    };
}

// FIXME: libsyntax should provide this (rust-lang/rust#17637)
struct AtomResult {
    expr: P<ast::Expr>,
    pat: P<ast::Pat>,
}

impl MacResult for AtomResult {
    fn make_expr(self: Box<AtomResult>) -> Option<P<ast::Expr>> {
        Some(self.expr)
    }

    fn make_pat(self: Box<AtomResult>) -> Option<P<ast::Pat>> {
        Some(self.pat)
    }
}

fn make_atom_result(cx: &mut ExtCtxt, sp: Span, name: &str) -> Option<AtomResult> {
    let i = match STATIC_ATOM_MAP.find_equiv(&name) {
        Some(i) => i,
        None => return None,
    };

    let data = static_atom::add_tag(*i as u32);

    Some(AtomResult {
        expr: quote_expr!(&mut *cx, ::string_cache::atom::Atom { data: $data }),
        pat: quote_pat!(&mut *cx, ::string_cache::atom::Atom { data: $data }),
    })
}

// Translate `atom!(title)` or `atom!("font-weight")` into an `Atom` constant or pattern.
pub fn expand_atom(cx: &mut ExtCtxt, sp: Span, tt: &[TokenTree]) -> Box<MacResult+'static> {
    let usage = "Usage: atom!(html) or atom!(\"font-weight\")";
    let name = match tt {
        [ref t] => expect!(cx, sp, atom_tok_to_str(t), usage),
        _ => bail!(cx, sp, usage),
    };
    box expect!(cx, sp, make_atom_result(cx, sp, name.get()),
        format!("Unknown static atom {:s}", name.get()).as_slice())
}

// Translate `ns!(HTML)` into `Namespace { atom: atom!("http://www.w3.org/1999/xhtml") }`.
// The argument is ASCII-case-insensitive.
pub fn expand_ns(cx: &mut ExtCtxt, sp: Span, tt: &[TokenTree]) -> Box<MacResult+'static> {
    static all_ns: &'static [(&'static str, &'static str)] = [
        ("", ""),
        ("html", "http://www.w3.org/1999/xhtml"),
        ("xml", "http://www.w3.org/XML/1998/namespace"),
        ("xmlns", "http://www.w3.org/2000/xmlns/"),
        ("xlink", "http://www.w3.org/1999/xlink"),
        ("svg", "http://www.w3.org/2000/svg"),
        ("mathml", "http://www.w3.org/1998/Math/MathML"),
    ];

    fn usage() -> String {
        let ns_names: Vec<&'static str> = all_ns.slice_from(1).iter()
            .map(|&(x, _)| x).collect();
        format!("Usage: ns!(HTML), case-insensitive. \
            Known namespaces: {:s}",
            ns_names.connect(" "))
    }

    let name = expect!(cx, sp, match tt {
        [ref t] => atom_tok_to_str(t),
        _ => None,
    }, usage().as_slice());

    let &(short, url) = expect!(cx, sp,
        all_ns.iter().find(|&&(short, _)| short.eq_ignore_ascii_case(name.get())),
        usage().as_slice());

    // All of the URLs should be in the static atom table.
    let AtomResult { expr, pat } = expect!(cx, sp, make_atom_result(cx, sp, url),
        format!("internal plugin error: can't find namespace url {:s}", url).as_slice());

    box AtomResult {
        expr: quote_expr!(&mut *cx, ::string_cache::namespace::Namespace($expr)),
        pat: quote_pat!(&mut *cx, ::string_cache::namespace::Namespace($pat)),
    }
}

#[macro_export]
macro_rules! qualname (($ns:tt, $local:tt) => (
    ::string_cache::namespace::QualName {
        ns: ns!($ns),
        local: atom!($local),
    }
))
<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2016 the imag 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 std::error::Error;

/// An iterator that maps `f` over the `Error` elements of `iter`, similar to `std::iter::Map`.
///
/// This `struct` is created by the `on_err()` method on `TraceIterator`. See its
/// documentation for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Clone)]
pub struct OnErr<I, F>{
    iter: I,
    f: F
}

impl<I, F, T, E> Iterator for OnErr<I, F> where
    I: Iterator<Item = Result<T, E>>,
    F: FnMut(&E)
{
    type Item = Result<T, E>;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        match self.iter.next() {
            Some(Err(e)) => {
                (self.f)(&e);
                Some(Err(e))
            },
            other => other
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<I, F> ExactSizeIterator for OnErr<I, F> where
    I: ExactSizeIterator,
    OnErr<I, F>: Iterator
{
}

impl<I, F, T, E> DoubleEndedIterator for OnErr<I, F> where
    I: DoubleEndedIterator<Item = Result<T, E>>,
    F: FnMut(&E)
{
    #[inline]
    fn next_back(&mut self) -> Option<Self::Item> {
        match self.iter.next_back() {
            Some(Err(e)) => {
                (self.f)(&e);
                Some(Err(e))
            },
            other => other
        }
    }
}

/// An iterator that unwraps the `Ok` items of `iter`, while passing the `Err` items to its
/// closure `f`.
///
/// This `struct` is created by the `unwrap_with()` method on `TraceIterator`. See its
/// documentation for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Clone)]
pub struct UnwrapWith<I, F>{
    iter: I,
    f: F
}

impl<I, F, T, E> Iterator for UnwrapWith<I, F> where
    I: Iterator<Item = Result<T, E>>,
    F: FnMut(E)
{
    type Item = T;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        loop {
            match self.iter.next() {
                Some(Err(e)) => {
                    (self.f)(e);
                },
                Some(Ok(item)) => return Some(item),
                None => return None,
            }
        }
    }
    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let (_, upper) = self.iter.size_hint();
        (0, upper)
    }
}

impl<I, F, T, E> DoubleEndedIterator for UnwrapWith<I, F> where
    I: DoubleEndedIterator<Item = Result<T, E>>,
    F: FnMut(E)
{
    #[inline]
    fn next_back(&mut self) -> Option<Self::Item> {
        loop {
            match self.iter.next_back() {
                Some(Err(e)) => {
                    (self.f)(e);
                },
                Some(Ok(item)) => return Some(item),
                None => return None,
            }
        }
    }
}

/// This trait provides methods that make it easier to work with iterators that yield a `Result`.
pub trait TraceIterator<T, E> : Iterator<Item = Result<T, E>> + Sized {
    /// Creates an iterator that yields the item in each `Ok` item, while filtering out the `Err`
    /// items. Each filtered `Err` will be trace-logged with [`::trace::trace_error`].
    ///
    /// As with all iterators, the processing is lazy. If you do not use the result of this method,
    /// nothing will be passed to `::trace::trace_error`, no matter how many `Err` items might
    /// be present.
    #[inline]
    fn trace_unwrap(self) -> UnwrapWith<Self, fn(E)> where E: Error {
        #[inline]
        fn trace_error<E: Error>(err: E) {
            ::trace::trace_error(&err);
        }

        self.unwrap_with(trace_error)
    }

    /// Takes a closure and creates an iterator that will call that closure for each `Err` element.
    /// The resulting iterator will yield the exact same items as the original iterator. A close
    /// analogue from the standard library would be `Iterator::inspect`.
    ///
    /// As with all iterators, the processing is lazy. The result of this method must be evaluated
    /// for the closure to be called.
    #[inline]
    fn on_err<F>(self, f: F) -> OnErr<Self, F>  where F: FnMut(&E) {
        OnErr { iter: self, f: f }
    }

    /// Takes a closure and creates an iterator that will yield the items inside all `Ok` items
    /// yielded by the original iterator. All `Err` items will be filtered out, and the contents
    /// of each `Err` will be passed to the closure.
    ///
    /// As with all iterators, the processing is lazy. The result of this method must be evaluated
    /// for the closure to be called.
    #[inline]
    fn unwrap_with<F>(self, f: F) -> UnwrapWith<Self, F>
        where F: FnMut(E)
    {
        UnwrapWith { iter: self, f: f }
    }
}

impl<I, T, E> TraceIterator<T, E> for I where
    I: Iterator<Item = Result<T, E>>
{}

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

    #[derive(Copy, Clone, Eq, PartialEq, Debug)]
    struct TestError(i32);

    #[test]
    fn test_unwrap_with() {
        let original = vec![Ok(1), Err(TestError(2)), Ok(3), Err(TestError(4))];
        let mut errs = vec![];

        let oks = original
            .into_iter()
            .unwrap_with(|e|errs.push(e))
            .collect::<Vec<_>>();

        assert_eq!(&oks, &[1, 3]);
        assert_eq!(&errs, &[TestError(2), TestError(4)]);
    }

    #[test]
    fn test_unwrap_with_backward() {
        let original = vec![Ok(1), Err(TestError(2)), Ok(3), Err(TestError(4))];
        let mut errs = vec![];

        let oks = original
            .into_iter()
            .rev()
            .unwrap_with(|e|errs.push(e))
            .collect::<Vec<_>>();

        assert_eq!(&oks, &[3, 1]);
        assert_eq!(&errs, &[TestError(4), TestError(2)]);
    }

    #[test]
    fn test_on_err() {
        let original = vec![Ok(1), Err(TestError(2)), Ok(3), Err(TestError(4))];
        let mut errs = vec![];

        let result = original
            .into_iter()
            .on_err(|e|errs.push(e.clone()))
            .collect::<Vec<_>>();

        assert_eq!(&result, &[Ok(1), Err(TestError(2)), Ok(3), Err(TestError(4))]);
        assert_eq!(&errs, &[TestError(2), TestError(4)]);
     }

    #[test]
    fn test_on_err_backward() {
        let original = vec![Ok(1), Err(TestError(2)), Ok(3), Err(TestError(4))];
        let mut errs = vec![];

        let result = original
            .into_iter()
            .rev()
            .on_err(|e|errs.push(e.clone()))
            .collect::<Vec<_>>();

        assert_eq!(&result, &[Err(TestError(4)), Ok(3), Err(TestError(2)), Ok(1)]);
        assert_eq!(&errs, &[TestError(4), TestError(2)]);
     }
}
<commit_msg>Simplify `OnErr` iterator `next` and `next_back`<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2016 the imag 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 std::error::Error;

/// An iterator that maps `f` over the `Error` elements of `iter`, similar to `std::iter::Map`.
///
/// This `struct` is created by the `on_err()` method on `TraceIterator`. See its
/// documentation for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Clone)]
pub struct OnErr<I, F>{
    iter: I,
    f: F
}

impl<I, F, T, E> Iterator for OnErr<I, F> where
    I: Iterator<Item = Result<T, E>>,
    F: FnMut(&E)
{
    type Item = Result<T, E>;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|r| r.map_err(|e| { (self.f)(&e); e }))
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<I, F> ExactSizeIterator for OnErr<I, F> where
    I: ExactSizeIterator,
    OnErr<I, F>: Iterator
{
}

impl<I, F, T, E> DoubleEndedIterator for OnErr<I, F> where
    I: DoubleEndedIterator<Item = Result<T, E>>,
    F: FnMut(&E)
{
    #[inline]
    fn next_back(&mut self) -> Option<Self::Item> {
        self.iter.next_back().map(|r| r.map_err(|e| { (self.f)(&e); e }))
    }
}

/// An iterator that unwraps the `Ok` items of `iter`, while passing the `Err` items to its
/// closure `f`.
///
/// This `struct` is created by the `unwrap_with()` method on `TraceIterator`. See its
/// documentation for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Clone)]
pub struct UnwrapWith<I, F>{
    iter: I,
    f: F
}

impl<I, F, T, E> Iterator for UnwrapWith<I, F> where
    I: Iterator<Item = Result<T, E>>,
    F: FnMut(E)
{
    type Item = T;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        loop {
            match self.iter.next() {
                Some(Err(e)) => {
                    (self.f)(e);
                },
                Some(Ok(item)) => return Some(item),
                None => return None,
            }
        }
    }
    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let (_, upper) = self.iter.size_hint();
        (0, upper)
    }
}

impl<I, F, T, E> DoubleEndedIterator for UnwrapWith<I, F> where
    I: DoubleEndedIterator<Item = Result<T, E>>,
    F: FnMut(E)
{
    #[inline]
    fn next_back(&mut self) -> Option<Self::Item> {
        loop {
            match self.iter.next_back() {
                Some(Err(e)) => {
                    (self.f)(e);
                },
                Some(Ok(item)) => return Some(item),
                None => return None,
            }
        }
    }
}

/// This trait provides methods that make it easier to work with iterators that yield a `Result`.
pub trait TraceIterator<T, E> : Iterator<Item = Result<T, E>> + Sized {
    /// Creates an iterator that yields the item in each `Ok` item, while filtering out the `Err`
    /// items. Each filtered `Err` will be trace-logged with [`::trace::trace_error`].
    ///
    /// As with all iterators, the processing is lazy. If you do not use the result of this method,
    /// nothing will be passed to `::trace::trace_error`, no matter how many `Err` items might
    /// be present.
    #[inline]
    fn trace_unwrap(self) -> UnwrapWith<Self, fn(E)> where E: Error {
        #[inline]
        fn trace_error<E: Error>(err: E) {
            ::trace::trace_error(&err);
        }

        self.unwrap_with(trace_error)
    }

    /// Takes a closure and creates an iterator that will call that closure for each `Err` element.
    /// The resulting iterator will yield the exact same items as the original iterator. A close
    /// analogue from the standard library would be `Iterator::inspect`.
    ///
    /// As with all iterators, the processing is lazy. The result of this method must be evaluated
    /// for the closure to be called.
    #[inline]
    fn on_err<F>(self, f: F) -> OnErr<Self, F>  where F: FnMut(&E) {
        OnErr { iter: self, f: f }
    }

    /// Takes a closure and creates an iterator that will yield the items inside all `Ok` items
    /// yielded by the original iterator. All `Err` items will be filtered out, and the contents
    /// of each `Err` will be passed to the closure.
    ///
    /// As with all iterators, the processing is lazy. The result of this method must be evaluated
    /// for the closure to be called.
    #[inline]
    fn unwrap_with<F>(self, f: F) -> UnwrapWith<Self, F>
        where F: FnMut(E)
    {
        UnwrapWith { iter: self, f: f }
    }
}

impl<I, T, E> TraceIterator<T, E> for I where
    I: Iterator<Item = Result<T, E>>
{}

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

    #[derive(Copy, Clone, Eq, PartialEq, Debug)]
    struct TestError(i32);

    #[test]
    fn test_unwrap_with() {
        let original = vec![Ok(1), Err(TestError(2)), Ok(3), Err(TestError(4))];
        let mut errs = vec![];

        let oks = original
            .into_iter()
            .unwrap_with(|e|errs.push(e))
            .collect::<Vec<_>>();

        assert_eq!(&oks, &[1, 3]);
        assert_eq!(&errs, &[TestError(2), TestError(4)]);
    }

    #[test]
    fn test_unwrap_with_backward() {
        let original = vec![Ok(1), Err(TestError(2)), Ok(3), Err(TestError(4))];
        let mut errs = vec![];

        let oks = original
            .into_iter()
            .rev()
            .unwrap_with(|e|errs.push(e))
            .collect::<Vec<_>>();

        assert_eq!(&oks, &[3, 1]);
        assert_eq!(&errs, &[TestError(4), TestError(2)]);
    }

    #[test]
    fn test_on_err() {
        let original = vec![Ok(1), Err(TestError(2)), Ok(3), Err(TestError(4))];
        let mut errs = vec![];

        let result = original
            .into_iter()
            .on_err(|e|errs.push(e.clone()))
            .collect::<Vec<_>>();

        assert_eq!(&result, &[Ok(1), Err(TestError(2)), Ok(3), Err(TestError(4))]);
        assert_eq!(&errs, &[TestError(2), TestError(4)]);
     }

    #[test]
    fn test_on_err_backward() {
        let original = vec![Ok(1), Err(TestError(2)), Ok(3), Err(TestError(4))];
        let mut errs = vec![];

        let result = original
            .into_iter()
            .rev()
            .on_err(|e|errs.push(e.clone()))
            .collect::<Vec<_>>();

        assert_eq!(&result, &[Err(TestError(4)), Ok(3), Err(TestError(2)), Ok(1)]);
        assert_eq!(&errs, &[TestError(4), TestError(2)]);
     }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::ops::{DerefMut, Deref};

use toml::Value;

use libimagrt::runtime::Runtime;
use libimagrt::edit::{Edit, EditResult};
use libimagstore::storeid::IntoStoreId;
use libimagstore::storeid::StoreId;
use libimagstore::storeid::StoreIdIterator;
use libimagstore::store::FileLockEntry;
use libimagstore::store::Store;
use libimagentrytag::tag::Tag;
use libimagentrytag::tagable::Tagable;
use libimagentrytag::result::Result as TagResult;

use module_path::ModuleEntryPath;
use result::Result;
use error::NoteError as NE;
use error::NoteErrorKind as NEK;

pub struct Note<'a> {
    entry: FileLockEntry<'a>,
}

impl<'a> Note<'a> {

    pub fn new(store: &Store, name: String, text: String) -> Result<Note> {
        use std::ops::DerefMut;

        debug!("Creating new Note: '{}'", name);
        let fle = {
            let lockentry = store.create(ModuleEntryPath::new(name.clone()).into_storeid());
            if lockentry.is_err() {
                return Err(NE::new(NEK::StoreWriteError, Some(Box::new(lockentry.err().unwrap()))));
            }
            let mut lockentry = lockentry.unwrap();

            {
                let mut entry  = lockentry.deref_mut();

                {
                    let mut header = entry.get_header_mut();
                    let setres = header.set("note", Value::Table(BTreeMap::new()));
                    if setres.is_err() {
                        let kind = NEK::StoreWriteError;
                        return Err(NE::new(kind, Some(Box::new(setres.err().unwrap()))));
                    }

                    let setres = header.set("note.name", Value::String(name));
                    if setres.is_err() {
                        let kind = NEK::StoreWriteError;
                        return Err(NE::new(kind, Some(Box::new(setres.err().unwrap()))));
                    }
                }

                *entry.get_content_mut() = text;
            }

            lockentry
        };

        Ok(Note { entry: fle })
    }

    pub fn set_name(&mut self, n: String) -> Result<()> {
        let mut header = self.entry.deref_mut().get_header_mut();
        header.set("note.name", Value::String(n))
            .map_err(|e| NE::new(NEK::StoreWriteError, Some(Box::new(e))))
            .map(|_| ())
    }

    pub fn get_name(&self) -> Result<String> {
        let header = self.entry.deref().get_header();
        match header.read("note.name") {
            Ok(Some(Value::String(s))) => Ok(String::from(s)),
            Ok(_)                => {
                let e = NE::new(NEK::HeaderTypeError, None);
                Err(NE::new(NEK::StoreReadError, Some(Box::new(e))))
            },
            Err(e) => Err(NE::new(NEK::StoreReadError, Some(Box::new(e))))
        }
    }

    pub fn set_text(&mut self, n: String) {
        *self.entry.deref_mut().get_content_mut() = n
    }

    pub fn get_text(&self) -> &String {
        self.entry.deref().get_content()
    }

    pub fn delete(store: &Store, name: String) -> Result<()> {
        store.delete(ModuleEntryPath::new(name).into_storeid())
            .map_err(|e| NE::new(NEK::StoreWriteError, Some(Box::new(e))))
    }

    pub fn retrieve(store: &Store, name: String) -> Result<Note> {
        store.retrieve(ModuleEntryPath::new(name).into_storeid())
            .map_err(|e| NE::new(NEK::StoreWriteError, Some(Box::new(e))))
            .map(|entry| Note { entry: entry })
    }

    pub fn all_notes(store: &Store) -> Result<NoteIterator> {
        store.retrieve_for_module("notes")
            .map(|iter| NoteIterator::new(store, iter))
            .map_err(|e| NE::new(NEK::StoreReadError, Some(Box::new(e))))
    }

}

impl<'a> Edit for Note<'a> {

    fn edit_content(&mut self, rt: &Runtime) -> EditResult<()> {
        self.entry.edit_content(rt)
    }

}

impl<'a> Tagable for Note<'a> {

    fn get_tags(&self) -> TagResult<Vec<Tag>> {
        self.entry.deref().get_tags()
    }

    fn set_tags(&mut self, ts: Vec<Tag>) -> TagResult<()> {
        self.entry.deref_mut().set_tags(ts)
    }

    fn add_tag(&mut self, t: Tag) -> TagResult<()> {
        self.entry.deref_mut().add_tag(t)
    }

    fn remove_tag(&mut self, t: Tag) -> TagResult<()> {
        self.entry.deref_mut().remove_tag(t)
    }

    fn has_tag(&self, t: &Tag) -> TagResult<bool> {
        self.entry.deref().has_tag(t)
    }

    fn has_tags(&self, ts: &Vec<Tag>) -> TagResult<bool> {
        self.entry.deref().has_tags(ts)
    }

}

trait FromStoreId {
    fn from_storeid<'a>(&'a Store, StoreId) -> Result<Note<'a>>;
}

impl<'a> FromStoreId for Note<'a> {

    fn from_storeid<'b>(store: &'b Store, id: StoreId) -> Result<Note<'b>> {
        debug!("Loading note from storeid: '{:?}'", id);
        match store.retrieve(id) {
            Err(e)    => Err(NE::new(NEK::StoreReadError, Some(Box::new(e)))),
            Ok(entry) => Ok(Note { entry: entry }),
        }
    }

}

impl<'a> Deref for Note<'a> {

    type Target = FileLockEntry<'a>;

    fn deref(&self) -> &FileLockEntry<'a> {
        &self.entry
    }

}

pub struct NoteIterator<'a> {
    store: &'a Store,
    iditer: StoreIdIterator,
}

impl<'a> NoteIterator<'a> {

    pub fn new(store: &'a Store, iditer: StoreIdIterator) -> NoteIterator<'a> {
        NoteIterator {
            store: store,
            iditer: iditer,
        }
    }

}

impl<'a> Iterator for NoteIterator<'a> {
    type Item = Result<Note<'a>>;

    fn next(&mut self) -> Option<Result<Note<'a>>> {
        self.iditer
            .next()
            .map(|id| Note::from_storeid(self.store, id))
    }

}

<commit_msg>libimagnotes: Replace .err().unwrap() with .unwrap_err()<commit_after>use std::collections::BTreeMap;
use std::ops::{DerefMut, Deref};

use toml::Value;

use libimagrt::runtime::Runtime;
use libimagrt::edit::{Edit, EditResult};
use libimagstore::storeid::IntoStoreId;
use libimagstore::storeid::StoreId;
use libimagstore::storeid::StoreIdIterator;
use libimagstore::store::FileLockEntry;
use libimagstore::store::Store;
use libimagentrytag::tag::Tag;
use libimagentrytag::tagable::Tagable;
use libimagentrytag::result::Result as TagResult;

use module_path::ModuleEntryPath;
use result::Result;
use error::NoteError as NE;
use error::NoteErrorKind as NEK;

pub struct Note<'a> {
    entry: FileLockEntry<'a>,
}

impl<'a> Note<'a> {

    pub fn new(store: &Store, name: String, text: String) -> Result<Note> {
        use std::ops::DerefMut;

        debug!("Creating new Note: '{}'", name);
        let fle = {
            let lockentry = store.create(ModuleEntryPath::new(name.clone()).into_storeid());
            if lockentry.is_err() {
                return Err(NE::new(NEK::StoreWriteError, Some(Box::new(lockentry.unwrap_err()))));
            }
            let mut lockentry = lockentry.unwrap();

            {
                let mut entry  = lockentry.deref_mut();

                {
                    let mut header = entry.get_header_mut();
                    let setres = header.set("note", Value::Table(BTreeMap::new()));
                    if setres.is_err() {
                        let kind = NEK::StoreWriteError;
                        return Err(NE::new(kind, Some(Box::new(setres.unwrap_err()))));
                    }

                    let setres = header.set("note.name", Value::String(name));
                    if setres.is_err() {
                        let kind = NEK::StoreWriteError;
                        return Err(NE::new(kind, Some(Box::new(setres.unwrap_err()))));
                    }
                }

                *entry.get_content_mut() = text;
            }

            lockentry
        };

        Ok(Note { entry: fle })
    }

    pub fn set_name(&mut self, n: String) -> Result<()> {
        let mut header = self.entry.deref_mut().get_header_mut();
        header.set("note.name", Value::String(n))
            .map_err(|e| NE::new(NEK::StoreWriteError, Some(Box::new(e))))
            .map(|_| ())
    }

    pub fn get_name(&self) -> Result<String> {
        let header = self.entry.deref().get_header();
        match header.read("note.name") {
            Ok(Some(Value::String(s))) => Ok(String::from(s)),
            Ok(_)                => {
                let e = NE::new(NEK::HeaderTypeError, None);
                Err(NE::new(NEK::StoreReadError, Some(Box::new(e))))
            },
            Err(e) => Err(NE::new(NEK::StoreReadError, Some(Box::new(e))))
        }
    }

    pub fn set_text(&mut self, n: String) {
        *self.entry.deref_mut().get_content_mut() = n
    }

    pub fn get_text(&self) -> &String {
        self.entry.deref().get_content()
    }

    pub fn delete(store: &Store, name: String) -> Result<()> {
        store.delete(ModuleEntryPath::new(name).into_storeid())
            .map_err(|e| NE::new(NEK::StoreWriteError, Some(Box::new(e))))
    }

    pub fn retrieve(store: &Store, name: String) -> Result<Note> {
        store.retrieve(ModuleEntryPath::new(name).into_storeid())
            .map_err(|e| NE::new(NEK::StoreWriteError, Some(Box::new(e))))
            .map(|entry| Note { entry: entry })
    }

    pub fn all_notes(store: &Store) -> Result<NoteIterator> {
        store.retrieve_for_module("notes")
            .map(|iter| NoteIterator::new(store, iter))
            .map_err(|e| NE::new(NEK::StoreReadError, Some(Box::new(e))))
    }

}

impl<'a> Edit for Note<'a> {

    fn edit_content(&mut self, rt: &Runtime) -> EditResult<()> {
        self.entry.edit_content(rt)
    }

}

impl<'a> Tagable for Note<'a> {

    fn get_tags(&self) -> TagResult<Vec<Tag>> {
        self.entry.deref().get_tags()
    }

    fn set_tags(&mut self, ts: Vec<Tag>) -> TagResult<()> {
        self.entry.deref_mut().set_tags(ts)
    }

    fn add_tag(&mut self, t: Tag) -> TagResult<()> {
        self.entry.deref_mut().add_tag(t)
    }

    fn remove_tag(&mut self, t: Tag) -> TagResult<()> {
        self.entry.deref_mut().remove_tag(t)
    }

    fn has_tag(&self, t: &Tag) -> TagResult<bool> {
        self.entry.deref().has_tag(t)
    }

    fn has_tags(&self, ts: &Vec<Tag>) -> TagResult<bool> {
        self.entry.deref().has_tags(ts)
    }

}

trait FromStoreId {
    fn from_storeid<'a>(&'a Store, StoreId) -> Result<Note<'a>>;
}

impl<'a> FromStoreId for Note<'a> {

    fn from_storeid<'b>(store: &'b Store, id: StoreId) -> Result<Note<'b>> {
        debug!("Loading note from storeid: '{:?}'", id);
        match store.retrieve(id) {
            Err(e)    => Err(NE::new(NEK::StoreReadError, Some(Box::new(e)))),
            Ok(entry) => Ok(Note { entry: entry }),
        }
    }

}

impl<'a> Deref for Note<'a> {

    type Target = FileLockEntry<'a>;

    fn deref(&self) -> &FileLockEntry<'a> {
        &self.entry
    }

}

pub struct NoteIterator<'a> {
    store: &'a Store,
    iditer: StoreIdIterator,
}

impl<'a> NoteIterator<'a> {

    pub fn new(store: &'a Store, iditer: StoreIdIterator) -> NoteIterator<'a> {
        NoteIterator {
            store: store,
            iditer: iditer,
        }
    }

}

impl<'a> Iterator for NoteIterator<'a> {
    type Item = Result<Note<'a>>;

    fn next(&mut self) -> Option<Result<Note<'a>>> {
        self.iditer
            .next()
            .map(|id| Note::from_storeid(self.store, id))
    }

}

<|endoftext|>