<commit_before>use std::borrow::{Borrow, BorrowMut, Cow};
use std::cmp::{Eq, PartialEq};
use std::error::Error;
use std::hash::{Hash, Hasher};
use std::ops::{Deref, DerefMut};
use std::{fmt, mem, ptr, str};
use odds::char::{encode_utf8, EncodeUtf8Error};
use ::utf8::PascalStr;
use ::PASCAL_STRING_BUF_SIZE;

/// An owned `PascalString`. This string type stores its data the stack. It is always 256 bytes long, with
/// the first byte storing the length *of the number of bytes used*.
///
/// Note that because this string type is utf8 encoded, the first byte will not store the number of characters
/// in the string.
pub struct PascalString {
    /// The number of bytes used in the string.
    len: u8,
    /// The internal character buffer, encoded in utf8
    chars_buf: [u8; PASCAL_STRING_BUF_SIZE]
}

impl PascalString {
    /// Creates a new, empty `PascalString`.
    #[inline]
    pub fn new() -> Self {
        Default::default()
    }

    /// Creates a new `PascalString` with the contents of `s`.
    ///
    /// # Returns
    ///
    /// If the contents of `s` can be stored in the buffer of the `PascalString`, then it returns
    /// `Ok`. Otherwise, returns `Err`.
    #[inline]
    pub fn from_str<S: AsRef<str>>(s: S) -> Result<Self, PascalStringCreateError> {
        let s = s.as_ref();
        if s.len() > PASCAL_STRING_BUF_SIZE {
            return Err(PascalStringCreateError::InputTooLong);
        }
        let mut pstring = PascalString::new();
        for ch in s.chars() {
            pstring.push(ch)
        }
        Ok(pstring)
    }

    /// Push a character onto the end of the string's internal buffer.
    ///
    /// # Panics
    ///
    /// Panics if there is no room to store the `char`.
    #[inline]
    pub fn push(&mut self, ch: char) {
        self.try_push(ch).unwrap()
    }

    /// Attempt to push a `char` onto the end of this string's internal buffer.
    ///
    /// # Returns
    ///
    /// Returns `Ok(())` if the operation succeeded, otherwise an error is returned.
    #[inline]
    pub fn try_push(&mut self, ch: char) -> Result<(), EncodeUtf8Error> {
        let num_bytes_extended = try!(encode_utf8(ch, &mut self.chars_buf[self.len as usize..]));
        self.len += num_bytes_extended as u8;
        Ok(())
    }

    /// Push a string onto the end of this string's internal buffer.
    ///
    /// # Panics
    ///
    /// Panics if there is no room to store the `str`.
    #[inline]
    pub fn push_str<S: AsRef<str>>(&mut self, s: S) {
        self.try_push_str(s).unwrap()
    }

    /// Attempt to push a string onto the end of this string's internal buffer.
    ///
    /// # Returns
    ///
    /// Returns `Ok(())` if the operation succeeded, otherwise an error is returned.
    #[inline]
    pub fn try_push_str<S: AsRef<str>>(&mut self, s: S) -> Result<(), PascalStringAppendError> {
        self._try_push_str(s.as_ref())
    }

    fn _try_push_str(&mut self, s: &str) -> Result<(), PascalStringAppendError> {
        if self.len() + s.len() > PASCAL_STRING_BUF_SIZE {
            return Err(PascalStringAppendError::NoRoom);
        }
        for ch in s.chars() {
            try!(self.try_push(ch))
        }
        Ok(())
    }
}

impl Default for PascalString {
    #[inline]
    fn default() -> Self {
        PascalString {
            len: 0,
            chars_buf: [0u8; PASCAL_STRING_BUF_SIZE]
        }
    }
}

impl Clone for PascalString {
    fn clone(&self) -> Self {
        let mut clone = PascalString::default();
        clone.len = self.len;
        unsafe {
            ptr::copy_nonoverlapping(&self.chars_buf, &mut clone.chars_buf, PASCAL_STRING_BUF_SIZE);
        }
        clone
    }
}

impl Hash for PascalString {
    #[inline]
    fn hash<H: Hasher>(&self, state: &mut H) {
        state.write_u8(self.len);
        state.write(&self.chars_buf);
    }
}

impl Deref for PascalString {
    type Target = PascalStr;

    #[inline]
    fn deref(&self) -> &Self::Target {
        unsafe { mem::transmute(&self.chars_buf[0..(self.len as usize)]) }
    }
}

impl DerefMut for PascalString {
    #[inline]
    fn deref_mut(&mut self) -> &mut Self::Target {
        unsafe { mem::transmute(&mut self.chars_buf[0..(self.len as usize)]) }
    }
}

impl AsRef<PascalStr> for PascalString {
    #[inline]
    fn as_ref(&self) -> &PascalStr {
        self.deref()
    }
}

impl AsRef<str> for PascalString {
    #[inline]
    fn as_ref(&self) -> &str {
        self.as_str()
    }
}

impl Borrow<PascalStr> for PascalString {
    #[inline]
    fn borrow(&self) -> &PascalStr {
        self.deref()
    }
}

impl BorrowMut<PascalStr> for PascalString {
    #[inline]
    fn borrow_mut(&mut self) -> &mut PascalStr {
        self.deref_mut()
    }
}

impl Eq for PascalString { }

impl PartialEq for PascalString {
    #[inline]
    fn eq(&self, other: &PascalString) -> bool {
        self.as_str().eq(other.as_str())
    }
}

impl PartialEq<PascalStr> for PascalString {
    #[inline]
    fn eq(&self, other: &PascalStr) -> bool {
        self.as_str().eq(other.as_str())
    }
}

impl<'a> PartialEq<Cow<'a, PascalStr>> for PascalString {
    #[inline]
    fn eq(&self, other: &Cow<'a, PascalStr>) -> bool {
        let other: &PascalStr = other.borrow();
        let other: &str = other.as_str();
        self.as_str().eq(other)
    }
}

impl PartialEq<String> for PascalString {
    #[inline]
    fn eq(&self, other: &String) -> bool {
        let other: &str = other.as_str();
        self.as_str().eq(other)
    }
}

impl PartialEq<str> for PascalString {
    #[inline]
    fn eq(&self, other: &str) -> bool {
        self.as_str().eq(other)
    }
}

impl<'a> PartialEq<Cow<'a, str>> for PascalString {
    #[inline]
    fn eq(&self, other: &Cow<'a, str>) -> bool {
        let other: &str = other.borrow();
        self.as_str().eq(other)
    }
}

#[derive(Debug, Clone, Copy)]
pub enum PascalStringCreateError {
    InputTooLong
}

#[derive(Debug, Clone, Copy)]
pub enum PascalStringAppendError {
    NoRoom,
    EncodeError(EncodeUtf8Error)
}

impl fmt::Display for PascalStringAppendError {
    fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
        let desc = self.description();
        match *self {
            PascalStringAppendError::NoRoom => fmtr.pad(desc),
            PascalStringAppendError::EncodeError(ref e) => write!(fmtr, "{}: {:?}", desc, e)
        }
    }
}

impl Error for PascalStringAppendError {
    fn description(&self) -> &str {
        match *self {
            PascalStringAppendError::NoRoom => "there is no room for the string to be appended",
            PascalStringAppendError::EncodeError(_) => "there was a problem encoding the character as utf8: {:?}"
        }
    }
}

impl From<EncodeUtf8Error> for PascalStringAppendError {
    fn from(e: EncodeUtf8Error) -> Self {
        PascalStringAppendError::EncodeError(e)
    }
}
<commit_msg>Improve PascalStringAppendError<commit_after>use std::borrow::{Borrow, BorrowMut, Cow};
use std::cmp::{Eq, PartialEq};
use std::error::Error;
use std::hash::{Hash, Hasher};
use std::ops::{Deref, DerefMut};
use std::{fmt, mem, ptr, str};
use odds::char::{encode_utf8, EncodeUtf8Error};
use ::utf8::PascalStr;
use ::PASCAL_STRING_BUF_SIZE;

/// An owned `PascalString`. This string type stores its data the stack. It is always 256 bytes long, with
/// the first byte storing the length *of the number of bytes used*.
///
/// Note that because this string type is utf8 encoded, the first byte will not store the number of characters
/// in the string.
pub struct PascalString {
    /// The number of bytes used in the string.
    len: u8,
    /// The internal character buffer, encoded in utf8
    chars_buf: [u8; PASCAL_STRING_BUF_SIZE]
}

impl PascalString {
    /// Creates a new, empty `PascalString`.
    #[inline]
    pub fn new() -> Self {
        Default::default()
    }

    /// Creates a new `PascalString` with the contents of `s`.
    ///
    /// # Returns
    ///
    /// If the contents of `s` can be stored in the buffer of the `PascalString`, then it returns
    /// `Ok`. Otherwise, returns `Err`.
    #[inline]
    pub fn from_str<S: AsRef<str>>(s: S) -> Result<Self, PascalStringCreateError> {
        let s = s.as_ref();
        if s.len() > PASCAL_STRING_BUF_SIZE {
            return Err(PascalStringCreateError::InputTooLong);
        }
        let mut pstring = PascalString::new();
        for ch in s.chars() {
            pstring.push(ch)
        }
        Ok(pstring)
    }

    /// Push a character onto the end of the string's internal buffer.
    ///
    /// # Panics
    ///
    /// Panics if there is no room to store the `char`.
    #[inline]
    pub fn push(&mut self, ch: char) {
        self.try_push(ch).unwrap()
    }

    /// Attempt to push a `char` onto the end of this string's internal buffer.
    ///
    /// # Returns
    ///
    /// Returns `Ok(())` if the operation succeeded, otherwise an error is returned.
    #[inline]
    pub fn try_push(&mut self, ch: char) -> Result<(), EncodeUtf8Error> {
        let num_bytes_extended = try!(encode_utf8(ch, &mut self.chars_buf[self.len as usize..]));
        self.len += num_bytes_extended as u8;
        Ok(())
    }

    /// Push a string onto the end of this string's internal buffer.
    ///
    /// # Panics
    ///
    /// Panics if there is no room to store the `str`.
    #[inline]
    pub fn push_str<S: AsRef<str>>(&mut self, s: S) {
        self.try_push_str(s).unwrap()
    }

    /// Attempt to push a string onto the end of this string's internal buffer.
    ///
    /// # Returns
    ///
    /// Returns `Ok(())` if the operation succeeded, otherwise an error is returned.
    #[inline]
    pub fn try_push_str<S: AsRef<str>>(&mut self, s: S) -> Result<(), PascalStringAppendError> {
        self._try_push_str(s.as_ref())
    }

    fn _try_push_str(&mut self, s: &str) -> Result<(), PascalStringAppendError> {
        if self.len() + s.len() > PASCAL_STRING_BUF_SIZE {
            return Err(PascalStringAppendError::NoRoom);
        }
        for ch in s.chars() {
            try!(self.try_push(ch))
        }
        Ok(())
    }
}

impl Default for PascalString {
    #[inline]
    fn default() -> Self {
        PascalString {
            len: 0,
            chars_buf: [0u8; PASCAL_STRING_BUF_SIZE]
        }
    }
}

impl Clone for PascalString {
    fn clone(&self) -> Self {
        let mut clone = PascalString::default();
        clone.len = self.len;
        unsafe {
            ptr::copy_nonoverlapping(&self.chars_buf, &mut clone.chars_buf, PASCAL_STRING_BUF_SIZE);
        }
        clone
    }
}

impl Hash for PascalString {
    #[inline]
    fn hash<H: Hasher>(&self, state: &mut H) {
        state.write_u8(self.len);
        state.write(&self.chars_buf);
    }
}

impl Deref for PascalString {
    type Target = PascalStr;

    #[inline]
    fn deref(&self) -> &Self::Target {
        unsafe { mem::transmute(&self.chars_buf[0..(self.len as usize)]) }
    }
}

impl DerefMut for PascalString {
    #[inline]
    fn deref_mut(&mut self) -> &mut Self::Target {
        unsafe { mem::transmute(&mut self.chars_buf[0..(self.len as usize)]) }
    }
}

impl AsRef<PascalStr> for PascalString {
    #[inline]
    fn as_ref(&self) -> &PascalStr {
        self.deref()
    }
}

impl AsRef<str> for PascalString {
    #[inline]
    fn as_ref(&self) -> &str {
        self.as_str()
    }
}

impl Borrow<PascalStr> for PascalString {
    #[inline]
    fn borrow(&self) -> &PascalStr {
        self.deref()
    }
}

impl BorrowMut<PascalStr> for PascalString {
    #[inline]
    fn borrow_mut(&mut self) -> &mut PascalStr {
        self.deref_mut()
    }
}

impl Eq for PascalString { }

impl PartialEq for PascalString {
    #[inline]
    fn eq(&self, other: &PascalString) -> bool {
        self.as_str().eq(other.as_str())
    }
}

impl PartialEq<PascalStr> for PascalString {
    #[inline]
    fn eq(&self, other: &PascalStr) -> bool {
        self.as_str().eq(other.as_str())
    }
}

impl<'a> PartialEq<Cow<'a, PascalStr>> for PascalString {
    #[inline]
    fn eq(&self, other: &Cow<'a, PascalStr>) -> bool {
        let other: &PascalStr = other.borrow();
        let other: &str = other.as_str();
        self.as_str().eq(other)
    }
}

impl PartialEq<String> for PascalString {
    #[inline]
    fn eq(&self, other: &String) -> bool {
        let other: &str = other.as_str();
        self.as_str().eq(other)
    }
}

impl PartialEq<str> for PascalString {
    #[inline]
    fn eq(&self, other: &str) -> bool {
        self.as_str().eq(other)
    }
}

impl<'a> PartialEq<Cow<'a, str>> for PascalString {
    #[inline]
    fn eq(&self, other: &Cow<'a, str>) -> bool {
        let other: &str = other.borrow();
        self.as_str().eq(other)
    }
}

#[derive(Debug, Clone, Copy)]
pub enum PascalStringCreateError {
    InputTooLong
}

#[derive(Debug, Clone, Copy)]
pub enum PascalStringAppendError {
    NoRoom,
    EncodeError(EncodeUtf8Error)
}

impl fmt::Display for PascalStringAppendError {
    fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
        let desc = self.description();
        match *self {
            PascalStringAppendError::NoRoom => fmtr.pad(desc),
            PascalStringAppendError::EncodeError(ref e) => write!(fmtr, "{}: {:?}", desc, e)
        }
    }
}

impl Error for PascalStringAppendError {
    fn description(&self) -> &str {
        match *self {
            PascalStringAppendError::NoRoom => "there is no room for the string to be appended",
            PascalStringAppendError::EncodeError(_) => "there was a problem encoding the character as utf8"
        }
    }

    fn cause(&self) -> Option<&Error> {
        // std::error::Error is not implemented for EncodeUtf8Error
        /*
        if let PascalStringAppendError::EncodeError(ref e) = *self {
            Some(e)
        } else {
            None
        }
        */
        None
    }
}

impl From<EncodeUtf8Error> for PascalStringAppendError {
    fn from(e: EncodeUtf8Error) -> Self {
        PascalStringAppendError::EncodeError(e)
    }
}
<|endoftext|>


<commit_before>fn main() {
    let length = 50;
    let width = 30;

    println!(
        "Area of rectangle with length: {} and width: {} is equal to: {}",
        length, width, area(length, width)
    );
}

fn area(length: u32, width: u32) -> u32 {
    length * width
}
<commit_msg>Add implementation with tuple usage<commit_after>fn main() {
    let length = 50;
    let width = 30;

    println!(
        "Area of rectangle with length: {} and width: {} is equal to: {}",
        length, width, area(length, width)
    );

    let rect = (length, width);

    println!(
        "Area of rectangle with length: {} and width: {} is equal to: {}",
        rect.0, rect.1, area_with_tuple(rect)
    );

}

fn area(length: u32, width: u32) -> u32 {
    length * width
}

fn area_with_tuple(dimensions: (u32, u32)) -> u32 {
    dimensions.0 * dimensions.1
}
<|endoftext|>


<commit_before>use align::HAlign;
use std::cmp;
use std::thread;
use theme::{ColorStyle, Effect};
use utils::Counter;
use view::View;
use Printer;

// pub type CbPromise = Option<Box<Fn(&mut Cursive) + Send>>;

/// Animated bar showing a progress value.
///
/// This bar has an internal counter, and adapts the length of the displayed
/// bar to the relative position of the counter between a minimum and maximum
/// values.
///
/// It also prints a customizable text in the center of the bar, which
/// defaults to the progression percentage.
///
/// # Example
///
/// ```
/// # use cursive::views::ProgressBar;
/// let bar = ProgressBar::new()
///                       .with_task(|counter| {
///                           // This closure is called in parallel.
///                           for _ in 0..100 {
///                               // Here we can communicate some
///                               // advancement back to the bar.
///                               counter.tick(1);
///                           }
///                       });
/// ```
pub struct ProgressBar {
    min: usize,
    max: usize,
    value: Counter,
    // TODO: use a Promise instead?
    label_maker: Box<Fn(usize, (usize, usize)) -> String>,
}

fn make_percentage(value: usize, (min, max): (usize, usize)) -> String {
    if value < min {
        return format!("0 %");
    }

    let (percentage, extra) = ratio(value - min, max - min, 100);
    let percentage = if extra > 4 {
        percentage + 1
    } else {
        percentage
    };
    format!("{} %", percentage)
}

/// Returns length * value/max
///
/// Constraint: `value` from 0 to `max` should, as much as possible, produce equal-sized segments
/// from 0 to length.
///
/// Returns a tuple with:
/// * The integer part of the division
/// * A value between 0 and 8 (exclusive) corresponding to the remainder.
fn ratio(value: usize, max: usize, length: usize) -> (usize, usize) {
    let integer = length * value / max;
    let fraction = length * value - max * integer;

    let fraction = fraction * 8 / max;

    (integer, fraction)
}

new_default!(ProgressBar);

impl ProgressBar {
    /// Creates a new progress bar.
    ///
    /// Default values:
    ///
    /// * `min`: 0
    /// * `max`: 100
    /// * `value`: 0
    pub fn new() -> Self {
        ProgressBar {
            min: 0,
            max: 100,
            value: Counter::new(0),
            label_maker: Box::new(make_percentage),
        }
    }

    /// Sets the value to follow.
    ///
    /// Use this to manually control the progress to display
    /// by directly modifying the value pointed to by `value`.
    pub fn with_value(mut self, value: Counter) -> Self {
        self.value = value;
        self
    }

    /// Starts a function in a separate thread, and monitor the progress.
    ///
    /// `f` will be given a `Counter` to increment the bar's progress.
    ///
    /// This does not reset the value, so it can be called several times
    /// to advance the progress in multiple sessions.
    pub fn start<F: FnOnce(Counter) + Send + 'static>(&mut self, f: F) {
        let counter: Counter = self.value.clone();

        thread::spawn(move || {
            f(counter);
        });
    }

    /// Starts a function in a separate thread, and monitor the progress.
    ///
    /// Chainable variant.
    pub fn with_task<F: FnOnce(Counter) + Send + 'static>(
        mut self, task: F,
    ) -> Self {
        self.start(task);
        self
    }

    /// Sets the label generator.
    ///
    /// The given function will be called with `(value, (min, max))`.
    /// Its output will be used as the label to print inside the progress bar.
    ///
    /// The default one shows a percentage progress:
    ///
    /// ```
    /// fn make_progress(value: usize, (min, max): (usize, usize)) -> String {
    ///     let percent = 101 * (value - min) / (1 + max - min);
    ///     format!("{} %", percent)
    /// }
    /// ```
    pub fn with_label<F: Fn(usize, (usize, usize)) -> String + 'static>(
        mut self, label_maker: F,
    ) -> Self {
        self.label_maker = Box::new(label_maker);
        self
    }

    /// Sets the minimum value.
    ///
    /// When `value` equals `min`, the bar is at the minimum level.
    ///
    /// If `self.min > max`, `self.min` is set to `max`.
    pub fn min(mut self, min: usize) -> Self {
        self.min = min;
        self.max = cmp::max(self.max, self.min);

        self
    }

    /// Sets the maximum value.
    ///
    /// When `value` equals `max`, the bar is at the maximum level.
    ///
    /// If `min > self.max`, `self.max` is set to `min`.
    pub fn max(mut self, max: usize) -> Self {
        self.max = max;
        self.min = cmp::min(self.min, self.max);

        self
    }

    /// Sets the `min` and `max` range for the value.
    ///
    /// If `min > max`, swap the two values.
    pub fn range(self, min: usize, max: usize) -> Self {
        if min > max {
            self.min(max).max(min)
        } else {
            self.min(min).max(max)
        }
    }

    /// Sets the current value.
    ///
    /// Value is clamped between `min` and `max`.
    pub fn set_value(&mut self, value: usize) {
        self.value.set(value);
    }
}

fn sub_block(extra: usize) -> &'static str {
    match extra {
        0 => " ",
        1 => "▏",
        2 => "▎",
        3 => "▍",
        4 => "▌",
        5 => "▋",
        6 => "▊",
        7 => "▉",
        _ => "█",
    }
}

impl View for ProgressBar {
    fn draw(&self, printer: &Printer) {
        // Now, the bar itself...
        let available = printer.size.x;

        let value = self.value.get();

        // If we're under the minimum, don't draw anything.
        // If we're over the maximum, we'll try to draw more, but the printer
        // will crop us anyway, so it's not a big deal.
        let (length, extra) = if value < self.min {
            (0, 0)
        } else {
            ratio(value - self.min, self.max - self.min, available)
        };

        let label = (self.label_maker)(value, (self.min, self.max));
        let offset = HAlign::Center.get_offset(label.len(), printer.size.x);

        printer.with_color(ColorStyle::highlight(), |printer| {
            // Draw the right half of the label in reverse
            printer.with_effect(Effect::Reverse, |printer| {
                printer.print((length, 0), sub_block(extra));
                printer.print((offset, 0), &label);
            });
            let printer = &printer.cropped((length, 1));
            printer.print_hline((0, 0), length, " ");

            // Draw the left part in highlight (it may be cropped)
            printer.print((offset, 0), &label);
        });
    }
}
<commit_msg>Modified `ProgressBar` to allow for customization of bar's color. (#279)<commit_after>use align::HAlign;
use std::cmp;
use std::thread;
use theme::{ColorStyle, ColorType, Effect};
use utils::Counter;
use view::View;
use Printer;

// pub type CbPromise = Option<Box<Fn(&mut Cursive) + Send>>;

/// Animated bar showing a progress value.
///
/// This bar has an internal counter, and adapts the length of the displayed
/// bar to the relative position of the counter between a minimum and maximum
/// values.
///
/// It also prints a customizable text in the center of the bar, which
/// defaults to the progression percentage.
///
/// The bar defaults to the current theme's highlight color,
/// but that can be customized.
///
/// # Example
///
/// ```
/// # use cursive::views::ProgressBar;
/// let bar = ProgressBar::new()
///                       .with_task(|counter| {
///                           // This closure is called in parallel.
///                           for _ in 0..100 {
///                               // Here we can communicate some
///                               // advancement back to the bar.
///                               counter.tick(1);
///                           }
///                       });
/// ```
pub struct ProgressBar {
    min: usize,
    max: usize,
    value: Counter,
    color: ColorType,
    // TODO: use a Promise instead?
    label_maker: Box<Fn(usize, (usize, usize)) -> String>,
}

fn make_percentage(value: usize, (min, max): (usize, usize)) -> String {
    if value < min {
        return format!("0 %");
    }

    let (percentage, extra) = ratio(value - min, max - min, 100);
    let percentage = if extra > 4 {
        percentage + 1
    } else {
        percentage
    };
    format!("{} %", percentage)
}

/// Returns length * value/max
///
/// Constraint: `value` from 0 to `max` should, as much as possible, produce equal-sized segments
/// from 0 to length.
///
/// Returns a tuple with:
/// * The integer part of the division
/// * A value between 0 and 8 (exclusive) corresponding to the remainder.
fn ratio(value: usize, max: usize, length: usize) -> (usize, usize) {
    let integer = length * value / max;
    let fraction = length * value - max * integer;

    let fraction = fraction * 8 / max;

    (integer, fraction)
}

new_default!(ProgressBar);

impl ProgressBar {
    /// Creates a new progress bar.
    ///
    /// Default values:
    ///
    /// * `min`: 0
    /// * `max`: 100
    /// * `value`: 0
    pub fn new() -> Self {
        ProgressBar {
            min: 0,
            max: 100,
            value: Counter::new(0),
            color: ColorStyle::highlight().back,
            label_maker: Box::new(make_percentage),
        }
    }

    /// Sets the value to follow.
    ///
    /// Use this to manually control the progress to display
    /// by directly modifying the value pointed to by `value`.
    pub fn with_value(mut self, value: Counter) -> Self {
        self.value = value;
        self
    }

    /// Starts a function in a separate thread, and monitor the progress.
    ///
    /// `f` will be given a `Counter` to increment the bar's progress.
    ///
    /// This does not reset the value, so it can be called several times
    /// to advance the progress in multiple sessions.
    pub fn start<F: FnOnce(Counter) + Send + 'static>(&mut self, f: F) {
        let counter: Counter = self.value.clone();

        thread::spawn(move || {
            f(counter);
        });
    }

    /// Starts a function in a separate thread, and monitor the progress.
    ///
    /// Chainable variant.
    pub fn with_task<F: FnOnce(Counter) + Send + 'static>(
        mut self, task: F,
    ) -> Self {
        self.start(task);
        self
    }

    /// Sets the label generator.
    ///
    /// The given function will be called with `(value, (min, max))`.
    /// Its output will be used as the label to print inside the progress bar.
    ///
    /// The default one shows a percentage progress:
    ///
    /// ```
    /// fn make_progress(value: usize, (min, max): (usize, usize)) -> String {
    ///     let percent = 101 * (value - min) / (1 + max - min);
    ///     format!("{} %", percent)
    /// }
    /// ```
    pub fn with_label<F: Fn(usize, (usize, usize)) -> String + 'static>(
        mut self, label_maker: F,
    ) -> Self {
        self.label_maker = Box::new(label_maker);
        self
    }

    /// Sets the minimum value.
    ///
    /// When `value` equals `min`, the bar is at the minimum level.
    ///
    /// If `self.min > max`, `self.min` is set to `max`.
    pub fn min(mut self, min: usize) -> Self {
        self.min = min;
        self.max = cmp::max(self.max, self.min);

        self
    }

    /// Sets the maximum value.
    ///
    /// When `value` equals `max`, the bar is at the maximum level.
    ///
    /// If `min > self.max`, `self.max` is set to `min`.
    pub fn max(mut self, max: usize) -> Self {
        self.max = max;
        self.min = cmp::min(self.min, self.max);

        self
    }

    /// Sets the `min` and `max` range for the value.
    ///
    /// If `min > max`, swap the two values.
    pub fn range(self, min: usize, max: usize) -> Self {
        if min > max {
            self.min(max).max(min)
        } else {
            self.min(min).max(max)
        }
    }

    /// Sets the current value.
    ///
    /// Value is clamped between `min` and `max`.
    pub fn set_value(&mut self, value: usize) {
        self.value.set(value);
    }

    /// Sets the color style.
    pub fn set_color<C>(&mut self, color: C)
    where
        C: Into<ColorType>,
    {
        self.color = color.into();
    }

    /// Sets the color style.
    ///
    /// Chainable variant of `set_color`.
    pub fn with_color<C>(mut self, color: C) -> Self
    where
        C: Into<ColorType>,
    {
        self.color = color.into();

        self
    }
}

fn sub_block(extra: usize) -> &'static str {
    match extra {
        0 => " ",
        1 => "▏",
        2 => "▎",
        3 => "▍",
        4 => "▌",
        5 => "▋",
        6 => "▊",
        7 => "▉",
        _ => "█",
    }
}

impl View for ProgressBar {
    fn draw(&self, printer: &Printer) {
        // Now, the bar itself...
        let available = printer.size.x;

        let value = self.value.get();

        // If we're under the minimum, don't draw anything.
        // If we're over the maximum, we'll try to draw more, but the printer
        // will crop us anyway, so it's not a big deal.
        let (length, extra) = if value < self.min {
            (0, 0)
        } else {
            ratio(value - self.min, self.max - self.min, available)
        };

        let label = (self.label_maker)(value, (self.min, self.max));
        let offset = HAlign::Center.get_offset(label.len(), printer.size.x);

        let color_style =
            ColorStyle::new(ColorStyle::highlight().front, self.color);

        printer.with_color(color_style, |printer| {
            // Draw the right half of the label in reverse
            printer.with_effect(Effect::Reverse, |printer| {
                printer.print((length, 0), sub_block(extra));
                printer.print((offset, 0), &label);
            });
            let printer = &printer.cropped((length, 1));
            printer.print_hline((0, 0), length, " ");

            // Draw the left part in color_style (it may be cropped)
            printer.print((offset, 0), &label);
        });
    }
}
<|endoftext|>


<commit_before>native "rust" mod rustrt {
  fn rust_list_files(str path) -> vec[str];
  fn rust_file_is_dir(str path) -> int;
}

impure fn list_dir(str path) -> vec[str] {
  ret rustrt.rust_list_files(path+"*");
}

const char path_sep = '\\';

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>Switch win32 path_sep to '/', add comment explaining a bit.<commit_after>native "rust" mod rustrt {
  fn rust_list_files(str path) -> vec[str];
  fn rust_file_is_dir(str path) -> int;
}

impure fn list_dir(str path) -> vec[str] {
  ret rustrt.rust_list_files(path+"*");
}

/* FIXME: win32 path handling actually accepts '/' or '\' and has subtly
 * different semantics for each. Since we build on mingw, we are usually
 * dealing with /-separated paths. But the whole interface to splitting and
 * joining pathnames needs a bit more abstraction on win32. Possibly a vec or
 * tag type.
 */
const char path_sep = '/';

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before>#[doc = "
Communication between tasks

Communication between tasks is facilitated by ports (in the receiving
task), and channels (in the sending task). Any number of channels may
feed into a single port.  Ports and channels may only transmit values
of unique types; that is, values that are statically guaranteed to be
accessed by a single 'owner' at a time.  Unique types include scalars,
vectors, strings, and records, tags, tuples and unique boxes (`~T`)
thereof. Most notably, shared boxes (`@T`) may not be transmitted
across channels.

# Example

~~~
let po = comm::port();
let ch = comm::chan(po);

task::spawn {||
    comm::send(ch, \"Hello, World\");
});

io::println(comm::recv(p));
~~~
"];

import either::either;
import libc::size_t;

export port::{};
export chan::{};
export send;
export recv;
export peek;
export recv_chan;
export select2;
export methods;
export listen;

#[doc = "
A communication endpoint that can receive messages

Each port has a unique per-task identity and may not be replicated or
transmitted. If a port value is copied, both copies refer to the same
port.  Ports may be associated with multiple `chan`s.
"]
enum port<T: send> {
    port_t(@port_ptr<T>)
}

// It's critical that this only have one variant, so it has a record
// layout, and will work in the rust_task structure in task.rs.
#[doc = "
A communication endpoint that can send messages

Each channel is bound to a port when the channel is constructed, so
the destination port for a channel must exist before the channel
itself.  Channels are weak: a channel does not keep the port it is
bound to alive. If a channel attempts to send data to a dead port that
data will be silently dropped.  Channels may be duplicated and
themselves transmitted over other channels.
"]
enum chan<T: send> {
    chan_t(port_id)
}

#[doc = "Constructs a port"]
fn port<T: send>() -> port<T> {
    port_t(@port_ptr(rustrt::new_port(sys::size_of::<T>() as size_t)))
}

impl methods<T: send> for port<T> {

    fn chan() -> chan<T> { chan(self) }
    fn send(+v: T) { self.chan().send(v) }
    fn recv() -> T { recv(self) }
    fn peek() -> bool { peek(self) }

}

impl methods<T: send> for chan<T> {

    fn chan() -> chan<T> { self }
    fn send(+v: T) { send(self, v) }
    fn recv() -> T { recv_chan(self) }
    fn peek() -> bool { peek_chan(self) }

}

#[doc = "Open a new receiving channel for the duration of a function"]
fn listen<T: send, U>(f: fn(chan<T>) -> U) -> U {
    let po = port();
    f(po.chan())
}

class port_ptr<T:send> {
  let po: *rust_port;
  new(po: *rust_port) { self.po = po; }
  drop unsafe {
    task::unkillable {||
        // Once the port is detached it's guaranteed not to receive further
        // messages
        let yield = 0u;
        let yieldp = ptr::addr_of(yield);
        rustrt::rust_port_begin_detach(self.po, yieldp);
        if yield != 0u {
            // Need to wait for the port to be detached
            // FIXME: If this fails then we're going to leave our port
            // in a bogus state. (Issue #1988)
            task::yield();
        }
        rustrt::rust_port_end_detach(self.po);

        // Drain the port so that all the still-enqueued items get dropped
        while rustrt::rust_port_size(self.po) > 0u as size_t {
            recv_::<T>(self.po);
        }
        rustrt::del_port(self.po);
    }
  }
}

#[doc = "
Internal function for converting from a channel to a port

# Failure

Fails if the port is detached or dead. Fails if the port
is owned by a different task.
"]
fn as_raw_port<T: send, U>(ch: comm::chan<T>, f: fn(*rust_port) -> U) -> U {

    class portref {
       let p: *rust_port;
       new(p: *rust_port) { self.p = p; }
       drop {
         if !ptr::is_null(self.p) {
           rustrt::rust_port_drop(self.p);
         }
       }
    }

    let p = portref(rustrt::rust_port_take(*ch));

    if ptr::is_null(p.p) {
        fail "unable to locate port for channel"
    } else if rustrt::get_task_id() != rustrt::rust_port_task(p.p) {
        fail "unable to access unowned port"
    }

    f(p.p)
}

#[doc = "
Constructs a channel. The channel is bound to the port used to
construct it.
"]
fn chan<T: send>(p: port<T>) -> chan<T> {
    chan_t(rustrt::get_port_id((**p).po))
}

#[doc = "
Sends data over a channel. The sent data is moved into the channel,
whereupon the caller loses access to it.
"]
fn send<T: send>(ch: chan<T>, -data: T) {
    let chan_t(p) = ch;
    let data_ptr = ptr::addr_of(data) as *();
    let res = rustrt::rust_port_id_send(p, data_ptr);
    if res != 0u unsafe {
        // Data sent successfully
        unsafe::forget(data);
    }
    task::yield();
}

#[doc = "
Receive from a port.  If no data is available on the port then the
task will block until data becomes available.
"]
fn recv<T: send>(p: port<T>) -> T { recv_((**p).po) }

#[doc = "Returns true if there are messages available"]
fn peek<T: send>(p: port<T>) -> bool { peek_((**p).po) }

#[doc(hidden)]
fn recv_chan<T: send>(ch: comm::chan<T>) -> T {
    as_raw_port(ch, {|x|recv_(x)})
}

fn peek_chan<T: send>(ch: comm::chan<T>) -> bool {
    as_raw_port(ch, {|x|peek_(x)})
}

#[doc = "Receive on a raw port pointer"]
fn recv_<T: send>(p: *rust_port) -> T {
    let yield = 0u;
    let yieldp = ptr::addr_of(yield);
    let mut res;
    res = rusti::init::<T>();
    rustrt::port_recv(ptr::addr_of(res) as *uint, p, yieldp);

    if yield != 0u {
        // Data isn't available yet, so res has not been initialized.
        task::yield();
    } else {
        // In the absence of compiler-generated preemption points
        // this is a good place to yield
        task::yield();
    }
    ret res;
}

fn peek_(p: *rust_port) -> bool unsafe {
    rustrt::rust_port_size(p) != 0u as libc::size_t
}

#[doc = "Receive on one of two ports"]
fn select2<A: send, B: send>(p_a: port<A>, p_b: port<B>)
    -> either<A, B> unsafe {
    let ports = [(**p_a).po, (**p_b).po];
    let n_ports = 2 as libc::size_t;
    let yield = 0u, yieldp = ptr::addr_of(yield);

    let mut resport: *rust_port;
    resport = rusti::init::<*rust_port>();
    vec::as_buf(ports) {|ports|
        rustrt::rust_port_select(ptr::addr_of(resport), ports, n_ports,
                                 yieldp);
    }

    if yield != 0u {
        // Wait for data
        task::yield();
    } else {
        // As in recv, this is a good place to yield anyway until
        // the compiler generates yield calls
        task::yield();
    }

    // Now we know the port we're supposed to receive from
    assert resport != ptr::null();

    if resport == (**p_a).po {
        either::left(recv(p_a))
    } else if resport == (**p_b).po {
        either::right(recv(p_b))
    } else {
        fail "unexpected result from rust_port_select";
    }
}

/* Implementation details */

enum rust_port {}

type port_id = int;

#[abi = "cdecl"]
native mod rustrt {
    fn rust_port_id_send(target_port: port_id, data: *()) -> libc::uintptr_t;

    fn new_port(unit_sz: libc::size_t) -> *rust_port;
    fn del_port(po: *rust_port);
    fn rust_port_begin_detach(po: *rust_port,
                              yield: *libc::uintptr_t);
    fn rust_port_end_detach(po: *rust_port);
    fn get_port_id(po: *rust_port) -> port_id;
    fn rust_port_size(po: *rust_port) -> libc::size_t;
    fn port_recv(dptr: *uint, po: *rust_port,
                 yield: *libc::uintptr_t);
    fn rust_port_select(dptr: **rust_port, ports: **rust_port,
                        n_ports: libc::size_t,
                        yield: *libc::uintptr_t);
    fn rust_port_take(port_id: port_id) -> *rust_port;
    fn rust_port_drop(p: *rust_port);
    fn rust_port_task(p: *rust_port) -> libc::uintptr_t;
    fn get_task_id() -> libc::uintptr_t;
}

#[abi = "rust-intrinsic"]
native mod rusti {
    fn init<T>() -> T;
}

/* Tests */

#[test]
fn create_port_and_chan() { let p = port::<int>(); chan(p); }

#[test]
fn send_int() {
    let p = port::<int>();
    let c = chan(p);
    send(c, 22);
}

#[test]
fn send_recv_fn() {
    let p = port::<int>();
    let c = chan::<int>(p);
    send(c, 42);
    assert (recv(p) == 42);
}

#[test]
fn send_recv_fn_infer() {
    let p = port();
    let c = chan(p);
    send(c, 42);
    assert (recv(p) == 42);
}

#[test]
fn chan_chan_infer() {
    let p = port(), p2 = port::<int>();
    let c = chan(p);
    send(c, chan(p2));
    recv(p);
}

#[test]
fn chan_chan() {
    let p = port::<chan<int>>(), p2 = port::<int>();
    let c = chan(p);
    send(c, chan(p2));
    recv(p);
}

#[test]
fn test_peek() {
    let po = port();
    let ch = chan(po);
    assert !peek(po);
    send(ch, ());
    assert peek(po);
    recv(po);
    assert !peek(po);
}

#[test]
fn test_select2_available() {
    let po_a = port();
    let po_b = port();
    let ch_a = chan(po_a);
    let ch_b = chan(po_b);

    send(ch_a, "a");

    assert select2(po_a, po_b) == either::left("a");

    send(ch_b, "b");

    assert select2(po_a, po_b) == either::right("b");
}

#[test]
fn test_select2_rendezvous() {
    let po_a = port();
    let po_b = port();
    let ch_a = chan(po_a);
    let ch_b = chan(po_b);

    iter::repeat(10u) {||
        task::spawn {||
            iter::repeat(10u) {|| task::yield() }
            send(ch_a, "a");
        };

        assert select2(po_a, po_b) == either::left("a");

        task::spawn {||
            iter::repeat(10u) {|| task::yield() }
            send(ch_b, "b");
        };

        assert select2(po_a, po_b) == either::right("b");
    }
}

#[test]
fn test_select2_stress() {
    let po_a = port();
    let po_b = port();
    let ch_a = chan(po_a);
    let ch_b = chan(po_b);

    let msgs = 100u;
    let times = 4u;

    iter::repeat(times) {||
        task::spawn {||
            iter::repeat(msgs) {||
                send(ch_a, "a")
            }
        };
        task::spawn {||
            iter::repeat(msgs) {||
                send(ch_b, "b")
            }
        };
    }

    let mut as = 0;
    let mut bs = 0;
    iter::repeat(msgs * times * 2u) {||
        alt check select2(po_a, po_b) {
          either::left("a") { as += 1 }
          either::right("b") { bs += 1 }
        }
    }

    assert as == 400;
    assert bs == 400;
}

#[test]
fn test_recv_chan() {
    let po = port();
    let ch = chan(po);
    send(ch, "flower");
    assert recv_chan(ch) == "flower";
}

#[test]
#[should_fail]
#[ignore(cfg(windows))]
fn test_recv_chan_dead() {
    let ch = chan(port());
    send(ch, "flower");
    recv_chan(ch);
}

#[test]
#[ignore(cfg(windows))]
fn test_recv_chan_wrong_task() {
    let po = port();
    let ch = chan(po);
    send(ch, "flower");
    assert result::is_failure(task::try {||
        recv_chan(ch)
    })
}

#[test]
fn test_port_send() {
    let po = port();
    po.send(());
    po.recv();
}

#[test]
fn test_chan_peek() {
    let po = port();
    let ch = po.chan();
    ch.send(());
    assert ch.peek();
}

#[test]
fn test_listen() {
    listen {|parent|
        task::spawn {||
            parent.send("oatmeal-salad");
        }
        assert parent.recv() == "oatmeal-salad";
    }
}

#[test]
#[ignore(cfg(windows))]
fn test_port_detach_fail() {
    iter::repeat(100u) {||
        let builder = task::builder();
        task::unsupervise(builder);
        task::run(builder) {||
            let po = port();
            let ch = po.chan();

            task::spawn {||
                fail;
            }

            task::spawn {||
                ch.send(());
            }
        }
    }
}
<commit_msg>core: Remove resolved FIXME around port destruction<commit_after>#[doc = "
Communication between tasks

Communication between tasks is facilitated by ports (in the receiving
task), and channels (in the sending task). Any number of channels may
feed into a single port.  Ports and channels may only transmit values
of unique types; that is, values that are statically guaranteed to be
accessed by a single 'owner' at a time.  Unique types include scalars,
vectors, strings, and records, tags, tuples and unique boxes (`~T`)
thereof. Most notably, shared boxes (`@T`) may not be transmitted
across channels.

# Example

~~~
let po = comm::port();
let ch = comm::chan(po);

task::spawn {||
    comm::send(ch, \"Hello, World\");
});

io::println(comm::recv(p));
~~~
"];

import either::either;
import libc::size_t;

export port::{};
export chan::{};
export send;
export recv;
export peek;
export recv_chan;
export select2;
export methods;
export listen;

#[doc = "
A communication endpoint that can receive messages

Each port has a unique per-task identity and may not be replicated or
transmitted. If a port value is copied, both copies refer to the same
port.  Ports may be associated with multiple `chan`s.
"]
enum port<T: send> {
    port_t(@port_ptr<T>)
}

// It's critical that this only have one variant, so it has a record
// layout, and will work in the rust_task structure in task.rs.
#[doc = "
A communication endpoint that can send messages

Each channel is bound to a port when the channel is constructed, so
the destination port for a channel must exist before the channel
itself.  Channels are weak: a channel does not keep the port it is
bound to alive. If a channel attempts to send data to a dead port that
data will be silently dropped.  Channels may be duplicated and
themselves transmitted over other channels.
"]
enum chan<T: send> {
    chan_t(port_id)
}

#[doc = "Constructs a port"]
fn port<T: send>() -> port<T> {
    port_t(@port_ptr(rustrt::new_port(sys::size_of::<T>() as size_t)))
}

impl methods<T: send> for port<T> {

    fn chan() -> chan<T> { chan(self) }
    fn send(+v: T) { self.chan().send(v) }
    fn recv() -> T { recv(self) }
    fn peek() -> bool { peek(self) }

}

impl methods<T: send> for chan<T> {

    fn chan() -> chan<T> { self }
    fn send(+v: T) { send(self, v) }
    fn recv() -> T { recv_chan(self) }
    fn peek() -> bool { peek_chan(self) }

}

#[doc = "Open a new receiving channel for the duration of a function"]
fn listen<T: send, U>(f: fn(chan<T>) -> U) -> U {
    let po = port();
    f(po.chan())
}

class port_ptr<T:send> {
  let po: *rust_port;
  new(po: *rust_port) { self.po = po; }
  drop unsafe {
    task::unkillable {||
        // Once the port is detached it's guaranteed not to receive further
        // messages
        let yield = 0u;
        let yieldp = ptr::addr_of(yield);
        rustrt::rust_port_begin_detach(self.po, yieldp);
        if yield != 0u {
            // Need to wait for the port to be detached
            task::yield();
        }
        rustrt::rust_port_end_detach(self.po);

        // Drain the port so that all the still-enqueued items get dropped
        while rustrt::rust_port_size(self.po) > 0u as size_t {
            recv_::<T>(self.po);
        }
        rustrt::del_port(self.po);
    }
  }
}

#[doc = "
Internal function for converting from a channel to a port

# Failure

Fails if the port is detached or dead. Fails if the port
is owned by a different task.
"]
fn as_raw_port<T: send, U>(ch: comm::chan<T>, f: fn(*rust_port) -> U) -> U {

    class portref {
       let p: *rust_port;
       new(p: *rust_port) { self.p = p; }
       drop {
         if !ptr::is_null(self.p) {
           rustrt::rust_port_drop(self.p);
         }
       }
    }

    let p = portref(rustrt::rust_port_take(*ch));

    if ptr::is_null(p.p) {
        fail "unable to locate port for channel"
    } else if rustrt::get_task_id() != rustrt::rust_port_task(p.p) {
        fail "unable to access unowned port"
    }

    f(p.p)
}

#[doc = "
Constructs a channel. The channel is bound to the port used to
construct it.
"]
fn chan<T: send>(p: port<T>) -> chan<T> {
    chan_t(rustrt::get_port_id((**p).po))
}

#[doc = "
Sends data over a channel. The sent data is moved into the channel,
whereupon the caller loses access to it.
"]
fn send<T: send>(ch: chan<T>, -data: T) {
    let chan_t(p) = ch;
    let data_ptr = ptr::addr_of(data) as *();
    let res = rustrt::rust_port_id_send(p, data_ptr);
    if res != 0u unsafe {
        // Data sent successfully
        unsafe::forget(data);
    }
    task::yield();
}

#[doc = "
Receive from a port.  If no data is available on the port then the
task will block until data becomes available.
"]
fn recv<T: send>(p: port<T>) -> T { recv_((**p).po) }

#[doc = "Returns true if there are messages available"]
fn peek<T: send>(p: port<T>) -> bool { peek_((**p).po) }

#[doc(hidden)]
fn recv_chan<T: send>(ch: comm::chan<T>) -> T {
    as_raw_port(ch, {|x|recv_(x)})
}

fn peek_chan<T: send>(ch: comm::chan<T>) -> bool {
    as_raw_port(ch, {|x|peek_(x)})
}

#[doc = "Receive on a raw port pointer"]
fn recv_<T: send>(p: *rust_port) -> T {
    let yield = 0u;
    let yieldp = ptr::addr_of(yield);
    let mut res;
    res = rusti::init::<T>();
    rustrt::port_recv(ptr::addr_of(res) as *uint, p, yieldp);

    if yield != 0u {
        // Data isn't available yet, so res has not been initialized.
        task::yield();
    } else {
        // In the absence of compiler-generated preemption points
        // this is a good place to yield
        task::yield();
    }
    ret res;
}

fn peek_(p: *rust_port) -> bool unsafe {
    rustrt::rust_port_size(p) != 0u as libc::size_t
}

#[doc = "Receive on one of two ports"]
fn select2<A: send, B: send>(p_a: port<A>, p_b: port<B>)
    -> either<A, B> unsafe {
    let ports = [(**p_a).po, (**p_b).po];
    let n_ports = 2 as libc::size_t;
    let yield = 0u, yieldp = ptr::addr_of(yield);

    let mut resport: *rust_port;
    resport = rusti::init::<*rust_port>();
    vec::as_buf(ports) {|ports|
        rustrt::rust_port_select(ptr::addr_of(resport), ports, n_ports,
                                 yieldp);
    }

    if yield != 0u {
        // Wait for data
        task::yield();
    } else {
        // As in recv, this is a good place to yield anyway until
        // the compiler generates yield calls
        task::yield();
    }

    // Now we know the port we're supposed to receive from
    assert resport != ptr::null();

    if resport == (**p_a).po {
        either::left(recv(p_a))
    } else if resport == (**p_b).po {
        either::right(recv(p_b))
    } else {
        fail "unexpected result from rust_port_select";
    }
}

/* Implementation details */

enum rust_port {}

type port_id = int;

#[abi = "cdecl"]
native mod rustrt {
    fn rust_port_id_send(target_port: port_id, data: *()) -> libc::uintptr_t;

    fn new_port(unit_sz: libc::size_t) -> *rust_port;
    fn del_port(po: *rust_port);
    fn rust_port_begin_detach(po: *rust_port,
                              yield: *libc::uintptr_t);
    fn rust_port_end_detach(po: *rust_port);
    fn get_port_id(po: *rust_port) -> port_id;
    fn rust_port_size(po: *rust_port) -> libc::size_t;
    fn port_recv(dptr: *uint, po: *rust_port,
                 yield: *libc::uintptr_t);
    fn rust_port_select(dptr: **rust_port, ports: **rust_port,
                        n_ports: libc::size_t,
                        yield: *libc::uintptr_t);
    fn rust_port_take(port_id: port_id) -> *rust_port;
    fn rust_port_drop(p: *rust_port);
    fn rust_port_task(p: *rust_port) -> libc::uintptr_t;
    fn get_task_id() -> libc::uintptr_t;
}

#[abi = "rust-intrinsic"]
native mod rusti {
    fn init<T>() -> T;
}

/* Tests */

#[test]
fn create_port_and_chan() { let p = port::<int>(); chan(p); }

#[test]
fn send_int() {
    let p = port::<int>();
    let c = chan(p);
    send(c, 22);
}

#[test]
fn send_recv_fn() {
    let p = port::<int>();
    let c = chan::<int>(p);
    send(c, 42);
    assert (recv(p) == 42);
}

#[test]
fn send_recv_fn_infer() {
    let p = port();
    let c = chan(p);
    send(c, 42);
    assert (recv(p) == 42);
}

#[test]
fn chan_chan_infer() {
    let p = port(), p2 = port::<int>();
    let c = chan(p);
    send(c, chan(p2));
    recv(p);
}

#[test]
fn chan_chan() {
    let p = port::<chan<int>>(), p2 = port::<int>();
    let c = chan(p);
    send(c, chan(p2));
    recv(p);
}

#[test]
fn test_peek() {
    let po = port();
    let ch = chan(po);
    assert !peek(po);
    send(ch, ());
    assert peek(po);
    recv(po);
    assert !peek(po);
}

#[test]
fn test_select2_available() {
    let po_a = port();
    let po_b = port();
    let ch_a = chan(po_a);
    let ch_b = chan(po_b);

    send(ch_a, "a");

    assert select2(po_a, po_b) == either::left("a");

    send(ch_b, "b");

    assert select2(po_a, po_b) == either::right("b");
}

#[test]
fn test_select2_rendezvous() {
    let po_a = port();
    let po_b = port();
    let ch_a = chan(po_a);
    let ch_b = chan(po_b);

    iter::repeat(10u) {||
        task::spawn {||
            iter::repeat(10u) {|| task::yield() }
            send(ch_a, "a");
        };

        assert select2(po_a, po_b) == either::left("a");

        task::spawn {||
            iter::repeat(10u) {|| task::yield() }
            send(ch_b, "b");
        };

        assert select2(po_a, po_b) == either::right("b");
    }
}

#[test]
fn test_select2_stress() {
    let po_a = port();
    let po_b = port();
    let ch_a = chan(po_a);
    let ch_b = chan(po_b);

    let msgs = 100u;
    let times = 4u;

    iter::repeat(times) {||
        task::spawn {||
            iter::repeat(msgs) {||
                send(ch_a, "a")
            }
        };
        task::spawn {||
            iter::repeat(msgs) {||
                send(ch_b, "b")
            }
        };
    }

    let mut as = 0;
    let mut bs = 0;
    iter::repeat(msgs * times * 2u) {||
        alt check select2(po_a, po_b) {
          either::left("a") { as += 1 }
          either::right("b") { bs += 1 }
        }
    }

    assert as == 400;
    assert bs == 400;
}

#[test]
fn test_recv_chan() {
    let po = port();
    let ch = chan(po);
    send(ch, "flower");
    assert recv_chan(ch) == "flower";
}

#[test]
#[should_fail]
#[ignore(cfg(windows))]
fn test_recv_chan_dead() {
    let ch = chan(port());
    send(ch, "flower");
    recv_chan(ch);
}

#[test]
#[ignore(cfg(windows))]
fn test_recv_chan_wrong_task() {
    let po = port();
    let ch = chan(po);
    send(ch, "flower");
    assert result::is_failure(task::try {||
        recv_chan(ch)
    })
}

#[test]
fn test_port_send() {
    let po = port();
    po.send(());
    po.recv();
}

#[test]
fn test_chan_peek() {
    let po = port();
    let ch = po.chan();
    ch.send(());
    assert ch.peek();
}

#[test]
fn test_listen() {
    listen {|parent|
        task::spawn {||
            parent.send("oatmeal-salad");
        }
        assert parent.recv() == "oatmeal-salad";
    }
}

#[test]
#[ignore(cfg(windows))]
fn test_port_detach_fail() {
    iter::repeat(100u) {||
        let builder = task::builder();
        task::unsupervise(builder);
        task::run(builder) {||
            let po = port();
            let ch = po.chan();

            task::spawn {||
                fail;
            }

            task::spawn {||
                ch.send(());
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Simple [DEFLATE][def]-based compression. This is a wrapper around the
//! [`miniz`][mz] library, which is a one-file pure-C implementation of zlib.
//!
//! [def]: https://en.wikipedia.org/wiki/DEFLATE
//! [mz]: https://code.google.com/p/miniz/

#![crate_name = "flate"]
#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/",
       test(attr(deny(warnings))))]
#![cfg_attr(not(stage0), deny(warnings))]

#![feature(libc)]
#![feature(staged_api)]
#![feature(unique)]
#![cfg_attr(test, feature(rand))]

extern crate libc;

use libc::{c_int, c_void, size_t};
use std::fmt;
use std::ops::Deref;
use std::ptr::Unique;
use std::slice;

#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Error {
    _unused: (),
}

impl Error {
    fn new() -> Error {
        Error { _unused: () }
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        "decompression error".fmt(f)
    }
}

pub struct Bytes {
    ptr: Unique<u8>,
    len: usize,
}

impl Deref for Bytes {
    type Target = [u8];
    fn deref(&self) -> &[u8] {
        unsafe { slice::from_raw_parts(*self.ptr, self.len) }
    }
}

impl Drop for Bytes {
    fn drop(&mut self) {
        unsafe {
            libc::free(*self.ptr as *mut _);
        }
    }
}

#[link(name = "miniz", kind = "static")]
#[cfg(not(cargobuild))]
extern "C" {}

extern "C" {
    /// Raw miniz compression function.
    fn tdefl_compress_mem_to_heap(psrc_buf: *const c_void,
                                  src_buf_len: size_t,
                                  pout_len: *mut size_t,
                                  flags: c_int)
                                  -> *mut c_void;

    /// Raw miniz decompression function.
    fn tinfl_decompress_mem_to_heap(psrc_buf: *const c_void,
                                    src_buf_len: size_t,
                                    pout_len: *mut size_t,
                                    flags: c_int)
                                    -> *mut c_void;
}

const LZ_NORM: c_int = 0x80;  // LZ with 128 probes, "normal"
const TINFL_FLAG_PARSE_ZLIB_HEADER: c_int = 0x1; // parse zlib header and adler32 checksum
const TDEFL_WRITE_ZLIB_HEADER: c_int = 0x01000; // write zlib header and adler32 checksum

fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Bytes {
    unsafe {
        let mut outsz: size_t = 0;
        let res = tdefl_compress_mem_to_heap(bytes.as_ptr() as *const _,
                                             bytes.len() as size_t,
                                             &mut outsz,
                                             flags);
        assert!(!res.is_null());
        Bytes {
            ptr: Unique::new(res as *mut u8),
            len: outsz as usize,
        }
    }
}

/// Compress a buffer, without writing any sort of header on the output.
pub fn deflate_bytes(bytes: &[u8]) -> Bytes {
    deflate_bytes_internal(bytes, LZ_NORM)
}

/// Compress a buffer, using a header that zlib can understand.
pub fn deflate_bytes_zlib(bytes: &[u8]) -> Bytes {
    deflate_bytes_internal(bytes, LZ_NORM | TDEFL_WRITE_ZLIB_HEADER)
}

fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Result<Bytes, Error> {
    unsafe {
        let mut outsz: size_t = 0;
        let res = tinfl_decompress_mem_to_heap(bytes.as_ptr() as *const _,
                                               bytes.len() as size_t,
                                               &mut outsz,
                                               flags);
        if !res.is_null() {
            Ok(Bytes {
                ptr: Unique::new(res as *mut u8),
                len: outsz as usize,
            })
        } else {
            Err(Error::new())
        }
    }
}

/// Decompress a buffer, without parsing any sort of header on the input.
pub fn inflate_bytes(bytes: &[u8]) -> Result<Bytes, Error> {
    inflate_bytes_internal(bytes, 0)
}

/// Decompress a buffer that starts with a zlib header.
pub fn inflate_bytes_zlib(bytes: &[u8]) -> Result<Bytes, Error> {
    inflate_bytes_internal(bytes, TINFL_FLAG_PARSE_ZLIB_HEADER)
}

#[cfg(test)]
mod tests {
    #![allow(deprecated)]
    use super::{deflate_bytes, inflate_bytes};
    use std::__rand::{Rng, thread_rng};

    #[test]
    fn test_flate_round_trip() {
        let mut r = thread_rng();
        let mut words = vec![];
        for _ in 0..20 {
            let range = r.gen_range(1, 10);
            let v = r.gen_iter::<u8>().take(range).collect::<Vec<u8>>();
            words.push(v);
        }
        for _ in 0..20 {
            let mut input = vec![];
            for _ in 0..2000 {
                input.extend_from_slice(r.choose(&words).unwrap());
            }
            let cmp = deflate_bytes(&input);
            let out = inflate_bytes(&cmp).unwrap();
            assert_eq!(&*input, &*out);
        }
    }

    #[test]
    fn test_zlib_flate() {
        let bytes = vec![1, 2, 3, 4, 5];
        let deflated = deflate_bytes(&bytes);
        let inflated = inflate_bytes(&deflated).unwrap();
        assert_eq!(&*inflated, &*bytes);
    }
}
<commit_msg>Auto merge of #37298 - nnethercote:faster-deflate, r=alexcrichton<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Simple [DEFLATE][def]-based compression. This is a wrapper around the
//! [`miniz`][mz] library, which is a one-file pure-C implementation of zlib.
//!
//! [def]: https://en.wikipedia.org/wiki/DEFLATE
//! [mz]: https://code.google.com/p/miniz/

#![crate_name = "flate"]
#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/",
       test(attr(deny(warnings))))]
#![cfg_attr(not(stage0), deny(warnings))]

#![feature(libc)]
#![feature(staged_api)]
#![feature(unique)]
#![cfg_attr(test, feature(rand))]

extern crate libc;

use libc::{c_int, c_void, size_t};
use std::fmt;
use std::ops::Deref;
use std::ptr::Unique;
use std::slice;

#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Error {
    _unused: (),
}

impl Error {
    fn new() -> Error {
        Error { _unused: () }
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        "decompression error".fmt(f)
    }
}

pub struct Bytes {
    ptr: Unique<u8>,
    len: usize,
}

impl Deref for Bytes {
    type Target = [u8];
    fn deref(&self) -> &[u8] {
        unsafe { slice::from_raw_parts(*self.ptr, self.len) }
    }
}

impl Drop for Bytes {
    fn drop(&mut self) {
        unsafe {
            libc::free(*self.ptr as *mut _);
        }
    }
}

#[link(name = "miniz", kind = "static")]
#[cfg(not(cargobuild))]
extern "C" {}

extern "C" {
    /// Raw miniz compression function.
    fn tdefl_compress_mem_to_heap(psrc_buf: *const c_void,
                                  src_buf_len: size_t,
                                  pout_len: *mut size_t,
                                  flags: c_int)
                                  -> *mut c_void;

    /// Raw miniz decompression function.
    fn tinfl_decompress_mem_to_heap(psrc_buf: *const c_void,
                                    src_buf_len: size_t,
                                    pout_len: *mut size_t,
                                    flags: c_int)
                                    -> *mut c_void;
}

const LZ_FAST: c_int = 0x01;  // LZ with 1 probe, "fast"
const TDEFL_GREEDY_PARSING_FLAG: c_int = 0x04000; // fast greedy parsing instead of lazy parsing

/// Compress a buffer without writing any sort of header on the output. Fast
/// compression is used because it is almost twice as fast as default
/// compression and the compression ratio is only marginally worse.
pub fn deflate_bytes(bytes: &[u8]) -> Bytes {
    let flags = LZ_FAST | TDEFL_GREEDY_PARSING_FLAG;
    unsafe {
        let mut outsz: size_t = 0;
        let res = tdefl_compress_mem_to_heap(bytes.as_ptr() as *const _,
                                             bytes.len() as size_t,
                                             &mut outsz,
                                             flags);
        assert!(!res.is_null());
        Bytes {
            ptr: Unique::new(res as *mut u8),
            len: outsz as usize,
        }
    }
}

/// Decompress a buffer without parsing any sort of header on the input.
pub fn inflate_bytes(bytes: &[u8]) -> Result<Bytes, Error> {
    let flags = 0;
    unsafe {
        let mut outsz: size_t = 0;
        let res = tinfl_decompress_mem_to_heap(bytes.as_ptr() as *const _,
                                               bytes.len() as size_t,
                                               &mut outsz,
                                               flags);
        if !res.is_null() {
            Ok(Bytes {
                ptr: Unique::new(res as *mut u8),
                len: outsz as usize,
            })
        } else {
            Err(Error::new())
        }
    }
}

#[cfg(test)]
mod tests {
    #![allow(deprecated)]
    use super::{deflate_bytes, inflate_bytes};
    use std::__rand::{Rng, thread_rng};

    #[test]
    fn test_flate_round_trip() {
        let mut r = thread_rng();
        let mut words = vec![];
        for _ in 0..20 {
            let range = r.gen_range(1, 10);
            let v = r.gen_iter::<u8>().take(range).collect::<Vec<u8>>();
            words.push(v);
        }
        for _ in 0..20 {
            let mut input = vec![];
            for _ in 0..2000 {
                input.extend_from_slice(r.choose(&words).unwrap());
            }
            let cmp = deflate_bytes(&input);
            let out = inflate_bytes(&cmp).unwrap();
            assert_eq!(&*input, &*out);
        }
    }

    #[test]
    fn test_zlib_flate() {
        let bytes = vec![1, 2, 3, 4, 5];
        let deflated = deflate_bytes(&bytes);
        let inflated = inflate_bytes(&deflated).unwrap();
        assert_eq!(&*inflated, &*bytes);
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use core::container::{Container, Mutable};
use core::cmp::Eq;
use core::prelude::*;
use core::uint;
use core::vec;

const initial_capacity: uint = 32u; // 2^5

pub struct Deque<T> {
    priv nelts: uint,
    priv lo: uint,
    priv hi: uint,
    priv elts: ~[Option<T>]
}

impl<T> Container for Deque<T> {
    pure fn len(&self) -> uint { self.nelts }
    pure fn is_empty(&self) -> bool { self.len() == 0 }
}

impl<T> Mutable for Deque<T> {
    fn clear(&mut self) {
        for vec::each_mut(self.elts) |x| { *x = None }
        self.nelts = 0;
        self.lo = 0;
        self.hi = 0;
    }
}

impl<T: Copy> Deque<T> {
    static pure fn new() -> Deque<T> {
        Deque{nelts: 0, lo: 0, hi: 0,
              elts: vec::from_fn(initial_capacity, |_| None)}
    }

    fn add_front(&mut self, t: T) {
        let oldlo: uint = self.lo;
        if self.lo == 0u {
            self.lo = self.elts.len() - 1u;
        } else { self.lo -= 1u; }
        if self.lo == self.hi {
            self.elts = grow(self.nelts, oldlo, self.elts);
            self.lo = self.elts.len() - 1u;
            self.hi = self.nelts;
        }
        self.elts[self.lo] = Some(t);
        self.nelts += 1u;
    }

    fn add_back(&mut self, t: T) {
        if self.lo == self.hi && self.nelts != 0u {
            self.elts = grow(self.nelts, self.lo, self.elts);
            self.lo = 0u;
            self.hi = self.nelts;
        }
        self.elts[self.hi] = Some(t);
        self.hi = (self.hi + 1u) % self.elts.len();
        self.nelts += 1u;
    }

    fn pop_front(&mut self) -> T {
        let t: T = get(self.elts, self.lo);
        self.elts[self.lo] = None;
        self.lo = (self.lo + 1u) % self.elts.len();
        self.nelts -= 1u;
        t
    }

    fn pop_back(&mut self) -> T {
        if self.hi == 0u {
            self.hi = self.elts.len() - 1u;
        } else { self.hi -= 1u; }
        let t: T = get(self.elts, self.hi);
        self.elts[self.hi] = None;
        self.nelts -= 1u;
        t
    }

    fn peek_front(&self) -> T { get(self.elts, self.lo) }

    fn peek_back(&self) -> T { get(self.elts, self.hi - 1u) }

    fn get(&self, i: int) -> T {
        let idx = (self.lo + (i as uint)) % self.elts.len();
        get(self.elts, idx)
    }
}

/// Grow is only called on full elts, so nelts is also len(elts), unlike
/// elsewhere.
fn grow<T: Copy>(nelts: uint, lo: uint, elts: &[Option<T>]) -> ~[Option<T>] {
    assert nelts == elts.len();
    let mut rv = ~[];

    let mut i = 0u;
    let nalloc = uint::next_power_of_two(nelts + 1u);
    while i < nalloc {
        if i < nelts {
            rv.push(elts[(lo + i) % nelts]);
        } else { rv.push(None); }
        i += 1u;
    }

    rv
}

fn get<T: Copy>(elts: &[Option<T>], i: uint) -> T {
    match elts[i] { Some(t) => t, _ => fail!() }
}

#[cfg(test)]
mod tests {
    use core::prelude::*;
    use super::*;

    #[test]
    fn test_simple() {
        let mut d = Deque::new();
        assert (d.len() == 0u);
        d.add_front(17);
        d.add_front(42);
        d.add_back(137);
        assert (d.len() == 3u);
        d.add_back(137);
        assert (d.len() == 4u);
        log(debug, d.peek_front());
        assert (d.peek_front() == 42);
        log(debug, d.peek_back());
        assert (d.peek_back() == 137);
        let mut i: int = d.pop_front();
        log(debug, i);
        assert (i == 42);
        i = d.pop_back();
        log(debug, i);
        assert (i == 137);
        i = d.pop_back();
        log(debug, i);
        assert (i == 137);
        i = d.pop_back();
        log(debug, i);
        assert (i == 17);
        assert (d.len() == 0u);
        d.add_back(3);
        assert (d.len() == 1u);
        d.add_front(2);
        assert (d.len() == 2u);
        d.add_back(4);
        assert (d.len() == 3u);
        d.add_front(1);
        assert (d.len() == 4u);
        log(debug, d.get(0));
        log(debug, d.get(1));
        log(debug, d.get(2));
        log(debug, d.get(3));
        assert (d.get(0) == 1);
        assert (d.get(1) == 2);
        assert (d.get(2) == 3);
        assert (d.get(3) == 4);
    }

    #[test]
    fn test_boxes() {
        let a: @int = @5;
        let b: @int = @72;
        let c: @int = @64;
        let d: @int = @175;

        let mut deq = Deque::new();
        assert (deq.len() == 0u);
        deq.add_front(a);
        deq.add_front(b);
        deq.add_back(c);
        assert (deq.len() == 3u);
        deq.add_back(d);
        assert (deq.len() == 4u);
        assert (deq.peek_front() == b);
        assert (deq.peek_back() == d);
        assert (deq.pop_front() == b);
        assert (deq.pop_back() == d);
        assert (deq.pop_back() == c);
        assert (deq.pop_back() == a);
        assert (deq.len() == 0u);
        deq.add_back(c);
        assert (deq.len() == 1u);
        deq.add_front(b);
        assert (deq.len() == 2u);
        deq.add_back(d);
        assert (deq.len() == 3u);
        deq.add_front(a);
        assert (deq.len() == 4u);
        assert (deq.get(0) == a);
        assert (deq.get(1) == b);
        assert (deq.get(2) == c);
        assert (deq.get(3) == d);
    }

    fn test_parameterized<T: Copy Eq Durable>(a: T, b: T, c: T, d: T) {
        let mut deq = Deque::new();
        assert (deq.len() == 0u);
        deq.add_front(a);
        deq.add_front(b);
        deq.add_back(c);
        assert (deq.len() == 3u);
        deq.add_back(d);
        assert (deq.len() == 4u);
        assert deq.peek_front() == b;
        assert deq.peek_back() == d;
        assert deq.pop_front() == b;
        assert deq.pop_back() == d;
        assert deq.pop_back() == c;
        assert deq.pop_back() == a;
        assert (deq.len() == 0u);
        deq.add_back(c);
        assert (deq.len() == 1u);
        deq.add_front(b);
        assert (deq.len() == 2u);
        deq.add_back(d);
        assert (deq.len() == 3u);
        deq.add_front(a);
        assert (deq.len() == 4u);
        assert deq.get(0) == a;
        assert deq.get(1) == b;
        assert deq.get(2) == c;
        assert deq.get(3) == d;
    }

    #[deriving_eq]
    enum Taggy { One(int), Two(int, int), Three(int, int, int), }

    #[deriving_eq]
    enum Taggypar<T> {
        Onepar(int), Twopar(int, int), Threepar(int, int, int),
    }

    #[deriving_eq]
    struct RecCy {
        x: int,
        y: int,
        t: Taggy
    }

    #[test]
    fn test_param_int() {
        test_parameterized::<int>(5, 72, 64, 175);
    }

    #[test]
    fn test_param_at_int() {
        test_parameterized::<@int>(@5, @72, @64, @175);
    }

    #[test]
    fn test_param_taggy() {
        test_parameterized::<Taggy>(One(1), Two(1, 2), Three(1, 2, 3),
                                    Two(17, 42));
    }

    #[test]
    fn test_param_taggypar() {
        test_parameterized::<Taggypar<int>>(Onepar::<int>(1),
                                            Twopar::<int>(1, 2),
                                            Threepar::<int>(1, 2, 3),
                                            Twopar::<int>(17, 42));
    }

    #[test]
    fn test_param_reccy() {
        let reccy1 = RecCy { x: 1, y: 2, t: One(1) };
        let reccy2 = RecCy { x: 345, y: 2, t: Two(1, 2) };
        let reccy3 = RecCy { x: 1, y: 777, t: Three(1, 2, 3) };
        let reccy4 = RecCy { x: 19, y: 252, t: Two(17, 42) };
        test_parameterized::<RecCy>(reccy1, reccy2, reccy3, reccy4);
    }
}
<commit_msg>deque: separate the methods that need Copy<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use core::container::{Container, Mutable};
use core::cmp::Eq;
use core::prelude::*;
use core::uint;
use core::vec;

const initial_capacity: uint = 32u; // 2^5

pub struct Deque<T> {
    priv nelts: uint,
    priv lo: uint,
    priv hi: uint,
    priv elts: ~[Option<T>]
}

impl<T> Container for Deque<T> {
    pure fn len(&self) -> uint { self.nelts }
    pure fn is_empty(&self) -> bool { self.len() == 0 }
}

impl<T> Mutable for Deque<T> {
    fn clear(&mut self) {
        for vec::each_mut(self.elts) |x| { *x = None }
        self.nelts = 0;
        self.lo = 0;
        self.hi = 0;
    }
}

impl<T> Deque<T> {
    static pure fn new() -> Deque<T> {
        Deque{nelts: 0, lo: 0, hi: 0,
              elts: vec::from_fn(initial_capacity, |_| None)}
    }
}

impl<T: Copy> Deque<T> {
    fn add_front(&mut self, t: T) {
        let oldlo: uint = self.lo;
        if self.lo == 0u {
            self.lo = self.elts.len() - 1u;
        } else { self.lo -= 1u; }
        if self.lo == self.hi {
            self.elts = grow(self.nelts, oldlo, self.elts);
            self.lo = self.elts.len() - 1u;
            self.hi = self.nelts;
        }
        self.elts[self.lo] = Some(t);
        self.nelts += 1u;
    }

    fn add_back(&mut self, t: T) {
        if self.lo == self.hi && self.nelts != 0u {
            self.elts = grow(self.nelts, self.lo, self.elts);
            self.lo = 0u;
            self.hi = self.nelts;
        }
        self.elts[self.hi] = Some(t);
        self.hi = (self.hi + 1u) % self.elts.len();
        self.nelts += 1u;
    }

    fn pop_front(&mut self) -> T {
        let t: T = get(self.elts, self.lo);
        self.elts[self.lo] = None;
        self.lo = (self.lo + 1u) % self.elts.len();
        self.nelts -= 1u;
        t
    }

    fn pop_back(&mut self) -> T {
        if self.hi == 0u {
            self.hi = self.elts.len() - 1u;
        } else { self.hi -= 1u; }
        let t: T = get(self.elts, self.hi);
        self.elts[self.hi] = None;
        self.nelts -= 1u;
        t
    }

    fn peek_front(&self) -> T { get(self.elts, self.lo) }

    fn peek_back(&self) -> T { get(self.elts, self.hi - 1u) }

    fn get(&self, i: int) -> T {
        let idx = (self.lo + (i as uint)) % self.elts.len();
        get(self.elts, idx)
    }
}

/// Grow is only called on full elts, so nelts is also len(elts), unlike
/// elsewhere.
fn grow<T: Copy>(nelts: uint, lo: uint, elts: &[Option<T>]) -> ~[Option<T>] {
    assert nelts == elts.len();
    let mut rv = ~[];

    let mut i = 0u;
    let nalloc = uint::next_power_of_two(nelts + 1u);
    while i < nalloc {
        if i < nelts {
            rv.push(elts[(lo + i) % nelts]);
        } else { rv.push(None); }
        i += 1u;
    }

    rv
}

fn get<T: Copy>(elts: &[Option<T>], i: uint) -> T {
    match elts[i] { Some(t) => t, _ => fail!() }
}

#[cfg(test)]
mod tests {
    use core::prelude::*;
    use super::*;

    #[test]
    fn test_simple() {
        let mut d = Deque::new();
        assert (d.len() == 0u);
        d.add_front(17);
        d.add_front(42);
        d.add_back(137);
        assert (d.len() == 3u);
        d.add_back(137);
        assert (d.len() == 4u);
        log(debug, d.peek_front());
        assert (d.peek_front() == 42);
        log(debug, d.peek_back());
        assert (d.peek_back() == 137);
        let mut i: int = d.pop_front();
        log(debug, i);
        assert (i == 42);
        i = d.pop_back();
        log(debug, i);
        assert (i == 137);
        i = d.pop_back();
        log(debug, i);
        assert (i == 137);
        i = d.pop_back();
        log(debug, i);
        assert (i == 17);
        assert (d.len() == 0u);
        d.add_back(3);
        assert (d.len() == 1u);
        d.add_front(2);
        assert (d.len() == 2u);
        d.add_back(4);
        assert (d.len() == 3u);
        d.add_front(1);
        assert (d.len() == 4u);
        log(debug, d.get(0));
        log(debug, d.get(1));
        log(debug, d.get(2));
        log(debug, d.get(3));
        assert (d.get(0) == 1);
        assert (d.get(1) == 2);
        assert (d.get(2) == 3);
        assert (d.get(3) == 4);
    }

    #[test]
    fn test_boxes() {
        let a: @int = @5;
        let b: @int = @72;
        let c: @int = @64;
        let d: @int = @175;

        let mut deq = Deque::new();
        assert (deq.len() == 0u);
        deq.add_front(a);
        deq.add_front(b);
        deq.add_back(c);
        assert (deq.len() == 3u);
        deq.add_back(d);
        assert (deq.len() == 4u);
        assert (deq.peek_front() == b);
        assert (deq.peek_back() == d);
        assert (deq.pop_front() == b);
        assert (deq.pop_back() == d);
        assert (deq.pop_back() == c);
        assert (deq.pop_back() == a);
        assert (deq.len() == 0u);
        deq.add_back(c);
        assert (deq.len() == 1u);
        deq.add_front(b);
        assert (deq.len() == 2u);
        deq.add_back(d);
        assert (deq.len() == 3u);
        deq.add_front(a);
        assert (deq.len() == 4u);
        assert (deq.get(0) == a);
        assert (deq.get(1) == b);
        assert (deq.get(2) == c);
        assert (deq.get(3) == d);
    }

    fn test_parameterized<T: Copy Eq Durable>(a: T, b: T, c: T, d: T) {
        let mut deq = Deque::new();
        assert (deq.len() == 0u);
        deq.add_front(a);
        deq.add_front(b);
        deq.add_back(c);
        assert (deq.len() == 3u);
        deq.add_back(d);
        assert (deq.len() == 4u);
        assert deq.peek_front() == b;
        assert deq.peek_back() == d;
        assert deq.pop_front() == b;
        assert deq.pop_back() == d;
        assert deq.pop_back() == c;
        assert deq.pop_back() == a;
        assert (deq.len() == 0u);
        deq.add_back(c);
        assert (deq.len() == 1u);
        deq.add_front(b);
        assert (deq.len() == 2u);
        deq.add_back(d);
        assert (deq.len() == 3u);
        deq.add_front(a);
        assert (deq.len() == 4u);
        assert deq.get(0) == a;
        assert deq.get(1) == b;
        assert deq.get(2) == c;
        assert deq.get(3) == d;
    }

    #[deriving_eq]
    enum Taggy { One(int), Two(int, int), Three(int, int, int), }

    #[deriving_eq]
    enum Taggypar<T> {
        Onepar(int), Twopar(int, int), Threepar(int, int, int),
    }

    #[deriving_eq]
    struct RecCy {
        x: int,
        y: int,
        t: Taggy
    }

    #[test]
    fn test_param_int() {
        test_parameterized::<int>(5, 72, 64, 175);
    }

    #[test]
    fn test_param_at_int() {
        test_parameterized::<@int>(@5, @72, @64, @175);
    }

    #[test]
    fn test_param_taggy() {
        test_parameterized::<Taggy>(One(1), Two(1, 2), Three(1, 2, 3),
                                    Two(17, 42));
    }

    #[test]
    fn test_param_taggypar() {
        test_parameterized::<Taggypar<int>>(Onepar::<int>(1),
                                            Twopar::<int>(1, 2),
                                            Threepar::<int>(1, 2, 3),
                                            Twopar::<int>(17, 42));
    }

    #[test]
    fn test_param_reccy() {
        let reccy1 = RecCy { x: 1, y: 2, t: One(1) };
        let reccy2 = RecCy { x: 345, y: 2, t: Two(1, 2) };
        let reccy3 = RecCy { x: 1, y: 777, t: Three(1, 2, 3) };
        let reccy4 = RecCy { x: 19, y: 252, t: Two(17, 42) };
        test_parameterized::<RecCy>(reccy1, reccy2, reccy3, reccy4);
    }
}
<|endoftext|>


<commit_before>//Patterned Pixel Grouping Interpolation by Alain Desbiolles
pub fn ppg_interpolate(img: &Image) -> Vec<f32> {
  let mut out: Vec<f32> = vec![0; (img.width*img.height*4) as usize];

  let dir: [i32; 5] = { 1, img.width, -1, -img.width, 1 };
  int row, col, diff[2], guess[2], c, d, i;
  ushort (*pix)[4];

  {
    // First interpolate just the borders
    border_interpolate(3, img, &mut out);
  }

  /*  Fill in the green layer with gradients and pattern recognition: */
  for (row=3; row < height-3; row++)
    for (col=3+(FC(row,3) & 1), c=FC(row,col); col < width-3; col+=2) {
      pix = image + row*width+col;
      for (i=0; (d=dir[i]) > 0; i++) {
        guess[i] = (pix[-d][1] + pix[0][c] + pix[d][1]) * 2
                      - pix[-2*d][c] - pix[2*d][c];
        diff[i] = ( ABS(pix[-2*d][c] - pix[ 0][c]) +
                    ABS(pix[ 2*d][c] - pix[ 0][c]) +
                    ABS(pix[  -d][1] - pix[ d][1]) ) * 3 +
                  ( ABS(pix[ 3*d][1] - pix[ d][1]) +
                    ABS(pix[-3*d][1] - pix[-d][1]) ) * 2;
      }
      d = dir[i = diff[0] > diff[1]];
      pix[0][1] = ULIM(guess[i] >> 2, pix[d][1], pix[-d][1]);
    }
/*  Calculate red and blue for each green pixel:                */
  for (row=1; row < height-1; row++)
    for (col=1+(FC(row,2) & 1), c=FC(row,col+1); col < width-1; col+=2) {
      pix = image + row*width+col;
      for (i=0; (d=dir[i]) > 0; c=2-c, i++)
        pix[0][c] = CLIP((pix[-d][c] + pix[d][c] + 2*pix[0][1]
                        - pix[-d][1] - pix[d][1]) >> 1);
    }
/*  Calculate blue for red pixels and vice versa:                */
  for (row=1; row < height-1; row++)
    for (col=1+(FC(row,1) & 1), c=2-FC(row,col); col < width-1; col+=2) {
      pix = image + row*width+col;
      for (i=0; (d=dir[i]+dir[i+1]) > 0; i++) {
        diff[i] = ABS(pix[-d][c] - pix[d][c]) +
                  ABS(pix[-d][1] - pix[0][1]) +
                  ABS(pix[ d][1] - pix[0][1]);
        guess[i] = pix[-d][c] + pix[d][c] + 2*pix[0][1]
                 - pix[-d][1] - pix[d][1];
      }
      if (diff[0] != diff[1])
        pix[0][c] = CLIP(guess[diff[0] > diff[1]] >> 1);
      else
        pix[0][c] = CLIP((guess[0]+guess[1]) >> 2);
    }
}

<commit_msg>Remove leftover code<commit_after><|endoftext|>


<commit_before>extern crate time;
extern crate rusqlite;

pub struct Db {
    db: rusqlite::Connection
}

#[derive(Debug,Clone,RustcEncodable)]
pub struct Image {
    pub id: i32,
    pub name: String,
    pub tags: Vec<String>,
    pub got_from: String,
    pub original_link: String,
    pub rating: char
}

#[derive(Debug,Clone)]
enum AnyWith {
    After(String),
    Before(String)
}

#[derive(Debug,Clone)]
enum Tag {
    Include(String),
    Exclude(String),
    Rating(Vec<String>),
    AnyWith(AnyWith),
    From(Vec<String>)
}

use self::rusqlite::{Result as SQLResult, Row};

impl Db {
    pub fn new() -> Db {
        use self::rusqlite::Connection;
        use std::path::Path;

        let conn = Connection::open(Path::new("db.db")).unwrap();
        conn.execute("CREATE TABLE IF NOT EXISTS images(
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    name TEXT NOT NULL UNIQUE,
                    tags TEXT NOT NULL,

                    got_from TEXT,
                    original_link TEXT,
                    rating CHAR);",&[]).unwrap();
        Db{
            db: conn
        }
    }

    pub fn add_with_tags_name(&self, tags: &[String], ext: &str) -> SQLResult<String> {
        let mut name = tags.join("_").replace("'","''");
        name.push_str(ext);
        try!(self.add_image(&name, tags, None, None, None));
        Ok(name)
    }

    pub fn add_image<'a, T1: Into<Option<&'a str>>,
    T2: Into<Option<&'a str>>,
    C: Into<Option<char>>>(&self, name: &str, tags: &[String], got_from: T1, original_link: T2, rating: C) -> SQLResult<()> {
        let mut fields = "INSERT INTO images (name, tags".to_string();
        let mut values = format!("VALUES('{}', '{}'", name, format!(",{},",tags.join(",").replace("'","''")));
        if let Some(x) = got_from.into() {
            fields.push_str(", got_from");
            values.push_str(&format!(", '{}'", x));
        }
        if let Some(x) = original_link.into() {
            fields.push_str(", original_link");
            values.push_str(&format!(", '{}'", x));
        }
        if let Some(x) = rating.into() {
            fields.push_str(", rating");
            values.push_str(&format!(", '{}'", x));
        }

        fields.push_str(")");
        values.push_str(")");

        let q = format!("{} {}", fields, values);
        self.db.execute(&q, &[]).unwrap();
        Ok(())
    }

    fn extract_all(row: Row) -> Image {
        let id = row.get(0);
        let name = row.get(1);
        let mut tags = row.get::<i32,String>(2).split(',').map(|x| x.to_string()).collect::<Vec<_>>();
        let l = tags.len()-2;
        tags.remove(0); tags.remove(l);

        let got_from = row.get::<i32, Option<String>>(3).unwrap_or(" ".to_string());
        let original_link = row.get::<i32,Option<String>>(4).unwrap_or(" ".to_string());
        let rating = row.get::<i32,Option<String>>(5).unwrap_or(" ".to_string()).chars().nth(0).unwrap_or(' ');

        Image{
            id: id,
            name: name,
            tags: tags,
            got_from: got_from,
            original_link: original_link,
            rating: rating
        }
    }

    fn extract_all_ref(row: &Row) -> Image {
        let id = row.get(0);
        let name = row.get(1);
        let mut tags = row.get::<i32,String>(2).split(',').map(|x| x.to_string()).collect::<Vec<_>>();
        let l = tags.len()-2;
        tags.remove(0); tags.remove(l);

        let got_from = row.get::<i32, Option<String>>(3).unwrap_or(" ".to_string());
        let original_link = row.get::<i32,Option<String>>(4).unwrap_or(" ".to_string());
        let rating = row.get::<i32,Option<String>>(5).unwrap_or(" ".to_string()).chars().nth(0).unwrap_or(' ');

        Image{
            id: id,
            name: name,
            tags: tags,
            got_from: got_from,
            original_link: original_link,
            rating: rating
        }
    }

    pub fn get_image(&self, id: i32) -> SQLResult<Image> {
        self.db.query_row("SELECT * FROM images WHERE id = ?", &[&id], Db::extract_all)
    }

    pub fn get_images<T: Into<Option<i32>>>(&self, take: T, skip: usize) -> SQLResult<Vec<Image>>{
        let take = match take.into() {
            Some(x) => x,
            None    => -1
        };

        let mut st = try!(self.db.prepare(&format!("SELECT * FROM images LIMIT {} OFFSET {}", take, skip)));
        let st = try!(st.query_map(&[], Db::extract_all_ref)).map(|x| x.unwrap());
        Ok(st.collect::<Vec<_>>())
    }

    pub fn by_tags<T: Into<Option<i32>>>(&self, take: T, skip: usize, tags: &[String]) -> SQLResult<Vec<Image>> {
        let tags = tags.iter().map(|x| parse_tag(&x.replace("_",r"\_").replace("%", r"\%").replace("'", "''"))).collect::<Vec<_>>();

        let q = tags.iter().map(|t| {
            match *t {
                Tag::Include(ref incl) => format!(r"tags LIKE '%,{},%' ESCAPE '\'", incl),
                Tag::Exclude(ref excl) => format!(r"tags NOT LIKE '%,{},%' ESCAPE '\'", excl),
                Tag::AnyWith(ref x) => match *x {
                    AnyWith::Before(ref bef) => format!(r"tags LIKE '%,{}%,%' ESCAPE '\'", bef),
                    AnyWith::After(ref aft) => format!(r"tags LIKE '%,%{},%' ESCAPE '\'", aft),
                },
                Tag::Rating(ref r) => {
                    let mut s = "(".to_string();
                    for tg in r {
                        s.push_str(&format!("rating = '{}' OR ", tg))
                    }
                    let _ = (0..4).inspect(|_| {s.pop(); }).collect::<Vec<_>>();
                    s.push_str(")");

                    s
                },

                Tag::From(ref f) => {
                    let mut s = "(".to_string();
                    for tg in f {
                        s.push_str(&format!("got_from = '{}' OR ", tg))
                    }
                    let _ = (0..4).inspect(|_| {s.pop(); }).collect::<Vec<_>>();
                    s.push_str(")");

                    s
                }
            }
        }).collect::<Vec<_>>().join(" AND ");

        let take = match take.into() {
            Some(x) => x,
            None    => -1
        };

        let mut st = try!(self.db.prepare(&format!("SELECT * FROM images WHERE {} LIMIT {} OFFSET {}", q, take, skip)));
        let st = try!(st.query_map(&[], Db::extract_all_ref)).map(|x| x.unwrap());
        Ok(st.collect::<Vec<_>>())
    }
}

fn parse_tag(tag: &str) -> Tag {
    if tag.starts_with("rating") {
        let tag = tag.split("rating:").collect::<Vec<_>>()[1];
        Tag::Rating(tag.split(',').map(|x| x.to_string()).collect::<Vec<_>>())
    } else if tag.starts_with("from") {
        let tag = tag.split("from:").collect::<Vec<_>>()[1];
        Tag::From(tag.split(',').map(|x| x.to_string()).collect::<Vec<_>>())
    } else if tag.starts_with('-') {
        Tag::Exclude(tag[1..].to_string())
    } else if tag.starts_with('*') {
        Tag::AnyWith(AnyWith::After(tag[1..].to_string()))
    } else if tag.ends_with('*') {
        let mut n = tag.to_string();
        n.pop();
        Tag::AnyWith(AnyWith::Before(n))
    } else {
        Tag::Include(tag.to_string())
    }
}
<commit_msg>try! -> ?<commit_after>extern crate time;
extern crate rusqlite;

pub struct Db {
    db: rusqlite::Connection
}

#[derive(Debug,Clone,RustcEncodable)]
pub struct Image {
    pub id: i32,
    pub name: String,
    pub tags: Vec<String>,
    pub got_from: String,
    pub original_link: String,
    pub rating: char
}

#[derive(Debug,Clone)]
enum AnyWith {
    After(String),
    Before(String)
}

#[derive(Debug,Clone)]
enum Tag {
    Include(String),
    Exclude(String),
    Rating(Vec<String>),
    AnyWith(AnyWith),
    From(Vec<String>)
}

use self::rusqlite::{Result as SQLResult, Row};

impl Db {
    pub fn new() -> Db {
        use self::rusqlite::Connection;
        use std::path::Path;

        let conn = Connection::open(Path::new("db.db")).unwrap();
        conn.execute("CREATE TABLE IF NOT EXISTS images(
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    name TEXT NOT NULL UNIQUE,
                    tags TEXT NOT NULL,

                    got_from TEXT,
                    original_link TEXT,
                    rating CHAR);",&[]).unwrap();
        Db{
            db: conn
        }
    }

    pub fn add_with_tags_name(&self, tags: &[String], ext: &str) -> SQLResult<String> {
        let mut name = tags.join("_").replace("'","''");
        name.push_str(ext);
        self.add_image(&name, tags, None, None, None)?;
        Ok(name)
    }

    pub fn add_image<'a, T1: Into<Option<&'a str>>,
    T2: Into<Option<&'a str>>,
    C: Into<Option<char>>>(&self, name: &str, tags: &[String], got_from: T1, original_link: T2, rating: C) -> SQLResult<()> {
        let mut fields = "INSERT INTO images (name, tags".to_string();
        let mut values = format!("VALUES('{}', '{}'", name, format!(",{},",tags.join(",").replace("'","''")));
        if let Some(x) = got_from.into() {
            fields.push_str(", got_from");
            values.push_str(&format!(", '{}'", x));
        }
        if let Some(x) = original_link.into() {
            fields.push_str(", original_link");
            values.push_str(&format!(", '{}'", x));
        }
        if let Some(x) = rating.into() {
            fields.push_str(", rating");
            values.push_str(&format!(", '{}'", x));
        }

        fields.push_str(")");
        values.push_str(")");

        let q = format!("{} {}", fields, values);
        self.db.execute(&q, &[]).unwrap();
        Ok(())
    }

    fn extract_all(row: Row) -> Image {
        let id = row.get(0);
        let name = row.get(1);
        let mut tags = row.get::<i32,String>(2).split(',').map(|x| x.to_string()).collect::<Vec<_>>();
        let l = tags.len()-2;
        tags.remove(0); tags.remove(l);

        let got_from = row.get::<i32, Option<String>>(3).unwrap_or(" ".to_string());
        let original_link = row.get::<i32,Option<String>>(4).unwrap_or(" ".to_string());
        let rating = row.get::<i32,Option<String>>(5).unwrap_or(" ".to_string()).chars().nth(0).unwrap_or(' ');

        Image{
            id: id,
            name: name,
            tags: tags,
            got_from: got_from,
            original_link: original_link,
            rating: rating
        }
    }

    fn extract_all_ref(row: &Row) -> Image {
        let id = row.get(0);
        let name = row.get(1);
        let mut tags = row.get::<i32,String>(2).split(',').map(|x| x.to_string()).collect::<Vec<_>>();
        let l = tags.len()-2;
        tags.remove(0); tags.remove(l);

        let got_from = row.get::<i32, Option<String>>(3).unwrap_or(" ".to_string());
        let original_link = row.get::<i32,Option<String>>(4).unwrap_or(" ".to_string());
        let rating = row.get::<i32,Option<String>>(5).unwrap_or(" ".to_string()).chars().nth(0).unwrap_or(' ');

        Image{
            id: id,
            name: name,
            tags: tags,
            got_from: got_from,
            original_link: original_link,
            rating: rating
        }
    }

    pub fn get_image(&self, id: i32) -> SQLResult<Image> {
        self.db.query_row("SELECT * FROM images WHERE id = ?", &[&id], Db::extract_all)
    }

    pub fn get_images<T: Into<Option<i32>>>(&self, take: T, skip: usize) -> SQLResult<Vec<Image>>{
        let take = match take.into() {
            Some(x) => x,
            None    => -1
        };

        let mut st = self.db.prepare(&format!("SELECT * FROM images LIMIT {} OFFSET {}", take, skip))?;
        let st = st.query_map(&[], Db::extract_all_ref)?.map(|x| x.unwrap());
        Ok(st.collect::<Vec<_>>())
    }

    pub fn by_tags<T: Into<Option<i32>>>(&self, take: T, skip: usize, tags: &[String]) -> SQLResult<Vec<Image>> {
        let tags = tags.iter().map(|x| parse_tag(&x.replace("_",r"\_").replace("%", r"\%").replace("'", "''"))).collect::<Vec<_>>();

        let q = tags.iter().map(|t| {
            match *t {
                Tag::Include(ref incl) => format!(r"tags LIKE '%,{},%' ESCAPE '\'", incl),
                Tag::Exclude(ref excl) => format!(r"tags NOT LIKE '%,{},%' ESCAPE '\'", excl),
                Tag::AnyWith(ref x) => match *x {
                    AnyWith::Before(ref bef) => format!(r"tags LIKE '%,{}%,%' ESCAPE '\'", bef),
                    AnyWith::After(ref aft) => format!(r"tags LIKE '%,%{},%' ESCAPE '\'", aft),
                },
                Tag::Rating(ref r) => {
                    let mut s = "(".to_string();
                    for tg in r {
                        s.push_str(&format!("rating = '{}' OR ", tg))
                    }
                    let _ = (0..4).inspect(|_| {s.pop(); }).collect::<Vec<_>>();
                    s.push_str(")");

                    s
                },

                Tag::From(ref f) => {
                    let mut s = "(".to_string();
                    for tg in f {
                        s.push_str(&format!("got_from = '{}' OR ", tg))
                    }
                    let _ = (0..4).inspect(|_| {s.pop(); }).collect::<Vec<_>>();
                    s.push_str(")");

                    s
                }
            }
        }).collect::<Vec<_>>().join(" AND ");

        let take = match take.into() {
            Some(x) => x,
            None    => -1
        };

        let mut st = self.db.prepare(&format!("SELECT * FROM images WHERE {} LIMIT {} OFFSET {}", q, take, skip))?;
        let st = st.query_map(&[], Db::extract_all_ref)?.map(|x| x.unwrap());
        Ok(st.collect::<Vec<_>>())
    }
}

fn parse_tag(tag: &str) -> Tag {
    if tag.starts_with("rating") {
        let tag = tag.split("rating:").collect::<Vec<_>>()[1];
        Tag::Rating(tag.split(',').map(|x| x.to_string()).collect::<Vec<_>>())
    } else if tag.starts_with("from") {
        let tag = tag.split("from:").collect::<Vec<_>>()[1];
        Tag::From(tag.split(',').map(|x| x.to_string()).collect::<Vec<_>>())
    } else if tag.starts_with('-') {
        Tag::Exclude(tag[1..].to_string())
    } else if tag.starts_with('*') {
        Tag::AnyWith(AnyWith::After(tag[1..].to_string()))
    } else if tag.ends_with('*') {
        let mut n = tag.to_string();
        n.pop();
        Tag::AnyWith(AnyWith::Before(n))
    } else {
        Tag::Include(tag.to_string())
    }
}
<|endoftext|>


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

mod aes_cmac_prf_key_manager_test;
mod hkdf_prf_key_manager_test;
mod hmac_prf_key_manager_test;
mod prf_key_templates_test;
mod set_factory_test;
<commit_msg>tink-prf: drop unused test file<commit_after><|endoftext|>