<commit_before>use bytes::BytesMut;
use http::HeaderMap;
use http::header::{CONTENT_LENGTH, TRANSFER_ENCODING};
use http::header::{HeaderValue, OccupiedEntry, ValueIter};

/// Maximum number of bytes needed to serialize a u64 into ASCII decimal.
const MAX_DECIMAL_U64_BYTES: usize = 20;

pub fn connection_keep_alive(value: &HeaderValue) -> bool {
    connection_has(value, "keep-alive")
}

pub fn connection_close(value: &HeaderValue) -> bool {
    connection_has(value, "close")
}

fn connection_has(value: &HeaderValue, needle: &str) -> bool {
    if let Ok(s) = value.to_str() {
        for val in s.split(',') {
            if eq_ascii(val.trim(), needle) {
                return true;
            }
        }
    }
    false
}

pub fn content_length_parse(value: &HeaderValue) -> Option<u64> {
    value
        .to_str()
        .ok()
        .and_then(|s| s.parse().ok())
}

pub fn content_length_parse_all(headers: &HeaderMap) -> Option<u64> {
    content_length_parse_all_values(headers.get_all(CONTENT_LENGTH).into_iter())
}

pub fn content_length_parse_all_values(values: ValueIter<HeaderValue>) -> Option<u64> {
    // If multiple Content-Length headers were sent, everything can still
    // be alright if they all contain the same value, and all parse
    // correctly. If not, then it's an error.

    let folded = values
        .fold(None, |prev, line| match prev {
            Some(Ok(prev)) => {
                Some(line
                    .to_str()
                    .map_err(|_| ())
                    .and_then(|s| s.parse().map_err(|_| ()))
                    .and_then(|n| if prev == n { Ok(n) } else { Err(()) }))
            },
            None => {
                Some(line
                    .to_str()
                    .map_err(|_| ())
                    .and_then(|s| s.parse().map_err(|_| ())))
            },
            Some(Err(())) => Some(Err(())),
        });

    if let Some(Ok(n)) = folded {
        Some(n)
    } else {
        None
    }
}

pub fn content_length_value(len: u64) -> HeaderValue {
    let mut len_buf = BytesMut::with_capacity(MAX_DECIMAL_U64_BYTES);
    ::itoa::fmt(&mut len_buf, len)
        .expect("BytesMut can hold a decimal u64");
    // safe because u64 Display is ascii numerals
    unsafe {
        HeaderValue::from_shared_unchecked(len_buf.freeze())
    }
}

pub fn set_content_length_if_missing(headers: &mut HeaderMap, len: u64) {
    headers
        .entry(CONTENT_LENGTH)
        .unwrap()
        .or_insert(content_length_value(len));
}

pub fn transfer_encoding_is_chunked(headers: &HeaderMap) -> bool {
    is_chunked(headers.get_all(TRANSFER_ENCODING).into_iter())
}

pub fn is_chunked(mut encodings: ValueIter<HeaderValue>) -> bool {
    // chunked must always be the last encoding, according to spec
    if let Some(line) = encodings.next_back() {
        return is_chunked_(line);
    }

    false
}

pub fn is_chunked_(value: &HeaderValue) -> bool {
    // chunked must always be the last encoding, according to spec
    if let Ok(s) = value.to_str() {
        if let Some(encoding) = s.rsplit(',').next() {
            return eq_ascii(encoding.trim(), "chunked");
        }
    }

    false
}

pub fn add_chunked(mut entry: OccupiedEntry<HeaderValue>) {
    const CHUNKED: &'static str = "chunked";

    if let Some(line) = entry.iter_mut().next_back() {
        // + 2 for ", "
        let new_cap = line.as_bytes().len() + CHUNKED.len() + 2;
        let mut buf = BytesMut::with_capacity(new_cap);
        buf.copy_from_slice(line.as_bytes());
        buf.copy_from_slice(b", ");
        buf.copy_from_slice(CHUNKED.as_bytes());

        *line = HeaderValue::from_shared(buf.freeze())
            .expect("original header value plus ascii is valid");
        return;
    }

    entry.insert(HeaderValue::from_static(CHUNKED));
}

fn eq_ascii(left: &str, right: &str) -> bool {
    // As of Rust 1.23, str gained this method inherently, and so the
    // compiler says this trait is unused.
    //
    // TODO: Once our minimum Rust compiler version is >=1.23, this can be removed.
    #[allow(unused, deprecated)]
    use std::ascii::AsciiExt;

    left.eq_ignore_ascii_case(right)
}

#[cfg(test)]
mod tests {

    #[cfg(feature = "nightly")]
    use test::Bencher;

    #[test]
    fn assert_max_decimal_u64_bytes() {
        assert_eq!(
            super::MAX_DECIMAL_U64_BYTES,
            ::std::u64::MAX.to_string().len()
        );
    }

    #[cfg(feature = "nightly")]
    #[bench]
    fn bench_content_length_fmt_small(b: &mut Bencher) {
        let n = 13;
        let s = n.to_string();
        b.bytes = s.len() as u64;

        b.iter(|| {
            let val = super::content_length_value(n);
            debug_assert_eq!(val, s);
            ::test::black_box(&val);
        })
    }

    #[cfg(feature = "nightly")]
    #[bench]
    fn bench_content_length_fmt_big(b: &mut Bencher) {
        let n = 326_893_010;
        let s = n.to_string();
        b.bytes = s.len() as u64;

        b.iter(|| {
            let val = super::content_length_value(n);
            debug_assert_eq!(val, s);
            ::test::black_box(&val);
        })
    }
}
<commit_msg>perf(headers): don't allocate to format content-length on 32bit when number is not huge<commit_after>use std::mem;

use bytes::BytesMut;
use http::HeaderMap;
use http::header::{CONTENT_LENGTH, TRANSFER_ENCODING};
use http::header::{HeaderValue, OccupiedEntry, ValueIter};

/// Maximum number of bytes needed to serialize a u64 into ASCII decimal.
const MAX_DECIMAL_U64_BYTES: usize = 20;

pub fn connection_keep_alive(value: &HeaderValue) -> bool {
    connection_has(value, "keep-alive")
}

pub fn connection_close(value: &HeaderValue) -> bool {
    connection_has(value, "close")
}

fn connection_has(value: &HeaderValue, needle: &str) -> bool {
    if let Ok(s) = value.to_str() {
        for val in s.split(',') {
            if eq_ascii(val.trim(), needle) {
                return true;
            }
        }
    }
    false
}

pub fn content_length_parse(value: &HeaderValue) -> Option<u64> {
    value
        .to_str()
        .ok()
        .and_then(|s| s.parse().ok())
}

pub fn content_length_parse_all(headers: &HeaderMap) -> Option<u64> {
    content_length_parse_all_values(headers.get_all(CONTENT_LENGTH).into_iter())
}

pub fn content_length_parse_all_values(values: ValueIter<HeaderValue>) -> Option<u64> {
    // If multiple Content-Length headers were sent, everything can still
    // be alright if they all contain the same value, and all parse
    // correctly. If not, then it's an error.

    let folded = values
        .fold(None, |prev, line| match prev {
            Some(Ok(prev)) => {
                Some(line
                    .to_str()
                    .map_err(|_| ())
                    .and_then(|s| s.parse().map_err(|_| ()))
                    .and_then(|n| if prev == n { Ok(n) } else { Err(()) }))
            },
            None => {
                Some(line
                    .to_str()
                    .map_err(|_| ())
                    .and_then(|s| s.parse().map_err(|_| ())))
            },
            Some(Err(())) => Some(Err(())),
        });

    if let Some(Ok(n)) = folded {
        Some(n)
    } else {
        None
    }
}

pub fn content_length_value(len: u64) -> HeaderValue {
    let mut len_buf = if mem::size_of::<BytesMut>() - 1 < MAX_DECIMAL_U64_BYTES {
        // when ptr size is 32bits...
        // max bytes don't fit inline, but the likelihood of the length
        // actually needing that many bytes is super tiny. So, only
        // allocate if we really need to.
        // constant version of 10.pow(15) - 1...
        const MAX_DECIMAL_INLINE: u64 = 999_999_999_999_999;
        if len <= MAX_DECIMAL_INLINE {
            // Still fits inline of 15 bytes...
            BytesMut::new()
        } else {
            // the number is huge, and doesn't fit into 15 bytes (on 32bit),
            // so we gotta allocate ;_;
            BytesMut::with_capacity(MAX_DECIMAL_U64_BYTES)
        }
    } else {
        // max bytes fit inline
        BytesMut::with_capacity(MAX_DECIMAL_U64_BYTES)
    };
    ::itoa::fmt(&mut len_buf, len)
        .expect("BytesMut can hold a decimal u64");
    // safe because u64 Display is ascii numerals
    unsafe {
        HeaderValue::from_shared_unchecked(len_buf.freeze())
    }
}

pub fn set_content_length_if_missing(headers: &mut HeaderMap, len: u64) {
    headers
        .entry(CONTENT_LENGTH)
        .unwrap()
        .or_insert(content_length_value(len));
}

pub fn transfer_encoding_is_chunked(headers: &HeaderMap) -> bool {
    is_chunked(headers.get_all(TRANSFER_ENCODING).into_iter())
}

pub fn is_chunked(mut encodings: ValueIter<HeaderValue>) -> bool {
    // chunked must always be the last encoding, according to spec
    if let Some(line) = encodings.next_back() {
        return is_chunked_(line);
    }

    false
}

pub fn is_chunked_(value: &HeaderValue) -> bool {
    // chunked must always be the last encoding, according to spec
    if let Ok(s) = value.to_str() {
        if let Some(encoding) = s.rsplit(',').next() {
            return eq_ascii(encoding.trim(), "chunked");
        }
    }

    false
}

pub fn add_chunked(mut entry: OccupiedEntry<HeaderValue>) {
    const CHUNKED: &'static str = "chunked";

    if let Some(line) = entry.iter_mut().next_back() {
        // + 2 for ", "
        let new_cap = line.as_bytes().len() + CHUNKED.len() + 2;
        let mut buf = BytesMut::with_capacity(new_cap);
        buf.copy_from_slice(line.as_bytes());
        buf.copy_from_slice(b", ");
        buf.copy_from_slice(CHUNKED.as_bytes());

        *line = HeaderValue::from_shared(buf.freeze())
            .expect("original header value plus ascii is valid");
        return;
    }

    entry.insert(HeaderValue::from_static(CHUNKED));
}

fn eq_ascii(left: &str, right: &str) -> bool {
    // As of Rust 1.23, str gained this method inherently, and so the
    // compiler says this trait is unused.
    //
    // TODO: Once our minimum Rust compiler version is >=1.23, this can be removed.
    #[allow(unused, deprecated)]
    use std::ascii::AsciiExt;

    left.eq_ignore_ascii_case(right)
}

#[cfg(test)]
mod tests {

    #[cfg(feature = "nightly")]
    use test::Bencher;

    #[test]
    fn assert_max_decimal_u64_bytes() {
        assert_eq!(
            super::MAX_DECIMAL_U64_BYTES,
            ::std::u64::MAX.to_string().len()
        );
    }

    #[cfg(feature = "nightly")]
    #[bench]
    fn bench_content_length_fmt_small(b: &mut Bencher) {
        let n = 13;
        let s = n.to_string();
        b.bytes = s.len() as u64;

        b.iter(|| {
            let val = super::content_length_value(n);
            debug_assert_eq!(val, s);
            ::test::black_box(&val);
        })
    }

    #[cfg(feature = "nightly")]
    #[bench]
    fn bench_content_length_fmt_big(b: &mut Bencher) {
        let n = 326_893_010;
        let s = n.to_string();
        b.bytes = s.len() as u64;

        b.iter(|| {
            let val = super::content_length_value(n);
            debug_assert_eq!(val, s);
            ::test::black_box(&val);
        })
    }
}
<|endoftext|>


<commit_before>//! History API

use std::collections::VecDeque;
use std::collections::vec_deque;
use std::fs::File;
use std::iter::DoubleEndedIterator;
use std::ops::Index;
use std::path::Path;
#[cfg(unix)]
use libc;

use super::Result;
use config::{Config, HistoryDuplicates};

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Direction {
    Forward,
    Reverse,
}

/// Current state of the history.
pub struct History {
    entries: VecDeque<String>,
    max_len: usize,
    ignore_space: bool,
    ignore_dups: bool,
}

impl History {
    pub fn new(config: Config) -> History {
        History {
            entries: VecDeque::new(),
            max_len: config.max_history_size(),
            ignore_space: config.history_duplicates() == HistoryDuplicates::IgnoreConsecutive,
            ignore_dups: config.history_ignore_space(),
        }
    }

    /// Return the history entry at position `index`, starting from 0.
    pub fn get(&self, index: usize) -> Option<&String> {
        self.entries.get(index)
    }

    /// Return the last history entry (i.e. previous command)
    pub fn last(&self) -> Option<&String> {
        self.entries.back()
    }

    /// Add a new entry in the history.
    pub fn add<S: AsRef<str> + Into<String>>(&mut self, line: S) -> bool {
        if self.max_len == 0 {
            return false;
        }
        if line.as_ref().is_empty() ||
           (self.ignore_space && line.as_ref().chars().next().map_or(true, |c| c.is_whitespace())) {
            return false;
        }
        if self.ignore_dups {
            if let Some(s) = self.entries.back() {
                if s == line.as_ref() {
                    return false;
                }
            }
        }
        if self.entries.len() == self.max_len {
            self.entries.pop_front();
        }
        self.entries.push_back(line.into());
        true
    }

    /// Returns the number of entries in the history.
    pub fn len(&self) -> usize {
        self.entries.len()
    }
    /// Returns true if the history has no entry.
    pub fn is_empty(&self) -> bool {
        self.entries.is_empty()
    }

    /// Set the maximum length for the history. This function can be called even
    /// if there is already some history, the function will make sure to retain
    /// just the latest `len` elements if the new history length value is smaller
    /// than the amount of items already inside the history.
    pub fn set_max_len(&mut self, len: usize) {
        self.max_len = len;
        if len == 0 {
            self.entries.clear();
            return;
        }
        loop {
            if self.entries.len() <= len {
                break;
            }
            self.entries.pop_front();
        }
    }

    /// Save the history in the specified file.
    pub fn save<P: AsRef<Path> + ?Sized>(&self, path: &P) -> Result<()> {
        use std::io::{BufWriter, Write};

        if self.is_empty() {
            return Ok(());
        }
        let old_umask = umask();
        let f = File::create(path);
        restore_umask(old_umask);
        let file = try!(f);
        fix_perm(&file);
        let mut wtr = BufWriter::new(file);
        for entry in &self.entries {
            try!(wtr.write_all(&entry.as_bytes()));
            try!(wtr.write_all(b"\n"));
        }
        Ok(())
    }

    /// Load the history from the specified file.
    ///
    /// # Failure
    /// Will return `Err` if path does not already exist.
    pub fn load<P: AsRef<Path> + ?Sized>(&mut self, path: &P) -> Result<()> {
        use std::io::{BufRead, BufReader};

        let file = try!(File::open(&path));
        let rdr = BufReader::new(file);
        for line in rdr.lines() {
            self.add(try!(line).as_ref()); // TODO truncate to MAX_LINE
        }
        Ok(())
    }

    /// Clear history
    pub fn clear(&mut self) {
        self.entries.clear()
    }

    /// Search history (start position inclusive [0, len-1])
    /// Return the absolute index of the nearest history entry that matches `term`.
    /// Return None if no entry contains `term` between [start, len -1] for forward search
    /// or between [0, start] for reverse search.
    pub fn search(&self, term: &str, start: usize, dir: Direction) -> Option<usize> {
        if term.is_empty() || start >= self.len() {
            return None;
        }
        match dir {
            Direction::Reverse => {
                let index = self.entries
                    .iter()
                    .rev()
                    .skip(self.entries.len() - 1 - start)
                    .position(|entry| entry.contains(term));
                index.and_then(|index| Some(start - index))
            }
            Direction::Forward => {
                let index = self.entries.iter().skip(start).position(|entry| entry.contains(term));
                index.and_then(|index| Some(index + start))
            }
        }
    }

    /// Return a forward iterator.
    pub fn iter(&self) -> Iter {
        Iter(self.entries.iter())
    }
}

impl Index<usize> for History {
    type Output = String;

    fn index(&self, index: usize) -> &String {
        &self.entries[index]
    }
}

impl<'a> IntoIterator for &'a History {
    type Item = &'a String;
    type IntoIter = Iter<'a>;

    fn into_iter(self) -> Iter<'a> {
        self.iter()
    }
}

/// History iterator.
pub struct Iter<'a>(vec_deque::Iter<'a, String>);

impl<'a> Iterator for Iter<'a> {
    type Item = &'a String;

    fn next(&mut self) -> Option<&'a String> {
        self.0.next()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.0.size_hint()
    }
}

impl<'a> DoubleEndedIterator for Iter<'a> {
    fn next_back(&mut self) -> Option<&'a String> {
        self.0.next_back()
    }
}

#[cfg(windows)]
fn umask() -> u16 {
    0
}
#[cfg(unix)]
fn umask() -> u16 {
    unsafe { libc::umask(libc::S_IXUSR | libc::S_IRWXG | libc::S_IRWXO) }
}
#[cfg(windows)]
fn restore_umask(_: u16) {}
#[cfg(unix)]
fn restore_umask(old_umask: u16) {
    unsafe {
        libc::umask(old_umask);
    }
}

#[cfg(windows)]
fn fix_perm(file: &File) {}
#[cfg(unix)]
fn fix_perm(file: &File) {
    use std::os::unix::io::AsRawFd;
    unsafe {
        libc::fchmod(file.as_raw_fd(), libc::S_IRUSR | libc::S_IWUSR);
    }
}

#[cfg(test)]
mod tests {
    extern crate tempdir;
    use std::path::Path;
    use super::{Direction, History};
    use config::Config;

    fn init() -> super::History {
        let mut history = History::new(Config::default());
        assert!(history.add("line1"));
        assert!(history.add("line2"));
        assert!(history.add("line3"));
        history
    }

    #[test]
    fn new() {
        let config = Config::default();
        let history = History::new(config);
        assert_eq!(config.max_history_size(), history.max_len);
        assert_eq!(0, history.entries.len());
    }

    #[test]
    fn add() {
        let config = Config::builder()
            .history_ignore_space(true)
            .build();
        let mut history = History::new(config);
        assert!(history.add("line1"));
        assert!(history.add("line2"));
        assert!(!history.add("line2"));
        assert!(!history.add(""));
        assert!(!history.add(" line3"));
    }

    #[test]
    fn set_max_len() {
        let mut history = init();
        history.set_max_len(1);
        assert_eq!(1, history.entries.len());
        assert_eq!(Some(&"line3".to_string()), history.last());
    }

    #[test]
    fn save() {
        let mut history = init();
        let td = tempdir::TempDir::new_in(&Path::new("."), "histo").unwrap();
        let history_path = td.path().join(".history");

        history.save(&history_path).unwrap();
        history.load(&history_path).unwrap();
        td.close().unwrap();
    }

    #[test]
    fn search() {
        let history = init();
        assert_eq!(None, history.search("", 0, Direction::Forward));
        assert_eq!(None, history.search("none", 0, Direction::Forward));
        assert_eq!(None, history.search("line", 3, Direction::Forward));

        assert_eq!(Some(0), history.search("line", 0, Direction::Forward));
        assert_eq!(Some(1), history.search("line", 1, Direction::Forward));
        assert_eq!(Some(2), history.search("line3", 1, Direction::Forward));
    }

    #[test]
    fn reverse_search() {
        let history = init();
        assert_eq!(None, history.search("", 2, Direction::Reverse));
        assert_eq!(None, history.search("none", 2, Direction::Reverse));
        assert_eq!(None, history.search("line", 3, Direction::Reverse));

        assert_eq!(Some(2), history.search("line", 2, Direction::Reverse));
        assert_eq!(Some(1), history.search("line", 1, Direction::Reverse));
        assert_eq!(Some(0), history.search("line1", 1, Direction::Reverse));
    }
}
<commit_msg>Try to fix travis build.<commit_after>//! History API

use std::collections::VecDeque;
use std::collections::vec_deque;
use std::fs::File;
use std::iter::DoubleEndedIterator;
use std::ops::Index;
use std::path::Path;
#[cfg(unix)]
use libc;

use super::Result;
use config::{Config, HistoryDuplicates};

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Direction {
    Forward,
    Reverse,
}

/// Current state of the history.
pub struct History {
    entries: VecDeque<String>,
    max_len: usize,
    ignore_space: bool,
    ignore_dups: bool,
}

impl History {
    pub fn new(config: Config) -> History {
        History {
            entries: VecDeque::new(),
            max_len: config.max_history_size(),
            ignore_space: config.history_duplicates() == HistoryDuplicates::IgnoreConsecutive,
            ignore_dups: config.history_ignore_space(),
        }
    }

    /// Return the history entry at position `index`, starting from 0.
    pub fn get(&self, index: usize) -> Option<&String> {
        self.entries.get(index)
    }

    /// Return the last history entry (i.e. previous command)
    pub fn last(&self) -> Option<&String> {
        self.entries.back()
    }

    /// Add a new entry in the history.
    pub fn add<S: AsRef<str> + Into<String>>(&mut self, line: S) -> bool {
        if self.max_len == 0 {
            return false;
        }
        if line.as_ref().is_empty() ||
           (self.ignore_space && line.as_ref().chars().next().map_or(true, |c| c.is_whitespace())) {
            return false;
        }
        if self.ignore_dups {
            if let Some(s) = self.entries.back() {
                if s == line.as_ref() {
                    return false;
                }
            }
        }
        if self.entries.len() == self.max_len {
            self.entries.pop_front();
        }
        self.entries.push_back(line.into());
        true
    }

    /// Returns the number of entries in the history.
    pub fn len(&self) -> usize {
        self.entries.len()
    }
    /// Returns true if the history has no entry.
    pub fn is_empty(&self) -> bool {
        self.entries.is_empty()
    }

    /// Set the maximum length for the history. This function can be called even
    /// if there is already some history, the function will make sure to retain
    /// just the latest `len` elements if the new history length value is smaller
    /// than the amount of items already inside the history.
    pub fn set_max_len(&mut self, len: usize) {
        self.max_len = len;
        if len == 0 {
            self.entries.clear();
            return;
        }
        loop {
            if self.entries.len() <= len {
                break;
            }
            self.entries.pop_front();
        }
    }

    /// Save the history in the specified file.
    pub fn save<P: AsRef<Path> + ?Sized>(&self, path: &P) -> Result<()> {
        use std::io::{BufWriter, Write};

        if self.is_empty() {
            return Ok(());
        }
        let old_umask = umask();
        let f = File::create(path);
        restore_umask(old_umask);
        let file = try!(f);
        fix_perm(&file);
        let mut wtr = BufWriter::new(file);
        for entry in &self.entries {
            try!(wtr.write_all(&entry.as_bytes()));
            try!(wtr.write_all(b"\n"));
        }
        Ok(())
    }

    /// Load the history from the specified file.
    ///
    /// # Failure
    /// Will return `Err` if path does not already exist.
    pub fn load<P: AsRef<Path> + ?Sized>(&mut self, path: &P) -> Result<()> {
        use std::io::{BufRead, BufReader};

        let file = try!(File::open(&path));
        let rdr = BufReader::new(file);
        for line in rdr.lines() {
            self.add(try!(line).as_ref()); // TODO truncate to MAX_LINE
        }
        Ok(())
    }

    /// Clear history
    pub fn clear(&mut self) {
        self.entries.clear()
    }

    /// Search history (start position inclusive [0, len-1])
    /// Return the absolute index of the nearest history entry that matches `term`.
    /// Return None if no entry contains `term` between [start, len -1] for forward search
    /// or between [0, start] for reverse search.
    pub fn search(&self, term: &str, start: usize, dir: Direction) -> Option<usize> {
        if term.is_empty() || start >= self.len() {
            return None;
        }
        match dir {
            Direction::Reverse => {
                let index = self.entries
                    .iter()
                    .rev()
                    .skip(self.entries.len() - 1 - start)
                    .position(|entry| entry.contains(term));
                index.and_then(|index| Some(start - index))
            }
            Direction::Forward => {
                let index = self.entries.iter().skip(start).position(|entry| entry.contains(term));
                index.and_then(|index| Some(index + start))
            }
        }
    }

    /// Return a forward iterator.
    pub fn iter(&self) -> Iter {
        Iter(self.entries.iter())
    }
}

impl Index<usize> for History {
    type Output = String;

    fn index(&self, index: usize) -> &String {
        &self.entries[index]
    }
}

impl<'a> IntoIterator for &'a History {
    type Item = &'a String;
    type IntoIter = Iter<'a>;

    fn into_iter(self) -> Iter<'a> {
        self.iter()
    }
}

/// History iterator.
pub struct Iter<'a>(vec_deque::Iter<'a, String>);

impl<'a> Iterator for Iter<'a> {
    type Item = &'a String;

    fn next(&mut self) -> Option<&'a String> {
        self.0.next()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.0.size_hint()
    }
}

impl<'a> DoubleEndedIterator for Iter<'a> {
    fn next_back(&mut self) -> Option<&'a String> {
        self.0.next_back()
    }
}

#[cfg(windows)]
fn umask() -> u16 {
    0
}
#[cfg(unix)]
fn umask() -> libc::mode_t {
    unsafe { libc::umask(libc::S_IXUSR | libc::S_IRWXG | libc::S_IRWXO) }
}
#[cfg(windows)]
fn restore_umask(_: u16) {}
#[cfg(unix)]
fn restore_umask(old_umask: libc::mode_t) {
    unsafe {
        libc::umask(old_umask);
    }
}

#[cfg(windows)]
fn fix_perm(file: &File) {}
#[cfg(unix)]
fn fix_perm(file: &File) {
    use std::os::unix::io::AsRawFd;
    unsafe {
        libc::fchmod(file.as_raw_fd(), libc::S_IRUSR | libc::S_IWUSR);
    }
}

#[cfg(test)]
mod tests {
    extern crate tempdir;
    use std::path::Path;
    use super::{Direction, History};
    use config::Config;

    fn init() -> super::History {
        let mut history = History::new(Config::default());
        assert!(history.add("line1"));
        assert!(history.add("line2"));
        assert!(history.add("line3"));
        history
    }

    #[test]
    fn new() {
        let config = Config::default();
        let history = History::new(config);
        assert_eq!(config.max_history_size(), history.max_len);
        assert_eq!(0, history.entries.len());
    }

    #[test]
    fn add() {
        let config = Config::builder()
            .history_ignore_space(true)
            .build();
        let mut history = History::new(config);
        assert!(history.add("line1"));
        assert!(history.add("line2"));
        assert!(!history.add("line2"));
        assert!(!history.add(""));
        assert!(!history.add(" line3"));
    }

    #[test]
    fn set_max_len() {
        let mut history = init();
        history.set_max_len(1);
        assert_eq!(1, history.entries.len());
        assert_eq!(Some(&"line3".to_string()), history.last());
    }

    #[test]
    fn save() {
        let mut history = init();
        let td = tempdir::TempDir::new_in(&Path::new("."), "histo").unwrap();
        let history_path = td.path().join(".history");

        history.save(&history_path).unwrap();
        history.load(&history_path).unwrap();
        td.close().unwrap();
    }

    #[test]
    fn search() {
        let history = init();
        assert_eq!(None, history.search("", 0, Direction::Forward));
        assert_eq!(None, history.search("none", 0, Direction::Forward));
        assert_eq!(None, history.search("line", 3, Direction::Forward));

        assert_eq!(Some(0), history.search("line", 0, Direction::Forward));
        assert_eq!(Some(1), history.search("line", 1, Direction::Forward));
        assert_eq!(Some(2), history.search("line3", 1, Direction::Forward));
    }

    #[test]
    fn reverse_search() {
        let history = init();
        assert_eq!(None, history.search("", 2, Direction::Reverse));
        assert_eq!(None, history.search("none", 2, Direction::Reverse));
        assert_eq!(None, history.search("line", 3, Direction::Reverse));

        assert_eq!(Some(2), history.search("line", 2, Direction::Reverse));
        assert_eq!(Some(1), history.search("line", 1, Direction::Reverse));
        assert_eq!(Some(0), history.search("line1", 1, Direction::Reverse));
    }
}
<|endoftext|>


<commit_before>//! Module for holding Validated logic
//!
//! `Validated` is a way of running a bunch of operations that can go wrong (for example,
//! functions returning `Result<T, E>`) and, in the case of one or more things going wrong,
//! having all the errors returned to you all at once. In the case that everything went well, you get
//! an `HList` of all your results.
//!
//! ```
//! # #[macro_use] extern crate frunk; use frunk::hlist::*; use frunk::validated::*; fn main() {
//!
//! #[derive(PartialEq, Eq, Debug)]
//! struct Person {
//!     age: i32,
//!     name: String,
//! }
//!
//! fn get_name() -> Result<String, String> {
//!     Result::Ok("James".to_owned())
//! }
//!
//! fn get_age() -> Result<i32, String> {
//!     Result::Ok(32)
//! }
//!
//! let v = get_name().into_validated() + get_age();
//! let person = v.into_result()
//!                .map(|hlist| {
//!                     let (name, age) = hlist.into_tuple2();
//!                     Person {
//!                         name: name,
//!                         age: age,
//!                     }
//!                 });
//!
//!  assert_eq!(person.unwrap(),
//!             Person {
//!                 name: "James".to_owned(),
//!                 age: 32,
//!             });
//! # }
//! ```

use super::hlist::*;
use std::ops::Add;

/// A Validated is either an Ok holding an HList or an Err, holding a vector
/// of collected errors.
#[derive(PartialEq, Debug, Eq, Clone, PartialOrd, Ord)]
pub enum Validated<T, E>
    where T: HList
{
    Ok(T),
    Err(Vec<E>),
}

impl<T, E> Validated<T, E>
    where T: HList
{
    /// Returns true if this validation is Ok, false otherwise
    ///
    /// ```
    /// # use frunk::validated::*;
    ///
    /// let r1: Result<String, String> = Result::Ok(String::from("hello"));
    /// let v = r1.into_validated();
    /// assert!(v.is_ok());
    /// ```
    pub fn is_ok(&self) -> bool {
        match *self {
            Validated::Ok(_) => true,
            _ => false,
        }
    }

    /// Returns true if this validation is Err, false otherwise
    ///
    /// ```
    /// # use frunk::validated::*;
    ///
    /// let r1: Result<String, i32> = Result::Err(32);
    /// let v = r1.into_validated();
    /// assert!(v.is_err());
    /// ```
    pub fn is_err(&self) -> bool {
        !self.is_ok()
    }

    /// Turns this Validated into a Result.
    ///
    /// If this Validated is Ok, it will become a Result::Ok, holding an HList of all the accumulated
    /// results. Otherwise, it will become a Result::Err with a list of all accumulated errors.
    ///
    /// ```
    /// # #[macro_use] extern crate frunk; use frunk::hlist::*; use frunk::validated::*; fn main() {
    ///
    /// #[derive(PartialEq, Eq, Debug)]
    /// struct Person {
    ///     age: i32,
    ///     name: String,
    /// }
    ///
    /// fn get_name() -> Result<String, String> {
    ///     Result::Ok("James".to_owned())
    /// }
    ///
    /// fn get_age() -> Result<i32, String> {
    ///     Result::Ok(32)
    /// }
    ///
    /// let v = get_name().into_validated() + get_age();
    /// let person = v.into_result()
    ///                .map(|hlist| {
    ///                     let (name, age) = hlist.into_tuple2();
    ///                     Person {
    ///                         name: name,
    ///                         age: age,
    ///                     }
    ///                 });
    ///
    ///  assert_eq!(person.unwrap(),
    ///             Person {
    ///                 name: "James".to_owned(),
    ///                 age: 32,
    ///             });
    /// # }
    pub fn into_result(self) -> Result<T, Vec<E>> {
        match self {
            Validated::Ok(h) => Result::Ok(h),
            Validated::Err(errors) => Result::Err(errors),
        }
    }
}

/// Trait for "lifting" a given type into a Validated
pub trait IntoValidated<T, E> {
    /// Consumes the current Result into a Validated so that we can begin chaining
    ///
    /// ```
    /// # use frunk::validated::*;
    ///
    /// let r1: Result<String, i32> = Result::Err(32);
    /// let v = r1.into_validated();
    /// assert!(v.is_err());
    /// ```
    fn into_validated(self) -> Validated<HCons<T, HNil>, E>;
}

impl<T, E> IntoValidated<T, E> for Result<T, E> {
    fn into_validated(self) -> Validated<HCons<T, HNil>, E> {
        match self {
            Result::Err(e) => Validated::Err(vec![e]),
            Result::Ok(v) => {
                Validated::Ok(HCons {
                    head: v,
                    tail: HNil,
                })
            }
        }
    }
}

/// Implements Add for the current Validated with a Result, returning a new Validated.
///
/// ```
/// # #[macro_use] extern crate frunk; use frunk::hlist::*; use frunk::validated::*; fn main() {
///
/// let r1: Result<String, String> = Result::Ok(String::from("hello"));
/// let r2: Result<i32, String> = Result::Ok(1);
/// let v = r1.into_validated() + r2;
/// assert_eq!(v, Validated::Ok(hlist!(String::from("hello"), 1)))
/// # }
/// ```
///
impl<T, E, T2> Add<Result<T2, E>> for Validated<T, E>
    where T: HList + Add<HCons<T2, HNil>>,
          <T as Add<HCons<T2, HNil>>>::Output: HList
{
    type Output = Validated<<T as Add<HCons<T2, HNil>>>::Output, E>;

    fn add(self, other: Result<T2, E>) -> Self::Output {
        let other_as_validated = other.into_validated();
        self + other_as_validated
    }
}

/// Implements Add for the current Validated with another Validated, returning a new Validated.
///
/// ```
/// # #[macro_use] extern crate frunk; use frunk::hlist::*; use frunk::validated::*; fn main() {
/// let r1: Result<String, String> = Result::Ok(String::from("hello"));
/// let r2: Result<i32, String> = Result::Ok(1);
/// let v1 = r1.into_validated();
/// let v2 = r2.into_validated();
/// let v3 = v1 + v2;
/// assert_eq!(v3, Validated::Ok(hlist!(String::from("hello"), 1)))
/// # }
/// ```
impl<T, E, T2> Add<Validated<T2, E>> for Validated<T, E>
    where T: HList + Add<T2>,
          T2: HList,
          <T as Add<T2>>::Output: HList
{
    type Output = Validated<<T as Add<T2>>::Output, E>;

    fn add(self, other: Validated<T2, E>) -> Self::Output {
        match (self, other) {
            (Validated::Err(mut errs), Validated::Err(errs2)) => {
                errs.extend(errs2);
                Validated::Err(errs)
            }
            (Validated::Err(errs), _) => Validated::Err(errs),
            (_, Validated::Err(errs)) => Validated::Err(errs),
            (Validated::Ok(h1), Validated::Ok(h2)) => Validated::Ok(h1 + h2),
        }
    }
}

#[cfg(test)]
mod tests {

    use super::super::hlist::*;
    use super::*;

    #[test]
    fn test_adding_ok_results() {
        let r1: Result<String, String> = Result::Ok(String::from("hello"));
        let r2: Result<i32, String> = Result::Ok(1);
        let v = r1.into_validated() + r2;
        assert_eq!(v, Validated::Ok(hlist!(String::from("hello"), 1)))
    }

    #[test]
    fn test_adding_validated_oks() {
        let r1: Result<String, String> = Result::Ok(String::from("hello"));
        let r2: Result<i32, String> = Result::Ok(1);
        let r3: Result<i32, String> = Result::Ok(3);
        let v1 = r1.into_validated();
        let v2 = r2.into_validated();
        let v3 = r3.into_validated();
        let comb = v1 + v2 + v3;
        assert_eq!(comb, Validated::Ok(hlist!(String::from("hello"), 1, 3)))
    }

    #[test]
    fn test_adding_err_results() {
        let r1: Result<i16, String> = Result::Ok(1);
        let r2: Result<i16, String> = Result::Err(String::from("NO!"));
        let v1 = r1.into_validated() + r2;
        assert!(v1.is_err());
        assert_eq!(v1, Validated::Err(vec!["NO!".to_owned()]))
    }

    #[derive(PartialEq, Eq, Debug)]
    struct Person {
        age: i32,
        name: String,
    }

    fn get_name() -> Result<String, String> {
        Result::Ok("James".to_owned())
    }

    fn get_age() -> Result<i32, String> {
        Result::Ok(32)
    }

    fn get_name_faulty() -> Result<String, String> {
        Result::Err("crap name".to_owned())
    }

    fn get_age_faulty() -> Result<i32, String> {
        Result::Err("crap age".to_owned())
    }

    #[test]
    fn test_to_result_ok() {

        let v = get_name().into_validated() + get_age();
        let person = v.into_result()
                      .map(|hlist| {
                          let (name, age) = hlist.into_tuple2();
                          Person {
                              name: name,
                              age: age,
                          }
                      });

        assert_eq!(person.unwrap(),
                   Person {
                       name: "James".to_owned(),
                       age: 32,
                   });
    }

    #[test]
    fn test_to_result_faulty() {

        let v = get_name_faulty().into_validated() + get_age_faulty();
        let person = v.into_result()
                      .map(|_| unimplemented!());

        assert_eq!(person.unwrap_err(),
                   vec!["crap name".to_owned(), "crap age".to_owned()]);
    }

}
<commit_msg>Refactor some Validated tests for clarity<commit_after>//! Module for holding Validated logic
//!
//! `Validated` is a way of running a bunch of operations that can go wrong (for example,
//! functions returning `Result<T, E>`) and, in the case of one or more things going wrong,
//! having all the errors returned to you all at once. In the case that everything went well, you get
//! an `HList` of all your results.
//!
//! ```
//! # #[macro_use] extern crate frunk; use frunk::hlist::*; use frunk::validated::*; fn main() {
//!
//! #[derive(PartialEq, Eq, Debug)]
//! struct Person {
//!     age: i32,
//!     name: String,
//! }
//!
//! fn get_name() -> Result<String, String> {
//!     Result::Ok("James".to_owned())
//! }
//!
//! fn get_age() -> Result<i32, String> {
//!     Result::Ok(32)
//! }
//!
//! let v = get_name().into_validated() + get_age();
//! let person = v.into_result()
//!                .map(|hlist| {
//!                     let (name, age) = hlist.into_tuple2();
//!                     Person {
//!                         name: name,
//!                         age: age,
//!                     }
//!                 });
//!
//!  assert_eq!(person.unwrap(),
//!             Person {
//!                 name: "James".to_owned(),
//!                 age: 32,
//!             });
//! # }
//! ```

use super::hlist::*;
use std::ops::Add;

/// A Validated is either an Ok holding an HList or an Err, holding a vector
/// of collected errors.
#[derive(PartialEq, Debug, Eq, Clone, PartialOrd, Ord)]
pub enum Validated<T, E>
    where T: HList
{
    Ok(T),
    Err(Vec<E>),
}

impl<T, E> Validated<T, E>
    where T: HList
{
    /// Returns true if this validation is Ok, false otherwise
    ///
    /// ```
    /// # use frunk::validated::*;
    ///
    /// let r1: Result<String, String> = Result::Ok(String::from("hello"));
    /// let v = r1.into_validated();
    /// assert!(v.is_ok());
    /// ```
    pub fn is_ok(&self) -> bool {
        match *self {
            Validated::Ok(_) => true,
            _ => false,
        }
    }

    /// Returns true if this validation is Err, false otherwise
    ///
    /// ```
    /// # use frunk::validated::*;
    ///
    /// let r1: Result<String, i32> = Result::Err(32);
    /// let v = r1.into_validated();
    /// assert!(v.is_err());
    /// ```
    pub fn is_err(&self) -> bool {
        !self.is_ok()
    }

    /// Turns this Validated into a Result.
    ///
    /// If this Validated is Ok, it will become a Result::Ok, holding an HList of all the accumulated
    /// results. Otherwise, it will become a Result::Err with a list of all accumulated errors.
    ///
    /// ```
    /// # #[macro_use] extern crate frunk; use frunk::hlist::*; use frunk::validated::*; fn main() {
    ///
    /// #[derive(PartialEq, Eq, Debug)]
    /// struct Person {
    ///     age: i32,
    ///     name: String,
    /// }
    ///
    /// fn get_name() -> Result<String, String> {
    ///     Result::Ok("James".to_owned())
    /// }
    ///
    /// fn get_age() -> Result<i32, String> {
    ///     Result::Ok(32)
    /// }
    ///
    /// let v = get_name().into_validated() + get_age();
    /// let person = v.into_result()
    ///                .map(|hlist| {
    ///                     let (name, age) = hlist.into_tuple2();
    ///                     Person {
    ///                         name: name,
    ///                         age: age,
    ///                     }
    ///                 });
    ///
    ///  assert_eq!(person.unwrap(),
    ///             Person {
    ///                 name: "James".to_owned(),
    ///                 age: 32,
    ///             });
    /// # }
    pub fn into_result(self) -> Result<T, Vec<E>> {
        match self {
            Validated::Ok(h) => Result::Ok(h),
            Validated::Err(errors) => Result::Err(errors),
        }
    }
}

/// Trait for "lifting" a given type into a Validated
pub trait IntoValidated<T, E> {
    /// Consumes the current Result into a Validated so that we can begin chaining
    ///
    /// ```
    /// # use frunk::validated::*;
    ///
    /// let r1: Result<String, i32> = Result::Err(32);
    /// let v = r1.into_validated();
    /// assert!(v.is_err());
    /// ```
    fn into_validated(self) -> Validated<HCons<T, HNil>, E>;
}

impl<T, E> IntoValidated<T, E> for Result<T, E> {
    fn into_validated(self) -> Validated<HCons<T, HNil>, E> {
        match self {
            Result::Err(e) => Validated::Err(vec![e]),
            Result::Ok(v) => {
                Validated::Ok(HCons {
                    head: v,
                    tail: HNil,
                })
            }
        }
    }
}

/// Implements Add for the current Validated with a Result, returning a new Validated.
///
/// ```
/// # #[macro_use] extern crate frunk; use frunk::hlist::*; use frunk::validated::*; fn main() {
///
/// let r1: Result<String, String> = Result::Ok(String::from("hello"));
/// let r2: Result<i32, String> = Result::Ok(1);
/// let v = r1.into_validated() + r2;
/// assert_eq!(v, Validated::Ok(hlist!(String::from("hello"), 1)))
/// # }
/// ```
///
impl<T, E, T2> Add<Result<T2, E>> for Validated<T, E>
    where T: HList + Add<HCons<T2, HNil>>,
          <T as Add<HCons<T2, HNil>>>::Output: HList
{
    type Output = Validated<<T as Add<HCons<T2, HNil>>>::Output, E>;

    fn add(self, other: Result<T2, E>) -> Self::Output {
        let other_as_validated = other.into_validated();
        self + other_as_validated
    }
}

/// Implements Add for the current Validated with another Validated, returning a new Validated.
///
/// ```
/// # #[macro_use] extern crate frunk; use frunk::hlist::*; use frunk::validated::*; fn main() {
/// let r1: Result<String, String> = Result::Ok(String::from("hello"));
/// let r2: Result<i32, String> = Result::Ok(1);
/// let v1 = r1.into_validated();
/// let v2 = r2.into_validated();
/// let v3 = v1 + v2;
/// assert_eq!(v3, Validated::Ok(hlist!(String::from("hello"), 1)))
/// # }
/// ```
impl<T, E, T2> Add<Validated<T2, E>> for Validated<T, E>
    where T: HList + Add<T2>,
          T2: HList,
          <T as Add<T2>>::Output: HList
{
    type Output = Validated<<T as Add<T2>>::Output, E>;

    fn add(self, other: Validated<T2, E>) -> Self::Output {
        match (self, other) {
            (Validated::Err(mut errs), Validated::Err(errs2)) => {
                errs.extend(errs2);
                Validated::Err(errs)
            }
            (Validated::Err(errs), _) => Validated::Err(errs),
            (_, Validated::Err(errs)) => Validated::Err(errs),
            (Validated::Ok(h1), Validated::Ok(h2)) => Validated::Ok(h1 + h2),
        }
    }
}

#[cfg(test)]
mod tests {

    use super::super::hlist::*;
    use super::*;

    #[test]
    fn test_adding_ok_results() {
        let r1: Result<String, String> = Result::Ok(String::from("hello"));
        let r2: Result<i32, String> = Result::Ok(1);
        let v = r1.into_validated() + r2;
        assert_eq!(v, Validated::Ok(hlist!(String::from("hello"), 1)))
    }

    #[test]
    fn test_adding_validated_oks() {
        let r1: Result<String, String> = Result::Ok(String::from("hello"));
        let r2: Result<i32, String> = Result::Ok(1);
        let r3: Result<i32, String> = Result::Ok(3);
        let v1 = r1.into_validated();
        let v2 = r2.into_validated();
        let v3 = r3.into_validated();
        let comb = v1 + v2 + v3;
        assert_eq!(comb, Validated::Ok(hlist!(String::from("hello"), 1, 3)))
    }

    #[test]
    fn test_adding_err_results() {
        let r1: Result<i16, String> = Result::Ok(1);
        let r2: Result<i16, String> = Result::Err(String::from("NO!"));
        let v1 = r1.into_validated() + r2;
        assert!(v1.is_err());
        assert_eq!(v1, Validated::Err(vec!["NO!".to_owned()]))
    }

    #[derive(PartialEq, Eq, Debug)]
    struct Person {
        age: i32,
        name: String,
        email: String,
    }

    #[derive(PartialEq, Eq, Debug)]
    pub enum YahNah {
        Yah,
        Nah,
    }

    /// Our Errors
    #[derive(PartialEq, Eq, Debug)]
    pub enum Nope {
        NameNope,
        AgeNope,
        EmailNope,
    }

    fn get_name(yah_nah: YahNah) -> Result<String, Nope> {
        match yah_nah {
            YahNah::Yah => Result::Ok("James".to_owned()),
            _ => Result::Err(Nope::NameNope),
        }
    }

    fn get_age(yah_nah: YahNah) -> Result<i32, Nope> {
        match yah_nah {
            YahNah::Yah => Result::Ok(32),
            _ => Result::Err(Nope::AgeNope),
        }
    }

    fn get_email(yah_nah: YahNah) -> Result<String, Nope> {
        match yah_nah {
            YahNah::Yah => Result::Ok("hello@world.com".to_owned()),
            _ => Result::Err(Nope::EmailNope),
        }
    }

    #[test]
    fn test_to_result_ok() {
        let v = get_name(YahNah::Yah).into_validated() + get_age(YahNah::Yah) +
                get_email(YahNah::Yah);
        let person = v.into_result()
                      .map(|hlist| {
                          let (name, (age, email)) = hlist.into_tuple2();
                          Person {
                              name: name,
                              age: age,
                              email: email,
                          }
                      });

        assert_eq!(person.unwrap(),
                   Person {
                       name: "James".to_owned(),
                       age: 32,
                       email: "hello@world.com".to_owned(),
                   });
    }

    #[test]
    fn test_to_result_faulty() {
        let v = get_name(YahNah::Nah).into_validated() + get_age(YahNah::Nah) +
                get_email(YahNah::Nah);
        let person = v.into_result()
                      .map(|_| unimplemented!());

        assert_eq!(person.unwrap_err(),
                   vec![Nope::NameNope, Nope::AgeNope, Nope::EmailNope]);
    }

}
<|endoftext|>


<commit_before>use std::error;
use std::fmt::{Debug, Display, Error, Formatter};
use std::io::{self, Write};

use codespan::{Files, Span as CodespanSpan};
use codespan_reporting::diagnostic::{Diagnostic, Label};
use termcolor::{ColorChoice, StandardStream};

use super::super::parser::Span;
use super::loader::LoadedModule;
use super::value::Value;
use super::vm::StackSnapshot;

#[derive(Debug)]
enum Kind {
    /// An error loading a file.
    /// (name, wrapped)
    LoadFile(String, Box<dyn error::Error>),
    /// (target, value)
    PropertyNotFound(Value, String),
    /// (name)
    UndefinedName(String),
}

impl Kind {
    /// Returns a label for the detail in the diagnostic.
    fn diagnostic_label(&self) -> String {
        use Kind::*;
        let label = match self {
            LoadFile(_, _) => "Import occurred here",
            PropertyNotFound(_, _) => "Missing property",
            UndefinedName(_) => "Undefined name",
        };
        label.to_owned()
    }
}

impl Display for Kind {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        use Kind::*;
        match self {
            LoadFile(name, wrapped) => {
                write!(f, "LoadFileError: could not load `{}': {:?}", name, wrapped)
            }
            PropertyNotFound(target, value) => write!(
                f,
                "PropertyNotFoundError: `{}' not found on {:?}",
                value, target
            ),
            UndefinedName(name) => write!(f, "UndefinedNameError: `{}' not found", name),
        }
    }
}

pub struct VmError {
    kind: Kind,
    stack: Option<StackSnapshot>,
    /// The source directly responsible for the error.
    source: Option<DebugSource>,
}

impl VmError {
    pub fn new_load_file(path: String, wrapped: Box<dyn error::Error>) -> Self {
        Self::new(Kind::LoadFile(path, wrapped))
    }

    pub fn new_property_not_found(target: Value, value: String) -> Self {
        Self::new(Kind::PropertyNotFound(target, value))
    }

    pub fn new_undefined_name(name: String) -> Self {
        Self::new(Kind::UndefinedName(name))
    }

    fn new(kind: Kind) -> Self {
        Self {
            kind,
            stack: None,
            source: None,
        }
    }

    /// Called by the VM to annotate the error with a stack trace.
    pub fn set_stack(&mut self, stack: StackSnapshot) {
        self.stack = Some(stack);
    }

    /// Called by the frame if it was able to find a source mapping for where
    /// the error occurred.
    pub fn set_source(&mut self, source: DebugSource) {
        self.source = Some(source);
    }

    pub fn print_debug(&self) -> io::Result<()> {
        let mut w = StandardStream::stdout(ColorChoice::Auto);
        writeln!(w, "{}", self)?;
        if let Some(stack) = &self.stack {
            for (index, debug_source) in stack.iter() {
                write!(w, "  {}: ", index)?;
                if let Some(function) = &debug_source.function {
                    write!(w, "{} at ", function)?;
                }
                write!(w, "{}", debug_source.module.name())?;
                if let Some(span) = &debug_source.span {
                    write!(w, ":{}", span.start.line)?;
                    if span.start.line != span.end.line {
                        write!(w, "-{}", span.end.line)?;
                    }
                }
                write!(w, "\n")?;
            }
        }
        if let Some(source) = &self.source {
            let mut files = Files::new();
            let name = source.module.name();
            let file = files.add(name, source.module.source());

            let label = self.kind.diagnostic_label();
            if let Some(source_span) = &source.span {
                let span = CodespanSpan::new(source_span.start.index, source_span.end.index);
                let diagnostic =
                    Diagnostic::new_error("".to_owned(), Label::new(file, span, label));
                codespan_reporting::term::emit(&mut w, &Default::default(), &files, &diagnostic)?;
            }
        }
        Ok(())
    }
}

impl Debug for VmError {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f, "VmError {{ {:?} }}", self.kind)
    }
}

impl Display for VmError {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f, "{}", self.kind)
    }
}

impl error::Error for VmError {}

/// Describes in a module where an error occurred.
pub struct DebugSource {
    module: LoadedModule,
    function: Option<String>,
    span: Option<Span>,
}

impl DebugSource {
    pub fn new(module: LoadedModule, function: Option<String>, span: Option<Span>) -> Self {
        Self {
            module,
            function,
            span,
        }
    }
}
<commit_msg>Add argument error kind<commit_after>use std::error;
use std::fmt::{Debug, Display, Error, Formatter};
use std::io::{self, Write};

use codespan::{Files, Span as CodespanSpan};
use codespan_reporting::diagnostic::{Diagnostic, Label};
use termcolor::{ColorChoice, StandardStream};

use super::super::parser::Span;
use super::loader::LoadedModule;
use super::value::Value;
use super::vm::StackSnapshot;

#[derive(Debug)]
enum Kind {
    /// (message)
    Argument(String),
    /// An error loading a file.
    /// (name, wrapped)
    LoadFile(String, Box<dyn error::Error>),
    /// (target, value)
    PropertyNotFound(Value, String),
    /// (name)
    UndefinedName(String),
}

impl Kind {
    /// Returns a label for the detail in the diagnostic.
    fn diagnostic_label(&self) -> String {
        use Kind::*;
        let label = match self {
            Argument(_) => "Argument here",
            LoadFile(_, _) => "Import occurred here",
            PropertyNotFound(_, _) => "Missing property",
            UndefinedName(_) => "Undefined name",
        };
        label.to_owned()
    }
}

impl Display for Kind {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        use Kind::*;
        match self {
            Argument(message) => {
                write!(f, "ArgumentError: {}", message)
            }
            LoadFile(name, wrapped) => {
                write!(f, "LoadFileError: could not load `{}': {:?}", name, wrapped)
            }
            PropertyNotFound(target, value) => write!(
                f,
                "PropertyNotFoundError: `{}' not found on {:?}",
                value, target
            ),
            UndefinedName(name) => write!(f, "UndefinedNameError: `{}' not found", name),
        }
    }
}

pub struct VmError {
    kind: Kind,
    stack: Option<StackSnapshot>,
    /// The source directly responsible for the error.
    source: Option<DebugSource>,
}

impl VmError {
    pub fn new_argument_error<S: Into<String>>(message: S) -> Self {
        Self::new(Kind::Argument(message.into()))
    }

    pub fn new_load_file(path: String, wrapped: Box<dyn error::Error>) -> Self {
        Self::new(Kind::LoadFile(path, wrapped))
    }

    pub fn new_property_not_found(target: Value, value: String) -> Self {
        Self::new(Kind::PropertyNotFound(target, value))
    }

    pub fn new_undefined_name(name: String) -> Self {
        Self::new(Kind::UndefinedName(name))
    }

    fn new(kind: Kind) -> Self {
        Self {
            kind,
            stack: None,
            source: None,
        }
    }

    /// Called by the VM to annotate the error with a stack trace.
    pub fn set_stack(&mut self, stack: StackSnapshot) {
        self.stack = Some(stack);
    }

    /// Called by the frame if it was able to find a source mapping for where
    /// the error occurred.
    pub fn set_source(&mut self, source: DebugSource) {
        self.source = Some(source);
    }

    pub fn print_debug(&self) -> io::Result<()> {
        let mut w = StandardStream::stdout(ColorChoice::Auto);
        writeln!(w, "{}", self)?;
        if let Some(stack) = &self.stack {
            for (index, debug_source) in stack.iter() {
                write!(w, "  {}: ", index)?;
                if let Some(function) = &debug_source.function {
                    write!(w, "{} at ", function)?;
                }
                write!(w, "{}", debug_source.module.name())?;
                if let Some(span) = &debug_source.span {
                    write!(w, ":{}", span.start.line)?;
                    if span.start.line != span.end.line {
                        write!(w, "-{}", span.end.line)?;
                    }
                }
                write!(w, "\n")?;
            }
        }
        if let Some(source) = &self.source {
            let mut files = Files::new();
            let name = source.module.name();
            let file = files.add(name, source.module.source());

            let label = self.kind.diagnostic_label();
            if let Some(source_span) = &source.span {
                let span = CodespanSpan::new(source_span.start.index, source_span.end.index);
                let diagnostic =
                    Diagnostic::new_error("".to_owned(), Label::new(file, span, label));
                codespan_reporting::term::emit(&mut w, &Default::default(), &files, &diagnostic)?;
            }
        }
        Ok(())
    }
}

impl Debug for VmError {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f, "VmError {{ {:?} }}", self.kind)
    }
}

impl Display for VmError {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f, "{}", self.kind)
    }
}

impl error::Error for VmError {}

/// Describes in a module where an error occurred.
pub struct DebugSource {
    module: LoadedModule,
    function: Option<String>,
    span: Option<Span>,
}

impl DebugSource {
    pub fn new(module: LoadedModule, function: Option<String>, span: Option<Span>) -> Self {
        Self {
            module,
            function,
            span,
        }
    }
}
<|endoftext|>


<commit_before>use core::iter::Iterator;
use nalgebra::{Dynamic, Matrix, VecStorage, Vector};
use std::collections::HashMap;
use std::io::{Error, ErrorKind, Result};

type StatusMatrix = Matrix<f32, Dynamic, Dynamic, VecStorage<f32, Dynamic, Dynamic>>;
type StatusVec = Vec<String>;
type WordsIndex = HashMap<String, usize>;

//
#[derive(Debug)]
pub struct SingleWord {
    this_word: String,
    next_word_map: HashMap<String, i64>,
    sum_count: i64,
}

impl SingleWord {
    fn new(w: String) -> Self {
        SingleWord {
            this_word: w,
            next_word_map: HashMap::new(),
            sum_count: 0,
        }
    }

    fn count_next(&mut self, next: &String) {
        if next == "" {
            return;
        };

        *self.next_word_map.entry(next.clone()).or_insert(0) += 1;
        self.sum_count += 1;
    }

    fn vector_maker(
        &self,
        l: &WordIndex,
    ) -> Vector<f32, Dynamic, VecStorage<f32, Dynamic, Dynamic>> {
    }
}

#[derive(Debug)]
pub struct WholeArticleMap {
    words_map: HashMap<String, SingleWord>,
    sum_num: i64,
}

impl WholeArticleMap {
    pub fn new() -> Self {
        WholeArticleMap {
            words_map: HashMap::new(),
            sum_num: 0,
        }
    }

    pub fn read_to_end(&mut self, buf: Vec<String>) -> Result<(i64, StatusVec)> {
        let mut head: String;
        let mut buf = buf.iter();
        let mut count = 0;
        let mut list: Vec<String> = vec![];

        if let Some(item) = buf.next() {
            head = item.into();
            count += 1;
            list.push(head.clone())
        } else {
            return Err(Error::from(ErrorKind::InvalidInput));
        }

        while let Some(b) = buf.next() {
            if b == "" {
                continue;
            }
            self.words_map
                .entry(head.clone())
                .or_insert(SingleWord::new(head.clone()))
                .count_next(b);
            head = b.clone();
            count += 1;
            list.push(head.clone());
        }

        self.sum_num = count;
        Ok((count, list))
    }
}

pub fn make_words_index(l: StatusVec) -> WordsIndex {
    l.iter()
        .cloned()
        .zip(0 as usize..)
        .collect::<HashMap<String, usize>>()
}
<commit_msg>I need change this lib<commit_after>use core::iter::Iterator;
use nalgebra::{Dim, Dynamic, Matrix, VecStorage, Vector};
use std::collections::HashMap;
use std::io::{Error, ErrorKind, Result};

type StatusMatrix = Matrix<f32, Dynamic, Dynamic, VecStorage<f32, Dynamic, Dynamic>>;
type StatusVec = Vec<String>;
type WordsIndex = HashMap<String, usize>;

//
#[derive(Debug)]
pub struct SingleWord {
    this_word: String,
    next_word_map: HashMap<String, i64>,
    sum_count: i64,
}

impl SingleWord {
    fn new(w: String) -> Self {
        SingleWord {
            this_word: w,
            next_word_map: HashMap::new(),
            sum_count: 0,
        }
    }

    fn count_next(&mut self, next: &String) {
        if next == "" {
            return;
        };

        *self.next_word_map.entry(next.clone()).or_insert(0) += 1;
        self.sum_count += 1;
    }

    fn vector_maker(
        &self,
        l: &WordIndex,
    ) -> Vector<f32, Dynamic, VecStorage<f32, Dynamic, Dynamic>> {
        let mut ve = VecStorage::new(l.iter().count(), Dim.from_usize(1), vec![]);
        //iter map
        for (w, id) in self.next_word_map.iter() {}
    }
}

#[derive(Debug)]
pub struct WholeArticleMap {
    words_map: HashMap<String, SingleWord>,
    sum_num: i64,
}

impl WholeArticleMap {
    pub fn new() -> Self {
        WholeArticleMap {
            words_map: HashMap::new(),
            sum_num: 0,
        }
    }

    pub fn read_to_end(&mut self, buf: Vec<String>) -> Result<(i64, StatusVec)> {
        let mut head: String;
        let mut buf = buf.iter();
        let mut count = 0;
        let mut list: Vec<String> = vec![];

        if let Some(item) = buf.next() {
            head = item.into();
            count += 1;
            list.push(head.clone())
        } else {
            return Err(Error::from(ErrorKind::InvalidInput));
        }

        while let Some(b) = buf.next() {
            if b == "" {
                continue;
            }
            self.words_map
                .entry(head.clone())
                .or_insert(SingleWord::new(head.clone()))
                .count_next(b);
            head = b.clone();
            count += 1;
            list.push(head.clone());
        }

        self.sum_num = count;
        Ok((count, list))
    }
}

pub fn make_words_index(l: StatusVec) -> WordsIndex {
    l.iter()
        .cloned()
        .zip(0 as usize..)
        .collect::<HashMap<String, usize>>()
}
<|endoftext|>


<commit_before>use std::fmt::{self, Display};

pub type Result<I> = ::std::result::Result<I, Error>;

/// askama error type
///
/// # Feature Interaction
///
/// If the feature `serde_json` is enabled an
/// additional error variant `Json` is added.
///
/// # Why not `failure`/`error-chain`?
///
/// Error from `error-chain` are not `Sync` which
/// can lead to problems e.g. when this is used
/// by a crate which use `failure`. Implementing
/// `Fail` on the other hand prevents the implementation
/// of `std::error::Error` until specialization lands
/// on stable. While errors impl. `Fail` can be
/// converted to a type impl. `std::error::Error`
/// using a adapter the benefits `failure` would
/// bring to this crate are small, which is why
/// `std::error::Error` was used.
///
#[derive(Debug)]
pub enum Error {
    /// formatting error
    Fmt(fmt::Error),

    /// json conversion error
    #[cfg(feature = "serde_json")]
    Json(::serde_json::Error),

    /// yaml conversion error
    #[cfg(feature = "serde_yaml")]
    Yaml(::serde_yaml::Error),

    /// This error needs to be non-exhaustive as
    /// the `Json` variants existence depends on
    /// a feature.
    #[doc(hidden)]
    __Nonexhaustive,
}

impl std::error::Error for Error {
    fn cause(&self) -> Option<&dyn std::error::Error> {
        match *self {
            Error::Fmt(ref err) => err.source(),
            #[cfg(feature = "serde_json")]
            Error::Json(ref err) => err.source(),
            #[cfg(feature = "serde_yaml")]
            Error::Yaml(ref err) => err.source(),
            _ => None,
        }
    }
}

impl Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Error::Fmt(ref err) => write!(formatter, "formatting error: {}", err),
            #[cfg(feature = "serde_json")]
            Error::Json(ref err) => write!(formatter, "json conversion error: {}", err),
            #[cfg(feature = "serde_yaml")]
            Error::Yaml(ref err) => write!(formatter, "yaml conversion error: {}", err),
            _ => write!(formatter, "unknown error: __Nonexhaustive"),
        }
    }
}

impl From<fmt::Error> for Error {
    fn from(err: fmt::Error) -> Self {
        Error::Fmt(err)
    }
}

#[cfg(feature = "serde_json")]
impl From<::serde_json::Error> for Error {
    fn from(err: ::serde_json::Error) -> Self {
        Error::Json(err)
    }
}

#[cfg(feature = "serde_yaml")]
impl From<::serde_yaml::Error> for Error {
    fn from(err: ::serde_yaml::Error) -> Self {
        Error::Yaml(err)
    }
}

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

    trait AssertSendSyncStatic: Send + Sync + 'static {}
    impl AssertSendSyncStatic for Error {}
}
<commit_msg>Properly annotate non-exhaustive enum<commit_after>use std::fmt::{self, Display};

pub type Result<I> = ::std::result::Result<I, Error>;

/// askama error type
///
/// # Feature Interaction
///
/// If the feature `serde_json` is enabled an
/// additional error variant `Json` is added.
///
/// # Why not `failure`/`error-chain`?
///
/// Error from `error-chain` are not `Sync` which
/// can lead to problems e.g. when this is used
/// by a crate which use `failure`. Implementing
/// `Fail` on the other hand prevents the implementation
/// of `std::error::Error` until specialization lands
/// on stable. While errors impl. `Fail` can be
/// converted to a type impl. `std::error::Error`
/// using a adapter the benefits `failure` would
/// bring to this crate are small, which is why
/// `std::error::Error` was used.
///
#[non_exhaustive]
#[derive(Debug)]
pub enum Error {
    /// formatting error
    Fmt(fmt::Error),

    /// json conversion error
    #[cfg(feature = "serde_json")]
    Json(::serde_json::Error),

    /// yaml conversion error
    #[cfg(feature = "serde_yaml")]
    Yaml(::serde_yaml::Error),
}

impl std::error::Error for Error {
    fn cause(&self) -> Option<&dyn std::error::Error> {
        match *self {
            Error::Fmt(ref err) => err.source(),
            #[cfg(feature = "serde_json")]
            Error::Json(ref err) => err.source(),
            #[cfg(feature = "serde_yaml")]
            Error::Yaml(ref err) => err.source(),
            _ => None,
        }
    }
}

impl Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Error::Fmt(ref err) => write!(formatter, "formatting error: {}", err),
            #[cfg(feature = "serde_json")]
            Error::Json(ref err) => write!(formatter, "json conversion error: {}", err),
            #[cfg(feature = "serde_yaml")]
            Error::Yaml(ref err) => write!(formatter, "yaml conversion error: {}", err),
            _ => write!(formatter, "unknown error: __Nonexhaustive"),
        }
    }
}

impl From<fmt::Error> for Error {
    fn from(err: fmt::Error) -> Self {
        Error::Fmt(err)
    }
}

#[cfg(feature = "serde_json")]
impl From<::serde_json::Error> for Error {
    fn from(err: ::serde_json::Error) -> Self {
        Error::Json(err)
    }
}

#[cfg(feature = "serde_yaml")]
impl From<::serde_yaml::Error> for Error {
    fn from(err: ::serde_yaml::Error) -> Self {
        Error::Yaml(err)
    }
}

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

    trait AssertSendSyncStatic: Send + Sync + 'static {}
    impl AssertSendSyncStatic for Error {}
}
<|endoftext|>


<commit_before><commit_msg>Reworked example as per minor discussion in #764<commit_after><|endoftext|>


<commit_before>use std::env;
use std::process::Command;
use std::str::{self, FromStr};

// The rustc-cfg strings below are *not* public API. Please let us know by
// opening a GitHub issue if your build environment requires some way to enable
// these cfgs other than by executing our build script.
fn main() {
    let minor = match rustc_minor_version() {
        Some(minor) => minor,
        None => return,
    };

    let target = env::var("TARGET").unwrap();
    let emscripten = target == "asmjs-unknown-emscripten" || target == "wasm32-unknown-emscripten";

    // std::collections::Bound was stabilized in Rust 1.17
    // but it was moved to core::ops later in Rust 1.26:
    // https://doc.rust-lang.org/core/ops/enum.Bound.html
    if minor >= 26 {
        println!("cargo:rustc-cfg=ops_bound");
    } else if minor >= 17 && cfg!(feature = "std") {
        println!("cargo:rustc-cfg=collections_bound");
    }

    // core::cmp::Reverse stabilized in Rust 1.19:
    // https://doc.rust-lang.org/stable/core/cmp/struct.Reverse.html
    if minor >= 19 {
        println!("cargo:rustc-cfg=core_reverse");
    }

    // CString::into_boxed_c_str stabilized in Rust 1.20:
    // https://doc.rust-lang.org/std/ffi/struct.CString.html#method.into_boxed_c_str
    if minor >= 20 {
        println!("cargo:rustc-cfg=de_boxed_c_str");
    }

    // From<Box<T>> for Rc<T> / Arc<T> stabilized in Rust 1.21:
    // https://doc.rust-lang.org/std/rc/struct.Rc.html#impl-From<Box<T>>
    // https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-From<Box<T>>
    if minor >= 21 {
        println!("cargo:rustc-cfg=de_rc_dst");
    }

    // Duration available in core since Rust 1.25:
    // https://blog.rust-lang.org/2018/03/29/Rust-1.25.html#library-stabilizations
    if minor >= 25 {
        println!("cargo:rustc-cfg=core_duration");
    }

    // 128-bit integers stabilized in Rust 1.26:
    // https://blog.rust-lang.org/2018/05/10/Rust-1.26.html
    //
    // Disabled on Emscripten targets as Emscripten doesn't
    // currently support integers larger than 64 bits.
    if minor >= 26 && !emscripten {
        println!("cargo:rustc-cfg=integer128");
    }

    // Inclusive ranges methods stabilized in Rust 1.27:
    // https://github.com/rust-lang/rust/pull/50758
    if minor >= 27 {
        println!("cargo:rustc-cfg=range_inclusive");
    }

    // Non-zero integers stabilized in Rust 1.28:
    // https://github.com/rust-lang/rust/pull/50808
    if minor >= 28 {
        println!("cargo:rustc-cfg=num_nonzero");
    }

    if minor >= 34 {
        println!("cargo:rustc-cfg=std_integer_atomics");
    }
}

fn rustc_minor_version() -> Option<u32> {
    let rustc = match env::var_os("RUSTC") {
        Some(rustc) => rustc,
        None => return None,
    };

    let output = match Command::new(rustc).arg("--version").output() {
        Ok(output) => output,
        Err(_) => return None,
    };

    let version = match str::from_utf8(&output.stdout) {
        Ok(version) => version,
        Err(_) => return None,
    };

    let mut pieces = version.split('.');
    if pieces.next() != Some("rustc 1") {
        return None;
    }

    let next = match pieces.next() {
        Some(next) => next,
        None => return None,
    };

    u32::from_str(next).ok()
}
<commit_msg>conservatively limit atomic features<commit_after>use std::env;
use std::process::Command;
use std::str::{self, FromStr};

// The rustc-cfg strings below are *not* public API. Please let us know by
// opening a GitHub issue if your build environment requires some way to enable
// these cfgs other than by executing our build script.
fn main() {
    let minor = match rustc_minor_version() {
        Some(minor) => minor,
        None => return,
    };

    let target = env::var("TARGET").unwrap();
    let emscripten = target == "asmjs-unknown-emscripten" || target == "wasm32-unknown-emscripten";

    let has_atomic_integers = target_has_at_least_atomic_u64(&target);

    // std::collections::Bound was stabilized in Rust 1.17
    // but it was moved to core::ops later in Rust 1.26:
    // https://doc.rust-lang.org/core/ops/enum.Bound.html
    if minor >= 26 {
        println!("cargo:rustc-cfg=ops_bound");
    } else if minor >= 17 && cfg!(feature = "std") {
        println!("cargo:rustc-cfg=collections_bound");
    }

    // core::cmp::Reverse stabilized in Rust 1.19:
    // https://doc.rust-lang.org/stable/core/cmp/struct.Reverse.html
    if minor >= 19 {
        println!("cargo:rustc-cfg=core_reverse");
    }

    // CString::into_boxed_c_str stabilized in Rust 1.20:
    // https://doc.rust-lang.org/std/ffi/struct.CString.html#method.into_boxed_c_str
    if minor >= 20 {
        println!("cargo:rustc-cfg=de_boxed_c_str");
    }

    // From<Box<T>> for Rc<T> / Arc<T> stabilized in Rust 1.21:
    // https://doc.rust-lang.org/std/rc/struct.Rc.html#impl-From<Box<T>>
    // https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-From<Box<T>>
    if minor >= 21 {
        println!("cargo:rustc-cfg=de_rc_dst");
    }

    // Duration available in core since Rust 1.25:
    // https://blog.rust-lang.org/2018/03/29/Rust-1.25.html#library-stabilizations
    if minor >= 25 {
        println!("cargo:rustc-cfg=core_duration");
    }

    // 128-bit integers stabilized in Rust 1.26:
    // https://blog.rust-lang.org/2018/05/10/Rust-1.26.html
    //
    // Disabled on Emscripten targets as Emscripten doesn't
    // currently support integers larger than 64 bits.
    if minor >= 26 && !emscripten {
        println!("cargo:rustc-cfg=integer128");
    }

    // Inclusive ranges methods stabilized in Rust 1.27:
    // https://github.com/rust-lang/rust/pull/50758
    if minor >= 27 {
        println!("cargo:rustc-cfg=range_inclusive");
    }

    // Non-zero integers stabilized in Rust 1.28:
    // https://github.com/rust-lang/rust/pull/50808
    if minor >= 28 {
        println!("cargo:rustc-cfg=num_nonzero");
    }

    if minor >= 34 && has_atomic_integers {
        println!("cargo:rustc-cfg=std_integer_atomics");
    }
}

fn rustc_minor_version() -> Option<u32> {
    let rustc = match env::var_os("RUSTC") {
        Some(rustc) => rustc,
        None => return None,
    };

    let output = match Command::new(rustc).arg("--version").output() {
        Ok(output) => output,
        Err(_) => return None,
    };

    let version = match str::from_utf8(&output.stdout) {
        Ok(version) => version,
        Err(_) => return None,
    };

    let mut pieces = version.split('.');
    if pieces.next() != Some("rustc 1") {
        return None;
    }

    let next = match pieces.next() {
        Some(next) => next,
        None => return None,
    };

    u32::from_str(next).ok()
}

fn target_has_at_least_atomic_u64(target: &str) -> bool {
    // The cfg variable target_has_atomic is unstable
    // so this data comes from the  src/librustc_target/spec/*.rs
    // files in the rust source. Generally, it's 64-bit platforms
    // plus i686.
    if target.starts_with("x86-64") || target.starts_with("i686") ||
        target.starts_with("aarch64") || target.starts_with("powerpc64") ||
        target.starts_with("sparc64") || target.starts_with("mips64el") {
        true
    } else {
        false
    }
}
<|endoftext|>


<commit_before>#[derive(Debug,Clone)]
pub enum Language {
    Fr,
    En,
    Ger,
    Rus,
    Jp,
    Other(String)
}

#[derive(Debug,Clone)]
pub enum MusicType {
    Opening(i32),
    Ending(i32),
    Insert,
    Other(String)
}

#[derive(Debug,Clone)]
pub enum MediaType {
    Anime,
    Movie,
    VideoGame,
    Other(String)
}

#[derive(Debug,Clone)]
pub struct MetaInfo {
    pub artist:String,
    pub origin:String,// name of anime / movie / video game
    pub music_type:MusicType,
    pub media_type:MediaType,
    pub language:Language
}
<commit_msg>Enhanced MediaInfo<commit_after>#[derive(Debug,Clone)]
pub enum Language {
    Fr,
    En,
    Ger,
    Rus,
    Jp,
    Other(String)
}

#[derive(Debug,Clone)]
pub enum MusicType {
    Opening(i32),
    Ending(i32),
    Insert,
    Other(String)
}

#[derive(Debug,Clone)]
pub enum MediaType {
    Anime,
    Movie,
    VideoGame,
    Other(String)
}

#[derive(Debug,Clone,Default)]
pub struct MetaInfo {
    pub artist:Option<String>,
    pub origin:Option<String>,// name of anime / movie / video game
    pub song_name:Option<String>,
    pub music_type:Option<MusicType>,
    pub media_type:Option<MediaType>,
    pub language:Option<Language>
}

impl MetaInfo {
    pub fn new() -> MetaInfo {
        MetaInfo::default()
    }

    pub fn with_artist(mut self,artist:String) -> MetaInfo {
        self.artist = Some(artist);
        self
    }

    pub fn with_origin(mut self,origin:String) -> MetaInfo {
        self.origin = Some(origin);
        self
    }

    pub fn with_song_name(mut self,song_name:String) -> MetaInfo {
        self.song_name = Some(song_name);
        self
    }

    pub fn with_music_type(mut self,music_type:MusicType) -> MetaInfo {
        self.music_type = Some(music_type);
        self
    }

    pub fn with_media_type(mut self,media_type:MediaType) -> MetaInfo {
        self.media_type = Some(media_type);
        self
    }

    pub fn with_language(mut self,language:Language) -> MetaInfo {
        self.language = Some(language);
        self
    }
}
<|endoftext|>


<commit_before>//! Command buffers.
//!
//! A command buffer collects a list of commands to be submitted to the device.
//! Each command buffer has specific capabilities for graphics, compute or transfer operations,
//! and can be either a "primary" command buffer or a "secondary" command buffer.  Operations
//! always start from a primary command buffer, but a primary command buffer can contain calls
//! to secondary command buffers that contain snippets of commands that do specific things, similar
//! to function calls.
//!
//! All the possible commands are implemented in the `RawCommandBuffer` trait, and then the `CommandBuffer`
//! and related types make a generic, strongly-typed wrapper around it that only expose the methods that
//! are valid for the capabilities it provides.

// TODO: Document pipelines and subpasses better.

use Backend;
use queue::capability::Supports;
use std::marker::PhantomData;

mod compute;
mod graphics;
mod raw;
mod render_pass;
mod transfer;

pub use self::graphics::*;
pub use self::raw::{
    ClearValueRaw, ClearColorRaw, ClearDepthStencilRaw, DescriptorSetOffset,
    RawCommandBuffer, CommandBufferFlags, Level as RawLevel, CommandBufferInheritanceInfo,
};
pub use self::render_pass::*;
pub use self::transfer::*;

use std::borrow::{Cow};

/// Trait indicating how many times a Submit object can be submitted to a command buffer.
pub trait Shot {
    ///
    const FLAGS: CommandBufferFlags;
}
/// Indicates a Submit that can only be submitted once.
pub enum OneShot { }
impl Shot for OneShot { const FLAGS: CommandBufferFlags = CommandBufferFlags::ONE_TIME_SUBMIT; }

/// Indicates a Submit that can be submitted multiple times.
pub enum MultiShot { }
impl Shot for MultiShot { const FLAGS: CommandBufferFlags = CommandBufferFlags::EMPTY; }

/// A trait indicating the level of a command buffer.
pub trait Level { }

/// Indicates a primary command buffer.

/// Vulkan describes a primary command buffer as one which can be directly submitted
/// to a queue, and can execute `Secondary` command buffers.
pub enum Primary { }
impl Level for Primary { }

/// Indicates a secondary command buffer.
///
/// Vulkan describes a secondary command buffer as one which cannot be directly submitted
/// to a queue, but can be executed by a primary command buffer. This allows
/// multiple secondary command buffers to be constructed which do specific
/// things and can then be composed together into primary command buffers.
pub enum Secondary { }
impl Level for Secondary { }

/// Thread-safe finished command buffer for submission.
pub struct Submit<B: Backend, C, S, L>(pub(crate) B::CommandBuffer, pub(crate) PhantomData<(C, S, L)>);
impl<B: Backend, C, S, L> Submit<B, C, S, L> {
    fn new(buffer: B::CommandBuffer) -> Self {
        Submit(buffer, PhantomData)
    }
}
unsafe impl<B: Backend, C, S, L> Send for Submit<B, C, S, L> {}

/// A trait representing a command buffer that can be added to a `Submission`.
pub unsafe trait Submittable<'a, B: Backend, C, L: Level> {
    /// Unwraps the object into its underlying command buffer.
    unsafe fn into_buffer(self) -> Cow<'a, B::CommandBuffer>;
}

unsafe impl<'a, B: Backend, C, L: Level> Submittable<'a, B, C, L> for Submit<B, C, OneShot, L> {
    unsafe fn into_buffer(self) -> Cow<'a, B::CommandBuffer> { Cow::Owned(self.0) }
}

unsafe impl<'a, B: Backend, C, L: Level> Submittable<'a, B, C, L> for &'a Submit<B, C, MultiShot, L> {
    unsafe fn into_buffer(self) -> Cow<'a, B::CommandBuffer> { Cow::Borrowed(&self.0) }
}

/// A convenience alias for not typing out the full signature of a secondary command buffer.
#[allow(type_alias_bounds)]
pub type SecondaryCommandBuffer<'a, B: Backend, C, S: Shot = OneShot> = CommandBuffer<'a, B, C, S, Secondary>;

/// A strongly-typed command buffer that will only implement methods that are valid for the operations
/// it supports.
pub struct CommandBuffer<'a, B: Backend, C, S: Shot = OneShot, L: Level = Primary> {
    pub(crate) raw: &'a mut B::CommandBuffer,
    pub(crate) _marker: PhantomData<(C, S, L)>
}

impl<'a, B: Backend, C, S: Shot, L: Level> CommandBuffer<'a, B, C, S, L> {
    /// Create a new typed command buffer from a raw command pool.
    pub unsafe fn new(raw: &'a mut B::CommandBuffer) -> Self {
        CommandBuffer {
            raw: raw,
            _marker: PhantomData,
        }
    }

    /// Get a reference to the raw command buffer
    pub fn as_raw(&self) -> &B::CommandBuffer {
        &*self.raw
    }

    /// Get a mutable reference to the raw command buffer
    pub fn as_raw_mut(&mut self) -> &mut B::CommandBuffer {
        self.raw
    }

    /// Finish recording commands to the command buffers.
    ///
    /// The command buffer will be consumed and can't be modified further.
    /// The command pool must be reset to able to re-record commands.
    pub fn finish(self) -> Submit<B, C, S, L> {
        Submit::new(self.raw.clone())
    }

    /// Downgrade a command buffer to a lesser capability type.
    ///
    /// This is safe as a downgraded version can't be `submit`'ed
    /// since `submit` requires `self` by move.
    pub fn downgrade<D>(&mut self) -> &mut CommandBuffer<'a, B, D, S>
    where
        C: Supports<D>
    {
        unsafe { ::std::mem::transmute(self) }
    }
}

impl<'a, B: Backend, C, S: Shot> CommandBuffer<'a, B, C, S, Primary> {
    /// Identical to the `RawCommandBuffer` method of the same name.
    pub fn execute_commands<I, K>(&mut self, submits: I)
    where
        I: IntoIterator,
        I::Item: Submittable<'a, B, K, Secondary>,
        C: Supports<K>,
    {
        let submits = submits.into_iter().collect::<Vec<_>>();
        self.raw.execute_commands(submits.into_iter().map(|submit| unsafe { submit.into_buffer() }));
    }
}

impl<'a, B: Backend, C, S: Shot, L: Level> Drop for CommandBuffer<'a, B, C, S, L> {
    fn drop(&mut self) {
        self.raw.finish();
    }
}
<commit_msg>[hal] change the order of cmd buffer finish call<commit_after>//! Command buffers.
//!
//! A command buffer collects a list of commands to be submitted to the device.
//! Each command buffer has specific capabilities for graphics, compute or transfer operations,
//! and can be either a "primary" command buffer or a "secondary" command buffer.  Operations
//! always start from a primary command buffer, but a primary command buffer can contain calls
//! to secondary command buffers that contain snippets of commands that do specific things, similar
//! to function calls.
//!
//! All the possible commands are implemented in the `RawCommandBuffer` trait, and then the `CommandBuffer`
//! and related types make a generic, strongly-typed wrapper around it that only expose the methods that
//! are valid for the capabilities it provides.

// TODO: Document pipelines and subpasses better.

use Backend;
use queue::capability::Supports;
use std::marker::PhantomData;

mod compute;
mod graphics;
mod raw;
mod render_pass;
mod transfer;

pub use self::graphics::*;
pub use self::raw::{
    ClearValueRaw, ClearColorRaw, ClearDepthStencilRaw, DescriptorSetOffset,
    RawCommandBuffer, CommandBufferFlags, Level as RawLevel, CommandBufferInheritanceInfo,
};
pub use self::render_pass::*;
pub use self::transfer::*;

use std::borrow::{Cow};

/// Trait indicating how many times a Submit object can be submitted to a command buffer.
pub trait Shot {
    ///
    const FLAGS: CommandBufferFlags;
}
/// Indicates a Submit that can only be submitted once.
pub enum OneShot { }
impl Shot for OneShot { const FLAGS: CommandBufferFlags = CommandBufferFlags::ONE_TIME_SUBMIT; }

/// Indicates a Submit that can be submitted multiple times.
pub enum MultiShot { }
impl Shot for MultiShot { const FLAGS: CommandBufferFlags = CommandBufferFlags::EMPTY; }

/// A trait indicating the level of a command buffer.
pub trait Level { }

/// Indicates a primary command buffer.

/// Vulkan describes a primary command buffer as one which can be directly submitted
/// to a queue, and can execute `Secondary` command buffers.
pub enum Primary { }
impl Level for Primary { }

/// Indicates a secondary command buffer.
///
/// Vulkan describes a secondary command buffer as one which cannot be directly submitted
/// to a queue, but can be executed by a primary command buffer. This allows
/// multiple secondary command buffers to be constructed which do specific
/// things and can then be composed together into primary command buffers.
pub enum Secondary { }
impl Level for Secondary { }

/// Thread-safe finished command buffer for submission.
pub struct Submit<B: Backend, C, S, L>(pub(crate) B::CommandBuffer, pub(crate) PhantomData<(C, S, L)>);
impl<B: Backend, C, S, L> Submit<B, C, S, L> {
    fn new(buffer: B::CommandBuffer) -> Self {
        Submit(buffer, PhantomData)
    }
}
unsafe impl<B: Backend, C, S, L> Send for Submit<B, C, S, L> {}

/// A trait representing a command buffer that can be added to a `Submission`.
pub unsafe trait Submittable<'a, B: Backend, C, L: Level> {
    /// Unwraps the object into its underlying command buffer.
    unsafe fn into_buffer(self) -> Cow<'a, B::CommandBuffer>;
}

unsafe impl<'a, B: Backend, C, L: Level> Submittable<'a, B, C, L> for Submit<B, C, OneShot, L> {
    unsafe fn into_buffer(self) -> Cow<'a, B::CommandBuffer> { Cow::Owned(self.0) }
}

unsafe impl<'a, B: Backend, C, L: Level> Submittable<'a, B, C, L> for &'a Submit<B, C, MultiShot, L> {
    unsafe fn into_buffer(self) -> Cow<'a, B::CommandBuffer> { Cow::Borrowed(&self.0) }
}

/// A convenience alias for not typing out the full signature of a secondary command buffer.
#[allow(type_alias_bounds)]
pub type SecondaryCommandBuffer<'a, B: Backend, C, S: Shot = OneShot> = CommandBuffer<'a, B, C, S, Secondary>;

/// A strongly-typed command buffer that will only implement methods that are valid for the operations
/// it supports.
pub struct CommandBuffer<'a, B: Backend, C, S: Shot = OneShot, L: Level = Primary> {
    pub(crate) raw: &'a mut B::CommandBuffer,
    pub(crate) _marker: PhantomData<(C, S, L)>
}

impl<'a, B: Backend, C, S: Shot, L: Level> CommandBuffer<'a, B, C, S, L> {
    /// Create a new typed command buffer from a raw command pool.
    pub unsafe fn new(raw: &'a mut B::CommandBuffer) -> Self {
        CommandBuffer {
            raw: raw,
            _marker: PhantomData,
        }
    }

    /// Get a reference to the raw command buffer
    pub fn as_raw(&self) -> &B::CommandBuffer {
        &*self.raw
    }

    /// Get a mutable reference to the raw command buffer
    pub fn as_raw_mut(&mut self) -> &mut B::CommandBuffer {
        self.raw
    }

    /// Finish recording commands to the command buffers.
    ///
    /// The command buffer will be consumed and can't be modified further.
    /// The command pool must be reset to able to re-record commands.
    pub fn finish(self) -> Submit<B, C, S, L> {
        self.raw.finish();
        let raw = self.raw.clone();

        ::std::mem::forget(self);

        Submit::new(raw)
    }

    /// Downgrade a command buffer to a lesser capability type.
    ///
    /// This is safe as a downgraded version can't be `submit`'ed
    /// since `submit` requires `self` by move.
    pub fn downgrade<D>(&mut self) -> &mut CommandBuffer<'a, B, D, S>
    where
        C: Supports<D>
    {
        unsafe { ::std::mem::transmute(self) }
    }
}

impl<'a, B: Backend, C, S: Shot> CommandBuffer<'a, B, C, S, Primary> {
    /// Identical to the `RawCommandBuffer` method of the same name.
    pub fn execute_commands<I, K>(&mut self, submits: I)
    where
        I: IntoIterator,
        I::Item: Submittable<'a, B, K, Secondary>,
        C: Supports<K>,
    {
        let submits = submits.into_iter().collect::<Vec<_>>();
        self.raw.execute_commands(submits.into_iter().map(|submit| unsafe { submit.into_buffer() }));
    }
}

impl<'a, B: Backend, C, S: Shot, L: Level> Drop for CommandBuffer<'a, B, C, S, L> {
    fn drop(&mut self) {
        self.raw.finish();
    }
}

<|endoftext|>