<commit_before>//! Decoding of OpenEXR (.exr) Images
//!
//! OpenEXR is an image format that is widely used, especially in VFX,
//! because it supports lossless and lossy compression for float data.
//!
//! # Related Links
//! * <https://www.openexr.com/documentation.html> - The OpenEXR reference.

// # ROADMAP
// - [] ImageDecoder
// - [] ImageEncoder
// - [] GenericImageView?
// - [] GenericImage?
// - [] Progress

// # MAYBE SOON
// - [] ImageDecoderExt::read_rect_with_progress
// - [] Layers -> Animation?

extern crate exr;
use exr::prelude::*;

use crate::{ImageDecoder, ImageResult, ColorType, Progress, image, ImageError, ImageFormat};
use std::io::{Write, Seek, BufRead, SeekFrom, Cursor};
use crate::error::{DecodingError, ImageFormatHint};
use self::exr::meta::header::Header;

/// An OpenEXR decoder
#[derive(Debug)]
pub struct ExrDecoder<R> {
    source: R,
    header: exr::meta::header::Header,
}

impl<R: BufRead + Seek + Send> ExrDecoder<R> {

    /// Create a decoder. Consumes the first few bytes of the source to extract image dimensions.
    pub fn read(mut source: R) -> ImageResult<Self> {

        // read meta data, then go back to the start of the file
        let mut meta_data = {
            let start_position = source.stream_position()?;
            let meta: MetaData = exr::meta::MetaData::read_from_buffered(&mut source, true)?;
            source.seek(SeekFrom::Start(start_position))?;
            meta
        };

        let header: Header = meta_data.headers.into_iter()
            .filter(|header|{
                let has_rgb = ["R","G","B"].iter().all(
                    |required| header.channels.list.iter().find(|chan| chan.name.eq(required)).is_some() // TODO eq_lowercase only if exrs supports it
                );

                !header.deep && has_rgb
            })
            .next()
            .ok_or_else(|| ImageError::Decoding(DecodingError::new(
                ImageFormatHint::Exact(ImageFormat::Exr),
                "image does not contain non-deep rgb channels"
            )))?;

        Ok(Self { source, header })
    }
}

impl<'a, R: 'a + BufRead + Seek + Send> ImageDecoder<'a> for ExrDecoder<R> {
    type Reader = Cursor<Vec<u8>>;

    fn dimensions(&self) -> (u32, u32) {
        let s = self.header.layer_size;
        (s.width() as u32, s.height() as u32)
    }

    // TODO fn original_color_type(&self) -> ExtendedColorType {}

    fn color_type(&self) -> ColorType {
        // TODO adapt to actual exr color type
        // TODO f32 ColorType::Rgba32
        ColorType::Rgba16
    }

    /// Use `read_image` if possible,
    /// as this method creates a whole new buffer to contain the entire image.
    fn into_reader(self) -> ImageResult<Self::Reader> {
        Ok(Cursor::new(image::decoder_to_vec(self)?)) // TODO no vec?
    }

    fn scanline_bytes(&self) -> u64 {
        // we cannot always read individual scan lines,
        // as the tiles or lines in the file could be in random order.
        // therefore we currently read all lines at once
        // Todo: respect exr.line_order
       self.total_bytes()
    }

    fn read_image(mut self, target: &mut [u8]) -> ImageResult<()> {
        self.read_image_with_progress(target, |_|{})
    }

    fn read_image_with_progress<F: Fn(Progress)>(self, target: &mut [u8], progress_callback: F) -> ImageResult<()> {
        // TODO reuse meta-data from earlier

        let result = exr::prelude::read()
            .no_deep_data().largest_resolution_level()
            .rgba_channels(
                // FIXME no alloc+copy, write into target slice directly!
                |size, _channels| (
                    size, vec![0_u16; size.area()*4]
                ),

                |(size, buffer), position, (r,g,b,a_or_1): (f32,f32,f32,f32)| {
                    // TODO white point chromaticities + srgb/linear conversion?
                    let first_f32_index = position.flat_index_for_size(*size);
                    let to_u16 = |v:f32| (v.clamp(0.0, 1.0) * u16::MAX as f32) as u16; // TODO remove, always use 32

                    buffer[first_f32_index*4 .. (first_f32_index + 1)*4]
                        .copy_from_slice(&[to_u16(r), to_u16(g), to_u16(b), to_u16(a_or_1)]);
                }
            )
            .first_valid_layer().all_attributes()
            .on_progress(move |progress| {
                let mut prog = progress_callback;
                prog(Progress::new((progress*100.0) as u64, 100_u64));
            })
            .from_buffered(self.source)?;

        target.copy_from_slice(bytemuck::cast_slice(result.layer_data.channel_data.pixels.1.as_slice()));
        // TODO keep meta data?

        Ok(())
    }
}

pub fn write_image(mut out: impl Write, bytes: &[u8], width: u32, height: u32, color_type: ColorType) -> ImageResult<()> {
    let pixels: &[u16] = bytemuck::try_cast_slice(bytes).expect("byte buffer must be aligned to u16");

    let mut seekable_write = Cursor::new(Vec::<u8>::with_capacity(bytes.len())); // TODO make parameter +seek
    let as_f32 = |v:u16| (v as f32) / u16::MAX as f32; // TODO remove, always use f32

    match color_type {
        ColorType::Rgb16 => {
            exr::prelude::Image::from_channels(
                (width as usize, height as usize),
                SpecificChannels::rgb(|pixel: Vec2<usize>| {
                    let pixel_index = 3 * pixel.flat_index_for_size(Vec2(width as usize, height as usize));
                    (as_f32(pixels[pixel_index]), as_f32(pixels[pixel_index+1]), as_f32(pixels[pixel_index+2]))
                })
            ).write().to_buffered(&mut seekable_write)?;
        }

        ColorType::Rgba16 => {
            exr::prelude::Image::from_channels(
                (width as usize, height as usize),
                SpecificChannels::rgba(|pixel: Vec2<usize>| {
                    let pixel_index = 4 * pixel.flat_index_for_size(Vec2(width as usize, height as usize));
                    (as_f32(pixels[pixel_index]), as_f32(pixels[pixel_index+1]), as_f32(pixels[pixel_index+2]), as_f32(pixels[pixel_index+3]))
                })
            ).write().to_buffered(&mut seekable_write)?;
        }

        _ => todo!()
    }

    out.write_all(seekable_write.into_inner().as_slice())?;
    Ok(())
}

impl From<exr::error::Error> for ImageError {
    fn from(exr_error: Error) -> Self {
        ImageError::Decoding(DecodingError::new(
            ImageFormatHint::Exact(ImageFormat::Exr),
            exr_error
        ))
    }
}

<commit_msg>the minorest improvements (minor cleanup)<commit_after>//! Decoding of OpenEXR (.exr) Images
//!
//! OpenEXR is an image format that is widely used, especially in VFX,
//! because it supports lossless and lossy compression for float data.
//!
//! # Related Links
//! * <https://www.openexr.com/documentation.html> - The OpenEXR reference.

// # ROADMAP
// - [] ImageDecoder
// - [] ImageEncoder
// - [] GenericImageView?
// - [] GenericImage?
// - [] Progress

// # MAYBE SOON
// - [] ImageDecoderExt::read_rect_with_progress
// - [] Layers -> Animation?

extern crate exr;
use exr::prelude::*;

use crate::{ImageDecoder, ImageResult, ColorType, Progress, image, ImageError, ImageFormat};
use std::io::{Write, Seek, BufRead, SeekFrom, Cursor};
use crate::error::{DecodingError, ImageFormatHint};
use self::exr::meta::header::Header;

/// An OpenEXR decoder
#[derive(Debug)]
pub struct ExrDecoder<R> {
    source: R,
    header: exr::meta::header::Header,
}

impl<R: BufRead + Seek + Send> ExrDecoder<R> {

    /// Create a decoder. Consumes the first few bytes of the source to extract image dimensions.
    pub fn read(mut source: R) -> ImageResult<Self> {

        // read meta data, then go back to the start of the file
        let mut meta_data = {
            let start_position = source.stream_position()?;
            let meta: MetaData = exr::meta::MetaData::read_from_buffered(&mut source, true)?;
            source.seek(SeekFrom::Start(start_position))?;
            meta
        };

        let header: Header = meta_data.headers.into_iter()
            .filter(|header|{
                let has_rgb = ["R","G","B"].iter().all(
                    // check if r/g/b exists in the channels
                    |required| header.channels.list.iter()
                        .find(|chan| chan.name.eq(required)).is_some() // TODO eq_lowercase only if exrs supports it
                );

                !header.deep && has_rgb
            })
            .next()
            .ok_or_else(|| ImageError::Decoding(DecodingError::new(
                ImageFormatHint::Exact(ImageFormat::Exr),
                "image does not contain non-deep rgb channels"
            )))?;

        Ok(Self { source, header })
    }
}

impl<'a, R: 'a + BufRead + Seek + Send> ImageDecoder<'a> for ExrDecoder<R> {
    type Reader = Cursor<Vec<u8>>;

    fn dimensions(&self) -> (u32, u32) {
        let size = self.header.layer_size;
        (size.width() as u32, size.height() as u32)
    }

    // TODO fn original_color_type(&self) -> ExtendedColorType {}

    fn color_type(&self) -> ColorType {
        // TODO adapt to actual exr color type
        // TODO f32 ColorType::Rgba32
        ColorType::Rgba16
    }

    /// Use `read_image` if possible,
    /// as this method creates a whole new buffer to contain the entire image.
    fn into_reader(self) -> ImageResult<Self::Reader> {
        Ok(Cursor::new(image::decoder_to_vec(self)?)) // TODO no vec?
    }

    fn scanline_bytes(&self) -> u64 {
        // we cannot always read individual scan lines,
        // as the tiles or lines in the file could be in random order.
        // therefore we currently read all lines at once
        // Todo: respect exr.line_order
       self.total_bytes()
    }

    fn read_image_with_progress<F: Fn(Progress)>(self, target: &mut [u8], progress_callback: F) -> ImageResult<()> {
        // TODO reuse meta-data from earlier

        let result = exr::prelude::read()
            .no_deep_data().largest_resolution_level()
            .rgba_channels(
                // FIXME no alloc+copy, write into target slice directly!
                |size, _channels| (
                    size, vec![0_u16; size.area()*4]
                ),

                |(size, buffer), position, (r,g,b,a_or_1): (f32,f32,f32,f32)| {
                    // TODO white point chromaticities + srgb/linear conversion?
                    let first_f32_index = position.flat_index_for_size(*size);
                    let to_u16 = |v:f32| (v.clamp(0.0, 1.0) * u16::MAX as f32) as u16; // TODO remove, always use f32

                    buffer[first_f32_index*4 .. (first_f32_index + 1)*4]
                        .copy_from_slice(&[to_u16(r), to_u16(g), to_u16(b), to_u16(a_or_1)]);
                }
            )
            .first_valid_layer().all_attributes()
            .on_progress(move |progress| {
                let precision = 1000;
                let mut prog = progress_callback;
                prog(Progress::new((progress*precision as f32) as u64, precision));
            })
            .from_buffered(self.source)?;

        target.copy_from_slice(bytemuck::cast_slice(result.layer_data.channel_data.pixels.1.as_slice()));
        // TODO keep meta data?

        Ok(())
    }
}

pub fn write_image(mut out: impl Write, bytes: &[u8], width: u32, height: u32, color_type: ColorType) -> ImageResult<()> {
    let pixels: &[u16] = bytemuck::try_cast_slice(bytes).expect("byte buffer must be aligned to u16");

    let mut seekable_write = Cursor::new(Vec::<u8>::with_capacity(bytes.len())); // TODO make parameter +seek
    let as_f32 = |v:u16| (v as f32) / u16::MAX as f32; // TODO remove, always use f32

    match color_type {
        ColorType::Rgb16 => {
            exr::prelude::Image::from_channels(
                (width as usize, height as usize),
                SpecificChannels::rgb(|pixel: Vec2<usize>| {
                    let pixel_index = 3 * pixel.flat_index_for_size(Vec2(width as usize, height as usize));
                    (as_f32(pixels[pixel_index]), as_f32(pixels[pixel_index+1]), as_f32(pixels[pixel_index+2]))
                })
            )
                .write()
                // .on_progress(|progress| todo!())
                .to_buffered(&mut seekable_write)?;
        }

        ColorType::Rgba16 => {
            exr::prelude::Image::from_channels(
                (width as usize, height as usize),
                SpecificChannels::rgba(|pixel: Vec2<usize>| {
                    let pixel_index = 4 * pixel.flat_index_for_size(Vec2(width as usize, height as usize));
                    (as_f32(pixels[pixel_index]), as_f32(pixels[pixel_index+1]), as_f32(pixels[pixel_index+2]), as_f32(pixels[pixel_index+3]))
                })
            )
                .write()
                // .on_progress(|progress| todo!())
                .to_buffered(&mut seekable_write)?;
        }

        _ => todo!()
    }

    out.write_all(seekable_write.into_inner().as_slice())?;
    Ok(())
}

impl From<exr::error::Error> for ImageError {
    fn from(exr_error: Error) -> Self {
        ImageError::Decoding(DecodingError::new(
            ImageFormatHint::Exact(ImageFormat::Exr),
            exr_error
        ))
    }
}

<|endoftext|>


<commit_before>use std::collections::hash_map::DefaultHasher;
use std::hash::{BuildHasherDefault, Hash};

use utils::HashIter;

/// Abstract, but safe counter.
pub trait Counter: Copy + Ord + Sized {
    /// Add self to another counter.
    ///
    /// Returns `Some(Self)` when the addition was successfull (i.e. no overflow occured) and
    /// `None` in case of an error.
    fn checked_add(self, other: Self) -> Option<Self>;

    /// Return a counter representing zero.
    fn zero() -> Self;

    /// Return a counter representing one.
    fn one() -> Self;

    /// Checks whether the counter is zero.
    fn is_zero(&self) -> bool;
}

macro_rules! impl_counter {
    ($t:ty) => {
        impl Counter for $t {
            #[inline]
            fn checked_add(self, other: Self) -> Option<Self> {
                self.checked_add(other)
            }

            #[inline]
            fn zero() -> Self {
                0
            }

            #[inline]
            fn one() -> Self {
                1
            }

            #[inline]
            fn is_zero(&self) -> bool {
                *self == 0
            }
        }
    }
}

impl_counter!(usize);
impl_counter!(u64);
impl_counter!(u32);
impl_counter!(u16);
impl_counter!(u8);

/// Simple implementation of a
/// [Count-min sketch](https://en.wikipedia.org/wiki/Count%E2%80%93min_sketch)
///
/// The type parameter `C` sets the type of the counter in the internal table and can be used to
/// reduce memory consumption when low counts are expected.
#[derive(Clone)]
pub struct CountMinSketch<C = usize>
where
    C: Counter,
{
    table: Vec<C>,
    w: usize,
    d: usize,
}

impl<C> CountMinSketch<C>
where
    C: Counter,
{
    /// Create new CountMinSketch based on table size.
    ///
    /// - `w` sets the number of columns
    /// - `d` sets the number of rows
    pub fn with_params(w: usize, d: usize) -> CountMinSketch<C> {
        let table = vec![C::zero(); w.checked_mul(d).unwrap()];
        CountMinSketch {
            table: table,
            w: w,
            d: d,
        }
    }

    /// Get number of columns of internal counter table.
    pub fn w(&self) -> usize {
        self.w
    }

    /// Get number of rows of internal counter table.
    pub fn d(&self) -> usize {
        self.d
    }

    /// Check whether the CountMinSketch is empty (i.e. no elements seen yet).
    pub fn is_empty(&self) -> bool {
        self.table.iter().all(|x| x.is_zero())
    }

    /// Add one to the counter of the given element.
    pub fn add<T>(&mut self, obj: &T)
    where
        T: Hash,
    {
        self.add_n(&obj, C::one())
    }

    /// Add `n` to the counter of the given element.
    pub fn add_n<T>(&mut self, obj: &T, n: C)
    where
        T: Hash,
    {
        let bh = BuildHasherDefault::<DefaultHasher>::default();
        for (i, pos) in HashIter::new(self.w, self.d, obj, bh).enumerate() {
            let x = i * self.w + pos;
            self.table[x] = self.table[x].checked_add(n).unwrap();
        }
    }

    /// Runs a point query, i.e. a query for the count of a single object.
    pub fn query_point<T>(&self, obj: &T) -> C
    where
        T: Hash,
    {
        let bh = BuildHasherDefault::<DefaultHasher>::default();
        HashIter::new(self.w, self.d, obj, bh)
            .enumerate()
            .map(|(i, pos)| i * self.w + pos)
            .map(|x| self.table[x])
            .min()
            .unwrap()
    }

    /// Merge self with another CountMinSketch.
    ///
    /// After this operation `self` will be in the same state as when it would have seen all
    /// elements from `self` and `other`.
    ///
    /// Panics when `d` and `w` from `self` and `other` differ.
    pub fn merge(&mut self, other: &CountMinSketch<C>) {
        assert_eq!(self.d, other.d);
        assert_eq!(self.w, other.w);

        self.table = self.table
            .iter()
            .zip(other.table.iter())
            .map(|x| x.0.checked_add(*x.1).unwrap())
            .collect();
    }

    /// Clear internal counters to a fresh state (i.e. no objects seen).
    pub fn clear(&mut self) {
        self.table = vec![C::zero(); self.w.checked_mul(self.d).unwrap()];
    }
}

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

    #[test]
    fn getter() {
        let cms = CountMinSketch::<usize>::with_params(10, 20);
        assert_eq!(cms.w(), 10);
        assert_eq!(cms.d(), 20);
    }

    #[test]
    fn empty() {
        let cms = CountMinSketch::<usize>::with_params(10, 10);
        assert_eq!(cms.query_point(&1), 0);
        assert!(cms.is_empty());
    }

    #[test]
    fn add_1() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add(&1);
        assert_eq!(cms.query_point(&1), 1);
        assert_eq!(cms.query_point(&2), 0);
    }

    #[test]
    fn add_2() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add(&1);
        cms.add(&1);
        assert_eq!(cms.query_point(&1), 2);
        assert_eq!(cms.query_point(&2), 0);
    }

    #[test]
    fn add_2_1a() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add(&1);
        cms.add(&2);
        cms.add(&1);
        assert_eq!(cms.query_point(&1), 2);
        assert_eq!(cms.query_point(&2), 1);
        assert_eq!(cms.query_point(&3), 0);
    }

    #[test]
    fn add_2_1b() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add_n(&1, 2);
        cms.add(&2);
        assert_eq!(cms.query_point(&1), 2);
        assert_eq!(cms.query_point(&2), 1);
        assert_eq!(cms.query_point(&3), 0);
    }

    #[test]
    fn merge() {
        let mut cms1 = CountMinSketch::<usize>::with_params(10, 10);
        let mut cms2 = CountMinSketch::<usize>::with_params(10, 10);

        cms1.add_n(&1, 1);
        cms1.add_n(&2, 2);
        assert_eq!(cms1.query_point(&1), 1);
        assert_eq!(cms1.query_point(&2), 2);
        assert_eq!(cms1.query_point(&3), 0);
        assert_eq!(cms1.query_point(&4), 0);

        cms2.add_n(&2, 20);
        cms2.add_n(&3, 30);
        assert_eq!(cms2.query_point(&1), 0);
        assert_eq!(cms2.query_point(&2), 20);
        assert_eq!(cms2.query_point(&3), 30);
        assert_eq!(cms2.query_point(&4), 0);

        cms1.merge(&cms2);
        assert_eq!(cms1.query_point(&1), 1);
        assert_eq!(cms1.query_point(&2), 22);
        assert_eq!(cms1.query_point(&3), 30);
        assert_eq!(cms1.query_point(&4), 0);
    }

    #[test]
    fn clear() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add(&1);
        assert_eq!(cms.query_point(&1), 1);
        assert!(!cms.is_empty());

        cms.clear();
        assert_eq!(cms.query_point(&1), 0);
        assert!(cms.is_empty());
    }

    #[test]
    fn clone() {
        let mut cms1 = CountMinSketch::<usize>::with_params(10, 10);

        cms1.add(&1);
        assert_eq!(cms1.query_point(&1), 1);
        assert_eq!(cms1.query_point(&2), 0);

        let cms2 = cms1.clone();
        assert_eq!(cms2.query_point(&1), 1);
        assert_eq!(cms2.query_point(&2), 0);

        cms1.add(&1);
        assert_eq!(cms1.query_point(&1), 2);
        assert_eq!(cms1.query_point(&2), 0);
        assert_eq!(cms2.query_point(&1), 1);
        assert_eq!(cms2.query_point(&2), 0);
    }
}
<commit_msg>countminsketch: impl debug<commit_after>use std::collections::hash_map::DefaultHasher;
use std::fmt;
use std::hash::{BuildHasherDefault, Hash};

use utils::HashIter;

/// Abstract, but safe counter.
pub trait Counter: Copy + fmt::Debug + Ord + Sized {
    /// Add self to another counter.
    ///
    /// Returns `Some(Self)` when the addition was successfull (i.e. no overflow occured) and
    /// `None` in case of an error.
    fn checked_add(self, other: Self) -> Option<Self>;

    /// Return a counter representing zero.
    fn zero() -> Self;

    /// Return a counter representing one.
    fn one() -> Self;

    /// Checks whether the counter is zero.
    fn is_zero(&self) -> bool;
}

macro_rules! impl_counter {
    ($t:ty) => {
        impl Counter for $t {
            #[inline]
            fn checked_add(self, other: Self) -> Option<Self> {
                self.checked_add(other)
            }

            #[inline]
            fn zero() -> Self {
                0
            }

            #[inline]
            fn one() -> Self {
                1
            }

            #[inline]
            fn is_zero(&self) -> bool {
                *self == 0
            }
        }
    }
}

impl_counter!(usize);
impl_counter!(u64);
impl_counter!(u32);
impl_counter!(u16);
impl_counter!(u8);

/// Simple implementation of a
/// [Count-min sketch](https://en.wikipedia.org/wiki/Count%E2%80%93min_sketch)
///
/// The type parameter `C` sets the type of the counter in the internal table and can be used to
/// reduce memory consumption when low counts are expected.
#[derive(Clone)]
pub struct CountMinSketch<C = usize>
where
    C: Counter,
{
    table: Vec<C>,
    w: usize,
    d: usize,
}

impl<C> CountMinSketch<C>
where
    C: Counter,
{
    /// Create new CountMinSketch based on table size.
    ///
    /// - `w` sets the number of columns
    /// - `d` sets the number of rows
    pub fn with_params(w: usize, d: usize) -> CountMinSketch<C> {
        let table = vec![C::zero(); w.checked_mul(d).unwrap()];
        CountMinSketch {
            table: table,
            w: w,
            d: d,
        }
    }

    /// Get number of columns of internal counter table.
    pub fn w(&self) -> usize {
        self.w
    }

    /// Get number of rows of internal counter table.
    pub fn d(&self) -> usize {
        self.d
    }

    /// Check whether the CountMinSketch is empty (i.e. no elements seen yet).
    pub fn is_empty(&self) -> bool {
        self.table.iter().all(|x| x.is_zero())
    }

    /// Add one to the counter of the given element.
    pub fn add<T>(&mut self, obj: &T)
    where
        T: Hash,
    {
        self.add_n(&obj, C::one())
    }

    /// Add `n` to the counter of the given element.
    pub fn add_n<T>(&mut self, obj: &T, n: C)
    where
        T: Hash,
    {
        let bh = BuildHasherDefault::<DefaultHasher>::default();
        for (i, pos) in HashIter::new(self.w, self.d, obj, bh).enumerate() {
            let x = i * self.w + pos;
            self.table[x] = self.table[x].checked_add(n).unwrap();
        }
    }

    /// Runs a point query, i.e. a query for the count of a single object.
    pub fn query_point<T>(&self, obj: &T) -> C
    where
        T: Hash,
    {
        let bh = BuildHasherDefault::<DefaultHasher>::default();
        HashIter::new(self.w, self.d, obj, bh)
            .enumerate()
            .map(|(i, pos)| i * self.w + pos)
            .map(|x| self.table[x])
            .min()
            .unwrap()
    }

    /// Merge self with another CountMinSketch.
    ///
    /// After this operation `self` will be in the same state as when it would have seen all
    /// elements from `self` and `other`.
    ///
    /// Panics when `d` and `w` from `self` and `other` differ.
    pub fn merge(&mut self, other: &CountMinSketch<C>) {
        assert_eq!(self.d, other.d);
        assert_eq!(self.w, other.w);

        self.table = self.table
            .iter()
            .zip(other.table.iter())
            .map(|x| x.0.checked_add(*x.1).unwrap())
            .collect();
    }

    /// Clear internal counters to a fresh state (i.e. no objects seen).
    pub fn clear(&mut self) {
        self.table = vec![C::zero(); self.w.checked_mul(self.d).unwrap()];
    }
}

impl fmt::Debug for CountMinSketch {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "CountMinSketch {{ w: {}, d: {} }}", self.w, self.d)
    }
}

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

    #[test]
    fn getter() {
        let cms = CountMinSketch::<usize>::with_params(10, 20);
        assert_eq!(cms.w(), 10);
        assert_eq!(cms.d(), 20);
    }

    #[test]
    fn empty() {
        let cms = CountMinSketch::<usize>::with_params(10, 10);
        assert_eq!(cms.query_point(&1), 0);
        assert!(cms.is_empty());
    }

    #[test]
    fn add_1() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add(&1);
        assert_eq!(cms.query_point(&1), 1);
        assert_eq!(cms.query_point(&2), 0);
    }

    #[test]
    fn add_2() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add(&1);
        cms.add(&1);
        assert_eq!(cms.query_point(&1), 2);
        assert_eq!(cms.query_point(&2), 0);
    }

    #[test]
    fn add_2_1a() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add(&1);
        cms.add(&2);
        cms.add(&1);
        assert_eq!(cms.query_point(&1), 2);
        assert_eq!(cms.query_point(&2), 1);
        assert_eq!(cms.query_point(&3), 0);
    }

    #[test]
    fn add_2_1b() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add_n(&1, 2);
        cms.add(&2);
        assert_eq!(cms.query_point(&1), 2);
        assert_eq!(cms.query_point(&2), 1);
        assert_eq!(cms.query_point(&3), 0);
    }

    #[test]
    fn merge() {
        let mut cms1 = CountMinSketch::<usize>::with_params(10, 10);
        let mut cms2 = CountMinSketch::<usize>::with_params(10, 10);

        cms1.add_n(&1, 1);
        cms1.add_n(&2, 2);
        assert_eq!(cms1.query_point(&1), 1);
        assert_eq!(cms1.query_point(&2), 2);
        assert_eq!(cms1.query_point(&3), 0);
        assert_eq!(cms1.query_point(&4), 0);

        cms2.add_n(&2, 20);
        cms2.add_n(&3, 30);
        assert_eq!(cms2.query_point(&1), 0);
        assert_eq!(cms2.query_point(&2), 20);
        assert_eq!(cms2.query_point(&3), 30);
        assert_eq!(cms2.query_point(&4), 0);

        cms1.merge(&cms2);
        assert_eq!(cms1.query_point(&1), 1);
        assert_eq!(cms1.query_point(&2), 22);
        assert_eq!(cms1.query_point(&3), 30);
        assert_eq!(cms1.query_point(&4), 0);
    }

    #[test]
    fn clear() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add(&1);
        assert_eq!(cms.query_point(&1), 1);
        assert!(!cms.is_empty());

        cms.clear();
        assert_eq!(cms.query_point(&1), 0);
        assert!(cms.is_empty());
    }

    #[test]
    fn clone() {
        let mut cms1 = CountMinSketch::<usize>::with_params(10, 10);

        cms1.add(&1);
        assert_eq!(cms1.query_point(&1), 1);
        assert_eq!(cms1.query_point(&2), 0);

        let cms2 = cms1.clone();
        assert_eq!(cms2.query_point(&1), 1);
        assert_eq!(cms2.query_point(&2), 0);

        cms1.add(&1);
        assert_eq!(cms1.query_point(&1), 2);
        assert_eq!(cms1.query_point(&2), 0);
        assert_eq!(cms2.query_point(&1), 1);
        assert_eq!(cms2.query_point(&2), 0);
    }

    #[test]
    fn debug() {
        let cms = CountMinSketch::<usize>::with_params(10, 20);
        assert_eq!(format!("{:?}", cms), "CountMinSketch { w: 10, d: 20 }");
    }
}
<|endoftext|>


<commit_before>use std::collections::hash_map::DefaultHasher;
use std::hash::{BuildHasherDefault, Hash};

use utils::HashIter;

/// Abstract, but safe counter.
pub trait Counter: Copy + Ord + Sized {
    /// Add self to another counter.
    ///
    /// Returns `Some(Self)` when the addition was successfull (i.e. no overflow occured) and
    /// `None` in case of an error.
    fn checked_add(self, other: Self) -> Option<Self>;

    /// Return a counter representing zero.
    fn zero() -> Self;

    /// Return a counter representing one.
    fn one() -> Self;
}

macro_rules! impl_counter {
    ($t:ty) => {
        impl Counter for $t {
            #[inline]
            fn checked_add(self, other: Self) -> Option<Self> {
                self.checked_add(other)
            }

            #[inline]
            fn zero() -> Self {
                0
            }

            #[inline]
            fn one() -> Self {
                1
            }
        }
    }
}

impl_counter!(usize);
impl_counter!(u64);
impl_counter!(u32);
impl_counter!(u16);
impl_counter!(u8);

/// Simple implementation of a
/// [Count-min sketch](https://en.wikipedia.org/wiki/Count%E2%80%93min_sketch)
///
/// The type parameter `C` sets the type of the counter in the internal table and can be used to
/// reduce memory consumption when low counts are expected.
pub struct CountMinSketch<C = usize>
where
    C: Counter,
{
    table: Vec<C>,
    w: usize,
    d: usize,
}

impl<C> CountMinSketch<C>
where
    C: Counter,
{
    /// Create new CountMinSketch based on table size.
    ///
    /// - `w` sets the number of columns
    /// - `d` sets the number of rows
    pub fn with_params(w: usize, d: usize) -> CountMinSketch<C> {
        let table = vec![C::zero(); w.checked_mul(d).unwrap()];
        CountMinSketch {
            table: table,
            w: w,
            d: d,
        }
    }

    /// Get number of columns of internal counter table.
    pub fn w(&self) -> usize {
        self.w
    }

    /// Get number of rows of internal counter table.
    pub fn d(&self) -> usize {
        self.d
    }

    /// Add one to the counter of the given element.
    pub fn add<T>(&mut self, obj: &T)
    where
        T: Hash,
    {
        self.add_n(&obj, C::one())
    }

    /// Add `n` to the counter of the given element.
    pub fn add_n<T>(&mut self, obj: &T, n: C)
    where
        T: Hash,
    {
        let bh = BuildHasherDefault::<DefaultHasher>::default();
        for (i, pos) in HashIter::new(self.w, self.d, obj, bh).enumerate() {
            let x = i * self.w + pos;
            self.table[x] = self.table[x].checked_add(n).unwrap();
        }
    }

    /// Runs a point query, i.e. a query for the count of a single object.
    pub fn query_point<T>(&self, obj: &T) -> C
    where
        T: Hash,
    {
        let bh = BuildHasherDefault::<DefaultHasher>::default();
        HashIter::new(self.w, self.d, obj, bh)
            .enumerate()
            .map(|(i, pos)| i * self.w + pos)
            .map(|x| self.table[x])
            .min()
            .unwrap()
    }

    /// Clear internal counters to a fresh state (i.e. no objects seen).
    pub fn clear(&mut self) {
        self.table = vec![C::zero(); self.w.checked_mul(self.d).unwrap()];
    }
}

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

    #[test]
    fn getter() {
        let cms = CountMinSketch::<usize>::with_params(10, 20);
        assert_eq!(cms.w(), 10);
        assert_eq!(cms.d(), 20);
    }

    #[test]
    fn empty() {
        let cms = CountMinSketch::<usize>::with_params(10, 10);
        assert_eq!(cms.query_point(&1), 0);
    }

    #[test]
    fn add_1() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add(&1);
        assert_eq!(cms.query_point(&1), 1);
        assert_eq!(cms.query_point(&2), 0);
    }

    #[test]
    fn add_2() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add(&1);
        cms.add(&1);
        assert_eq!(cms.query_point(&1), 2);
        assert_eq!(cms.query_point(&2), 0);
    }

    #[test]
    fn add_2_1() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add(&1);
        cms.add(&2);
        cms.add(&1);
        assert_eq!(cms.query_point(&1), 2);
        assert_eq!(cms.query_point(&2), 1);
        assert_eq!(cms.query_point(&3), 0);
    }

    #[test]
    fn clear() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add(&1);
        assert_eq!(cms.query_point(&1), 1);

        cms.clear();
        assert_eq!(cms.query_point(&1), 0);
    }
}
<commit_msg>countminsketch: impl is_empty<commit_after>use std::collections::hash_map::DefaultHasher;
use std::hash::{BuildHasherDefault, Hash};

use utils::HashIter;

/// Abstract, but safe counter.
pub trait Counter: Copy + Ord + Sized {
    /// Add self to another counter.
    ///
    /// Returns `Some(Self)` when the addition was successfull (i.e. no overflow occured) and
    /// `None` in case of an error.
    fn checked_add(self, other: Self) -> Option<Self>;

    /// Return a counter representing zero.
    fn zero() -> Self;

    /// Return a counter representing one.
    fn one() -> Self;

    /// Checks whether the counter is zero.
    fn is_zero(&self) -> bool;
}

macro_rules! impl_counter {
    ($t:ty) => {
        impl Counter for $t {
            #[inline]
            fn checked_add(self, other: Self) -> Option<Self> {
                self.checked_add(other)
            }

            #[inline]
            fn zero() -> Self {
                0
            }

            #[inline]
            fn one() -> Self {
                1
            }

            #[inline]
            fn is_zero(&self) -> bool {
                *self == 0
            }
        }
    }
}

impl_counter!(usize);
impl_counter!(u64);
impl_counter!(u32);
impl_counter!(u16);
impl_counter!(u8);

/// Simple implementation of a
/// [Count-min sketch](https://en.wikipedia.org/wiki/Count%E2%80%93min_sketch)
///
/// The type parameter `C` sets the type of the counter in the internal table and can be used to
/// reduce memory consumption when low counts are expected.
pub struct CountMinSketch<C = usize>
where
    C: Counter,
{
    table: Vec<C>,
    w: usize,
    d: usize,
}

impl<C> CountMinSketch<C>
where
    C: Counter,
{
    /// Create new CountMinSketch based on table size.
    ///
    /// - `w` sets the number of columns
    /// - `d` sets the number of rows
    pub fn with_params(w: usize, d: usize) -> CountMinSketch<C> {
        let table = vec![C::zero(); w.checked_mul(d).unwrap()];
        CountMinSketch {
            table: table,
            w: w,
            d: d,
        }
    }

    /// Get number of columns of internal counter table.
    pub fn w(&self) -> usize {
        self.w
    }

    /// Get number of rows of internal counter table.
    pub fn d(&self) -> usize {
        self.d
    }

    /// Check whether the CountMinSketch is empty (i.e. no elements seen yet).
    pub fn is_empty(&self) -> bool {
        self.table.iter().all(|x| x.is_zero())
    }

    /// Add one to the counter of the given element.
    pub fn add<T>(&mut self, obj: &T)
    where
        T: Hash,
    {
        self.add_n(&obj, C::one())
    }

    /// Add `n` to the counter of the given element.
    pub fn add_n<T>(&mut self, obj: &T, n: C)
    where
        T: Hash,
    {
        let bh = BuildHasherDefault::<DefaultHasher>::default();
        for (i, pos) in HashIter::new(self.w, self.d, obj, bh).enumerate() {
            let x = i * self.w + pos;
            self.table[x] = self.table[x].checked_add(n).unwrap();
        }
    }

    /// Runs a point query, i.e. a query for the count of a single object.
    pub fn query_point<T>(&self, obj: &T) -> C
    where
        T: Hash,
    {
        let bh = BuildHasherDefault::<DefaultHasher>::default();
        HashIter::new(self.w, self.d, obj, bh)
            .enumerate()
            .map(|(i, pos)| i * self.w + pos)
            .map(|x| self.table[x])
            .min()
            .unwrap()
    }

    /// Clear internal counters to a fresh state (i.e. no objects seen).
    pub fn clear(&mut self) {
        self.table = vec![C::zero(); self.w.checked_mul(self.d).unwrap()];
    }
}

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

    #[test]
    fn getter() {
        let cms = CountMinSketch::<usize>::with_params(10, 20);
        assert_eq!(cms.w(), 10);
        assert_eq!(cms.d(), 20);
    }

    #[test]
    fn empty() {
        let cms = CountMinSketch::<usize>::with_params(10, 10);
        assert_eq!(cms.query_point(&1), 0);
        assert!(cms.is_empty());
    }

    #[test]
    fn add_1() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add(&1);
        assert_eq!(cms.query_point(&1), 1);
        assert_eq!(cms.query_point(&2), 0);
    }

    #[test]
    fn add_2() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add(&1);
        cms.add(&1);
        assert_eq!(cms.query_point(&1), 2);
        assert_eq!(cms.query_point(&2), 0);
    }

    #[test]
    fn add_2_1() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add(&1);
        cms.add(&2);
        cms.add(&1);
        assert_eq!(cms.query_point(&1), 2);
        assert_eq!(cms.query_point(&2), 1);
        assert_eq!(cms.query_point(&3), 0);
    }

    #[test]
    fn clear() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add(&1);
        assert_eq!(cms.query_point(&1), 1);
        assert!(!cms.is_empty());

        cms.clear();
        assert_eq!(cms.query_point(&1), 0);
        assert!(cms.is_empty());
    }
}
<|endoftext|>


<commit_before>use hubcaps::{
    self,
    gists::{self, Content, GistOptions},
    Credentials, Github,
};
use hyper;
use hyper_tls;
use std::collections::HashMap;
use tokio1::{prelude::Future, runtime::current_thread::Runtime};

const FILENAME: &str = "playground.rs";
const DESCRIPTION: &str = "Code shared from the Rust Playground";

pub struct Gist {
    pub id: String,
    pub url: String,
    pub code: String,
}

impl From<gists::Gist> for Gist {
    fn from(other: gists::Gist) -> Self {
        let mut files: Vec<_> = other.files
            .into_iter()
            .map(|(name, file)| (name, file.content.unwrap_or_default()))
            .collect();

        files.sort_by(|(name1, _), (name2, _)| name1.cmp(name2));

        let code = match files.len() {
            0 | 1 => files.into_iter().map(|(_, content)| content).collect(),
            _ => {
                files
                    .into_iter()
                    .map(|(name, content)| format!("// {}\n{}\n\n", name, content))
                    .collect()
            }
        };

        Gist {
            id: other.id,
            url: other.html_url,
            code: code,
        }
    }
}

pub fn create(token: String, code: String) -> Gist {
    Runtime::new()
        .expect("unable to create runtime")
        .block_on(create_future(token, code))
        .expect("Unable to create gist")
    // TODO: Better reporting of failures
}

pub fn create_future(token: String, code: String) -> impl Future<Item = Gist, Error = hubcaps::Error> {
    let github = github(token);

    let file = Content {
        filename: None,
        content: code,
    };

    let mut files = HashMap::new();
    files.insert(FILENAME.into(), file);

    let options = GistOptions {
        description: Some(DESCRIPTION.into()),
        public: Some(true),
        files,
    };

    github
        .gists()
        .create(&options)
        .map(Into::into)
}

pub fn load(token: String, id: &str) -> Gist {
    Runtime::new()
        .expect("unable to create runtime")
        .block_on(load_future(token, id))
        .expect("Unable to load gist")
    // TODO: Better reporting of a 404
}

pub fn load_future(token: String, id: &str) -> impl Future<Item = Gist, Error = ::hubcaps::Error> {
    let github = github(token);

    github
        .gists()
        .get(id)
        .map(Into::into)
}

type HubcapConnector = hyper_tls::HttpsConnector<hyper::client::HttpConnector>;

fn github(token: String) -> Github<HubcapConnector> {
    Github::new(
        String::from("The Rust Playground"),
        Some(Credentials::Token(token)),
    )
}
<commit_msg>Change GitHub Gist creation to be private<commit_after>use hubcaps::{
    self,
    gists::{self, Content, GistOptions},
    Credentials, Github,
};
use hyper;
use hyper_tls;
use std::collections::HashMap;
use tokio1::{prelude::Future, runtime::current_thread::Runtime};

const FILENAME: &str = "playground.rs";
const DESCRIPTION: &str = "Code shared from the Rust Playground";

pub struct Gist {
    pub id: String,
    pub url: String,
    pub code: String,
}

impl From<gists::Gist> for Gist {
    fn from(other: gists::Gist) -> Self {
        let mut files: Vec<_> = other.files
            .into_iter()
            .map(|(name, file)| (name, file.content.unwrap_or_default()))
            .collect();

        files.sort_by(|(name1, _), (name2, _)| name1.cmp(name2));

        let code = match files.len() {
            0 | 1 => files.into_iter().map(|(_, content)| content).collect(),
            _ => {
                files
                    .into_iter()
                    .map(|(name, content)| format!("// {}\n{}\n\n", name, content))
                    .collect()
            }
        };

        Gist {
            id: other.id,
            url: other.html_url,
            code: code,
        }
    }
}

pub fn create(token: String, code: String) -> Gist {
    Runtime::new()
        .expect("unable to create runtime")
        .block_on(create_future(token, code))
        .expect("Unable to create gist")
    // TODO: Better reporting of failures
}

pub fn create_future(token: String, code: String) -> impl Future<Item = Gist, Error = hubcaps::Error> {
    let github = github(token);

    let file = Content {
        filename: None,
        content: code,
    };

    let mut files = HashMap::new();
    files.insert(FILENAME.into(), file);

    let options = GistOptions {
        description: Some(DESCRIPTION.into()),
        public: Some(false),
        files,
    };

    github
        .gists()
        .create(&options)
        .map(Into::into)
}

pub fn load(token: String, id: &str) -> Gist {
    Runtime::new()
        .expect("unable to create runtime")
        .block_on(load_future(token, id))
        .expect("Unable to load gist")
    // TODO: Better reporting of a 404
}

pub fn load_future(token: String, id: &str) -> impl Future<Item = Gist, Error = ::hubcaps::Error> {
    let github = github(token);

    github
        .gists()
        .get(id)
        .map(Into::into)
}

type HubcapConnector = hyper_tls::HttpsConnector<hyper::client::HttpConnector>;

fn github(token: String) -> Github<HubcapConnector> {
    Github::new(
        String::from("The Rust Playground"),
        Some(Credentials::Token(token)),
    )
}
<|endoftext|>


<commit_before>extern crate futures_await as futures;
#[macro_use]
extern crate reql;
extern crate reql_types;
extern crate tokio;

use futures::stream::Stream;
use reql::{Client, Document, Run};
use reql_types::ServerStatus;

fn main() {
    // Create a new ReQL client
    let r = Client::new();

    // Create a connection pool
    let conn = r.connect(args!()).unwrap();

    // Run the query
    let stati = r.db("rethinkdb")
        .table("server_status")
        .run::<ServerStatus>(conn)
        .unwrap();

    // Process the results
    for res in stati.wait() {
        match res {
            // The server returned the response we were expecting
            Ok(Some(Document::Expected(status))) => {
                println!("{:?}", status);
            }
            // We got a response alright, but it wasn't the one we were
            // expecting plus it's not an error either, otherwise it would
            // have been returned as such (This simply means that the response
            // we got couldn't be serialised into the type we were expecting)
            Ok(Some(Document::Unexpected(status))) => {
                println!("unexpected response from server: {:?}", status);
            }
            // This is impossible in this particular example since there
            // needs to be at least one server available to give this
            // response otherwise we would have run into an error for
            // failing to connect
            Ok(None) => {
                println!("got no documents in the database");
            }
            // Our query ran into an error
            Err(error) => {
                println!("{:?}", error);
            }
        }
    }
}
<commit_msg>Update blocking example<commit_after>extern crate futures_await as futures;
#[macro_use]
extern crate reql;
extern crate reql_types;

use reql::{Client, Document, Run};
use reql_types::ServerStatus;
use futures::executor::block_on;
use futures::StreamExt;

fn main() {
    // Create a new ReQL client
    let r = Client::new();

    // Create a connection pool
    let conn = r.connect(args!()).unwrap();

    // Run the query
    let stati = r.db("rethinkdb")
        .table("server_status")
        .run::<ServerStatus>(conn)
        .unwrap();

    // Process the results
    match block_on(stati.into_future()).unwrap().0.unwrap() {
        // The server returned the response we were expecting
        Some(Document::Expected(status)) => {
            println!("{:?}", status);
        }
        // We got a response alright, but it wasn't the one we were
        // expecting plus it's not an error either, otherwise it would
        // have been returned as such (This simply means that the response
        // we got couldn't be serialised into the type we were expecting)
        Some(Document::Unexpected(status)) => {
            println!("unexpected response from server: {:?}", status);
        }
        // This is impossible in this particular example since there
        // needs to be at least one server available to give this
        // response otherwise we would have run into an error for
        // failing to connect
        None => {
            println!("got no documents in the database");
        }
    }
}
<|endoftext|>


<commit_before>extern crate timely;

use std::collections::HashMap;

use timely::dataflow::operators::{ToStream, Inspect};
use timely::dataflow::operators::generic::operator::Operator;
use timely::dataflow::channels::pact::Pipeline;

fn main() {
    timely::example(|scope| {
        let mut counts_by_time = HashMap::new();
        vec![0, 1, 2, 2, 2, 3, 3, 4]
            .into_iter()
            .to_stream(scope)
            .unary(Pipeline, "Distinct", move |_,_| move |input, output| {
                input.for_each(|time, data| {
                    let counts = counts_by_time.entry(time.time().clone())
                                               .or_insert(HashMap::new());
                    let mut session = output.session(&time);
                    for &datum in data.iter() {
                        let count = counts.entry(datum)
                                          .or_insert(0);
                        if *count == 0 {
                           session.give(datum);
                        }
                        *count += 1;
                    }
                })
            })
            .inspect(|x| println!("hello: {:?}", x));
    });
}
<commit_msg>Improve the distinct example<commit_after>extern crate timely;

use std::collections::HashMap;

use timely::dataflow::InputHandle;
use timely::dataflow::operators::{Input, Inspect, Probe};
use timely::dataflow::operators::generic::operator::Operator;
use timely::dataflow::channels::pact::Exchange;

fn main() {
    // initializes and runs a timely dataflow.
    timely::execute_from_args(std::env::args(), |worker| {
        let index = worker.index();
        let mut input = InputHandle::new();

        // create a new input, exchange data, and inspect its output
        let probe = worker.dataflow(|scope| {
            let mut counts_by_time = HashMap::new();
            scope.input_from(&mut input)
                .unary(Exchange::new(|x| *x), "Distinct", move |_, _|
                    move |input, output| {
                        input.for_each(|time, data| {
                            let counts = counts_by_time.entry(time.time().clone())
                                .or_insert(HashMap::new());
                            let mut session = output.session(&time);
                            for &datum in data.iter() {
                                let count = counts.entry(datum).or_insert(0);
                                if *count == 0 {
                                    session.give(datum);
                                }
                                *count += 1;
                            }
                        })
                    })
                .inspect(move |x| println!("worker {}:\tvalue {}", index, x))
                .probe()
        });

        // introduce data and watch!
        for round in 0..1 {
            if index == 0 {
                vec![0, 1, 2, 2, 2, 3, 3, 4].iter().for_each(|x| input.send(*x));
            } else if index == 1 {
                vec![0, 0, 3, 4, 4, 5, 7, 7].iter().for_each(|x| input.send(*x));
            }
            input.advance_to(round + 1);
            while probe.less_than(input.time()) {
                worker.step();
            }
        }
    }).unwrap();
}
<|endoftext|>


<commit_before>#[macro_use] extern crate assert_cli;

mod utils;
use utils::{clone_out_test, execute_command, get_toml};

// https://github.com/killercup/cargo-edit/issues/32
#[test]
fn issue_32() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/rm/Cargo.toml");

    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.foo").is_none());

    execute_command(&["add", "foo@1.0"], &manifest);
    execute_command(&["add", "bar@1.0.7"], &manifest);

    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.foo").is_some());
    assert!(toml.lookup("dependencies.bar").is_some());

    execute_command(&["rm", "foo"], &manifest);
    execute_command(&["rm", "bar"], &manifest);

    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.foo").is_none());
    assert!(toml.lookup("dependencies.bar").is_none());
}

#[test]
fn no_argument() {
    assert_cli!("target/debug/cargo-rm", &["rm"] => Error 1,
                r"Invalid arguments.

Usage:
    cargo rm <crate> [--dev|--build] [options]
    cargo rm (-h|--help)
    cargo rm --version")
        .unwrap();
}

#[test]
fn unknown_flags() {
    assert_cli!("target/debug/cargo-rm", &["rm", "foo", "--flag"] => Error 1,
                r"Unknown flag: '--flag'

Usage:
    cargo rm <crate> [--dev|--build] [options]
    cargo rm (-h|--help)
    cargo rm --version")
        .unwrap();
}
<commit_msg>Add Tests for Nice `cargo rm` Errors<commit_after>#[macro_use]
extern crate assert_cli;

mod utils;
use utils::{clone_out_test, execute_command, get_toml};

// https://github.com/killercup/cargo-edit/issues/32
#[test]
fn issue_32() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/rm/Cargo.toml");

    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.foo").is_none());

    execute_command(&["add", "foo@1.0"], &manifest);
    execute_command(&["add", "bar@1.0.7"], &manifest);

    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.foo").is_some());
    assert!(toml.lookup("dependencies.bar").is_some());

    execute_command(&["rm", "foo"], &manifest);
    execute_command(&["rm", "bar"], &manifest);

    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.foo").is_none());
    assert!(toml.lookup("dependencies.bar").is_none());
}

#[test]
fn invalid_dependency() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/rm/Cargo.toml");

    assert_cli!("target/debug/cargo-rm",
                &["rm", "invalid_dependency_name", &format!("--manifest-path={}", manifest)]
                => Error 1, "Could not edit `Cargo.toml`.

ERROR: The dependency `invalid_dependency_name` could not be found in `dependencies`.")
        .unwrap();
}

#[test]
fn invalid_section() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/rm/Cargo.toml");

    assert_cli!("target/debug/cargo-rm",
                &["rm", "semver", "--build", &format!("--manifest-path={}", manifest)]
                => Error 1, "Could not edit `Cargo.toml`.

ERROR: The table `build-dependencies` could not be found.")
        .unwrap();
}

#[test]
fn invalid_dependency_in_section() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/rm/Cargo.toml");

    assert_cli!("target/debug/cargo-rm",
                &["rm", "semver", "--dev", &format!("--manifest-path={}", manifest)]
                => Error 1, "Could not edit `Cargo.toml`.

ERROR: The dependency `semver` could not be found in `dev-dependencies`.")
        .unwrap();
}

#[test]
fn no_argument() {
    assert_cli!("target/debug/cargo-rm", &["rm"] => Error 1,
                r"Invalid arguments.

Usage:
    cargo rm <crate> [--dev|--build] [options]
    cargo rm (-h|--help)
    cargo rm --version")
        .unwrap();
}

#[test]
fn unknown_flags() {
    assert_cli!("target/debug/cargo-rm", &["rm", "foo", "--flag"] => Error 1,
                r"Unknown flag: '--flag'

Usage:
    cargo rm <crate> [--dev|--build] [options]
    cargo rm (-h|--help)
    cargo rm --version")
        .unwrap();
}
<|endoftext|>


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

use self::Node::*;

/// A `Node` in the `Rope`'s tree.
///
/// A `Node` is either a `Leaf` holding a `String`, or a
/// a `Branch` concatenating together two `Node`s.
#[derive(Debug, Clone)]
pub enum Node {
    /// A leaf node
    Leaf(String)
  , /// A branch concatenating together `l`eft and `r`ight nodes.
    Branch(BranchNode)
}

#[derive(Debug, Clone)]
pub struct BranchNode {
    /// The length of this node
    len: usize
  , /// The weight of a node is the summed weight of its left subtree
    weight: usize
  , /// The left branch node
    pub left: Option<Box<Node>>
  , /// The right branch node
    pub right: Option<Box<Node>>
}

impl Default for Node {
    fn default() -> Self { Node::empty() }

}

/// Returns the _n_th fibonacci number.
// TODO: replace with an iterative implementation and/or lookup table?
fn fibonacci(n: usize) -> usize {
    match n { 0 => 1
            , 1 => 1
            , _ => fibonacci(n - 1) + fibonacci(n - 2)
            }
}

impl BranchNode {

    #[inline]
    fn new(left: Box<Node>, right: Box<Node>) -> Self {
        BranchNode { len: left.len() + right.len()
                   , weight: left.subtree_weight()
                   , left: Some(left)
                   , right: Some(right)
                   }
    }

    #[inline]
    fn take_right(&mut self) -> Box<Node> {
        mem::replace(&mut self.right, None).unwrap_or(box Node::empty())
    }

    #[inline]
    fn take_left(&mut self) -> Box<Node> {
        self.left.take().unwrap_or(box Node::empty())
    }

    #[inline]
    fn update_weight(&mut self) {
        self.weight = self.left.as_ref()
                          .map(Box::as_ref)
                          .map_or(0, Node::subtree_weight);
    }

    fn split(&mut self, index: usize) -> &mut Node {
        if index < self.weight {
            // split the left node
            *self = if let BranchNode {
                left: Some(box ref mut left)
              , ref mut right, ..
            } = *self {
                let mut l_leaf = mem::replace(left, Node::empty());
                l_leaf.split(index);
                let r = right.take().unwrap_or(box Node::empty());
                // replacing *self with a new BranchNode will update the
                // node's weight automagically
                BranchNode::new(box l_leaf, r)
            } else {
                unreachable!()
            };
            self.left.as_mut().unwrap()
        } else {
            // split the right node
            *self = if let BranchNode {
                ref mut left
              , right: Some(box ref mut right), ..
            } = *self {
                let mut r_leaf = mem::replace(right, Node::empty());
                r_leaf.split(index);
                let l = left.take().unwrap_or(box Node::empty());
                // replacing *self with a new BranchNode will update the
                // node's weight automagically
                BranchNode::new(l, box r_leaf)
            } else {
                // i think this should never happen
                unreachable!()
            };
            self.right.as_mut().unwrap()
        }
    }

//         }
// else if let
//
//         // let mut result: &mut Node;
//         let result = if index < self.weight {
//             if let Some(box ref mut left @ Leaf(_)) = self.left {
//                 left.split(index);
//                 left
//             } else {
//                 panic!()
//             }
//         } else if let Some(box ref mut right) = self.right {
//             right.split(index - self.weight)
//         } else {
//             panic!()
//         };
//         self.update_weight();
//         return result
    // }
}

impl Node {
    fn split_leaf(&mut self, index: usize) -> bool {
        // we mutably borrow `self` here. This precludes us from changing it
        // directly as in `*self = ...`, because the borrow checker won't allow
        // it. Therefore, the assignment to `self` must be outside the `if let`
        // clause.
        *self = if let Leaf(ref mut s) = *self {

            // if this node is a Leaf, take the String out of it
            // (note that empty strings don't allocate).
            let string = mem::replace(s, String::new());
            // split the string into left and right parts...
            let left = Leaf(string[index..].to_string());
            let right = Leaf(string[..index].to_string());
            // construct the new Branch node that will be reassigned to `self`
            Node::new_branch(left, right)
        } else {
            // if this node is not a Leaf, we return immediately, thus skipping
            // the assignment
            return false
        };
        return true
    }

    pub fn split(&mut self, index: usize) -> &mut Node {
        if self.split_leaf(index) == true {
            self
        } else {
            if let &mut Branch(ref mut node) = self {
                node.split(index)
            } else {
                unreachable!()
            }
        }
    }

    pub const fn empty() -> Self {
        Branch(BranchNode { len: 0
                          , weight: 0
                          , left: None
                          , right: None
                          })
    }

    /// Concatenate two `Node`s to return a new `Branch` node.
    #[inline]
    pub fn new_branch(left: Self, right: Self) -> Self {
        Branch(BranchNode::new(box left, box right))
    }

    #[inline]
    pub fn concat(&mut self, right: Self) {
        *self = Node::new_branch(mem::replace(self, Node::empty()), right)
    }

    #[inline]
    pub const fn new_leaf(string: String) -> Self {
        Leaf(string)
    }

    /// Returns true if this node is balanced
    ///
    /// "We define the depth of a leaf to be 0, and the depth of a
    /// concatenation to be one plus the maximum depth of its children. Let
    /// _Fn_ be the _n_th Fibonacci number. A rope of depth _n_ is balanced if
    /// its length is at least _Fn_+2, e.g. a balanced rope of depth 1 must
    /// have length at least 2. Note that balanced ropes may contain unbalanced
    /// subropes."
    /// – from "Ropes: An Alternative to Strings"
    #[inline]
    pub fn is_balanced(&self) -> bool {
        self.len() >= fibonacci(self.depth() + 2)
    }

    /// Returns the depth in the tree of a node
    #[inline]
    fn depth(&self) -> usize {
        use std::cmp::max;

        match self {
            &Node::Leaf(_) => 0
          , &Node::Branch(BranchNode { ref left, ref right, .. }) =>
                max( left.as_ref().map(Box::as_ref).map_or(0, Node::depth)
                   , right.as_ref().map(Box::as_ref).map_or(0, Node::depth)
                   ) + 1
            }
    }

    /// Returns the length of a node
    //  TODO: do we want to cache this?
    pub fn len(&self) -> usize {
        match self { &Leaf(ref s) => s.len()
                   , &Branch(BranchNode { ref left, ref right, .. }) =>
                        left.as_ref().map(Box::as_ref).map_or(0, Node::len) +
                        right.as_ref().map(Box::as_ref).map_or(0, Node::len)
                    }
    }

    /// Calculates the weight of a node
    #[inline]
    fn subtree_weight (&self) -> usize {
        match self { &Leaf(ref s) => s.len()
                   , &Branch(BranchNode { ref left, .. }) =>
                        left.as_ref().map(Box::as_ref)
                            .map_or(0, Node::subtree_weight)
                    }
    }

    /// Rebalance the subrope starting at this `Node`, returning a new `Node`
    ///
    /// From "Ropes: An Alternative to Strings":
    /// > "The rebalancing operation maintains an ordered sequence of (empty
    /// > or) balanced ropes, one for each length interval [_Fn_, _Fn_+1), for
    /// > _n_ >= 2. We traverse the rope from left to right, inserting each
    /// > leaf into the appropriate sequence position, depending on its length.
    ///
    /// > The concatenation of the sequence of ropes in order of decreasing
    /// > length is equivalent to the prefix of the rope we have traversed so
    /// > far. Each new leaf _x_ is with_insert_ropeed into the appropriate entry of the
    /// > sequence. Assume that _x_’s length is in the interval [_Fn_, _Fn_+1),
    /// > and thus it should be put in slot _n_ (which also corresponds to
    /// > maximum depth _n_ − 2). If all lower and equal numbered levels are
    /// > empty, then this can be done directly. If not, then we concatenate
    /// > ropes in slots 2, ... ,(_n_ − 1) (concatenating onto the left), and
    /// > concatenate _x_ to the right of the result. We then continue to
    /// > concatenate ropes from the sequence in increasing order to the left
    /// > of this result, until the result fits into an empty slot in the
    /// > sequence."
    pub fn rebalance(self) -> Self {
        // TODO: this is a huge mess, I based it on the IBM Java implementation
        //       please refactor until it stops being ugly!
        //        - eliza, 12/17/2016

        if self.is_balanced() {
            // the subrope is already balanced, do nothing
            self
        } else {
            let mut leaves: Vec<Option<Node>> =
                self.into_leaves().map(Option::Some).collect();
            let len = leaves.len();
            fn _rebalance(l: &mut Vec<Option<Node>>, start: usize, end: usize)
                          -> Node {
                match end - start {
                    1 => l[start].take().unwrap()
                  , 2 => l[start].take().unwrap() + l[start + 1].take().unwrap()
                  , n => {
                        let mid = start + (n / 2);
                        _rebalance(l, start, mid) + _rebalance(l, mid, end)

                    }
                }
            };
            _rebalance(&mut leaves, 0, len)
        }
    }

    /// Returns an iterator over all leaf nodes in this `Node`'s subrope
    fn leaves<'a>(&'a self) -> Leaves<'a> {
        Leaves(vec![self])
    }

    /// Returns a move iterator over all leaf nodes in this `Node`'s subrope
    fn into_leaves(self) -> IntoLeaves {
        IntoLeaves(vec![self])
    }

    /// Returns an iterator over all the strings in this `Node`s subrope'
    #[inline]
    pub fn strings<'a>(&'a self) -> impl Iterator<Item=&'a str> {
        box self.leaves().map(|n| match n {
            &Leaf(ref s) => s.as_ref()
          , _ => unreachable!("Node.leaves() iterator contained something \
                               that wasn't a leaf. Barring _force majeure_, \
                               this should be impossible. Something's broken.")
        })
    }

    /// Returns a move iterator over all the strings in this `Node`s subrope'
    ///
    /// Consumes `self`.
    #[inline]
    pub fn into_strings(self) -> impl Iterator<Item=String> {
        box self.into_leaves().map(|n| match n {
            Leaf(s) => s
            , _ => unreachable!("Node.into_leaves() iterator contained \
                                 something  that wasn't a leaf. Barring _force \
                                 majeure_, this should be impossible. \
                                 Something's broken.")
        })
    }

    str_iters! {
        #[doc="Returns an iterator over all the bytes in this `Node`'s \
               subrope \n\

               \nAs a Rope consists of a sequence of bytes, we can iterate \
               through a rope by byte. This method returns such an iterator."]
        #[inline]
        impl bytes<u8> for Node {}
        #[doc="Returns an iterator over all the characters in this `Node`'s \
               subrope \n\

               \nAs a `Rope` consists of valid UTF-8, we can iterate through a \
               `Rope` by `char`. This method returns such an iterator. \n\

               \nIt's important to remember that `char` represents a Unicode \
               Scalar Value, and may not match your idea of what a \
               'character' is. Iteration over grapheme clusters may be what \
               you actually want."]
        #[inline]
        impl chars<char> for Node {}
        // TODO: this is actually Wrong, the indices will wrap around once we
        //       iterate into the next leaf node. we'll need to write our own
        //       char_indices iterator that tracks the character's index in the
        //       global Rope. shouldn't be too hard, just a fold...
        //          - eliza, 12/18/2016
        // #[inline]
        // impl char_indices<(usize, char)> for Node {}
        #[inline]
        impl split_whitespace<&'a str> for Node {}
        #[inline]
        impl lines<&'a str> for Node {}
    }

    // /// Returns n iterator over the bytes of this `Node`'s subrope
    // ///
    // ///
    // #[inline]
    // pub fn bytes<'a>(&'a self) -> impl Iterator<Item=u8> + 'a {
    //     self.strings().flat_map(str::bytes)
    // }

    /// Returns an iterator over the grapheme clusters of this `Node`'s subrope'
    ///
    /// This is the iterator returned by `Node::into_iter`.
    #[inline]
    pub fn graphemes<'a>(&'a self) -> impl Iterator<Item=&'a str> {
        // the compiler won't let me mark this as unimplemented using the
        // unimplemented!() macro, due to Reasons (i suspect relating to
        // returning `impl Trait`)
        //  - eliza, 12/18/2016
        panic!("Unimplemented!");
        self.strings()
    }

}

/// An iterator over a series of leaf `Node`s
struct Leaves<'a>(Vec<&'a Node>);

impl<'a> Iterator for Leaves<'a> {
    type Item = &'a Node;
    fn next(&mut self) -> Option<Self::Item> {
        match self.0.pop() {
            None => None
          , Some(leaf @ &Leaf(_)) => Some(leaf)
          , Some(&Branch(BranchNode { ref left, ref right, .. })) => {
                if let &Some(box ref r) = right { self.0.push(r); }
                if let &Some(box ref l) = left { self.0.push(l); }
                self.next()
            }
        }
    }
}

/// A move iterator over a series of leaf `Node`s
struct IntoLeaves(Vec<Node>);

impl Iterator for IntoLeaves {
    type Item = Node;
    fn next(&mut self) -> Option<Self::Item> {
        match self.0.pop() {
            None => None
          , Some(leaf @ Leaf(_)) => Some(leaf)
          , Some(Branch(BranchNode { left, right, .. })) => {
                if let Some(box r) = right { self.0.push(r); }
                if let Some(box l) = left { self.0.push(l); }
                self.next()
            }
        }
    }
}

impl ops::Add for Node {
    type Output = Self;
    /// Concatenate two `Node`s, returning a `Branch` node.
    fn add(self, right: Self) -> Self { Node::new_branch(self, right) }
}
<commit_msg>rope: remove dead code from BranchNode<commit_after>use std::ops;
use std::mem;

use self::Node::*;

/// A `Node` in the `Rope`'s tree.
///
/// A `Node` is either a `Leaf` holding a `String`, or a
/// a `Branch` concatenating together two `Node`s.
#[derive(Debug, Clone)]
pub enum Node {
    /// A leaf node
    Leaf(String)
  , /// A branch concatenating together `l`eft and `r`ight nodes.
    Branch(BranchNode)
}

#[derive(Debug, Clone)]
pub struct BranchNode {
    /// The length of this node
    len: usize
  , /// The weight of a node is the summed weight of its left subtree
    weight: usize
  , /// The left branch node
    pub left: Option<Box<Node>>
  , /// The right branch node
    pub right: Option<Box<Node>>
}

impl Default for Node {
    fn default() -> Self { Node::empty() }

}

/// Returns the _n_th fibonacci number.
// TODO: replace with an iterative implementation and/or lookup table?
fn fibonacci(n: usize) -> usize {
    match n { 0 => 1
            , 1 => 1
            , _ => fibonacci(n - 1) + fibonacci(n - 2)
            }
}

impl BranchNode {

    #[inline]
    fn new(left: Box<Node>, right: Box<Node>) -> Self {
        BranchNode { len: left.len() + right.len()
                   , weight: left.subtree_weight()
                   , left: Some(left)
                   , right: Some(right)
                   }
    }

    fn split(&mut self, index: usize) -> &mut Node {
        if index < self.weight {
            // split the left node
            *self = if let BranchNode {
                left: Some(box ref mut left)
              , ref mut right, ..
            } = *self {
                let mut l_leaf = mem::replace(left, Node::empty());
                l_leaf.split(index);
                let r = right.take().unwrap_or(box Node::empty());
                // replacing *self with a new BranchNode will update the
                // node's weight automagically
                BranchNode::new(box l_leaf, r)
            } else {
                unreachable!()
            };
            self.left.as_mut().unwrap()
        } else {
            // split the right node
            *self = if let BranchNode {
                ref mut left
              , right: Some(box ref mut right), ..
            } = *self {
                let mut r_leaf = mem::replace(right, Node::empty());
                r_leaf.split(index);
                let l = left.take().unwrap_or(box Node::empty());
                // replacing *self with a new BranchNode will update the
                // node's weight automagically
                BranchNode::new(l, box r_leaf)
            } else {
                // i think this should never happen
                unreachable!()
            };
            self.right.as_mut().unwrap()
        }
    }

}

impl Node {
    fn split_leaf(&mut self, index: usize) -> bool {
        // we mutably borrow `self` here. This precludes us from changing it
        // directly as in `*self = ...`, because the borrow checker won't allow
        // it. Therefore, the assignment to `self` must be outside the `if let`
        // clause.
        *self = if let Leaf(ref mut s) = *self {

            // if this node is a Leaf, take the String out of it
            // (note that empty strings don't allocate).
            let string = mem::replace(s, String::new());
            // split the string into left and right parts...
            let left = Leaf(string[index..].to_string());
            let right = Leaf(string[..index].to_string());
            // construct the new Branch node that will be reassigned to `self`
            Node::new_branch(left, right)
        } else {
            // if this node is not a Leaf, we return immediately, thus skipping
            // the assignment
            return false
        };
        return true
    }

    pub fn split(&mut self, index: usize) -> &mut Node {
        if self.split_leaf(index) == true {
            self
        } else {
            if let &mut Branch(ref mut node) = self {
                node.split(index)
            } else {
                unreachable!()
            }
        }
    }

    pub const fn empty() -> Self {
        Branch(BranchNode { len: 0
                          , weight: 0
                          , left: None
                          , right: None
                          })
    }

    /// Concatenate two `Node`s to return a new `Branch` node.
    #[inline]
    pub fn new_branch(left: Self, right: Self) -> Self {
        Branch(BranchNode::new(box left, box right))
    }

    #[inline]
    pub fn concat(&mut self, right: Self) {
        *self = Node::new_branch(mem::replace(self, Node::empty()), right)
    }

    #[inline]
    pub const fn new_leaf(string: String) -> Self {
        Leaf(string)
    }

    /// Returns true if this node is balanced
    ///
    /// "We define the depth of a leaf to be 0, and the depth of a
    /// concatenation to be one plus the maximum depth of its children. Let
    /// _Fn_ be the _n_th Fibonacci number. A rope of depth _n_ is balanced if
    /// its length is at least _Fn_+2, e.g. a balanced rope of depth 1 must
    /// have length at least 2. Note that balanced ropes may contain unbalanced
    /// subropes."
    /// – from "Ropes: An Alternative to Strings"
    #[inline]
    pub fn is_balanced(&self) -> bool {
        self.len() >= fibonacci(self.depth() + 2)
    }

    /// Returns the depth in the tree of a node
    #[inline]
    fn depth(&self) -> usize {
        use std::cmp::max;

        match self {
            &Node::Leaf(_) => 0
          , &Node::Branch(BranchNode { ref left, ref right, .. }) =>
                max( left.as_ref().map(Box::as_ref).map_or(0, Node::depth)
                   , right.as_ref().map(Box::as_ref).map_or(0, Node::depth)
                   ) + 1
            }
    }

    /// Returns the length of a node
    //  TODO: do we want to cache this?
    pub fn len(&self) -> usize {
        match self { &Leaf(ref s) => s.len()
                   , &Branch(BranchNode { ref left, ref right, .. }) =>
                        left.as_ref().map(Box::as_ref).map_or(0, Node::len) +
                        right.as_ref().map(Box::as_ref).map_or(0, Node::len)
                    }
    }

    /// Calculates the weight of a node
    #[inline]
    fn subtree_weight (&self) -> usize {
        match self { &Leaf(ref s) => s.len()
                   , &Branch(BranchNode { ref left, .. }) =>
                        left.as_ref().map(Box::as_ref)
                            .map_or(0, Node::subtree_weight)
                    }
    }

    /// Rebalance the subrope starting at this `Node`, returning a new `Node`
    ///
    /// From "Ropes: An Alternative to Strings":
    /// > "The rebalancing operation maintains an ordered sequence of (empty
    /// > or) balanced ropes, one for each length interval [_Fn_, _Fn_+1), for
    /// > _n_ >= 2. We traverse the rope from left to right, inserting each
    /// > leaf into the appropriate sequence position, depending on its length.
    ///
    /// > The concatenation of the sequence of ropes in order of decreasing
    /// > length is equivalent to the prefix of the rope we have traversed so
    /// > far. Each new leaf _x_ is with_insert_ropeed into the appropriate entry of the
    /// > sequence. Assume that _x_’s length is in the interval [_Fn_, _Fn_+1),
    /// > and thus it should be put in slot _n_ (which also corresponds to
    /// > maximum depth _n_ − 2). If all lower and equal numbered levels are
    /// > empty, then this can be done directly. If not, then we concatenate
    /// > ropes in slots 2, ... ,(_n_ − 1) (concatenating onto the left), and
    /// > concatenate _x_ to the right of the result. We then continue to
    /// > concatenate ropes from the sequence in increasing order to the left
    /// > of this result, until the result fits into an empty slot in the
    /// > sequence."
    pub fn rebalance(self) -> Self {
        // TODO: this is a huge mess, I based it on the IBM Java implementation
        //       please refactor until it stops being ugly!
        //        - eliza, 12/17/2016

        if self.is_balanced() {
            // the subrope is already balanced, do nothing
            self
        } else {
            let mut leaves: Vec<Option<Node>> =
                self.into_leaves().map(Option::Some).collect();
            let len = leaves.len();
            fn _rebalance(l: &mut Vec<Option<Node>>, start: usize, end: usize)
                          -> Node {
                match end - start {
                    1 => l[start].take().unwrap()
                  , 2 => l[start].take().unwrap() + l[start + 1].take().unwrap()
                  , n => {
                        let mid = start + (n / 2);
                        _rebalance(l, start, mid) + _rebalance(l, mid, end)

                    }
                }
            };
            _rebalance(&mut leaves, 0, len)
        }
    }

    /// Returns an iterator over all leaf nodes in this `Node`'s subrope
    fn leaves<'a>(&'a self) -> Leaves<'a> {
        Leaves(vec![self])
    }

    /// Returns a move iterator over all leaf nodes in this `Node`'s subrope
    fn into_leaves(self) -> IntoLeaves {
        IntoLeaves(vec![self])
    }

    /// Returns an iterator over all the strings in this `Node`s subrope'
    #[inline]
    pub fn strings<'a>(&'a self) -> impl Iterator<Item=&'a str> {
        box self.leaves().map(|n| match n {
            &Leaf(ref s) => s.as_ref()
          , _ => unreachable!("Node.leaves() iterator contained something \
                               that wasn't a leaf. Barring _force majeure_, \
                               this should be impossible. Something's broken.")
        })
    }

    /// Returns a move iterator over all the strings in this `Node`s subrope'
    ///
    /// Consumes `self`.
    #[inline]
    pub fn into_strings(self) -> impl Iterator<Item=String> {
        box self.into_leaves().map(|n| match n {
            Leaf(s) => s
            , _ => unreachable!("Node.into_leaves() iterator contained \
                                 something  that wasn't a leaf. Barring _force \
                                 majeure_, this should be impossible. \
                                 Something's broken.")
        })
    }

    str_iters! {
        #[doc="Returns an iterator over all the bytes in this `Node`'s \
               subrope \n\

               \nAs a Rope consists of a sequence of bytes, we can iterate \
               through a rope by byte. This method returns such an iterator."]
        #[inline]
        impl bytes<u8> for Node {}
        #[doc="Returns an iterator over all the characters in this `Node`'s \
               subrope \n\

               \nAs a `Rope` consists of valid UTF-8, we can iterate through a \
               `Rope` by `char`. This method returns such an iterator. \n\

               \nIt's important to remember that `char` represents a Unicode \
               Scalar Value, and may not match your idea of what a \
               'character' is. Iteration over grapheme clusters may be what \
               you actually want."]
        #[inline]
        impl chars<char> for Node {}
        // TODO: this is actually Wrong, the indices will wrap around once we
        //       iterate into the next leaf node. we'll need to write our own
        //       char_indices iterator that tracks the character's index in the
        //       global Rope. shouldn't be too hard, just a fold...
        //          - eliza, 12/18/2016
        // #[inline]
        // impl char_indices<(usize, char)> for Node {}
        #[inline]
        impl split_whitespace<&'a str> for Node {}
        #[inline]
        impl lines<&'a str> for Node {}
    }

    // /// Returns n iterator over the bytes of this `Node`'s subrope
    // ///
    // ///
    // #[inline]
    // pub fn bytes<'a>(&'a self) -> impl Iterator<Item=u8> + 'a {
    //     self.strings().flat_map(str::bytes)
    // }

    /// Returns an iterator over the grapheme clusters of this `Node`'s subrope'
    ///
    /// This is the iterator returned by `Node::into_iter`.
    #[inline]
    pub fn graphemes<'a>(&'a self) -> impl Iterator<Item=&'a str> {
        // the compiler won't let me mark this as unimplemented using the
        // unimplemented!() macro, due to Reasons (i suspect relating to
        // returning `impl Trait`)
        //  - eliza, 12/18/2016
        panic!("Unimplemented!");
        self.strings()
    }

}

/// An iterator over a series of leaf `Node`s
struct Leaves<'a>(Vec<&'a Node>);

impl<'a> Iterator for Leaves<'a> {
    type Item = &'a Node;
    fn next(&mut self) -> Option<Self::Item> {
        match self.0.pop() {
            None => None
          , Some(leaf @ &Leaf(_)) => Some(leaf)
          , Some(&Branch(BranchNode { ref left, ref right, .. })) => {
                if let &Some(box ref r) = right { self.0.push(r); }
                if let &Some(box ref l) = left { self.0.push(l); }
                self.next()
            }
        }
    }
}

/// A move iterator over a series of leaf `Node`s
struct IntoLeaves(Vec<Node>);

impl Iterator for IntoLeaves {
    type Item = Node;
    fn next(&mut self) -> Option<Self::Item> {
        match self.0.pop() {
            None => None
          , Some(leaf @ Leaf(_)) => Some(leaf)
          , Some(Branch(BranchNode { left, right, .. })) => {
                if let Some(box r) = right { self.0.push(r); }
                if let Some(box l) = left { self.0.push(l); }
                self.next()
            }
        }
    }
}

impl ops::Add for Node {
    type Output = Self;
    /// Concatenate two `Node`s, returning a `Branch` node.
    fn add(self, right: Self) -> Self { Node::new_branch(self, right) }
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::cmp::Ordering;
use std::collections::hash_map::DefaultHasher;
use std::collections::{BTreeSet, HashSet};
use std::hash::{Hash, Hasher};
use std::mem;

type Book = u32;
type GroupedBasket = Vec<Group>;
type Price = u32;
const BOOK_PRICE: Price = 800;

#[derive(Debug, Clone)]
struct Group(RefCell<BTreeSet<Book>>);

impl Group {
    fn new() -> Group {
        Group(RefCell::new(BTreeSet::new()))
    }

    fn new_containing(book: Book) -> Group {
        let g = Group::new();
        g.0.borrow_mut().insert(book);
        g
    }

    fn price(&self) -> Price {
        (self.0.borrow().len() as Price)
            * BOOK_PRICE
            * match self.0.borrow().len() {
                2 => 95,
                3 => 90,
                4 => 80,
                5 => 75,
                _ => 100,
            }
            / 100
    }
}

impl Ord for Group {
    // we want to order groups first by qty contained DESC, then by lowest value ASC
    fn cmp(&self, other: &Group) -> Ordering {
        match other.0.borrow().len().cmp(&self.0.borrow().len()) {
            Ordering::Equal => {
                if self.0.borrow().is_empty() {
                    Ordering::Equal
                } else {
                    self.0
                        .borrow()
                        .iter()
                        .next()
                        .unwrap()
                        .cmp(other.0.borrow().iter().next().unwrap())
                }
            }
            otherwise => otherwise,
        }
    }
}

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

impl PartialEq for Group {
    fn eq(&self, other: &Group) -> bool {
        self.0.borrow().eq(&other.0.borrow())
    }
}

impl Eq for Group {}

impl Hash for Group {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        self.0.borrow().hash(hasher);
    }
}

fn basket_price(basket: &GroupedBasket) -> Price {
    basket.iter().map(|g| g.price()).sum()
}

/// Compute the hash of a GroupedBasket
///
/// Note that we don't actually care at all about the _values_ within
/// the groups, only their lengths. Therefore, let's hash not the actual
/// GB but its lengths.
fn hash_of(basket: &GroupedBasket) -> u64 {
    let lengths = basket
        .iter()
        .map(|g| g.0.borrow().len())
        .collect::<Vec<_>>();
    let mut hasher = DefaultHasher::new();
    lengths.hash(&mut hasher);
    hasher.finish()
}

pub fn lowest_price(books: &[Book]) -> Price {
    DecomposeGroups::new(books)
        .map(|gb| basket_price(&gb))
        .min()
        .unwrap_or(0)
}

struct DecomposeGroups {
    prev_states: HashSet<u64>,
    next: Option<GroupedBasket>,
}

impl Iterator for DecomposeGroups {
    type Item = GroupedBasket;
    fn next(&mut self) -> Option<Self::Item> {
        // our goal here: produce a stream of valid groups, differentiated by their
        // counts, from most compact to most dispersed.
        //
        // Algorithm:
        //  - Start with the most compact groups possible
        //  - If the number of groups == 0 or the max population of any group == 1, return None
        //  - For every item in the most populous group:
        //      - Try removing it and adding it to a smaller group.
        //          - Can any smaller group accept it? if yes, move it there and return
        //  - If it cannot be added to any smaller group, try the next item from this set
        //  - If no item from the most populous group can be added to any smaller group,
        //    then move the last item from the most populous group into a new group, alone,
        //    and return
        let return_value = self.next.clone();
        if let Some(groups) = mem::replace(&mut self.next, None) {
            if !(groups.is_empty() || groups.iter().all(|g| g.0.borrow().len() == 1)) {
                let mut hypothetical;
                for mpg_book in groups[0].0.borrow().iter() {
                    for (idx, other_group) in groups[1..].iter().enumerate() {
                        if !other_group.0.borrow().contains(mpg_book) {
                            hypothetical = groups.clone();
                            hypothetical[0].0.borrow_mut().remove(mpg_book);
                            hypothetical[1 + idx].0.borrow_mut().insert(*mpg_book);
                            hypothetical.sort();
                            let hypothetical_hash = hash_of(&hypothetical);
                            if !self.prev_states.contains(&hypothetical_hash) {
                                self.prev_states.insert(hypothetical_hash);
                                self.next = Some(hypothetical);
                                return return_value;
                            }
                        }
                    }
                }
                // we've gone through all the items of the most populous group,
                // and none of them can be added to any other existing group.
                // We need to create a new group;
                let book = {
                    let backing_bt = groups[0].0.borrow();
                    let mut book_iter = backing_bt.iter();
                    *book_iter.next().unwrap()
                };
                hypothetical = groups;
                hypothetical[0].0.borrow_mut().remove(&book);
                hypothetical.push(Group::new_containing(book));
                hypothetical.sort();
                self.prev_states.insert(hash_of(&hypothetical));
                self.next = Some(hypothetical);
            }
        }
        return_value
    }
}

impl DecomposeGroups {
    fn new(books: &[Book]) -> DecomposeGroups {
        let mut book_groups = GroupedBasket::new();
        'nextbook: for book in books {
            for Group(book_group) in book_groups.iter() {
                if !book_group.borrow().contains(&book) {
                    book_group.borrow_mut().insert(*book);
                    continue 'nextbook;
                }
            }
            // if we're here, we still haven't found a place for the book.
            // better add it to a new group
            book_groups.push(Group::new_containing(*book));
        }
        book_groups.sort();

        DecomposeGroups {
            next: Some(book_groups),
            prev_states: HashSet::new(),
        }
    }
}
<commit_msg>prefer slices over borrowed vecs in exercise examples (#1019)<commit_after>use std::cell::RefCell;
use std::cmp::Ordering;
use std::collections::hash_map::DefaultHasher;
use std::collections::{BTreeSet, HashSet};
use std::hash::{Hash, Hasher};
use std::mem;

type Book = u32;
type Price = u32;
const BOOK_PRICE: Price = 800;

#[derive(Debug, Clone)]
struct Group(RefCell<BTreeSet<Book>>);

impl Group {
    fn new() -> Group {
        Group(RefCell::new(BTreeSet::new()))
    }

    fn new_containing(book: Book) -> Group {
        let g = Group::new();
        g.0.borrow_mut().insert(book);
        g
    }

    fn price(&self) -> Price {
        (self.0.borrow().len() as Price)
            * BOOK_PRICE
            * match self.0.borrow().len() {
                2 => 95,
                3 => 90,
                4 => 80,
                5 => 75,
                _ => 100,
            }
            / 100
    }
}

impl Ord for Group {
    // we want to order groups first by qty contained DESC, then by lowest value ASC
    fn cmp(&self, other: &Group) -> Ordering {
        match other.0.borrow().len().cmp(&self.0.borrow().len()) {
            Ordering::Equal => {
                if self.0.borrow().is_empty() {
                    Ordering::Equal
                } else {
                    self.0
                        .borrow()
                        .iter()
                        .next()
                        .unwrap()
                        .cmp(other.0.borrow().iter().next().unwrap())
                }
            }
            otherwise => otherwise,
        }
    }
}

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

impl PartialEq for Group {
    fn eq(&self, other: &Group) -> bool {
        self.0.borrow().eq(&other.0.borrow())
    }
}

impl Eq for Group {}

impl Hash for Group {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        self.0.borrow().hash(hasher);
    }
}

fn basket_price(basket: &[Group]) -> Price {
    basket.iter().map(|g| g.price()).sum()
}

/// Compute the hash of a Vec<Group>
///
/// Note that we don't actually care at all about the _values_ within
/// the groups, only their lengths. Therefore, let's hash only those.
fn hash_of(basket: &[Group]) -> u64 {
    let lengths = basket
        .iter()
        .map(|g| g.0.borrow().len())
        .collect::<Vec<_>>();
    let mut hasher = DefaultHasher::new();
    lengths.hash(&mut hasher);
    hasher.finish()
}

pub fn lowest_price(books: &[Book]) -> Price {
    DecomposeGroups::new(books)
        .map(|gb| basket_price(&gb))
        .min()
        .unwrap_or(0)
}

struct DecomposeGroups {
    prev_states: HashSet<u64>,
    next: Option<Vec<Group>>,
}

impl Iterator for DecomposeGroups {
    type Item = Vec<Group>;
    fn next(&mut self) -> Option<Self::Item> {
        // our goal here: produce a stream of valid groups, differentiated by their
        // counts, from most compact to most dispersed.
        //
        // Algorithm:
        //  - Start with the most compact groups possible
        //  - If the number of groups == 0 or the max population of any group == 1, return None
        //  - For every item in the most populous group:
        //      - Try removing it and adding it to a smaller group.
        //          - Can any smaller group accept it? if yes, move it there and return
        //  - If it cannot be added to any smaller group, try the next item from this set
        //  - If no item from the most populous group can be added to any smaller group,
        //    then move the last item from the most populous group into a new group, alone,
        //    and return
        let return_value = self.next.clone();
        if let Some(groups) = mem::replace(&mut self.next, None) {
            if !(groups.is_empty() || groups.iter().all(|g| g.0.borrow().len() == 1)) {
                let mut hypothetical;
                for mpg_book in groups[0].0.borrow().iter() {
                    for (idx, other_group) in groups[1..].iter().enumerate() {
                        if !other_group.0.borrow().contains(mpg_book) {
                            hypothetical = groups.clone();
                            hypothetical[0].0.borrow_mut().remove(mpg_book);
                            hypothetical[1 + idx].0.borrow_mut().insert(*mpg_book);
                            hypothetical.sort();
                            let hypothetical_hash = hash_of(&hypothetical);
                            if !self.prev_states.contains(&hypothetical_hash) {
                                self.prev_states.insert(hypothetical_hash);
                                self.next = Some(hypothetical);
                                return return_value;
                            }
                        }
                    }
                }
                // we've gone through all the items of the most populous group,
                // and none of them can be added to any other existing group.
                // We need to create a new group;
                let book = {
                    let backing_bt = groups[0].0.borrow();
                    let mut book_iter = backing_bt.iter();
                    *book_iter.next().unwrap()
                };
                hypothetical = groups;
                hypothetical[0].0.borrow_mut().remove(&book);
                hypothetical.push(Group::new_containing(book));
                hypothetical.sort();
                self.prev_states.insert(hash_of(&hypothetical));
                self.next = Some(hypothetical);
            }
        }
        return_value
    }
}

impl DecomposeGroups {
    fn new(books: &[Book]) -> DecomposeGroups {
        let mut book_groups = Vec::new();
        'nextbook: for book in books {
            for Group(book_group) in book_groups.iter() {
                if !book_group.borrow().contains(&book) {
                    book_group.borrow_mut().insert(*book);
                    continue 'nextbook;
                }
            }
            // if we're here, we still haven't found a place for the book.
            // better add it to a new group
            book_groups.push(Group::new_containing(*book));
        }
        book_groups.sort();

        DecomposeGroups {
            next: Some(book_groups),
            prev_states: HashSet::new(),
        }
    }
}
<|endoftext|>


<commit_before>
<commit_msg>rectangles: Add template to the stub file (#612)<commit_after>pub fn count(lines: &[&str]) -> u32 {
    unimplemented!("Determine the count of rectangles in the ASCII diagram represented by the following lines:\n{:#?}\n.", lines);
}
<|endoftext|>