<commit_before>use std::borrow::Cow;

use console::{measure_text_width, Style};

use crate::format::{BinaryBytes, DecimalBytes, FormattedDuration, HumanBytes, HumanDuration};
use crate::progress::ProgressState;
use crate::utils::{expand_template, pad_str};

#[cfg(feature = "improved_unicode")]
use unicode_segmentation::UnicodeSegmentation;

/// Controls the rendering style of progress bars.
#[derive(Clone, Debug)]
pub struct ProgressStyle {
    tick_strings: Vec<Box<str>>,
    progress_chars: Vec<Box<str>>,
    template: Cow<'static, str>,
    // how unicode-big each char in progress_chars is
    char_width: usize,
}

#[cfg(feature = "improved_unicode")]
fn segment(s: &str) -> Vec<Box<str>> {
    UnicodeSegmentation::graphemes(s, true)
        .map(|s| s.into())
        .collect()
}

#[cfg(not(feature = "improved_unicode"))]
fn segment(s: &str) -> Vec<Box<str>> {
    s.chars().map(|x| x.to_string().into()).collect()
}

#[cfg(feature = "improved_unicode")]
fn measure(s: &str) -> usize {
    unicode_width::UnicodeWidthStr::width(s)
}

#[cfg(not(feature = "improved_unicode"))]
fn measure(s: &str) -> usize {
    s.chars().count()
}

/// finds the unicode-aware width of the passed grapheme cluters
/// panics on an empty parameter, or if the characters are not equal-width
fn width(c: &[Box<str>]) -> usize {
    c.iter()
        .map(|s| measure(s.as_ref()))
        .fold(None, |acc, new| {
            match acc {
                None => return Some(new),
                Some(old) => assert_eq!(old, new, "got passed un-equal width progress characters"),
            }
            acc
        })
        .unwrap()
}

impl ProgressStyle {
    /// Returns the default progress bar style for bars.
    pub fn default_bar() -> ProgressStyle {
        let progress_chars = segment("█░");
        let char_width = width(&progress_chars);
        ProgressStyle {
            tick_strings: "⠁⠁⠉⠙⠚⠒⠂⠂⠒⠲⠴⠤⠄⠄⠤⠠⠠⠤⠦⠖⠒⠐⠐⠒⠓⠋⠉⠈⠈ "
                .chars()
                .map(|c| c.to_string().into())
                .collect(),
            progress_chars,
            char_width,
            template: Cow::Borrowed("{wide_bar} {pos}/{len}"),
        }
    }

    /// Returns the default progress bar style for spinners.
    pub fn default_spinner() -> ProgressStyle {
        let progress_chars = segment("█░");
        let char_width = width(&progress_chars);
        ProgressStyle {
            tick_strings: "⠁⠁⠉⠙⠚⠒⠂⠂⠒⠲⠴⠤⠄⠄⠤⠠⠠⠤⠦⠖⠒⠐⠐⠒⠓⠋⠉⠈⠈ "
                .chars()
                .map(|c| c.to_string().into())
                .collect(),
            progress_chars,
            char_width,
            template: Cow::Borrowed("{spinner} {msg}"),
        }
    }

    /// Sets the tick character sequence for spinners.
    pub fn tick_chars(mut self, s: &str) -> ProgressStyle {
        self.tick_strings = s.chars().map(|c| c.to_string().into()).collect();
        self
    }

    /// Sets the tick string sequence for spinners.
    pub fn tick_strings(mut self, s: &[&str]) -> ProgressStyle {
        self.tick_strings = s.iter().map(|s| s.to_string().into()).collect();
        self
    }

    /// Sets the progress characters `(filled, current, to do)`.
    /// You can pass more then three for a more detailed display.
    /// All passed grapheme clusters need to be of equal width.
    pub fn progress_chars(mut self, s: &str) -> ProgressStyle {
        self.progress_chars = segment(s);
        self.char_width = width(&self.progress_chars);
        self
    }

    /// Sets the template string for the progress bar.
    ///
    /// List of keys is available at crate root docs.
    pub fn template(mut self, s: &str) -> ProgressStyle {
        self.template = Cow::Owned(s.into());
        self
    }

    /// Returns the tick char for a given number.
    #[deprecated(since = "0.13.0", note = "Deprecated in favor of get_tick_str")]
    pub fn get_tick_char(&self, idx: u64) -> char {
        self.get_tick_str(idx).chars().next().unwrap_or(' ')
    }

    /// Returns the tick string for a given number.
    pub fn get_tick_str(&self, idx: u64) -> &str {
        &self.tick_strings[(idx as usize) % (self.tick_strings.len() - 1)]
    }

    /// Returns the tick char for the finished state.
    #[deprecated(since = "0.13.0", note = "Deprecated in favor of get_final_tick_str")]
    pub fn get_final_tick_char(&self) -> char {
        self.get_final_tick_str().chars().next().unwrap_or(' ')
    }

    /// Returns the tick string for the finished state.
    pub fn get_final_tick_str(&self) -> &str {
        &self.tick_strings[self.tick_strings.len() - 1]
    }

    pub(crate) fn format_bar(
        &self,
        state: &ProgressState,
        width: usize,
        alt_style: Option<&Style>,
    ) -> String {
        // The number of clusters from progress_chars to write (rounding down).
        let width = width / state.style.char_width;
        // The number of full clusters (including a fractional component for a partially-full one).
        let fill = state.fraction() * width as f32;
        // The number of entirely full clusters (by truncating `fill`).
        let entirely_filled = fill as usize;
        // 1 if the bar is not entirely empty or full (meaning we need to draw the "current"
        // character between the filled and "to do" segment), 0 otherwise.
        let head = if fill > 0.0 && entirely_filled < width {
            1
        } else {
            0
        };

        let pb = state.style.progress_chars[0].repeat(entirely_filled);

        let cur = if head == 1 {
            // Number of fine-grained progress entries in progress_chars.
            let n = state.style.progress_chars.len().saturating_sub(2);
            let cur_char = if n <= 1 {
                // No fine-grained entries. 1 is the single "current" entry if we have one, the "to
                // do" entry if not.
                1
            } else {
                // Pick a fine-grained entry, ranging from the last one (n) if the fractional part
                // of fill is 0 to the first one (1) if the fractional part of fill is almost 1.
                n.saturating_sub((fill.fract() * n as f32) as usize)
            };
            state.style.progress_chars[cur_char].to_string()
        } else {
            "".into()
        };

        // Number of entirely empty clusters needed to fill the bar up to `width`.
        let bg = width.saturating_sub(entirely_filled).saturating_sub(head);
        let rest = state.style.progress_chars.last().unwrap().repeat(bg);
        format!(
            "{}{}{}",
            pb,
            cur,
            alt_style.unwrap_or(&Style::new()).apply_to(rest)
        )
    }

    pub(crate) fn format_state(&self, state: &ProgressState) -> Vec<String> {
        let (pos, len) = state.position();
        let mut rv = vec![];

        for line in self.template.lines() {
            let mut wide_element = None;

            let s = expand_template(line, |var| match var.key {
                "wide_bar" => {
                    wide_element = Some(var.duplicate_for_key("bar"));
                    "\x00".into()
                }
                "bar" => self.format_bar(state, var.width.unwrap_or(20), var.alt_style.as_ref()),
                "spinner" => state.current_tick_str().to_string(),
                "wide_msg" => {
                    wide_element = Some(var.duplicate_for_key("msg"));
                    "\x00".into()
                }
                "msg" => state.message().to_string(),
                "prefix" => state.prefix().to_string(),
                "pos" => pos.to_string(),
                "len" => len.to_string(),
                "percent" => format!("{:.*}", 0, state.fraction() * 100f32),
                "bytes" => format!("{}", HumanBytes(state.pos)),
                "total_bytes" => format!("{}", HumanBytes(state.len)),
                "decimal_bytes" => format!("{}", DecimalBytes(state.pos)),
                "decimal_total_bytes" => format!("{}", DecimalBytes(state.len)),
                "binary_bytes" => format!("{}", BinaryBytes(state.pos)),
                "binary_total_bytes" => format!("{}", BinaryBytes(state.len)),
                "elapsed_precise" => format!("{}", FormattedDuration(state.started.elapsed())),
                "elapsed" => format!("{:#}", HumanDuration(state.started.elapsed())),
                "per_sec" => format!("{}/s", state.per_sec()),
                "bytes_per_sec" => format!("{}/s", HumanBytes(state.per_sec())),
                "binary_bytes_per_sec" => format!("{}/s", BinaryBytes(state.per_sec())),
                "eta_precise" => format!("{}", FormattedDuration(state.eta())),
                "eta" => format!("{:#}", HumanDuration(state.eta())),
                "duration_precise" => format!("{}", FormattedDuration(state.duration())),
                "duration" => format!("{:#}", HumanDuration(state.duration())),
                _ => "".into(),
            });

            rv.push(if let Some(ref var) = wide_element {
                let total_width = state.width();
                if var.key == "bar" {
                    let bar_width = total_width.saturating_sub(measure_text_width(&s));
                    s.replace(
                        "\x00",
                        &self.format_bar(state, bar_width, var.alt_style.as_ref()),
                    )
                } else if var.key == "msg" {
                    let msg_width = total_width.saturating_sub(measure_text_width(&s));
                    let msg = pad_str(state.message(), msg_width, var.align, true);
                    s.replace(
                        "\x00",
                        if var.last_element {
                            msg.trim_end()
                        } else {
                            &msg
                        },
                    )
                } else {
                    unreachable!()
                }
            } else {
                s.to_string()
            });
        }

        rv
    }
}
<commit_msg>Change ProgressStyle::template from Cow<'static, str> to Box<str><commit_after>use console::{measure_text_width, Style};

use crate::format::{BinaryBytes, DecimalBytes, FormattedDuration, HumanBytes, HumanDuration};
use crate::progress::ProgressState;
use crate::utils::{expand_template, pad_str};

#[cfg(feature = "improved_unicode")]
use unicode_segmentation::UnicodeSegmentation;

/// Controls the rendering style of progress bars.
#[derive(Clone, Debug)]
pub struct ProgressStyle {
    tick_strings: Vec<Box<str>>,
    progress_chars: Vec<Box<str>>,
    template: Box<str>,
    // how unicode-big each char in progress_chars is
    char_width: usize,
}

#[cfg(feature = "improved_unicode")]
fn segment(s: &str) -> Vec<Box<str>> {
    UnicodeSegmentation::graphemes(s, true)
        .map(|s| s.into())
        .collect()
}

#[cfg(not(feature = "improved_unicode"))]
fn segment(s: &str) -> Vec<Box<str>> {
    s.chars().map(|x| x.to_string().into()).collect()
}

#[cfg(feature = "improved_unicode")]
fn measure(s: &str) -> usize {
    unicode_width::UnicodeWidthStr::width(s)
}

#[cfg(not(feature = "improved_unicode"))]
fn measure(s: &str) -> usize {
    s.chars().count()
}

/// finds the unicode-aware width of the passed grapheme cluters
/// panics on an empty parameter, or if the characters are not equal-width
fn width(c: &[Box<str>]) -> usize {
    c.iter()
        .map(|s| measure(s.as_ref()))
        .fold(None, |acc, new| {
            match acc {
                None => return Some(new),
                Some(old) => assert_eq!(old, new, "got passed un-equal width progress characters"),
            }
            acc
        })
        .unwrap()
}

impl ProgressStyle {
    /// Returns the default progress bar style for bars.
    pub fn default_bar() -> ProgressStyle {
        let progress_chars = segment("█░");
        let char_width = width(&progress_chars);
        ProgressStyle {
            tick_strings: "⠁⠁⠉⠙⠚⠒⠂⠂⠒⠲⠴⠤⠄⠄⠤⠠⠠⠤⠦⠖⠒⠐⠐⠒⠓⠋⠉⠈⠈ "
                .chars()
                .map(|c| c.to_string().into())
                .collect(),
            progress_chars,
            char_width,
            template: "{wide_bar} {pos}/{len}".into(),
        }
    }

    /// Returns the default progress bar style for spinners.
    pub fn default_spinner() -> ProgressStyle {
        let progress_chars = segment("█░");
        let char_width = width(&progress_chars);
        ProgressStyle {
            tick_strings: "⠁⠁⠉⠙⠚⠒⠂⠂⠒⠲⠴⠤⠄⠄⠤⠠⠠⠤⠦⠖⠒⠐⠐⠒⠓⠋⠉⠈⠈ "
                .chars()
                .map(|c| c.to_string().into())
                .collect(),
            progress_chars,
            char_width,
            template: "{spinner} {msg}".into(),
        }
    }

    /// Sets the tick character sequence for spinners.
    pub fn tick_chars(mut self, s: &str) -> ProgressStyle {
        self.tick_strings = s.chars().map(|c| c.to_string().into()).collect();
        self
    }

    /// Sets the tick string sequence for spinners.
    pub fn tick_strings(mut self, s: &[&str]) -> ProgressStyle {
        self.tick_strings = s.iter().map(|s| s.to_string().into()).collect();
        self
    }

    /// Sets the progress characters `(filled, current, to do)`.
    /// You can pass more then three for a more detailed display.
    /// All passed grapheme clusters need to be of equal width.
    pub fn progress_chars(mut self, s: &str) -> ProgressStyle {
        self.progress_chars = segment(s);
        self.char_width = width(&self.progress_chars);
        self
    }

    /// Sets the template string for the progress bar.
    ///
    /// List of keys is available at crate root docs.
    pub fn template(mut self, s: &str) -> ProgressStyle {
        self.template = s.into();
        self
    }

    /// Returns the tick char for a given number.
    #[deprecated(since = "0.13.0", note = "Deprecated in favor of get_tick_str")]
    pub fn get_tick_char(&self, idx: u64) -> char {
        self.get_tick_str(idx).chars().next().unwrap_or(' ')
    }

    /// Returns the tick string for a given number.
    pub fn get_tick_str(&self, idx: u64) -> &str {
        &self.tick_strings[(idx as usize) % (self.tick_strings.len() - 1)]
    }

    /// Returns the tick char for the finished state.
    #[deprecated(since = "0.13.0", note = "Deprecated in favor of get_final_tick_str")]
    pub fn get_final_tick_char(&self) -> char {
        self.get_final_tick_str().chars().next().unwrap_or(' ')
    }

    /// Returns the tick string for the finished state.
    pub fn get_final_tick_str(&self) -> &str {
        &self.tick_strings[self.tick_strings.len() - 1]
    }

    pub(crate) fn format_bar(
        &self,
        state: &ProgressState,
        width: usize,
        alt_style: Option<&Style>,
    ) -> String {
        // The number of clusters from progress_chars to write (rounding down).
        let width = width / state.style.char_width;
        // The number of full clusters (including a fractional component for a partially-full one).
        let fill = state.fraction() * width as f32;
        // The number of entirely full clusters (by truncating `fill`).
        let entirely_filled = fill as usize;
        // 1 if the bar is not entirely empty or full (meaning we need to draw the "current"
        // character between the filled and "to do" segment), 0 otherwise.
        let head = if fill > 0.0 && entirely_filled < width {
            1
        } else {
            0
        };

        let pb = state.style.progress_chars[0].repeat(entirely_filled);

        let cur = if head == 1 {
            // Number of fine-grained progress entries in progress_chars.
            let n = state.style.progress_chars.len().saturating_sub(2);
            let cur_char = if n <= 1 {
                // No fine-grained entries. 1 is the single "current" entry if we have one, the "to
                // do" entry if not.
                1
            } else {
                // Pick a fine-grained entry, ranging from the last one (n) if the fractional part
                // of fill is 0 to the first one (1) if the fractional part of fill is almost 1.
                n.saturating_sub((fill.fract() * n as f32) as usize)
            };
            state.style.progress_chars[cur_char].to_string()
        } else {
            "".into()
        };

        // Number of entirely empty clusters needed to fill the bar up to `width`.
        let bg = width.saturating_sub(entirely_filled).saturating_sub(head);
        let rest = state.style.progress_chars.last().unwrap().repeat(bg);
        format!(
            "{}{}{}",
            pb,
            cur,
            alt_style.unwrap_or(&Style::new()).apply_to(rest)
        )
    }

    pub(crate) fn format_state(&self, state: &ProgressState) -> Vec<String> {
        let (pos, len) = state.position();
        let mut rv = vec![];

        for line in self.template.lines() {
            let mut wide_element = None;

            let s = expand_template(line, |var| match var.key {
                "wide_bar" => {
                    wide_element = Some(var.duplicate_for_key("bar"));
                    "\x00".into()
                }
                "bar" => self.format_bar(state, var.width.unwrap_or(20), var.alt_style.as_ref()),
                "spinner" => state.current_tick_str().to_string(),
                "wide_msg" => {
                    wide_element = Some(var.duplicate_for_key("msg"));
                    "\x00".into()
                }
                "msg" => state.message().to_string(),
                "prefix" => state.prefix().to_string(),
                "pos" => pos.to_string(),
                "len" => len.to_string(),
                "percent" => format!("{:.*}", 0, state.fraction() * 100f32),
                "bytes" => format!("{}", HumanBytes(state.pos)),
                "total_bytes" => format!("{}", HumanBytes(state.len)),
                "decimal_bytes" => format!("{}", DecimalBytes(state.pos)),
                "decimal_total_bytes" => format!("{}", DecimalBytes(state.len)),
                "binary_bytes" => format!("{}", BinaryBytes(state.pos)),
                "binary_total_bytes" => format!("{}", BinaryBytes(state.len)),
                "elapsed_precise" => format!("{}", FormattedDuration(state.started.elapsed())),
                "elapsed" => format!("{:#}", HumanDuration(state.started.elapsed())),
                "per_sec" => format!("{}/s", state.per_sec()),
                "bytes_per_sec" => format!("{}/s", HumanBytes(state.per_sec())),
                "binary_bytes_per_sec" => format!("{}/s", BinaryBytes(state.per_sec())),
                "eta_precise" => format!("{}", FormattedDuration(state.eta())),
                "eta" => format!("{:#}", HumanDuration(state.eta())),
                "duration_precise" => format!("{}", FormattedDuration(state.duration())),
                "duration" => format!("{:#}", HumanDuration(state.duration())),
                _ => "".into(),
            });

            rv.push(if let Some(ref var) = wide_element {
                let total_width = state.width();
                if var.key == "bar" {
                    let bar_width = total_width.saturating_sub(measure_text_width(&s));
                    s.replace(
                        "\x00",
                        &self.format_bar(state, bar_width, var.alt_style.as_ref()),
                    )
                } else if var.key == "msg" {
                    let msg_width = total_width.saturating_sub(measure_text_width(&s));
                    let msg = pad_str(state.message(), msg_width, var.align, true);
                    s.replace(
                        "\x00",
                        if var.last_element {
                            msg.trim_end()
                        } else {
                            &msg
                        },
                    )
                } else {
                    unreachable!()
                }
            } else {
                s.to_string()
            });
        }

        rv
    }
}
<|endoftext|>


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

//! The dirichlet distribution.

use Rng;
use distributions::Distribution;
use distributions::gamma::Gamma;

/// The dirichelet distribution `Dirichlet(alpha)`.
///
/// The Dirichlet distribution } is a family of continuous multivariate probability distributions parameterized by
/// a vector alpha of positive reals
/// It is a multivariate generalization of the beta distribution.
///
/// # Example
///
/// ```
/// use rand::prelude::*;
/// use rand::distributions::Dirichlet;
///
/// let dirichlet = Dirichlet::new(&vec![1.0, 2.0, 3.0]);
/// let samples = dirichlet.sample(&mut rand::thread_rng());
/// println!("{:?} is from a Dirichlet([1.0, 2.0, 3.0]) distribution", samples);
/// ```

#[derive(Clone, Debug)]
pub struct Dirichlet {
    /// Concentration parameters (alpha)
    alpha: Vec<f64>,
}

impl Dirichlet {
    /// Construct a new `Dirichlet` with the given alpha parameter
    /// `alpha`. Panics if `alpha.len() < 2`.
    #[inline]
    pub fn new(alpha: &[f64]) -> Dirichlet {
        assert!(
            alpha.len() > 1,
            "Dirichlet::new called with `alpha` with length <  2"
        );
        for i in 0..alpha.len() {
            assert!(
                alpha[i] > 0.0,
                "Dirichlet::new called with `alpha`  <=  0.0"
            );
        }

        Dirichlet {
            alpha: alpha.to_vec(),
        }
    }

    /// Construct a new `Dirichlet` with the given shape parameter and size
    /// `alpha`. Panics if `alpha <= 0.0`.
    /// `size` . Panic if `size < 2`
    #[inline]
    pub fn new_with_param(alpha: f64, size: usize) -> Dirichlet {
        assert!(alpha > 0.0, "Dirichlet::new called with `alpha`  <=  0.0");
        assert!(size > 1, "Dirichlet::new called with `size`  <=  1");
        Dirichlet {
            alpha: vec![alpha; size],
        }
    }
}

impl Distribution<Vec<f64>> for Dirichlet {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec<f64> {
        let n = self.alpha.len();
        let mut samples = vec![0.0f64; n];
        let mut sum = 0.0f64;

        for i in 0..n {
            let g = Gamma::new(self.alpha[i], 1.0);
            samples[i] = g.sample(rng);
            sum += samples[i];
        }
        let invacc = 1.0 / sum;
        for i in 0..n {
            samples[i] *= invacc;
        }
        samples
    }
}

#[cfg(test)]
mod test {
    use super::Dirichlet;
    use distributions::Distribution;

    #[test]
    fn test_dirichlet() {
        let d = Dirichlet::new(&vec![1.0, 2.0, 3.0]);
        let mut rng = ::test::rng(221);
        let samples = d.sample(&mut rng);
        let _: Vec<f64> = samples
            .into_iter()
            .map(|x| {
                assert!(x > 0.0);
                x
            })
            .collect();
    }

    #[test]
    fn test_dirichlet_with_param() {
        let alpha = 0.5f64;
        let size = 2;
        let d = Dirichlet::new_with_param(alpha, size);
        let mut rng = ::test::rng(221);
        let samples = d.sample(&mut rng);
        let _: Vec<f64> = samples
            .into_iter()
            .map(|x| {
                assert!(x > 0.0);
                x
            })
            .collect();
    }

    #[test]
    #[should_panic]
    fn test_dirichlet_invalid_length() {
        Dirichlet::new_with_param(0.5f64, 1);
    }

    #[test]
    #[should_panic]
    fn test_dirichlet_invalid_alpha() {
        Dirichlet::new_with_param(0.0f64, 2);
    }
}
<commit_msg>review comments<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The dirichlet distribution.

use Rng;
use distributions::Distribution;
use distributions::gamma::Gamma;

/// The dirichelet distribution `Dirichlet(alpha)`.
///
/// The Dirichlet distribution } is a family of continuous multivariate probability distributions parameterized by
/// a vector alpha of positive reals. https://en.wikipedia.org/wiki/Dirichlet_distribution
/// It is a multivariate generalization of the beta distribution.
///
/// # Example
///
/// ```
/// use rand::prelude::*;
/// use rand::distributions::Dirichlet;
///
/// let dirichlet = Dirichlet::new(vec![1.0, 2.0, 3.0]);
/// let samples = dirichlet.sample(&mut rand::thread_rng());
/// println!("{:?} is from a Dirichlet([1.0, 2.0, 3.0]) distribution", samples);
/// ```

#[derive(Clone, Debug)]
pub struct Dirichlet {
    /// Concentration parameters (alpha)
    alpha: Vec<f64>,
}

impl Dirichlet {
    /// Construct a new `Dirichlet` with the given alpha parameter
    /// `alpha`. Panics if `alpha.len() < 2`.
    #[inline]
    pub fn new<V: Into<Vec<f64>>>(alpha: V) -> Dirichlet {
        let a = alpha.into();
        assert!(a.len() > 1);
        for i in 0..a.len() {
            assert!(a[i] > 0.0);
        }

        Dirichlet { alpha: a.into() }
    }

    /// Construct a new `Dirichlet` with the given shape parameter and size
    /// `alpha`. Panics if `alpha <= 0.0`.
    /// `size` . Panic if `size < 2`
    #[inline]
    pub fn new_with_param(alpha: f64, size: usize) -> Dirichlet {
        assert!(alpha > 0.0);
        assert!(size > 1);
        Dirichlet {
            alpha: vec![alpha; size],
        }
    }
}

impl Distribution<Vec<f64>> for Dirichlet {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec<f64> {
        let n = self.alpha.len();
        let mut samples = vec![0.0f64; n];
        let mut sum = 0.0f64;

        for i in 0..n {
            let g = Gamma::new(self.alpha[i], 1.0);
            samples[i] = g.sample(rng);
            sum += samples[i];
        }
        let invacc = 1.0 / sum;
        for i in 0..n {
            samples[i] *= invacc;
        }
        samples
    }
}

#[cfg(test)]
mod test {
    use super::Dirichlet;
    use distributions::Distribution;

    #[test]
    fn test_dirichlet() {
        let d = Dirichlet::new(vec![1.0, 2.0, 3.0]);
        let mut rng = ::test::rng(221);
        let samples = d.sample(&mut rng);
        let _: Vec<f64> = samples
            .into_iter()
            .map(|x| {
                assert!(x > 0.0);
                x
            })
            .collect();
    }

    #[test]
    fn test_dirichlet_with_param() {
        let alpha = 0.5f64;
        let size = 2;
        let d = Dirichlet::new_with_param(alpha, size);
        let mut rng = ::test::rng(221);
        let samples = d.sample(&mut rng);
        let _: Vec<f64> = samples
            .into_iter()
            .map(|x| {
                assert!(x > 0.0);
                x
            })
            .collect();
    }

    #[test]
    #[should_panic]
    fn test_dirichlet_invalid_length() {
        Dirichlet::new_with_param(0.5f64, 1);
    }

    #[test]
    #[should_panic]
    fn test_dirichlet_invalid_alpha() {
        Dirichlet::new_with_param(0.0f64, 2);
    }
}
<|endoftext|>


<commit_before>use BitField;
use BitArray;

#[test]
fn test_integer_bit_lengths() {
    assert_eq!(u8::bit_length(), 8);
    assert_eq!(u16::bit_length(), 16);
    assert_eq!(u32::bit_length(), 32);
    assert_eq!(u64::bit_length(), 64);

    assert_eq!(i8::bit_length(), 8);
    assert_eq!(i16::bit_length(), 16);
    assert_eq!(i32::bit_length(), 32);
    assert_eq!(i64::bit_length(), 64);
}

#[test]
fn test_set_reset_u8() {
    let mut field = 0b11110010u8;
    let mut bit_i = |i| {
        field.set_bit(i, true);
        assert_eq!(field.get_bit(i), true);
        field.set_bit(i, false);
        assert_eq!(field.get_bit(i), false);
        field.set_bit(i, true);
        assert_eq!(field.get_bit(i), true);
    };
    for i in 0..8 {
        bit_i(i);
    }
}

#[test]
fn test_set_reset_u16() {
    let mut field = 0b1111001010010110u16;
    let mut bit_i = |i| {
        field.set_bit(i, true);
        assert_eq!(field.get_bit(i), true);
        field.set_bit(i, false);
        assert_eq!(field.get_bit(i), false);
        field.set_bit(i, true);
        assert_eq!(field.get_bit(i), true);
    };
    for i in 0..16 {
        bit_i(i);
    }
}

#[test]
fn test_read_u32() {
    let field = 0b1111111111010110u32;
    assert_eq!(field.get_bit(0), false);
    assert_eq!(field.get_bit(1), true);
    assert_eq!(field.get_bit(2), true);
    assert_eq!(field.get_bit(3), false);
    assert_eq!(field.get_bit(4), true);
    assert_eq!(field.get_bit(5), false);
    for i in 6..16 {
        assert_eq!(field.get_bit(i), true);
    }
    for i in 16..32 {
        assert_eq!(field.get_bit(i), false);
    }

    assert_eq!(field.get_bits(16..32), 0);
    assert_eq!(field.get_bits(6..16), 0b1111111111);
    assert_eq!(field.get_bits(0..6), 0b010110);
    assert_eq!(field.get_bits(0..10), 0b1111010110);
    assert_eq!(field.get_bits(5..12), 0b1111110);
}

#[test]
fn test_set_reset_u32() {
    let mut field = 0b1111111111010110u32;
    let mut bit_i = |i| {
        field.set_bit(i, true);
        assert_eq!(field.get_bit(i), true);
        field.set_bit(i, false);
        assert_eq!(field.get_bit(i), false);
        field.set_bit(i, true);
        assert_eq!(field.get_bit(i), true);
    };
    for i in 0..32 {
        bit_i(i);
    }
}

#[test]
fn test_set_range_u32() {
    let mut field = 0b1111111111010110u32;
    field.set_bits(10..15, 0b00000);
    assert_eq!(field.get_bits(10..15), 0b00000);
    field.set_bits(10..15, 0b10101);
    assert_eq!(field.get_bits(10..15), 0b10101);
    field.set_bits(10..15, 0b01010);
    assert_eq!(field.get_bits(10..15), 0b01010);
    field.set_bits(10..15, 0b11111);
    assert_eq!(field.get_bits(10..15), 0b11111);

    field.set_bits(0..16, 0xdead);
    field.set_bits(14..32, 0xbeaf);
    assert_eq!(field.get_bits(0..16), 0xdead);
    assert_eq!(field.get_bits(14..32), 0xbeaf);
}

#[test]
fn test_read_u64() {
    let field = 0b1111111111010110u64 << 32;
    for i in 0..32 {
        assert_eq!(field.get_bit(i), false);
    }
    assert_eq!(field.get_bit(32), false);
    assert_eq!(field.get_bit(33), true);
    assert_eq!(field.get_bit(34), true);
    assert_eq!(field.get_bit(35), false);
    assert_eq!(field.get_bit(36), true);
    assert_eq!(field.get_bit(37), false);
    for i in 38..48 {
        assert_eq!(field.get_bit(i), true);
    }
    for i in 48..64 {
        assert_eq!(field.get_bit(i), false);
    }

    assert_eq!(field.get_bits(0..32), 0);
    assert_eq!(field.get_bits(48..64), 0);
    assert_eq!(field.get_bits(38..48), 0b1111111111);
    assert_eq!(field.get_bits(32..38), 0b010110);
    assert_eq!(field.get_bits(32..42), 0b1111010110);
    assert_eq!(field.get_bits(37..44), 0b1111110);
}

#[test]
fn test_set_reset_u64() {
    let mut field = 0b1111111111010110u64 << 32;
    let mut bit_i = |i| {
        field.set_bit(i, true);
        assert_eq!(field.get_bit(i), true);
        field.set_bit(i, false);
        assert_eq!(field.get_bit(i), false);
        field.set_bit(i, true);
        assert_eq!(field.get_bit(i), true);
    };
    for i in 0..64 {
        bit_i(i);
    }
}

#[test]
fn test_set_range_u64() {
    let mut field = 0b1111111111010110u64 << 32;
    field.set_bits(42..47, 0b00000);
    assert_eq!(field.get_bits(42..47), 0b00000);
    field.set_bits(10..15, 0b10101);
    assert_eq!(field.get_bits(10..15), 0b10101);
    field.set_bits(40..45, 0b01010);
    assert_eq!(field.get_bits(40..45), 0b01010);
    field.set_bits(40..45, 0b11111);
    assert_eq!(field.get_bits(40..45), 0b11111);

    field.set_bits(0..16, 0xdead);
    field.set_bits(14..32, 0xbeaf);
    field.set_bits(32..64, 0xcafebabe);
    assert_eq!(field.get_bits(0..16), 0xdead);
    assert_eq!(field.get_bits(14..32), 0xbeaf);
    assert_eq!(field.get_bits(32..64), 0xcafebabe);
}

#[test]
fn test_array_length() {
    assert_eq!((&[2u8, 3u8, 4u8]).bit_length(), 24);
    assert_eq!((&[2i8, 3i8, 4i8, 5i8]).bit_length(), 32);

    assert_eq!((&[2u16, 3u16, 4u16]).bit_length(), 48);
    assert_eq!((&[2i16, 3i16, 4i16, 5i16]).bit_length(), 64);

    assert_eq!((&[2u32, 3u32, 4u32]).bit_length(), 96);
    assert_eq!((&[2i32, 3i32, 4i32, 5i32]).bit_length(), 128);

    assert_eq!((&[2u64, 3u64, 4u64]).bit_length(), 192);
    assert_eq!((&[2i64, 3i64, 4i64, 5i64]).bit_length(), 256);
}

#[test]
fn test_get_array() {
    let mut test_val = [0xffu8];
    &test_val.set_bit(0,false);
    assert_eq!(test_val, [0xfeu8]);
    &test_val.set_bit(4,false);
    assert_eq!(test_val, [0xeeu8]);

    let mut test_array = [0xffu8, 0x00u8, 0xffu8];
    &test_array.set_bit(7, false);
    &test_array.set_bit(8, true);
    &test_array.set_bit(16, false);

    assert_eq!(test_array, [0x7fu8, 0x01u8, 0xfeu8]);
}
<commit_msg>Added more tests for the new BitArray type<commit_after>use BitField;
use BitArray;

#[test]
fn test_integer_bit_lengths() {
    assert_eq!(u8::bit_length(), 8);
    assert_eq!(u16::bit_length(), 16);
    assert_eq!(u32::bit_length(), 32);
    assert_eq!(u64::bit_length(), 64);

    assert_eq!(i8::bit_length(), 8);
    assert_eq!(i16::bit_length(), 16);
    assert_eq!(i32::bit_length(), 32);
    assert_eq!(i64::bit_length(), 64);
}

#[test]
fn test_set_reset_u8() {
    let mut field = 0b11110010u8;
    let mut bit_i = |i| {
        field.set_bit(i, true);
        assert_eq!(field.get_bit(i), true);
        field.set_bit(i, false);
        assert_eq!(field.get_bit(i), false);
        field.set_bit(i, true);
        assert_eq!(field.get_bit(i), true);
    };
    for i in 0..8 {
        bit_i(i);
    }
}

#[test]
fn test_set_reset_u16() {
    let mut field = 0b1111001010010110u16;
    let mut bit_i = |i| {
        field.set_bit(i, true);
        assert_eq!(field.get_bit(i), true);
        field.set_bit(i, false);
        assert_eq!(field.get_bit(i), false);
        field.set_bit(i, true);
        assert_eq!(field.get_bit(i), true);
    };
    for i in 0..16 {
        bit_i(i);
    }
}

#[test]
fn test_read_u32() {
    let field = 0b1111111111010110u32;
    assert_eq!(field.get_bit(0), false);
    assert_eq!(field.get_bit(1), true);
    assert_eq!(field.get_bit(2), true);
    assert_eq!(field.get_bit(3), false);
    assert_eq!(field.get_bit(4), true);
    assert_eq!(field.get_bit(5), false);
    for i in 6..16 {
        assert_eq!(field.get_bit(i), true);
    }
    for i in 16..32 {
        assert_eq!(field.get_bit(i), false);
    }

    assert_eq!(field.get_bits(16..32), 0);
    assert_eq!(field.get_bits(6..16), 0b1111111111);
    assert_eq!(field.get_bits(0..6), 0b010110);
    assert_eq!(field.get_bits(0..10), 0b1111010110);
    assert_eq!(field.get_bits(5..12), 0b1111110);
}

#[test]
fn test_set_reset_u32() {
    let mut field = 0b1111111111010110u32;
    let mut bit_i = |i| {
        field.set_bit(i, true);
        assert_eq!(field.get_bit(i), true);
        field.set_bit(i, false);
        assert_eq!(field.get_bit(i), false);
        field.set_bit(i, true);
        assert_eq!(field.get_bit(i), true);
    };
    for i in 0..32 {
        bit_i(i);
    }
}

#[test]
fn test_set_range_u32() {
    let mut field = 0b1111111111010110u32;
    field.set_bits(10..15, 0b00000);
    assert_eq!(field.get_bits(10..15), 0b00000);
    field.set_bits(10..15, 0b10101);
    assert_eq!(field.get_bits(10..15), 0b10101);
    field.set_bits(10..15, 0b01010);
    assert_eq!(field.get_bits(10..15), 0b01010);
    field.set_bits(10..15, 0b11111);
    assert_eq!(field.get_bits(10..15), 0b11111);

    field.set_bits(0..16, 0xdead);
    field.set_bits(14..32, 0xbeaf);
    assert_eq!(field.get_bits(0..16), 0xdead);
    assert_eq!(field.get_bits(14..32), 0xbeaf);
}

#[test]
fn test_read_u64() {
    let field = 0b1111111111010110u64 << 32;
    for i in 0..32 {
        assert_eq!(field.get_bit(i), false);
    }
    assert_eq!(field.get_bit(32), false);
    assert_eq!(field.get_bit(33), true);
    assert_eq!(field.get_bit(34), true);
    assert_eq!(field.get_bit(35), false);
    assert_eq!(field.get_bit(36), true);
    assert_eq!(field.get_bit(37), false);
    for i in 38..48 {
        assert_eq!(field.get_bit(i), true);
    }
    for i in 48..64 {
        assert_eq!(field.get_bit(i), false);
    }

    assert_eq!(field.get_bits(0..32), 0);
    assert_eq!(field.get_bits(48..64), 0);
    assert_eq!(field.get_bits(38..48), 0b1111111111);
    assert_eq!(field.get_bits(32..38), 0b010110);
    assert_eq!(field.get_bits(32..42), 0b1111010110);
    assert_eq!(field.get_bits(37..44), 0b1111110);
}

#[test]
fn test_set_reset_u64() {
    let mut field = 0b1111111111010110u64 << 32;
    let mut bit_i = |i| {
        field.set_bit(i, true);
        assert_eq!(field.get_bit(i), true);
        field.set_bit(i, false);
        assert_eq!(field.get_bit(i), false);
        field.set_bit(i, true);
        assert_eq!(field.get_bit(i), true);
    };
    for i in 0..64 {
        bit_i(i);
    }
}

#[test]
fn test_set_range_u64() {
    let mut field = 0b1111111111010110u64 << 32;
    field.set_bits(42..47, 0b00000);
    assert_eq!(field.get_bits(42..47), 0b00000);
    field.set_bits(10..15, 0b10101);
    assert_eq!(field.get_bits(10..15), 0b10101);
    field.set_bits(40..45, 0b01010);
    assert_eq!(field.get_bits(40..45), 0b01010);
    field.set_bits(40..45, 0b11111);
    assert_eq!(field.get_bits(40..45), 0b11111);

    field.set_bits(0..16, 0xdead);
    field.set_bits(14..32, 0xbeaf);
    field.set_bits(32..64, 0xcafebabe);
    assert_eq!(field.get_bits(0..16), 0xdead);
    assert_eq!(field.get_bits(14..32), 0xbeaf);
    assert_eq!(field.get_bits(32..64), 0xcafebabe);
}

#[test]
fn test_array_length() {
    assert_eq!((&[2u8, 3u8, 4u8]).bit_length(), 24);
    assert_eq!((&[2i8, 3i8, 4i8, 5i8]).bit_length(), 32);

    assert_eq!((&[2u16, 3u16, 4u16]).bit_length(), 48);
    assert_eq!((&[2i16, 3i16, 4i16, 5i16]).bit_length(), 64);

    assert_eq!((&[2u32, 3u32, 4u32]).bit_length(), 96);
    assert_eq!((&[2i32, 3i32, 4i32, 5i32]).bit_length(), 128);

    assert_eq!((&[2u64, 3u64, 4u64]).bit_length(), 192);
    assert_eq!((&[2i64, 3i64, 4i64, 5i64]).bit_length(), 256);
}

#[test]
fn test_set_bit_array() {
    let mut test_val = [0xffu8];
    &test_val.set_bit(0,false);
    assert_eq!(test_val, [0xfeu8]);
    &test_val.set_bit(4,false);
    assert_eq!(test_val, [0xeeu8]);

    let mut test_array = [0xffu8, 0x00u8, 0xffu8];
    &test_array.set_bit(7, false);
    &test_array.set_bit(8, true);
    &test_array.set_bit(16, false);

    assert_eq!(test_array, [0x7fu8, 0x01u8, 0xfeu8]);
}

#[test]
fn test_get_bit_array() {
    let test_val = [0xefu8];
    assert_eq!(test_val.get_bit(1), true);
    assert_eq!(test_val.get_bit(4), false);

    let test_array = [0xffu8, 0x00u8, 0xffu8];
    assert_eq!(test_array.get_bit(7), true);
    assert_eq!(test_array.get_bit(8), false);
    assert_eq!(test_array.get_bit(16), true);
}

#[test]
fn test_set_bits_array() {
    let mut test_val = [0xffu8];

    test_val.set_bits(0..4, 0x0u8);
    assert_eq!(test_val, [0xf0u8]);

    test_val.set_bits(0..4,0xau8);
    assert_eq!(test_val, [0xfau8]);

    test_val.set_bits(4..8,0xau8);
    assert_eq!(test_val, [0xaau8]);

    let mut test_array = [0xffu8, 0x00u8, 0xffu8];

    test_array.set_bits(7..9, 0b10);
    assert_eq!(test_array, [0x7f, 0x01, 0xff]);

    test_array.set_bits(12..20, 0xaa);
    assert_eq!(test_array, [0x7f, 0xa1, 0xfa]);

    test_array.set_bits(16..24, 0xaa);
    assert_eq!(test_array, [0x7f, 0xa1, 0xaa]);

    test_array.set_bits(6..14, 0x00);
    assert_eq!(test_array, [0x3f, 0x80, 0xaa]);
}

#[test]
fn test_get_bits_array() {
    let mut test_val = [0xf0u8];
    assert_eq!(test_val.get_bits(0..4), 0x0u8);

    test_val = [0xfau8];
    assert_eq!(test_val.get_bits(0..4), 0xau8);

    test_val = [0xaau8];
    assert_eq!(test_val.get_bits(4..8), 0xau8);

    let mut test_array: [u8; 3] = [0xff, 0x01, 0xff];
    assert_eq!(test_array.get_bits(7..9), 0b11u8);

    test_array = [0x7f, 0xa1, 0xfa];
    assert_eq!(test_array.get_bits(12..20), 0xaa);

    test_array = [0x7f, 0xa1, 0xaa];
    assert_eq!(test_array.get_bits(16..24), 0xaa);

    test_array = [0x3f, 0x80, 0xaa];
    assert_eq!(test_array.get_bits(6..14), 0x00);

}

<|endoftext|>


<commit_before>#![cfg(test)]

// These tests involve async files
use std::fs;
use std::fs::File;
use std::thread;
use std::time::Duration;
use std::io;
use std::io::prelude::*;
use std::result::Result;

use super::Promise;

#[test]
pub fn test_new() {
    Promise::new(|| {
        File::create("/tmp/promise-new")
    });

    thread::sleep(Duration::from_secs(1));

    assert!(File::open("/tmp/promise-new").is_ok());
    fs::remove_file("/tmp/promise-new");
}

#[test]
pub fn test_then() {
    Promise::new(|| {
        fs::create_dir("/tmp/promise-then")
    })
    .then(|t| {
        File::create("/tmp/promise-then/file")
    }, |e| {
        println!("Unable to create dir!");
        Err(io::Error::new(io::ErrorKind::Other, "Couldn't make dir!"))
    });

    thread::sleep(Duration::from_secs(1));
    assert!(File::open("/tmp/promise-then/file").is_ok());
    fs::remove_dir_all("/tmp/promise-then");
}

#[derive(Debug)]
enum TestErrType {
    CreateDir,
    CreateFile,
    WriteFile,
    ReadFile
}

#[test]
pub fn test_then_ok() {
    Promise::new(|| {
        match fs::create_dir("/tmp/promise-then-ok/") {
            Ok(_) => Ok(()),
            Err(_) => Err(TestErrType::CreateDir)
        }
    })
    .then_ok(|k| {
        // k is (), as that's what was passed through Ok(())
        match File::create("/tmp/promise-then-ok/file") {
            Ok(file) => Ok(file), // Now file is passed along
            Err(_) => Err(TestErrType::CreateFile)
        }
    })
    // Note here mutability can be added in the scope of one promise's
    // function. This was not passed a mut file.
    .then_ok(|mut file| {
        match file.write_all(b"Hello world!") {
            Ok(_) => Ok(()), // Original file is dropped, flushes
            Err(_) => Err(TestErrType::WriteFile) // Keep err type
        }
    })
    .then_err(|e| {
        println!("File process errored at {:?}", e);
        Err(())
    });

    thread::sleep(Duration::from_secs(1));
    let mut s = String::new();
    let maybe_file = File::open("/tmp/promise-then-ok/file");
    assert!(maybe_file.is_ok());
    let mut file = maybe_file.unwrap();
    assert!(file.read_to_string(&mut s).is_ok());
    assert_eq!(s, "Hello world!");
}
<commit_msg>Add a simple test case for promise::all.<commit_after>#![cfg(test)]

// These tests involve async files
use std::fs;
use std::fs::File;
use std::thread;
use std::time::Duration;
use std::io;
use std::io::prelude::*;
use std::result::Result;

use super::Promise;

#[test]
pub fn test_new() {
    Promise::new(|| {
        File::create("/tmp/promise-new")
    });

    thread::sleep(Duration::from_secs(1));

    assert!(File::open("/tmp/promise-new").is_ok());
    fs::remove_file("/tmp/promise-new");
}

#[test]
pub fn test_then() {
    Promise::new(|| {
        fs::create_dir("/tmp/promise-then")
    })
    .then(|t| {
        File::create("/tmp/promise-then/file")
    }, |e| {
        println!("Unable to create dir!");
        Err(io::Error::new(io::ErrorKind::Other, "Couldn't make dir!"))
    });

    thread::sleep(Duration::from_secs(1));
    assert!(File::open("/tmp/promise-then/file").is_ok());
    fs::remove_dir_all("/tmp/promise-then");
}

#[derive(Debug)]
enum TestErrType {
    CreateDir,
    CreateFile,
    WriteFile,
    ReadFile
}

#[test]
pub fn test_then_ok() {
    Promise::new(|| {
        match fs::create_dir("/tmp/promise-then-ok/") {
            Ok(_) => Ok(()),
            Err(_) => Err(TestErrType::CreateDir)
        }
    })
    .then_ok(|k| {
        // k is (), as that's what was passed through Ok(())
        match File::create("/tmp/promise-then-ok/file") {
            Ok(file) => Ok(file), // Now file is passed along
            Err(_) => Err(TestErrType::CreateFile)
        }
    })
    // Note here mutability can be added in the scope of one promise's
    // function. This was not passed a mut file.
    .then_ok(|mut file| {
        match file.write_all(b"Hello world!") {
            Ok(_) => Ok(()), // Original file is dropped, flushes
            Err(_) => Err(TestErrType::WriteFile) // Keep err type
        }
    })
    .then_err(|e| {
        println!("File process errored at {:?}", e);
        Err(())
    });

    thread::sleep(Duration::from_secs(1));
    let mut s = String::new();
    let maybe_file = File::open("/tmp/promise-then-ok/file");
    assert!(maybe_file.is_ok());
    let mut file = maybe_file.unwrap();
    assert!(file.read_to_string(&mut s).is_ok());
    assert_eq!(s, "Hello world!");
}

#[test]
pub fn promise_all() {
    let mut p: Vec<Promise<u32,u32>> = Vec::new();
    for x in 0..10 {
        p.push(Promise::new(move || {
            thread::sleep(Duration::from_secs(1));
            Ok(x)
        })
        .then(move |t| {
            assert_eq!(t, x);
            Ok(t)
        }, |e| {
            println!("err: {:?}", e);
            Err(e)
        }));
    }

    Promise::all(p).then( move |t| {
      assert_eq!(t.len(), 10);
      Ok(())
    }, |e| {
      println!("err: {:?}", e);
      Err(())
    });
}
<|endoftext|>


<commit_before>use std::time;
use ::{CanSocket, ShouldRetry};

#[test]
fn test_nonexistant_device() {
    assert!(CanSocket::open("invalid").is_err());
}

#[test]
#[cfg(feature = "vcan_tests")]
fn vcan0_timeout() {
    let cs = CanSocket::open("vcan0").unwrap();
    cs.set_read_timeout(time::Duration::from_millis(100)).unwrap();
    assert!(cs.read_frame().should_retry());
}

#[test]
#[cfg(feature = "vcan_tests")]
fn vcan0_set_error_mask() {
    let cs = CanSocket::open("vcan0").unwrap();
    cs.error_filter_drop_all().unwrap();
    cs.error_filter_accept_all().unwrap();
}
<commit_msg>Remove unused imports.<commit_after>use ::CanSocket;

#[test]
fn test_nonexistant_device() {
    assert!(CanSocket::open("invalid").is_err());
}

#[test]
#[cfg(feature = "vcan_tests")]
fn vcan0_timeout() {
    let cs = CanSocket::open("vcan0").unwrap();
    cs.set_read_timeout(time::Duration::from_millis(100)).unwrap();
    assert!(cs.read_frame().should_retry());
}

#[test]
#[cfg(feature = "vcan_tests")]
fn vcan0_set_error_mask() {
    let cs = CanSocket::open("vcan0").unwrap();
    cs.error_filter_drop_all().unwrap();
    cs.error_filter_accept_all().unwrap();
}
<|endoftext|>


<commit_before>use variables::*;
use variables::LpExpression::*;
use problem::*;
use std::rc::Rc;

#[test]
fn expressions_creation() {
    let ref a = LpInteger::new("a")
        .lower_bound(10.0)
        .upper_bound(20.0);
    let ref b = LpInteger::new("b");

    assert_eq!(a + b, AddExpr(Rc::new(ConsInt(a.clone())), Rc::new(ConsInt(b.clone()))));
}

#[test]
fn expressions_to_string() {
    let ref a = LpInteger::new("a");
    let ref b = LpInteger::new("b");
    let ref c = LpInteger::new("c");

    assert_eq!((a + 2*b + c).to_string(), "a + 2 b + c");
    assert_eq!((a + b*2 + c).to_string(), "a + 2 b + c");
    assert_eq!((a + b*2 + 3 * 2 * c).to_string(), "a + 2 b + 6 c");
    assert_eq!((a + 2).to_string(), "a + 2");
    assert_eq!((2*a + 2*b -4*c).to_string(), "2 a + 2 b - 4 c");
    assert_eq!((-2*a).to_string(), "-2 a");

}

<commit_msg>Add some unit tests for LpConstraint<commit_after>use variables::*;
use variables::LpExpression::*;
use problem::*;
use std::rc::Rc;
use operations::LpOperations;

#[test]
fn expressions_creation() {
    let ref a = LpInteger::new("a")
        .lower_bound(10.0)
        .upper_bound(20.0);
    let ref b = LpInteger::new("b");

    assert_eq!(a + b, AddExpr(Rc::new(ConsInt(a.clone())), Rc::new(ConsInt(b.clone()))));
}

#[test]
fn expressions_to_string() {
    let ref a = LpInteger::new("a");
    let ref b = LpInteger::new("b");
    let ref c = LpInteger::new("c");

    assert_eq!((a + 2*b + c).to_string(), "a + 2 b + c");
    assert_eq!((a + b*2 + c).to_string(), "a + 2 b + c");
    assert_eq!((a + b*2 + 3 * 2 * c).to_string(), "a + 2 b + 6 c");
    assert_eq!((a + 2).to_string(), "a + 2");
    assert_eq!((2*a + 2*b -4*c).to_string(), "2 a + 2 b - 4 c");
    assert_eq!((-2*a).to_string(), "-2 a");
}

#[test]
fn constraints_to_string() {
    let ref a = LpInteger::new("a");
    let ref b = LpInteger::new("b");
    let ref c = LpInteger::new("c");

    assert_eq!((a+b).equal(10).to_string(), "a + b = 10");
    assert_eq!((2*a + b).ge(10).to_string(), "2 a + b >= 10");
    assert_eq!((2*a + b + 20).ge(c).to_string(), "2 a + b - c >= -20");
    assert_eq!((-a).ge(10).to_string(), "-a >= 10");
    assert_eq!((2*a - 20 + b).ge(-c).to_string(), "2 a + b + c >= 20");
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

// Manage the linear volume that stores metadata on pool levels 5-7.

use std::convert::From;
use std::error::Error;
use std::fs::{create_dir, OpenOptions, read_dir, remove_file, rename};
use std::io::ErrorKind;
use std::io::prelude::*;
use std::os::unix::io::AsRawFd;
use std::path::PathBuf;

use devicemapper::{LinearDev, DM, Segment};
use serde_json;
use nix::unistd::fsync;

use super::super::engine::HasUuid;
use super::super::errors::EngineResult;
use super::super::types::{FilesystemUuid, PoolUuid};

use super::engine::DEV_PATH;
use super::filesystem::{create_fs, mount_fs, unmount_fs, StratFilesystem};
use super::serde_structs::{FilesystemSave, Recordable};

// TODO: Monitor fs size and extend linear and fs if needed
// TODO: Document format of stuff on MDV in SWDD (currently ad-hoc)

#[derive(Debug)]
pub struct MetadataVol {
    dev: LinearDev,
    mount_pt: PathBuf,
}

impl MetadataVol {
    /// Initialize a new Metadata Volume.
    pub fn initialize(pool_uuid: &PoolUuid, dev: LinearDev) -> EngineResult<MetadataVol> {
        try!(create_fs(try!(dev.devnode()).as_path()));
        MetadataVol::setup(pool_uuid, dev)
    }

    /// Set up an existing Metadata Volume.
    pub fn setup(pool_uuid: &PoolUuid, dev: LinearDev) -> EngineResult<MetadataVol> {
        let filename = format!(".mdv-{}", pool_uuid.simple());
        let mount_pt: PathBuf = vec![DEV_PATH, &filename].iter().collect();

        if let Err(err) = create_dir(&mount_pt) {
            if err.kind() != ErrorKind::AlreadyExists {
                return Err(From::from(err));
            }
        }

        try!(mount_fs(&try!(dev.devnode()), &mount_pt));

        if let Err(err) = create_dir(&mount_pt.join("filesystems")) {
            if err.kind() != ErrorKind::AlreadyExists {
                return Err(From::from(err));
            }
        }

        Ok(MetadataVol { dev, mount_pt })
    }

    /// Save info on a new filesystem to persistent storage, or update
    /// the existing info on a filesystem.
    // Write to a temp file and then rename to actual filename, to
    // ensure file contents are not truncated if operation is
    // interrupted.
    pub fn save_fs(&self, fs: &StratFilesystem) -> EngineResult<()> {
        let data = try!(serde_json::to_string(&try!(fs.record())));
        let path = self.mount_pt
            .join("filesystems")
            .join(fs.uuid().simple().to_string())
            .with_extension("json");

        let temp_path = path.clone().with_extension("temp");

        // Braces to ensure f is closed before renaming
        {
            let mut f = try!(OpenOptions::new()
                                 .write(true)
                                 .create(true)
                                 .open(&temp_path));
            try!(f.write_all(data.as_bytes()));

            // Try really hard to make sure it goes to disk
            try!(f.flush());
            try!(fsync(f.as_raw_fd()));
        }

        try!(rename(temp_path, path));

        Ok(())
    }

    /// Remove info on a filesystem from persistent storage.
    pub fn rm_fs(&self, fs_uuid: &FilesystemUuid) -> EngineResult<()> {
        let fs_path = self.mount_pt
            .join("filesystems")
            .join(fs_uuid.simple().to_string())
            .with_extension("json");
        if let Err(err) = remove_file(fs_path) {
            if err.kind() != ErrorKind::NotFound {
                return Err(From::from(err));
            }
        }

        Ok(())
    }

    /// Check the current state of the MDV.
    pub fn check(&self) -> EngineResult<()> {
        for dir_e in try!(read_dir(self.mount_pt.join("filesystems"))) {
            let dir_e = try!(dir_e);

            // Clean up any lingering .temp files. These should only
            // exist if there was a crash during save_fs().
            if dir_e.path().ends_with(".temp") {
                match remove_file(dir_e.path()) {
                    Err(err) => {
                        debug!("could not remove file {:?}: {}",
                               dir_e.path(),
                               err.description())
                    }
                    Ok(_) => debug!("Cleaning up temp file {:?}", dir_e.path()),
                }
            }
        }

        Ok(())
    }

    #[allow(dead_code)]
    /// Get list of filesystems stored on the MDV.
    pub fn filesystems(&self) -> EngineResult<Vec<FilesystemSave>> {
        let mut filesystems = Vec::new();

        for dir_e in try!(read_dir(self.mount_pt.join("filesystems"))) {
            let dir_e = try!(dir_e);

            if dir_e.path().ends_with(".temp") {
                continue;
            }

            let mut f = try!(OpenOptions::new().read(true).open(&dir_e.path()));
            let mut data = Vec::new();
            try!(f.read_to_end(&mut data));

            filesystems.push(try!(serde_json::from_slice(&data)));
        }

        Ok(filesystems)
    }

    /// Return the segments used.
    pub fn segments(&self) -> &[Segment] {
        self.dev.segments()
    }

    /// Tear down a Metadata Volume.
    pub fn teardown(self, dm: &DM) -> EngineResult<()> {
        let v: Vec<&str> = Vec::new();
        try!(unmount_fs(&self.mount_pt, &v));
        try!(self.dev.teardown(dm));

        Ok(())
    }
}
<commit_msg>Use a constant for "filesystems"<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

// Manage the linear volume that stores metadata on pool levels 5-7.

use std::convert::From;
use std::error::Error;
use std::fs::{create_dir, OpenOptions, read_dir, remove_file, rename};
use std::io::ErrorKind;
use std::io::prelude::*;
use std::os::unix::io::AsRawFd;
use std::path::PathBuf;

use devicemapper::{LinearDev, DM, Segment};
use serde_json;
use nix::unistd::fsync;

use super::super::engine::HasUuid;
use super::super::errors::EngineResult;
use super::super::types::{FilesystemUuid, PoolUuid};

use super::engine::DEV_PATH;
use super::filesystem::{create_fs, mount_fs, unmount_fs, StratFilesystem};
use super::serde_structs::{FilesystemSave, Recordable};

// TODO: Monitor fs size and extend linear and fs if needed
// TODO: Document format of stuff on MDV in SWDD (currently ad-hoc)

const FILESYSTEM_DIR: &'static str = "filesystems";

#[derive(Debug)]
pub struct MetadataVol {
    dev: LinearDev,
    mount_pt: PathBuf,
}

impl MetadataVol {
    /// Initialize a new Metadata Volume.
    pub fn initialize(pool_uuid: &PoolUuid, dev: LinearDev) -> EngineResult<MetadataVol> {
        try!(create_fs(try!(dev.devnode()).as_path()));
        MetadataVol::setup(pool_uuid, dev)
    }

    /// Set up an existing Metadata Volume.
    pub fn setup(pool_uuid: &PoolUuid, dev: LinearDev) -> EngineResult<MetadataVol> {
        let filename = format!(".mdv-{}", pool_uuid.simple());
        let mount_pt: PathBuf = vec![DEV_PATH, &filename].iter().collect();

        if let Err(err) = create_dir(&mount_pt) {
            if err.kind() != ErrorKind::AlreadyExists {
                return Err(From::from(err));
            }
        }

        try!(mount_fs(&try!(dev.devnode()), &mount_pt));

        if let Err(err) = create_dir(&mount_pt.join(FILESYSTEM_DIR)) {
            if err.kind() != ErrorKind::AlreadyExists {
                return Err(From::from(err));
            }
        }

        Ok(MetadataVol { dev, mount_pt })
    }

    /// Save info on a new filesystem to persistent storage, or update
    /// the existing info on a filesystem.
    // Write to a temp file and then rename to actual filename, to
    // ensure file contents are not truncated if operation is
    // interrupted.
    pub fn save_fs(&self, fs: &StratFilesystem) -> EngineResult<()> {
        let data = try!(serde_json::to_string(&try!(fs.record())));
        let path = self.mount_pt
            .join(FILESYSTEM_DIR)
            .join(fs.uuid().simple().to_string())
            .with_extension("json");

        let temp_path = path.clone().with_extension("temp");

        // Braces to ensure f is closed before renaming
        {
            let mut f = try!(OpenOptions::new()
                                 .write(true)
                                 .create(true)
                                 .open(&temp_path));
            try!(f.write_all(data.as_bytes()));

            // Try really hard to make sure it goes to disk
            try!(f.flush());
            try!(fsync(f.as_raw_fd()));
        }

        try!(rename(temp_path, path));

        Ok(())
    }

    /// Remove info on a filesystem from persistent storage.
    pub fn rm_fs(&self, fs_uuid: &FilesystemUuid) -> EngineResult<()> {
        let fs_path = self.mount_pt
            .join(FILESYSTEM_DIR)
            .join(fs_uuid.simple().to_string())
            .with_extension("json");
        if let Err(err) = remove_file(fs_path) {
            if err.kind() != ErrorKind::NotFound {
                return Err(From::from(err));
            }
        }

        Ok(())
    }

    /// Check the current state of the MDV.
    pub fn check(&self) -> EngineResult<()> {
        for dir_e in try!(read_dir(self.mount_pt.join(FILESYSTEM_DIR))) {
            let dir_e = try!(dir_e);

            // Clean up any lingering .temp files. These should only
            // exist if there was a crash during save_fs().
            if dir_e.path().ends_with(".temp") {
                match remove_file(dir_e.path()) {
                    Err(err) => {
                        debug!("could not remove file {:?}: {}",
                               dir_e.path(),
                               err.description())
                    }
                    Ok(_) => debug!("Cleaning up temp file {:?}", dir_e.path()),
                }
            }
        }

        Ok(())
    }

    #[allow(dead_code)]
    /// Get list of filesystems stored on the MDV.
    pub fn filesystems(&self) -> EngineResult<Vec<FilesystemSave>> {
        let mut filesystems = Vec::new();

        for dir_e in try!(read_dir(self.mount_pt.join(FILESYSTEM_DIR))) {
            let dir_e = try!(dir_e);

            if dir_e.path().ends_with(".temp") {
                continue;
            }

            let mut f = try!(OpenOptions::new().read(true).open(&dir_e.path()));
            let mut data = Vec::new();
            try!(f.read_to_end(&mut data));

            filesystems.push(try!(serde_json::from_slice(&data)));
        }

        Ok(filesystems)
    }

    /// Return the segments used.
    pub fn segments(&self) -> &[Segment] {
        self.dev.segments()
    }

    /// Tear down a Metadata Volume.
    pub fn teardown(self, dm: &DM) -> EngineResult<()> {
        let v: Vec<&str> = Vec::new();
        try!(unmount_fs(&self.mount_pt, &v));
        try!(self.dev.teardown(dm));

        Ok(())
    }
}
<|endoftext|>


<commit_before>#![crate_type="staticlib"]
#![no_std]

extern crate core;
extern crate zinc;
#[macro_use] #[plugin] #[no_link] extern crate macro_platformtree;

use zinc::drivers::chario::CharIO;
use zinc::drivers::lcd::hd44780u::{Hd44780u, Font};

platformtree!(
  tiva_c@mcu {
    clock {
      source = "MOSC";
      xtal   = "X16_0MHz";
      pll    = false;
    }

    gpio {
      a {
        d7@5 { direction = "out"; }
      }
      b {
        rs@0 { direction = "out"; }
        en@1 { direction = "out"; }
        d6@4 { direction = "out"; }
      }
      e {
        d4@4 { direction = "out"; }
        d5@5 { direction = "out"; }
      }
    }

    timer {
      /* The mcu contain both 16/32bit and "wide" 32/64bit timers. */
      timer@w0 {
        /* prescale sysclk to 1Mhz since the wait code expects 1us
         * granularity */
        prescale = 80;
        mode = "periodic";
      }
    }
  }

  os {
    single_task {
      loop = "run";
      args {
        timer = &timer;
        rs   = &rs;
        en   = &en;
        d4   = &d4;
        d5   = &d5;
        d6   = &d6;
        d7   = &d7;
      }
    }
  }
);

pub fn run(args: &pt::run_args) {

  let lcd = Hd44780u::new(args.timer,
                          args.rs,
                          args.en,
                          [ args.d4, args.d5, args.d6, args.d7 ]);

  lcd.init(true, Font::Font5x8);

  // Create custom 'heart' character at index 0.
  lcd.custom_char_5x8(0,
                      [0b00000,
                       0b01010,
                       0b11111,
                       0b11111,
                       0b11111,
                       0b01110,
                       0b00100,
                       0b00000]);
  // Create custom 'stick figure' character at index 1
  lcd.custom_char_5x8(1,
                      [0b00100,
                       0b01010,
                       0b00100,
                       0b11111,
                       0b00100,
                       0b01010,
                       0b10001,
                       0b00000]);

  // Enable blinking
  lcd.display_control(true, false, true);

  // Display a message surounded by two hearts
  lcd.puts("\0  Hello Zinc  \0");

  // Move to the 2nd line
  lcd.set_pos(0, 1);

  // Write a line of stick figures
  lcd.puts("\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01");

  // Move the cursor back to the middle of the first line
  lcd.set_pos(8, 0);

  loop {}
}
<commit_msg>Fixed missing plugin feature in tiva_c demo<commit_after>#![feature(plugin)]
#![crate_type="staticlib"]
#![no_std]

extern crate core;
extern crate zinc;
#[macro_use] #[plugin] #[no_link] extern crate macro_platformtree;

use zinc::drivers::chario::CharIO;
use zinc::drivers::lcd::hd44780u::{Hd44780u, Font};

platformtree!(
  tiva_c@mcu {
    clock {
      source = "MOSC";
      xtal   = "X16_0MHz";
      pll    = false;
    }

    gpio {
      a {
        d7@5 { direction = "out"; }
      }
      b {
        rs@0 { direction = "out"; }
        en@1 { direction = "out"; }
        d6@4 { direction = "out"; }
      }
      e {
        d4@4 { direction = "out"; }
        d5@5 { direction = "out"; }
      }
    }

    timer {
      /* The mcu contain both 16/32bit and "wide" 32/64bit timers. */
      timer@w0 {
        /* prescale sysclk to 1Mhz since the wait code expects 1us
         * granularity */
        prescale = 80;
        mode = "periodic";
      }
    }
  }

  os {
    single_task {
      loop = "run";
      args {
        timer = &timer;
        rs   = &rs;
        en   = &en;
        d4   = &d4;
        d5   = &d5;
        d6   = &d6;
        d7   = &d7;
      }
    }
  }
);

pub fn run(args: &pt::run_args) {

  let lcd = Hd44780u::new(args.timer,
                          args.rs,
                          args.en,
                          [ args.d4, args.d5, args.d6, args.d7 ]);

  lcd.init(true, Font::Font5x8);

  // Create custom 'heart' character at index 0.
  lcd.custom_char_5x8(0,
                      [0b00000,
                       0b01010,
                       0b11111,
                       0b11111,
                       0b11111,
                       0b01110,
                       0b00100,
                       0b00000]);
  // Create custom 'stick figure' character at index 1
  lcd.custom_char_5x8(1,
                      [0b00100,
                       0b01010,
                       0b00100,
                       0b11111,
                       0b00100,
                       0b01010,
                       0b10001,
                       0b00000]);

  // Enable blinking
  lcd.display_control(true, false, true);

  // Display a message surounded by two hearts
  lcd.puts("\0  Hello Zinc  \0");

  // Move to the 2nd line
  lcd.set_pos(0, 1);

  // Write a line of stick figures
  lcd.puts("\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01");

  // Move the cursor back to the middle of the first line
  lcd.set_pos(8, 0);

  loop {}
}
<|endoftext|>


<commit_before>use std::borrow::Cow;

pub fn dv(input: &[u8]) -> Cow<str> {
    String::from_utf8_lossy(&input)
}

pub fn epoch_int() -> u64 {
    use std::time::{UNIX_EPOCH, SystemTime};

    let now = SystemTime::now();
    let unix = now.duration_since(UNIX_EPOCH).unwrap().as_secs();

    unix
}

pub fn split_string(input: &[u8]) -> Vec<Vec<u8>> {
    let mut buf: Vec<Vec<u8>> = Vec::new();
    let mut tmp: Vec<u8> = Vec::new();

    for (index, &i) in input.iter().enumerate() {
        if i == b' ' {
            buf.push(tmp);
            tmp = Vec::new();
            continue;
        }

        tmp.push(i);

        if index + 1 == input.len() {
            buf.push(tmp);
            break;
        }
    }

    buf
}

pub fn unsplit_string(argv: &[Vec<u8>], argc: usize, startidx: usize, max: usize) -> Vec<u8> {
    let mut dest: Vec<u8> = Vec::new();
    let mut vec: Vec<Vec<u8>> = Vec::new();

    for i in startidx..argc {
        vec.push(argv[i as usize].clone());
    }

    if max > vec.len() { return dest; }

    for i in 0..max {
        for j in 0..vec[i as usize].len() {
            dest.push(vec[i as usize][j as usize]);
        }
        dest.push(b' ');
    }

    dest
}

pub fn u8_slice_to_lower(input: &[u8]) -> Vec<u8> {
    use std::ascii::AsciiExt;

    let mut buf: Vec<u8> = input.to_vec().clone();
    for mut byte in &mut buf {
        byte.make_ascii_lowercase();
    }

    return buf;
}

pub fn trim_bytes_right(mut input: &[u8]) -> &[u8] {
    loop {
        match input.iter().next_back() {
            Some(&b'\r') | Some(&b'\n') => {
                input = &input[0..input.len()-1]
            }
            _ => break,
        }
    }

    input
}

#[test]
fn test_unsplit_string() {
    let my_argv: Vec<Vec<u8>> = vec![
        format!("A").into_bytes(),
        format!("BB").into_bytes(),
        format!("TEST").into_bytes(),
        format!("SOMETING").into_bytes(),
        format!("FDSAADFS").into_bytes(),
        format!("FADS").into_bytes(),
        format!("ASDf").into_bytes(),
    ];

    let new_unsplit = unsplit_string(&my_argv, 7, 3, 3);
    assert_eq!(&new_unsplit, b"SOMETING FDSAADFS FADS ");
    assert_eq!(new_unsplit.len(), 23);

    let my_argv: Vec<Vec<u8>> = vec![
        format!("B").into_bytes(),
        format!("#channel").into_bytes(),
        format!("9999999999").into_bytes(),
        format!("+stnzl").into_bytes(),
        format!("554").into_bytes(),
        format!("AAAAA:o,AAAAB,AAAAC").into_bytes(),
    ];

    let new_unsplit = unsplit_string(&my_argv, 6, 3, 2);
    assert_eq!(&new_unsplit, b"+stnzl 554 ");
    assert_eq!(new_unsplit.len(), 11);
}

#[test]
fn test_split_string() {
    let s = split_string(&format!("+ntl 34").into_bytes());
    assert_eq!(s.len(), 2);
    assert_eq!(s[0], b"+ntl");
    assert_eq!(s[1], b"34");

    let s = split_string(&format!("fdas fasd adsf asfd dfas").into_bytes());
    assert_eq!(s.len(), 5);
    assert_eq!(s[0], b"fdas");
    assert_eq!(s[1], b"fasd");
    assert_eq!(s[2], b"adsf");
    assert_eq!(s[3], b"asfd");
    assert_eq!(s[4], b"dfas");

    let s = split_string(&format!("aaaaaaa").into_bytes());
    assert_eq!(s.len(), 1);
    assert_eq!(s[0], b"aaaaaaa");

    let s = split_string(&format!("").into_bytes());
    assert_eq!(s.len(), 0);
}

#[test]
fn test_u8_slice_to_lower() {
    let caps = &String::from("THIS IS IN ALL CAPS").into_bytes();
    let lowered = u8_slice_to_lower(&caps);
    assert_eq!(lowered.len(), 19);
    assert_eq!(lowered, b"this is in all caps");
}

#[test]
fn test_trim_bytes_right() {
    let mystr: &[u8] = &String::from("This has newlines and a carriage return\r\n").into_bytes();
    let clean = trim_bytes_right(mystr);
    assert_eq!(clean.len(), 39);
    assert_eq!(clean[38], b'n');
}
<commit_msg>utils: Add ceiling division<commit_after>use std::borrow::Cow;

pub fn dv(input: &[u8]) -> Cow<str> {
    String::from_utf8_lossy(&input)
}

pub fn epoch_int() -> u64 {
    use std::time::{UNIX_EPOCH, SystemTime};

    let now = SystemTime::now();
    let unix = now.duration_since(UNIX_EPOCH).unwrap().as_secs();

    unix
}

pub fn split_string(input: &[u8]) -> Vec<Vec<u8>> {
    let mut buf: Vec<Vec<u8>> = Vec::new();
    let mut tmp: Vec<u8> = Vec::new();

    for (index, &i) in input.iter().enumerate() {
        if i == b' ' {
            buf.push(tmp);
            tmp = Vec::new();
            continue;
        }

        tmp.push(i);

        if index + 1 == input.len() {
            buf.push(tmp);
            break;
        }
    }

    buf
}

pub fn unsplit_string(argv: &[Vec<u8>], argc: usize, startidx: usize, max: usize) -> Vec<u8> {
    let mut dest: Vec<u8> = Vec::new();
    let mut vec: Vec<Vec<u8>> = Vec::new();

    for i in startidx..argc {
        vec.push(argv[i as usize].clone());
    }

    if max > vec.len() { return dest; }

    for i in 0..max {
        for j in 0..vec[i as usize].len() {
            dest.push(vec[i as usize][j as usize]);
        }
        dest.push(b' ');
    }

    dest
}

pub fn u8_slice_to_lower(input: &[u8]) -> Vec<u8> {
    use std::ascii::AsciiExt;

    let mut buf: Vec<u8> = input.to_vec().clone();
    for mut byte in &mut buf {
        byte.make_ascii_lowercase();
    }

    return buf;
}

pub fn trim_bytes_right(mut input: &[u8]) -> &[u8] {
    loop {
        match input.iter().next_back() {
            Some(&b'\r') | Some(&b'\n') => {
                input = &input[0..input.len()-1]
            }
            _ => break,
        }
    }

    input
}

pub fn ceiling_division(left: usize, right: usize) -> usize {
    assert!(left > 0);

    1 + ((left - 1) / right)
}

#[test]
fn test_ceiling_division() {
    assert_eq!(ceiling_division(499, 500), 1);
    assert_eq!(ceiling_division(500, 500), 1);
    assert_eq!(ceiling_division(501, 500), 2);
}

#[test]
fn test_unsplit_string() {
    let my_argv: Vec<Vec<u8>> = vec![
        format!("A").into_bytes(),
        format!("BB").into_bytes(),
        format!("TEST").into_bytes(),
        format!("SOMETING").into_bytes(),
        format!("FDSAADFS").into_bytes(),
        format!("FADS").into_bytes(),
        format!("ASDf").into_bytes(),
    ];

    let new_unsplit = unsplit_string(&my_argv, 7, 3, 3);
    assert_eq!(&new_unsplit, b"SOMETING FDSAADFS FADS ");
    assert_eq!(new_unsplit.len(), 23);

    let my_argv: Vec<Vec<u8>> = vec![
        format!("B").into_bytes(),
        format!("#channel").into_bytes(),
        format!("9999999999").into_bytes(),
        format!("+stnzl").into_bytes(),
        format!("554").into_bytes(),
        format!("AAAAA:o,AAAAB,AAAAC").into_bytes(),
    ];

    let new_unsplit = unsplit_string(&my_argv, 6, 3, 2);
    assert_eq!(&new_unsplit, b"+stnzl 554 ");
    assert_eq!(new_unsplit.len(), 11);
}

#[test]
fn test_split_string() {
    let s = split_string(&format!("+ntl 34").into_bytes());
    assert_eq!(s.len(), 2);
    assert_eq!(s[0], b"+ntl");
    assert_eq!(s[1], b"34");

    let s = split_string(&format!("fdas fasd adsf asfd dfas").into_bytes());
    assert_eq!(s.len(), 5);
    assert_eq!(s[0], b"fdas");
    assert_eq!(s[1], b"fasd");
    assert_eq!(s[2], b"adsf");
    assert_eq!(s[3], b"asfd");
    assert_eq!(s[4], b"dfas");

    let s = split_string(&format!("aaaaaaa").into_bytes());
    assert_eq!(s.len(), 1);
    assert_eq!(s[0], b"aaaaaaa");

    let s = split_string(&format!("").into_bytes());
    assert_eq!(s.len(), 0);
}

#[test]
fn test_u8_slice_to_lower() {
    let caps = &String::from("THIS IS IN ALL CAPS").into_bytes();
    let lowered = u8_slice_to_lower(&caps);
    assert_eq!(lowered.len(), 19);
    assert_eq!(lowered, b"this is in all caps");
}

#[test]
fn test_trim_bytes_right() {
    let mystr: &[u8] = &String::from("This has newlines and a carriage return\r\n").into_bytes();
    let clean = trim_bytes_right(mystr);
    assert_eq!(clean.len(), 39);
    assert_eq!(clean[38], b'n');
}
<|endoftext|>


<commit_before>use std::cmp::PartialEq;
use std::fmt;
use std::borrow::Cow;

use unicase;
use quoted_string::{self, ContentChars, AsciiCaseInsensitiveEq};

/// A parameter value section of a `Mime`.
///
/// Except for the `charset` parameter, parameters
/// are compared case sensitive
#[derive(Clone, Copy, Eq, PartialOrd, Ord, Hash)]
pub struct Value<'a> {
    pub(crate) source: &'a str,
    pub(crate) ascii_case_insensitive: bool
}

impl<'a> Value<'a> {

    /// Returns the underlying representation.
    ///
    /// The underlying representation differs from the content,
    /// as it can contain quotes surrounding the content and
    /// quoted-pairs, even if non of them are necessary to
    /// represent the content.
    ///
    /// For example the representation `r#""a\"\ b""#` corresponds
    /// to the content `r#""a" b"#`. Another semantically  equivalent
    /// (i.e. with the same content) representation  is `r#""a\" b""`
    ///
    /// # Example
    ///
    /// ```
    /// let mime = r#"text/plain; param="abc def""#.parse::<mime::Mime>().unwrap();
    /// let param = mime.get_param("param").unwrap();
    /// assert_eq!(param.as_str_repr(), r#""abc def""#);
    /// ```
    pub fn as_str_repr(&self) -> &'a str {
        self.source
    }

    /// Returns the content of this instance.
    ///
    /// It differs to the representation in that it will remove the
    /// quotation marks from the quoted string and will "unquote"
    /// quoted pairs.
    ///
    /// If the underlying representation is a quoted string containing
    /// quoted-pairs `Cow::Owned` is returned.
    ///
    /// If the underlying representation is a quoted-string without
    /// quoted-pairs `Cow::Borrowed` is returned as normal
    /// str slicing can be used to strip the surrounding double quoted.
    ///
    /// If the underlying representation is not a quoted-string
    /// `Cow::Borrowed` is returned, too.
    ///
    /// # Example
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let raw_mime = r#"text/plain; p1="char is \a"; p2="simple"; p3=simple2"#;
    /// let mime = raw_mime.parse::<mime::Mime>().unwrap();
    ///
    /// let param1 = mime.get_param("p1").unwrap();
    /// let expected: Cow<'static, str> = Cow::Owned(r#"char is a"#.into());
    /// assert_eq!(param1.to_content(), expected);
    ///
    /// let param2 = mime.get_param("p2").unwrap();
    /// assert_eq!(param2.to_content(), Cow::Borrowed("simple"));
    ///
    /// let param3 = mime.get_param("p3").unwrap();
    /// assert_eq!(param3.to_content(), Cow::Borrowed("simple2"));
    /// ```
    ///
    pub fn to_content(&self) -> Cow<'a, str> {
        quoted_string::unquote_unchecked(self.source)
    }

    fn eq_str(&self, s: &str) -> bool {
        if self.source.chars().next() == Some('"') {
            let content_chars = ContentChars::from_string_unchecked(self.source);
            if self.ascii_case_insensitive {
                content_chars.eq_ignore_ascii_case(s)
            } else {
                content_chars == s
            }
        } else {
            if self.ascii_case_insensitive {
                unicase::eq_ascii(self.source, s)
            } else {
                self.source == s
            }
        }

    }

}

impl<'a, 'b> PartialEq<Value<'b>> for Value<'a> {
    #[inline]
    fn eq(&self, other: &Value<'b>) -> bool {
        let left_content_chars = ContentChars::from_string_unchecked(self.source);
        let right_content_chars = ContentChars::from_string_unchecked(other.source);

        if self.ascii_case_insensitive || other.ascii_case_insensitive {
            left_content_chars.eq_ignore_ascii_case(&right_content_chars)
        } else {
            left_content_chars == right_content_chars
        }
    }
}

impl<'a, 'b> PartialEq<Value<'b>> for &'a str {
    #[inline]
    fn eq(&self, other: &Value<'b>) -> bool {
        other.eq_str(*self)
    }
}

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

impl<'a, 'b> PartialEq<&'b str> for Value<'a> {
    #[inline]
    fn eq(&self, other: & &'b str) -> bool {
        self.eq_str(*other)
    }
}

impl<'a> From<Value<'a>> for Cow<'a, str> {
    #[inline]
    fn from(value: Value<'a>) -> Self {
        value.to_content()
    }
}

impl<'a> fmt::Debug for Value<'a> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(self.source, f)
    }
}

impl<'a> fmt::Display for Value<'a> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self.source, f)
    }
}

#[cfg(test)]
mod test {
    use std::cmp::PartialEq;
    use std::fmt::Debug;

    use super::Value;

    fn bidi_eq<A: Debug+PartialEq<B>, B: Debug+PartialEq<A>>(left: A, right: B) {
        assert_eq!(left, right);
        assert_eq!(right, left);
    }

    fn bidi_ne<A: Debug+PartialEq<B>, B: Debug+PartialEq<A>>(left: A, right: B) {
        assert_ne!(left, right);
        assert_ne!(right, left);
    }

    #[test]
    fn test_value_eq_str() {
        let value = Value {
            source: "abc",
            ascii_case_insensitive: false
        };
        let value_quoted = Value {
            source: "\"abc\"",
            ascii_case_insensitive: false
        };
        let value_quoted_with_esacpes = Value {
            source: "\"a\\bc\"",
            ascii_case_insensitive: false
        };

        bidi_eq(value, "abc");
        bidi_ne(value, "\"abc\"");
        bidi_ne(value, "\"a\\bc\"");

        bidi_eq(value_quoted, "abc");
        bidi_ne(value_quoted, "\"abc\"");
        bidi_ne(value_quoted, "\"a\\bc\"");

        bidi_eq(value_quoted_with_esacpes, "abc");
        bidi_ne(value_quoted_with_esacpes, "\"abc\"");
        bidi_ne(value_quoted_with_esacpes, "\"a\\bc\"");

        assert_ne!(value, "aBc");
        assert_ne!(value_quoted, "aBc");
        assert_ne!(value_quoted_with_esacpes, "aBc");
    }

    #[test]
    fn test_value_eq_str_ascii_case_insensitive() {
        let value = Value {
            source: "abc",
            ascii_case_insensitive: true
        };
        let value_quoted = Value {
            source: "\"abc\"",
            ascii_case_insensitive: true
        };
        let value_quoted_with_esacpes = Value {
            source: "\"a\\bc\"",
            ascii_case_insensitive: true
        };

        //1st. all case sensitive checks which still apply
        bidi_eq(value, "abc");
        bidi_ne(value, "\"abc\"");
        bidi_ne(value, "\"a\\bc\"");

        bidi_eq(value_quoted, "abc");
        bidi_ne(value_quoted, "\"abc\"");
        bidi_ne(value_quoted, "\"a\\bc\"");

        bidi_eq(value_quoted_with_esacpes, "abc");
        bidi_ne(value_quoted_with_esacpes, "\"abc\"");
        bidi_ne(value_quoted_with_esacpes, "\"a\\bc\"");

        //2nd the case insensitive check
        bidi_eq(value, "aBc");
        bidi_ne(value, "\"aBc\"");
        bidi_ne(value, "\"a\\Bc\"");

        bidi_eq(value_quoted, "aBc");
        bidi_ne(value_quoted, "\"aBc\"");
        bidi_ne(value_quoted, "\"a\\Bc\"");

        bidi_eq(value_quoted_with_esacpes, "aBc");
        bidi_ne(value_quoted_with_esacpes, "\"aBc\"");
        bidi_ne(value_quoted_with_esacpes, "\"a\\Bc\"");
    }

    #[test]
    fn test_value_eq_value() {
        let value = Value {
            source: "abc",
            ascii_case_insensitive: false
        };
        let value_quoted = Value {
            source: "\"abc\"",
            ascii_case_insensitive: false
        };
        let value_quoted_with_esacpes = Value {
            source: "\"a\\bc\"",
            ascii_case_insensitive: false
        };
        assert_eq!(value, value);
        assert_eq!(value_quoted, value_quoted);
        assert_eq!(value_quoted_with_esacpes, value_quoted_with_esacpes);

        bidi_eq(value, value_quoted);
        bidi_eq(value, value_quoted_with_esacpes);
        bidi_eq(value_quoted, value_quoted_with_esacpes);
    }

    #[test]
    fn test_value_eq_value_case_insensitive() {
        let value = Value {
            source: "Abc",
            ascii_case_insensitive: true
        };
        let value_quoted = Value {
            source: "\"aBc\"",
            ascii_case_insensitive: true
        };
        let value_quoted_with_esacpes = Value {
            source: "\"a\\bC\"",
            ascii_case_insensitive: true
        };
        assert_eq!(value, value);
        assert_eq!(value_quoted, value_quoted);
        assert_eq!(value_quoted_with_esacpes, value_quoted_with_esacpes);

        bidi_eq(value, value_quoted);
        bidi_eq(value, value_quoted_with_esacpes);
        bidi_eq(value_quoted, value_quoted_with_esacpes);
    }

    #[test]
    fn test_value_eq_value_mixed_case_sensitivity() {
        let value = Value {
            source: "Abc",
            ascii_case_insensitive: true
        };
        let value_quoted = Value {
            source: "\"aBc\"",
            ascii_case_insensitive: false
        };
        let value_quoted_with_esacpes = Value {
            source: "\"a\\bC\"",
            ascii_case_insensitive: false
        };

        bidi_eq(value, value_quoted);
        bidi_eq(value, value_quoted_with_esacpes);

        //both are ascii case insensitive
        bidi_ne(value_quoted, value_quoted_with_esacpes);
    }

}<commit_msg>test: added tests for as_str_repr and to_content<commit_after>use std::cmp::PartialEq;
use std::fmt;
use std::borrow::Cow;

use unicase;
use quoted_string::{self, ContentChars, AsciiCaseInsensitiveEq};

/// A parameter value section of a `Mime`.
///
/// Except for the `charset` parameter, parameters
/// are compared case sensitive
#[derive(Clone, Copy, Eq, PartialOrd, Ord, Hash)]
pub struct Value<'a> {
    pub(crate) source: &'a str,
    pub(crate) ascii_case_insensitive: bool
}

impl<'a> Value<'a> {

    /// Returns the underlying representation.
    ///
    /// The underlying representation differs from the content,
    /// as it can contain quotes surrounding the content and
    /// quoted-pairs, even if non of them are necessary to
    /// represent the content.
    ///
    /// For example the representation `r#""a\"\ b""#` corresponds
    /// to the content `r#""a" b"#`. Another semantically  equivalent
    /// (i.e. with the same content) representation  is `r#""a\" b""`
    ///
    /// # Example
    ///
    /// ```
    /// let mime = r#"text/plain; param="abc def""#.parse::<mime::Mime>().unwrap();
    /// let param = mime.get_param("param").unwrap();
    /// assert_eq!(param.as_str_repr(), r#""abc def""#);
    /// ```
    pub fn as_str_repr(&self) -> &'a str {
        self.source
    }

    /// Returns the content of this instance.
    ///
    /// It differs to the representation in that it will remove the
    /// quotation marks from the quoted string and will "unquote"
    /// quoted pairs.
    ///
    /// If the underlying representation is a quoted string containing
    /// quoted-pairs `Cow::Owned` is returned.
    ///
    /// If the underlying representation is a quoted-string without
    /// quoted-pairs `Cow::Borrowed` is returned as normal
    /// str slicing can be used to strip the surrounding double quoted.
    ///
    /// If the underlying representation is not a quoted-string
    /// `Cow::Borrowed` is returned, too.
    ///
    /// # Example
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let raw_mime = r#"text/plain; p1="char is \a"; p2="simple"; p3=simple2"#;
    /// let mime = raw_mime.parse::<mime::Mime>().unwrap();
    ///
    /// let param1 = mime.get_param("p1").unwrap();
    /// let expected: Cow<'static, str> = Cow::Owned(r#"char is a"#.into());
    /// assert_eq!(param1.to_content(), expected);
    ///
    /// let param2 = mime.get_param("p2").unwrap();
    /// assert_eq!(param2.to_content(), Cow::Borrowed("simple"));
    ///
    /// let param3 = mime.get_param("p3").unwrap();
    /// assert_eq!(param3.to_content(), Cow::Borrowed("simple2"));
    /// ```
    ///
    pub fn to_content(&self) -> Cow<'a, str> {
        quoted_string::unquote_unchecked(self.source)
    }

    fn eq_str(&self, s: &str) -> bool {
        if self.source.chars().next() == Some('"') {
            let content_chars = ContentChars::from_string_unchecked(self.source);
            if self.ascii_case_insensitive {
                content_chars.eq_ignore_ascii_case(s)
            } else {
                content_chars == s
            }
        } else {
            if self.ascii_case_insensitive {
                unicase::eq_ascii(self.source, s)
            } else {
                self.source == s
            }
        }

    }

}

impl<'a, 'b> PartialEq<Value<'b>> for Value<'a> {
    #[inline]
    fn eq(&self, other: &Value<'b>) -> bool {
        let left_content_chars = ContentChars::from_string_unchecked(self.source);
        let right_content_chars = ContentChars::from_string_unchecked(other.source);

        if self.ascii_case_insensitive || other.ascii_case_insensitive {
            left_content_chars.eq_ignore_ascii_case(&right_content_chars)
        } else {
            left_content_chars == right_content_chars
        }
    }
}

impl<'a, 'b> PartialEq<Value<'b>> for &'a str {
    #[inline]
    fn eq(&self, other: &Value<'b>) -> bool {
        other.eq_str(*self)
    }
}

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

impl<'a, 'b> PartialEq<&'b str> for Value<'a> {
    #[inline]
    fn eq(&self, other: & &'b str) -> bool {
        self.eq_str(*other)
    }
}

impl<'a> From<Value<'a>> for Cow<'a, str> {
    #[inline]
    fn from(value: Value<'a>) -> Self {
        value.to_content()
    }
}

impl<'a> fmt::Debug for Value<'a> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(self.source, f)
    }
}

impl<'a> fmt::Display for Value<'a> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self.source, f)
    }
}

#[cfg(test)]
mod test {
    use std::borrow::Cow;
    use std::cmp::PartialEq;
    use std::fmt::Debug;

    use super::Value;

    fn bidi_eq<A: Debug+PartialEq<B>, B: Debug+PartialEq<A>>(left: A, right: B) {
        assert_eq!(left, right);
        assert_eq!(right, left);
    }

    fn bidi_ne<A: Debug+PartialEq<B>, B: Debug+PartialEq<A>>(left: A, right: B) {
        assert_ne!(left, right);
        assert_ne!(right, left);
    }

    #[test]
    fn test_value_eq_str() {
        let value = Value {
            source: "abc",
            ascii_case_insensitive: false
        };
        let value_quoted = Value {
            source: "\"abc\"",
            ascii_case_insensitive: false
        };
        let value_quoted_with_esacpes = Value {
            source: "\"a\\bc\"",
            ascii_case_insensitive: false
        };

        bidi_eq(value, "abc");
        bidi_ne(value, "\"abc\"");
        bidi_ne(value, "\"a\\bc\"");

        bidi_eq(value_quoted, "abc");
        bidi_ne(value_quoted, "\"abc\"");
        bidi_ne(value_quoted, "\"a\\bc\"");

        bidi_eq(value_quoted_with_esacpes, "abc");
        bidi_ne(value_quoted_with_esacpes, "\"abc\"");
        bidi_ne(value_quoted_with_esacpes, "\"a\\bc\"");

        assert_ne!(value, "aBc");
        assert_ne!(value_quoted, "aBc");
        assert_ne!(value_quoted_with_esacpes, "aBc");
    }

    #[test]
    fn test_value_eq_str_ascii_case_insensitive() {
        let value = Value {
            source: "abc",
            ascii_case_insensitive: true
        };
        let value_quoted = Value {
            source: "\"abc\"",
            ascii_case_insensitive: true
        };
        let value_quoted_with_esacpes = Value {
            source: "\"a\\bc\"",
            ascii_case_insensitive: true
        };

        //1st. all case sensitive checks which still apply
        bidi_eq(value, "abc");
        bidi_ne(value, "\"abc\"");
        bidi_ne(value, "\"a\\bc\"");

        bidi_eq(value_quoted, "abc");
        bidi_ne(value_quoted, "\"abc\"");
        bidi_ne(value_quoted, "\"a\\bc\"");

        bidi_eq(value_quoted_with_esacpes, "abc");
        bidi_ne(value_quoted_with_esacpes, "\"abc\"");
        bidi_ne(value_quoted_with_esacpes, "\"a\\bc\"");

        //2nd the case insensitive check
        bidi_eq(value, "aBc");
        bidi_ne(value, "\"aBc\"");
        bidi_ne(value, "\"a\\Bc\"");

        bidi_eq(value_quoted, "aBc");
        bidi_ne(value_quoted, "\"aBc\"");
        bidi_ne(value_quoted, "\"a\\Bc\"");

        bidi_eq(value_quoted_with_esacpes, "aBc");
        bidi_ne(value_quoted_with_esacpes, "\"aBc\"");
        bidi_ne(value_quoted_with_esacpes, "\"a\\Bc\"");
    }

    #[test]
    fn test_value_eq_value() {
        let value = Value {
            source: "abc",
            ascii_case_insensitive: false
        };
        let value_quoted = Value {
            source: "\"abc\"",
            ascii_case_insensitive: false
        };
        let value_quoted_with_esacpes = Value {
            source: "\"a\\bc\"",
            ascii_case_insensitive: false
        };
        assert_eq!(value, value);
        assert_eq!(value_quoted, value_quoted);
        assert_eq!(value_quoted_with_esacpes, value_quoted_with_esacpes);

        bidi_eq(value, value_quoted);
        bidi_eq(value, value_quoted_with_esacpes);
        bidi_eq(value_quoted, value_quoted_with_esacpes);
    }

    #[test]
    fn test_value_eq_value_case_insensitive() {
        let value = Value {
            source: "Abc",
            ascii_case_insensitive: true
        };
        let value_quoted = Value {
            source: "\"aBc\"",
            ascii_case_insensitive: true
        };
        let value_quoted_with_esacpes = Value {
            source: "\"a\\bC\"",
            ascii_case_insensitive: true
        };
        assert_eq!(value, value);
        assert_eq!(value_quoted, value_quoted);
        assert_eq!(value_quoted_with_esacpes, value_quoted_with_esacpes);

        bidi_eq(value, value_quoted);
        bidi_eq(value, value_quoted_with_esacpes);
        bidi_eq(value_quoted, value_quoted_with_esacpes);
    }

    #[test]
    fn test_value_eq_value_mixed_case_sensitivity() {
        let value = Value {
            source: "Abc",
            ascii_case_insensitive: true
        };
        let value_quoted = Value {
            source: "\"aBc\"",
            ascii_case_insensitive: false
        };
        let value_quoted_with_esacpes = Value {
            source: "\"a\\bC\"",
            ascii_case_insensitive: false
        };

        bidi_eq(value, value_quoted);
        bidi_eq(value, value_quoted_with_esacpes);

        //both are ascii case insensitive
        bidi_ne(value_quoted, value_quoted_with_esacpes);
    }

    #[test]
    fn test_as_str_repr() {
        let value = Value { source: "\"ab cd\"", ascii_case_insensitive: false };
        assert_eq!(value, "ab cd");
        assert_eq!(value.as_str_repr(), "\"ab cd\"");
    }

    #[test]
    fn test_to_content_not_quoted() {
        let value = Value { source: "abc", ascii_case_insensitive: false};
        assert_eq!(value.to_content(), Cow::Borrowed("abc"));
    }

    #[test]
    fn test_to_content_quoted_simple() {
        let value = Value { source: "\"ab cd\"", ascii_case_insensitive: false};
        assert_eq!(value.to_content(), Cow::Borrowed("ab cd"));
    }

    #[test]
    fn test_to_content_with_quoted_pair() {
        let value = Value { source: "\"ab\\\"cd\"", ascii_case_insensitive: false};
        assert_eq!(value, "ab\"cd");
        let expected: Cow<'static, str> = Cow::Owned("ab\"cd".into());
        assert_eq!(value.to_content(), expected);
    }

}<|endoftext|>