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

// This is the backtracking matching engine. It has the same exact capability
// as the full NFA simulation, except it is artificially restricted to small
// regexes on small inputs because of its memory requirements.
//
// In particular, this is a *bounded* backtracking engine. It retains worst
// case linear time by keeping track of the states that is has visited (using a
// bitmap). Namely, once a state is visited, it is never visited again. Since a
// state is keyed by `(instruction index, input index)`, we have that its time
// complexity is `O(mn)` (i.e., linear in the size of the search text).
//
// The backtracking engine can beat out the NFA simulation on small
// regexes/inputs because it doesn't have to keep track of multiple copies of
// the capture groups. In benchmarks, the backtracking engine is roughly twice
// as fast as the full NFA simulation. Note though that its performance doesn't
// scale, even if you're willing to live with the memory requirements. Namely,
// the bitset has to be zeroed on each execution, which becomes quite expensive
// on large bitsets.

use exec::ProgramCache;
use input::{Input, InputAt};
use prog::{Program, InstPtr};
use re_trait::Slot;

type Bits = u32;

const BIT_SIZE: usize = 32;
const MAX_SIZE_BYTES: usize = 256 * (1 << 10); // 256 KB

/// Returns true iff the given regex and input should be executed by this
/// engine with reasonable memory usage.
pub fn should_exec(num_insts: usize, text_len: usize) -> bool {
    // Total memory usage in bytes is determined by:
    //
    //   ((len(insts) * (len(input) + 1) + bits - 1) / bits) * (size_of(u32))
    //
    // The actual limit picked is pretty much a heuristic.
    // See: https://github.com/rust-lang/regex/issues/215
    let size = ((num_insts * (text_len + 1) + BIT_SIZE - 1) / BIT_SIZE) * 4;
    size <= MAX_SIZE_BYTES
}

/// A backtracking matching engine.
#[derive(Debug)]
pub struct Bounded<'a, 'm, 'r, 's, I> {
    prog: &'r Program,
    input: I,
    matches: &'m mut [bool],
    slots: &'s mut [Slot],
    m: &'a mut Cache,
}

/// Shared cached state between multiple invocations of a backtracking engine
/// in the same thread.
#[derive(Clone, Debug)]
pub struct Cache {
    jobs: Vec<Job>,
    visited: Vec<Bits>,
}

impl Cache {
    /// Create new empty cache for the backtracking engine.
    pub fn new(_prog: &Program) -> Self {
        Cache { jobs: vec![], visited: vec![] }
    }
}

/// A job is an explicit unit of stack space in the backtracking engine.
///
/// The "normal" representation is a single state transition, which corresponds
/// to an NFA state and a character in the input. However, the backtracking
/// engine must keep track of old capture group values. We use the explicit
/// stack to do it.
#[derive(Clone, Copy, Debug)]
enum Job {
    Inst { ip: InstPtr, at: InputAt },
    SaveRestore { slot: usize, old_pos: Option<usize> },
}

impl<'a, 'm, 'r, 's, I: Input> Bounded<'a, 'm, 'r, 's, I> {
    /// Execute the backtracking matching engine.
    ///
    /// If there's a match, `exec` returns `true` and populates the given
    /// captures accordingly.
    pub fn exec(
        prog: &'r Program,
        cache: &ProgramCache,
        matches: &'m mut [bool],
        slots: &'s mut [Slot],
        input: I,
        start: usize,
    ) -> bool {
        let mut cache = cache.borrow_mut();
        let mut cache = &mut cache.backtrack;
        let start = input.at(start);
        let mut b = Bounded {
            prog: prog,
            input: input,
            matches: matches,
            slots: slots,
            m: cache,
        };
        b.exec_(start)
    }

    /// Clears the cache such that the backtracking engine can be executed
    /// on some input of fixed length.
    fn clear(&mut self) {
        // Reset the job memory so that we start fresh.
        self.m.jobs.clear();

        // Now we need to clear the bit state set.
        // We do this by figuring out how much space we need to keep track
        // of the states we've visited.
        // Then we reset all existing allocated space to 0.
        // Finally, we request more space if we need it.
        //
        // This is all a little circuitous, but doing this unsafely
        // doesn't seem to have a measurable impact on performance.
        // (Probably because backtracking is limited to such small
        // inputs/regexes in the first place.)
        let visited_len =
            (self.prog.len() * (self.input.len() + 1) + BIT_SIZE - 1)
            /
            BIT_SIZE;
        self.m.visited.truncate(visited_len);
        for v in &mut self.m.visited {
            *v = 0;
        }
        if visited_len > self.m.visited.len() {
            let len = self.m.visited.len();
            self.m.visited.reserve_exact(visited_len - len);
            for _ in 0..(visited_len - len) {
                self.m.visited.push(0);
            }
        }
    }

    /// Start backtracking at the given position in the input, but also look
    /// for literal prefixes.
    fn exec_(&mut self, mut at: InputAt) -> bool {
        self.clear();
        // If this is an anchored regex at the beginning of the input, then
        // we're either already done or we only need to try backtracking once.
        if self.prog.is_anchored_start {
            return if !at.is_start() {
                false
            } else {
                self.backtrack(at)
            };
        }
        let mut matched = false;
        loop {
            if !self.prog.prefixes.is_empty() {
                at = match self.input.prefix_at(&self.prog.prefixes, at) {
                    None => break,
                    Some(at) => at,
                };
            }
            matched = self.backtrack(at) || matched;
            if matched && self.prog.matches.len() == 1 {
                return true;
            }
            if at.is_end() {
                break;
            }
            at = self.input.at(at.next_pos());
        }
        matched
    }

    /// The main backtracking loop starting at the given input position.
    fn backtrack(&mut self, start: InputAt) -> bool {
        // N.B. We use an explicit stack to avoid recursion.
        // To avoid excessive pushing and popping, most transitions are handled
        // in the `step` helper function, which only pushes to the stack when
        // there's a capture or a branch.
        let mut matched = false;
        self.m.jobs.push(Job::Inst { ip: 0, at: start });
        while let Some(job) = self.m.jobs.pop() {
            match job {
                Job::Inst { ip, at } => {
                    if self.step(ip, at) {
                        // Only quit if we're matching one regex.
                        // If we're matching a regex set, then mush on and
                        // try to find other matches (if we want them).
                        if self.prog.matches.len() == 1 {
                            return true;
                        }
                        matched = true;
                    }
                }
                Job::SaveRestore { slot, old_pos } => {
                    if slot < self.slots.len() {
                        self.slots[slot] = old_pos;
                    }
                }
            }
        }
        matched
    }

    fn step(&mut self, mut ip: InstPtr, mut at: InputAt) -> bool {
        use prog::Inst::*;
        loop {
            // This loop is an optimization to avoid constantly pushing/popping
            // from the stack. Namely, if we're pushing a job only to run it
            // next, avoid the push and just mutate `ip` (and possibly `at`)
            // in place.
            match self.prog[ip] {
                Match(slot) => {
                    if slot < self.matches.len() {
                        self.matches[slot] = true;
                    }
                    return true;
                }
                Save(ref inst) => {
                    if let Some(&old_pos) = self.slots.get(inst.slot) {
                        // If this path doesn't work out, then we save the old
                        // capture index (if one exists) in an alternate
                        // job. If the next path fails, then the alternate
                        // job is popped and the old capture index is restored.
                        self.m.jobs.push(Job::SaveRestore {
                            slot: inst.slot,
                            old_pos: old_pos,
                        });
                        self.slots[inst.slot] = Some(at.pos());
                    }
                    ip = inst.goto;
                }
                Split(ref inst) => {
                    self.m.jobs.push(Job::Inst { ip: inst.goto2, at: at });
                    ip = inst.goto1;
                }
                EmptyLook(ref inst) => {
                    if self.input.is_empty_match(at, inst) {
                        ip = inst.goto;
                    } else {
                        return false;
                    }
                }
                Char(ref inst) => {
                    if inst.c == at.char() {
                        ip = inst.goto;
                        at = self.input.at(at.next_pos());
                    } else {
                        return false;
                    }
                }
                Ranges(ref inst) => {
                    if inst.matches(at.char()) {
                        ip = inst.goto;
                        at = self.input.at(at.next_pos());
                    } else {
                        return false;
                    }
                }
                Bytes(ref inst) => {
                    if let Some(b) = at.byte() {
                        if inst.matches(b) {
                            ip = inst.goto;
                            at = self.input.at(at.next_pos());
                            continue;
                        }
                    }
                    return false;
                }
            }
            if self.has_visited(ip, at) {
                return false;
            }
        }
    }

    fn has_visited(&mut self, ip: InstPtr, at: InputAt) -> bool {
        let k = ip * (self.input.len() + 1) + at.pos();
        let k1 = k / BIT_SIZE;
        let k2 = usize_to_u32(1 << (k & (BIT_SIZE - 1)));
        if self.m.visited[k1] & k2 == 0 {
            self.m.visited[k1] |= k2;
            false
        } else {
            true
        }
    }
}

fn usize_to_u32(n: usize) -> u32 {
    if (n as u64) > (::std::u32::MAX as u64) {
        panic!("BUG: {} is too big to fit into u32", n)
    }
    n as u32
}
<commit_msg>Fix typo in backtrack.rs<commit_after>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// This is the backtracking matching engine. It has the same exact capability
// as the full NFA simulation, except it is artificially restricted to small
// regexes on small inputs because of its memory requirements.
//
// In particular, this is a *bounded* backtracking engine. It retains worst
// case linear time by keeping track of the states that it has visited (using a
// bitmap). Namely, once a state is visited, it is never visited again. Since a
// state is keyed by `(instruction index, input index)`, we have that its time
// complexity is `O(mn)` (i.e., linear in the size of the search text).
//
// The backtracking engine can beat out the NFA simulation on small
// regexes/inputs because it doesn't have to keep track of multiple copies of
// the capture groups. In benchmarks, the backtracking engine is roughly twice
// as fast as the full NFA simulation. Note though that its performance doesn't
// scale, even if you're willing to live with the memory requirements. Namely,
// the bitset has to be zeroed on each execution, which becomes quite expensive
// on large bitsets.

use exec::ProgramCache;
use input::{Input, InputAt};
use prog::{Program, InstPtr};
use re_trait::Slot;

type Bits = u32;

const BIT_SIZE: usize = 32;
const MAX_SIZE_BYTES: usize = 256 * (1 << 10); // 256 KB

/// Returns true iff the given regex and input should be executed by this
/// engine with reasonable memory usage.
pub fn should_exec(num_insts: usize, text_len: usize) -> bool {
    // Total memory usage in bytes is determined by:
    //
    //   ((len(insts) * (len(input) + 1) + bits - 1) / bits) * (size_of(u32))
    //
    // The actual limit picked is pretty much a heuristic.
    // See: https://github.com/rust-lang/regex/issues/215
    let size = ((num_insts * (text_len + 1) + BIT_SIZE - 1) / BIT_SIZE) * 4;
    size <= MAX_SIZE_BYTES
}

/// A backtracking matching engine.
#[derive(Debug)]
pub struct Bounded<'a, 'm, 'r, 's, I> {
    prog: &'r Program,
    input: I,
    matches: &'m mut [bool],
    slots: &'s mut [Slot],
    m: &'a mut Cache,
}

/// Shared cached state between multiple invocations of a backtracking engine
/// in the same thread.
#[derive(Clone, Debug)]
pub struct Cache {
    jobs: Vec<Job>,
    visited: Vec<Bits>,
}

impl Cache {
    /// Create new empty cache for the backtracking engine.
    pub fn new(_prog: &Program) -> Self {
        Cache { jobs: vec![], visited: vec![] }
    }
}

/// A job is an explicit unit of stack space in the backtracking engine.
///
/// The "normal" representation is a single state transition, which corresponds
/// to an NFA state and a character in the input. However, the backtracking
/// engine must keep track of old capture group values. We use the explicit
/// stack to do it.
#[derive(Clone, Copy, Debug)]
enum Job {
    Inst { ip: InstPtr, at: InputAt },
    SaveRestore { slot: usize, old_pos: Option<usize> },
}

impl<'a, 'm, 'r, 's, I: Input> Bounded<'a, 'm, 'r, 's, I> {
    /// Execute the backtracking matching engine.
    ///
    /// If there's a match, `exec` returns `true` and populates the given
    /// captures accordingly.
    pub fn exec(
        prog: &'r Program,
        cache: &ProgramCache,
        matches: &'m mut [bool],
        slots: &'s mut [Slot],
        input: I,
        start: usize,
    ) -> bool {
        let mut cache = cache.borrow_mut();
        let mut cache = &mut cache.backtrack;
        let start = input.at(start);
        let mut b = Bounded {
            prog: prog,
            input: input,
            matches: matches,
            slots: slots,
            m: cache,
        };
        b.exec_(start)
    }

    /// Clears the cache such that the backtracking engine can be executed
    /// on some input of fixed length.
    fn clear(&mut self) {
        // Reset the job memory so that we start fresh.
        self.m.jobs.clear();

        // Now we need to clear the bit state set.
        // We do this by figuring out how much space we need to keep track
        // of the states we've visited.
        // Then we reset all existing allocated space to 0.
        // Finally, we request more space if we need it.
        //
        // This is all a little circuitous, but doing this unsafely
        // doesn't seem to have a measurable impact on performance.
        // (Probably because backtracking is limited to such small
        // inputs/regexes in the first place.)
        let visited_len =
            (self.prog.len() * (self.input.len() + 1) + BIT_SIZE - 1)
            /
            BIT_SIZE;
        self.m.visited.truncate(visited_len);
        for v in &mut self.m.visited {
            *v = 0;
        }
        if visited_len > self.m.visited.len() {
            let len = self.m.visited.len();
            self.m.visited.reserve_exact(visited_len - len);
            for _ in 0..(visited_len - len) {
                self.m.visited.push(0);
            }
        }
    }

    /// Start backtracking at the given position in the input, but also look
    /// for literal prefixes.
    fn exec_(&mut self, mut at: InputAt) -> bool {
        self.clear();
        // If this is an anchored regex at the beginning of the input, then
        // we're either already done or we only need to try backtracking once.
        if self.prog.is_anchored_start {
            return if !at.is_start() {
                false
            } else {
                self.backtrack(at)
            };
        }
        let mut matched = false;
        loop {
            if !self.prog.prefixes.is_empty() {
                at = match self.input.prefix_at(&self.prog.prefixes, at) {
                    None => break,
                    Some(at) => at,
                };
            }
            matched = self.backtrack(at) || matched;
            if matched && self.prog.matches.len() == 1 {
                return true;
            }
            if at.is_end() {
                break;
            }
            at = self.input.at(at.next_pos());
        }
        matched
    }

    /// The main backtracking loop starting at the given input position.
    fn backtrack(&mut self, start: InputAt) -> bool {
        // N.B. We use an explicit stack to avoid recursion.
        // To avoid excessive pushing and popping, most transitions are handled
        // in the `step` helper function, which only pushes to the stack when
        // there's a capture or a branch.
        let mut matched = false;
        self.m.jobs.push(Job::Inst { ip: 0, at: start });
        while let Some(job) = self.m.jobs.pop() {
            match job {
                Job::Inst { ip, at } => {
                    if self.step(ip, at) {
                        // Only quit if we're matching one regex.
                        // If we're matching a regex set, then mush on and
                        // try to find other matches (if we want them).
                        if self.prog.matches.len() == 1 {
                            return true;
                        }
                        matched = true;
                    }
                }
                Job::SaveRestore { slot, old_pos } => {
                    if slot < self.slots.len() {
                        self.slots[slot] = old_pos;
                    }
                }
            }
        }
        matched
    }

    fn step(&mut self, mut ip: InstPtr, mut at: InputAt) -> bool {
        use prog::Inst::*;
        loop {
            // This loop is an optimization to avoid constantly pushing/popping
            // from the stack. Namely, if we're pushing a job only to run it
            // next, avoid the push and just mutate `ip` (and possibly `at`)
            // in place.
            match self.prog[ip] {
                Match(slot) => {
                    if slot < self.matches.len() {
                        self.matches[slot] = true;
                    }
                    return true;
                }
                Save(ref inst) => {
                    if let Some(&old_pos) = self.slots.get(inst.slot) {
                        // If this path doesn't work out, then we save the old
                        // capture index (if one exists) in an alternate
                        // job. If the next path fails, then the alternate
                        // job is popped and the old capture index is restored.
                        self.m.jobs.push(Job::SaveRestore {
                            slot: inst.slot,
                            old_pos: old_pos,
                        });
                        self.slots[inst.slot] = Some(at.pos());
                    }
                    ip = inst.goto;
                }
                Split(ref inst) => {
                    self.m.jobs.push(Job::Inst { ip: inst.goto2, at: at });
                    ip = inst.goto1;
                }
                EmptyLook(ref inst) => {
                    if self.input.is_empty_match(at, inst) {
                        ip = inst.goto;
                    } else {
                        return false;
                    }
                }
                Char(ref inst) => {
                    if inst.c == at.char() {
                        ip = inst.goto;
                        at = self.input.at(at.next_pos());
                    } else {
                        return false;
                    }
                }
                Ranges(ref inst) => {
                    if inst.matches(at.char()) {
                        ip = inst.goto;
                        at = self.input.at(at.next_pos());
                    } else {
                        return false;
                    }
                }
                Bytes(ref inst) => {
                    if let Some(b) = at.byte() {
                        if inst.matches(b) {
                            ip = inst.goto;
                            at = self.input.at(at.next_pos());
                            continue;
                        }
                    }
                    return false;
                }
            }
            if self.has_visited(ip, at) {
                return false;
            }
        }
    }

    fn has_visited(&mut self, ip: InstPtr, at: InputAt) -> bool {
        let k = ip * (self.input.len() + 1) + at.pos();
        let k1 = k / BIT_SIZE;
        let k2 = usize_to_u32(1 << (k & (BIT_SIZE - 1)));
        if self.m.visited[k1] & k2 == 0 {
            self.m.visited[k1] |= k2;
            false
        } else {
            true
        }
    }
}

fn usize_to_u32(n: usize) -> u32 {
    if (n as u64) > (::std::u32::MAX as u64) {
        panic!("BUG: {} is too big to fit into u32", n)
    }
    n as u32
}
<|endoftext|>


<commit_before>use super::{Open, Sink};
use libpulse_binding::{self as pulse, stream::Direction};
use libpulse_simple_binding::Simple;
use std::io;

const APP_NAME: &str = "librespot";
const STREAM_NAME: &str = "Spotify endpoint";

pub struct PulseAudioSink {
    s: Option<Simple>,
    ss: pulse::sample::Spec,
    device: Option<String>,
}

impl Open for PulseAudioSink {
    fn open(device: Option<String>) -> PulseAudioSink {
        debug!("Using PulseAudio sink");

        let ss = pulse::sample::Spec {
            format: pulse::sample::Format::S16le,
            channels: 2, // stereo
            rate: 44100,
        };
        debug_assert!(ss.is_valid());

        PulseAudioSink {
            s: None,
            ss: ss,
            device: device,
        }
    }
}

impl Sink for PulseAudioSink {
    fn start(&mut self) -> io::Result<()> {
        if self.s.is_some() {
            return Ok(());
        }

        let device = self.device.as_ref().map(|s| (*s).as_str());
        let result = Simple::new(
            None,                // Use the default server.
            APP_NAME,            // Our application's name.
            Direction::Playback, // Direction.
            device,              // Our device (sink) name.
            STREAM_NAME,         // Description of our stream.
            &self.ss,            // Our sample format.
            None,                // Use default channel map.
            None,                // Use default buffering attributes.
        );
        match result {
            Ok(s) => {
                self.s = Some(s);
                Ok(())
            }
            Err(e) => Err(io::Error::new(
                io::ErrorKind::ConnectionRefused,
                e.to_string().unwrap(),
            )),
        }
    }

    fn stop(&mut self) -> io::Result<()> {
        self.s = None;
        Ok(())
    }

    fn write(&mut self, data: &[i16]) -> io::Result<()> {
        if let Some(s) = &self.s {
            let d: &[u8] = unsafe { std::mem::transmute(data) };

            match s.write(d) {
                Ok(_) => Ok(()),
                Err(e) => Err(io::Error::new(
                    io::ErrorKind::BrokenPipe,
                    e.to_string().unwrap(),
                )),
            }
        } else {
            Err(io::Error::new(
                io::ErrorKind::NotConnected,
                "Not connected to pulseaudio",
            ))
        }
    }
}
<commit_msg>Fix playback in pulseaudio backend (#577)<commit_after>use super::{Open, Sink};
use libpulse_binding::{self as pulse, stream::Direction};
use libpulse_simple_binding::Simple;
use std::io;

const APP_NAME: &str = "librespot";
const STREAM_NAME: &str = "Spotify endpoint";

pub struct PulseAudioSink {
    s: Option<Simple>,
    ss: pulse::sample::Spec,
    device: Option<String>,
}

impl Open for PulseAudioSink {
    fn open(device: Option<String>) -> PulseAudioSink {
        debug!("Using PulseAudio sink");

        let ss = pulse::sample::Spec {
            format: pulse::sample::Format::S16le,
            channels: 2, // stereo
            rate: 44100,
        };
        debug_assert!(ss.is_valid());

        PulseAudioSink {
            s: None,
            ss: ss,
            device: device,
        }
    }
}

impl Sink for PulseAudioSink {
    fn start(&mut self) -> io::Result<()> {
        if self.s.is_some() {
            return Ok(());
        }

        let device = self.device.as_ref().map(|s| (*s).as_str());
        let result = Simple::new(
            None,                // Use the default server.
            APP_NAME,            // Our application's name.
            Direction::Playback, // Direction.
            device,              // Our device (sink) name.
            STREAM_NAME,         // Description of our stream.
            &self.ss,            // Our sample format.
            None,                // Use default channel map.
            None,                // Use default buffering attributes.
        );
        match result {
            Ok(s) => {
                self.s = Some(s);
                Ok(())
            }
            Err(e) => Err(io::Error::new(
                io::ErrorKind::ConnectionRefused,
                e.to_string().unwrap(),
            )),
        }
    }

    fn stop(&mut self) -> io::Result<()> {
        self.s = None;
        Ok(())
    }

    fn write(&mut self, data: &[i16]) -> io::Result<()> {
        if let Some(s) = &self.s {
            // SAFETY: An i16 consists of two bytes, so that the given slice can be interpreted
            // as a byte array of double length. Each byte pointer is validly aligned, and so
            // is the newly created slice.
            let d: &[u8] =
                unsafe { std::slice::from_raw_parts(data.as_ptr() as *const u8, data.len() * 2) };

            match s.write(d) {
                Ok(_) => Ok(()),
                Err(e) => Err(io::Error::new(
                    io::ErrorKind::BrokenPipe,
                    e.to_string().unwrap(),
                )),
            }
        } else {
            Err(io::Error::new(
                io::ErrorKind::NotConnected,
                "Not connected to pulseaudio",
            ))
        }
    }
}
<|endoftext|>


<commit_before>//! Module containing types and functions for mapping between byte indexes and line and column
//! locations

use pos::{BytePos, Column, Line, Location, Span};

/// Type which provides a bidirectional mapping between byte offsets and line and column locations
/// for some source file
#[derive(Clone, Debug)]
pub struct Lines {
    starting_bytes: Vec<BytePos>,
    end: usize,
}

impl Lines {
    /// Creates a mapping for `src`
    pub fn new<I>(src: I) -> Lines
    where
        I: IntoIterator<Item = u8>,
    {
        use std::iter;

        let mut len = 0;
        let starting_bytes = {
            let input_indices = src.into_iter()
                .inspect(|_| len += 1)
                .enumerate()
                .filter(|&(_, b)| b == b'\n')
                .map(|(i, _)| BytePos::from(i + 1)); // index of first char in the line

            iter::once(BytePos::from(0)).chain(input_indices).collect()
        };
        Lines {
            starting_bytes,
            end: len,
        }
    }

    /// Returns the byte offset of the start of `line_number`
    pub fn line(&self, line_number: Line) -> Option<BytePos> {
        let line_number = line_number.to_usize();
        self.starting_bytes.get(line_number).cloned()
    }

    pub fn offset(&self, line: Line, column: Column) -> Option<BytePos> {
        self.line(line).and_then(|mut offset| {
            offset += BytePos::from(column.to_usize());
            if offset.to_usize() >= self.end {
                None
            } else {
                Some(offset)
            }
        })
    }

    /// Returns the line and column location of `byte`
    pub fn location(&self, byte: BytePos) -> Option<Location> {
        if byte.to_usize() <= self.end {
            let line_index = self.line_number_at_byte(byte);

            self.line(line_index).map(|line_byte| {
                Location {
                    line: line_index,
                    column: Column::from((byte - line_byte).to_usize()),
                    absolute: byte,
                }
            })
        } else {
            None
        }
    }

    /// Returns which line `byte` points to
    pub fn line_number_at_byte(&self, byte: BytePos) -> Line {
        let num_lines = self.starting_bytes.len();

        Line::from(
            (0..num_lines)
                .filter(|&i| self.starting_bytes[i] > byte)
                .map(|i| i - 1)
                .next()
                .unwrap_or(num_lines - 1),
        )
    }
}

/// Type which provides a bidirectional mapping between byte offsets and line and column locations
#[derive(Clone, Debug)]
pub struct Source<'a> {
    src: &'a str,
    /// The starting byte position of each line in `src`
    lines: Lines,
}

impl<'a> Source<'a> {
    pub fn new(src: &str) -> Source {
        Source {
            src: src,
            lines: Lines::new(src.as_bytes().iter().cloned()),
        }
    }

    /// Returns the string which defines the source
    pub fn src(&self) -> &'a str {
        self.src
    }

    pub fn lines(&self) -> &Lines {
        &self.lines
    }

    /// Returns the byte offset and source of `line_number`
    pub fn line(&self, line_number: Line) -> Option<(BytePos, &str)> {
        self.lines.line(line_number).map(|start| {
            let line = match self.lines.starting_bytes.get(line_number.to_usize() + 1) {
                Some(end) => &self.src[start.to_usize()..end.to_usize() - 1], // Skip '\n'
                None => &self.src[start.to_usize()..],
            };

            (start, line)
        })
    }

    /// Returns the line number and the source at `byte`
    pub fn line_at_byte(&self, byte: BytePos) -> Option<(BytePos, &str)> {
        let line_number = self.line_number_at_byte(byte);
        self.line(line_number)
    }

    /// Returns which line `byte` points to
    pub fn line_number_at_byte(&self, byte: BytePos) -> Line {
        self.lines.line_number_at_byte(byte)
    }

    /// Returns the line and column location of `byte`
    pub fn location(&self, byte: BytePos) -> Option<Location> {
        self.lines.location(byte)
    }

    /// Returns the starting position of any comments and whitespace before `end`
    pub fn comment_start_before(&self, end: BytePos) -> BytePos {
        let mut iter = self.comments_between(Span::new(BytePos::from(0), end));
        // Scan from `end` until a non comment token is found
        for _ in iter.by_ref().rev() {}
        BytePos::from(iter.src.len())
    }

    pub fn comments_between(&self, span: Span<BytePos>) -> CommentIter<'a> {
        CommentIter {
            src: &self.src[span.start.to_usize()..span.end.to_usize()],
        }
    }
}

pub struct CommentIter<'a> {
    src: &'a str,
}

impl<'a> Iterator for CommentIter<'a> {
    type Item = &'a str;

    fn next(&mut self) -> Option<&'a str> {
        if self.src.is_empty() {
            None
        } else {
            self.src = self.src
                .trim_matches(|c: char| c.is_whitespace() && c != '\n');
            if self.src.starts_with("//") && !self.src.starts_with("///") {
                let comment_line = self.src.lines().next().unwrap();
                self.src = &self.src[comment_line.len()..];
                self.src = if self.src.starts_with("\r\n") {
                    &self.src[2..]
                } else {
                    // \n
                    &self.src[1..]
                };
                Some(comment_line)
            } else if self.src.starts_with("/*") {
                self.src.find("*/").map(|i| {
                    let (comment, rest) = self.src.split_at(i + 2);
                    self.src = rest;
                    comment
                })
            } else if self.src.starts_with("\n") {
                self.src = &self.src[1..];
                Some("")
            } else {
                None
            }
        }
    }
}

impl<'a> DoubleEndedIterator for CommentIter<'a> {
    fn next_back(&mut self) -> Option<&'a str> {
        if self.src.is_empty() {
            None
        } else {
            self.src = self.src
                .trim_right_matches(|c: char| c.is_whitespace() && c != '\n');
            if self.src.ends_with("\n") {
                let comment_line = self.src[..self.src.len() - 1].lines().next_back().unwrap();
                let trimmed = comment_line.trim_left();

                let newline_len = if self.src.ends_with("\r\n") { 2 } else { 1 };
                self.src = &self.src[..(self.src.len() - newline_len)];

                if trimmed.starts_with("//") && !trimmed.starts_with("///") {
                    self.src = &self.src[..(self.src.len() - 2 - trimmed.len() - 1)];
                    Some(trimmed)
                } else {
                    Some("")
                }
            } else if self.src.ends_with("*/") {
                self.src.rfind("/*").map(|i| {
                    let (rest, comment) = self.src.split_at(i);
                    self.src = rest;
                    comment
                })
            } else {
                None
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use pos::{BytePos, Column, Line, Location};

    use super::Source;

    fn test_source() -> Source<'static> {
        Source::new("hello!\nhowdy\n\nhi萤\nbloop\n")
    }

    #[test]
    fn source_line() {
        let source = test_source();

        assert_eq!(
            source.line(Line::from(0)),
            Some((BytePos::from(0), "hello!"))
        );
        assert_eq!(
            source.line(Line::from(1)),
            Some((BytePos::from(7), "howdy"))
        );
        assert_eq!(source.line(Line::from(2)), Some((BytePos::from(13), "")));
        assert_eq!(
            source.line(Line::from(3)),
            Some((BytePos::from(14), "hi萤"))
        );
        assert_eq!(
            source.line(Line::from(4)),
            Some((BytePos::from(20), "bloop"))
        );
        assert_eq!(source.line(Line::from(5)), Some((BytePos::from(26), "")));
        assert_eq!(source.line(Line::from(6)), None);
    }

    #[test]
    fn source_line_number_at_byte() {
        let source = test_source();

        assert_eq!(source.line_number_at_byte(BytePos::from(0)), Line::from(0));
        assert_eq!(source.line_number_at_byte(BytePos::from(6)), Line::from(0));
        assert_eq!(source.line_number_at_byte(BytePos::from(7)), Line::from(1));
        assert_eq!(source.line_number_at_byte(BytePos::from(8)), Line::from(1));

        assert_eq!(source.line_number_at_byte(BytePos::from(12)), Line::from(1));
        assert_eq!(source.line_number_at_byte(BytePos::from(13)), Line::from(2));
        assert_eq!(source.line_number_at_byte(BytePos::from(14)), Line::from(3));
        assert_eq!(source.line_number_at_byte(BytePos::from(15)), Line::from(3));

        assert_eq!(source.line_number_at_byte(BytePos::from(18)), Line::from(3));
        assert_eq!(source.line_number_at_byte(BytePos::from(19)), Line::from(3));
        assert_eq!(source.line_number_at_byte(BytePos::from(20)), Line::from(4));

        assert_eq!(
            source.line_number_at_byte(BytePos::from(400)),
            Line::from(5)
        );
    }

    #[test]
    fn source_location() {
        let source = test_source();

        assert_eq!(
            source.location(BytePos::from(0)),
            Some(Location {
                line: Line::from(0),
                column: Column::from(0),
                absolute: BytePos::from(0),
            })
        );

        assert_eq!(
            source.location(BytePos::from(3)),
            Some(Location {
                line: Line::from(0),
                column: Column::from(3),
                absolute: BytePos::from(3),
            })
        );

        assert_eq!(
            source.location(BytePos::from(16)),
            Some(Location {
                line: Line::from(3),
                column: Column::from(2),
                absolute: BytePos::from(16),
            })
        );

        assert_eq!(source.location(BytePos::from(400)), None);
    }

    #[test]
    fn source_location_end_of_source() {
        let source = test_source();
        assert_eq!(
            source.location(BytePos::from(source.src.len())),
            Some(Location {
                line: Line::from(5),
                column: Column::from(0),
                absolute: BytePos::from(source.src.len()),
            })
        );
    }
}
<commit_msg>refactor(base): Add Source::with_lines<commit_after>//! Module containing types and functions for mapping between byte indexes and line and column
//! locations

use pos::{BytePos, Column, Line, Location, Span};

/// Type which provides a bidirectional mapping between byte offsets and line and column locations
/// for some source file
#[derive(Clone, Debug)]
pub struct Lines {
    starting_bytes: Vec<BytePos>,
    end: usize,
}

impl Lines {
    /// Creates a mapping for `src`
    pub fn new<I>(src: I) -> Lines
    where
        I: IntoIterator<Item = u8>,
    {
        use std::iter;

        let mut len = 0;
        let starting_bytes = {
            let input_indices = src.into_iter()
                .inspect(|_| len += 1)
                .enumerate()
                .filter(|&(_, b)| b == b'\n')
                .map(|(i, _)| BytePos::from(i + 1)); // index of first char in the line

            iter::once(BytePos::from(0)).chain(input_indices).collect()
        };
        Lines {
            starting_bytes,
            end: len,
        }
    }

    /// Returns the byte offset of the start of `line_number`
    pub fn line(&self, line_number: Line) -> Option<BytePos> {
        let line_number = line_number.to_usize();
        self.starting_bytes.get(line_number).cloned()
    }

    pub fn offset(&self, line: Line, column: Column) -> Option<BytePos> {
        self.line(line).and_then(|mut offset| {
            offset += BytePos::from(column.to_usize());
            if offset.to_usize() >= self.end {
                None
            } else {
                Some(offset)
            }
        })
    }

    /// Returns the line and column location of `byte`
    pub fn location(&self, byte: BytePos) -> Option<Location> {
        if byte.to_usize() <= self.end {
            let line_index = self.line_number_at_byte(byte);

            self.line(line_index).map(|line_byte| {
                Location {
                    line: line_index,
                    column: Column::from((byte - line_byte).to_usize()),
                    absolute: byte,
                }
            })
        } else {
            None
        }
    }

    /// Returns which line `byte` points to
    pub fn line_number_at_byte(&self, byte: BytePos) -> Line {
        let num_lines = self.starting_bytes.len();

        Line::from(
            (0..num_lines)
                .filter(|&i| self.starting_bytes[i] > byte)
                .map(|i| i - 1)
                .next()
                .unwrap_or(num_lines - 1),
        )
    }
}

/// Type which provides a bidirectional mapping between byte offsets and line and column locations
#[derive(Clone, Debug)]
pub struct Source<'a> {
    src: &'a str,
    /// The starting byte position of each line in `src`
    lines: Lines,
}

impl<'a> Source<'a> {
    pub fn new(src: &str) -> Source {
        Source::with_lines(src, Lines::new(src.as_bytes().iter().cloned()))
    }

    pub fn with_lines(src: &str, lines: Lines) -> Source {
        Source { src, lines }
    }

    /// Returns the string which defines the source
    pub fn src(&self) -> &'a str {
        self.src
    }

    pub fn lines(&self) -> &Lines {
        &self.lines
    }

    /// Returns the byte offset and source of `line_number`
    pub fn line(&self, line_number: Line) -> Option<(BytePos, &str)> {
        self.lines.line(line_number).map(|start| {
            let line = match self.lines.starting_bytes.get(line_number.to_usize() + 1) {
                Some(end) => &self.src[start.to_usize()..end.to_usize() - 1], // Skip '\n'
                None => &self.src[start.to_usize()..],
            };

            (start, line)
        })
    }

    /// Returns the line number and the source at `byte`
    pub fn line_at_byte(&self, byte: BytePos) -> Option<(BytePos, &str)> {
        let line_number = self.line_number_at_byte(byte);
        self.line(line_number)
    }

    /// Returns which line `byte` points to
    pub fn line_number_at_byte(&self, byte: BytePos) -> Line {
        self.lines.line_number_at_byte(byte)
    }

    /// Returns the line and column location of `byte`
    pub fn location(&self, byte: BytePos) -> Option<Location> {
        self.lines.location(byte)
    }

    /// Returns the starting position of any comments and whitespace before `end`
    pub fn comment_start_before(&self, end: BytePos) -> BytePos {
        let mut iter = self.comments_between(Span::new(BytePos::from(0), end));
        // Scan from `end` until a non comment token is found
        for _ in iter.by_ref().rev() {}
        BytePos::from(iter.src.len())
    }

    pub fn comments_between(&self, span: Span<BytePos>) -> CommentIter<'a> {
        CommentIter {
            src: &self.src[span.start.to_usize()..span.end.to_usize()],
        }
    }
}

pub struct CommentIter<'a> {
    src: &'a str,
}

impl<'a> Iterator for CommentIter<'a> {
    type Item = &'a str;

    fn next(&mut self) -> Option<&'a str> {
        if self.src.is_empty() {
            None
        } else {
            self.src = self.src
                .trim_matches(|c: char| c.is_whitespace() && c != '\n');
            if self.src.starts_with("//") && !self.src.starts_with("///") {
                let comment_line = self.src.lines().next().unwrap();
                self.src = &self.src[comment_line.len()..];
                self.src = if self.src.starts_with("\r\n") {
                    &self.src[2..]
                } else {
                    // \n
                    &self.src[1..]
                };
                Some(comment_line)
            } else if self.src.starts_with("/*") {
                self.src.find("*/").map(|i| {
                    let (comment, rest) = self.src.split_at(i + 2);
                    self.src = rest;
                    comment
                })
            } else if self.src.starts_with("\n") {
                self.src = &self.src[1..];
                Some("")
            } else {
                None
            }
        }
    }
}

impl<'a> DoubleEndedIterator for CommentIter<'a> {
    fn next_back(&mut self) -> Option<&'a str> {
        if self.src.is_empty() {
            None
        } else {
            self.src = self.src
                .trim_right_matches(|c: char| c.is_whitespace() && c != '\n');
            if self.src.ends_with("\n") {
                let comment_line = self.src[..self.src.len() - 1].lines().next_back().unwrap();
                let trimmed = comment_line.trim_left();

                let newline_len = if self.src.ends_with("\r\n") { 2 } else { 1 };
                self.src = &self.src[..(self.src.len() - newline_len)];

                if trimmed.starts_with("//") && !trimmed.starts_with("///") {
                    self.src = &self.src[..(self.src.len() - 2 - trimmed.len() - 1)];
                    Some(trimmed)
                } else {
                    Some("")
                }
            } else if self.src.ends_with("*/") {
                self.src.rfind("/*").map(|i| {
                    let (rest, comment) = self.src.split_at(i);
                    self.src = rest;
                    comment
                })
            } else {
                None
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use pos::{BytePos, Column, Line, Location};

    use super::Source;

    fn test_source() -> Source<'static> {
        Source::new("hello!\nhowdy\n\nhi萤\nbloop\n")
    }

    #[test]
    fn source_line() {
        let source = test_source();

        assert_eq!(
            source.line(Line::from(0)),
            Some((BytePos::from(0), "hello!"))
        );
        assert_eq!(
            source.line(Line::from(1)),
            Some((BytePos::from(7), "howdy"))
        );
        assert_eq!(source.line(Line::from(2)), Some((BytePos::from(13), "")));
        assert_eq!(
            source.line(Line::from(3)),
            Some((BytePos::from(14), "hi萤"))
        );
        assert_eq!(
            source.line(Line::from(4)),
            Some((BytePos::from(20), "bloop"))
        );
        assert_eq!(source.line(Line::from(5)), Some((BytePos::from(26), "")));
        assert_eq!(source.line(Line::from(6)), None);
    }

    #[test]
    fn source_line_number_at_byte() {
        let source = test_source();

        assert_eq!(source.line_number_at_byte(BytePos::from(0)), Line::from(0));
        assert_eq!(source.line_number_at_byte(BytePos::from(6)), Line::from(0));
        assert_eq!(source.line_number_at_byte(BytePos::from(7)), Line::from(1));
        assert_eq!(source.line_number_at_byte(BytePos::from(8)), Line::from(1));

        assert_eq!(source.line_number_at_byte(BytePos::from(12)), Line::from(1));
        assert_eq!(source.line_number_at_byte(BytePos::from(13)), Line::from(2));
        assert_eq!(source.line_number_at_byte(BytePos::from(14)), Line::from(3));
        assert_eq!(source.line_number_at_byte(BytePos::from(15)), Line::from(3));

        assert_eq!(source.line_number_at_byte(BytePos::from(18)), Line::from(3));
        assert_eq!(source.line_number_at_byte(BytePos::from(19)), Line::from(3));
        assert_eq!(source.line_number_at_byte(BytePos::from(20)), Line::from(4));

        assert_eq!(
            source.line_number_at_byte(BytePos::from(400)),
            Line::from(5)
        );
    }

    #[test]
    fn source_location() {
        let source = test_source();

        assert_eq!(
            source.location(BytePos::from(0)),
            Some(Location {
                line: Line::from(0),
                column: Column::from(0),
                absolute: BytePos::from(0),
            })
        );

        assert_eq!(
            source.location(BytePos::from(3)),
            Some(Location {
                line: Line::from(0),
                column: Column::from(3),
                absolute: BytePos::from(3),
            })
        );

        assert_eq!(
            source.location(BytePos::from(16)),
            Some(Location {
                line: Line::from(3),
                column: Column::from(2),
                absolute: BytePos::from(16),
            })
        );

        assert_eq!(source.location(BytePos::from(400)), None);
    }

    #[test]
    fn source_location_end_of_source() {
        let source = test_source();
        assert_eq!(
            source.location(BytePos::from(source.src.len())),
            Some(Location {
                line: Line::from(5),
                column: Column::from(0),
                absolute: BytePos::from(source.src.len()),
            })
        );
    }
}
<|endoftext|>


<commit_before>use getopts::{optflag,optopt,getopts,usage};
use std::os;
use std::collections::HashMap;
use std::io;
use std::io::fs::PathExtensions;

use item::parse_item;

fn get_env() -> HashMap<String, String> {
    let mut env = HashMap::new();
    env.extend(os::env().into_iter().filter(|&(ref key, ref value)| {
        key.as_slice().starts_with("MATES_") && value.len() > 0
    }));
    env
}

fn from_env<'a>(env: &'a HashMap<String, String>, key: &str) -> Option<&'a String> {
    env.find_equiv(&key)
}

fn expect_env<'a>(env: &'a HashMap<String, String>, key: &str) -> &'a String {
    from_env(env, key).expect(
        format!("The {} environment variable must be set.", key).as_slice()
    )
}

fn build_index(outfile: &Path, dir: &Path) {
    if !dir.is_dir() {
        fail!("MATES_DIR must be a directory.");
    };

    let mut outf = io::File::create(outfile);
    let entries = match io::fs::readdir(dir) {
        Ok(x) => x,
        Err(f) => { fail!(f.desc) }
    };
    for entry in entries.iter() {
        if !entry.is_file() {
            continue;
        }
        let itemstr = match io::File::open(entry).read_to_string() {
            Ok(x) => x,
            Err(f) => { fail!(format!("Failed to open {}: {}", entry.display(), f.desc)) }
        };
        let item = parse_item(&itemstr);
        let name = item.single_value(&"FN".into_string());
        match item.all_values(&"EMAIL".into_string()) {
            Some(emails) => {
                for email in emails.iter() {
                    outf.write_str(format!("{}\t{}\n", email.get_raw_value(), name).as_slice());
                };
            },
            None => ()
        };
    };
}

pub fn cli_main() {
    let args = os::args();

    let program = args[0].as_slice();
    let opts = [
        optflag("i", "index", "Create index."),
        optflag("h", "help", "Print help."),
        optopt("m", "mutt-search", "Search in index, for mutt search.", "")
    ];

    let matches = match getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(format!("Failed to parse arguments: {}", f.to_err_msg())) }
    };

    let env = get_env();

    let print_usage = || {
        println!("{}", usage(program, opts));
        println!("Environment variables:");
        println!("- MATES_INDEX: Path to index file, which is basically a cache of all");
        println!("               contacts.");
        println!("- MATES_DIR:   The vdir to use.");
        println!("- MATES_GREP:  The grep executable to use.");
    };

    if matches.opt_present("h") {
        print_usage();
    } else if matches.opt_present("index") {
        let index_file = expect_env(&env, "MATES_INDEX");
        let mates_dir = expect_env(&env, "MATES_DIR");
        println!("Rebuilding index file \"{}\"...", index_file);
        build_index(
            &Path::new(index_file.as_slice()),
            &Path::new(mates_dir.as_slice())
        );
    } else if matches.opt_present("mutt-search") {
        let index_file = expect_env(&env, "MATES_INDEX");
        let default_grep = "grep".into_string();
        let grep_cmd = match from_env(&env, "MATES_GREP") {
            Some(x) => x,
            None => &default_grep
        };

        // FIXME: Better way to write this? We already checked for presence of mutt-search before
        let query = matches.opt_str("mutt-search").expect("This should never happen and yet it did.");
        match match io::Command::new(grep_cmd.as_slice())
            .arg(query.as_slice())
            .arg(index_file.as_slice())
            .stdout(io::process::InheritFd(1))
            .stderr(io::process::InheritFd(2))
            .spawn() {
                Ok(child) => child,
                Err(e) => fail!("Failed to execute grep command: {}", e),
            }.wait() {
                Ok(code) => {
                    os::set_exit_status(match code {
                        io::process::ExitStatus(x) => x,
                        io::process::ExitSignal(x) => x,
                    });
                },
                Err(e) => fail!("Failed to execute grep command: {}", e),
            };
    } else {
        print_usage();
    };
}
<commit_msg>Check for IO Error<commit_after>use getopts::{optflag,optopt,getopts,usage};
use std::os;
use std::collections::HashMap;
use std::io;
use std::io::fs::PathExtensions;

use item::parse_item;

fn get_env() -> HashMap<String, String> {
    let mut env = HashMap::new();
    env.extend(os::env().into_iter().filter(|&(ref key, ref value)| {
        key.as_slice().starts_with("MATES_") && value.len() > 0
    }));
    env
}

fn from_env<'a>(env: &'a HashMap<String, String>, key: &str) -> Option<&'a String> {
    env.find_equiv(&key)
}

fn expect_env<'a>(env: &'a HashMap<String, String>, key: &str) -> &'a String {
    from_env(env, key).expect(
        format!("The {} environment variable must be set.", key).as_slice()
    )
}

fn build_index(outfile: &Path, dir: &Path) {
    if !dir.is_dir() {
        fail!("MATES_DIR must be a directory.");
    };

    let mut outf = io::File::create(outfile);
    let entries = match io::fs::readdir(dir) {
        Ok(x) => x,
        Err(f) => { fail!(f.desc) }
    };
    for entry in entries.iter() {
        if !entry.is_file() {
            continue;
        }
        let itemstr = match io::File::open(entry).read_to_string() {
            Ok(x) => x,
            Err(f) => { fail!(format!("Failed to open {}: {}", entry.display(), f.desc)) }
        };
        let item = parse_item(&itemstr);
        let name = item.single_value(&"FN".into_string());
        match item.all_values(&"EMAIL".into_string()) {
            Some(emails) => {
                for email in emails.iter() {
                    match outf.write_str(
                        format!("{}\t{}\n", email.get_raw_value(), name).as_slice()
                    ) {
                        Ok(x) => (),
                        Err(f) => fail!(f.desc)
                    };
                };
            },
            None => ()
        };
    };
}

pub fn cli_main() {
    let args = os::args();

    let program = args[0].as_slice();
    let opts = [
        optflag("i", "index", "Create index."),
        optflag("h", "help", "Print help."),
        optopt("m", "mutt-search", "Search in index, for mutt search.", "")
    ];

    let matches = match getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(format!("Failed to parse arguments: {}", f.to_err_msg())) }
    };

    let env = get_env();

    let print_usage = || {
        println!("{}", usage(program, opts));
        println!("Environment variables:");
        println!("- MATES_INDEX: Path to index file, which is basically a cache of all");
        println!("               contacts.");
        println!("- MATES_DIR:   The vdir to use.");
        println!("- MATES_GREP:  The grep executable to use.");
    };

    if matches.opt_present("h") {
        print_usage();
    } else if matches.opt_present("index") {
        let index_file = expect_env(&env, "MATES_INDEX");
        let mates_dir = expect_env(&env, "MATES_DIR");
        println!("Rebuilding index file \"{}\"...", index_file);
        build_index(
            &Path::new(index_file.as_slice()),
            &Path::new(mates_dir.as_slice())
        );
    } else if matches.opt_present("mutt-search") {
        let index_file = expect_env(&env, "MATES_INDEX");
        let default_grep = "grep".into_string();
        let grep_cmd = match from_env(&env, "MATES_GREP") {
            Some(x) => x,
            None => &default_grep
        };

        // FIXME: Better way to write this? We already checked for presence of mutt-search before
        let query = matches.opt_str("mutt-search").expect("This should never happen and yet it did.");
        match match io::Command::new(grep_cmd.as_slice())
            .arg(query.as_slice())
            .arg(index_file.as_slice())
            .stdout(io::process::InheritFd(1))
            .stderr(io::process::InheritFd(2))
            .spawn() {
                Ok(child) => child,
                Err(e) => fail!("Failed to execute grep command: {}", e),
            }.wait() {
                Ok(code) => {
                    os::set_exit_status(match code {
                        io::process::ExitStatus(x) => x,
                        io::process::ExitSignal(x) => x,
                    });
                },
                Err(e) => fail!("Failed to execute grep command: {}", e),
            };
    } else {
        print_usage();
    };
}
<|endoftext|>


<commit_before>use std::option::Option;
use std::vec::Vec;

pub struct Scanner<'a> {
    src: &'a str,
    white_spaces: Vec<char>,
    special_chars: Vec<char>,
}

impl<'a> Scanner<'a> {

    pub fn new(src: &'a str) -> Scanner {
        Scanner {
                src: src,
                white_spaces: vec![' ', '\t', '\n'],
                special_chars: vec!['!', '?', '%', '(', ')', '\'', '"', '>', '<', '=', '+', '-', '*', '/', '\\']
        }
    }

    fn is_char_types_changed(&self, current_char: &char) -> bool {
        let first_char = &(self.take_first_char());
        // println!("first char is - '{}', current char is - '{}'", first_char, current_char);
        self.is_ascii_symbol(first_char) && (self.is_white_space(current_char) || self.is_special_char(current_char))
            || self.is_white_space(first_char) && (self.is_ascii_symbol(current_char) || self.is_special_char(current_char) || first_char != current_char)
            || self.is_special_char(first_char) && (self.is_ascii_symbol(current_char) || self.is_white_space(current_char) || first_char != current_char)
    }

    fn is_ascii_symbol(&self, c: &char) -> bool {
        !self.special_chars.contains(&c) && !self.white_spaces.contains(&c)
    }

    fn is_white_space(&self, c: &char) -> bool {
        self.white_spaces.contains(c)
    }

    fn is_special_char(&self, c: &char) -> bool {
        self.special_chars.contains(c)
    }

    fn find_delimeter_index(&self) -> usize {
        self.src.chars().take_while(|c| !self.is_char_types_changed(&c)).count()
    }

    fn take_first_char(&self) -> char {
        self.src.chars().next().unwrap()
    }

    fn next_lexem(&mut self) -> Option<&'a str> {
        let delimeter_index = self.find_delimeter_index();
        let result = self.take_lexem(&delimeter_index);
        self.resize_src(&delimeter_index);
        result
    }

    fn take_lexem(&self, delimeter_index: &usize) -> Option<&'a str> {
        Option::Some(&(self.src)[0..*delimeter_index])
    }

    fn resize_src(&mut self, delimeter_index: &usize) {
        self.src = &(self.src)[*delimeter_index..self.src.len()];
    }
}

impl<'a> Iterator for Scanner<'a> {

    type Item = &'a str;

    fn next(&mut self) -> Option<&'a str> {
        if self.src.is_empty() {
            return Option::None
        }
        self.next_lexem()
    }
}

pub struct Evaluator<'a> {
    scanner: Scanner<'a>,
}

impl<'a> Evaluator<'a> {

    pub fn new(src: &'a str) -> Evaluator {
        Evaluator { scanner: Scanner::new(src) }
    }
}

impl<'a> Iterator for Evaluator<'a> {

    type Item = &'a str;

    fn next(&mut self) -> Option<&'a str> {
        let lexem = self.scanner.next();
        match lexem {
            Some(val) => if val != " " { lexem } else { self.next() } ,
            None => lexem
        }
    }
}
<commit_msg>skip white space algorithm development<commit_after>use std::option::Option;
use std::vec::Vec;
use std::iter::Iterator;

pub struct Scanner<'a> {
    src: &'a str,
    white_spaces: Vec<char>,
    special_chars: Vec<char>,
}

impl<'a> Scanner<'a> {

    pub fn new(src: &'a str) -> Scanner {
        Scanner {
                src: src,
                white_spaces: vec![' ', '\t', '\n'],
                special_chars: vec!['!', '?', '%', '(', ')', '\'', '"', '>', '<', '=', '+', '-', '*', '/', '\\']
        }
    }

    fn is_char_types_changed(&self, current_char: &char) -> bool {
        let first_char = &(self.take_first_char());
        // println!("first char is - '{}', current char is - '{}'", first_char, current_char);
        self.is_ascii_symbol(first_char) && (self.is_white_space(current_char) || self.is_special_char(current_char))
            || self.is_white_space(first_char) && (self.is_ascii_symbol(current_char) || self.is_special_char(current_char) || first_char != current_char)
            || self.is_special_char(first_char) && (self.is_ascii_symbol(current_char) || self.is_white_space(current_char) || first_char != current_char)
    }

    fn is_ascii_symbol(&self, c: &char) -> bool {
        !self.special_chars.contains(&c) && !self.white_spaces.contains(&c)
    }

    fn is_white_space(&self, c: &char) -> bool {
        self.white_spaces.contains(c)
    }

    fn is_special_char(&self, c: &char) -> bool {
        self.special_chars.contains(c)
    }

    fn find_delimeter_index(&self) -> usize {
        self.src.chars().take_while(|c| !self.is_char_types_changed(&c)).count()
    }

    fn take_first_char(&self) -> char {
        self.src.chars().next().unwrap()
    }

    fn next_lexem(&mut self) -> Option<&'a str> {
        let delimeter_index = self.find_delimeter_index();
        let result = self.take_lexem(&delimeter_index);
        self.resize_src(&delimeter_index);
        result
    }

    fn take_lexem(&self, delimeter_index: &usize) -> Option<&'a str> {
        Option::Some(&(self.src)[0..*delimeter_index])
    }

    fn resize_src(&mut self, delimeter_index: &usize) {
        self.src = &(self.src)[*delimeter_index..self.src.len()];
    }
}

impl<'a> Iterator for Scanner<'a> {

    type Item = &'a str;

    fn next(&mut self) -> Option<&'a str> {
        if self.src.is_empty() {
            return Option::None
        }
        self.next_lexem()
    }
}

// "--" -> "\n"
// "/*" -> "*/"
// " "|"\n"|"\t" -> ""

pub struct Evaluator<'a> {
    scanner: Scanner<'a>,
    white_spaces: Vec<&'a str>,
}

impl<'a> Evaluator<'a> {

    pub fn new(src: &'a str) -> Evaluator {
        Evaluator { scanner: Scanner::new(src), white_spaces: vec![" "] }
    }

    fn skip_spaces(&mut self) {
        let lexem = self.scanner.peekable().peek();
        match lexem {
            Some(val) => match *val {
                " " => self.scanner.skip_while(|s| self.skip_while_not_a_space(s)),
                _ => self.scanner.skip_while(self.nothing_to_do("")),
            },
            None => self.scanner.skip_while(self.nothing_to_do("")),
        }
    }

    fn nothing_to_do(&self, s: &'a str) -> bool {
        false
    }

    fn skip_while_not_a_space(&self, s: &'a str) -> bool {
        self.white_spaces.contains(s)
    }
}

impl<'a> Iterator for Evaluator<'a> {

    type Item = &'a str;

    fn next(&mut self) -> Option<&'a str> {
        self.skip_spaces();
        let lexem = self.scanner.next();
        match lexem {
            Some(val) => if val != " " { lexem } else { self.next() } ,
            None => lexem
        }
    }
}
<|endoftext|>


<commit_before>//! Benchmark sqrt and cbrt

#![feature(test)]

extern crate num_integer;
extern crate num_traits;
extern crate test;

use num_integer::Integer;
use num_traits::{AsPrimitive, PrimInt, WrappingAdd, WrappingMul};
use test::{black_box, Bencher};

trait BenchInteger: Integer + PrimInt + WrappingAdd + WrappingMul + 'static {}

impl<T> BenchInteger for T where T: Integer + PrimInt + WrappingAdd + WrappingMul + 'static {}

trait NaiveAverage {
    fn naive_average_floor(&self, other: &Self) -> Self;
    fn naive_average_ceil(&self, other: &Self) -> Self;
}

trait UncheckedAverage {
    fn unchecked_average_floor(&self, other: &Self) -> Self;
    fn unchecked_average_ceil(&self, other: &Self) -> Self;
}

fn bench<T, F>(b: &mut Bencher, v: &[(T, T)], f: F)
where
    T: Integer,
    F: Fn(&T, &T) -> T,
{
    b.iter(|| {
        for (x, y) in v {
            black_box(f(x, y));
        }
    });
}

// Simple PRNG so we don't have to worry about rand compatibility
fn lcg<T>(x: T) -> T
where
    u32: AsPrimitive<T>,
    T: BenchInteger,
{
    // LCG parameters from Numerical Recipes
    // (but we're applying it to arbitrary sizes)
    const LCG_A: u32 = 1664525;
    const LCG_C: u32 = 1013904223;
    x.wrapping_mul(&LCG_A.as_()).wrapping_add(&LCG_C.as_())
}

macro_rules! naive_average {
    ($T:ident) => {
        impl super::NaiveAverage for $T {
            fn naive_average_floor(&self, other: &$T) -> $T {
                match self.checked_add(*other) {
                    Some(z) => z/2,
                    None => if self > other {
                        let diff = self - other;
                        other + diff/2
                    } else {
                        let diff = other - self;
                        self + diff/2
                    }
                }
            }
            fn naive_average_ceil(&self, other: &$T) -> $T {
                match self.checked_add(*other).and_then(|x| x.checked_add(1)) {
                    Some(z) => z/2,
                    None => if self > other {
                        let diff = self - other;
                        self - diff/2
                    } else {
                        let diff = other - self;
                        other - diff/2
                    }
                }
            }
        }
    };
}

macro_rules! unchecked_average {
    ($T:ident) => {
        impl super::UncheckedAverage for $T {
            fn unchecked_average_floor(&self, other: &$T) -> $T {
                self.wrapping_add(*other) / 2
            }
            fn unchecked_average_ceil(&self, other: &$T) -> $T {
                (self.wrapping_add(*other) / 2).wrapping_add(1)
            }
        }
    };
}

macro_rules! bench_average {
    ($($T:ident),*) => {$(
        mod $T {
            use test::Bencher;
            use num_integer::Average;
            use UncheckedAverage;
            use NaiveAverage;

            naive_average!($T);
            unchecked_average!($T);

            const SIZE: $T = 30;

            fn overflowing() -> Vec<($T, $T)> {
                (($T::max_value()-SIZE)..$T::max_value())
                    .flat_map(|x| -> Vec<_> {
                        (($T::max_value()-100)..($T::max_value()-100+SIZE))
                            .map(|y| (x, y))
                            .collect()
                    })
                    .collect()
            }

            fn small() -> Vec<($T, $T)> {
                (0..SIZE)
                   .flat_map(|x| -> Vec<_> {(0..SIZE).map(|y| (x, y)).collect()})
                   .collect()
            }

            fn rand() -> Vec<($T, $T)> {
                small()
                    .into_iter()
                    .map(|(x, y)| (super::lcg(x), super::lcg(y)))
                    .collect()
            }

            #[bench]
            fn average_floor_small(b: &mut Bencher) {
                let v = small();
                super::bench(b, &v, |x: &$T, y: &$T| x.average_floor(y));
            }

            #[bench]
            fn average_floor_small_naive(b: &mut Bencher) {
                let v = small();
                super::bench(b, &v, |x: &$T, y: &$T| x.naive_average_floor(y));
            }

            #[bench]
            fn average_floor_small_unchecked(b: &mut Bencher) {
                let v = small();
                super::bench(b, &v, |x: &$T, y: &$T| x.unchecked_average_floor(y));
            }

            #[bench]
            fn average_floor_overflowing(b: &mut Bencher) {
                let v = overflowing();
                super::bench(b, &v, |x: &$T, y: &$T| x.average_floor(y));
            }

            #[bench]
            fn average_floor_overflowing_naive(b: &mut Bencher) {
                let v = overflowing();
                super::bench(b, &v, |x: &$T, y: &$T| x.naive_average_floor(y));
            }

            #[bench]
            fn average_floor_overflowing_unchecked(b: &mut Bencher) {
                let v = overflowing();
                super::bench(b, &v, |x: &$T, y: &$T| x.unchecked_average_floor(y));
            }

            #[bench]
            fn average_floor_rand(b: &mut Bencher) {
                let v = rand();
                super::bench(b, &v, |x: &$T, y: &$T| x.average_floor(y));
            }

            #[bench]
            fn average_floor_rand_naive(b: &mut Bencher) {
                let v = rand();
                super::bench(b, &v, |x: &$T, y: &$T| x.naive_average_floor(y));
            }

            #[bench]
            fn average_floor_rand_unchecked(b: &mut Bencher) {
                let v = rand();
                super::bench(b, &v, |x: &$T, y: &$T| x.unchecked_average_floor(y));
            }
        }
    )*}
}

bench_average!(i8, i16, i32, i64, i128, isize);
bench_average!(u8, u16, u32, u64, u128, usize);
<commit_msg>Run `cargo fmt` on source code<commit_after>//! Benchmark sqrt and cbrt

#![feature(test)]

extern crate num_integer;
extern crate num_traits;
extern crate test;

use num_integer::Integer;
use num_traits::{AsPrimitive, PrimInt, WrappingAdd, WrappingMul};
use test::{black_box, Bencher};

trait BenchInteger: Integer + PrimInt + WrappingAdd + WrappingMul + 'static {}

impl<T> BenchInteger for T where T: Integer + PrimInt + WrappingAdd + WrappingMul + 'static {}

trait NaiveAverage {
    fn naive_average_floor(&self, other: &Self) -> Self;
    fn naive_average_ceil(&self, other: &Self) -> Self;
}

trait UncheckedAverage {
    fn unchecked_average_floor(&self, other: &Self) -> Self;
    fn unchecked_average_ceil(&self, other: &Self) -> Self;
}

fn bench<T, F>(b: &mut Bencher, v: &[(T, T)], f: F)
where
    T: Integer,
    F: Fn(&T, &T) -> T,
{
    b.iter(|| {
        for (x, y) in v {
            black_box(f(x, y));
        }
    });
}

// Simple PRNG so we don't have to worry about rand compatibility
fn lcg<T>(x: T) -> T
where
    u32: AsPrimitive<T>,
    T: BenchInteger,
{
    // LCG parameters from Numerical Recipes
    // (but we're applying it to arbitrary sizes)
    const LCG_A: u32 = 1664525;
    const LCG_C: u32 = 1013904223;
    x.wrapping_mul(&LCG_A.as_()).wrapping_add(&LCG_C.as_())
}

macro_rules! naive_average {
    ($T:ident) => {
        impl super::NaiveAverage for $T {
            fn naive_average_floor(&self, other: &$T) -> $T {
                match self.checked_add(*other) {
                    Some(z) => z / 2,
                    None => {
                        if self > other {
                            let diff = self - other;
                            other + diff / 2
                        } else {
                            let diff = other - self;
                            self + diff / 2
                        }
                    }
                }
            }
            fn naive_average_ceil(&self, other: &$T) -> $T {
                match self.checked_add(*other).and_then(|x| x.checked_add(1)) {
                    Some(z) => z / 2,
                    None => {
                        if self > other {
                            let diff = self - other;
                            self - diff / 2
                        } else {
                            let diff = other - self;
                            other - diff / 2
                        }
                    }
                }
            }
        }
    };
}

macro_rules! unchecked_average {
    ($T:ident) => {
        impl super::UncheckedAverage for $T {
            fn unchecked_average_floor(&self, other: &$T) -> $T {
                self.wrapping_add(*other) / 2
            }
            fn unchecked_average_ceil(&self, other: &$T) -> $T {
                (self.wrapping_add(*other) / 2).wrapping_add(1)
            }
        }
    };
}

macro_rules! bench_average {
    ($($T:ident),*) => {$(
        mod $T {
            use test::Bencher;
            use num_integer::Average;
            use UncheckedAverage;
            use NaiveAverage;

            naive_average!($T);
            unchecked_average!($T);

            const SIZE: $T = 30;

            fn overflowing() -> Vec<($T, $T)> {
                (($T::max_value()-SIZE)..$T::max_value())
                    .flat_map(|x| -> Vec<_> {
                        (($T::max_value()-100)..($T::max_value()-100+SIZE))
                            .map(|y| (x, y))
                            .collect()
                    })
                    .collect()
            }

            fn small() -> Vec<($T, $T)> {
                (0..SIZE)
                   .flat_map(|x| -> Vec<_> {(0..SIZE).map(|y| (x, y)).collect()})
                   .collect()
            }

            fn rand() -> Vec<($T, $T)> {
                small()
                    .into_iter()
                    .map(|(x, y)| (super::lcg(x), super::lcg(y)))
                    .collect()
            }

            #[bench]
            fn average_floor_small(b: &mut Bencher) {
                let v = small();
                super::bench(b, &v, |x: &$T, y: &$T| x.average_floor(y));
            }

            #[bench]
            fn average_floor_small_naive(b: &mut Bencher) {
                let v = small();
                super::bench(b, &v, |x: &$T, y: &$T| x.naive_average_floor(y));
            }

            #[bench]
            fn average_floor_small_unchecked(b: &mut Bencher) {
                let v = small();
                super::bench(b, &v, |x: &$T, y: &$T| x.unchecked_average_floor(y));
            }

            #[bench]
            fn average_floor_overflowing(b: &mut Bencher) {
                let v = overflowing();
                super::bench(b, &v, |x: &$T, y: &$T| x.average_floor(y));
            }

            #[bench]
            fn average_floor_overflowing_naive(b: &mut Bencher) {
                let v = overflowing();
                super::bench(b, &v, |x: &$T, y: &$T| x.naive_average_floor(y));
            }

            #[bench]
            fn average_floor_overflowing_unchecked(b: &mut Bencher) {
                let v = overflowing();
                super::bench(b, &v, |x: &$T, y: &$T| x.unchecked_average_floor(y));
            }

            #[bench]
            fn average_floor_rand(b: &mut Bencher) {
                let v = rand();
                super::bench(b, &v, |x: &$T, y: &$T| x.average_floor(y));
            }

            #[bench]
            fn average_floor_rand_naive(b: &mut Bencher) {
                let v = rand();
                super::bench(b, &v, |x: &$T, y: &$T| x.naive_average_floor(y));
            }

            #[bench]
            fn average_floor_rand_unchecked(b: &mut Bencher) {
                let v = rand();
                super::bench(b, &v, |x: &$T, y: &$T| x.unchecked_average_floor(y));
            }
        }
    )*}
}

bench_average!(i8, i16, i32, i64, i128, isize);
bench_average!(u8, u16, u32, u64, u128, usize);
<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!");
    let x = 5;
    let y = 8;
    let z = &y;
    if *z == y {
        println!("{:p} {} {}",z,*z, z);
    }

    let mut i: i32 = 1;
    //    foo(&mut i);//error: cannot borrow immutable borrowed content `*z` as mutable
    let z=&mut i;
    foo(z);//error: cannot borrow immutable borrowed content `*z` as mutable
    println!("{} {}",*z,z);

    //reference:
    let x = 5;
    let y = &x;

    println!("{}", *y);
    println!("{:p}", y);
    println!("{}", y);//because println! will automatically dereference it for us.

    let x = 5;
    let y = &x;
    println!("{}", succ(y));
    println!("{}", succ(&x));
    println!("{}", x);//unchanged

    let mut x = 5;
    let y = &mut x;

    let x = 5;
    let y = &x;
    let z = &x;

    let mut x = 5;
    let y = &mut x;
    //    let z = &mut x; // error: cannot borrow `x` as mutable more than once at a time

    //boxes:
    let x = Box::new(5);//Boxes are appropriate to use in two situations: Recursive data structures, and occasionally, when returning data.
    println!("{}", succ(&*x));
    println!("{}", succ(&*x));
    println!("{}", succ(&*x));

    //recursive data structure
    let list: List<i32> = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Cons(3, Box::new(List::Nil))))));
    println!("{:?}", list);

    let x = &mut 5;
    if *x < 10 {
        let y = &x; // uhm https://github.com/rust-lang/rust/issues/21575
        println!("Oh no: {} {:p}", y,y);
        println!("Oh no: {} {:p}", x,x);
        //*y=&mut 6;
    }
    println!("Oh no: {} {:p}", x,x);
    *x -= 1;
    println!("Oh no: {} {:p}", x,x);
}//main //Box::new freed here

#[derive(Show)]
enum List<T> {
    Cons(T, Box<List<T>>),
    //The reference to another List inside of the Cons enum variant must be a box, because we don't
    //know the length of the list. Because we don't know the length, we don't know the size, and
    //therefore, we need to heap allocate our list.
    //Working with recursive or other unknown-sized data structures is the primary use-case for boxes.
    Nil,
}

fn foo(x: &mut i32) {
    *x = 5
}

fn succ(x: &i32) -> i32 { *x + 1 }

fn realsucc(x: i32) -> i32 { x + 1 }

<commit_msg>derive Show became derive Debug<commit_after>//#![feature(custom_derive)]

fn main() {
    println!("Hello, world!");
    let x = 5;
    let y = 8;
    let z = &y;
    if *z == y {
        println!("{:p} {} {}",z,*z, z);
    }

    let mut i: i32 = 1;
    //    foo(&mut i);//error: cannot borrow immutable borrowed content `*z` as mutable
    let z=&mut i;
    foo(z);//error: cannot borrow immutable borrowed content `*z` as mutable
    println!("{} {}",*z,z);

    //reference:
    let x = 5;
    let y = &x;

    println!("{}", *y);
    println!("{:p}", y);
    println!("{}", y);//because println! will automatically dereference it for us.

    let x = 5;
    let y = &x;
    println!("{}", succ(y));
    println!("{}", succ(&x));
    println!("{}", x);//unchanged

    let mut x = 5;
    let y = &mut x;

    let x = 5;
    let y = &x;
    let z = &x;

    let mut x = 5;
    let y = &mut x;
    //    let z = &mut x; // error: cannot borrow `x` as mutable more than once at a time

    //boxes:
    let x = Box::new(5);//Boxes are appropriate to use in two situations: Recursive data structures, and occasionally, when returning data.
    println!("{}", succ(&*x));
    println!("{}", succ(&*x));
    println!("{}", succ(&*x));

    //recursive data structure
    let list: List<i32> = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Cons(3, Box::new(List::Nil))))));
    println!("{:?}", list);

    let x = &mut 5;
    if *x < 10 {
        let y = &x; // uhm https://github.com/rust-lang/rust/issues/21575
        println!("Oh no: {} {:p}", y,y);
        println!("Oh no: {} {:p}", x,x);
        //*y=&mut 6;
    }
    println!("Oh no: {} {:p}", x,x);
    *x -= 1;
    println!("Oh no: {} {:p}", x,x);

    //src: https://doc.rust-lang.org/nightly/book/functions.html#function-pointers
    //function pointers
    fn plus_one(i: i32) -> i32 {
            i + 1
    }
    // without type inference
    let f: fn(i32) -> i32 = plus_one;
    println!("{}",f(10));

    // with type inference
    let f = plus_one;
    println!("{}",f(10));
}//main //Box::new freed here

#[derive(Debug)]
enum List<T> {
    Cons(T, Box<List<T>>),
    //The reference to another List inside of the Cons enum variant must be a box, because we don't
    //know the length of the list. Because we don't know the length, we don't know the size, and
    //therefore, we need to heap allocate our list.
    //Working with recursive or other unknown-sized data structures is the primary use-case for boxes.
    Nil,
}

fn foo(x: &mut i32) {
    *x = 5
}

fn succ(x: &i32) -> i32 { *x + 1 }

fn realsucc(x: i32) -> i32 { x + 1 }

<|endoftext|>