<commit_before>extern crate regex;
extern crate reqwest;
extern crate select;

use irc::client::prelude::*;
use irc::error::Error as IrcError;

use self::regex::Regex;

use std::str;
use std::io::{self, Read};
use self::reqwest::Client;
use self::reqwest::header::Connection;

use self::select::document::Document;
use self::select::predicate::Name;

use plugin::*;

lazy_static! {
    static ref RE: Regex = Regex::new(r"http(s)?://(\S+)").unwrap();
}

#[derive(PluginName, Debug)]
pub struct Url {
    max_kib: usize,
}

impl Url {
    /// If a file is larger than `max_kib` KiB the download is stopped
    pub fn new(max_kib: usize) -> Url {
        Url {max_kib: max_kib}
    }

    fn grep_url(&self, msg: &str) -> Option<String> {
        match RE.captures(msg) {
            Some(captures) => {
                debug!("Url captures: {:?}", captures);

                Some(captures.get(0).unwrap().as_str().to_string())
            }
            None => None,
        }
    }

    fn url(&self, server: &IrcServer, message: &str, target: &str) -> Result<(), IrcError> {
        let url = match self.grep_url(message) {
            Some(url) => url,
            None => {
                return Ok(());
            }
        };

        let response = Client::new()
            .get(&url)
            .header(Connection::close())
            .send();

        match response {
            Ok(mut response) => {
                let mut body = String::new();

                // 500 kilobyte buffer
                let mut buf = [0; 500 * 1000];
                let mut written = 0;
                // Read until we reach EOF or max_kib KiB
                loop {
                    let len = match response.read(&mut buf) {
                        Ok(0) => break,
                        Ok(len) => len,
                        Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
                        Err(e) => {
                            debug!("Download from \"{}\" failed: {}", url, e);
                            return Ok(())
                        }
                    };

                    let slice = match str::from_utf8(&buf[..len]) {
                        Ok(slice) => slice,
                        Err(e) => {
                            debug!("Failed to read bytes from \"{}\" as UTF8: {}", url, e);
                            return Ok(());
                        }
                    };

                    body.push_str(slice);
                    written += len;

                    // Check if the file is too large to download
                    if written > self.max_kib * 1024 {
                        debug!("Stopping download - File from \"{}\" is larger than {} KiB", url, self.max_kib);
                        return Ok(());
                    }
                }

                // let mut body = String::new();
                // if let Err(e) = response.read_to_string(&mut body) {
                //     error!("Failed to read string from \"{}\": {}", url, e);
                //     return Ok(());
                // }
                // let doc = Document::from(body.as_ref());

                let doc = Document::from(body.as_ref());
                if let Some(title) = doc.find(Name("title")).next() {
                    let text = title.children().next().unwrap();
                    debug!("Title: {:?}", text);

                    server.send_privmsg(target, text.as_text().unwrap())

                } else {
                    Ok(())
                }
            }
            Err(e) => {
                debug!("Bad response from \"{}\": ({})", url, e);
                Ok(())
            }
        }
    }
}

impl Plugin for Url {
    fn is_allowed(&self, _: &IrcServer, message: &Message) -> bool {
        match message.command {
            Command::PRIVMSG(_, ref msg) => RE.is_match(msg),
            _ => false,
        }
    }

    fn execute(&self, server: &IrcServer, message: &Message) -> Result<(), IrcError> {
        match message.command {
            Command::PRIVMSG(_, ref content) => {
                self.url(server, content, message.response_target().unwrap())
            }
            _ => Ok(()),
        }
    }

    fn command(&self, server: &IrcServer, command: PluginCommand) -> Result<(), IrcError> {
        server.send_notice(&command.source,
                           "This Plugin does not implement any commands.")
    }
}

#[cfg(test)]
mod tests {}
<commit_msg>Only match urls which start with http<commit_after>extern crate regex;
extern crate reqwest;
extern crate select;

use irc::client::prelude::*;
use irc::error::Error as IrcError;

use self::regex::Regex;

use std::str;
use std::io::{self, Read};
use self::reqwest::Client;
use self::reqwest::header::Connection;

use self::select::document::Document;
use self::select::predicate::Name;

use plugin::*;

lazy_static! {
    static ref RE: Regex = Regex::new(r"(^|\s)(https?://\S+)").unwrap();
}

#[derive(PluginName, Debug)]
pub struct Url {
    max_kib: usize,
}

impl Url {
    /// If a file is larger than `max_kib` KiB the download is stopped
    pub fn new(max_kib: usize) -> Url {
        Url {max_kib: max_kib}
    }

    fn grep_url(&self, msg: &str) -> Option<String> {
        match RE.captures(msg) {
            Some(captures) => {
                debug!("Url captures: {:?}", captures);

                Some(captures.get(2).unwrap().as_str().to_string())
            }
            None => None,
        }
    }

    fn url(&self, server: &IrcServer, message: &str, target: &str) -> Result<(), IrcError> {
        let url = match self.grep_url(message) {
            Some(url) => url,
            None => {
                return Ok(());
            }
        };

        let response = Client::new()
            .get(&url)
            .header(Connection::close())
            .send();

        match response {
            Ok(mut response) => {
                let mut body = String::new();

                // 500 kilobyte buffer
                let mut buf = [0; 500 * 1000];
                let mut written = 0;
                // Read until we reach EOF or max_kib KiB
                loop {
                    let len = match response.read(&mut buf) {
                        Ok(0) => break,
                        Ok(len) => len,
                        Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
                        Err(e) => {
                            debug!("Download from \"{}\" failed: {}", url, e);
                            return Ok(())
                        }
                    };

                    let slice = match str::from_utf8(&buf[..len]) {
                        Ok(slice) => slice,
                        Err(e) => {
                            debug!("Failed to read bytes from \"{}\" as UTF8: {}", url, e);
                            return Ok(());
                        }
                    };

                    body.push_str(slice);
                    written += len;

                    // Check if the file is too large to download
                    if written > self.max_kib * 1024 {
                        debug!("Stopping download - File from \"{}\" is larger than {} KiB", url, self.max_kib);
                        return Ok(());
                    }
                }

                // let mut body = String::new();
                // if let Err(e) = response.read_to_string(&mut body) {
                //     error!("Failed to read string from \"{}\": {}", url, e);
                //     return Ok(());
                // }
                // let doc = Document::from(body.as_ref());

                let doc = Document::from(body.as_ref());
                if let Some(title) = doc.find(Name("title")).next() {
                    let text = title.children().next().unwrap();
                    debug!("Title: {:?}", text);

                    server.send_privmsg(target, text.as_text().unwrap())

                } else {
                    Ok(())
                }
            }
            Err(e) => {
                debug!("Bad response from \"{}\": ({})", url, e);
                Ok(())
            }
        }
    }
}

impl Plugin for Url {
    fn is_allowed(&self, _: &IrcServer, message: &Message) -> bool {
        match message.command {
            Command::PRIVMSG(_, ref msg) => RE.is_match(msg),
            _ => false,
        }
    }

    fn execute(&self, server: &IrcServer, message: &Message) -> Result<(), IrcError> {
        match message.command {
            Command::PRIVMSG(_, ref content) => {
                self.url(server, content, message.response_target().unwrap())
            }
            _ => Ok(()),
        }
    }

    fn command(&self, server: &IrcServer, command: PluginCommand) -> Result<(), IrcError> {
        server.send_notice(&command.source,
                           "This Plugin does not implement any commands.")
    }
}

#[cfg(test)]
mod tests {}
<|endoftext|>


<commit_before>use crate::{IdentFragment, ToTokens, TokenStreamExt};
use std::fmt;
use std::ops::BitOr;

pub use proc_macro2::*;

pub struct HasIterator; // True
pub struct ThereIsNoIteratorInRepetition; // False

impl BitOr<ThereIsNoIteratorInRepetition> for ThereIsNoIteratorInRepetition {
    type Output = ThereIsNoIteratorInRepetition;
    fn bitor(self, _rhs: ThereIsNoIteratorInRepetition) -> ThereIsNoIteratorInRepetition {
        ThereIsNoIteratorInRepetition
    }
}

impl BitOr<ThereIsNoIteratorInRepetition> for HasIterator {
    type Output = HasIterator;
    fn bitor(self, _rhs: ThereIsNoIteratorInRepetition) -> HasIterator {
        HasIterator
    }
}

impl BitOr<HasIterator> for ThereIsNoIteratorInRepetition {
    type Output = HasIterator;
    fn bitor(self, _rhs: HasIterator) -> HasIterator {
        HasIterator
    }
}

impl BitOr<HasIterator> for HasIterator {
    type Output = HasIterator;
    fn bitor(self, _rhs: HasIterator) -> HasIterator {
        HasIterator
    }
}

/// Extension traits used by the implementation of `quote!`. These are defined
/// in separate traits, rather than as a single trait due to ambiguity issues.
///
/// These traits expose a `quote_into_iter` method which should allow calling
/// whichever impl happens to be applicable. Calling that method repeatedly on
/// the returned value should be idempotent.
pub mod ext {
    use super::{HasIterator as HasIter, ThereIsNoIteratorInRepetition as DoesNotHaveIter};
    use crate::ToTokens;
    use std::slice;

    /// Extension trait providing the `quote_into_iter` method on iterators.
    pub trait RepIteratorExt: Iterator + Sized {
        fn quote_into_iter(self) -> (Self, HasIter) {
            (self, HasIter)
        }
    }

    impl<T: Iterator> RepIteratorExt for T {}

    /// Extension trait providing the `quote_into_iter` method for
    /// non-iterable types. These types interpolate the same value in each
    /// iteration of the repetition.
    pub trait RepToTokensExt {
        /// Pretend to be an iterator for the purposes of `quote_into_iter`.
        /// This allows repeated calls to `quote_into_iter` to continue
        /// correctly returning DoesNotHaveIter.
        fn next(&self) -> Option<&Self> {
            Some(self)
        }

        fn quote_into_iter<'a>(&'a self) -> (&'a Self, DoesNotHaveIter) {
            (self, DoesNotHaveIter)
        }
    }

    impl<T: ToTokens + ?Sized> RepToTokensExt for T {}

    /// Extension trait providing the `quote_into_iter` method for types
    /// convertable into slices.
    ///
    /// NOTE: This is implemented manually, rather than by using a blanket impl
    /// over `AsRef<[T]>` to reduce the chance of ambiguity conflicts with other
    /// `quote_into_iter` methods from this module.
    pub trait RepSliceExt {
        type Item;

        fn as_slice(&self) -> &[Self::Item];

        fn quote_into_iter<'a>(&'a self) -> (slice::Iter<'a, Self::Item>, HasIter) {
            (self.as_slice().iter(), HasIter)
        }
    }

    impl<'a, T: RepSliceExt + ?Sized> RepSliceExt for &'a T {
        type Item = T::Item;

        fn as_slice(&self) -> &[Self::Item] {
            <T as RepSliceExt>::as_slice(*self)
        }
    }

    impl<'a, T: RepSliceExt + ?Sized> RepSliceExt for &'a mut T {
        type Item = T::Item;

        fn as_slice(&self) -> &[Self::Item] {
            <T as RepSliceExt>::as_slice(*self)
        }
    }

    impl<T> RepSliceExt for [T] {
        type Item = T;

        fn as_slice(&self) -> &[Self::Item] {
            self
        }
    }

    impl<T> RepSliceExt for Vec<T> {
        type Item = T;

        fn as_slice(&self) -> &[Self::Item] {
            &self[..]
        }
    }

    macro_rules! array_rep_slice {
        ($($l:tt)*) => {
            $(
                impl<T> RepSliceExt for [T; $l] {
                    type Item = T;

                    fn as_slice(&self) -> &[Self::Item] {
                        &self[..]
                    }
                }
            )*
        }
    }

    array_rep_slice!(
        0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
        17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
    );
}

// Helper type used within interpolations to allow for repeated binding names.
// Implements the relevant traits, and exports a dummy `next()` method.
#[derive(Copy, Clone)]
pub struct RepInterp<T>(pub T);

impl<T> RepInterp<T> {
    // This method is intended to look like `Iterator::next`, and is called when
    // a name is bound multiple times, as the previous binding will shadow the
    // original `Iterator` object. This allows us to avoid advancing the
    // iterator multiple times per iteration.
    pub fn next(self) -> Option<T> {
        Some(self.0)
    }
}

impl<T: ext::RepSliceExt> ext::RepSliceExt for RepInterp<T> {
    type Item = T::Item;

    fn as_slice(&self) -> &[Self::Item] {
        self.0.as_slice()
    }
}

impl<T: Iterator> Iterator for RepInterp<T> {
    type Item = T::Item;

    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}

impl<T: ToTokens> ToTokens for RepInterp<T> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        self.0.to_tokens(tokens);
    }
}

fn is_ident_start(c: u8) -> bool {
    (b'a' <= c && c <= b'z') || (b'A' <= c && c <= b'Z') || c == b'_'
}

fn is_ident_continue(c: u8) -> bool {
    (b'a' <= c && c <= b'z') || (b'A' <= c && c <= b'Z') || c == b'_' || (b'0' <= c && c <= b'9')
}

fn is_ident(token: &str) -> bool {
    let mut iter = token.bytes();
    let first_ok = iter.next().map(is_ident_start).unwrap_or(false);

    first_ok && iter.all(is_ident_continue)
}

pub fn parse(tokens: &mut TokenStream, span: Span, s: &str) {
    if is_ident(s) {
        // Fast path, since idents are the most common token.
        tokens.append(Ident::new(s, span));
    } else {
        let s: TokenStream = s.parse().expect("invalid token stream");
        tokens.extend(s.into_iter().map(|mut t| {
            t.set_span(span);
            t
        }));
    }
}

macro_rules! push_punct {
    ($name:ident $char1:tt) => {
        pub fn $name(tokens: &mut TokenStream, span: Span) {
            let mut punct = Punct::new($char1, Spacing::Alone);
            punct.set_span(span);
            tokens.append(punct);
        }
    };
    ($name:ident $char1:tt $char2:tt) => {
        pub fn $name(tokens: &mut TokenStream, span: Span) {
            let mut punct = Punct::new($char1, Spacing::Joint);
            punct.set_span(span);
            tokens.append(punct);
            let mut punct = Punct::new($char2, Spacing::Alone);
            punct.set_span(span);
            tokens.append(punct);
        }
    };
    ($name:ident $char1:tt $char2:tt $char3:tt) => {
        pub fn $name(tokens: &mut TokenStream, span: Span) {
            let mut punct = Punct::new($char1, Spacing::Joint);
            punct.set_span(span);
            tokens.append(punct);
            let mut punct = Punct::new($char2, Spacing::Joint);
            punct.set_span(span);
            tokens.append(punct);
            let mut punct = Punct::new($char3, Spacing::Alone);
            punct.set_span(span);
            tokens.append(punct);
        }
    };
}

push_punct!(push_add '+');
push_punct!(push_add_eq '+' '=');
push_punct!(push_and '&');
push_punct!(push_and_and '&' '&');
push_punct!(push_and_eq '&' '=');
push_punct!(push_at '@');
push_punct!(push_bang '!');
push_punct!(push_caret '^');
push_punct!(push_caret_eq '^' '=');
push_punct!(push_colon ':');
push_punct!(push_colon2 ':' ':');
push_punct!(push_comma ',');
push_punct!(push_div '/');
push_punct!(push_div_eq '/' '=');
push_punct!(push_dot '.');
push_punct!(push_dot2 '.' '.');
push_punct!(push_dot3 '.' '.' '.');
push_punct!(push_dot_dot_eq '.' '.' '=');
push_punct!(push_eq '=');
push_punct!(push_eq_eq '=' '=');
push_punct!(push_ge '>' '=');
push_punct!(push_gt '>');
push_punct!(push_le '<' '=');
push_punct!(push_lt '<');
push_punct!(push_mul_eq '*' '=');
push_punct!(push_ne '!' '=');
push_punct!(push_or '|');
push_punct!(push_or_eq '|' '=');
push_punct!(push_or_or '|' '|');
push_punct!(push_pound '#');
push_punct!(push_question '?');
push_punct!(push_rarrow '-' '>');
push_punct!(push_larrow '<' '-');
push_punct!(push_rem '%');
push_punct!(push_rem_eq '%' '=');
push_punct!(push_fat_arrow '=' '>');
push_punct!(push_semi ';');
push_punct!(push_shl '<' '<');
push_punct!(push_shl_eq '<' '<' '=');
push_punct!(push_shr '>' '>');
push_punct!(push_shr_eq '>' '>' '=');
push_punct!(push_star '*');
push_punct!(push_sub '-');
push_punct!(push_sub_eq '-' '=');

// Helper method for constructing identifiers from the `format_ident!` macro,
// handling `r#` prefixes.
//
// Directly parsing the input string may produce a valid identifier,
// although the input string was invalid, due to ignored characters such as
// whitespace and comments. Instead, we always create a non-raw identifier
// to validate that the string is OK, and only parse again if needed.
//
// The `is_ident` method defined above is insufficient for validation, as it
// will reject non-ASCII identifiers.
pub fn mk_ident(id: &str, span: Option<Span>) -> Ident {
    let span = span.unwrap_or_else(Span::call_site);

    let is_raw = id.starts_with("r#");
    let unraw = Ident::new(if is_raw { &id[2..] } else { id }, span);
    if !is_raw {
        return unraw;
    }

    // At this point, the identifier is raw, and the unraw-ed version of it was
    // successfully converted into an identifier. Try to produce a valid raw
    // identifier by running the `TokenStream` parser, and unwrapping the first
    // token as an `Ident`.
    //
    // FIXME: When `Ident::new_raw` becomes stable, this method should be
    // updated to call it when available.
    match id.parse::<TokenStream>() {
        Ok(ts) => {
            let mut iter = ts.into_iter();
            match (iter.next(), iter.next()) {
                (Some(TokenTree::Ident(mut id)), None) => {
                    id.set_span(span);
                    id
                }
                _ => unreachable!("valid raw ident fails to parse"),
            }
        }
        Err(_) => unreachable!("valid raw ident fails to parse"),
    }
}

// Adapts from `IdentFragment` to `fmt::Display` for use by the `format_ident!`
// macro, and exposes span information from these fragments.
//
// This struct also has forwarding implementations of the formatting traits
// `Octal`, `LowerHex`, `UpperHex`, and `Binary` to allow for their use within
// `format_ident!`.
#[derive(Copy, Clone)]
pub struct IdentFragmentAdapter<T: IdentFragment>(pub T);

impl<T: IdentFragment> IdentFragmentAdapter<T> {
    pub fn span(&self) -> Option<Span> {
        self.0.span()
    }
}

impl<T: IdentFragment> fmt::Display for IdentFragmentAdapter<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        IdentFragment::fmt(&self.0, f)
    }
}

impl<T: IdentFragment + fmt::Octal> fmt::Octal for IdentFragmentAdapter<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Octal::fmt(&self.0, f)
    }
}

impl<T: IdentFragment + fmt::LowerHex> fmt::LowerHex for IdentFragmentAdapter<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::LowerHex::fmt(&self.0, f)
    }
}

impl<T: IdentFragment + fmt::UpperHex> fmt::UpperHex for IdentFragmentAdapter<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::UpperHex::fmt(&self.0, f)
    }
}

impl<T: IdentFragment + fmt::Binary> fmt::Binary for IdentFragmentAdapter<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Binary::fmt(&self.0, f)
    }
}
<commit_msg>Simplify unneeded lifetimes in runtime<commit_after>use crate::{IdentFragment, ToTokens, TokenStreamExt};
use std::fmt;
use std::ops::BitOr;

pub use proc_macro2::*;

pub struct HasIterator; // True
pub struct ThereIsNoIteratorInRepetition; // False

impl BitOr<ThereIsNoIteratorInRepetition> for ThereIsNoIteratorInRepetition {
    type Output = ThereIsNoIteratorInRepetition;
    fn bitor(self, _rhs: ThereIsNoIteratorInRepetition) -> ThereIsNoIteratorInRepetition {
        ThereIsNoIteratorInRepetition
    }
}

impl BitOr<ThereIsNoIteratorInRepetition> for HasIterator {
    type Output = HasIterator;
    fn bitor(self, _rhs: ThereIsNoIteratorInRepetition) -> HasIterator {
        HasIterator
    }
}

impl BitOr<HasIterator> for ThereIsNoIteratorInRepetition {
    type Output = HasIterator;
    fn bitor(self, _rhs: HasIterator) -> HasIterator {
        HasIterator
    }
}

impl BitOr<HasIterator> for HasIterator {
    type Output = HasIterator;
    fn bitor(self, _rhs: HasIterator) -> HasIterator {
        HasIterator
    }
}

/// Extension traits used by the implementation of `quote!`. These are defined
/// in separate traits, rather than as a single trait due to ambiguity issues.
///
/// These traits expose a `quote_into_iter` method which should allow calling
/// whichever impl happens to be applicable. Calling that method repeatedly on
/// the returned value should be idempotent.
pub mod ext {
    use super::{HasIterator as HasIter, ThereIsNoIteratorInRepetition as DoesNotHaveIter};
    use crate::ToTokens;
    use std::slice;

    /// Extension trait providing the `quote_into_iter` method on iterators.
    pub trait RepIteratorExt: Iterator + Sized {
        fn quote_into_iter(self) -> (Self, HasIter) {
            (self, HasIter)
        }
    }

    impl<T: Iterator> RepIteratorExt for T {}

    /// Extension trait providing the `quote_into_iter` method for
    /// non-iterable types. These types interpolate the same value in each
    /// iteration of the repetition.
    pub trait RepToTokensExt {
        /// Pretend to be an iterator for the purposes of `quote_into_iter`.
        /// This allows repeated calls to `quote_into_iter` to continue
        /// correctly returning DoesNotHaveIter.
        fn next(&self) -> Option<&Self> {
            Some(self)
        }

        fn quote_into_iter(&self) -> (&Self, DoesNotHaveIter) {
            (self, DoesNotHaveIter)
        }
    }

    impl<T: ToTokens + ?Sized> RepToTokensExt for T {}

    /// Extension trait providing the `quote_into_iter` method for types
    /// convertable into slices.
    ///
    /// NOTE: This is implemented manually, rather than by using a blanket impl
    /// over `AsRef<[T]>` to reduce the chance of ambiguity conflicts with other
    /// `quote_into_iter` methods from this module.
    pub trait RepSliceExt {
        type Item;

        fn as_slice(&self) -> &[Self::Item];

        fn quote_into_iter(&self) -> (slice::Iter<Self::Item>, HasIter) {
            (self.as_slice().iter(), HasIter)
        }
    }

    impl<'a, T: RepSliceExt + ?Sized> RepSliceExt for &'a T {
        type Item = T::Item;

        fn as_slice(&self) -> &[Self::Item] {
            <T as RepSliceExt>::as_slice(*self)
        }
    }

    impl<'a, T: RepSliceExt + ?Sized> RepSliceExt for &'a mut T {
        type Item = T::Item;

        fn as_slice(&self) -> &[Self::Item] {
            <T as RepSliceExt>::as_slice(*self)
        }
    }

    impl<T> RepSliceExt for [T] {
        type Item = T;

        fn as_slice(&self) -> &[Self::Item] {
            self
        }
    }

    impl<T> RepSliceExt for Vec<T> {
        type Item = T;

        fn as_slice(&self) -> &[Self::Item] {
            &self[..]
        }
    }

    macro_rules! array_rep_slice {
        ($($l:tt)*) => {
            $(
                impl<T> RepSliceExt for [T; $l] {
                    type Item = T;

                    fn as_slice(&self) -> &[Self::Item] {
                        &self[..]
                    }
                }
            )*
        }
    }

    array_rep_slice!(
        0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
        17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
    );
}

// Helper type used within interpolations to allow for repeated binding names.
// Implements the relevant traits, and exports a dummy `next()` method.
#[derive(Copy, Clone)]
pub struct RepInterp<T>(pub T);

impl<T> RepInterp<T> {
    // This method is intended to look like `Iterator::next`, and is called when
    // a name is bound multiple times, as the previous binding will shadow the
    // original `Iterator` object. This allows us to avoid advancing the
    // iterator multiple times per iteration.
    pub fn next(self) -> Option<T> {
        Some(self.0)
    }
}

impl<T: ext::RepSliceExt> ext::RepSliceExt for RepInterp<T> {
    type Item = T::Item;

    fn as_slice(&self) -> &[Self::Item] {
        self.0.as_slice()
    }
}

impl<T: Iterator> Iterator for RepInterp<T> {
    type Item = T::Item;

    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}

impl<T: ToTokens> ToTokens for RepInterp<T> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        self.0.to_tokens(tokens);
    }
}

fn is_ident_start(c: u8) -> bool {
    (b'a' <= c && c <= b'z') || (b'A' <= c && c <= b'Z') || c == b'_'
}

fn is_ident_continue(c: u8) -> bool {
    (b'a' <= c && c <= b'z') || (b'A' <= c && c <= b'Z') || c == b'_' || (b'0' <= c && c <= b'9')
}

fn is_ident(token: &str) -> bool {
    let mut iter = token.bytes();
    let first_ok = iter.next().map(is_ident_start).unwrap_or(false);

    first_ok && iter.all(is_ident_continue)
}

pub fn parse(tokens: &mut TokenStream, span: Span, s: &str) {
    if is_ident(s) {
        // Fast path, since idents are the most common token.
        tokens.append(Ident::new(s, span));
    } else {
        let s: TokenStream = s.parse().expect("invalid token stream");
        tokens.extend(s.into_iter().map(|mut t| {
            t.set_span(span);
            t
        }));
    }
}

macro_rules! push_punct {
    ($name:ident $char1:tt) => {
        pub fn $name(tokens: &mut TokenStream, span: Span) {
            let mut punct = Punct::new($char1, Spacing::Alone);
            punct.set_span(span);
            tokens.append(punct);
        }
    };
    ($name:ident $char1:tt $char2:tt) => {
        pub fn $name(tokens: &mut TokenStream, span: Span) {
            let mut punct = Punct::new($char1, Spacing::Joint);
            punct.set_span(span);
            tokens.append(punct);
            let mut punct = Punct::new($char2, Spacing::Alone);
            punct.set_span(span);
            tokens.append(punct);
        }
    };
    ($name:ident $char1:tt $char2:tt $char3:tt) => {
        pub fn $name(tokens: &mut TokenStream, span: Span) {
            let mut punct = Punct::new($char1, Spacing::Joint);
            punct.set_span(span);
            tokens.append(punct);
            let mut punct = Punct::new($char2, Spacing::Joint);
            punct.set_span(span);
            tokens.append(punct);
            let mut punct = Punct::new($char3, Spacing::Alone);
            punct.set_span(span);
            tokens.append(punct);
        }
    };
}

push_punct!(push_add '+');
push_punct!(push_add_eq '+' '=');
push_punct!(push_and '&');
push_punct!(push_and_and '&' '&');
push_punct!(push_and_eq '&' '=');
push_punct!(push_at '@');
push_punct!(push_bang '!');
push_punct!(push_caret '^');
push_punct!(push_caret_eq '^' '=');
push_punct!(push_colon ':');
push_punct!(push_colon2 ':' ':');
push_punct!(push_comma ',');
push_punct!(push_div '/');
push_punct!(push_div_eq '/' '=');
push_punct!(push_dot '.');
push_punct!(push_dot2 '.' '.');
push_punct!(push_dot3 '.' '.' '.');
push_punct!(push_dot_dot_eq '.' '.' '=');
push_punct!(push_eq '=');
push_punct!(push_eq_eq '=' '=');
push_punct!(push_ge '>' '=');
push_punct!(push_gt '>');
push_punct!(push_le '<' '=');
push_punct!(push_lt '<');
push_punct!(push_mul_eq '*' '=');
push_punct!(push_ne '!' '=');
push_punct!(push_or '|');
push_punct!(push_or_eq '|' '=');
push_punct!(push_or_or '|' '|');
push_punct!(push_pound '#');
push_punct!(push_question '?');
push_punct!(push_rarrow '-' '>');
push_punct!(push_larrow '<' '-');
push_punct!(push_rem '%');
push_punct!(push_rem_eq '%' '=');
push_punct!(push_fat_arrow '=' '>');
push_punct!(push_semi ';');
push_punct!(push_shl '<' '<');
push_punct!(push_shl_eq '<' '<' '=');
push_punct!(push_shr '>' '>');
push_punct!(push_shr_eq '>' '>' '=');
push_punct!(push_star '*');
push_punct!(push_sub '-');
push_punct!(push_sub_eq '-' '=');

// Helper method for constructing identifiers from the `format_ident!` macro,
// handling `r#` prefixes.
//
// Directly parsing the input string may produce a valid identifier,
// although the input string was invalid, due to ignored characters such as
// whitespace and comments. Instead, we always create a non-raw identifier
// to validate that the string is OK, and only parse again if needed.
//
// The `is_ident` method defined above is insufficient for validation, as it
// will reject non-ASCII identifiers.
pub fn mk_ident(id: &str, span: Option<Span>) -> Ident {
    let span = span.unwrap_or_else(Span::call_site);

    let is_raw = id.starts_with("r#");
    let unraw = Ident::new(if is_raw { &id[2..] } else { id }, span);
    if !is_raw {
        return unraw;
    }

    // At this point, the identifier is raw, and the unraw-ed version of it was
    // successfully converted into an identifier. Try to produce a valid raw
    // identifier by running the `TokenStream` parser, and unwrapping the first
    // token as an `Ident`.
    //
    // FIXME: When `Ident::new_raw` becomes stable, this method should be
    // updated to call it when available.
    match id.parse::<TokenStream>() {
        Ok(ts) => {
            let mut iter = ts.into_iter();
            match (iter.next(), iter.next()) {
                (Some(TokenTree::Ident(mut id)), None) => {
                    id.set_span(span);
                    id
                }
                _ => unreachable!("valid raw ident fails to parse"),
            }
        }
        Err(_) => unreachable!("valid raw ident fails to parse"),
    }
}

// Adapts from `IdentFragment` to `fmt::Display` for use by the `format_ident!`
// macro, and exposes span information from these fragments.
//
// This struct also has forwarding implementations of the formatting traits
// `Octal`, `LowerHex`, `UpperHex`, and `Binary` to allow for their use within
// `format_ident!`.
#[derive(Copy, Clone)]
pub struct IdentFragmentAdapter<T: IdentFragment>(pub T);

impl<T: IdentFragment> IdentFragmentAdapter<T> {
    pub fn span(&self) -> Option<Span> {
        self.0.span()
    }
}

impl<T: IdentFragment> fmt::Display for IdentFragmentAdapter<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        IdentFragment::fmt(&self.0, f)
    }
}

impl<T: IdentFragment + fmt::Octal> fmt::Octal for IdentFragmentAdapter<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Octal::fmt(&self.0, f)
    }
}

impl<T: IdentFragment + fmt::LowerHex> fmt::LowerHex for IdentFragmentAdapter<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::LowerHex::fmt(&self.0, f)
    }
}

impl<T: IdentFragment + fmt::UpperHex> fmt::UpperHex for IdentFragmentAdapter<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::UpperHex::fmt(&self.0, f)
    }
}

impl<T: IdentFragment + fmt::Binary> fmt::Binary for IdentFragmentAdapter<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Binary::fmt(&self.0, f)
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::ops;
use std::ops::{Range, RangeFrom, RangeTo, RangeFull};

use super::util;

// This is useful til the RangeArgument is made stable
trait FromRange {
    #[inline(always)]
    fn from_range(&self, seg: &Segment) -> (usize, usize);
}

impl FromRange for RangeFull {
    #[inline(always)]
    fn from_range(&self, seg: &Segment) -> (usize, usize) {
        return (0, seg.len());
    }
}

impl FromRange for Range<usize> {
    #[inline(always)]
    fn from_range(&self, _: &Segment) -> (usize, usize) {
        return (self.start, self.end);
    }
}

impl FromRange for RangeFrom<usize> {
    #[inline(always)]
    fn from_range(&self, seg: &Segment) -> (usize, usize) {
        return (self.start, seg.len());
    }
}

impl FromRange for RangeTo<usize> {
    #[inline(always)]
    fn from_range(&self, _: &Segment) -> (usize, usize) {
        return (0, self.end);
    }
}

pub struct Segment {
    vecs: Vec<Vec<u8>>,
    length: usize,
}

#[derive(Copy, Clone)]
struct Index {
    outer: usize,
    inner: usize,
}

pub struct Items<'a> {
    seg: &'a Segment,
    index: Index,
    num_elem: Option<usize>,
}

pub struct MutItems<'a> {
    seg: &'a mut Segment,
    index: Index,
    num_elem: Option<usize>,
}

pub struct Slices<'a> {
    seg: &'a Segment,
    outer: usize,
}

static MIN_BLOCK_SIZE: usize = 1024 * 1024;
static MAX_BLOCK_SIZE: usize = 4 * 1024 * 1024;

impl Segment {
    pub fn _internal_debug(&self) -> Vec<usize> {
        self.vecs.iter().map(|v| v.len()).collect::<Vec<usize>>()
    }
    pub fn new() -> Segment {
        Segment {
            vecs: Vec::new(),
            length: 0,
        }
    }
    pub fn from_vec(values: Vec<u8>) -> Segment {
        let len = values.len();
        Segment {
            vecs: vec!(values),
            length: len,
        }
    }

    pub fn from_slice(values: &[u8]) -> Segment {
        Segment {
            vecs: vec!(values.into()),
            length: values.len(),
        }
    }

    pub fn len(&self) -> usize {
        self.length
    }

    fn calc_len(&mut self) {
        self.length = 0;
        for len in self.vecs.iter().map(|v| v.len()) {
            self.length += len
        }
    }

    fn pos_to_index(&self, pos: usize, for_insert: bool) -> Index {
        if pos == 0 {
            return Index { outer: 0, inner: 0 };
        }

        let mut cur_pos = pos;
        for (i, vec) in self.vecs.iter().enumerate() {
            if cur_pos < vec.len() || (for_insert && cur_pos == vec.len()) {
                return Index {
                    outer: i,
                    inner: cur_pos,
                }
            }
            cur_pos -= vec.len();
        }

        panic!("Position {} is out of bounds", pos);
    }

    pub fn iter_range<'a, R: FromRange>(&'a self, range: R) -> Items<'a> {
        let (from, to) = range.from_range(self);
        if to < from {
            panic!("to ({}) is smaller than from ({})!", to, from);
        }

        let idx = self.pos_to_index(from, false);
        Items {
            seg: self,
            index: idx,
            num_elem: Some(to - from),
        }
    }

    pub fn mut_iter_range<'a, R: FromRange>(&'a mut self, range: R) -> MutItems<'a> {
        let (from, to) = range.from_range(self);
        if to < from {
            panic!("to ({}) is smaller than from ({})!", to, from);
        }

        let idx = self.pos_to_index(from, false);
        MutItems {
            seg: self,
            index: idx,
            num_elem: Some(to - from),
        }
    }

    pub fn iter_slices<'a>(&'a self) -> Slices<'a> {
        Slices {
            seg: self,
            outer: 0,
        }
    }

    fn prepare_insert(&mut self, index: Index) -> Index {
        // TODO: Get self.vecs.get(index.outer) into a local variable without ruining lifetimes?
        if index.outer >= self.vecs.len() {
            self.vecs.push(Vec::new());
        }

        if self.vecs[index.outer].len() < MAX_BLOCK_SIZE {
            return index;
        }

        let page_start_idx = (index.inner / MIN_BLOCK_SIZE) * MIN_BLOCK_SIZE;
        if page_start_idx == 0 {
            if self.vecs[index.outer].len() > MAX_BLOCK_SIZE {
                let insert_vec: Vec < _ >= self.vecs[index.outer][MIN_BLOCK_SIZE..].into();
                self.vecs.insert(index.outer + 1, insert_vec);
                self.vecs[index.outer].truncate(MIN_BLOCK_SIZE);
            }

            return index;
        } else {
            let insert_vec: Vec<_> = self.vecs[index.outer][page_start_idx..].into();
            self.vecs.insert(index.outer + 1, insert_vec);
            self.vecs[index.outer].truncate(page_start_idx);
            return self.prepare_insert(Index {
                outer: index.outer + 1,
                inner: index.inner - page_start_idx
            })
        }
    }

    pub fn insert(&mut self, offset: usize, values: &[u8]) {
        let mut index = self.pos_to_index(offset, true);
        index = self.prepare_insert(index);

        // This is needed for the mut borrow vec
        {
            let vec = &mut self.vecs[index.outer];
            // TODO: There has to be a better way for this range
            for val in values.into_iter().rev() {
                vec.insert(index.inner, *val);
            }
        }

        self.calc_len();
    }

    // TODO: Convert to drain when that settles
    pub fn move_out_slice(&mut self, start_offset: usize, end_offset: usize) -> Vec<u8> {
        assert!(start_offset <= end_offset);
        let mut res = Vec::new();
        let mut index = self.pos_to_index(start_offset, false);
        let num_elem = end_offset - start_offset;

        for _ in 0..num_elem {
            let c = self.vecs[index.outer].remove(index.inner);
            res.push(c);

            if index.inner >= self.vecs[index.outer].len() {
                if self.vecs[index.outer].len() == 0 {
                    self.vecs.remove(index.outer);
                } else {
                    index.inner = 0;
                    index.outer += 1;
                }
            }
        }

        self.calc_len();

        res
    }

    pub fn find_slice(&self, needle: &[u8]) -> Option<usize> {
        self.find_slice_from(0, needle)
    }

    pub fn find_slice_from(&self, from: usize, needle: &[u8]) -> Option<usize> {
        for i in from..self.len() {
            if util::iter_equals(self.iter_range(i..i+needle.len()), needle.iter()) {
                return Some(i);
            }
        }
        None
    }
}

impl ops::Index<usize> for Segment {
    type Output = u8;
    fn index<'a>(&'a self, _index: usize) -> &'a u8 {
        let idx = self.pos_to_index(_index, false);
        &self.vecs[idx.outer][idx.inner]
    }
}

impl ops::IndexMut<usize> for Segment {
    fn index_mut<'a>(&'a mut self, _index: usize) -> &'a mut u8 {
        let idx = self.pos_to_index(_index, false);
        &mut self.vecs[idx.outer][idx.inner]
    }
}

impl fmt::Debug for Segment {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.vecs.fmt(f)
    }
}

impl<'a> Iterator for Items<'a> {
    type Item = &'a u8;
    fn next(&mut self) -> Option<&'a u8> {
        if self.index.outer >= self.seg.vecs.len() {
            return None;
        }
        if let Some(ref mut num_elem) = self.num_elem {
            if *num_elem <= 0 {
                return None;
            }
            *num_elem -= 1;
        }

        let elem = {
            let vv = &self.seg.vecs[self.index.outer];
            &vv[self.index.inner]
        };

        self.index.inner += 1;
        if self.index.inner >= self.seg.vecs[self.index.outer].len() {
            self.index.inner = 0;
            self.index.outer += 1;
        }

        Some(elem)
    }
}

impl<'a> Iterator for MutItems<'a> {
    type Item = &'a mut u8;
    fn next(&mut self) -> Option<&'a mut u8> {
        if self.index.outer >= self.seg.vecs.len() {
            return None;
        }
        if let Some(ref mut num_elem) = self.num_elem {
            if *num_elem <= 0 {
                return None;
            }
            *num_elem -= 1;
        }

        let elem_raw: *mut u8 = {
            let vv = &mut self.seg.vecs[self.index.outer];
            &mut vv[self.index.inner]
        };

        self.index.inner += 1;
        if self.index.inner >= self.seg.vecs[self.index.outer].len() {
            self.index.inner = 0;
            self.index.outer += 1;
        }

        Some(unsafe { &mut *elem_raw })
    }
}

impl<'a> Iterator for Slices<'a> {
    type Item = &'a [u8];
    fn next(&mut self) -> Option<&'a [u8]> {
        if self.outer >= self.seg.vecs.len() {
            None
        } else {
            let i = self.outer;
            self.outer += 1;
            Some(&self.seg.vecs[i])
        }
    }
}

#[test]
fn test_segment() {
    let mut s = Segment::from_slice(&[1, 2, 3, 4]);
    s.insert_slice(0, &[7, 7, 7, 7, 7]);
}
<commit_msg>Add proper test helper function to Segment<commit_after>use std::fmt;
use std::ops;
use std::ops::{Range, RangeFrom, RangeTo, RangeFull};

use super::util;

// This is useful til the RangeArgument is made stable
trait FromRange {
    #[inline(always)]
    fn from_range(&self, seg: &Segment) -> (usize, usize);
}

impl FromRange for RangeFull {
    #[inline(always)]
    fn from_range(&self, seg: &Segment) -> (usize, usize) {
        return (0, seg.len());
    }
}

impl FromRange for Range<usize> {
    #[inline(always)]
    fn from_range(&self, _: &Segment) -> (usize, usize) {
        return (self.start, self.end);
    }
}

impl FromRange for RangeFrom<usize> {
    #[inline(always)]
    fn from_range(&self, seg: &Segment) -> (usize, usize) {
        return (self.start, seg.len());
    }
}

impl FromRange for RangeTo<usize> {
    #[inline(always)]
    fn from_range(&self, _: &Segment) -> (usize, usize) {
        return (0, self.end);
    }
}

pub struct Segment {
    vecs: Vec<Vec<u8>>,
    length: usize,
}

#[derive(Copy, Clone)]
struct Index {
    outer: usize,
    inner: usize,
}

pub struct Items<'a> {
    seg: &'a Segment,
    index: Index,
    num_elem: Option<usize>,
}

pub struct MutItems<'a> {
    seg: &'a mut Segment,
    index: Index,
    num_elem: Option<usize>,
}

pub struct Slices<'a> {
    seg: &'a Segment,
    outer: usize,
}

static MIN_BLOCK_SIZE: usize = 1024 * 1024;
static MAX_BLOCK_SIZE: usize = 4 * 1024 * 1024;

impl Segment {
    pub fn new() -> Segment {
        Segment {
            vecs: Vec::new(),
            length: 0,
        }
    }
    pub fn from_vec(values: Vec<u8>) -> Segment {
        let len = values.len();
        Segment {
            vecs: vec!(values),
            length: len,
        }
    }

    pub fn from_slice(values: &[u8]) -> Segment {
        Segment {
            vecs: vec!(values.into()),
            length: values.len(),
        }
    }

    pub fn len(&self) -> usize {
        self.length
    }

    fn calc_len(&mut self) {
        self.length = 0;
        for len in self.vecs.iter().map(|v| v.len()) {
            self.length += len
        }
    }

    fn pos_to_index(&self, pos: usize, for_insert: bool) -> Index {
        if pos == 0 {
            return Index { outer: 0, inner: 0 };
        }

        let mut cur_pos = pos;
        for (i, vec) in self.vecs.iter().enumerate() {
            if cur_pos < vec.len() || (for_insert && cur_pos == vec.len()) {
                return Index {
                    outer: i,
                    inner: cur_pos,
                }
            }
            cur_pos -= vec.len();
        }

        panic!("Position {} is out of bounds", pos);
    }

    pub fn iter_range<'a, R: FromRange>(&'a self, range: R) -> Items<'a> {
        let (from, to) = range.from_range(self);
        if to < from {
            panic!("to ({}) is smaller than from ({})!", to, from);
        }

        let idx = self.pos_to_index(from, false);
        Items {
            seg: self,
            index: idx,
            num_elem: Some(to - from),
        }
    }

    pub fn mut_iter_range<'a, R: FromRange>(&'a mut self, range: R) -> MutItems<'a> {
        let (from, to) = range.from_range(self);
        if to < from {
            panic!("to ({}) is smaller than from ({})!", to, from);
        }

        let idx = self.pos_to_index(from, false);
        MutItems {
            seg: self,
            index: idx,
            num_elem: Some(to - from),
        }
    }

    pub fn iter_slices<'a>(&'a self) -> Slices<'a> {
        Slices {
            seg: self,
            outer: 0,
        }
    }

    fn prepare_insert(&mut self, index: Index) -> Index {
        // TODO: Get self.vecs.get(index.outer) into a local variable without ruining lifetimes?
        if index.outer >= self.vecs.len() {
            self.vecs.push(Vec::new());
        }

        if self.vecs[index.outer].len() < MAX_BLOCK_SIZE {
            return index;
        }

        let page_start_idx = (index.inner / MIN_BLOCK_SIZE) * MIN_BLOCK_SIZE;
        if page_start_idx == 0 {
            if self.vecs[index.outer].len() > MAX_BLOCK_SIZE {
                let insert_vec: Vec < _ >= self.vecs[index.outer][MIN_BLOCK_SIZE..].into();
                self.vecs.insert(index.outer + 1, insert_vec);
                self.vecs[index.outer].truncate(MIN_BLOCK_SIZE);
            }

            return index;
        } else {
            let insert_vec: Vec<_> = self.vecs[index.outer][page_start_idx..].into();
            self.vecs.insert(index.outer + 1, insert_vec);
            self.vecs[index.outer].truncate(page_start_idx);
            return self.prepare_insert(Index {
                outer: index.outer + 1,
                inner: index.inner - page_start_idx
            })
        }
    }

    pub fn insert(&mut self, offset: usize, values: &[u8]) {
        let mut index = self.pos_to_index(offset, true);
        index = self.prepare_insert(index);

        // This is needed for the mut borrow vec
        {
            let vec = &mut self.vecs[index.outer];
            // TODO: There has to be a better way for this range
            for val in values.into_iter().rev() {
                vec.insert(index.inner, *val);
            }
        }

        self.calc_len();
    }

    // TODO: Convert to drain when that settles
    pub fn move_out_slice(&mut self, start_offset: usize, end_offset: usize) -> Vec<u8> {
        assert!(start_offset <= end_offset);
        let mut res = Vec::new();
        let mut index = self.pos_to_index(start_offset, false);
        let num_elem = end_offset - start_offset;

        for _ in 0..num_elem {
            let c = self.vecs[index.outer].remove(index.inner);
            res.push(c);

            if index.inner >= self.vecs[index.outer].len() {
                if self.vecs[index.outer].len() == 0 {
                    self.vecs.remove(index.outer);
                } else {
                    index.inner = 0;
                    index.outer += 1;
                }
            }
        }

        self.calc_len();

        res
    }

    pub fn find_slice(&self, needle: &[u8]) -> Option<usize> {
        self.find_slice_from(0, needle)
    }

    pub fn find_slice_from(&self, from: usize, needle: &[u8]) -> Option<usize> {
        for i in from..self.len() {
            if util::iter_equals(self.iter_range(i..i+needle.len()), needle.iter()) {
                return Some(i);
            }
        }
        None
    }

    #[cfg(test)]
    fn get_lengths(&self) -> Vec<usize> {
        self.vecs.iter().map(|v| v.len()).collect::<Vec<usize>>()
    }
}

impl ops::Index<usize> for Segment {
    type Output = u8;
    fn index<'a>(&'a self, _index: usize) -> &'a u8 {
        let idx = self.pos_to_index(_index, false);
        &self.vecs[idx.outer][idx.inner]
    }
}

impl ops::IndexMut<usize> for Segment {
    fn index_mut<'a>(&'a mut self, _index: usize) -> &'a mut u8 {
        let idx = self.pos_to_index(_index, false);
        &mut self.vecs[idx.outer][idx.inner]
    }
}

impl fmt::Debug for Segment {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.vecs.fmt(f)
    }
}

impl<'a> Iterator for Items<'a> {
    type Item = &'a u8;
    fn next(&mut self) -> Option<&'a u8> {
        if self.index.outer >= self.seg.vecs.len() {
            return None;
        }
        if let Some(ref mut num_elem) = self.num_elem {
            if *num_elem <= 0 {
                return None;
            }
            *num_elem -= 1;
        }

        let elem = {
            let vv = &self.seg.vecs[self.index.outer];
            &vv[self.index.inner]
        };

        self.index.inner += 1;
        if self.index.inner >= self.seg.vecs[self.index.outer].len() {
            self.index.inner = 0;
            self.index.outer += 1;
        }

        Some(elem)
    }
}

impl<'a> Iterator for MutItems<'a> {
    type Item = &'a mut u8;
    fn next(&mut self) -> Option<&'a mut u8> {
        if self.index.outer >= self.seg.vecs.len() {
            return None;
        }
        if let Some(ref mut num_elem) = self.num_elem {
            if *num_elem <= 0 {
                return None;
            }
            *num_elem -= 1;
        }

        let elem_raw: *mut u8 = {
            let vv = &mut self.seg.vecs[self.index.outer];
            &mut vv[self.index.inner]
        };

        self.index.inner += 1;
        if self.index.inner >= self.seg.vecs[self.index.outer].len() {
            self.index.inner = 0;
            self.index.outer += 1;
        }

        Some(unsafe { &mut *elem_raw })
    }
}

impl<'a> Iterator for Slices<'a> {
    type Item = &'a [u8];
    fn next(&mut self) -> Option<&'a [u8]> {
        if self.outer >= self.seg.vecs.len() {
            None
        } else {
            let i = self.outer;
            self.outer += 1;
            Some(&self.seg.vecs[i])
        }
    }
}

#[test]
fn test_segment() {
    let mut s = Segment::from_slice(&[1, 2, 3, 4]);
    s.insert_slice(0, &[7, 7, 7, 7, 7]);
}
<|endoftext|>


<commit_before>// Copyright 2015 Nicholas Bishop
//
// Closest-point method adapted from "Real-Time Collision Detection"
// by Christer Ericson, published by Morgan Kaufmann Publishers,
// Copyright 2005 Elsevier Inc
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use vector::{distance3, dot3, Vec3f};

/// Line segment between two points
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Segment3f {
    pub start: Vec3f,
    pub end: Vec3f
}

impl Segment3f {
    pub fn new(start: &Vec3f, end: &Vec3f) -> Segment3f {
        Segment3f {
            start: *start,
            end: *end
        }
    }

    pub fn length(&self) -> f32 {
        distance3(self.start, self.end)
    }

    /// Find the point on the segment closest to the input point. The
    /// return value contains both the parametric and actual location
    /// of the closest point.
    ///
    /// Adapted from "Real-Time Collision Detection" by Christer
    /// Ericson, published by Morgan Kaufmann Publishers, Copyright
    /// 2005 Elsevier Inc
    pub fn closest_point_to_point(&self, point: &Vec3f) -> (f32, Vec3f) {
        let a = self.start;
        let b = self.end;

        let ab = b - a;
        // Project point onto ab, but deferring divide by dot3(ab, ab)
        let t = dot3(*point - a, ab);
        if t <= 0.0f32 {
            // point projects outside the [a,b] interval, on the a
            // side; clamp to a
            (0.0f32, a)
        } else {
            // Always nonnegative since denom = ||ab|| ∧ 2
            let denom = dot3(ab, ab);
            if t >= denom {
                // point projects outside the [a,b] interval, on the b
                // side; clamp to b
                (1.0f32, b)
            } else {
                // point projects inside the [a,b] interval; must do
                // deferred divide now
                (t / denom, a + ab * t)
            }
        }
    }
}

#[test]
fn test_segment_length() {
    use vector::vec3f;
    let s = Segment3f::new(&vec3f(0, 0, 0),
                           &vec3f(0, 0, 9));
    assert!(s.length() == 9.0);
}

#[test]
fn test_segment_closest_point_to_point() {
    use vector::vec3f;
    let s = Segment3f::new(&vec3f(2, 0, 0),
                           &vec3f(3, 0, 0));
    assert!(s.closest_point_to_point(&vec3f(1, 0, 0)) ==
            (0.0, vec3f(2, 0, 0)));
    assert!(s.closest_point_to_point(&vec3f(4, 0, 0)) ==
            (1.0, vec3f(3, 0, 0)));
    assert!(s.closest_point_to_point(&vec3f(2.5, 1, 0)) ==
            (0.5, vec3f(2.5, 0, 0)));
}
<commit_msg>Add docstring<commit_after>// Copyright 2015 Nicholas Bishop
//
// Closest-point method adapted from "Real-Time Collision Detection"
// by Christer Ericson, published by Morgan Kaufmann Publishers,
// Copyright 2005 Elsevier Inc
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use vector::{distance3, dot3, Vec3f};

/// Line segment between two points
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Segment3f {
    pub start: Vec3f,
    pub end: Vec3f
}

impl Segment3f {
    pub fn new(start: &Vec3f, end: &Vec3f) -> Segment3f {
        Segment3f {
            start: *start,
            end: *end
        }
    }

    /// Length of the line segment
    pub fn length(&self) -> f32 {
        distance3(self.start, self.end)
    }

    /// Find the point on the segment closest to the input point. The
    /// return value contains both the parametric and actual location
    /// of the closest point.
    ///
    /// Adapted from "Real-Time Collision Detection" by Christer
    /// Ericson, published by Morgan Kaufmann Publishers, Copyright
    /// 2005 Elsevier Inc
    pub fn closest_point_to_point(&self, point: &Vec3f) -> (f32, Vec3f) {
        let a = self.start;
        let b = self.end;

        let ab = b - a;
        // Project point onto ab, but deferring divide by dot3(ab, ab)
        let t = dot3(*point - a, ab);
        if t <= 0.0f32 {
            // point projects outside the [a,b] interval, on the a
            // side; clamp to a
            (0.0f32, a)
        } else {
            // Always nonnegative since denom = ||ab|| ∧ 2
            let denom = dot3(ab, ab);
            if t >= denom {
                // point projects outside the [a,b] interval, on the b
                // side; clamp to b
                (1.0f32, b)
            } else {
                // point projects inside the [a,b] interval; must do
                // deferred divide now
                (t / denom, a + ab * t)
            }
        }
    }
}

#[test]
fn test_segment_length() {
    use vector::vec3f;
    let s = Segment3f::new(&vec3f(0, 0, 0),
                           &vec3f(0, 0, 9));
    assert!(s.length() == 9.0);
}

#[test]
fn test_segment_closest_point_to_point() {
    use vector::vec3f;
    let s = Segment3f::new(&vec3f(2, 0, 0),
                           &vec3f(3, 0, 0));
    assert!(s.closest_point_to_point(&vec3f(1, 0, 0)) ==
            (0.0, vec3f(2, 0, 0)));
    assert!(s.closest_point_to_point(&vec3f(4, 0, 0)) ==
            (1.0, vec3f(3, 0, 0)));
    assert!(s.closest_point_to_point(&vec3f(2.5, 1, 0)) ==
            (0.5, vec3f(2.5, 0, 0)));
}
<|endoftext|>


<commit_before>/**
 * A structure shared across REPL instances for storing history
 * such as statements and view items. I wish the AST was sendable.
 */
struct Repl {
    prompt: ~str,
    binary: ~str,
    running: bool,
    view_items: ~str,
    stmts: ~str
}

/// A utility function that hands off a pretty printer to a callback.
fn with_pp(intr: @token::ident_interner,
           cb: fn(pprust::ps, io::Writer)) -> ~str {
    do io::with_str_writer |writer| {
        let pp = pprust::rust_printer(writer, intr);

        cb(pp, writer);
        pp::eof(pp.s);
    }
}

/**
 * The AST (or the rest of rustc) are not sendable yet,
 * so recorded things are printed to strings. A terrible hack that
 * needs changes to rustc in order to be outed. This is unfortunately
 * going to cause the REPL to regress in parser performance,
 * because it has to parse the statements and view_items on each
 * input.
 */
fn record(repl: Repl, blk: @ast::blk, intr: @token::ident_interner) -> Repl {
    let view_items = if blk.node.view_items.len() > 0 {
        let new_view_items = do with_pp(intr) |pp, writer| {
            for blk.node.view_items.each |view_item| {
                pprust::print_view_item(pp, *view_item);
                writer.write_line(~"");
            }
        };

        debug!("new view items %s", new_view_items);

        repl.view_items + "\n" + new_view_items
    } else { repl.view_items };
    let stmts = if blk.node.stmts.len() > 0 {
        let new_stmts = do with_pp(intr) |pp, writer| {
            for blk.node.stmts.each |stmt| {
                match stmt.node {
                    ast::stmt_decl(*) => {
                        pprust::print_stmt(pp, **stmt);
                        writer.write_line(~"");
                    }
                    ast::stmt_expr(expr, _) | ast::stmt_semi(expr, _) => {
                        match expr.node {
                            ast::expr_assign(*) |
                            ast::expr_assign_op(*) |
                            ast::expr_swap(*) => {
                                pprust::print_stmt(pp, **stmt);
                                writer.write_line(~"");
                            }
                            _ => {}
                        }
                    }
                }
            }
        };

        debug!("new stmts %s", new_stmts);

        repl.stmts + "\n" + new_stmts
    } else { repl.stmts };

    Repl{
        view_items: view_items,
        stmts: stmts,
        .. repl
    }
}

/// Run an input string in a Repl, returning the new Repl.
fn run(repl: Repl, input: ~str) -> Repl {
    let options: @session::options = @{
        crate_type: session::unknown_crate,
        binary: repl.binary,
        .. *session::basic_options()
    };

    debug!("building driver input");
    let head = include_str!("wrapper.rs");
    let foot = fmt!("%s\nfn main() {\n%s\n\nprint({\n%s\n})\n}",
                    repl.view_items, repl.stmts, input);
    let wrapped = driver::str_input(head + foot);

    debug!("inputting %s", head + foot);

    debug!("building a driver session");
    let sess = driver::build_session(options, diagnostic::emit);

    debug!("building driver configuration");
    let cfg = driver::build_configuration(sess,
                                          repl.binary,
                                          wrapped);

    debug!("parsing");
    let mut crate = driver::parse_input(sess, cfg, wrapped);
    let mut opt = None;

    for crate.node.module.items.each |item| {
        match item.node {
            ast::item_fn(_, _, _, blk) => {
                if item.ident == sess.ident_of(~"main") {
                    opt = blk.node.expr;
                }
            }
            _ => {}
        }
    }

    let blk = match opt.get().node {
        ast::expr_call(_, exprs, _) => {
            match exprs[0].node {
                ast::expr_block(blk) => @blk,
                _ => fail
            }
        }
        _ => fail
    };

    debug!("configuration");
    crate = front::config::strip_unconfigured_items(crate);

    debug!("maybe building test harness");
    crate = front::test::modify_for_testing(sess, crate);

    debug!("expansion");
    crate = syntax::ext::expand::expand_crate(sess.parse_sess,
                                              sess.opts.cfg,
                                              crate);

    debug!("intrinsic injection");
    crate = front::intrinsic_inject::inject_intrinsic(sess, crate);

    debug!("core injection");
    crate = front::core_inject::maybe_inject_libcore_ref(sess, crate);

    debug!("building lint settings table");
    lint::build_settings_crate(sess, crate);

    debug!("ast indexing");
    let ast_map = syntax::ast_map::map_crate(sess.diagnostic(), *crate);

    debug!("external crate/lib resolution");
    creader::read_crates(sess.diagnostic(), *crate, sess.cstore,
                         sess.filesearch,
                         session::sess_os_to_meta_os(sess.targ_cfg.os),
                         sess.opts.static, sess.parse_sess.interner);

    debug!("language item collection");
    let lang_items = middle::lang_items::collect_language_items(crate, sess);

    debug!("resolution");
    let {def_map: def_map,
         exp_map2: exp_map2,
         trait_map: trait_map} = middle::resolve::resolve_crate(sess,
                                                                lang_items,
                                                                crate);

    debug!("freevar finding");
    let freevars = freevars::annotate_freevars(def_map, crate);

    debug!("region_resolution");
    let region_map = middle::region::resolve_crate(sess, def_map, crate);

    debug!("region paramaterization inference");
    let rp_set = middle::region::determine_rp_in_crate(sess, ast_map,
                                                       def_map, crate);

    debug!("typechecking");
    let ty_cx = ty::mk_ctxt(sess, def_map, ast_map, freevars,
                            region_map, rp_set, move lang_items, crate);
    let (method_map, vtable_map) = typeck::check_crate(ty_cx, trait_map,
                                                       crate);

    debug!("const marking");
    middle::const_eval::process_crate(crate, def_map, ty_cx);

    debug!("const checking");
    middle::check_const::check_crate(sess, crate, ast_map, def_map,
                                     method_map, ty_cx);

    debug!("privacy checking");
    middle::privacy::check_crate(ty_cx, &method_map, crate);

    debug!("loop checking");
    middle::check_loop::check_crate(ty_cx, crate);

    debug!("alt checking");
    middle::check_alt::check_crate(ty_cx, crate);

    debug!("liveness checking");
    let last_use_map = middle::liveness::check_crate(ty_cx,
                                                     method_map, crate);

    debug!("borrow checking");
    let (root_map, mutbl_map) = middle::borrowck::check_crate(ty_cx,
                                                              method_map,
                                                              last_use_map,
                                                              crate);

    debug!("kind checking");
    kind::check_crate(ty_cx, method_map, last_use_map, crate);

    debug!("lint checking");
    lint::check_crate(ty_cx, crate);

    let maps = {mutbl_map: mutbl_map,
                root_map: root_map,
                last_use_map: last_use_map,
                method_map: method_map,
                vtable_map: vtable_map};

    debug!("translation");
    let (llmod, _) = trans::base::trans_crate(sess, crate, ty_cx,
                                              ~path::from_str("<repl>"),
                                              exp_map2, maps);
    let pm = llvm::LLVMCreatePassManager();

    debug!("executing jit");
    back::link::jit::exec(sess, pm, llmod, 0, false);
    llvm::LLVMDisposePassManager(pm);

    debug!("recording input into repl history");
    record(repl, blk, sess.parse_sess.interner)
}

/// Run a command, e.g. :clear, :exit, etc.
fn run_cmd(repl: &mut Repl, _in: io::Reader, _out: io::Writer,
           cmd: ~str, _args: ~[~str]) {
    match cmd {
        ~"exit" => repl.running = false,
        ~"clear" => {
            repl.view_items = ~"";
            repl.stmts = ~"";

            rl::clear();
        }
        ~"help" => {
            io::println(~":clear - clear the screen\n" +
                        ~":exit - exit from the repl\n" +
                        ~":help - show this message");
        }
        _ => io::println(~"unknown cmd: " + cmd)
    }
}

fn main() {
    let args = os::args();
    let in = io::stdin();
    let out = io::stdout();
    let mut repl = Repl {
        prompt: ~"rusti> ",
        binary: args[0],
        running: true,
        view_items: ~"",
        stmts: ~""
    };

    do rl::complete |line, suggest| {
        if line.starts_with(":") {
            suggest(~":clear");
            suggest(~":exit");
            suggest(~":help");
        }
    }

    while repl.running {
        let result = rl::read(repl.prompt);

        if result.is_none() {
            break;
        }

        let line = result.get();

        if line.is_empty() {
            io::println(~"()");

            loop;
        }

        rl::add_history(line);

        if line.starts_with(~":") {
            let full = line.substr(1, line.len() - 1);
            let split = full.split_char(' ');
            let len = split.len();

            if len > 0 {
                let cmd = split[0];

                if !cmd.is_empty() {
                    let args = if len > 1 {
                        do vec::view(split, 1, len - 1).map |arg| {
                            *arg
                        }
                    } else { ~[] };

                    run_cmd(&mut repl, in, out, cmd, args);

                    loop;
                }
            }
        }

        let result = do task::try |copy repl| {
            run(copy repl, line)
        };

        if result.is_ok() {
            repl = result.get();
        }
    }
}
<commit_msg>rusti: Add current working directory to search path<commit_after>/**
 * A structure shared across REPL instances for storing history
 * such as statements and view items. I wish the AST was sendable.
 */
struct Repl {
    prompt: ~str,
    binary: ~str,
    running: bool,
    view_items: ~str,
    stmts: ~str
}

/// A utility function that hands off a pretty printer to a callback.
fn with_pp(intr: @token::ident_interner,
           cb: fn(pprust::ps, io::Writer)) -> ~str {
    do io::with_str_writer |writer| {
        let pp = pprust::rust_printer(writer, intr);

        cb(pp, writer);
        pp::eof(pp.s);
    }
}

/**
 * The AST (or the rest of rustc) are not sendable yet,
 * so recorded things are printed to strings. A terrible hack that
 * needs changes to rustc in order to be outed. This is unfortunately
 * going to cause the REPL to regress in parser performance,
 * because it has to parse the statements and view_items on each
 * input.
 */
fn record(repl: Repl, blk: @ast::blk, intr: @token::ident_interner) -> Repl {
    let view_items = if blk.node.view_items.len() > 0 {
        let new_view_items = do with_pp(intr) |pp, writer| {
            for blk.node.view_items.each |view_item| {
                pprust::print_view_item(pp, *view_item);
                writer.write_line(~"");
            }
        };

        debug!("new view items %s", new_view_items);

        repl.view_items + "\n" + new_view_items
    } else { repl.view_items };
    let stmts = if blk.node.stmts.len() > 0 {
        let new_stmts = do with_pp(intr) |pp, writer| {
            for blk.node.stmts.each |stmt| {
                match stmt.node {
                    ast::stmt_decl(*) => {
                        pprust::print_stmt(pp, **stmt);
                        writer.write_line(~"");
                    }
                    ast::stmt_expr(expr, _) | ast::stmt_semi(expr, _) => {
                        match expr.node {
                            ast::expr_assign(*) |
                            ast::expr_assign_op(*) |
                            ast::expr_swap(*) => {
                                pprust::print_stmt(pp, **stmt);
                                writer.write_line(~"");
                            }
                            _ => {}
                        }
                    }
                }
            }
        };

        debug!("new stmts %s", new_stmts);

        repl.stmts + "\n" + new_stmts
    } else { repl.stmts };

    Repl{
        view_items: view_items,
        stmts: stmts,
        .. repl
    }
}

/// Run an input string in a Repl, returning the new Repl.
fn run(repl: Repl, input: ~str) -> Repl {
    let options: @session::options = @{
        crate_type: session::unknown_crate,
        binary: repl.binary,
        addl_lib_search_paths: ~[os::getcwd()],
        .. *session::basic_options()
    };

    debug!("building driver input");
    let head = include_str!("wrapper.rs");
    let foot = fmt!("%s\nfn main() {\n%s\n\nprint({\n%s\n})\n}",
                    repl.view_items, repl.stmts, input);
    let wrapped = driver::str_input(head + foot);

    debug!("inputting %s", head + foot);

    debug!("building a driver session");
    let sess = driver::build_session(options, diagnostic::emit);

    debug!("building driver configuration");
    let cfg = driver::build_configuration(sess,
                                          repl.binary,
                                          wrapped);

    debug!("parsing");
    let mut crate = driver::parse_input(sess, cfg, wrapped);
    let mut opt = None;

    for crate.node.module.items.each |item| {
        match item.node {
            ast::item_fn(_, _, _, blk) => {
                if item.ident == sess.ident_of(~"main") {
                    opt = blk.node.expr;
                }
            }
            _ => {}
        }
    }

    let blk = match opt.get().node {
        ast::expr_call(_, exprs, _) => {
            match exprs[0].node {
                ast::expr_block(blk) => @blk,
                _ => fail
            }
        }
        _ => fail
    };

    debug!("configuration");
    crate = front::config::strip_unconfigured_items(crate);

    debug!("maybe building test harness");
    crate = front::test::modify_for_testing(sess, crate);

    debug!("expansion");
    crate = syntax::ext::expand::expand_crate(sess.parse_sess,
                                              sess.opts.cfg,
                                              crate);

    debug!("intrinsic injection");
    crate = front::intrinsic_inject::inject_intrinsic(sess, crate);

    debug!("core injection");
    crate = front::core_inject::maybe_inject_libcore_ref(sess, crate);

    debug!("building lint settings table");
    lint::build_settings_crate(sess, crate);

    debug!("ast indexing");
    let ast_map = syntax::ast_map::map_crate(sess.diagnostic(), *crate);

    debug!("external crate/lib resolution");
    creader::read_crates(sess.diagnostic(), *crate, sess.cstore,
                         sess.filesearch,
                         session::sess_os_to_meta_os(sess.targ_cfg.os),
                         sess.opts.static, sess.parse_sess.interner);

    debug!("language item collection");
    let lang_items = middle::lang_items::collect_language_items(crate, sess);

    debug!("resolution");
    let {def_map: def_map,
         exp_map2: exp_map2,
         trait_map: trait_map} = middle::resolve::resolve_crate(sess,
                                                                lang_items,
                                                                crate);

    debug!("freevar finding");
    let freevars = freevars::annotate_freevars(def_map, crate);

    debug!("region_resolution");
    let region_map = middle::region::resolve_crate(sess, def_map, crate);

    debug!("region paramaterization inference");
    let rp_set = middle::region::determine_rp_in_crate(sess, ast_map,
                                                       def_map, crate);

    debug!("typechecking");
    let ty_cx = ty::mk_ctxt(sess, def_map, ast_map, freevars,
                            region_map, rp_set, move lang_items, crate);
    let (method_map, vtable_map) = typeck::check_crate(ty_cx, trait_map,
                                                       crate);

    debug!("const marking");
    middle::const_eval::process_crate(crate, def_map, ty_cx);

    debug!("const checking");
    middle::check_const::check_crate(sess, crate, ast_map, def_map,
                                     method_map, ty_cx);

    debug!("privacy checking");
    middle::privacy::check_crate(ty_cx, &method_map, crate);

    debug!("loop checking");
    middle::check_loop::check_crate(ty_cx, crate);

    debug!("alt checking");
    middle::check_alt::check_crate(ty_cx, crate);

    debug!("liveness checking");
    let last_use_map = middle::liveness::check_crate(ty_cx,
                                                     method_map, crate);

    debug!("borrow checking");
    let (root_map, mutbl_map) = middle::borrowck::check_crate(ty_cx,
                                                              method_map,
                                                              last_use_map,
                                                              crate);

    debug!("kind checking");
    kind::check_crate(ty_cx, method_map, last_use_map, crate);

    debug!("lint checking");
    lint::check_crate(ty_cx, crate);

    let maps = {mutbl_map: mutbl_map,
                root_map: root_map,
                last_use_map: last_use_map,
                method_map: method_map,
                vtable_map: vtable_map};

    debug!("translation");
    let (llmod, _) = trans::base::trans_crate(sess, crate, ty_cx,
                                              ~path::from_str("<repl>"),
                                              exp_map2, maps);
    let pm = llvm::LLVMCreatePassManager();

    debug!("executing jit");
    back::link::jit::exec(sess, pm, llmod, 0, false);
    llvm::LLVMDisposePassManager(pm);

    debug!("recording input into repl history");
    record(repl, blk, sess.parse_sess.interner)
}

/// Run a command, e.g. :clear, :exit, etc.
fn run_cmd(repl: &mut Repl, _in: io::Reader, _out: io::Writer,
           cmd: ~str, _args: ~[~str]) {
    match cmd {
        ~"exit" => repl.running = false,
        ~"clear" => {
            repl.view_items = ~"";
            repl.stmts = ~"";

            rl::clear();
        }
        ~"help" => {
            io::println(~":clear - clear the screen\n" +
                        ~":exit - exit from the repl\n" +
                        ~":help - show this message");
        }
        _ => io::println(~"unknown cmd: " + cmd)
    }
}

fn main() {
    let args = os::args();
    let in = io::stdin();
    let out = io::stdout();
    let mut repl = Repl {
        prompt: ~"rusti> ",
        binary: args[0],
        running: true,
        view_items: ~"",
        stmts: ~""
    };

    do rl::complete |line, suggest| {
        if line.starts_with(":") {
            suggest(~":clear");
            suggest(~":exit");
            suggest(~":help");
        }
    }

    while repl.running {
        let result = rl::read(repl.prompt);

        if result.is_none() {
            break;
        }

        let line = result.get();

        if line.is_empty() {
            io::println(~"()");

            loop;
        }

        rl::add_history(line);

        if line.starts_with(~":") {
            let full = line.substr(1, line.len() - 1);
            let split = full.split_char(' ');
            let len = split.len();

            if len > 0 {
                let cmd = split[0];

                if !cmd.is_empty() {
                    let args = if len > 1 {
                        do vec::view(split, 1, len - 1).map |arg| {
                            *arg
                        }
                    } else { ~[] };

                    run_cmd(&mut repl, in, out, cmd, args);

                    loop;
                }
            }
        }

        let result = do task::try |copy repl| {
            run(copy repl, line)
        };

        if result.is_ok() {
            repl = result.get();
        }
    }
}
<|endoftext|>


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

//! Provides helper functionality.

use std::env;
use std::process::{Command};
use std::path::{Path, PathBuf};

use glob;

use libc::{c_int};

use super::{CXVersion};

//================================================
// Macros
//================================================

// try_opt! ______________________________________

macro_rules! try_opt {
    ($option:expr) => ({
        match $option {
            Some(some) => some,
            None => return None,
        }
    });
}

//================================================
// Structs
//================================================

/// A `clang` executable.
#[derive(Clone, Debug)]
pub struct Clang {
    /// The path to this `clang` executable.
    pub path: PathBuf,
    /// The version of this `clang` executable if it could be parsed.
    pub version: Option<CXVersion>,
    /// The directories searched by this `clang` executable for C headers.
    pub c_search_paths: Vec<PathBuf>,
    /// The directories searched by this `clang` executable for C++ headers.
    pub cpp_search_paths: Vec<PathBuf>,
}

impl Clang {
    //- Constructors -----------------------------

    fn new(path: PathBuf) -> Clang {
        let version = parse_version(&path);
        let c_search_paths = parse_search_paths(&path, "c");
        let cpp_search_paths = parse_search_paths(&path, "c++");
        Clang {
            path: path,
            version: version,
            c_search_paths: c_search_paths,
            cpp_search_paths: cpp_search_paths,
        }
    }

    /// Returns a `clang` executable if one can be found.
    ///
    /// If the `CLANG_PATH` environment variable is set, that is the instance of `clang` used.
    /// Otherwise, a series of directories are searched. First, If a path is supplied, that is the
    /// first directory searched. Then, the directory returned by `llvm-config --bindir` is
    /// searched. On OS X systems, `xcodebuild -find clang` will next be queried. Last, the
    /// directories in the system's `PATH` are searched.
    pub fn find(path: Option<&Path>) -> Option<Clang> {
        if let Ok(path) = env::var("CLANG_PATH") {
            return Some(Clang::new(path.into()));
        }

        let mut paths = vec![];
        if let Some(path) = path {
            paths.push(path.into());
        }
        if let Ok(path) = run_llvm_config(&["--bindir"]) {
            paths.push(path.into());
        }
        if cfg!(target_os="macos") {
            if let Ok((path, _)) = run("xcodebuild", &["-find", "clang"]) {
                paths.push(path.into());
            }
        }
        paths.extend(env::split_paths(&env::var("PATH").unwrap()));

        let default = format!("clang{}", env::consts::EXE_SUFFIX);
        let versioned = format!("clang-[0-9]*{}", env::consts::EXE_SUFFIX);
        let patterns = &[&default[..], &versioned[..]];
        for path in paths {
            if let Some(path) = find(&path, patterns) {
                return Some(Clang::new(path));
            }
        }
        None
    }
}

//================================================
// Functions
//================================================

/// Returns the first match to the supplied glob patterns in the supplied directory if there are any
/// matches.
fn find(directory: &Path, patterns: &[&str]) -> Option<PathBuf> {
    for pattern in patterns {
        let pattern = directory.join(pattern).to_string_lossy().into_owned();
        if let Some(path) = try_opt!(glob::glob(&pattern).ok()).filter_map(|p| p.ok()).next() {
            return Some(path);
        }
    }
    None
}

/// Attempts to run an executable, returning the `stdout` and `stderr` output if successful.
fn run(executable: &str, arguments: &[&str]) -> Result<(String, String), String> {
    Command::new(executable).args(arguments).output().map(|o| {
        let stdout = String::from_utf8_lossy(&o.stdout).into_owned();
        let stderr = String::from_utf8_lossy(&o.stderr).into_owned();
        (stdout, stderr)
    }).map_err(|_| format!("could not run executable: `{}`", executable))
}

/// Runs `clang`, returning the `stdout` and `stderr` output.
fn run_clang(path: &Path, arguments: &[&str]) -> (String, String) {
    run(&path.to_string_lossy().into_owned(), arguments).unwrap()
}

/// Runs `llvm-config`, returning the `stdout` output if successful.
fn run_llvm_config(arguments: &[&str]) -> Result<String, String> {
    let config = env::var("LLVM_CONFIG_PATH").unwrap_or_else(|_| "llvm-config".to_string());
    run(&config, arguments).map(|(o, _)| o)
}

/// Parses a version number if possible, ignoring trailing non-digit characters.
fn parse_version_number(number: &str) -> Option<c_int> {
    number.chars().take_while(|c| c.is_digit(10)).collect::<String>().parse().ok()
}

/// Parses the version from the output of a `clang` executable if possible.
fn parse_version(path: &Path) -> Option<CXVersion> {
    let output = run_clang(path, &["--version"]).0;
    let start = try_opt!(output.find("version ")) + 8;
    let mut numbers = try_opt!(output[start..].split_whitespace().nth(0)).split('.');
    let major = try_opt!(numbers.next().and_then(parse_version_number));
    let minor = try_opt!(numbers.next().and_then(parse_version_number));
    let subminor = numbers.next().and_then(parse_version_number).unwrap_or(0);
    Some(CXVersion { Major: major, Minor: minor, Subminor: subminor })
}

/// Parses the search paths from the output of a `clang` executable.
fn parse_search_paths(path: &Path, language: &str) -> Vec<PathBuf> {
    let output = run_clang(path, &["-E", "-x", language, "-", "-v"]).1;
    let include_start = "#include <...> search starts here:";
    let start = output.find(include_start).expect(include_start) + include_start.len();
    let end = output.find("End of search list.").expect("End of search list");
    let paths = output[start..end].replace("(framework directory)", "");
    paths.lines().filter(|l| !l.is_empty()).map(|l| Path::new(l.trim()).into()).collect()
}
<commit_msg>Improve clang searching (#47)<commit_after>// Copyright 2016 Kyle Mayes
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Provides helper functionality.

use std::{io, env};
use std::process::{Command};
use std::path::{Path, PathBuf};

use glob;

use libc::{c_int};

use super::{CXVersion};

//================================================
// Macros
//================================================

// try_opt! ______________________________________

macro_rules! try_opt {
    ($option:expr) => ({
        match $option {
            Some(some) => some,
            None => return None,
        }
    });
}

//================================================
// Structs
//================================================

/// A `clang` executable.
#[derive(Clone, Debug)]
pub struct Clang {
    /// The path to this `clang` executable.
    pub path: PathBuf,
    /// The version of this `clang` executable if it could be parsed.
    pub version: Option<CXVersion>,
    /// The directories searched by this `clang` executable for C headers.
    pub c_search_paths: Vec<PathBuf>,
    /// The directories searched by this `clang` executable for C++ headers.
    pub cpp_search_paths: Vec<PathBuf>,
}

impl Clang {
    //- Constructors -----------------------------

    fn new(path: PathBuf) -> Clang {
        let version = parse_version(&path);
        let c_search_paths = parse_search_paths(&path, "c");
        let cpp_search_paths = parse_search_paths(&path, "c++");
        Clang {
            path: path,
            version: version,
            c_search_paths: c_search_paths,
            cpp_search_paths: cpp_search_paths,
        }
    }

    /// Returns a `clang` executable if one can be found.
    ///
    /// If the `CLANG_PATH` environment variable is set, that is the instance of `clang` used.
    /// Otherwise, a series of directories are searched. First, If a path is supplied, that is the
    /// first directory searched. Then, the directory returned by `llvm-config --bindir` is
    /// searched. On OS X systems, `xcodebuild -find clang` will next be queried. Last, the
    /// directories in the system's `PATH` are searched.
    pub fn find(path: Option<&Path>) -> Option<Clang> {
        if let Ok(path) = env::var("CLANG_PATH") {
            return Some(Clang::new(path.into()));
        }

        let mut paths = vec![];
        if let Some(path) = path {
            paths.push(path.into());
        }
        if let Ok(path) = run_llvm_config(&["--bindir"]) {
            paths.push(path.into());
        }
        if cfg!(target_os="macos") {
            if let Ok((path, _)) = run("xcodebuild", &["-find", "clang"]) {
                paths.push(path.into());
            }
        }
        paths.extend(env::split_paths(&env::var("PATH").unwrap()));

        let default = format!("clang{}", env::consts::EXE_SUFFIX);
        let versioned = format!("clang-[0-9]*{}", env::consts::EXE_SUFFIX);
        let patterns = &[&default[..], &versioned[..]];
        for path in paths {
            if let Some(path) = find(&path, patterns) {
                return Some(Clang::new(path));
            }
        }
        None
    }
}

//================================================
// Functions
//================================================

/// Returns the first match to the supplied glob patterns in the supplied directory if there are any
/// matches.
fn find(directory: &Path, patterns: &[&str]) -> Option<PathBuf> {
    for pattern in patterns {
        let pattern = directory.join(pattern).to_string_lossy().into_owned();
        if let Some(path) = try_opt!(glob::glob(&pattern).ok()).filter_map(|p| p.ok()).next() {
            if path.is_file() && is_executable(&path).unwrap_or(false) {
                return Some(path);
            }
        }
    }
    None
}

#[cfg(unix)]
fn is_executable(path: &Path) -> io::Result<bool> {
    use libc;
    use std::ffi::CString;
    use std::os::unix::ffi::OsStrExt;
    let cpath = CString::new(path.as_os_str().as_bytes())?;
    let res = unsafe { libc::access(cpath.as_ptr(), libc::X_OK) };
    Ok(res == 0)
}

#[cfg(not(unix))]
fn is_executable(path: &Path) -> io::Result<bool> {
    Ok(true)
}

/// Attempts to run an executable, returning the `stdout` and `stderr` output if successful.
fn run(executable: &str, arguments: &[&str]) -> Result<(String, String), String> {
    Command::new(executable).args(arguments).output().map(|o| {
        let stdout = String::from_utf8_lossy(&o.stdout).into_owned();
        let stderr = String::from_utf8_lossy(&o.stderr).into_owned();
        (stdout, stderr)
    }).map_err(|_| format!("could not run executable: `{}`", executable))
}

/// Runs `clang`, returning the `stdout` and `stderr` output.
fn run_clang(path: &Path, arguments: &[&str]) -> (String, String) {
    run(&path.to_string_lossy().into_owned(), arguments).unwrap()
}

/// Runs `llvm-config`, returning the `stdout` output if successful.
fn run_llvm_config(arguments: &[&str]) -> Result<String, String> {
    let config = env::var("LLVM_CONFIG_PATH").unwrap_or_else(|_| "llvm-config".to_string());
    run(&config, arguments).map(|(o, _)| o)
}

/// Parses a version number if possible, ignoring trailing non-digit characters.
fn parse_version_number(number: &str) -> Option<c_int> {
    number.chars().take_while(|c| c.is_digit(10)).collect::<String>().parse().ok()
}

/// Parses the version from the output of a `clang` executable if possible.
fn parse_version(path: &Path) -> Option<CXVersion> {
    let output = run_clang(path, &["--version"]).0;
    let start = try_opt!(output.find("version ")) + 8;
    let mut numbers = try_opt!(output[start..].split_whitespace().nth(0)).split('.');
    let major = try_opt!(numbers.next().and_then(parse_version_number));
    let minor = try_opt!(numbers.next().and_then(parse_version_number));
    let subminor = numbers.next().and_then(parse_version_number).unwrap_or(0);
    Some(CXVersion { Major: major, Minor: minor, Subminor: subminor })
}

/// Parses the search paths from the output of a `clang` executable.
fn parse_search_paths(path: &Path, language: &str) -> Vec<PathBuf> {
    let output = run_clang(path, &["-E", "-x", language, "-", "-v"]).1;
    let include_start = "#include <...> search starts here:";
    let start = output.find(include_start).expect(include_start) + include_start.len();
    let end = output.find("End of search list.").expect("End of search list");
    let paths = output[start..end].replace("(framework directory)", "");
    paths.lines().filter(|l| !l.is_empty()).map(|l| Path::new(l.trim()).into()).collect()
}
<|endoftext|>


<commit_before>use libc;
use std::os::unix::io::RawFd;
use {Errno, Result};

libc_bitflags! {
    flags EfdFlags: libc::c_int {
        const EFD_CLOEXEC, // Since Linux 2.6.27
        const EFD_NONBLOCK, // Since Linux 2.6.27
        const EFD_SEMAPHORE, // Since Linux 2.6.30
    }
}

pub fn eventfd(initval: libc::c_uint, flags: EfdFlags) -> Result<RawFd> {
    let res = unsafe { libc::eventfd(initval, flags.bits()) };

    Errno::result(res).map(|r| r as RawFd)
}
<commit_msg>fix eventfd build<commit_after>use libc;
use std::os::unix::io::RawFd;
use {Errno, Result};

libc_bitflags! {
    flags EfdFlags: libc::c_int {
        EFD_CLOEXEC, // Since Linux 2.6.27
        EFD_NONBLOCK, // Since Linux 2.6.27
        EFD_SEMAPHORE, // Since Linux 2.6.30
    }
}

pub fn eventfd(initval: libc::c_uint, flags: EfdFlags) -> Result<RawFd> {
    let res = unsafe { libc::eventfd(initval, flags.bits()) };

    Errno::result(res).map(|r| r as RawFd)
}
<|endoftext|>


<commit_before>
use biquad_filter;

// number of bands for the vocoder
const BANDS: usize = 30;
const FRAMES: usize = 256;

pub struct Vocoder {
    filters_c: Vec<biquad_filter::BiquadFilter>,
    buffer: [[f32; FRAMES]; BANDS],
}

impl Vocoder {
    pub fn new(sample_rate: f32) -> Vocoder {
        // initialize the filter bank
        let mut filters_c = Vec::with_capacity(BANDS);
        for _i in 0..BANDS {
            let mut filter = biquad_filter::BiquadFilter::new(sample_rate);
            filter.set_bandpass(200f32, 1.5f32);
            filters_c.push(filter);
        }

        Vocoder {
            filters_c: filters_c,
            buffer: [[0f32; FRAMES]; BANDS],
        }
    }

    pub fn generate(&mut self, output: &mut[f32], modulator: &[f32], carrier: &mut[f32]) {
        // filter the carrier into bands
        for (band, filter) in self.buffer.iter_mut().zip(self.filters_c.iter_mut()) {
            filter.filter(carrier, band);
        }

        for (output_s, buffer_s) in output.iter_mut().zip(self.buffer[0].iter()) {
            *output_s = *buffer_s;
        }
    }
}
<commit_msg>vocoder is in a functional state<commit_after>
use biquad_filter::BiquadFilter;

// number of bands for the vocoder
const BANDS: usize = 30;
const FRAMES: usize = 256;

pub struct Vocoder {
    carrier_filters: Vec<BiquadFilter>,
    modulator_filters: Vec<BiquadFilter>,
    carrier_filtered: [[f32; FRAMES]; BANDS],
    modulator_filtered: [[f32; FRAMES]; BANDS],
}

impl Vocoder {
    pub fn new(sample_rate: f32) -> Vocoder {
        Vocoder {
            carrier_filters: Vocoder::init_filterbank(sample_rate),
            modulator_filters: Vocoder::init_filterbank(sample_rate),
            carrier_filtered: [[0f32; FRAMES]; BANDS],
            modulator_filtered: [[0f32; FRAMES]; BANDS],
        }
    }

    // make a constant-Q filter bank of the given range
    // TODO don't hardcode the range
    fn init_filterbank(sample_rate: f32) -> Vec<BiquadFilter> {
        let mut carrier_filters = Vec::with_capacity(BANDS);
        let bands = BANDS;
        let range = 200f32..5000f32;
        let log_range = range.start.ln()..range.end.ln();
        let log_delta = (log_range.end - log_range.start) / bands as f32;
        for i in 0..bands {
            let from = (log_range.start + log_delta * i as f32).exp();
            let to = (log_range.start + log_delta * (i+1) as f32).exp();
            let fc = (to + from) / 2f32;
            let q = fc / (to - from);  // about the same for all bands

            let mut filter = BiquadFilter::new(sample_rate);
            filter.set_bandpass(fc, 2f32 * q);
            carrier_filters.push(filter);
        }
        carrier_filters
    }

    pub fn generate(&mut self, output: &mut[f32], modulator: &[f32], carrier: &mut[f32]) {
        // filter the modulator into bands
        for (modulator_band, filter) in self.modulator_filtered.iter_mut().zip(self.modulator_filters.iter_mut()) {
            filter.filter(modulator, modulator_band);
        }

        // measure modulator bands amplitude

        // filter the carrier into bands
        for (carrier_band, filter) in self.carrier_filtered.iter_mut().zip(self.carrier_filters.iter_mut()) {
            filter.filter(carrier, carrier_band);
        }

        // modulate carrier with modulator amplitudes
        for (carrier_band, modulator_band) in self.carrier_filtered.iter_mut().zip(self.modulator_filtered.iter()) {
            let mut max_s = 0f32;

            for modulator_s in modulator_band.iter() {
                max_s = if *modulator_s > max_s { *modulator_s } else { max_s };
            }

            for carrier_s in carrier_band.iter_mut() {
                *carrier_s = *carrier_s * max_s;
            }
        }

        // output mix
        for carrier_band in self.carrier_filtered.iter() {
            for (output_s, band_s) in output.iter_mut().zip(carrier_band.iter()) {
                *output_s += *band_s;
            }
        }
        let gain = 20f32;  // using insane gain because my filters suck
        for output_s in output.iter_mut() {
            *output_s *= gain / BANDS as f32;
        }
    }
}
<|endoftext|>