<commit_before>// Copyright 2013 The rust-pcre authors.
//
// 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.

#[link(name = "pcre", vers = "0.1")];
#[crate_type = "lib"];

use std::libc::{c_int, c_uchar, c_void};
use std::option::{Option};
use std::ptr;
use std::vec;

pub type options = c_int;
pub type study_options = c_int;

pub static PCRE_CASELESS: options = 0x00000001;
pub static PCRE_MULTILINE: options = 0x00000002;
pub static PCRE_DOTALL: options = 0x00000004;
pub static PCRE_EXTENDED: options = 0x00000008;
pub static PCRE_ANCHORED: options = 0x00000010;
pub static PCRE_DOLLAR_ENDONLY: options = 0x00000020;
pub static PCRE_EXTRA: options = 0x00000040;
pub static PCRE_NOTBOL: options = 0x00000080;
pub static PCRE_NOTEOL: options = 0x00000100;
pub static PCRE_UNGREEDY: options = 0x00000200;
pub static PCRE_NOTEMPTY: options = 0x00000400;
pub static PCRE_UTF8: options = 0x00000800;
pub static PCRE_UTF16: options = 0x00000800;
pub static PCRE_UTF32: options = 0x00000800;
pub static PCRE_NO_AUTO_CAPTURE: options = 0x00001000;
pub static PCRE_NO_UTF8_CHECK: options = 0x00002000;
pub static PCRE_NO_UTF16_CHECK: options = 0x00002000;
pub static PCRE_NO_UTF32_CHECK: options = 0x00002000;
pub static PCRE_AUTO_CALLOUT: options = 0x00004000;
pub static PCRE_PARTIAL_SOFT: options = 0x00008000;
pub static PCRE_PARTIAL: options = 0x00008000;
pub static PCRE_NEVER_UTF: options = 0x00010000;
pub static PCRE_DFA_SHORTEST: options = 0x00010000;
pub static PCRE_DFA_RESTART: options = 0x00020000;
pub static PCRE_FIRSTLINE: options = 0x00040000;
pub static PCRE_DUPNAMES: options = 0x00080000;
pub static PCRE_NEWLINE_CR: options = 0x00100000;
pub static PCRE_NEWLINE_LF: options = 0x00200000;
pub static PCRE_NEWLINE_CRLF: options = 0x00300000;
pub static PCRE_NEWLINE_ANY: options = 0x00400000;
pub static PCRE_NEWLINE_ANYCRLF: options = 0x00500000;
pub static PCRE_BSR_ANYCRLF: options = 0x00800000;
pub static PCRE_BSR_UNICODE: options = 0x01000000;
pub static PCRE_JAVASCRIPT_COMPAT: options = 0x02000000;
pub static PCRE_NO_START_OPTIMIZE: options = 0x04000000;
pub static PCRE_NO_START_OPTIMISE: options = 0x04000000;
pub static PCRE_PARTIAL_HARD: options = 0x08000000;
pub static PCRE_NOTEMPTY_ATSTART: options = 0x10000000;
pub static PCRE_UCP: options = 0x20000000;

pub static PCRE_STUDY_JIT_COMPILE: study_options = 0x0001;
pub static PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE: study_options = 0x0002;
pub static PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE: study_options = 0x0004;
pub static PCRE_STUDY_EXTRA_NEEDED: study_options = 0x0008;

mod detail;

pub struct Pcre {

    priv code: *detail::pcre,

    priv extra: *detail::pcre_extra,

    priv capture_count_: uint

}

pub struct Match<'self> {

    priv subject: &'self str,

    priv ovector: ~[c_int]

}

impl Pcre {
    fn compile(pattern: &str) -> Pcre {
        Pcre::compile_with_options(pattern, 0)
    }

    fn compile_with_options(pattern: &str, options: options) -> Pcre {
        do pattern.with_c_str |pattern_c_str| {
            // Use the default character tables.
            let tableptr: *c_uchar = ptr::null();
            let code = detail::pcre_compile(pattern_c_str, options, tableptr);
            assert!(ptr::is_not_null(code));

            let extra: *detail::pcre_extra = ptr::null();

            let mut capture_count: c_int = 0;
            detail::pcre_fullinfo(code, extra, detail::PCRE_INFO_CAPTURECOUNT, &mut capture_count as *mut c_int as *mut c_void);

            Pcre {
                code: code,
                extra: extra,
                capture_count_: capture_count as uint
            }
        }
    }

    fn capture_count(&self) -> uint {
        self.capture_count_
    }

    fn exec<'a>(&self, subject: &'a str) -> Option<Match<'a>> {
        self.exec_from(subject, 0)
    }

    fn exec_from<'a>(&self, subject: &'a str, startoffset: uint) -> Option<Match<'a>> {
        self.exec_from_with_options(subject, startoffset, 0)
    }

    fn exec_from_with_options<'a>(&self, subject: &'a str, startoffset: uint, options: options) -> Option<Match<'a>> {
        let ovecsize = (self.capture_count_ + 1) * 3;
        let mut ovector: ~[c_int] = vec::from_elem(ovecsize, 0 as c_int);

        unsafe {
            do subject.with_c_str_unchecked |subject_c_str| -> Option<Match<'a>> {
                if detail::pcre_exec(self.code, self.extra, subject_c_str, subject.len() as c_int, startoffset as c_int, options, vec::raw::to_mut_ptr(ovector), ovecsize as c_int) {
                    Some(Match {
                        subject: subject,
                        // TODO: Is it possible to avoid to_owned()?
                        // Probably need multiple lifetime parameters:
                        // https://mail.mozilla.org/pipermail/rust-dev/2013-September/005829.html
                        ovector: ovector.slice_to((self.capture_count_ + 1) * 2).to_owned()
                    })
                } else {
                    None
                }
            }
        }
    }

    fn study(&mut self) -> bool {
        self.study_with_options(0)
    }

    fn study_with_options(&mut self, options: study_options) -> bool {
        // Free any current study data.
        detail::pcre_free_study(self.extra);
        self.extra = ptr::null();

        let extra = detail::pcre_study(self.code, options);
        self.extra = extra;
        ptr::is_not_null(extra)
    }
}

impl Drop for Pcre {
    fn drop(&mut self) {
        detail::pcre_free_study(self.extra);
        self.extra = ptr::null();
        detail::pcre_free(self.code as *c_void);
        self.code = ptr::null();
    }
}

impl<'self> Match<'self> {

    fn group_start(&self, n: uint) -> uint {
        self.ovector[(n * 2) as uint] as uint
    }

    fn group_end(&self, n: uint) -> uint {
        self.ovector[(n * 2 + 1) as uint] as uint
    }

    fn group_len(&self, n: uint) -> uint {
        let group_offsets = self.ovector.slice_from((n * 2) as uint);
        (group_offsets[1] - group_offsets[0]) as uint
    }

    fn group(&self, n: uint) -> &'self str {
        let group_offsets = self.ovector.slice_from((n * 2) as uint);
        let start = group_offsets[0];
        let end = group_offsets[1];
        self.subject.slice(start as uint, end as uint)
    }

}

#[cfg(test)]
mod tests {

    #[test]
    #[should_fail]
    fn test_compile_nul() {
        // Nul bytes are not allowed in the pattern string.
        ::Pcre::compile("\0abc");
    }

    #[test]
    #[should_fail]
    fn test_compile_bad_pattern() {
        ::Pcre::compile("[");
    }

    #[test]
    fn test_compile_capture_count() {
        let re = ::Pcre::compile("(?:abc)(def)");
        assert_eq!(re.capture_count(), 1u);
    }

    #[test]
    fn test_exec_basic() {
        let re = ::Pcre::compile("^...$");
        assert_eq!(re.capture_count(), 0u);
        let m = re.exec("abc").unwrap();
        assert_eq!(m.group(0), "abc");
    }

    #[test]
    fn test_exec_no_match() {
        let re = ::Pcre::compile("abc");
        assert!(re.exec("def").is_none());
    }

    #[test]
    fn test_exec_nul_byte() {
        // Nul bytes *are* allowed in subject strings, however.
        let re = ::Pcre::compile("abc\\0def");
        let m = re.exec("abc\0def").unwrap();
        assert_eq!(m.group(0), "abc\0def");
    }

    #[test]
    fn test_exec_from_basic() {
        let re = ::Pcre::compile("abc");
        let subject = "abcabc";
        let m1 = re.exec_from(subject, 1u).unwrap();
        assert_eq!(m1.group_start(0u), 3u);
        assert_eq!(m1.group_end(0u), 6u);
        assert_eq!(m1.group_len(0u), 3u);
        let m2 = re.exec(subject).unwrap();
        assert_eq!(m2.group_start(0u), 0u);
    }

    #[test]
    fn test_study_basic() {
        let mut re = ::Pcre::compile("abc");
        let mut study_res = re.study();
        assert!(study_res);
        // Re-study the pattern two more times (to check for leaks when the test program
        // is run through Valgrind).
        study_res = re.study();
        assert!(study_res);
        study_res = re.study();
        assert!(study_res);
    }
}
<commit_msg>Rename the `tests` module to `test`<commit_after>// Copyright 2013 The rust-pcre authors.
//
// 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.

#[link(name = "pcre", vers = "0.1")];
#[crate_type = "lib"];

use std::libc::{c_int, c_uchar, c_void};
use std::option::{Option};
use std::ptr;
use std::vec;

pub type options = c_int;
pub type study_options = c_int;

pub static PCRE_CASELESS: options = 0x00000001;
pub static PCRE_MULTILINE: options = 0x00000002;
pub static PCRE_DOTALL: options = 0x00000004;
pub static PCRE_EXTENDED: options = 0x00000008;
pub static PCRE_ANCHORED: options = 0x00000010;
pub static PCRE_DOLLAR_ENDONLY: options = 0x00000020;
pub static PCRE_EXTRA: options = 0x00000040;
pub static PCRE_NOTBOL: options = 0x00000080;
pub static PCRE_NOTEOL: options = 0x00000100;
pub static PCRE_UNGREEDY: options = 0x00000200;
pub static PCRE_NOTEMPTY: options = 0x00000400;
pub static PCRE_UTF8: options = 0x00000800;
pub static PCRE_UTF16: options = 0x00000800;
pub static PCRE_UTF32: options = 0x00000800;
pub static PCRE_NO_AUTO_CAPTURE: options = 0x00001000;
pub static PCRE_NO_UTF8_CHECK: options = 0x00002000;
pub static PCRE_NO_UTF16_CHECK: options = 0x00002000;
pub static PCRE_NO_UTF32_CHECK: options = 0x00002000;
pub static PCRE_AUTO_CALLOUT: options = 0x00004000;
pub static PCRE_PARTIAL_SOFT: options = 0x00008000;
pub static PCRE_PARTIAL: options = 0x00008000;
pub static PCRE_NEVER_UTF: options = 0x00010000;
pub static PCRE_DFA_SHORTEST: options = 0x00010000;
pub static PCRE_DFA_RESTART: options = 0x00020000;
pub static PCRE_FIRSTLINE: options = 0x00040000;
pub static PCRE_DUPNAMES: options = 0x00080000;
pub static PCRE_NEWLINE_CR: options = 0x00100000;
pub static PCRE_NEWLINE_LF: options = 0x00200000;
pub static PCRE_NEWLINE_CRLF: options = 0x00300000;
pub static PCRE_NEWLINE_ANY: options = 0x00400000;
pub static PCRE_NEWLINE_ANYCRLF: options = 0x00500000;
pub static PCRE_BSR_ANYCRLF: options = 0x00800000;
pub static PCRE_BSR_UNICODE: options = 0x01000000;
pub static PCRE_JAVASCRIPT_COMPAT: options = 0x02000000;
pub static PCRE_NO_START_OPTIMIZE: options = 0x04000000;
pub static PCRE_NO_START_OPTIMISE: options = 0x04000000;
pub static PCRE_PARTIAL_HARD: options = 0x08000000;
pub static PCRE_NOTEMPTY_ATSTART: options = 0x10000000;
pub static PCRE_UCP: options = 0x20000000;

pub static PCRE_STUDY_JIT_COMPILE: study_options = 0x0001;
pub static PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE: study_options = 0x0002;
pub static PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE: study_options = 0x0004;
pub static PCRE_STUDY_EXTRA_NEEDED: study_options = 0x0008;

mod detail;

pub struct Pcre {

    priv code: *detail::pcre,

    priv extra: *detail::pcre_extra,

    priv capture_count_: uint

}

pub struct Match<'self> {

    priv subject: &'self str,

    priv ovector: ~[c_int]

}

impl Pcre {
    fn compile(pattern: &str) -> Pcre {
        Pcre::compile_with_options(pattern, 0)
    }

    fn compile_with_options(pattern: &str, options: options) -> Pcre {
        do pattern.with_c_str |pattern_c_str| {
            // Use the default character tables.
            let tableptr: *c_uchar = ptr::null();
            let code = detail::pcre_compile(pattern_c_str, options, tableptr);
            assert!(ptr::is_not_null(code));

            let extra: *detail::pcre_extra = ptr::null();

            let mut capture_count: c_int = 0;
            detail::pcre_fullinfo(code, extra, detail::PCRE_INFO_CAPTURECOUNT, &mut capture_count as *mut c_int as *mut c_void);

            Pcre {
                code: code,
                extra: extra,
                capture_count_: capture_count as uint
            }
        }
    }

    fn capture_count(&self) -> uint {
        self.capture_count_
    }

    fn exec<'a>(&self, subject: &'a str) -> Option<Match<'a>> {
        self.exec_from(subject, 0)
    }

    fn exec_from<'a>(&self, subject: &'a str, startoffset: uint) -> Option<Match<'a>> {
        self.exec_from_with_options(subject, startoffset, 0)
    }

    fn exec_from_with_options<'a>(&self, subject: &'a str, startoffset: uint, options: options) -> Option<Match<'a>> {
        let ovecsize = (self.capture_count_ + 1) * 3;
        let mut ovector: ~[c_int] = vec::from_elem(ovecsize, 0 as c_int);

        unsafe {
            do subject.with_c_str_unchecked |subject_c_str| -> Option<Match<'a>> {
                if detail::pcre_exec(self.code, self.extra, subject_c_str, subject.len() as c_int, startoffset as c_int, options, vec::raw::to_mut_ptr(ovector), ovecsize as c_int) {
                    Some(Match {
                        subject: subject,
                        // TODO: Is it possible to avoid to_owned()?
                        // Probably need multiple lifetime parameters:
                        // https://mail.mozilla.org/pipermail/rust-dev/2013-September/005829.html
                        ovector: ovector.slice_to((self.capture_count_ + 1) * 2).to_owned()
                    })
                } else {
                    None
                }
            }
        }
    }

    fn study(&mut self) -> bool {
        self.study_with_options(0)
    }

    fn study_with_options(&mut self, options: study_options) -> bool {
        // Free any current study data.
        detail::pcre_free_study(self.extra);
        self.extra = ptr::null();

        let extra = detail::pcre_study(self.code, options);
        self.extra = extra;
        ptr::is_not_null(extra)
    }
}

impl Drop for Pcre {
    fn drop(&mut self) {
        detail::pcre_free_study(self.extra);
        self.extra = ptr::null();
        detail::pcre_free(self.code as *c_void);
        self.code = ptr::null();
    }
}

impl<'self> Match<'self> {

    fn group_start(&self, n: uint) -> uint {
        self.ovector[(n * 2) as uint] as uint
    }

    fn group_end(&self, n: uint) -> uint {
        self.ovector[(n * 2 + 1) as uint] as uint
    }

    fn group_len(&self, n: uint) -> uint {
        let group_offsets = self.ovector.slice_from((n * 2) as uint);
        (group_offsets[1] - group_offsets[0]) as uint
    }

    fn group(&self, n: uint) -> &'self str {
        let group_offsets = self.ovector.slice_from((n * 2) as uint);
        let start = group_offsets[0];
        let end = group_offsets[1];
        self.subject.slice(start as uint, end as uint)
    }

}

#[cfg(test)]
mod test {

    #[test]
    #[should_fail]
    fn test_compile_nul() {
        // Nul bytes are not allowed in the pattern string.
        ::Pcre::compile("\0abc");
    }

    #[test]
    #[should_fail]
    fn test_compile_bad_pattern() {
        ::Pcre::compile("[");
    }

    #[test]
    fn test_compile_capture_count() {
        let re = ::Pcre::compile("(?:abc)(def)");
        assert_eq!(re.capture_count(), 1u);
    }

    #[test]
    fn test_exec_basic() {
        let re = ::Pcre::compile("^...$");
        assert_eq!(re.capture_count(), 0u);
        let m = re.exec("abc").unwrap();
        assert_eq!(m.group(0), "abc");
    }

    #[test]
    fn test_exec_no_match() {
        let re = ::Pcre::compile("abc");
        assert!(re.exec("def").is_none());
    }

    #[test]
    fn test_exec_nul_byte() {
        // Nul bytes *are* allowed in subject strings, however.
        let re = ::Pcre::compile("abc\\0def");
        let m = re.exec("abc\0def").unwrap();
        assert_eq!(m.group(0), "abc\0def");
    }

    #[test]
    fn test_exec_from_basic() {
        let re = ::Pcre::compile("abc");
        let subject = "abcabc";
        let m1 = re.exec_from(subject, 1u).unwrap();
        assert_eq!(m1.group_start(0u), 3u);
        assert_eq!(m1.group_end(0u), 6u);
        assert_eq!(m1.group_len(0u), 3u);
        let m2 = re.exec(subject).unwrap();
        assert_eq!(m2.group_start(0u), 0u);
    }

    #[test]
    fn test_study_basic() {
        let mut re = ::Pcre::compile("abc");
        let mut study_res = re.study();
        assert!(study_res);
        // Re-study the pattern two more times (to check for leaks when the test program
        // is run through Valgrind).
        study_res = re.study();
        assert!(study_res);
        study_res = re.study();
        assert!(study_res);
    }
}
<|endoftext|>


<commit_before>use std::sync::mpsc;
use std::sync::mpsc::TryRecvError;
use std::time::{Instant, Duration};
use std::thread;
use std::io::Stdout;
use pbr::{ProgressBar, Units};

// like a beautiful film
static REFRESH_DELAY: u64 = 1000 / 15;

pub struct Progress {
    thread: thread::JoinHandle<()>,
    tx: mpsc::Sender<Msg>,
}

pub enum Msg {
    SetMessage(String),
    SetSize(u64),
    Add(u64),
    Finish(String),
}

fn new_pb(size: u64) -> ProgressBar<Stdout> {
    let mut pb = ProgressBar::new(size);
    pb.set_units(Units::Bytes);
    pb.format(" =💃 ⛩");
    pb.tick_format("⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏");
    pb
}

fn do_maybe<F>(pb_maybe: &mut Option<ProgressBar<Stdout>>, f: F)
    where F : Fn(&mut ProgressBar<Stdout>) -> ()
{
    if let Some(ref mut pb) = pb_maybe.as_mut() {
        f(pb);
    }
}

impl Progress {
    pub fn new() -> Progress {
        let (tx, rx) = mpsc::channel();
        let t = thread::spawn(move || {
            let mut pb = None;
            let mut last_add = Instant::now();
            let mut frame_total: u64 = 0;
            let mut frame_message: Option<String> = None;

            loop {
                match rx.try_recv() {
                    Ok(Msg::SetMessage(msg)) => {
                        frame_message = Some(msg);
                    }
                    Ok(Msg::SetSize(size)) => {
                        pb = Some(new_pb(size));
                    }
                    Ok(Msg::Add(size)) => {
                        frame_total += size;
                    }
                    Ok(Msg::Finish(msg)) => {
                        do_maybe(&mut pb, |pb| pb.finish_print(&msg));
                        break;
                    }
                    Err(TryRecvError::Empty) => {
                        if let Some(msg) = frame_message {
                            do_maybe(&mut pb, |pb| pb.message(&msg));
                        }
                        do_maybe(&mut pb, |pb| {
                            if pb.total > 0 {
                                pb.add(frame_total);
                            }
                        });
                        if frame_total > 0 {
                            last_add = Instant::now();
                            do_maybe(&mut pb, |pb| { pb.add(frame_total); });
                        } else if last_add.elapsed() < Duration::from_secs(5) {
                            do_maybe(&mut pb, |pb| pb.tick());
                        }

                        frame_message = None;
                        frame_total = 0;
                        thread::sleep(Duration::from_millis(REFRESH_DELAY));
                    }
                    _ => {
                        panic!("disconnected channel");
                    }
                }
            }
        });
        Progress {
            thread: t,
            tx: tx,
        }
    }

    pub fn message<S: Into<String>>(&self, msg: S) {
        self.tx.send(Msg::SetMessage(msg.into())).unwrap();
    }

    pub fn finish<S: Into<String>>(self, msg: S) {
        self.tx.send(Msg::Finish(msg.into())).unwrap();
        let _ = self.thread.join();
    }

    pub fn add(&self, amount: u64) {
        self.tx.send(Msg::Add(amount)).unwrap();
    }

    pub fn size(&self, size: u64) {
        self.tx.send(Msg::SetSize(size)).unwrap();
    }
}

<commit_msg>maaath it's the best<commit_after>use std::sync::mpsc;
use std::sync::mpsc::TryRecvError;
use std::time::{Instant, Duration};
use std::thread;
use std::io::Stdout;
use pbr::{ProgressBar, Units};

// like a beautiful film
static REFRESH_DELAY: u64 = 1000 / 10;

pub struct Progress {
    thread: thread::JoinHandle<()>,
    tx: mpsc::Sender<Msg>,
}

pub enum Msg {
    SetMessage(String),
    SetSize(u64),
    Add(u64),
    Finish(String),
}

fn new_pb(size: u64) -> ProgressBar<Stdout> {
    let mut pb = ProgressBar::new(size);
    pb.set_units(Units::Bytes);
    pb.format(" =💃 ⛩");
    pb.tick_format("⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏");
    pb
}

fn do_maybe<F>(pb_maybe: &mut Option<ProgressBar<Stdout>>, f: F)
    where F : Fn(&mut ProgressBar<Stdout>) -> ()
{
    if let Some(ref mut pb) = pb_maybe.as_mut() {
        f(pb);
    }
}

impl Progress {
    pub fn new() -> Progress {
        let (tx, rx) = mpsc::channel();
        let t = thread::spawn(move || {
            let mut pb = None;
            let mut last_add = Instant::now();
            let mut frame_total: u64 = 0;
            let mut frame_message: Option<String> = None;

            loop {
                match rx.try_recv() {
                    Ok(Msg::SetMessage(msg)) => {
                        frame_message = Some(msg);
                    }
                    Ok(Msg::SetSize(size)) => {
                        pb = Some(new_pb(size));
                    }
                    Ok(Msg::Add(size)) => {
                        frame_total += size;
                    }
                    Ok(Msg::Finish(msg)) => {
                        do_maybe(&mut pb, |pb| pb.finish_print(&msg));
                        break;
                    }
                    Err(TryRecvError::Empty) => {
                        if let Some(msg) = frame_message {
                            do_maybe(&mut pb, |pb| pb.message(&msg));
                        }
                        if frame_total > 0 {
                            last_add = Instant::now();
                            do_maybe(&mut pb, |pb| { pb.add(frame_total); });
                        } else if last_add.elapsed() < Duration::from_secs(5) {
                            do_maybe(&mut pb, |pb| pb.tick());
                        }

                        frame_message = None;
                        frame_total = 0;
                        thread::sleep(Duration::from_millis(REFRESH_DELAY));
                    }
                    _ => {
                        panic!("disconnected channel");
                    }
                }
            }
        });
        Progress {
            thread: t,
            tx: tx,
        }
    }

    pub fn message<S: Into<String>>(&self, msg: S) {
        self.tx.send(Msg::SetMessage(msg.into())).unwrap();
    }

    pub fn finish<S: Into<String>>(self, msg: S) {
        self.tx.send(Msg::Finish(msg.into())).unwrap();
        let _ = self.thread.join();
    }

    pub fn add(&self, amount: u64) {
        self.tx.send(Msg::Add(amount)).unwrap();
    }

    pub fn size(&self, size: u64) {
        self.tx.send(Msg::SetSize(size)).unwrap();
    }
}

<|endoftext|>


<commit_before>pub trait RefInto<'a, T>: MutInto<'a, T> {
    fn ref_into(&'a self) -> T;
}

pub trait MutInto<'a, T> {
    fn mut_into(&'a mut self) -> T;
}
<commit_msg>Add basic `RefInto` and `MutInto` implementations<commit_after>pub trait RefInto<'a, T>: MutInto<'a, T> {
    fn ref_into(&'a self) -> T;
}

pub trait MutInto<'a, T> {
    fn mut_into(&'a mut self) -> T;
}

impl<'a, T: 'a> RefInto<'a, &'a T> for T {
    fn ref_into(&'a self) -> &'a T {
        self
    }
}

impl<'a, T: 'a> RefInto<'a, &'a T> for &'a T {
    fn ref_into(&'a self) -> &'a T {
        &**self
    }
}

impl<'a, T: 'a> MutInto<'a, &'a T> for T {
    fn mut_into(&'a mut self) -> &'a T {
        self
    }
}

impl<'a, T: 'a> MutInto<'a, &'a T> for &'a T {
    fn mut_into(&'a mut self) -> &'a T {
        &**self
    }
}

impl<'a, T: 'a> MutInto<'a, &'a T> for &'a mut T {
    fn mut_into(&'a mut self) -> &'a T {
        &**self
    }
}

impl<'a, T: 'a> MutInto<'a, &'a mut T> for T {
    fn mut_into(&'a mut self) -> &'a mut T {
        self
    }
}

impl<'a, T: 'a> MutInto<'a, &'a mut T> for &'a mut T {
    fn mut_into(&'a mut self) -> &'a mut T {
        &mut **self
    }
}
<|endoftext|>


<commit_before>use std::sync::{
    Arc,
    Mutex,
};

use c_ares;
use futures;
use futures::Future;

use error::Error;
use eventloop::{
    EventLoop,
    EventLoopHandle
};

/// Used to configure the behaviour of the resolver.
#[derive(Default)]
pub struct Options {
    inner: c_ares::Options,
}

impl Options {
    /// Returns a fresh `Options`, on which no values are set.
    pub fn new() -> Self {
        Self::default()
    }
}

/// An asynchronous DNS resolver.
pub struct Resolver {
    ares_channel: Arc<Mutex<c_ares::Channel>>,
    event_loop_handle: EventLoopHandle,
}

impl Resolver {
    /// Create a new Resolver.
    pub fn new(options: Options) -> Result<Resolver, Error> {
        // Create and run the event loop.
        let event_loop = try!(EventLoop::new(options.inner));
        let channel = event_loop.ares_channel.clone();
        let handle = event_loop.run();

        // Return the Resolver.
        let resolver = Resolver {
            ares_channel: channel,
            event_loop_handle: handle,
        };
        Ok(resolver)
    }

    pub fn query_cname(&self, name: &str)
        -> futures::BoxFuture<c_ares::CNameResults, c_ares::Error> {
        let (c, p) = futures::oneshot();
        self.ares_channel.lock().unwrap().query_cname(name, move |result| {
            c.complete(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    pub fn query_mx(&self, name: &str)
        -> futures::BoxFuture<c_ares::MXResults, c_ares::Error> {
        let (c, p) = futures::oneshot();
        self.ares_channel.lock().unwrap().query_mx(name, move |result| {
            c.complete(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    pub fn query_naptr(&self, name: &str)
        -> futures::BoxFuture<c_ares::NAPTRResults, c_ares::Error> {
        let (c, p) = futures::oneshot();
        self.ares_channel.lock().unwrap().query_naptr(name, move |result| {
            c.complete(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }
}

impl Drop for Resolver {
    fn drop(&mut self) {
        // Shut down the event loop.
        self.event_loop_handle.shutdown();
    }
}
<commit_msg>Implement options<commit_after>use std::sync::{
    Arc,
    Mutex,
};

use c_ares;
use futures;
use futures::Future;

use error::Error;
use eventloop::{
    EventLoop,
    EventLoopHandle
};

/// Used to configure the behaviour of the resolver.
#[derive(Default)]
pub struct Options {
    inner: c_ares::Options,
}

impl Options {
    /// Returns a fresh `Options`, on which no values are set.
    pub fn new() -> Self {
        Self::default()
    }

    /// Set flags controlling the behaviour of the resolver.  The available
    /// flags are documented [here](flags/index.html).
    pub fn set_flags(&mut self, flags: c_ares::flags::Flags) -> &mut Self {
        self.inner.set_flags(flags);
        self
    }

    /// Set the number of milliseconds each name server is given to respond to
    /// a query on the first try.  (After the first try, the timeout algorithm
    /// becomes more complicated, but scales linearly with the value of
    /// timeout).  The default is 5000ms.
    pub fn set_timeout(&mut self, ms: u32) -> &mut Self {
        self.inner.set_timeout(ms);
        self
    }

    /// Set the number of tries the resolver will try contacting each name
    /// server before giving up.  The default is four tries.
    pub fn set_tries(&mut self, tries: u32) -> &mut Self {
        self.inner.set_tries(tries);
        self
    }

    /// Set the number of dots which must be present in a domain name for it to
    /// be queried for "as is" prior to querying for it with the default domain
    /// extensions appended.  The default value is 1 unless set otherwise by
    /// resolv.conf or the RES_OPTIONS environment variable.
    pub fn set_ndots(&mut self, ndots: u32) -> &mut Self {
        self.inner.set_ndots(ndots);
        self
    }

    /// Set the UDP port to use for queries.  The default value is 53, the
    /// standard name service port.
    pub fn set_udp_port(&mut self, udp_port: u16) -> &mut Self {
        self.inner.set_udp_port(udp_port);
        self
    }

    /// Set the TCP port to use for queries.  The default value is 53, the
    /// standard name service port.
    pub fn set_tcp_port(&mut self, tcp_port: u16) -> &mut Self {
        self.inner.set_tcp_port(tcp_port);
        self
    }

    /// Set the domains to search, instead of the domains specified in
    /// resolv.conf or the domain derived from the kernel hostname variable.
    pub fn set_domains(&mut self, domains: &[&str]) -> &mut Self {
        self.inner.set_domains(domains);
        self
    }

    /// Set the lookups to perform for host queries. `lookups` should be set to
    /// a string of the characters "b" or "f", where "b" indicates a DNS lookup
    /// and "f" indicates a lookup in the hosts file.
    pub fn set_lookups(&mut self, lookups: &str) -> &mut Self {
        self.inner.set_lookups(lookups);
        self
    }

    /// Set the socket send buffer size.
    pub fn set_sock_send_buffer_size(&mut self, size: u32) -> &mut Self {
        self.inner.set_sock_send_buffer_size(size);
        self
    }

    /// Set the socket receive buffer size.
    pub fn set_sock_receive_buffer_size(&mut self, size: u32) -> &mut Self {
        self.inner.set_sock_receive_buffer_size(size);
        self
    }

    /// Configure round robin selection of nameservers.
    pub fn set_rotate(&mut self) -> &mut Self {
        self.inner.set_rotate();
        self
    }

    /// Prevent round robin selection of nameservers.
    pub fn set_no_rotate(&mut self) -> &mut Self {
        self.inner.set_no_rotate();
        self
    }

    /// Set the EDNS packet size.
    pub fn set_ednspsz(&mut self, size: u32) -> &mut Self {
        self.inner.set_ednspsz(size);
        self
    }
}

/// An asynchronous DNS resolver.
pub struct Resolver {
    ares_channel: Arc<Mutex<c_ares::Channel>>,
    event_loop_handle: EventLoopHandle,
}

impl Resolver {
    /// Create a new Resolver.
    pub fn new(options: Options) -> Result<Resolver, Error> {
        // Create and run the event loop.
        let event_loop = try!(EventLoop::new(options.inner));
        let channel = event_loop.ares_channel.clone();
        let handle = event_loop.run();

        // Return the Resolver.
        let resolver = Resolver {
            ares_channel: channel,
            event_loop_handle: handle,
        };
        Ok(resolver)
    }

    pub fn query_cname(&self, name: &str)
        -> futures::BoxFuture<c_ares::CNameResults, c_ares::Error> {
        let (c, p) = futures::oneshot();
        self.ares_channel.lock().unwrap().query_cname(name, move |result| {
            c.complete(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    pub fn query_mx(&self, name: &str)
        -> futures::BoxFuture<c_ares::MXResults, c_ares::Error> {
        let (c, p) = futures::oneshot();
        self.ares_channel.lock().unwrap().query_mx(name, move |result| {
            c.complete(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    pub fn query_naptr(&self, name: &str)
        -> futures::BoxFuture<c_ares::NAPTRResults, c_ares::Error> {
        let (c, p) = futures::oneshot();
        self.ares_channel.lock().unwrap().query_naptr(name, move |result| {
            c.complete(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }
}

impl Drop for Resolver {
    fn drop(&mut self) {
        // Shut down the event loop.
        self.event_loop_handle.shutdown();
    }
}
<|endoftext|>


<commit_before>//! The `parser` module contains a lot of useful functionality
//! to parse tokens from the lexer (and creating the parsetree
//! and the ast)
//! its an predictiv parser for a LL(1) grammar
//! for more info about the parser: look in the Compiler Dragonbook,
//! Chapter 4.4.4, "Nonrecursive Predictive Parsing"

pub use frontend::lexer::Token;
pub use frontend::ast;
pub use frontend::parsetree::{ParseTree, PNode};
use self::NonTerminalType::*;
use frontend::lexer::Token::{TokPassageName, TokText, TokFormatItalic, TokFormatBold};

/*

----------------------------------------
Grammatik:

LL(1)
------------------------------------------------------------+-----------------------------------
S -> Passage S2                                             |
S2 -> S                                                     |
S2 -> ɛ                                                     |
Passage -> PassageName PassageContent                       | "add passage (name)", simple
PassageContent -> TextPassage PassageContent                | add text as child
PassageContent -> Formatting PassageContent                 |
PassageContent -> ɛ                                         |
Formating -> BoldFormatting                                 |
Formating -> ItalicFormatting                               |
BoldFormatting -> FormatBold BoldContent FormatBold         | add child bold
BoldContent -> TextPassage BoldContent                      | add text as child
BoldContent -> FormatItalic BoldItalicContent FormatItalic  | add child italic
BoldContent -> ɛ                                            |
ItalicFormatting -> FormatItalic ItalicContent FormatItalic | add child italic
ItalicContent -> TextPassage ItalicContent                  | add text as child
ItalicContent -> FormatBold BoldItalicContent FormatBold    | add child bold
ItalicContent -> ɛ                                          | add text as child
BoldItalicContent -> TextPassage                            |
------------------------------------------------------------+-----------------------------------

::Start
Hello World, ''Yeah''.
//Italic// is possible too.

*/

pub fn parse_tokens(tokens: Vec<Token>) -> ast::AST {
    let mut parser: Parser = Parser::new(tokens);
    parser.parsing();
    parser.ast
}

//==============================
// grammar

#[derive(Debug, Copy, Clone)]
pub enum NonTerminalType {
    S,
    S2,
    Passage,
    PassageContent,
    Formating,
    BoldFormatting,
    ItalicFormatting,
    BoldContent,
    ItalicContent,
    BoldItalicContent
}

//==============================
// parser

struct Parser {
    tree: ParseTree,
    ast: ast::AST,
    stack: Stack,
    ast_path: Vec<usize>,
    tokens: Vec<Token>,
    lookahead: usize
}

impl Parser {
    pub fn new(tokens: Vec<Token>) -> Parser {
        Parser {
            tree: ParseTree::new(),
            ast: ast::AST::new(),
            stack: Stack::new(),
            ast_path: Vec::new(),
            tokens: tokens,
            lookahead: 0
        }
    }

    /// the predictive stack ll(1) parsing routine
    pub fn parsing(&mut self) {
        self.stack.push_start();

        while let Some(top) = self.stack.pop() {
            if self.tree.is_terminal(top.to_vec()) {
                self.next_token();
            } else {
                self.apply_grammar(top.to_vec());
            }
        }

        self.tree.print();
    }

    /// apply the ll(1) grammar
    /// the match-statement simulates the parsing-table behavior
    ///
    fn apply_grammar(&mut self, top_path: Vec<usize>) {
        if let Some(token) = self.tokens.get_mut(self.lookahead) {

            let to_add_path: Vec<usize> = top_path.to_vec();

            // the frst item in the tuple is the current state and
            // the snd is the current lookup-token
            let state_first: (NonTerminalType, &Token) = (self.tree.get_non_terminal(top_path).clone(), token);

            let mut new_nodes = Vec::new();
            //use self::*;
            match state_first {
                (S, &TokPassageName(_)) => {
                    new_nodes.push(PNode::new_non_terminal(Passage));
                    new_nodes.push(PNode::new_non_terminal(S2));
                },
                (S2, &TokPassageName(_)) => {
                    new_nodes.push(PNode::new_non_terminal(S));
                },
                (Passage, &TokPassageName(ref name)) => {
                    let new_token: Token = TokPassageName(name.clone());
                    new_nodes.push(PNode::new_terminal(new_token));
                    new_nodes.push(PNode::new_non_terminal(PassageContent));

                    // ast
                    self.ast_path.clear();
                    let ast_count_passages = self.ast.cound_childs(self.ast_path.to_vec());
                    let new_token2: Token = TokPassageName(name.clone());
                    self.ast.add_passage(new_token2);
                    self.ast_path.push(ast_count_passages);
                },
                (PassageContent, &TokText(ref text)) => {
                    let new_token: Token = TokText(text.clone());
                    new_nodes.push(PNode::new_terminal(new_token));
                    new_nodes.push(PNode::new_non_terminal(PassageContent));

                    // ast
                    let new_token2: Token = TokText(text.clone());
                    self.ast.add_child(&self.ast_path, new_token2);
                },
                (PassageContent, &TokFormatBold) | (PassageContent, &TokFormatItalic) => {
                    new_nodes.push(PNode::new_non_terminal(Formating));
                    new_nodes.push(PNode::new_non_terminal(PassageContent));
                },
                (Formating, &TokFormatBold) => {
                    new_nodes.push(PNode::new_non_terminal(BoldFormatting));
                },
                (Formating, &TokFormatItalic) => {
                    new_nodes.push(PNode::new_non_terminal(ItalicFormatting));
                },
                (BoldFormatting, &TokFormatBold) => {
                    new_nodes.push(PNode::new_terminal(TokFormatBold));
                    new_nodes.push(PNode::new_non_terminal(BoldContent));
                    new_nodes.push(PNode::new_terminal(TokFormatBold));

                    // ast
                    let ast_count_passages = self.ast.cound_childs(self.ast_path.to_vec());
                    let ast_token: Token = TokFormatBold;
                    self.ast.add_child(&self.ast_path, ast_token);
                    self.ast_path.push(ast_count_passages);
                },
                (ItalicFormatting, &TokFormatItalic) => {
                    new_nodes.push(PNode::new_terminal(TokFormatItalic));
                    new_nodes.push(PNode::new_non_terminal(ItalicContent));
                    new_nodes.push(PNode::new_terminal(TokFormatItalic));

                    // ast
                    let ast_count_passages = self.ast.cound_childs(self.ast_path.to_vec());
                    let ast_token: Token = TokFormatItalic;
                    self.ast.add_child(&self.ast_path, ast_token);
                    self.ast_path.push(ast_count_passages);
                },
                (BoldContent, &TokText(ref text)) => {
                    let new_token: Token = TokText(text.clone());
                    new_nodes.push(PNode::new_terminal(new_token));
                    new_nodes.push(PNode::new_non_terminal(BoldContent));

                    // ast
                    let ast_token: Token = TokText(text.clone());
                    self.ast.add_child(&self.ast_path, ast_token);
                },
                (ItalicContent, &TokText(ref text)) => {
                    let new_token: Token = TokText(text.clone());
                    new_nodes.push(PNode::new_terminal(new_token));
                    new_nodes.push(PNode::new_non_terminal(ItalicContent));

                    // ast
                    let ast_token: Token = TokText(text.clone());
                    self.ast.add_child(&self.ast_path, ast_token);
                },
                (BoldContent, &TokFormatItalic) => {
                    new_nodes.push(PNode::new_terminal(TokFormatItalic));
                    new_nodes.push(PNode::new_non_terminal(BoldItalicContent));
                    new_nodes.push(PNode::new_terminal(TokFormatItalic));
                },
                (ItalicContent, &TokFormatBold) => {
                    new_nodes.push(PNode::new_terminal(TokFormatBold));
                    new_nodes.push(PNode::new_non_terminal(BoldItalicContent));
                    new_nodes.push(PNode::new_terminal(TokFormatBold));
                },
                (BoldItalicContent, &TokText(ref text)) => {
                    let new_token: Token = TokText(text.clone());
                    new_nodes.push(PNode::new_terminal(new_token));
                },

                (BoldContent, &TokFormatBold) => {
                    // jump one ast-level higher
                    self.ast_path.pop();
                },
                (ItalicContent, &TokFormatItalic) => {
                    // jump one ast-level higher
                    self.ast_path.pop();
                },
                _ => {

                }
            }

            // adds the new nodes to the tree
            // and adds the path in the tree to the stack
            let length = new_nodes.len().clone();
            self.tree.add_nodes(new_nodes, &to_add_path);
            self.stack.push_path(length as u8, to_add_path);

        } else {
            // no token left
            // only ɛ-productions could be here
            // these productions will be poped of the stack
        }
    }

    /// sets the lookahead to the next token
    fn next_token(&mut self) {
        self.lookahead = self.lookahead + 1;
    }
}

//==============================
// stack of the parser
struct Stack {
    data: Vec<Vec<usize>>
}

impl Stack {
    pub fn new() -> Stack {
        Stack { data: Vec::new() }
    }

    /// pushs the address of the first startsymbol to the stack
    fn push_start(&mut self) {
        self.data.push(vec![]);
    }

    /// save the path of the nodes in the tree to the stack
    /// the right part of the production
    /// should be on the stack in reverse order
    fn push_path(&mut self, count_elements: u8, to_add_path: Vec<usize>) {
        for i in 0..count_elements {
            let mut path: Vec<usize> = to_add_path.to_vec();
            path.push((count_elements-i-1) as usize);
            self.data.push(path);
        }
    }

    fn pop(&mut self) -> Option<Vec<usize>> {
        self.data.pop()
    }
}

//==============================
//
#[test]
fn it_works() {

}

<commit_msg>-small changes<commit_after>//! The `parser` module contains a lot of useful functionality
//! to parse tokens from the lexer (and creating the parsetree
//! and the ast)
//! its an predictiv parser for a LL(1) grammar
//! for more info about the parser: look in the Compiler Dragonbook,
//! Chapter 4.4.4, "Nonrecursive Predictive Parsing"

pub use frontend::lexer::Token;
pub use frontend::ast;
pub use frontend::parsetree::{ParseTree, PNode};
use self::NonTerminalType::*;
use frontend::lexer::Token::{TokPassageName, TokText, TokFormatItalic, TokFormatBold};

/*

----------------------------------------
Grammatik:

LL(1)
------------------------------------------------------------+-----------------------------------
S -> Passage S2                                             |
S2 -> S                                                     |
S2 -> ɛ                                                     |
Passage -> PassageName PassageContent                       | "add passage (name)", simple
PassageContent -> TextPassage PassageContent                | add text as child
PassageContent -> Formatting PassageContent                 |
PassageContent -> ɛ                                         |
Formating -> BoldFormatting                                 |
Formating -> ItalicFormatting                               |
BoldFormatting -> FormatBold BoldContent FormatBold         | add child bold
BoldContent -> TextPassage BoldContent                      | add text as child
BoldContent -> FormatItalic BoldItalicContent FormatItalic  | add child italic
BoldContent -> ɛ                                            |
ItalicFormatting -> FormatItalic ItalicContent FormatItalic | add child italic
ItalicContent -> TextPassage ItalicContent                  | add text as child
ItalicContent -> FormatBold BoldItalicContent FormatBold    | add child bold
ItalicContent -> ɛ                                          | add text as child
BoldItalicContent -> TextPassage                            |
------------------------------------------------------------+-----------------------------------

::Start
Hello World, ''Yeah''.
//Italic// is possible too.

*/

pub fn parse_tokens(tokens: Vec<Token>) -> ast::AST {
    let mut parser: Parser = Parser::new(tokens);
    parser.parsing();
    parser.ast
}

//==============================
// grammar

#[derive(Debug, Copy, Clone)]
pub enum NonTerminalType {
    S,
    S2,
    Passage,
    PassageContent,
    Formating,
    BoldFormatting,
    ItalicFormatting,
    BoldContent,
    ItalicContent,
    BoldItalicContent
}

//==============================
// parser

struct Parser {
    tree: ParseTree,
    ast: ast::AST,
    stack: Stack,
    ast_path: Vec<usize>,
    tokens: Vec<Token>,
    lookahead: usize
}

impl Parser {
    pub fn new(tokens: Vec<Token>) -> Parser {
        Parser {
            tree: ParseTree::new(),
            ast: ast::AST::new(),
            stack: Stack::new(),
            ast_path: Vec::new(),
            tokens: tokens,
            lookahead: 0
        }
    }

    /// the predictive stack ll(1) parsing routine
    pub fn parsing(&mut self) {
        self.stack.push_start();

        while let Some(top) = self.stack.pop() {
            if self.tree.is_terminal(top.to_vec()) {
                self.next_token();
            } else {
                self.apply_grammar(top.to_vec());
            }
        }

        self.tree.print();
    }

    /// apply the ll(1) grammar
    /// the match-statement simulates the parsing-table behavior
    ///
    /// it creates the parse tree (from the ll(1) grammar)
    /// and the ast from the sdd
    fn apply_grammar(&mut self, top_path: Vec<usize>) {
        if let Some(token) = self.tokens.get_mut(self.lookahead) {

            let to_add_path: Vec<usize> = top_path.to_vec();

            // the frst item in the tuple is the current state and
            // the snd is the current lookup-token
            let state_first: (NonTerminalType, &Token) = (self.tree.get_non_terminal(top_path).clone(), token);

            let mut new_nodes = Vec::new();
            //use self::*;
            match state_first {
                (S, &TokPassageName(_)) => {
                    new_nodes.push(PNode::new_non_terminal(Passage));
                    new_nodes.push(PNode::new_non_terminal(S2));
                },
                (S2, &TokPassageName(_)) => {
                    new_nodes.push(PNode::new_non_terminal(S));
                },
                (Passage, &TokPassageName(ref name)) => {
                    let new_token: Token = TokPassageName(name.clone());
                    new_nodes.push(PNode::new_terminal(new_token));
                    new_nodes.push(PNode::new_non_terminal(PassageContent));

                    // ast
                    self.ast_path.clear();
                    let ast_count_passages = self.ast.cound_childs(self.ast_path.to_vec());
                    let new_token2: Token = TokPassageName(name.clone());
                    self.ast.add_passage(new_token2);
                    self.ast_path.push(ast_count_passages);
                },
                (PassageContent, &TokText(ref text)) => {
                    let new_token: Token = TokText(text.clone());
                    new_nodes.push(PNode::new_terminal(new_token));
                    new_nodes.push(PNode::new_non_terminal(PassageContent));

                    // ast
                    let new_token2: Token = TokText(text.clone());
                    self.ast.add_child(&self.ast_path, new_token2);
                },
                (PassageContent, &TokFormatBold) | (PassageContent, &TokFormatItalic) => {
                    new_nodes.push(PNode::new_non_terminal(Formating));
                    new_nodes.push(PNode::new_non_terminal(PassageContent));
                },
                (Formating, &TokFormatBold) => {
                    new_nodes.push(PNode::new_non_terminal(BoldFormatting));
                },
                (Formating, &TokFormatItalic) => {
                    new_nodes.push(PNode::new_non_terminal(ItalicFormatting));
                },
                (BoldFormatting, &TokFormatBold) => {
                    new_nodes.push(PNode::new_terminal(TokFormatBold));
                    new_nodes.push(PNode::new_non_terminal(BoldContent));
                    new_nodes.push(PNode::new_terminal(TokFormatBold));

                    // ast
                    let ast_count_passages = self.ast.cound_childs(self.ast_path.to_vec());
                    let ast_token: Token = TokFormatBold;
                    self.ast.add_child(&self.ast_path, ast_token);
                    self.ast_path.push(ast_count_passages);
                },
                (ItalicFormatting, &TokFormatItalic) => {
                    new_nodes.push(PNode::new_terminal(TokFormatItalic));
                    new_nodes.push(PNode::new_non_terminal(ItalicContent));
                    new_nodes.push(PNode::new_terminal(TokFormatItalic));

                    // ast
                    let ast_count_passages = self.ast.cound_childs(self.ast_path.to_vec());
                    let ast_token: Token = TokFormatItalic;
                    self.ast.add_child(&self.ast_path, ast_token);
                    self.ast_path.push(ast_count_passages);
                },
                (BoldContent, &TokText(ref text)) => {
                    let new_token: Token = TokText(text.clone());
                    new_nodes.push(PNode::new_terminal(new_token));
                    new_nodes.push(PNode::new_non_terminal(BoldContent));

                    // ast
                    let ast_token: Token = TokText(text.clone());
                    self.ast.add_child(&self.ast_path, ast_token);
                },
                (ItalicContent, &TokText(ref text)) => {
                    let new_token: Token = TokText(text.clone());
                    new_nodes.push(PNode::new_terminal(new_token));
                    new_nodes.push(PNode::new_non_terminal(ItalicContent));

                    // ast
                    let ast_token: Token = TokText(text.clone());
                    self.ast.add_child(&self.ast_path, ast_token);
                },
                (BoldContent, &TokFormatItalic) => {
                    new_nodes.push(PNode::new_terminal(TokFormatItalic));
                    new_nodes.push(PNode::new_non_terminal(BoldItalicContent));
                    new_nodes.push(PNode::new_terminal(TokFormatItalic));
                },
                (ItalicContent, &TokFormatBold) => {
                    new_nodes.push(PNode::new_terminal(TokFormatBold));
                    new_nodes.push(PNode::new_non_terminal(BoldItalicContent));
                    new_nodes.push(PNode::new_terminal(TokFormatBold));
                },
                (BoldItalicContent, &TokText(ref text)) => {
                    let new_token: Token = TokText(text.clone());
                    new_nodes.push(PNode::new_terminal(new_token));
                },

                (BoldContent, &TokFormatBold) => {
                    // jump one ast-level higher
                    self.ast_path.pop();
                },
                (ItalicContent, &TokFormatItalic) => {
                    // jump one ast-level higher
                    self.ast_path.pop();
                },
                _ => {

                }
            }

            // adds the new nodes to the tree
            // and adds the path in the tree to the stack
            let length = new_nodes.len().clone();
            self.tree.add_nodes(new_nodes, &to_add_path);
            self.stack.push_path(length as u8, to_add_path);

        } else {
            // no token left
            // only ɛ-productions could be here
            // these productions will be poped of the stack
        }
    }

    /// sets the lookahead to the next token
    fn next_token(&mut self) {
        self.lookahead = self.lookahead + 1;
    }
}

//==============================
// stack of the parser
struct Stack {
    data: Vec<Vec<usize>>
}

impl Stack {
    pub fn new() -> Stack {
        Stack { data: Vec::new() }
    }

    /// pushs the address of the first startsymbol to the stack
    fn push_start(&mut self) {
        self.data.push(vec![]);
    }

    /// save the path of the nodes in the tree to the stack
    /// the right part of the production
    /// should be on the stack in reverse order
    fn push_path(&mut self, count_elements: u8, to_add_path: Vec<usize>) {
        for i in 0..count_elements {
            let mut path: Vec<usize> = to_add_path.to_vec();
            path.push((count_elements-i-1) as usize);
            self.data.push(path);
        }
    }

    fn pop(&mut self) -> Option<Vec<usize>> {
        self.data.pop()
    }
}

//==============================
//
#[test]
fn it_works() {

}

<|endoftext|>


<commit_before>use std::path::PathBuf;
use std::process::{Command, Stdio};

use rsh::State;

// TODO "Error handling mother trucker, do you speak it?"
pub fn exec(s: &State) -> i32 {
    let mut args = s.argv.iter();
    let mut exec_path: Option<PathBuf> = None;
    let exec_name = args.next().unwrap().as_str();

    'outer: for path in s.exec_paths().iter() {
        for entry in path.read_dir().unwrap() {
            if let Ok(e) = entry {
                if e.file_name() == *exec_name {
                    exec_path = Some(e.path().clone());
                    break 'outer;
                }
            }
        }
    }

    if exec_path.is_none() {
        println!("No such command: {}", exec_name);
        return 1000;
    }

    let command = Command::new(exec_path.unwrap().to_str().unwrap())
        .args(&args.collect::<Vec<&String>>())
        .current_dir(s.cwd.clone())
        .stdin(Stdio::inherit())
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .spawn();

    if command.is_err() {
        println!("Error running {}: {}", exec_name, command.err().unwrap());
        return 1000;
    }

    match command.unwrap().wait() {
        Ok(exit) => if let Some(i) = exit.code() { i } else { 1000 },
        Err(e) => {
            println!("Error starting {}: {}", exec_name, e);
            1000
        }
    }
}
<commit_msg>fixed an unwrap causing issues when searching path<commit_after>use std::path::PathBuf;
use std::process::{Command, Stdio};

use rsh::State;

// TODO "Error handling mother trucker, do you speak it?"
pub fn exec(s: &State) -> i32 {
    let mut args = s.argv.iter();
    let mut exec_path: Option<PathBuf> = None;
    let exec_name = args.next().unwrap().as_str();

    'outer: for path in s.exec_paths().iter() {
        let read_dir = path.read_dir();

        if read_dir.is_err() {
            continue;
        }

        for entry in read_dir.unwrap() {
            if let Ok(e) = entry {
                if e.file_name() == *exec_name {
                    exec_path = Some(e.path().clone());
                    break 'outer;
                }
            }
        }
    }

    if exec_path.is_none() {
        println!("No such command: {}", exec_name);
        return 1000;
    }

    let command = Command::new(exec_path.unwrap().to_str().unwrap())
        .args(&args.collect::<Vec<&String>>())
        .current_dir(s.cwd.clone())
        .stdin(Stdio::inherit())
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .spawn();

    if command.is_err() {
        println!("Error running {}: {}", exec_name, command.err().unwrap());
        return 1000;
    }

    match command.unwrap().wait() {
        Ok(exit) => if let Some(i) = exit.code() { i } else { 1000 },
        Err(e) => {
            println!("Error starting {}: {}", exec_name, e);
            1000
        }
    }
}
<|endoftext|>


<commit_before>//! `cargo upgrade`
#![warn(missing_docs, missing_debug_implementations, missing_copy_implementations, trivial_casts,
       trivial_numeric_casts, unsafe_code, unstable_features, unused_import_braces,
       unused_qualifications)]

extern crate cargo_metadata;
extern crate docopt;
#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate serde_derive;
extern crate toml;

use std::collections::HashMap;
use std::io::{self, Write};
use std::path::Path;
use std::process;

extern crate cargo_edit;
use cargo_edit::{get_latest_dependency, Dependency, Manifest};

mod errors {
    error_chain!{
        links {
            CargoEditLib(::cargo_edit::Error, ::cargo_edit::ErrorKind);
        }

        foreign_links {
            // cargo-metadata doesn't (yet) export `ErrorKind`)
            Metadata(::cargo_metadata::Error);
        }
    }
}
use errors::*;

static USAGE: &'static str = r"
Upgrade all dependencies in a manifest file to the latest version.

Usage:
    cargo upgrade [--all] [--dependency <dep>...] [--manifest-path <path>] [options]
    cargo upgrade (-h | --help)
    cargo upgrade (-V | --version)

Options:
    --all                       Upgrade all packages in the workspace.
    -d --dependency <dep>       Specific dependency to upgrade. If this option is used, only the
                                specified dependencies will be upgraded.
    --manifest-path <path>      Path to the manifest to upgrade.
    --allow-prerelease          Include prerelease versions when fetching from crates.io (e.g.
                                '0.6.0-alpha'). Defaults to false.
    -h --help                   Show this help page.
    -V --version                Show version.

Dev, build, and all target dependencies will also be upgraded. Only dependencies from crates.io are
supported. Git/path dependencies will be ignored.

All packages in the workspace will be upgraded if the `--all` flag is supplied. The `--all` flag may
be supplied in the presence of a virtual manifest.
";

/// Docopts input args.
#[derive(Debug, Deserialize)]
struct Args {
    /// `--dependency -d <dep>`
    flag_dependency: Vec<String>,
    /// `--manifest-path <path>`
    flag_manifest_path: Option<String>,
    /// `--version`
    flag_version: bool,
    /// `--all`
    flag_all: bool,
    /// `--allow-prerelease`
    flag_allow_prerelease: bool,
}

fn is_version_dependency(dep: &toml::Value) -> bool {
    if let Some(table) = dep.as_table() {
        !table.contains_key("git") && !table.contains_key("path")
    } else {
        true
    }
}

fn update_manifest(
    manifest_path: &Option<String>,
    only_update: &[String],
    allow_prerelease: bool,
) -> Result<()> {
    let manifest_path = manifest_path.as_ref().map(From::from);
    let mut manifest = Manifest::open(&manifest_path)?;

    for (table_path, table) in manifest.get_sections() {
        for (name, old_value) in &table {
            if (only_update.is_empty() || only_update.contains(name)) &&
                is_version_dependency(old_value)
            {
                let latest_version = get_latest_dependency(name, allow_prerelease)?;

                manifest.update_table_entry(&table_path, &latest_version)?;
            }
        }
    }

    let mut file = Manifest::find_file(&manifest_path)?;
    manifest.write_to_file(&mut file)?;

    Ok(())
}

fn update_manifest_from_cache(
    manifest_path: &Option<String>,
    only_update: &[String],
    new_deps: &HashMap<String, Dependency>,
) -> Result<()> {
    let manifest_path = manifest_path.as_ref().map(From::from);
    let mut manifest = Manifest::open(&manifest_path)?;

    for (table_path, table) in manifest.get_sections() {
        for (name, old_value) in &table {
            if (only_update.is_empty() || only_update.contains(name)) &&
                is_version_dependency(old_value)
            {
                let latest_version = &new_deps[name];

                manifest.update_table_entry(&table_path, latest_version)?;
            }
        }
    }

    let mut file = Manifest::find_file(&manifest_path)?;
    manifest
        .write_to_file(&mut file)
        .chain_err(|| "Failed to write new manifest contents")
}

/// Get a list of the paths of all the (non-virtual) manifests in the workspace.
fn get_workspace_manifests(manifest_path: &Option<String>) -> Result<Vec<String>> {
    Ok(
        cargo_metadata::metadata_deps(manifest_path.as_ref().map(|p| Path::new(p)), true)
            .chain_err(|| "Failed to get metadata")?
            .packages
            .iter()
            .map(|p| p.manifest_path.clone())
            .collect(),
    )
}

/// Look up all current direct crates.io dependencies in the workspace. Then get the latest version
/// for each.
fn get_all_new_deps(
    manifest_path: &Option<String>,
    allow_prerelease: bool,
) -> Result<HashMap<String, Dependency>> {
    let mut new_deps = HashMap::new();

    cargo_metadata::metadata_deps(manifest_path.as_ref().map(|p| Path::new(p)), true)
        .chain_err(|| "Failed to get metadata")?
        .packages
        .iter()
        .flat_map(|package| package.dependencies.to_owned())
        .map(|dependency| {
            if !new_deps.contains_key(&dependency.name) {
                new_deps.insert(
                    dependency.name.clone(),
                    get_latest_dependency(&dependency.name, allow_prerelease)?,
                );
            }
            Ok(())
        })
        .collect::<Result<Vec<()>>>()?;

    Ok(new_deps)
}

fn update_workspace_manifests(
    manifest_path: &Option<String>,
    only_update: &[String],
    allow_prerelease: bool,
) -> Result<()> {
    let new_deps = get_all_new_deps(manifest_path, allow_prerelease)?;

    get_workspace_manifests(manifest_path).and_then(|manifests| {
        for manifest in manifests {
            update_manifest_from_cache(&Some(manifest), only_update, &new_deps)?
        }

        Ok(())
    })
}

fn main() {
    let args = docopt::Docopt::new(USAGE)
        .and_then(|d| d.deserialize::<Args>())
        .unwrap_or_else(|err| err.exit());

    if args.flag_version {
        println!("cargo-upgrade version {}", env!("CARGO_PKG_VERSION"));
        process::exit(0);
    }

    let output = if args.flag_all {
        update_workspace_manifests(
            &args.flag_manifest_path,
            &args.flag_dependency,
            args.flag_allow_prerelease,
        )
    } else {
        update_manifest(
            &args.flag_manifest_path,
            &args.flag_dependency,
            args.flag_allow_prerelease,
        )
    };

    if let Err(err) = output {
        let mut stderr = io::stderr();

        writeln!(stderr, "Command failed due to unhandled error: {}\n", err).unwrap();

        for e in err.iter().skip(1) {
            writeln!(stderr, "Caused by: {}", e).unwrap();
        }

        if let Some(backtrace) = err.backtrace() {
            writeln!(stderr, "Backtrace: {:?}", backtrace).unwrap();
        }

        process::exit(1);
    }
}
<commit_msg>Handle specified dependencies properly<commit_after>//! `cargo upgrade`
#![warn(missing_docs, missing_debug_implementations, missing_copy_implementations, trivial_casts,
       trivial_numeric_casts, unsafe_code, unstable_features, unused_import_braces,
       unused_qualifications)]

extern crate cargo_metadata;
extern crate docopt;
#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate serde_derive;
extern crate toml;

use std::collections::HashMap;
use std::io::{self, Write};
use std::path::Path;
use std::process;

extern crate cargo_edit;
use cargo_edit::{get_latest_dependency, Dependency, Manifest};

mod errors {
    error_chain!{
        links {
            CargoEditLib(::cargo_edit::Error, ::cargo_edit::ErrorKind);
        }

        foreign_links {
            // cargo-metadata doesn't (yet) export `ErrorKind`)
            Metadata(::cargo_metadata::Error);
        }
    }
}
use errors::*;

static USAGE: &'static str = r"
Upgrade all dependencies in a manifest file to the latest version.

Usage:
    cargo upgrade [--all] [--dependency <dep>...] [--manifest-path <path>] [options]
    cargo upgrade (-h | --help)
    cargo upgrade (-V | --version)

Options:
    --all                       Upgrade all packages in the workspace.
    -d --dependency <dep>       Specific dependency to upgrade. If this option is used, only the
                                specified dependencies will be upgraded.
    --manifest-path <path>      Path to the manifest to upgrade.
    --allow-prerelease          Include prerelease versions when fetching from crates.io (e.g.
                                '0.6.0-alpha'). Defaults to false.
    -h --help                   Show this help page.
    -V --version                Show version.

Dev, build, and all target dependencies will also be upgraded. Only dependencies from crates.io are
supported. Git/path dependencies will be ignored.

All packages in the workspace will be upgraded if the `--all` flag is supplied. The `--all` flag may
be supplied in the presence of a virtual manifest.
";

/// Docopts input args.
#[derive(Debug, Deserialize)]
struct Args {
    /// `--dependency -d <dep>`
    flag_dependency: Vec<String>,
    /// `--manifest-path <path>`
    flag_manifest_path: Option<String>,
    /// `--version`
    flag_version: bool,
    /// `--all`
    flag_all: bool,
    /// `--allow-prerelease`
    flag_allow_prerelease: bool,
}

fn is_version_dependency(dep: &toml::Value) -> bool {
    if let Some(table) = dep.as_table() {
        !table.contains_key("git") && !table.contains_key("path")
    } else {
        true
    }
}

fn update_manifest(
    manifest_path: &Option<String>,
    only_update: &[String],
    allow_prerelease: bool,
) -> Result<()> {
    let manifest_path = manifest_path.as_ref().map(From::from);
    let mut manifest = Manifest::open(&manifest_path)?;

    for (table_path, table) in manifest.get_sections() {
        for (name, old_value) in &table {
            if (only_update.is_empty() || only_update.contains(name)) &&
                is_version_dependency(old_value)
            {
                let latest_version = get_latest_dependency(name, allow_prerelease)?;

                manifest.update_table_entry(&table_path, &latest_version)?;
            }
        }
    }

    let mut file = Manifest::find_file(&manifest_path)?;
    manifest.write_to_file(&mut file)?;

    Ok(())
}

fn update_manifest_from_cache(
    manifest_path: &Option<String>,
    only_update: &[String],
    new_deps: &HashMap<String, Dependency>,
) -> Result<()> {
    let manifest_path = manifest_path.as_ref().map(From::from);
    let mut manifest = Manifest::open(&manifest_path)?;

    for (table_path, table) in manifest.get_sections() {
        for (name, old_value) in &table {
            if (only_update.is_empty() || only_update.contains(name)) &&
                is_version_dependency(old_value)
            {
                let latest_version = &new_deps[name];

                manifest.update_table_entry(&table_path, latest_version)?;
            }
        }
    }

    let mut file = Manifest::find_file(&manifest_path)?;
    manifest
        .write_to_file(&mut file)
        .chain_err(|| "Failed to write new manifest contents")
}

/// Get a list of the paths of all the (non-virtual) manifests in the workspace.
fn get_workspace_manifests(manifest_path: &Option<String>) -> Result<Vec<String>> {
    Ok(
        cargo_metadata::metadata_deps(manifest_path.as_ref().map(|p| Path::new(p)), true)
            .chain_err(|| "Failed to get metadata")?
            .packages
            .iter()
            .map(|p| p.manifest_path.clone())
            .collect(),
    )
}

/// Look up all current direct crates.io dependencies in the workspace. Then get the latest version
/// for each.
fn get_all_new_deps(
    manifest_path: &Option<String>,
    allow_prerelease: bool,
) -> Result<HashMap<String, Dependency>> {
    let mut new_deps = HashMap::new();

    cargo_metadata::metadata_deps(manifest_path.as_ref().map(|p| Path::new(p)), true)
        .chain_err(|| "Failed to get metadata")?
        .packages
        .iter()
        .flat_map(|package| package.dependencies.to_owned())
        .map(|dependency| {
            if !new_deps.contains_key(&dependency.name) {
                new_deps.insert(
                    dependency.name.clone(),
                    get_latest_dependency(&dependency.name, allow_prerelease)?,
                );
            }
            Ok(())
        })
        .collect::<Result<Vec<()>>>()?;

    Ok(new_deps)
}

/// Get the latest versions of the specified crates.io dependencies.
fn get_specified_new_deps(
    depedencies: &[String],
    allow_prerelease: bool,
) -> Result<HashMap<String, Dependency>> {
    depedencies
        .into_iter()
        .map(|dep| {
            Ok((
                dep.to_owned(),
                get_latest_dependency(dep, allow_prerelease)?,
            ))
        })
        .collect()
}

fn update_workspace_manifests(
    manifest_path: &Option<String>,
    only_update: &[String],
    allow_prerelease: bool,
) -> Result<()> {
    let new_deps = if !only_update.is_empty() {
        get_specified_new_deps(only_update, allow_prerelease)?
    } else {
        get_all_new_deps(manifest_path, allow_prerelease)?
    };

    get_workspace_manifests(manifest_path).and_then(|manifests| {
        for manifest in manifests {
            update_manifest_from_cache(&Some(manifest), only_update, &new_deps)?
        }

        Ok(())
    })
}

fn main() {
    let args = docopt::Docopt::new(USAGE)
        .and_then(|d| d.deserialize::<Args>())
        .unwrap_or_else(|err| err.exit());

    if args.flag_version {
        println!("cargo-upgrade version {}", env!("CARGO_PKG_VERSION"));
        process::exit(0);
    }

    let output = if args.flag_all {
        update_workspace_manifests(
            &args.flag_manifest_path,
            &args.flag_dependency,
            args.flag_allow_prerelease,
        )
    } else {
        update_manifest(
            &args.flag_manifest_path,
            &args.flag_dependency,
            args.flag_allow_prerelease,
        )
    };

    if let Err(err) = output {
        let mut stderr = io::stderr();

        writeln!(stderr, "Command failed due to unhandled error: {}\n", err).unwrap();

        for e in err.iter().skip(1) {
            writeln!(stderr, "Caused by: {}", e).unwrap();
        }

        if let Some(backtrace) = err.backtrace() {
            writeln!(stderr, "Backtrace: {:?}", backtrace).unwrap();
        }

        process::exit(1);
    }
}
<|endoftext|>


<commit_before>use libc::{self, c_int};
use {Errno, Result};
use unistd::Pid;

use sys::signal::Signal;

mod ffi {
    use libc::{pid_t, c_int};

    extern {
        pub fn waitpid(pid: pid_t, status: *mut c_int, options: c_int) -> pid_t;
    }
}

#[cfg(not(any(target_os = "linux",
              target_os = "android")))]
libc_bitflags!(
    pub struct WaitPidFlag: c_int {
        WNOHANG;
        WUNTRACED;
    }
);

#[cfg(any(target_os = "linux",
          target_os = "android"))]
libc_bitflags!(
    pub struct WaitPidFlag: c_int {
        WNOHANG;
        WUNTRACED;
        WEXITED;
        WCONTINUED;
        WNOWAIT; // Don't reap, just poll status.
        __WNOTHREAD; // Don't wait on children of other threads in this group
        __WALL; // Wait on all children, regardless of type
        __WCLONE;
    }
);

#[cfg(any(target_os = "linux",
          target_os = "android"))]
const WSTOPPED: WaitPidFlag = WUNTRACED;

/// Possible return values from `wait()` or `waitpid()`.
///
/// Each status (other than `StillAlive`) describes a state transition
/// in a child process `Pid`, such as the process exiting or stopping,
/// plus additional data about the transition if any.
///
/// Note that there are two Linux-specific enum variants, `PtraceEvent`
/// and `PtraceSyscall`. Portable code should avoid exhaustively
/// matching on `WaitStatus`.
#[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum WaitStatus {
    /// The process exited normally (as with `exit()` or returning from
    /// `main`) with the given exit code. This case matches the C macro
    /// `WIFEXITED(status)`; the second field is `WEXITSTATUS(status)`.
    Exited(Pid, i8),
    /// The process was killed by the given signal. The third field
    /// indicates whether the signal generated a core dump. This case
    /// matches the C macro `WIFSIGNALED(status)`; the last two fields
    /// correspond to `WTERMSIG(status)` and `WCOREDUMP(status)`.
    Signaled(Pid, Signal, bool),
    /// The process is alive, but was stopped by the given signal. This
    /// is only reported if `WaitPidFlag::WUNTRACED` was passed. This
    /// case matches the C macro `WIFSTOPPED(status)`; the second field
    /// is `WSTOPSIG(status)`.
    Stopped(Pid, Signal),
    /// The traced process was stopped by a `PTRACE_EVENT_*` event. See
    /// [`nix::sys::ptrace`] and [`ptrace`(2)] for more information. All
    /// currently-defined events use `SIGTRAP` as the signal; the third
    /// field is the `PTRACE_EVENT_*` value of the event.
    ///
    /// [`nix::sys::ptrace`]: ../ptrace/index.html
    /// [`ptrace`(2)]: http://man7.org/linux/man-pages/man2/ptrace.2.html
    #[cfg(any(target_os = "linux", target_os = "android"))]
    PtraceEvent(Pid, Signal, c_int),
    /// The traced process was stopped by execution of a system call,
    /// and `PTRACE_O_TRACESYSGOOD` is in effect. See [`ptrace`(2)] for
    /// more information.
    ///
    /// [`ptrace`(2)]: http://man7.org/linux/man-pages/man2/ptrace.2.html
    #[cfg(any(target_os = "linux", target_os = "android"))]
    PtraceSyscall(Pid),
    /// The process was previously stopped but has resumed execution
    /// after receiving a `SIGCONT` signal. This is only reported if
    /// `WaitPidFlag::WCONTINUED` was passed. This case matches the C
    /// macro `WIFCONTINUED(status)`.
    Continued(Pid),
    /// There are currently no state changes to report in any awaited
    /// child process. This is only returned if `WaitPidFlag::WNOHANG`
    /// was used (otherwise `wait()` or `waitpid()` would block until
    /// there was something to report).
    StillAlive
}

impl WaitStatus {
    /// Extracts the PID from the WaitStatus unless it equals StillAlive.
    pub fn pid(&self) -> Option<Pid> {
        use self::WaitStatus::*;
        match *self {
            Exited(p, _) => Some(p),
            Signaled(p, _, _) => Some(p),
            Stopped(p, _) => Some(p),
            Continued(p) => Some(p),
            StillAlive => None,

            #[cfg(any(target_os = "linux", target_os = "android"))]
            PtraceEvent(p, _, _) => Some(p),
            #[cfg(any(target_os = "linux", target_os = "android"))]
            PtraceSyscall(p) => Some(p),
        }
    }
}

#[cfg(any(target_os = "linux",
          target_os = "android"))]
mod status {
    use sys::signal::Signal;
    use libc::c_int;
    use libc::SIGTRAP;

    pub fn exited(status: i32) -> bool {
        (status & 0x7F) == 0
    }

    pub fn exit_status(status: i32) -> i8 {
        ((status & 0xFF00) >> 8) as i8
    }

    pub fn signaled(status: i32) -> bool {
        ((((status & 0x7f) + 1) as i8) >> 1) > 0
    }

    pub fn term_signal(status: i32) -> Signal {
        Signal::from_c_int(status & 0x7f).unwrap()
    }

    pub fn dumped_core(status: i32) -> bool {
        (status & 0x80) != 0
    }

    pub fn stopped(status: i32) -> bool {
        (status & 0xff) == 0x7f
    }

    pub fn stop_signal(status: i32) -> Signal {
        // Keep only 7 bits of the signal: the high bit
        // is used to indicate syscall stops, below.
        Signal::from_c_int((status & 0x7F00) >> 8).unwrap()
    }

    pub fn syscall_stop(status: i32) -> bool {
        // From ptrace(2), setting PTRACE_O_TRACESYSGOOD has the effect
        // of delivering SIGTRAP | 0x80 as the signal number for syscall
        // stops. This allows easily distinguishing syscall stops from
        // genuine SIGTRAP signals.
        ((status & 0xFF00) >> 8) == SIGTRAP | 0x80
    }

    pub fn stop_additional(status: i32) -> c_int {
        (status >> 16) as c_int
    }

    pub fn continued(status: i32) -> bool {
        status == 0xFFFF
    }
}

#[cfg(any(target_os = "macos",
          target_os = "ios"))]
mod status {
    use sys::signal::{Signal,SIGCONT};

    const WCOREFLAG: i32 = 0x80;
    const WSTOPPED: i32 = 0x7f;

    fn wstatus(status: i32) -> i32 {
        status & 0x7F
    }

    pub fn exit_status(status: i32) -> i8 {
        ((status >> 8) & 0xFF) as i8
    }

    pub fn stop_signal(status: i32) -> Signal {
        Signal::from_c_int(status >> 8).unwrap()
    }

    pub fn continued(status: i32) -> bool {
        wstatus(status) == WSTOPPED && stop_signal(status) == SIGCONT
    }

    pub fn stopped(status: i32) -> bool {
        wstatus(status) == WSTOPPED && stop_signal(status) != SIGCONT
    }

    pub fn exited(status: i32) -> bool {
        wstatus(status) == 0
    }

    pub fn signaled(status: i32) -> bool {
        wstatus(status) != WSTOPPED && wstatus(status) != 0
    }

    pub fn term_signal(status: i32) -> Signal {
        Signal::from_c_int(wstatus(status)).unwrap()
    }

    pub fn dumped_core(status: i32) -> bool {
        (status & WCOREFLAG) != 0
    }
}

#[cfg(any(target_os = "freebsd",
          target_os = "openbsd",
          target_os = "dragonfly",
          target_os = "netbsd"))]
mod status {
    use sys::signal::Signal;

    const WCOREFLAG: i32 = 0x80;
    const WSTOPPED: i32 = 0x7f;

    fn wstatus(status: i32) -> i32 {
        status & 0x7F
    }

    pub fn stopped(status: i32) -> bool {
        wstatus(status) == WSTOPPED
    }

    pub fn stop_signal(status: i32) -> Signal {
        Signal::from_c_int(status >> 8).unwrap()
    }

    pub fn signaled(status: i32) -> bool {
        wstatus(status) != WSTOPPED && wstatus(status) != 0 && status != 0x13
    }

    pub fn term_signal(status: i32) -> Signal {
        Signal::from_c_int(wstatus(status)).unwrap()
    }

    pub fn exited(status: i32) -> bool {
        wstatus(status) == 0
    }

    pub fn exit_status(status: i32) -> i8 {
        (status >> 8) as i8
    }

    pub fn continued(status: i32) -> bool {
        status == 0x13
    }

    pub fn dumped_core(status: i32) -> bool {
        (status & WCOREFLAG) != 0
    }
}

fn decode(pid : Pid, status: i32) -> WaitStatus {
    if status::exited(status) {
        WaitStatus::Exited(pid, status::exit_status(status))
    } else if status::signaled(status) {
        WaitStatus::Signaled(pid, status::term_signal(status), status::dumped_core(status))
    } else if status::stopped(status) {
        cfg_if! {
            if #[cfg(any(target_os = "linux", target_os = "android"))] {
                fn decode_stopped(pid: Pid, status: i32) -> WaitStatus {
                    let status_additional = status::stop_additional(status);
                    if status::syscall_stop(status) {
                        WaitStatus::PtraceSyscall(pid)
                    } else if status_additional == 0 {
                        WaitStatus::Stopped(pid, status::stop_signal(status))
                    } else {
                        WaitStatus::PtraceEvent(pid, status::stop_signal(status), status::stop_additional(status))
                    }
                }
            } else {
                fn decode_stopped(pid: Pid, status: i32) -> WaitStatus {
                    WaitStatus::Stopped(pid, status::stop_signal(status))
                }
            }
        }
        decode_stopped(pid, status)
    } else {
        assert!(status::continued(status));
        WaitStatus::Continued(pid)
    }
}

pub fn waitpid<P: Into<Option<Pid>>>(pid: P, options: Option<WaitPidFlag>) -> Result<WaitStatus> {
    use self::WaitStatus::*;

    let mut status: i32 = 0;

    let option_bits = match options {
        Some(bits) => bits.bits(),
        None => 0
    };

    let res = unsafe { ffi::waitpid(pid.into().unwrap_or(Pid::from_raw(-1)).into(), &mut status as *mut c_int, option_bits) };

    Ok(match try!(Errno::result(res)) {
        0 => StillAlive,
        res => decode(Pid::from_raw(res), status),
    })
}

pub fn wait() -> Result<WaitStatus> {
    waitpid(None, None)
}
<commit_msg>Use libc definitions for wait module<commit_after>use libc::{self, c_int};
use {Errno, Result};
use unistd::Pid;

use sys::signal::Signal;

libc_bitflags!(
    pub struct WaitPidFlag: c_int {
        WNOHANG;
        WUNTRACED;
        WEXITED;
        WCONTINUED;
        WSTOPPED;
        /// Don't reap, just poll status.
        WNOWAIT;
        /// Don't wait on children of other threads in this group
        #[cfg(any(target_os = "android", target_os = "linux"))]
        __WNOTHREAD;
        /// Wait on all children, regardless of type
        #[cfg(any(target_os = "android", target_os = "linux"))]
        __WALL;
        #[cfg(any(target_os = "android", target_os = "linux"))]
        __WCLONE;
    }
);

/// Possible return values from `wait()` or `waitpid()`.
///
/// Each status (other than `StillAlive`) describes a state transition
/// in a child process `Pid`, such as the process exiting or stopping,
/// plus additional data about the transition if any.
///
/// Note that there are two Linux-specific enum variants, `PtraceEvent`
/// and `PtraceSyscall`. Portable code should avoid exhaustively
/// matching on `WaitStatus`.
#[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum WaitStatus {
    /// The process exited normally (as with `exit()` or returning from
    /// `main`) with the given exit code. This case matches the C macro
    /// `WIFEXITED(status)`; the second field is `WEXITSTATUS(status)`.
    Exited(Pid, i32),
    /// The process was killed by the given signal. The third field
    /// indicates whether the signal generated a core dump. This case
    /// matches the C macro `WIFSIGNALED(status)`; the last two fields
    /// correspond to `WTERMSIG(status)` and `WCOREDUMP(status)`.
    Signaled(Pid, Signal, bool),
    /// The process is alive, but was stopped by the given signal. This
    /// is only reported if `WaitPidFlag::WUNTRACED` was passed. This
    /// case matches the C macro `WIFSTOPPED(status)`; the second field
    /// is `WSTOPSIG(status)`.
    Stopped(Pid, Signal),
    /// The traced process was stopped by a `PTRACE_EVENT_*` event. See
    /// [`nix::sys::ptrace`] and [`ptrace`(2)] for more information. All
    /// currently-defined events use `SIGTRAP` as the signal; the third
    /// field is the `PTRACE_EVENT_*` value of the event.
    ///
    /// [`nix::sys::ptrace`]: ../ptrace/index.html
    /// [`ptrace`(2)]: http://man7.org/linux/man-pages/man2/ptrace.2.html
    #[cfg(any(target_os = "linux", target_os = "android"))]
    PtraceEvent(Pid, Signal, c_int),
    /// The traced process was stopped by execution of a system call,
    /// and `PTRACE_O_TRACESYSGOOD` is in effect. See [`ptrace`(2)] for
    /// more information.
    ///
    /// [`ptrace`(2)]: http://man7.org/linux/man-pages/man2/ptrace.2.html
    #[cfg(any(target_os = "linux", target_os = "android"))]
    PtraceSyscall(Pid),
    /// The process was previously stopped but has resumed execution
    /// after receiving a `SIGCONT` signal. This is only reported if
    /// `WaitPidFlag::WCONTINUED` was passed. This case matches the C
    /// macro `WIFCONTINUED(status)`.
    Continued(Pid),
    /// There are currently no state changes to report in any awaited
    /// child process. This is only returned if `WaitPidFlag::WNOHANG`
    /// was used (otherwise `wait()` or `waitpid()` would block until
    /// there was something to report).
    StillAlive
}

impl WaitStatus {
    /// Extracts the PID from the WaitStatus unless it equals StillAlive.
    pub fn pid(&self) -> Option<Pid> {
        use self::WaitStatus::*;
        match *self {
            Exited(p, _) => Some(p),
            Signaled(p, _, _) => Some(p),
            Stopped(p, _) => Some(p),
            Continued(p) => Some(p),
            StillAlive => None,

            #[cfg(any(target_os = "linux", target_os = "android"))]
            PtraceEvent(p, _, _) => Some(p),
            #[cfg(any(target_os = "linux", target_os = "android"))]
            PtraceSyscall(p) => Some(p),
        }
    }
}

fn exited(status: i32) -> bool {
    unsafe { libc::WIFEXITED(status) }
}

fn exit_status(status: i32) -> i32 {
    unsafe { libc::WEXITSTATUS(status) }
}

fn signaled(status: i32) -> bool {
    unsafe { libc::WIFSIGNALED(status) }
}

fn term_signal(status: i32) -> Signal {
    Signal::from_c_int(unsafe { libc::WTERMSIG(status) }).unwrap()
}

fn dumped_core(status: i32) -> bool {
    unsafe { libc::WCOREDUMP(status) }
}

fn stopped(status: i32) -> bool {
    unsafe { libc::WIFSTOPPED(status) }
}

fn stop_signal(status: i32) -> Signal {
    Signal::from_c_int(unsafe { libc::WSTOPSIG(status) }).unwrap()
}

fn syscall_stop(status: i32) -> bool {
    // From ptrace(2), setting PTRACE_O_TRACESYSGOOD has the effect
    // of delivering SIGTRAP | 0x80 as the signal number for syscall
    // stops. This allows easily distinguishing syscall stops from
    // genuine SIGTRAP signals.
    unsafe { libc::WSTOPSIG(status) == libc::SIGTRAP | 0x80 }
}

fn stop_additional(status: i32) -> c_int {
    (status >> 16) as c_int
}

fn continued(status: i32) -> bool {
    unsafe { libc::WIFCONTINUED(status) }
}

fn decode(pid : Pid, status: i32) -> WaitStatus {
    if exited(status) {
        WaitStatus::Exited(pid, exit_status(status))
    } else if signaled(status) {
        WaitStatus::Signaled(pid, term_signal(status), dumped_core(status))
    } else if stopped(status) {
        cfg_if! {
            if #[cfg(any(target_os = "linux", target_os = "android"))] {
                fn decode_stopped(pid: Pid, status: i32) -> WaitStatus {
                    let status_additional = stop_additional(status);
                    if syscall_stop(status) {
                        WaitStatus::PtraceSyscall(pid)
                    } else if status_additional == 0 {
                        WaitStatus::Stopped(pid, stop_signal(status))
                    } else {
                        WaitStatus::PtraceEvent(pid, stop_signal(status), stop_additional(status))
                    }
                }
            } else {
                fn decode_stopped(pid: Pid, status: i32) -> WaitStatus {
                    WaitStatus::Stopped(pid, stop_signal(status))
                }
            }
        }
        decode_stopped(pid, status)
    } else {
        assert!(continued(status));
        WaitStatus::Continued(pid)
    }
}

pub fn waitpid<P: Into<Option<Pid>>>(pid: P, options: Option<WaitPidFlag>) -> Result<WaitStatus> {
    use self::WaitStatus::*;

    let mut status: i32 = 0;

    let option_bits = match options {
        Some(bits) => bits.bits(),
        None => 0
    };

    let res = unsafe { libc::waitpid(pid.into().unwrap_or(Pid::from_raw(-1)).into(), &mut status as *mut c_int, option_bits) };

    Ok(match try!(Errno::result(res)) {
        0 => StillAlive,
        res => decode(Pid::from_raw(res), status),
    })
}

pub fn wait() -> Result<WaitStatus> {
    waitpid(None, None)
}
<|endoftext|>


<commit_before>use commands::Command;

/// Specify an optional argument to a ReQL command
///
/// # Example
///
/// Pass the `right_bound` optional argument to [between](trait.Between.html).
///
/// ```
/// # use reql::commands::*;
/// # use reql::commands::run::Dummy;
/// # struct Heroes;
/// # let r = Command::new();
/// r.table("marvel").between(10, 20).opt_arg("right_bound", "closed").run::<Heroes>();
/// ```
///
/// To pass more than one optional argument, chain `opt_arg` once for each argument.
///
/// # Example
///
/// ```
/// # use reql::commands::*;
/// # use reql::commands::run::Dummy;
/// # struct Heroes;
/// # let r = Command::new();
/// r.table("marvel").between(10, 20)
///     .opt_arg("right_bound", "closed")
///     .opt_arg("index", "power")
///     .run::<Heroes>();
/// ```
///
/// The key is optional because some commands (eg. `error`) have optional arguments that
/// that can only be specified via `opt_arg`. In such a case just pass in `None` as the key.
pub trait OptArg {
    fn opt_arg<K, V>(&self, option: K, value: V) -> Command
        where K: Into<Option<&str>>, V: ::ToArg;
}

impl OptArg for Command {
    fn opt_arg<K, V>(&self, option: K, value: V) -> Command
        where K: Into<Option<&str>>, V: ::ToArg
    {
        let mut cmd = self.clone();
        {
            let term = cmd.mut_term();
            match option.into() {
                Some(option) => {
                    let temp_pair = Command::create_term_pair(option, value);
                    term.mut_optargs().push(temp_pair);
                }
                None => {
                    term.mut_args().push(value.to_arg());
                }
            }
        }
        cmd
    }
}
<commit_msg>Update opt_arg examples<commit_after>use commands::Command;

/// Specify an optional argument to a ReQL command
///
/// # Example
///
/// Pass the `right_bound` optional argument to [between](trait.Between.html).
///
/// ```
/// # use reql::commands::*;
/// # use reql::commands::run::Dummy;
/// # struct Heroes;
/// # let r = Command::new();
/// r.table("marvel").between(args!(10, 20, {right_bound: "closed"})).run::<Heroes>();
/// ```
///
/// To pass more than one optional argument, chain `opt_arg` once for each argument.
///
/// # Example
///
/// ```
/// # use reql::commands::*;
/// # use reql::commands::run::Dummy;
/// # struct Heroes;
/// # let r = Command::new();
/// r.table("marvel").between(args!(10, 20, {
///     right_bound: "closed",
///     index: "power",
/// }))
/// .run::<Heroes>();
/// ```
///
/// The key is optional because some commands (eg. `error`) have optional arguments that
/// that can only be specified via `opt_arg`. In such a case just pass in `None` as the key.
pub trait OptArg {
    fn opt_arg<'a, K, V>(&self, option: K, value: V) -> Command
        where K: Into<Option<&'a str>>, V: ::ToArg;
}

impl OptArg for Command {
    fn opt_arg<'a, K, V>(&self, key: K, value: V) -> Command
        where K: Into<Option<&'a str>>, V: ::ToArg
    {
        let mut cmd = self.clone();
        {
            let term = cmd.mut_term();
            match key.into() {
                Some(option) => {
                    let temp_pair = Command::create_term_pair(option, value);
                    term.mut_optargs().push(temp_pair);
                }
                None => {
                    term.mut_args().push(value.to_arg());
                }
            }
        }
        cmd
    }
}
<|endoftext|>