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

//! Set of structs and methods that act as a sort of internal prelude.
//!
//! The elements available in this module and its children are fairly basic building blocks that
//! the other modules all glob-import to make available as a common language. A lot of
//! infrastructure code goes in here.
//!
//! # Module contents
//!
//! Since i split this into multiple files that are then "flattened" into the final module, it's
//! worth giving an inventory of what's in here, since every file has a `use common::*;` in it.
//!
//! ## Type Aliases
//!
//! These types are used commonly enough in the library that they're re-exported here for easy use.
//!
//! * `hyper::headers::HeaderMap<hyper::headers::HeaderValue>` (re-exported as the alias `Headers`)
//!
//! ## `ParamList`
//!
//! `ParamList` is a type alias for use as a collection of parameters to a given web call. It's
//! consumed in the auth module, and provides some easy wrappers to consistently handle some types.
//!
//! `add_param` is a basic function that turns its arguments into `Cow<'static, str>`, then inserts them
//! as a parameter into the given `ParamList`.
//!
//! `add_name_param` provides some special handling for the `UserID` enum, since Twitter always
//! handles user parameters the same way: either as a `"user_id"` parameter with the ID, or as a
//! `"screen_name"` parameter with the screen name. Since that's also how the `UserID` enum is laid
//! out, this just puts the right parameter into the given `ParamList`.
//!
//! `add_list_param` does the same thing, but for `ListID`. Lists get a little more complicated
//! than users, though, since there are technically *three* ways to reference a list: by its ID, by
//! the owner's ID and the list slug, or by the owner's screen name and the list slug. Again, since
//! Twitter always uses the same set of parameters when referencing a list, this deals with all of
//! that work in one place, and i can just take a `ListID` from the user and shove it directly into
//! a `ParamList`.
//!
//! `multiple_names_param` is for when a function takes an `IntoIterator<Item=UserID>` It's
//! possible to mix and match the use of the `"user_id"` and `"screen_name"` parameters on these
//! lookup functions, so this saves up all that handling and splits the iterator into two strings:
//! one for the user IDs, one for the screen names.
//!
//! ## Miscellaneous functions
//!
//! `codepoints_to_bytes` is a convenience function that i use when Twitter returns text ranges in
//! terms of codepoint offsets rather than byte offsets. It takes the pair of numbers from twitter
//! and the string it refers to, and returns a pair that can be used directly to slice the given
//! string. It's also an example of how function parameters are themselves patterns, because i
//! destructure the pair right in the signature. `>_>`
//!
//! `deserialize_datetime` and `deserialize_mime` are glue functions to read these specific items
//! out in a `Deserialize` implementation. Twitter always gives timestamps in the same format, so
//! having that function here saves us from having to write the format out everywhere.
//!
//! `merge_by` and its companion type `MergeBy` is a copy of the iterator adapter of the same name
//! from itertools, because i didn't want to add another dependency onto the great towering pile
//! that is my dep tree. `>_>`
//!
//! `max_opt` and `min_opt` are helper functions because i didn't realize that `Option` derived
//! `PartialOrd` and `Ord` at the time. Strictly speaking they're subtly different because
//! `std::cmp::{min,max}` require `Ord` and `min_opt` won't reach for the None if it's there,
//! unlike the derived `PartialOrd` which considers None to be less than Some.
//!
//! ## `Response`
//!
//! Also in its own module, `Response` is a public structure that contains rate-limit information
//! from Twitter, alongside some other desired output. This type is used all over the place in
//! egg-mode, because i wanted to make sure people always had rate-limit information on hand. The
//! module also contains the types and functions that all web calls go through: the ones that load
//! a web call, parse out the rate-limit headers, and call some handler to perform final processing
//! on the result.
//!
//! `request_with_json_response` is the most common future constructor, which just defers to
//! `raw_request` (which just calls `serde_json` and loads up the rate-limit headers)
//! then deserializes the json response to given type.
//!
//! `rate_headers` is an infra function that takes the `Headers` and returns an empty `Response`
//! with the rate-limit info parsed out. It's only exported for a couple functions in `list` which
//! need to get that info even on an error.

use std::borrow::Cow;
use std::collections::HashMap;
use std::future::Future;
use std::iter::Peekable;
use std::pin::Pin;

use chrono::{self, TimeZone};
use hyper::header::{HeaderMap, HeaderValue};
use mime;
use serde::de::Error;
use serde::{Deserialize, Deserializer};

mod response;

pub use crate::common::response::*;
use crate::{error, list, user};

pub type Headers = HeaderMap<HeaderValue>;
pub(crate) type CowStr = Cow<'static, str>;

///Convenience type used to hold parameters to an API call.
#[derive(Debug, Clone, Default, derive_more::Deref, derive_more::DerefMut, derive_more::From)]
pub(crate) struct ParamList(HashMap<Cow<'static, str>, Cow<'static, str>>);

impl ParamList {
    pub(crate) fn new() -> Self {
        Self(HashMap::new())
    }

    pub(crate) fn extended_tweets(self) -> Self {
        self.add_param("tweet_mode", "extended")
    }

    ///Convenience function to add a key/value parameter to a `ParamList`.
    pub(crate) fn add_param(
        mut self,
        key: impl Into<Cow<'static, str>>,
        value: impl Into<Cow<'static, str>>,
    ) -> Self {
        self.insert(key.into(), value.into());
        self
    }

    ///Convenience function to add a key/value parameter to a `ParamList`.
    pub(crate) fn add_opt_param(
        self,
        key: impl Into<Cow<'static, str>>,
        value: Option<impl Into<Cow<'static, str>>>,
    ) -> Self {
        match value {
            Some(val) => self.add_param(key.into(), val.into()),
            None => self,
        }
    }

    ///Convenience function to add a key/value parameter to a `ParamList` without moving.
    pub(crate) fn add_param_ref(
        &mut self,
        key: impl Into<Cow<'static, str>>,
        value: impl Into<Cow<'static, str>>,
    ) {
        self.0.insert(key.into(), value.into());
    }

    pub(crate) fn add_name_param(self, id: user::UserID) -> Self {
        match id {
            user::UserID::ID(id) => self.add_param("user_id", id.to_string()),
            user::UserID::ScreenName(name) => self.add_param("screen_name", name),
        }
    }

    pub(crate) fn add_list_param(mut self, list: list::ListID) -> Self {
        match list {
            list::ListID::Slug(owner, name) => {
                match owner {
                    user::UserID::ID(id) => {
                        self.add_param_ref("owner_id", id.to_string());
                    }
                    user::UserID::ScreenName(name) => {
                        self.add_param_ref("owner_screen_name", name);
                    }
                }
                self.add_param("slug", name.clone())
            }
            list::ListID::ID(id) => self.add_param("list_id", id.to_string()),
        }
    }
}

// Helper trait to stringify the contents of an Option
pub(crate) trait MapString {
    fn map_string(&self) -> Option<String>;
}

impl<T: std::fmt::Display> MapString for Option<T> {
    fn map_string(&self) -> Option<String> {
        self.as_ref().map(|v| v.to_string())
    }
}

pub fn multiple_names_param<T, I>(accts: I) -> (String, String)
where
    T: Into<user::UserID>,
    I: IntoIterator<Item = T>,
{
    let mut ids = Vec::new();
    let mut names = Vec::new();

    for x in accts {
        match x.into() {
            user::UserID::ID(id) => ids.push(id.to_string()),
            user::UserID::ScreenName(name) => names.push(name),
        }
    }

    (ids.join(","), names.join(","))
}

///Convenient type alias for futures that resolve to responses from Twitter.
pub(crate) type FutureResponse<T> = Pin<Box<dyn Future<Output = error::Result<Response<T>>>>>;

pub fn codepoints_to_bytes(&mut (ref mut start, ref mut end): &mut (usize, usize), text: &str) {
    let mut byte_start = *start;
    let mut byte_end = *end;
    for (ch_offset, (by_offset, _)) in text.char_indices().enumerate() {
        if ch_offset == *start {
            byte_start = by_offset;
        } else if ch_offset == *end {
            byte_end = by_offset;
        }
    }
    *start = byte_start;
    if text.chars().count() == *end {
        *end = text.len()
    } else {
        *end = byte_end
    }
}

///A clone of MergeBy from Itertools.
pub struct MergeBy<Iter, Fun>
where
    Iter: Iterator,
{
    left: Peekable<Iter>,
    right: Peekable<Iter>,
    comp: Fun,
    fused: Option<bool>,
}

impl<Iter, Fun> Iterator for MergeBy<Iter, Fun>
where
    Iter: Iterator,
    Fun: FnMut(&Iter::Item, &Iter::Item) -> bool,
{
    type Item = Iter::Item;

    fn next(&mut self) -> Option<Self::Item> {
        let is_left = match self.fused {
            Some(lt) => lt,
            None => match (self.left.peek(), self.right.peek()) {
                (Some(a), Some(b)) => (self.comp)(a, b),
                (Some(_), None) => {
                    self.fused = Some(true);
                    true
                }
                (None, Some(_)) => {
                    self.fused = Some(false);
                    false
                }
                (None, None) => return None,
            },
        };

        if is_left {
            self.left.next()
        } else {
            self.right.next()
        }
    }
}

pub fn merge_by<Iter, Fun>(left: Iter, right: Iter, comp: Fun) -> MergeBy<Iter::IntoIter, Fun>
where
    Iter: IntoIterator,
    Fun: FnMut(&Iter::Item, &Iter::Item) -> bool,
{
    MergeBy {
        left: left.into_iter().peekable(),
        right: right.into_iter().peekable(),
        comp: comp,
        fused: None,
    }
}

pub fn max_opt<T: PartialOrd>(left: Option<T>, right: Option<T>) -> Option<T> {
    match (left, right) {
        (Some(left), Some(right)) => {
            if left >= right {
                Some(left)
            } else {
                Some(right)
            }
        }
        (left, None) => left,
        (None, right) => right,
    }
}

pub fn min_opt<T: PartialOrd>(left: Option<T>, right: Option<T>) -> Option<T> {
    match (left, right) {
        (Some(left), Some(right)) => {
            if left <= right {
                Some(left)
            } else {
                Some(right)
            }
        }
        (left, None) => left,
        (None, right) => right,
    }
}

pub fn deserialize_datetime<'de, D>(ser: D) -> Result<chrono::DateTime<chrono::Utc>, D::Error>
where
    D: Deserializer<'de>,
{
    let s = String::deserialize(ser)?;
    let date = (chrono::Utc)
        .datetime_from_str(&s, "%a %b %d %T %z %Y")
        .map_err(|e| D::Error::custom(e))?;
    Ok(date)
}

pub fn deserialize_mime<'de, D>(ser: D) -> Result<mime::Mime, D::Error>
where
    D: Deserializer<'de>,
{
    let str = String::deserialize(ser)?;
    str.parse().map_err(|e| D::Error::custom(e))
}

#[cfg(test)]
pub(crate) mod tests {
    use super::*;
    use std::fs::File;
    use std::io::Read;

    pub(crate) fn load_file(path: &str) -> String {
        let mut file = File::open(path).unwrap();
        let mut content = String::new();
        file.read_to_string(&mut content).unwrap();
        content
    }

    #[test]
    fn test_codepoints_to_bytes() {
        let unicode = "frônt Iñtërnâtiônàližætiøn ënd";
        // suppose we want to slice out the middle word.
        // 30 codepoints of which we want the middle 20;
        let mut range = (6, 26);
        codepoints_to_bytes(&mut range, unicode);
        assert_eq!(&unicode[range.0..range.1], "Iñtërnâtiônàližætiøn");

        let mut range = (6, 30);
        codepoints_to_bytes(&mut range, unicode);
        assert_eq!(&unicode[range.0..range.1], "Iñtërnâtiônàližætiøn ënd");
    }
}
<commit_msg>add `Send` to trait bounds in `FutureResponse<T>`<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

//! Set of structs and methods that act as a sort of internal prelude.
//!
//! The elements available in this module and its children are fairly basic building blocks that
//! the other modules all glob-import to make available as a common language. A lot of
//! infrastructure code goes in here.
//!
//! # Module contents
//!
//! Since i split this into multiple files that are then "flattened" into the final module, it's
//! worth giving an inventory of what's in here, since every file has a `use common::*;` in it.
//!
//! ## Type Aliases
//!
//! These types are used commonly enough in the library that they're re-exported here for easy use.
//!
//! * `hyper::headers::HeaderMap<hyper::headers::HeaderValue>` (re-exported as the alias `Headers`)
//!
//! ## `ParamList`
//!
//! `ParamList` is a type alias for use as a collection of parameters to a given web call. It's
//! consumed in the auth module, and provides some easy wrappers to consistently handle some types.
//!
//! `add_param` is a basic function that turns its arguments into `Cow<'static, str>`, then inserts them
//! as a parameter into the given `ParamList`.
//!
//! `add_name_param` provides some special handling for the `UserID` enum, since Twitter always
//! handles user parameters the same way: either as a `"user_id"` parameter with the ID, or as a
//! `"screen_name"` parameter with the screen name. Since that's also how the `UserID` enum is laid
//! out, this just puts the right parameter into the given `ParamList`.
//!
//! `add_list_param` does the same thing, but for `ListID`. Lists get a little more complicated
//! than users, though, since there are technically *three* ways to reference a list: by its ID, by
//! the owner's ID and the list slug, or by the owner's screen name and the list slug. Again, since
//! Twitter always uses the same set of parameters when referencing a list, this deals with all of
//! that work in one place, and i can just take a `ListID` from the user and shove it directly into
//! a `ParamList`.
//!
//! `multiple_names_param` is for when a function takes an `IntoIterator<Item=UserID>` It's
//! possible to mix and match the use of the `"user_id"` and `"screen_name"` parameters on these
//! lookup functions, so this saves up all that handling and splits the iterator into two strings:
//! one for the user IDs, one for the screen names.
//!
//! ## Miscellaneous functions
//!
//! `codepoints_to_bytes` is a convenience function that i use when Twitter returns text ranges in
//! terms of codepoint offsets rather than byte offsets. It takes the pair of numbers from twitter
//! and the string it refers to, and returns a pair that can be used directly to slice the given
//! string. It's also an example of how function parameters are themselves patterns, because i
//! destructure the pair right in the signature. `>_>`
//!
//! `deserialize_datetime` and `deserialize_mime` are glue functions to read these specific items
//! out in a `Deserialize` implementation. Twitter always gives timestamps in the same format, so
//! having that function here saves us from having to write the format out everywhere.
//!
//! `merge_by` and its companion type `MergeBy` is a copy of the iterator adapter of the same name
//! from itertools, because i didn't want to add another dependency onto the great towering pile
//! that is my dep tree. `>_>`
//!
//! `max_opt` and `min_opt` are helper functions because i didn't realize that `Option` derived
//! `PartialOrd` and `Ord` at the time. Strictly speaking they're subtly different because
//! `std::cmp::{min,max}` require `Ord` and `min_opt` won't reach for the None if it's there,
//! unlike the derived `PartialOrd` which considers None to be less than Some.
//!
//! ## `Response`
//!
//! Also in its own module, `Response` is a public structure that contains rate-limit information
//! from Twitter, alongside some other desired output. This type is used all over the place in
//! egg-mode, because i wanted to make sure people always had rate-limit information on hand. The
//! module also contains the types and functions that all web calls go through: the ones that load
//! a web call, parse out the rate-limit headers, and call some handler to perform final processing
//! on the result.
//!
//! `request_with_json_response` is the most common future constructor, which just defers to
//! `raw_request` (which just calls `serde_json` and loads up the rate-limit headers)
//! then deserializes the json response to given type.
//!
//! `rate_headers` is an infra function that takes the `Headers` and returns an empty `Response`
//! with the rate-limit info parsed out. It's only exported for a couple functions in `list` which
//! need to get that info even on an error.

use std::borrow::Cow;
use std::collections::HashMap;
use std::future::Future;
use std::iter::Peekable;
use std::pin::Pin;

use chrono::{self, TimeZone};
use hyper::header::{HeaderMap, HeaderValue};
use mime;
use serde::de::Error;
use serde::{Deserialize, Deserializer};

mod response;

pub use crate::common::response::*;
use crate::{error, list, user};

pub type Headers = HeaderMap<HeaderValue>;
pub(crate) type CowStr = Cow<'static, str>;

///Convenience type used to hold parameters to an API call.
#[derive(Debug, Clone, Default, derive_more::Deref, derive_more::DerefMut, derive_more::From)]
pub(crate) struct ParamList(HashMap<Cow<'static, str>, Cow<'static, str>>);

impl ParamList {
    pub(crate) fn new() -> Self {
        Self(HashMap::new())
    }

    pub(crate) fn extended_tweets(self) -> Self {
        self.add_param("tweet_mode", "extended")
    }

    ///Convenience function to add a key/value parameter to a `ParamList`.
    pub(crate) fn add_param(
        mut self,
        key: impl Into<Cow<'static, str>>,
        value: impl Into<Cow<'static, str>>,
    ) -> Self {
        self.insert(key.into(), value.into());
        self
    }

    ///Convenience function to add a key/value parameter to a `ParamList`.
    pub(crate) fn add_opt_param(
        self,
        key: impl Into<Cow<'static, str>>,
        value: Option<impl Into<Cow<'static, str>>>,
    ) -> Self {
        match value {
            Some(val) => self.add_param(key.into(), val.into()),
            None => self,
        }
    }

    ///Convenience function to add a key/value parameter to a `ParamList` without moving.
    pub(crate) fn add_param_ref(
        &mut self,
        key: impl Into<Cow<'static, str>>,
        value: impl Into<Cow<'static, str>>,
    ) {
        self.0.insert(key.into(), value.into());
    }

    pub(crate) fn add_name_param(self, id: user::UserID) -> Self {
        match id {
            user::UserID::ID(id) => self.add_param("user_id", id.to_string()),
            user::UserID::ScreenName(name) => self.add_param("screen_name", name),
        }
    }

    pub(crate) fn add_list_param(mut self, list: list::ListID) -> Self {
        match list {
            list::ListID::Slug(owner, name) => {
                match owner {
                    user::UserID::ID(id) => {
                        self.add_param_ref("owner_id", id.to_string());
                    }
                    user::UserID::ScreenName(name) => {
                        self.add_param_ref("owner_screen_name", name);
                    }
                }
                self.add_param("slug", name.clone())
            }
            list::ListID::ID(id) => self.add_param("list_id", id.to_string()),
        }
    }
}

// Helper trait to stringify the contents of an Option
pub(crate) trait MapString {
    fn map_string(&self) -> Option<String>;
}

impl<T: std::fmt::Display> MapString for Option<T> {
    fn map_string(&self) -> Option<String> {
        self.as_ref().map(|v| v.to_string())
    }
}

pub fn multiple_names_param<T, I>(accts: I) -> (String, String)
where
    T: Into<user::UserID>,
    I: IntoIterator<Item = T>,
{
    let mut ids = Vec::new();
    let mut names = Vec::new();

    for x in accts {
        match x.into() {
            user::UserID::ID(id) => ids.push(id.to_string()),
            user::UserID::ScreenName(name) => names.push(name),
        }
    }

    (ids.join(","), names.join(","))
}

///Convenient type alias for futures that resolve to responses from Twitter.
pub(crate) type FutureResponse<T> =
    Pin<Box<dyn Future<Output = error::Result<Response<T>>> + Send>>;

pub fn codepoints_to_bytes(&mut (ref mut start, ref mut end): &mut (usize, usize), text: &str) {
    let mut byte_start = *start;
    let mut byte_end = *end;
    for (ch_offset, (by_offset, _)) in text.char_indices().enumerate() {
        if ch_offset == *start {
            byte_start = by_offset;
        } else if ch_offset == *end {
            byte_end = by_offset;
        }
    }
    *start = byte_start;
    if text.chars().count() == *end {
        *end = text.len()
    } else {
        *end = byte_end
    }
}

///A clone of MergeBy from Itertools.
pub struct MergeBy<Iter, Fun>
where
    Iter: Iterator,
{
    left: Peekable<Iter>,
    right: Peekable<Iter>,
    comp: Fun,
    fused: Option<bool>,
}

impl<Iter, Fun> Iterator for MergeBy<Iter, Fun>
where
    Iter: Iterator,
    Fun: FnMut(&Iter::Item, &Iter::Item) -> bool,
{
    type Item = Iter::Item;

    fn next(&mut self) -> Option<Self::Item> {
        let is_left = match self.fused {
            Some(lt) => lt,
            None => match (self.left.peek(), self.right.peek()) {
                (Some(a), Some(b)) => (self.comp)(a, b),
                (Some(_), None) => {
                    self.fused = Some(true);
                    true
                }
                (None, Some(_)) => {
                    self.fused = Some(false);
                    false
                }
                (None, None) => return None,
            },
        };

        if is_left {
            self.left.next()
        } else {
            self.right.next()
        }
    }
}

pub fn merge_by<Iter, Fun>(left: Iter, right: Iter, comp: Fun) -> MergeBy<Iter::IntoIter, Fun>
where
    Iter: IntoIterator,
    Fun: FnMut(&Iter::Item, &Iter::Item) -> bool,
{
    MergeBy {
        left: left.into_iter().peekable(),
        right: right.into_iter().peekable(),
        comp: comp,
        fused: None,
    }
}

pub fn max_opt<T: PartialOrd>(left: Option<T>, right: Option<T>) -> Option<T> {
    match (left, right) {
        (Some(left), Some(right)) => {
            if left >= right {
                Some(left)
            } else {
                Some(right)
            }
        }
        (left, None) => left,
        (None, right) => right,
    }
}

pub fn min_opt<T: PartialOrd>(left: Option<T>, right: Option<T>) -> Option<T> {
    match (left, right) {
        (Some(left), Some(right)) => {
            if left <= right {
                Some(left)
            } else {
                Some(right)
            }
        }
        (left, None) => left,
        (None, right) => right,
    }
}

pub fn deserialize_datetime<'de, D>(ser: D) -> Result<chrono::DateTime<chrono::Utc>, D::Error>
where
    D: Deserializer<'de>,
{
    let s = String::deserialize(ser)?;
    let date = (chrono::Utc)
        .datetime_from_str(&s, "%a %b %d %T %z %Y")
        .map_err(|e| D::Error::custom(e))?;
    Ok(date)
}

pub fn deserialize_mime<'de, D>(ser: D) -> Result<mime::Mime, D::Error>
where
    D: Deserializer<'de>,
{
    let str = String::deserialize(ser)?;
    str.parse().map_err(|e| D::Error::custom(e))
}

#[cfg(test)]
pub(crate) mod tests {
    use super::*;
    use std::fs::File;
    use std::io::Read;

    pub(crate) fn load_file(path: &str) -> String {
        let mut file = File::open(path).unwrap();
        let mut content = String::new();
        file.read_to_string(&mut content).unwrap();
        content
    }

    #[test]
    fn test_codepoints_to_bytes() {
        let unicode = "frônt Iñtërnâtiônàližætiøn ënd";
        // suppose we want to slice out the middle word.
        // 30 codepoints of which we want the middle 20;
        let mut range = (6, 26);
        codepoints_to_bytes(&mut range, unicode);
        assert_eq!(&unicode[range.0..range.1], "Iñtërnâtiônàližætiøn");

        let mut range = (6, 30);
        codepoints_to_bytes(&mut range, unicode);
        assert_eq!(&unicode[range.0..range.1], "Iñtërnâtiônàližætiøn ënd");
    }
}
<|endoftext|>


<commit_before>use super::{ParserError, ParserResult};
use super::primitives::{PrimitiveIterator, U1, U2, U4};

use std::ops::Deref;
use std::rc::Rc;

macro_rules! generate_constant_pool_retrieval_method {
    ($variant_name:ident, $struct_name:ident, $method_name:ident) => {
        pub fn $method_name(index: usize,
                            constant_pool: &Vec<ConstantPoolItem>)
            -> ParserResult<Rc<$struct_name>> {
                let actual_index = ConstantPoolItem::shift_index(index);

                if let Some(item) = constant_pool.get(actual_index) {
                    match item {
                        &ConstantPoolItem::$variant_name(ref val) => return Ok(val.clone()),
                        item @ _ => {
                            let name = item.to_friendly_name();
                            return Err(ParserError::UnexpectedConstantPoolItem(name))
                        }
                    }
                }

                Err(ParserError::ConstantPoolIndexOutOfBounds(actual_index))
            }

    }
}

#[derive(Debug)]
pub struct ClassInfo {
    pub tag: U1,
    pub name_index: U2,
}

#[derive(Debug)]
pub struct FieldOrMethodOrInterfaceMethodInfo {
    pub tag: U1,
    pub class_index: U2,
    pub name_and_type_index: U2,
}

#[derive(Debug)]
pub struct StringInfo {
    pub tag: U1,
    pub string_index: U2,
}

#[derive(Debug)]
pub struct NameAndTypeInfo {
    pub tag: U1,
    pub name_index: U2,
    pub descriptor_index: U2,
}

#[derive(Debug)]
pub struct Utf8Info {
    pub tag: U1,
    pub length: U2,
    pub value: String,
}

impl Deref for Utf8Info {
    type Target = str;

    fn deref(&self) -> &str {
        &self.value
    }
}

#[derive(Debug)]
pub enum ConstantPoolItem {
    Class(Rc<ClassInfo>),
    FieldOrMethodOrInterfaceMethod(Rc<FieldOrMethodOrInterfaceMethodInfo>),
    String(Rc<StringInfo>),
    IntegerOrFloat { tag: U1, bytes: U1 },
    LongOrDouble {
        tag: U1,
        high_bytes: U4,
        low_bytes: U4,
    },
    NameAndType(Rc<NameAndTypeInfo>),
    Utf8(Rc<Utf8Info>),
    MethodHandle {
        tag: U1,
        reference_kind: U1,
        reference_index: U2,
    },
    MethodType { tag: U1, descriptor_index: U2 },
    InvokeDynamic {
        tag: U1,
        bootstrap_method_attr_index: U2,
        name_and_type_index: U2,
    },
}

impl ConstantPoolItem {
    pub fn from<T: PrimitiveIterator>(iter: &mut T) -> ParserResult<ConstantPoolItem> {
        let tag = try!(iter.next_u1());

        match tag {
            1 => {
                let length = try!(iter.next_u2());

                let mut byte_vec = vec![];
                for _ in 0..length {
                    byte_vec.push(try!(iter.next_u1()));
                }

                let value = try!(String::from_utf8(byte_vec));

                Ok(ConstantPoolItem::Utf8(Rc::new(Utf8Info {
                    tag: tag,
                    length: length,
                    value: value,
                })))
            }
            7 => {
                Ok(ConstantPoolItem::Class(Rc::new(ClassInfo {
                    tag: tag,
                    name_index: try!(iter.next_u2()),
                })))
            }
            8 => {
                Ok(ConstantPoolItem::String(Rc::new(StringInfo {
                    tag: tag,
                    string_index: try!(iter.next_u2()),
                })))
            }
            9 | 10 | 11 => {
                Ok(ConstantPoolItem::FieldOrMethodOrInterfaceMethod(
                        Rc::new(FieldOrMethodOrInterfaceMethodInfo {
                    tag: tag,
                    class_index: try!(iter.next_u2()),
                    name_and_type_index: try!(iter.next_u2()),
                })))
            }
            12 => {
                Ok(ConstantPoolItem::NameAndType(Rc::new(NameAndTypeInfo {
                    tag: tag,
                    name_index: try!(iter.next_u2()),
                    descriptor_index: try!(iter.next_u2()),
                })))
            }
            _ => Err(ParserError::UnknownConstantPoolTag(tag)),
        }
    }

    #[cfg_attr(rustfmt, rustfmt_skip)]
    pub fn to_friendly_name(&self) -> &'static str {
        match self {
            &ConstantPoolItem::Utf8(..) => "Utf8",
            &ConstantPoolItem::Class(..) => "Class",
            &ConstantPoolItem::String(..) => "String",
            &ConstantPoolItem::FieldOrMethodOrInterfaceMethod(..) =>
                "Field|Method|InterfaceMethod",
                &ConstantPoolItem::NameAndType(..) => "NameAndType",
                _ => "Not yet implemented",
        }
    }

    pub fn retrieve_item(index: usize,
                         constant_pool: &Vec<ConstantPoolItem>)
                         -> ParserResult<&ConstantPoolItem> {
        let actual_index = Self::shift_index(index);
        return constant_pool.get(actual_index)
            .ok_or(ParserError::ConstantPoolIndexOutOfBounds(actual_index));
    }

    generate_constant_pool_retrieval_method!(Class, ClassInfo, retrieve_class_info);
    generate_constant_pool_retrieval_method!(Utf8, Utf8Info, retrieve_utf8_info);

    // TODO: Split the enum/struct into seperate variants
    generate_constant_pool_retrieval_method!(FieldOrMethodOrInterfaceMethod,
                                             FieldOrMethodOrInterfaceMethodInfo,
                                             retrieve_field_info);
    generate_constant_pool_retrieval_method!(FieldOrMethodOrInterfaceMethod,
                                             FieldOrMethodOrInterfaceMethodInfo,
                                             retrieve_method_info);
    generate_constant_pool_retrieval_method!(FieldOrMethodOrInterfaceMethod,
                                             FieldOrMethodOrInterfaceMethodInfo,
                                             retrieve_interface_method_info);

    generate_constant_pool_retrieval_method!(String, StringInfo, retrieve_string_info);
    generate_constant_pool_retrieval_method!(NameAndType,
                                             NameAndTypeInfo,
                                             retrieve_name_and_type_info);

    fn shift_index(unshifted_index: usize) -> usize {
        unshifted_index - 1 // references to the constant pool start from one
    }
}

#[derive(Debug)]
pub struct CodeAttribute {
    pub attribute_name: Rc<Utf8Info>,
    pub max_stack: U2,
    pub max_locals: U2,
    pub code_length: U4,
    pub code: Vec<U1>,
    pub exception_table_length: U2,
    pub exception_table: Vec<ExceptionHandler>,
    pub attributes_count: U2,
    pub attributes: Vec<Attribute>,
}

impl CodeAttribute {
    pub fn from<T: PrimitiveIterator>(attribute_name: Rc<Utf8Info>,
                                      iter: &mut T,
                                      constant_pool: &Vec<ConstantPoolItem>)
                                      -> ParserResult<CodeAttribute> {
        let max_stack = try!(iter.next_u2());
        let max_locals = try!(iter.next_u2());

        let code_length = try!(iter.next_u4());
        let mut code = vec![];
        for _ in 0..code_length {
            code.push(try!(iter.next_u1()));
        }

        let exception_table_length = try!(iter.next_u2());
        let mut exception_table = vec![];
        for _ in 0..exception_table_length {
            exception_table.push(try!(ExceptionHandler::from(iter)));
        }

        let attributes_count = try!(iter.next_u2());
        let mut attributes = vec![];
        for _ in 0..attributes_count {
            attributes.push(try!(Attribute::from(iter, constant_pool)));
        }

        Ok(CodeAttribute {
            attribute_name: attribute_name,
            max_stack: max_stack,
            max_locals: max_locals,
            code_length: code_length,
            code: code,
            exception_table_length: exception_table_length,
            exception_table: exception_table,
            attributes_count: attributes_count,
            attributes: attributes,
        })
    }
}

#[derive(Debug)]
pub struct ExceptionHandler {
    pub start_pc: U2,
    pub end_pc: U2,
    pub handler_pc: U2,
    pub catch_type: U2,
}

impl ExceptionHandler {
    pub fn from<T: PrimitiveIterator>(iter: &mut T) -> ParserResult<ExceptionHandler> {
        let start_pc = try!(iter.next_u2());
        let end_pc = try!(iter.next_u2());
        let handler_pc = try!(iter.next_u2());
        let catch_type = try!(iter.next_u2());

        Ok(ExceptionHandler {
            start_pc: start_pc,
            end_pc: end_pc,
            handler_pc: handler_pc,
            catch_type: catch_type,
        })
    }
}

#[derive(Debug)]
pub enum Attribute {
    Code(Rc<CodeAttribute>),
    Unknown {
        attribute_name: Rc<Utf8Info>,
        info: Vec<U1>,
    },
}

impl Attribute {
    pub fn from<T: PrimitiveIterator>(iter: &mut T,
                                      constant_pool: &Vec<ConstantPoolItem>)
                                      -> ParserResult<Attribute> {
        let attribute_name_index = try!(iter.next_u2());
        let attribute_name =
            try!(ConstantPoolItem::retrieve_utf8_info(attribute_name_index as usize,
                                                      constant_pool));

        let attribute_length = try!(iter.next_u4());

        match &**attribute_name {
            "Code" => {
                Ok(Attribute::Code(Rc::new(try!(CodeAttribute::from(attribute_name,
                                                                    iter,
                                                                    constant_pool)))))
            }
            _ => {
                let mut info = vec![];
                for _ in 0..attribute_length {
                    info.push(try!(iter.next_u1()));
                }

                Ok(Attribute::Unknown {
                    attribute_name: attribute_name,
                    info: info,
                })
            }
        }
    }
}

macro_rules! generate_method_or_field_parser_impl {
    ($impl_name:ident) => {
        impl $impl_name {
            pub fn from<T: PrimitiveIterator>(iter: &mut T,
                                              constant_pool: &Vec<ConstantPoolItem>)
                -> ParserResult<$impl_name> {
                    let access_flags = try!(iter.next_u2());

                    let name_index = try!(iter.next_u2());
                    let name = try!(ConstantPoolItem::retrieve_utf8_info(name_index as usize,
                                                                         constant_pool));

                    let descriptor_index = try!(iter.next_u2());
                    let descriptor = try!(ConstantPoolItem::retrieve_utf8_info(
                            descriptor_index as usize,
                            constant_pool));

                    let attributes_count = try!(iter.next_u2());
                    let mut attributes = vec![];
                    for _ in 0..attributes_count {
                        attributes.push(Rc::new(try!(Attribute::from(iter, constant_pool))));
                    }

                    Ok($impl_name {
                        access_flags: access_flags,
                        name: name,
                        descriptor: descriptor,
                        attributes_count: attributes_count,
                        attributes: attributes,
                    })

                }
        }
    }
}

#[derive(Debug)]
pub struct Field {
    pub access_flags: U2,
    pub name: Rc<Utf8Info>,
    pub descriptor: Rc<Utf8Info>,
    pub attributes_count: U2,
    pub attributes: Vec<Rc<Attribute>>,
}

#[derive(Debug)]
pub struct Method {
    pub access_flags: U2,
    pub name: Rc<Utf8Info>,
    pub descriptor: Rc<Utf8Info>,
    pub attributes_count: U2,
    pub attributes: Vec<Rc<Attribute>>,
}

generate_method_or_field_parser_impl!(Field);
generate_method_or_field_parser_impl!(Method);

pub struct AccessFlags;

impl AccessFlags {
    pub fn is_public(access_flags: U2) -> bool {
        (access_flags & 0x0001) != 0
    }

    pub fn is_private(access_flags: U2) -> bool {
        (access_flags & 0x0002) != 0
    }

    pub fn is_protected(access_flags: U2) -> bool {
        (access_flags & 0x0004) != 0
    }

    pub fn is_static(access_flags: U2) -> bool {
        (access_flags & 0x0008) != 0
    }

    pub fn is_final(access_flags: U2) -> bool {
        (access_flags & 0x0010) != 0
    }

    pub fn is_super(access_flags: U2) -> bool {
        (access_flags & 0x0020) != 0
    }

    pub fn is_volatile(access_flags: U2) -> bool {
        (access_flags & 0x0040) != 0
    }

    pub fn is_bridge(access_flags: U2) -> bool {
        (access_flags & 0x0040) != 0
    }

    pub fn is_transient(access_flags: U2) -> bool {
        (access_flags & 0x0080) != 0
    }

    pub fn is_varargs(access_flags: U2) -> bool {
        (access_flags & 0x0080) != 0
    }

    pub fn is_native(access_flags: U2) -> bool {
        (access_flags & 0x0100) != 0
    }

    pub fn is_interface(access_flags: U2) -> bool {
        (access_flags & 0x0200) != 0
    }

    pub fn is_abstract(access_flags: U2) -> bool {
        (access_flags & 0x0400) != 0
    }

    pub fn is_strict(access_flags: U2) -> bool {
        (access_flags & 0x0800) != 0
    }

    pub fn is_synthetic(access_flags: U2) -> bool {
        (access_flags & 0x1000) != 0
    }

    pub fn is_annotation(access_flags: U2) -> bool {
        (access_flags & 0x2000) != 0
    }

    pub fn is_enum(access_flags: U2) -> bool {
        (access_flags & 0x4000) != 0
    }
}
<commit_msg>Split out ConstantPool Field/Method/Interface into seperate variants<commit_after>use super::{ParserError, ParserResult};
use super::primitives::{PrimitiveIterator, U1, U2, U4};

use std::ops::Deref;
use std::rc::Rc;

macro_rules! generate_constant_pool_retrieval_method {
    ($variant_name:ident, $struct_name:ident, $method_name:ident) => {
        pub fn $method_name(index: usize,
                            constant_pool: &Vec<ConstantPoolItem>)
            -> ParserResult<Rc<$struct_name>> {
                let actual_index = ConstantPoolItem::shift_index(index);

                if let Some(item) = constant_pool.get(actual_index) {
                    match item {
                        &ConstantPoolItem::$variant_name(ref val) => return Ok(val.clone()),
                        item @ _ => {
                            let name = item.to_friendly_name();
                            return Err(ParserError::UnexpectedConstantPoolItem(name))
                        }
                    }
                }

                Err(ParserError::ConstantPoolIndexOutOfBounds(actual_index))
            }

    }
}

#[derive(Debug)]
pub struct ClassInfo {
    pub tag: U1,
    pub name_index: U2,
}

#[derive(Debug)]
pub struct FieldOrMethodOrInterfaceMethodInfo {
    pub tag: U1,
    pub class_index: U2,
    pub name_and_type_index: U2,
}

#[derive(Debug)]
pub struct StringInfo {
    pub tag: U1,
    pub string_index: U2,
}

#[derive(Debug)]
pub struct NameAndTypeInfo {
    pub tag: U1,
    pub name_index: U2,
    pub descriptor_index: U2,
}

#[derive(Debug)]
pub struct Utf8Info {
    pub tag: U1,
    pub length: U2,
    pub value: String,
}

impl Deref for Utf8Info {
    type Target = str;

    fn deref(&self) -> &str {
        &self.value
    }
}

#[derive(Debug)]
pub enum ConstantPoolItem {
    Class(Rc<ClassInfo>),
    Field(Rc<FieldOrMethodOrInterfaceMethodInfo>),
    Method(Rc<FieldOrMethodOrInterfaceMethodInfo>),
    InterfaceMethod(Rc<FieldOrMethodOrInterfaceMethodInfo>),
    String(Rc<StringInfo>),
    IntegerOrFloat { tag: U1, bytes: U1 },
    LongOrDouble {
        tag: U1,
        high_bytes: U4,
        low_bytes: U4,
    },
    NameAndType(Rc<NameAndTypeInfo>),
    Utf8(Rc<Utf8Info>),
    MethodHandle {
        tag: U1,
        reference_kind: U1,
        reference_index: U2,
    },
    MethodType { tag: U1, descriptor_index: U2 },
    InvokeDynamic {
        tag: U1,
        bootstrap_method_attr_index: U2,
        name_and_type_index: U2,
    },
}

impl ConstantPoolItem {
    pub fn from<T: PrimitiveIterator>(iter: &mut T) -> ParserResult<ConstantPoolItem> {
        let tag = try!(iter.next_u1());

        match tag {
            1 => {
                let length = try!(iter.next_u2());

                let mut byte_vec = vec![];
                for _ in 0..length {
                    byte_vec.push(try!(iter.next_u1()));
                }

                let value = try!(String::from_utf8(byte_vec));

                Ok(ConstantPoolItem::Utf8(Rc::new(Utf8Info {
                    tag: tag,
                    length: length,
                    value: value,
                })))
            }
            7 => {
                Ok(ConstantPoolItem::Class(Rc::new(ClassInfo {
                    tag: tag,
                    name_index: try!(iter.next_u2()),
                })))
            }
            8 => {
                Ok(ConstantPoolItem::String(Rc::new(StringInfo {
                    tag: tag,
                    string_index: try!(iter.next_u2()),
                })))
            }
            9 => {
                Ok(ConstantPoolItem::Field(Rc::new(FieldOrMethodOrInterfaceMethodInfo {
                    tag: tag,
                    class_index: try!(iter.next_u2()),
                    name_and_type_index: try!(iter.next_u2()),
                })))
            }
            10 => {
                Ok(ConstantPoolItem::Method(Rc::new(FieldOrMethodOrInterfaceMethodInfo {
                    tag: tag,
                    class_index: try!(iter.next_u2()),
                    name_and_type_index: try!(iter.next_u2()),
                })))
            }
            11 => {
                Ok(ConstantPoolItem::InterfaceMethod(Rc::new(FieldOrMethodOrInterfaceMethodInfo {
                    tag: tag,
                    class_index: try!(iter.next_u2()),
                    name_and_type_index: try!(iter.next_u2()),
                })))
            }
            12 => {
                Ok(ConstantPoolItem::NameAndType(Rc::new(NameAndTypeInfo {
                    tag: tag,
                    name_index: try!(iter.next_u2()),
                    descriptor_index: try!(iter.next_u2()),
                })))
            }
            _ => Err(ParserError::UnknownConstantPoolTag(tag)),
        }
    }

    #[cfg_attr(rustfmt, rustfmt_skip)]
    pub fn to_friendly_name(&self) -> &'static str {
        match self {
            &ConstantPoolItem::Utf8(..) => "Utf8",
            &ConstantPoolItem::Class(..) => "Class",
            &ConstantPoolItem::String(..) => "String",
            &ConstantPoolItem::Field(..) => "Field",
            &ConstantPoolItem::Method(..) => "Method",
            &ConstantPoolItem::InterfaceMethod(..) => "InterfaceMethod",
            &ConstantPoolItem::NameAndType(..) => "NameAndType",
            _ => "Not yet implemented",
        }
    }

    pub fn retrieve_item(index: usize,
                         constant_pool: &Vec<ConstantPoolItem>)
                         -> ParserResult<&ConstantPoolItem> {
        let actual_index = Self::shift_index(index);
        return constant_pool.get(actual_index)
            .ok_or(ParserError::ConstantPoolIndexOutOfBounds(actual_index));
    }

    generate_constant_pool_retrieval_method!(Class, ClassInfo, retrieve_class_info);
    generate_constant_pool_retrieval_method!(Utf8, Utf8Info, retrieve_utf8_info);
    generate_constant_pool_retrieval_method!(Field,
                                             FieldOrMethodOrInterfaceMethodInfo,
                                             retrieve_field_info);
    generate_constant_pool_retrieval_method!(Method,
                                             FieldOrMethodOrInterfaceMethodInfo,
                                             retrieve_method_info);
    generate_constant_pool_retrieval_method!(InterfaceMethod,
                                             FieldOrMethodOrInterfaceMethodInfo,
                                             retrieve_interface_method_info);
    generate_constant_pool_retrieval_method!(String, StringInfo, retrieve_string_info);
    generate_constant_pool_retrieval_method!(NameAndType,
                                             NameAndTypeInfo,
                                             retrieve_name_and_type_info);

    fn shift_index(unshifted_index: usize) -> usize {
        unshifted_index - 1 // references to the constant pool start from one
    }
}

#[derive(Debug)]
pub struct CodeAttribute {
    pub max_stack: U2,
    pub max_locals: U2,
    pub code_length: U4,
    pub code: Vec<U1>,
    pub exception_table_length: U2,
    pub exception_table: Vec<ExceptionHandler>,
    pub attributes_count: U2,
    pub attributes: Vec<Attribute>,
}

impl CodeAttribute {
    pub fn from<T: PrimitiveIterator>(iter: &mut T,
                                      constant_pool: &Vec<ConstantPoolItem>)
                                      -> ParserResult<CodeAttribute> {
        let max_stack = try!(iter.next_u2());
        let max_locals = try!(iter.next_u2());

        let code_length = try!(iter.next_u4());
        let mut code = vec![];
        for _ in 0..code_length {
            code.push(try!(iter.next_u1()));
        }

        let exception_table_length = try!(iter.next_u2());
        let mut exception_table = vec![];
        for _ in 0..exception_table_length {
            exception_table.push(try!(ExceptionHandler::from(iter)));
        }

        let attributes_count = try!(iter.next_u2());
        let mut attributes = vec![];
        for _ in 0..attributes_count {
            attributes.push(try!(Attribute::from(iter, constant_pool)));
        }

        Ok(CodeAttribute {
            max_stack: max_stack,
            max_locals: max_locals,
            code_length: code_length,
            code: code,
            exception_table_length: exception_table_length,
            exception_table: exception_table,
            attributes_count: attributes_count,
            attributes: attributes,
        })
    }
}

#[derive(Debug)]
pub struct ExceptionHandler {
    pub start_pc: U2,
    pub end_pc: U2,
    pub handler_pc: U2,
    pub catch_type: U2,
}

impl ExceptionHandler {
    pub fn from<T: PrimitiveIterator>(iter: &mut T) -> ParserResult<ExceptionHandler> {
        let start_pc = try!(iter.next_u2());
        let end_pc = try!(iter.next_u2());
        let handler_pc = try!(iter.next_u2());
        let catch_type = try!(iter.next_u2());

        Ok(ExceptionHandler {
            start_pc: start_pc,
            end_pc: end_pc,
            handler_pc: handler_pc,
            catch_type: catch_type,
        })
    }
}

#[derive(Debug)]
pub enum Attribute {
    Code(Rc<CodeAttribute>),
    Unknown {
        attribute_name: Rc<Utf8Info>,
        info: Vec<U1>,
    },
}

impl Attribute {
    pub fn from<T: PrimitiveIterator>(iter: &mut T,
                                      constant_pool: &Vec<ConstantPoolItem>)
                                      -> ParserResult<Attribute> {
        let attribute_name_index = try!(iter.next_u2());
        let attribute_name =
            try!(ConstantPoolItem::retrieve_utf8_info(attribute_name_index as usize,
                                                      constant_pool));

        let attribute_length = try!(iter.next_u4());

        match &**attribute_name {
            "Code" => Ok(Attribute::Code(Rc::new(try!(CodeAttribute::from(iter, constant_pool))))),
            _ => {
                let mut info = vec![];
                for _ in 0..attribute_length {
                    info.push(try!(iter.next_u1()));
                }

                Ok(Attribute::Unknown {
                    attribute_name: attribute_name,
                    info: info,
                })
            }
        }
    }
}

macro_rules! generate_method_or_field_parser_impl {
    ($impl_name:ident) => {
        impl $impl_name {
            pub fn from<T: PrimitiveIterator>(iter: &mut T,
                                              constant_pool: &Vec<ConstantPoolItem>)
                -> ParserResult<$impl_name> {
                    let access_flags = try!(iter.next_u2());

                    let name_index = try!(iter.next_u2());
                    let name = try!(ConstantPoolItem::retrieve_utf8_info(name_index as usize,
                                                                         constant_pool));

                    let descriptor_index = try!(iter.next_u2());
                    let descriptor = try!(ConstantPoolItem::retrieve_utf8_info(
                            descriptor_index as usize,
                            constant_pool));

                    let attributes_count = try!(iter.next_u2());
                    let mut attributes = vec![];
                    for _ in 0..attributes_count {
                        attributes.push(Rc::new(try!(Attribute::from(iter, constant_pool))));
                    }

                    Ok($impl_name {
                        access_flags: access_flags,
                        name: name,
                        descriptor: descriptor,
                        attributes_count: attributes_count,
                        attributes: attributes,
                    })

                }
        }
    }
}

#[derive(Debug)]
pub struct Field {
    pub access_flags: U2,
    pub name: Rc<Utf8Info>,
    pub descriptor: Rc<Utf8Info>,
    pub attributes_count: U2,
    pub attributes: Vec<Rc<Attribute>>,
}

#[derive(Debug)]
pub struct Method {
    pub access_flags: U2,
    pub name: Rc<Utf8Info>,
    pub descriptor: Rc<Utf8Info>,
    pub attributes_count: U2,
    pub attributes: Vec<Rc<Attribute>>,
}

generate_method_or_field_parser_impl!(Field);
generate_method_or_field_parser_impl!(Method);

pub struct AccessFlags;

impl AccessFlags {
    pub fn is_public(access_flags: U2) -> bool {
        (access_flags & 0x0001) != 0
    }

    pub fn is_private(access_flags: U2) -> bool {
        (access_flags & 0x0002) != 0
    }

    pub fn is_protected(access_flags: U2) -> bool {
        (access_flags & 0x0004) != 0
    }

    pub fn is_static(access_flags: U2) -> bool {
        (access_flags & 0x0008) != 0
    }

    pub fn is_final(access_flags: U2) -> bool {
        (access_flags & 0x0010) != 0
    }

    pub fn is_super(access_flags: U2) -> bool {
        (access_flags & 0x0020) != 0
    }

    pub fn is_volatile(access_flags: U2) -> bool {
        (access_flags & 0x0040) != 0
    }

    pub fn is_bridge(access_flags: U2) -> bool {
        (access_flags & 0x0040) != 0
    }

    pub fn is_transient(access_flags: U2) -> bool {
        (access_flags & 0x0080) != 0
    }

    pub fn is_varargs(access_flags: U2) -> bool {
        (access_flags & 0x0080) != 0
    }

    pub fn is_native(access_flags: U2) -> bool {
        (access_flags & 0x0100) != 0
    }

    pub fn is_interface(access_flags: U2) -> bool {
        (access_flags & 0x0200) != 0
    }

    pub fn is_abstract(access_flags: U2) -> bool {
        (access_flags & 0x0400) != 0
    }

    pub fn is_strict(access_flags: U2) -> bool {
        (access_flags & 0x0800) != 0
    }

    pub fn is_synthetic(access_flags: U2) -> bool {
        (access_flags & 0x1000) != 0
    }

    pub fn is_annotation(access_flags: U2) -> bool {
        (access_flags & 0x2000) != 0
    }

    pub fn is_enum(access_flags: U2) -> bool {
        (access_flags & 0x4000) != 0
    }
}
<|endoftext|>


<commit_before>use crypto::digest::Digest;
use crypto::sha1::Sha1;
use std::iter::repeat;

#[derive(Debug,Eq,PartialEq)]
struct Address {
    data: [u8; 20]
}

impl Address {
    pub fn for_content(content: &str) -> Address {
        let mut hasher = Sha1::new();
        hasher.input_str(content);
        let mut data = [0; 20];
        hasher.result(&mut data);
        Address {
            data: data
        }
    }

    pub fn from_str(string: &str) -> Address {
        use rustc_serialize::hex::FromHex;
        let bytes = string.from_hex().unwrap();
        let mut data = [0u8; 20];
        for (place, byte) in data.iter_mut().zip(bytes.iter()) {
            *place = *byte;
        }
        Address {
            data: data
        }
    }

    pub fn to_str(&self) -> String {
        use rustc_serialize::hex::ToHex;
        self.data.to_hex()
    }
}

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

    #[test]
    fn test_for_content() {
        let address = Address::for_content("some string");
        assert_eq!(address.to_str(), "8b45e4bd1c6acb88bebf6407d16205f567e62a3e");
    }

    #[test]
    fn test_from_str() {
        let address = Address::from_str("8b45e4bd1c6acb88bebf6407d16205f567e62a3e");
        assert_eq!(address.to_str(), "8b45e4bd1c6acb88bebf6407d16205f567e62a3e");
    }

    #[test]
    fn test_equal() {
        let a = Address::from_str("8b45e4bd1c6acb88bebf6407d16205f567e62a3e");
        let b = Address::from_str("8b45e4bd1c6acb88bebf6407d16205f567e62a3e");
        assert_eq!(a, b);
    }

    #[test]
    fn test_not_equal() {
        let a = Address::from_str("8b45e4bd1c6acb88bebf6407d16205f567e62a3e");
        let b = Address::from_str("8b45e4bd1c6acb88bebf6407d16205f567e62a3f");
        assert!(a != b);
    }
}
<commit_msg>Derive Clone, Copy and Hash for Address<commit_after>use crypto::digest::Digest;
use crypto::sha1::Sha1;
use std::iter::repeat;

#[derive(Clone,Copy,Debug,Eq,Hash,PartialEq)]
struct Address {
    data: [u8; 20]
}

impl Address {
    pub fn for_content(content: &str) -> Address {
        let mut hasher = Sha1::new();
        hasher.input_str(content);
        let mut data = [0; 20];
        hasher.result(&mut data);
        Address {
            data: data
        }
    }

    pub fn from_str(string: &str) -> Address {
        use rustc_serialize::hex::FromHex;
        let bytes = string.from_hex().unwrap();
        let mut data = [0u8; 20];
        for (place, byte) in data.iter_mut().zip(bytes.iter()) {
            *place = *byte;
        }
        Address {
            data: data
        }
    }

    pub fn to_str(&self) -> String {
        use rustc_serialize::hex::ToHex;
        self.data.to_hex()
    }
}

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

    #[test]
    fn test_for_content() {
        let address = Address::for_content("some string");
        assert_eq!(address.to_str(), "8b45e4bd1c6acb88bebf6407d16205f567e62a3e");
    }

    #[test]
    fn test_from_str() {
        let address = Address::from_str("8b45e4bd1c6acb88bebf6407d16205f567e62a3e");
        assert_eq!(address.to_str(), "8b45e4bd1c6acb88bebf6407d16205f567e62a3e");
    }

    #[test]
    fn test_equal() {
        let a = Address::from_str("8b45e4bd1c6acb88bebf6407d16205f567e62a3e");
        let b = Address::from_str("8b45e4bd1c6acb88bebf6407d16205f567e62a3e");
        assert_eq!(a, b);
    }

    #[test]
    fn test_not_equal() {
        let a = Address::from_str("8b45e4bd1c6acb88bebf6407d16205f567e62a3e");
        let b = Address::from_str("8b45e4bd1c6acb88bebf6407d16205f567e62a3f");
        assert!(a != b);
    }
}
<|endoftext|>


<commit_before>#![ cfg_attr( not( feature = "use_std" ), no_std ) ]
#![ doc( html_logo_url = "https://raw.githubusercontent.com/Wandalen/wTools/alpha/asset/img/graph_logo_v1_trans.png" ) ]
#![ doc( html_favicon_url = "https://raw.githubusercontent.com/Wandalen/wTools/alpha/asset/img/graph_logo_v1_trans.ico" ) ]
#![ doc( html_root_url = "https://docs.rs/graphs_tools/latest/graphs_tools/" ) ]
#![ warn( rust_2018_idioms ) ]
#![ warn( missing_debug_implementations ) ]
#![ warn( missing_docs ) ]

#![ feature( type_name_of_val ) ]
#![ feature( type_alias_impl_trait ) ]
// #![ feature( trace_macros ) ]

//!
//! Implementation of automata.
//!

#![ doc = include_str!( concat!( env!( "CARGO_MANIFEST_DIR" ), "/Readme.md" ) ) ]

// // xxx : move
//
// pub struct IteratorAdapter< Item >
// {
//   iterator : Box< dyn Iterator< Item = Item > >
// }
//
// impl< Item > core::iter::Iterator
// for IteratorAdapter< Item >
// {
//   type Item = Item;
//   fn next( &mut self ) -> Option< Self::Item >
//   {
//     self.iterator.next()
//   }
// }
//
// trait IntoIteratorAdapter
// where
//   Self : Iterator + 'static,
// {
//   fn into_iter_adapter( self ) -> IteratorAdapter< < Self as Iterator >::Item >
//   where
//     Self : Sized,
//   {
//     let iterator : Box< dyn Iterator< Item = < Self as Iterator >::Item > > = Box::new( self );
//     IteratorAdapter::< < Self as Iterator >::Item > { iterator }
//   }
// }
//
// impl< T > IntoIteratorAdapter for T
// where
//   T : Iterator + 'static,
// {
// }

/// Abstract layer.
#[ cfg( feature = "use_std" ) ]
pub mod abs;
/// Canonical representation.
#[ cfg( feature = "use_std" ) ]
pub mod canonical;
/// Algorithms.
#[ cfg( feature = "use_std" ) ]
pub mod algo;
// /// Matrix representation.
// pub mod matrix;

/// Namespace with dependencies.
pub mod dependency
{
}

/// Exposed namespace of the module.
pub mod exposed
{
  pub use super::prelude::*;
  #[ cfg( feature = "use_std" ) ]
  pub use super::abs::exposed::*;
  pub use super::prelude::*;
  #[ cfg( feature = "use_std" ) ]
  pub use super::algo::exposed::*;
  #[ cfg( feature = "use_std" ) ]
  pub use super::canonical::exposed::*;
  // pub use super::matrix::exposed::*;
}

pub use exposed::*;

/// Prelude to use essentials: `use my_module::prelude::*`.
pub mod prelude
{
  #[ cfg( feature = "use_std" ) ]
  pub use super::abs::prelude::*;
  #[ cfg( feature = "use_std" ) ]
  pub use super::algo::prelude::*;
  #[ cfg( feature = "use_std" ) ]
  pub use super::canonical::prelude::*;
  // pub use super::matrix::prelude::*;
}

// xxx : implement checks
//
// - graph is connected
// - graph is complete
// - graph is isomorphic with another graph
// - graph get regularity degree
// - graph is bipartite
// - graph decomposition on cycles
// - graph decomposition on connected components
//
// - node get open neighbourhood?
// - node get closed neighbourhood?
// - node get degree ( nodes )
// - node get size ( edges )
//
<commit_msg>Fix module `graphs_tools`, comment out unstable features<commit_after>#![ cfg_attr( not( feature = "use_std" ), no_std ) ]
#![ doc( html_logo_url = "https://raw.githubusercontent.com/Wandalen/wTools/alpha/asset/img/graph_logo_v1_trans.png" ) ]
#![ doc( html_favicon_url = "https://raw.githubusercontent.com/Wandalen/wTools/alpha/asset/img/graph_logo_v1_trans.ico" ) ]
#![ doc( html_root_url = "https://docs.rs/graphs_tools/latest/graphs_tools/" ) ]
#![ warn( rust_2018_idioms ) ]
#![ warn( missing_debug_implementations ) ]
#![ warn( missing_docs ) ]

// #![ feature( type_name_of_val ) ]
// #![ feature( type_alias_impl_trait ) ]
// #![ feature( trace_macros ) ]

//!
//! Implementation of automata.
//!

#![ doc = include_str!( concat!( env!( "CARGO_MANIFEST_DIR" ), "/Readme.md" ) ) ]

// // xxx : move
//
// pub struct IteratorAdapter< Item >
// {
//   iterator : Box< dyn Iterator< Item = Item > >
// }
//
// impl< Item > core::iter::Iterator
// for IteratorAdapter< Item >
// {
//   type Item = Item;
//   fn next( &mut self ) -> Option< Self::Item >
//   {
//     self.iterator.next()
//   }
// }
//
// trait IntoIteratorAdapter
// where
//   Self : Iterator + 'static,
// {
//   fn into_iter_adapter( self ) -> IteratorAdapter< < Self as Iterator >::Item >
//   where
//     Self : Sized,
//   {
//     let iterator : Box< dyn Iterator< Item = < Self as Iterator >::Item > > = Box::new( self );
//     IteratorAdapter::< < Self as Iterator >::Item > { iterator }
//   }
// }
//
// impl< T > IntoIteratorAdapter for T
// where
//   T : Iterator + 'static,
// {
// }

/// Abstract layer.
#[ cfg( feature = "use_std" ) ]
pub mod abs;
/// Canonical representation.
#[ cfg( feature = "use_std" ) ]
pub mod canonical;
/// Algorithms.
#[ cfg( feature = "use_std" ) ]
pub mod algo;
// /// Matrix representation.
// pub mod matrix;

/// Namespace with dependencies.
pub mod dependency
{
}

/// Exposed namespace of the module.
pub mod exposed
{
  pub use super::prelude::*;
  #[ cfg( feature = "use_std" ) ]
  pub use super::abs::exposed::*;
  pub use super::prelude::*;
  #[ cfg( feature = "use_std" ) ]
  pub use super::algo::exposed::*;
  #[ cfg( feature = "use_std" ) ]
  pub use super::canonical::exposed::*;
  // pub use super::matrix::exposed::*;
}

pub use exposed::*;

/// Prelude to use essentials: `use my_module::prelude::*`.
pub mod prelude
{
  #[ cfg( feature = "use_std" ) ]
  pub use super::abs::prelude::*;
  #[ cfg( feature = "use_std" ) ]
  pub use super::algo::prelude::*;
  #[ cfg( feature = "use_std" ) ]
  pub use super::canonical::prelude::*;
  // pub use super::matrix::prelude::*;
}

// xxx : implement checks
//
// - graph is connected
// - graph is complete
// - graph is isomorphic with another graph
// - graph get regularity degree
// - graph is bipartite
// - graph decomposition on cycles
// - graph decomposition on connected components
//
// - node get open neighbourhood?
// - node get closed neighbourhood?
// - node get degree ( nodes )
// - node get size ( edges )
//
<|endoftext|>


<commit_before>//! A TCP socket implementation of Hamelin.
#![feature(env, io)]
extern crate hamelin;
extern crate mio;

use std::collections::HashMap;
use std::env::args;
use std::old_io::IoErrorKind::TimedOut;
use hamelin::{BufferedAsyncStream, Hamelin, HamelinGuard};
use mio::{EventLoop, Handler, Interest, IoAcceptor, NonBlock, PollOpt, ReadHint, Token};
use mio::net::SockAddr;
use mio::net::tcp::{TcpSocket, TcpAcceptor};

const SERVER: Token = Token(0);

struct Client {
    stream: BufferedAsyncStream<TcpSocket>,
    guard: HamelinGuard,
}

impl Client {
    fn new(sock: TcpSocket, guard: HamelinGuard) -> Client {
        Client {
            stream: BufferedAsyncStream::new(sock),
            guard: guard
        }
    }

    fn wait(&mut self) -> Result<(), ()> {
        self.guard.wait().map_err(|_| ())
    }

    fn read(&mut self) -> Result<(), ()> {
        match self.stream.read_line() {
            Ok(line) => match self.guard.write_line(&line) {
                Ok(_) => Ok(()),
                Err(ref e) if e.kind == TimedOut => Ok(()),
                Err(_) => Err(()),
            },
            Err(ref e) if e.kind == TimedOut => Ok(()),
            Err(_) => Err(()),
        }
    }

    fn write(&mut self) -> Result<(), ()> {
        match self.guard.read_line() {
            Ok(line) => match self.stream.write_line(&line) {
                Ok(_) => {
                    Ok(())
                },
                Err(ref e) if e.kind == TimedOut => Ok(()),
                Err(_) => Err(()),
            },
            Err(ref e) if e.kind == TimedOut => Ok(()),
            Err(_) => Err(()),
        }
    }
}

struct HamelinHandler {
    server: TcpAcceptor,
    hamelin: Hamelin,
    token_index: usize,
    clients: HashMap<usize, Client>,
}

impl HamelinHandler {
    fn new(server: TcpAcceptor, hamelin: Hamelin) -> HamelinHandler {
        HamelinHandler {
            server: server,
            hamelin: hamelin,
            token_index: 1,
            clients: HashMap::new(),
        }
    }

    fn accept(&mut self, eloop: &mut EventLoop<(), ()>) {
        if let NonBlock::Ready(client) = self.server.accept().unwrap() {
            let token = mio::Token(self.token_index);
            self.token_index += 1;
            eloop.register_opt(&client, token, Interest::all(), PollOpt::level())
                 .ok().expect("Failed to accept new client.");
            self.clients.insert(
                token.as_usize(), Client::new(client, self.hamelin.spawn().unwrap())
            );
            println!("Client connected.");
        }
    }

    fn read(&mut self, token: usize) -> Result<(), ()> {
        let client = &mut self.clients[token];
        let res = client.read();
        res
    }

    fn write(&mut self, token: usize) -> Result<(), ()> {
        if let Some(ref mut client) = self.clients.get_mut(&token) {
            let res = client.write();
            res
        } else {
            Err(())
        }
    }
}

impl Handler<(), ()> for HamelinHandler {
    fn readable(&mut self, eloop: &mut EventLoop<(), ()>, token: Token, _: ReadHint) {
        match token {
            SERVER => self.accept(eloop),
            Token(x) => {
                if let Err(_) = self.read(x) {
                    eloop.deregister(&self.clients[x].stream.stream).unwrap();
                    let _ = self.clients[x].wait();
                    self.clients.remove(&x);
                }
            },
        }
    }

    fn writable(&mut self, _: &mut EventLoop<(), ()>, token: Token) {
        match token {
            SERVER => (),
            Token(x) => {
                let _ = self.write(x);
            }
        }
    }
}

fn main() {
    let args: Vec<_> = args().skip(1).collect();
    if args.len() < 3 {
        println!("Usage: hamelin host port command [args]");
        return;
    }
    let hamelin = Hamelin::new(&args[2], if args.len() > 3 {
        Some(&args[3..])
    } else {
        None
    });
    let addr = SockAddr::parse(&format!("{}:{}", if args[0] == "localhost" { "127.0.0.1" } else
                                        { &args[0] }, args[1])).unwrap();
    let server = TcpSocket::v4().unwrap()
                    .bind(&addr).unwrap()
                    .listen(256).unwrap();
    println!("Server bound on {:?}.", addr);
    let mut eloop = EventLoop::<(), ()>::new().unwrap();
    eloop.register(&server, SERVER).unwrap();
    eloop.run(HamelinHandler::new(server, hamelin)).ok().expect("Failed to execute event loop.");
}
<commit_msg>Updated for latest mio.<commit_after>//! A TCP socket implementation of Hamelin.
#![feature(env, old_io)]
extern crate hamelin;
extern crate mio;

use std::collections::HashMap;
use std::env::args;
use std::old_io::IoErrorKind::TimedOut;
use hamelin::{BufferedAsyncStream, Hamelin, HamelinGuard};
use mio::{EventLoop, Handler, Interest, IoAcceptor, NonBlock, PollOpt, ReadHint, Token};
use mio::net::SockAddr;
use mio::net::tcp::{TcpSocket, TcpAcceptor};

const SERVER: Token = Token(0);

struct Client {
    stream: BufferedAsyncStream<TcpSocket>,
    guard: HamelinGuard,
}

impl Client {
    fn new(sock: TcpSocket, guard: HamelinGuard) -> Client {
        Client {
            stream: BufferedAsyncStream::new(sock),
            guard: guard
        }
    }

    fn wait(&mut self) -> Result<(), ()> {
        self.guard.wait().map_err(|_| ())
    }

    fn read(&mut self) -> Result<(), ()> {
        match self.stream.read_line() {
            Ok(line) => match self.guard.write_line(&line) {
                Ok(_) => Ok(()),
                Err(ref e) if e.kind == TimedOut => Ok(()),
                Err(_) => Err(()),
            },
            Err(ref e) if e.kind == TimedOut => Ok(()),
            Err(_) => Err(()),
        }
    }

    fn write(&mut self) -> Result<(), ()> {
        match self.guard.read_line() {
            Ok(line) => match self.stream.write_line(&line) {
                Ok(_) => {
                    Ok(())
                },
                Err(ref e) if e.kind == TimedOut => Ok(()),
                Err(_) => Err(()),
            },
            Err(ref e) if e.kind == TimedOut => Ok(()),
            Err(_) => Err(()),
        }
    }
}

struct HamelinHandler {
    server: TcpAcceptor,
    hamelin: Hamelin,
    token_index: usize,
    clients: HashMap<usize, Client>,
}

impl HamelinHandler {
    fn new(server: TcpAcceptor, hamelin: Hamelin) -> HamelinHandler {
        HamelinHandler {
            server: server,
            hamelin: hamelin,
            token_index: 1,
            clients: HashMap::new(),
        }
    }

    fn accept(&mut self, eloop: &mut EventLoop<(), ()>) {
        if let NonBlock::Ready(client) = self.server.accept().unwrap() {
            let token = mio::Token(self.token_index);
            self.token_index += 1;
            eloop.register_opt(&client, token, Interest::all(), PollOpt::level())
                 .ok().expect("Failed to accept new client.");
            self.clients.insert(
                token.as_usize(), Client::new(client, self.hamelin.spawn().unwrap())
            );
            println!("Client connected.");
        }
    }

    fn read(&mut self, token: usize) -> Result<(), ()> {
        let client = &mut self.clients[token];
        let res = client.read();
        res
    }

    fn write(&mut self, token: usize) -> Result<(), ()> {
        if let Some(ref mut client) = self.clients.get_mut(&token) {
            let res = client.write();
            res
        } else {
            Err(())
        }
    }
}

impl Handler<(), ()> for HamelinHandler {
    fn readable(&mut self, eloop: &mut EventLoop<(), ()>, token: Token, _: ReadHint) {
        match token {
            SERVER => self.accept(eloop),
            Token(x) => {
                if let Err(_) = self.read(x) {
                    eloop.deregister(&self.clients[x].stream.stream).unwrap();
                    let _ = self.clients[x].wait();
                    self.clients.remove(&x);
                }
            },
        }
    }

    fn writable(&mut self, _: &mut EventLoop<(), ()>, token: Token) {
        match token {
            SERVER => (),
            Token(x) => {
                let _ = self.write(x);
            }
        }
    }
}

fn main() {
    let args: Vec<_> = args().skip(1).collect();
    if args.len() < 3 {
        println!("Usage: hamelin host port command [args]");
        return;
    }
    let hamelin = Hamelin::new(&args[2], if args.len() > 3 {
        Some(&args[3..])
    } else {
        None
    });
    let addr = SockAddr::parse(&format!("{}:{}", if args[0] == "localhost" { "127.0.0.1" } else
                                        { &*args[0] }, args[1])).unwrap();
    let server = TcpSocket::v4().unwrap()
                    .bind(&addr).unwrap()
                    .listen(256).unwrap();
    println!("Server bound on {:?}.", addr);
    let mut eloop = EventLoop::<(), ()>::new().unwrap();
    eloop.register(&server, SERVER).unwrap();
    let mut handler = HamelinHandler::new(server, hamelin);
    eloop.run(&mut handler).ok().expect("Failed to execute event loop.");
}
<|endoftext|>


<commit_before>use std::env;

use cargo::ops;
use cargo::util::{CliResult, Config};

#[derive(RustcDecodable)]
pub struct Options {
    flag_verbose: u32,
    flag_quiet: Option<bool>,
    flag_color: Option<String>,
    flag_bin: bool,
    flag_lib: bool,
    arg_path: String,
    flag_name: Option<String>,
    flag_vcs: Option<ops::VersionControl>,
    flag_frozen: bool,
    flag_locked: bool,
}

pub const USAGE: &'static str = "
Create a new cargo package at <path>

Usage:
    cargo new [options] <path>
    cargo new -h | --help

Options:
    -h, --help          Print this message
    --vcs VCS           Initialize a new repository for the given version
                        control system (git or hg) or do not initialize any version
                        control at all (none) overriding a global configuration.
    --bin               Use a binary (application) template
    --lib               Use a library template
    --name NAME         Set the resulting package name
    -v, --verbose ...   Use verbose output (-vv very verbose/build.rs output)
    -q, --quiet         No output printed to stdout
    --color WHEN        Coloring: auto, always, never
    --frozen            Require Cargo.lock and cache are up to date
    --locked            Require Cargo.lock is up to date
";

pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
    debug!("executing; cmd=cargo-new; args={:?}", env::args().collect::<Vec<_>>());
    config.configure(options.flag_verbose,
                     options.flag_quiet,
                     &options.flag_color,
                     options.flag_frozen,
                     options.flag_locked)?;

    let Options { flag_bin, flag_lib, arg_path, flag_name, flag_vcs, .. } = options;

    let opts = ops::NewOptions::new(flag_vcs,
                                    flag_bin,
                                    flag_lib,
                                    &arg_path,
                                    flag_name.as_ref().map(|s| s.as_ref()));

    let opts_lib = opts.lib;
    ops::new(opts, config)?;

    config.shell().status("Created", format!("{} `{}` project",
                                             if opts_lib { "library" }
                                             else {"binary (application)"},
                                             arg_path))?;

    Ok(None)
}

<commit_msg>Update new command help doc<commit_after>use std::env;

use cargo::ops;
use cargo::util::{CliResult, Config};

#[derive(RustcDecodable)]
pub struct Options {
    flag_verbose: u32,
    flag_quiet: Option<bool>,
    flag_color: Option<String>,
    flag_bin: bool,
    flag_lib: bool,
    arg_path: String,
    flag_name: Option<String>,
    flag_vcs: Option<ops::VersionControl>,
    flag_frozen: bool,
    flag_locked: bool,
}

pub const USAGE: &'static str = "
Create a new cargo package at <path>

Usage:
    cargo new [options] <path>
    cargo new -h | --help

Options:
    -h, --help          Print this message
    --vcs VCS           Initialize a new repository for the given version
                        control system (git or hg) or do not initialize any version
                        control at all (none) overriding a global configuration.
    --bin               Use a binary (application) template
    --lib               Use a library template
    --name NAME         Set the resulting package name, defaults to the value of <path>
    -v, --verbose ...   Use verbose output (-vv very verbose/build.rs output)
    -q, --quiet         No output printed to stdout
    --color WHEN        Coloring: auto, always, never
    --frozen            Require Cargo.lock and cache are up to date
    --locked            Require Cargo.lock is up to date
";

pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
    debug!("executing; cmd=cargo-new; args={:?}", env::args().collect::<Vec<_>>());
    config.configure(options.flag_verbose,
                     options.flag_quiet,
                     &options.flag_color,
                     options.flag_frozen,
                     options.flag_locked)?;

    let Options { flag_bin, flag_lib, arg_path, flag_name, flag_vcs, .. } = options;

    let opts = ops::NewOptions::new(flag_vcs,
                                    flag_bin,
                                    flag_lib,
                                    &arg_path,
                                    flag_name.as_ref().map(|s| s.as_ref()));

    let opts_lib = opts.lib;
    ops::new(opts, config)?;

    config.shell().status("Created", format!("{} `{}` project",
                                             if opts_lib { "library" }
                                             else {"binary (application)"},
                                             arg_path))?;

    Ok(None)
}

<|endoftext|>


<commit_before>//#![deny(warnings)]

extern crate coreutils;

use coreutils::ArgParser;
use std::{process, env};
use std::io::{self, Read, Write};

const MAN_PAGE: &'static str = /* @MANSTART{tee} */ r#"
NAME
    tee - read from standard input and write to standard output and files

SYNOPSIS
    tee [OPTION]... [FILE]...

DESCRIPTION
    Copy standard input to each FILE, and also to standard output.

    -a, --append
        append to given FILEs, do not overwrite

    --help display this help and exit

AUTHOR
    Written by Stefan Lücke.
"#; /* @MANEND */

fn main() {
    let mut parser = ArgParser::new(2).
        add_flag(&["a", "append"]).
        add_flag(&["h", "help"]);
    parser.parse(env::args());

    let mut stdout = io::stdout();

    if parser.found("help") {
        stdout.write_all(MAN_PAGE.as_bytes()).unwrap();
        stdout.flush().unwrap();
        process::exit(0);
    }

    let mut fds: Vec<std::fs::File> = Vec::with_capacity(env::args().len());

    if parser.found("append") {
        let args = env::args().skip(2);
        if args.len() > 0 {
            for arg in args {
               let fd = std::fs::OpenOptions::new().append(true).open(arg);
               match fd {
                   Ok(f) => fds.push(f),
                   Err(e) => println!("Err(e): {}", e),
               }
            }
        }
    } else {
        let args = env::args().skip(1);
        if args.len() > 0 {
            for arg in args {
               let fd = std::fs::OpenOptions::new().write(true).create(true).open(arg);
               match fd {
                   Ok(f) => fds.push(f),
                   Err(e) => println!("Err(e): {}", e),
               }
            }
        }
    }

    let stdintemp = io::stdin();
    let mut stdin = stdintemp.lock();
    let mut buffer: &mut [u8] = &mut[0 as u8; 4096];
    'programmloop: loop {
        let result_read = stdin.read(buffer);
        match result_read {
            Ok(size) => {
                if size == 0 {
                    // we've read a EOF here
                    break;
                }

                let result_write = stdout.write(&mut buffer[0..size]);
                    match result_write {
                        Ok(_) => (),
                        Err(e) => {
                            println!("Err(e): {}", e);
                            break 'programmloop;
                        },
                    };

                // iterate over open files
                'writeloop: for mut f in &mut fds {
                    let result_write = f.write(&mut buffer[0..size]);
                    match result_write {
                        Ok(_) => (),
                        Err(e) => {
                            println!("Err(e): {}", e);
                            break 'programmloop;
                        },
                    };
                }

            },
            Err(e) => {
                println!("Err(e): {}", e);
                break;
            },
        };
    }

    stdout.flush().unwrap();
    process::exit(0);
}
<commit_msg>Create file in tee append<commit_after>//#![deny(warnings)]

extern crate coreutils;

use coreutils::ArgParser;
use std::{process, env};
use std::io::{self, Read, Write};

const MAN_PAGE: &'static str = /* @MANSTART{tee} */ r#"
NAME
    tee - read from standard input and write to standard output and files

SYNOPSIS
    tee [OPTION]... [FILE]...

DESCRIPTION
    Copy standard input to each FILE, and also to standard output.

    -a, --append
        append to given FILEs, do not overwrite

    --help display this help and exit

AUTHOR
    Written by Stefan Lücke.
"#; /* @MANEND */

fn main() {
    let mut parser = ArgParser::new(2).
        add_flag(&["a", "append"]).
        add_flag(&["h", "help"]);
    parser.parse(env::args());

    let mut stdout = io::stdout();

    if parser.found("help") {
        stdout.write_all(MAN_PAGE.as_bytes()).unwrap();
        stdout.flush().unwrap();
        process::exit(0);
    }

    let mut fds: Vec<std::fs::File> = Vec::with_capacity(env::args().len());

    if parser.found("append") {
        let args = env::args().skip(2);
        if args.len() > 0 {
            for arg in args {
               let fd = std::fs::OpenOptions::new().append(true).create(true).open(arg);
               match fd {
                   Ok(f) => fds.push(f),
                   Err(e) => println!("Err(e): {}", e),
               }
            }
        }
    } else {
        let args = env::args().skip(1);
        if args.len() > 0 {
            for arg in args {
               let fd = std::fs::OpenOptions::new().write(true).create(true).open(arg);
               match fd {
                   Ok(f) => fds.push(f),
                   Err(e) => println!("Err(e): {}", e),
               }
            }
        }
    }

    let stdintemp = io::stdin();
    let mut stdin = stdintemp.lock();
    let mut buffer: &mut [u8] = &mut[0 as u8; 4096];
    'programmloop: loop {
        let result_read = stdin.read(buffer);
        match result_read {
            Ok(size) => {
                if size == 0 {
                    // we've read a EOF here
                    break;
                }

                let result_write = stdout.write(&mut buffer[0..size]);
                    match result_write {
                        Ok(_) => (),
                        Err(e) => {
                            println!("Err(e): {}", e);
                            break 'programmloop;
                        },
                    };

                // iterate over open files
                'writeloop: for mut f in &mut fds {
                    let result_write = f.write(&mut buffer[0..size]);
                    match result_write {
                        Ok(_) => (),
                        Err(e) => {
                            println!("Err(e): {}", e);
                            break 'programmloop;
                        },
                    };
                }

            },
            Err(e) => {
                println!("Err(e): {}", e);
                break;
            },
        };
    }

    stdout.flush().unwrap();
    process::exit(0);
}
<|endoftext|>