<commit_before>use std;
use std::error::Error;
use std::borrow::Cow;
use std::collections::HashMap;
use std::io::Read;
use hyper;
use hyper::header::{Authorization, Scheme};
use hyper::method::Method;
use time;
use rand::{self, Rng};
use crypto::hmac::Hmac;
use crypto::mac::Mac;
use crypto::sha1::Sha1;
use rustc_serialize::base64::{self, ToBase64};
use super::{percent_encode, add_param, ParamList, links, error};

///Basic component of the OAuth authorization header. Intended to be combined
///with hyper's `Authorization` struct to create a full request header.
#[derive(Clone, Debug)]
struct TwitterOAuth {
    consumer_key: String,
    nonce: String,
    signature: Option<String>,
    timestamp: i64,
    token: Option<String>,
    callback: Option<String>,
    verifier: Option<String>,
}

impl std::str::FromStr for TwitterOAuth {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut consumer_key: Option<String> = None;
        let mut nonce: Option<String> = None;
        let mut signature: Option<String> = None;
        let mut timestamp: Option<i64> = None;
        let mut token: Option<String> = None;
        let mut callback: Option<String> = None;
        let mut verifier: Option<String> = None;

        for substr in s.split(',') {
            let mut parts = substr.trim().split('=');
            match parts.next() {
                Some("oauth_consumer_key") => consumer_key = parts.next().map(str::to_string),
                Some("oauth_nonce") => nonce = parts.next().map(str::to_string),
                Some("oauth_signature") => signature = parts.next().map(str::to_string),
                Some("oauth_timestamp") => match parts.next().map(i64::from_str) {
                    Some(Ok(n)) => timestamp = Some(n),
                    Some(Err(e)) => return Err(e.description().to_string()),
                    None => timestamp = None,
                },
                Some("oauth_token") => token = parts.next().map(str::to_string),
                Some("oauth_callback") => callback = parts.next().map(str::to_string),
                Some("oauth_verifier") => verifier = parts.next().map(str::to_string),
                Some(_) => return Err("unexpected OAuth Authorization header field".to_string()),
                None => return Err("unexpected header format".to_string()),
            }
        }

        Ok(TwitterOAuth {
            consumer_key: try!(consumer_key.ok_or("no oauth_consumer_key")),
            nonce: try!(nonce.ok_or("no oauth_nonce")),
            signature: signature,
            timestamp: try!(timestamp.ok_or("no oauth_timestamp")),
            token: token,
            callback: callback,
            verifier: verifier,
        })
    }
}

impl Scheme for TwitterOAuth {
    fn scheme() -> Option<&'static str> {
        Some("OAuth")
    }

    fn fmt_scheme(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        try!(write!(f, "oauth_consumer_key=\"{}\"", percent_encode(&self.consumer_key)));

        try!(write!(f, ", oauth_nonce=\"{}\"", percent_encode(&self.nonce)));

        if let Some(ref signature) = self.signature {
            try!(write!(f, ", oauth_signature=\"{}\"", percent_encode(signature)));
        }

        try!(write!(f, ", oauth_signature_method=\"{}\"", percent_encode("HMAC-SHA1")));

        try!(write!(f, ", oauth_timestamp=\"{}\"", self.timestamp));

        if let Some(ref token) = self.token {
            try!(write!(f, ", oauth_token=\"{}\"", percent_encode(token)));
        }

        try!(write!(f, ", oauth_version=\"{}\"", "1.0"));

        if let Some(ref callback) = self.callback {
            try!(write!(f, ", oauth_callback=\"{}\"", percent_encode(callback)));
        }

        if let Some(ref verifier) = self.verifier {
            try!(write!(f, ", oauth_verifier=\"{}\"", percent_encode(verifier)));
        }

        Ok(())
    }
}

pub struct Token<'a> {
    key: Cow<'a, str>,
    secret: Cow<'a, str>,
}

impl<'a> Token<'a> {
    pub fn new<K, S>(key: K, secret: S) -> Token<'a>
        where K: Into<Cow<'a, str>>,
              S: Into<Cow<'a, str>>
    {
        Token {
            key: key.into(),
            secret: secret.into(),
        }
    }
}

fn sign(header: TwitterOAuth,
        method: Method,
        uri: &str,
        params: Option<&ParamList>,
        con_token: &Token,
        access_token: Option<&Token>) -> TwitterOAuth {
    let query_string = {
        let mut sig_params = params.map(|p| p.clone()).unwrap_or(HashMap::new());

        add_param(&mut sig_params, "oauth_consumer_key", header.consumer_key.as_str());
        add_param(&mut sig_params, "oauth_nonce", header.nonce.as_str());
        add_param(&mut sig_params, "oauth_signature_method", "HMAC-SHA1");
        add_param(&mut sig_params, "oauth_timestamp", format!("{}", header.timestamp));
        add_param(&mut sig_params, "oauth_version", "1.0");

        if let Some(ref token) = header.token {
            add_param(&mut sig_params, "oauth_token", token.as_str());
        }

        if let Some(ref callback) = header.callback {
            add_param(&mut sig_params, "oauth_callback", callback.as_str());
        }

        if let Some(ref verifier) = header.verifier {
            add_param(&mut sig_params, "oauth_verifier", verifier.as_str());
        }

        let mut query = sig_params.iter()
                                  .map(|(k, v)| format!("{}={}", percent_encode(k), percent_encode(v)))
                                  .collect::<Vec<_>>();
        query.sort();

        query.join("&")
    };

    let base_str = format!("{}&{}&{}",
                           percent_encode(method.as_ref()),
                           percent_encode(uri),
                           percent_encode(&query_string));
    let key = format!("{}&{}",
                      percent_encode(&con_token.secret),
                      percent_encode(&access_token.unwrap_or(&Token::new("", "")).secret));

    let mut sig = Hmac::new(Sha1::new(), key.as_bytes());
    sig.input(base_str.as_bytes());

    let config = base64::Config {
        char_set: base64::CharacterSet::Standard,
        newline: base64::Newline::LF,
        pad: true,
        line_length: None,
    };

    TwitterOAuth {
        consumer_key: header.consumer_key,
        nonce: header.nonce,
        signature: Some(sig.result().code().to_base64(config)),
        timestamp: header.timestamp,
        token: header.token,
        callback: header.callback,
        verifier: header.verifier,
    }
}

fn get_header(method: Method,
              uri: &str,
              con_token: &Token,
              access_token: Option<&Token>,
              callback: Option<String>,
              verifier: Option<String>,
              params: Option<&ParamList>) -> TwitterOAuth {
    let header = TwitterOAuth {
        consumer_key: con_token.key.to_string(),
        nonce: rand::thread_rng().gen_ascii_chars().take(32).collect::<String>(),
        signature: None,
        timestamp: time::now_utc().to_timespec().sec,
        token: access_token.map(|tok| tok.key.to_string()),
        callback: callback,
        verifier: verifier,
    };

    sign(header, method, uri, params, con_token, access_token)
}

pub fn request_token<S: Into<String>>(con_token: &Token, callback: S) -> Result<Token<'static>, error::Error> {
    let header = get_header(Method::Post, links::auth::REQUEST_TOKEN,
                            con_token, None, Some(callback.into()), None, None);

    let client = hyper::Client::new();
    let mut resp = try!(client.post(links::auth::REQUEST_TOKEN)
                              .header(Authorization(header))
                              .send());

    let mut full_resp = String::new();
    try!(resp.read_to_string(&mut full_resp));

    let mut key: Option<String> = None;
    let mut secret: Option<String> = None;

    for elem in full_resp.split('&') {
        let mut kv = elem.splitn(2, '=');
        match kv.next() {
            Some("oauth_token") => key = kv.next().map(|s| s.to_string()),
            Some("oauth_token_secret") => secret = kv.next().map(|s| s.to_string()),
            Some(_) => (),
            None => return Err(error::Error::InvalidResponse),
        }
    }

    Ok(Token::new(try!(key.ok_or(error::Error::MissingValue("oauth_token"))),
                  try!(secret.ok_or(error::Error::MissingValue("oauth_token_secret")))))
}

pub fn authorize_url(request_token: &Token) -> String {
    format!("{}?oauth_token={}", links::auth::AUTHORIZE, request_token.key)
}

pub fn access_token<S: Into<String>>(con_token: &Token,
                                     request_token: &Token,
                                     verifier: S) -> Result<(Token<'static>, i64, String), error::Error> {
    let header = get_header(Method::Post, links::auth::ACCESS_TOKEN,
                            con_token, Some(request_token), None, Some(verifier.into()), None);

    let client = hyper::Client::new();
    let mut resp = try!(client.post(links::auth::ACCESS_TOKEN)
                              .header(Authorization(header))
                              .send());

    let mut full_resp = String::new();
    try!(resp.read_to_string(&mut full_resp));

    let mut key: Option<String> = None;
    let mut secret: Option<String> = None;
    let mut id: Option<i64> = None;
    let mut username: Option<String> = None;

    for elem in full_resp.split('&') {
        let mut kv = elem.splitn(2, '=');
        match kv.next() {
            Some("oauth_token") => key = kv.next().map(|s| s.to_string()),
            Some("oauth_token_secret") => secret = kv.next().map(|s| s.to_string()),
            Some("user_id") => id = kv.next().and_then(|s| i64::from_str_radix(s, 10).ok()),
            Some("screen_name") => username = kv.next().map(|s| s.to_string()),
            Some(_) => (),
            None => return Err(error::Error::InvalidResponse),
        }
    }

    Ok((Token::new(try!(key.ok_or(error::Error::MissingValue("oauth_token"))),
                  try!(secret.ok_or(error::Error::MissingValue("oauth_token_secret")))),
        try!(id.ok_or(error::Error::MissingValue("user_id"))),
        try!(username.ok_or(error::Error::MissingValue("screen_name")))))
}
<commit_msg>add documentation comments<commit_after>use std;
use std::error::Error;
use std::borrow::Cow;
use std::collections::HashMap;
use std::io::Read;
use hyper;
use hyper::header::{Authorization, Scheme};
use hyper::method::Method;
use time;
use rand::{self, Rng};
use crypto::hmac::Hmac;
use crypto::mac::Mac;
use crypto::sha1::Sha1;
use rustc_serialize::base64::{self, ToBase64};
use super::{percent_encode, add_param, ParamList, links, error};

///OAuth header set given to Twitter calls.
///
///Since different authorization/authentication calls have various parameters
///that go into this header, they're optionally placed at the end of this header.
///On the other hand, `signature` is optional so a structured header can be
///passed to `sign()` for signature.
#[derive(Clone, Debug)]
struct TwitterOAuth {
    consumer_key: String,
    nonce: String,
    signature: Option<String>,
    timestamp: i64,
    token: Option<String>,
    callback: Option<String>,
    verifier: Option<String>,
}

impl std::str::FromStr for TwitterOAuth {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut consumer_key: Option<String> = None;
        let mut nonce: Option<String> = None;
        let mut signature: Option<String> = None;
        let mut timestamp: Option<i64> = None;
        let mut token: Option<String> = None;
        let mut callback: Option<String> = None;
        let mut verifier: Option<String> = None;

        for substr in s.split(',') {
            let mut parts = substr.trim().split('=');
            match parts.next() {
                Some("oauth_consumer_key") => consumer_key = parts.next().map(str::to_string),
                Some("oauth_nonce") => nonce = parts.next().map(str::to_string),
                Some("oauth_signature") => signature = parts.next().map(str::to_string),
                Some("oauth_timestamp") => match parts.next().map(i64::from_str) {
                    Some(Ok(n)) => timestamp = Some(n),
                    Some(Err(e)) => return Err(e.description().to_string()),
                    None => timestamp = None,
                },
                Some("oauth_token") => token = parts.next().map(str::to_string),
                Some("oauth_callback") => callback = parts.next().map(str::to_string),
                Some("oauth_verifier") => verifier = parts.next().map(str::to_string),
                Some(_) => return Err("unexpected OAuth Authorization header field".to_string()),
                None => return Err("unexpected header format".to_string()),
            }
        }

        Ok(TwitterOAuth {
            consumer_key: try!(consumer_key.ok_or("no oauth_consumer_key")),
            nonce: try!(nonce.ok_or("no oauth_nonce")),
            signature: signature,
            timestamp: try!(timestamp.ok_or("no oauth_timestamp")),
            token: token,
            callback: callback,
            verifier: verifier,
        })
    }
}

impl Scheme for TwitterOAuth {
    fn scheme() -> Option<&'static str> {
        Some("OAuth")
    }

    fn fmt_scheme(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        try!(write!(f, "oauth_consumer_key=\"{}\"", percent_encode(&self.consumer_key)));

        try!(write!(f, ", oauth_nonce=\"{}\"", percent_encode(&self.nonce)));

        if let Some(ref signature) = self.signature {
            try!(write!(f, ", oauth_signature=\"{}\"", percent_encode(signature)));
        }

        try!(write!(f, ", oauth_signature_method=\"{}\"", percent_encode("HMAC-SHA1")));

        try!(write!(f, ", oauth_timestamp=\"{}\"", self.timestamp));

        if let Some(ref token) = self.token {
            try!(write!(f, ", oauth_token=\"{}\"", percent_encode(token)));
        }

        try!(write!(f, ", oauth_version=\"{}\"", "1.0"));

        if let Some(ref callback) = self.callback {
            try!(write!(f, ", oauth_callback=\"{}\"", percent_encode(callback)));
        }

        if let Some(ref verifier) = self.verifier {
            try!(write!(f, ", oauth_verifier=\"{}\"", percent_encode(verifier)));
        }

        Ok(())
    }
}

///A key/secret pair representing an OAuth token.
pub struct Token<'a> {
    key: Cow<'a, str>,
    secret: Cow<'a, str>,
}

impl<'a> Token<'a> {
    ///Creates a Token with the given key and secret.
    ///
    ///This can be called with either `&str` or `String`. In the former
    ///case the resulting Token will have the same lifetime as the given
    ///reference. If two Strings are given, the Token effectively has
    ///lifetime `'static`.
    pub fn new<K, S>(key: K, secret: S) -> Token<'a>
        where K: Into<Cow<'a, str>>,
              S: Into<Cow<'a, str>>
    {
        Token {
            key: key.into(),
            secret: secret.into(),
        }
    }
}

///With the given OAuth header and method parameters, create an OAuth
///signature and return the header with the signature in line.
fn sign(header: TwitterOAuth,
        method: Method,
        uri: &str,
        params: Option<&ParamList>,
        con_token: &Token,
        access_token: Option<&Token>) -> TwitterOAuth {
    let query_string = {
        let mut sig_params = params.map(|p| p.clone()).unwrap_or(HashMap::new());

        add_param(&mut sig_params, "oauth_consumer_key", header.consumer_key.as_str());
        add_param(&mut sig_params, "oauth_nonce", header.nonce.as_str());
        add_param(&mut sig_params, "oauth_signature_method", "HMAC-SHA1");
        add_param(&mut sig_params, "oauth_timestamp", format!("{}", header.timestamp));
        add_param(&mut sig_params, "oauth_version", "1.0");

        if let Some(ref token) = header.token {
            add_param(&mut sig_params, "oauth_token", token.as_str());
        }

        if let Some(ref callback) = header.callback {
            add_param(&mut sig_params, "oauth_callback", callback.as_str());
        }

        if let Some(ref verifier) = header.verifier {
            add_param(&mut sig_params, "oauth_verifier", verifier.as_str());
        }

        let mut query = sig_params.iter()
                                  .map(|(k, v)| format!("{}={}", percent_encode(k), percent_encode(v)))
                                  .collect::<Vec<_>>();
        query.sort();

        query.join("&")
    };

    let base_str = format!("{}&{}&{}",
                           percent_encode(method.as_ref()),
                           percent_encode(uri),
                           percent_encode(&query_string));
    let key = format!("{}&{}",
                      percent_encode(&con_token.secret),
                      percent_encode(&access_token.unwrap_or(&Token::new("", "")).secret));

    let mut sig = Hmac::new(Sha1::new(), key.as_bytes());
    sig.input(base_str.as_bytes());

    let config = base64::Config {
        char_set: base64::CharacterSet::Standard,
        newline: base64::Newline::LF,
        pad: true,
        line_length: None,
    };

    TwitterOAuth {
        consumer_key: header.consumer_key,
        nonce: header.nonce,
        signature: Some(sig.result().code().to_base64(config)),
        timestamp: header.timestamp,
        token: header.token,
        callback: header.callback,
        verifier: header.verifier,
    }
}

///With the given method parameters, return a signed OAuth header.
fn get_header(method: Method,
              uri: &str,
              con_token: &Token,
              access_token: Option<&Token>,
              callback: Option<String>,
              verifier: Option<String>,
              params: Option<&ParamList>) -> TwitterOAuth {
    let header = TwitterOAuth {
        consumer_key: con_token.key.to_string(),
        nonce: rand::thread_rng().gen_ascii_chars().take(32).collect::<String>(),
        signature: None,
        timestamp: time::now_utc().to_timespec().sec,
        token: access_token.map(|tok| tok.key.to_string()),
        callback: callback,
        verifier: verifier,
    };

    sign(header, method, uri, params, con_token, access_token)
}

///With the given consumer Token, ask Twitter for a request Token that can be
///used to request access to the user's account.
///
///This can be considered Step 1 in obtaining access to a user's account. With
///this Token, a web-based application can use `authenticate_url` (currently
///unimplemented), and a desktop-based application can use `authorize_url` to
///perform the authorization request.
///
///The parameter `callback` is used to provide an OAuth Callback URL for a web-
///or mobile-based application to receive the results of the authorization request.
///To use the PIN-Based Auth request, this must be set to `"oob"`. The resulting
///Token can be passed to `authorize_url` to give the user a means to accept the
///request.
pub fn request_token<S: Into<String>>(con_token: &Token, callback: S) -> Result<Token<'static>, error::Error> {
    let header = get_header(Method::Post, links::auth::REQUEST_TOKEN,
                            con_token, None, Some(callback.into()), None, None);

    let client = hyper::Client::new();
    let mut resp = try!(client.post(links::auth::REQUEST_TOKEN)
                              .header(Authorization(header))
                              .send());

    let mut full_resp = String::new();
    try!(resp.read_to_string(&mut full_resp));

    let mut key: Option<String> = None;
    let mut secret: Option<String> = None;

    for elem in full_resp.split('&') {
        let mut kv = elem.splitn(2, '=');
        match kv.next() {
            Some("oauth_token") => key = kv.next().map(|s| s.to_string()),
            Some("oauth_token_secret") => secret = kv.next().map(|s| s.to_string()),
            Some(_) => (),
            None => return Err(error::Error::InvalidResponse),
        }
    }

    Ok(Token::new(try!(key.ok_or(error::Error::MissingValue("oauth_token"))),
                  try!(secret.ok_or(error::Error::MissingValue("oauth_token_secret")))))
}

///With the given request Token, return a URL that a user can access to
///accept or reject an authorization request.
///
///This can be considered Step 2 in obtaining access to a user's account.
///Using PIN-Based Auth, give the URL that this function returns to the
///user so they can process the authorization request. They will receive
///a PIN in return, that can be given as the Verifier to `access_token`.
pub fn authorize_url(request_token: &Token) -> String {
    format!("{}?oauth_token={}", links::auth::AUTHORIZE, request_token.key)
}

///With the given OAuth tokens and verifier, ask Twitter for an access
///Token that can be used to sign further requests to the Twitter API.
///
///This can be considered Step 3 in obtaining access to a user's account.
///The Token this function returns represents the user's authorization
///that your app can use their account, and needs to be given to all other
///functions in the Twitter API.
///
///The OAuth Verifier this function takes is either given as a result of
///the OAuth Callback given to `request_token`, or the PIN given to the
///user as a result of their access of the `authorize_url`.
///
///This function also returns the User ID and Username of the authenticated
///user.
pub fn access_token<S: Into<String>>(con_token: &Token,
                                     request_token: &Token,
                                     verifier: S) -> Result<(Token<'static>, i64, String), error::Error> {
    let header = get_header(Method::Post, links::auth::ACCESS_TOKEN,
                            con_token, Some(request_token), None, Some(verifier.into()), None);

    let client = hyper::Client::new();
    let mut resp = try!(client.post(links::auth::ACCESS_TOKEN)
                              .header(Authorization(header))
                              .send());

    let mut full_resp = String::new();
    try!(resp.read_to_string(&mut full_resp));

    let mut key: Option<String> = None;
    let mut secret: Option<String> = None;
    let mut id: Option<i64> = None;
    let mut username: Option<String> = None;

    for elem in full_resp.split('&') {
        let mut kv = elem.splitn(2, '=');
        match kv.next() {
            Some("oauth_token") => key = kv.next().map(|s| s.to_string()),
            Some("oauth_token_secret") => secret = kv.next().map(|s| s.to_string()),
            Some("user_id") => id = kv.next().and_then(|s| i64::from_str_radix(s, 10).ok()),
            Some("screen_name") => username = kv.next().map(|s| s.to_string()),
            Some(_) => (),
            None => return Err(error::Error::InvalidResponse),
        }
    }

    Ok((Token::new(try!(key.ok_or(error::Error::MissingValue("oauth_token"))),
                  try!(secret.ok_or(error::Error::MissingValue("oauth_token_secret")))),
        try!(id.ok_or(error::Error::MissingValue("user_id"))),
        try!(username.ok_or(error::Error::MissingValue("screen_name")))))
}
<|endoftext|>


<commit_before>use std::io::{Read, Seek, SeekFrom};
use std::{mem, ptr};

use Result;

pub trait Band {
    fn position(&mut self) -> Result<u64>;
    fn read_i16(&mut self) -> Result<i16>;
    fn read_i64(&mut self) -> Result<i64>;
    fn read_u16(&mut self) -> Result<u16>;
    fn read_u32(&mut self) -> Result<u32>;
    fn seek(&mut self, u64) -> Result<u64>;
}

#[cfg(target_endian = "big")]
macro_rules! convert(
    ($data:ident) => ();
);

#[cfg(target_endian = "little")]
macro_rules! convert(
    ($data:ident) => ($data.reverse());
);

macro_rules! read(
    ($this:ident, $count:expr) => (unsafe {
        let mut buffer: [u8; $count] = mem::uninitialized();
        if try!($this.read(&mut buffer)) != $count {
            return raise!("failed to read as much as needed");
        }
        convert!(buffer);
        Ok(ptr::read(buffer.as_ptr() as *const _))
    });
);

impl<T> Band for T where T: Read + Seek {
    fn read_i16(&mut self) -> Result<i16> {
        read!(self, 2)
    }

    fn read_u16(&mut self) -> Result<u16> {
        read!(self, 2)
    }

    fn read_u32(&mut self) -> Result<u32> {
        read!(self, 4)
    }

    fn read_i64(&mut self) -> Result<i64> {
        read!(self, 8)
    }

    #[inline]
    fn seek(&mut self, position: u64) -> Result<u64> {
        Seek::seek(self, SeekFrom::Start(position))
    }

    #[inline]
    fn position(&mut self) -> Result<u64> {
        Seek::seek(self, SeekFrom::Current(0))
    }
}
<commit_msg>Clarify the job of convert<commit_after>use std::io::{Read, Seek, SeekFrom};
use std::{mem, ptr};

use Result;

pub trait Band {
    fn position(&mut self) -> Result<u64>;
    fn read_i16(&mut self) -> Result<i16>;
    fn read_i64(&mut self) -> Result<i64>;
    fn read_u16(&mut self) -> Result<u16>;
    fn read_u32(&mut self) -> Result<u32>;
    fn seek(&mut self, u64) -> Result<u64>;
}

#[cfg(target_endian = "big")]
macro_rules! big_endian_to_target(
    ($data:ident) => ();
);

#[cfg(target_endian = "little")]
macro_rules! big_endian_to_target(
    ($data:ident) => ($data.reverse());
);

macro_rules! read(
    ($this:ident, $count:expr) => (unsafe {
        let mut buffer: [u8; $count] = mem::uninitialized();
        if try!($this.read(&mut buffer)) != $count {
            return raise!("failed to read as much as needed");
        }
        big_endian_to_target!(buffer);
        Ok(ptr::read(buffer.as_ptr() as *const _))
    });
);

impl<T> Band for T where T: Read + Seek {
    fn read_i16(&mut self) -> Result<i16> {
        read!(self, 2)
    }

    fn read_u16(&mut self) -> Result<u16> {
        read!(self, 2)
    }

    fn read_u32(&mut self) -> Result<u32> {
        read!(self, 4)
    }

    fn read_i64(&mut self) -> Result<i64> {
        read!(self, 8)
    }

    #[inline]
    fn seek(&mut self, position: u64) -> Result<u64> {
        Seek::seek(self, SeekFrom::Start(position))
    }

    #[inline]
    fn position(&mut self) -> Result<u64> {
        Seek::seek(self, SeekFrom::Current(0))
    }
}
<|endoftext|>


<commit_before>use std::fmt;

use Table as TomlTable;
use Value::{mod, String, Integer, Float, Boolean, Datetime, Array, Table};

struct Printer<'a, 'b:'a> {
    output: &'a mut fmt::Formatter<'b>,
    stack: Vec<&'a str>,
}

impl fmt::Show for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            String(ref s) => {
                try!(write!(f, "\""));
                for ch in s.as_slice().chars() {
                    match ch {
                        '\u{8}' => try!(write!(f, "\\b")),
                        '\u{9}' => try!(write!(f, "\\t")),
                        '\u{a}' => try!(write!(f, "\\n")),
                        '\u{c}' => try!(write!(f, "\\f")),
                        '\u{d}' => try!(write!(f, "\\r")),
                        '\u{22}' => try!(write!(f, "\\\"")),
                        '\u{5c}' => try!(write!(f, "\\\\")),
                        ch => try!(write!(f, "{}", ch)),
                    }
                }
                write!(f, "\"")
            }
            Integer(i) => write!(f, "{}", i),
            Float(fp) => {
                try!(write!(f, "{}", fp));
                if fp % 1.0 == 0.0 { try!(write!(f, ".0")) }
                Ok(())
            }
            Boolean(b) => write!(f, "{}", b),
            Datetime(ref s) => write!(f, "{}", s),
            Array(ref a) => {
                match a.as_slice().head() {
                   Some(&Table(..)) =>
                       try!(write!(f, "invalid toml array of tables")),
                   _ => {}
                }
                write!(f, "{}", a)
            }
            Table(ref t) => {
                let mut p = Printer { output: f, stack: Vec::new() };
                p.print(t)
            }
        }
    }
}

impl<'a, 'b> Printer<'a, 'b> {
    fn print(&mut self, table: &'a TomlTable) -> fmt::Result {
        for (k, v) in table.iter() {
            match *v {
                Table(..) => continue,
                Array(ref a) => {
                    match a.as_slice().head() {
                        Some(&Table(..)) => continue,
                        _ => {}
                    }
                }
                _ => {}
            }
            try!(writeln!(self.output, "{} = {}", k, v));
        }
        for (k, v) in table.iter() {
            match *v {
                Table(ref inner) => {
                    self.stack.push(k.as_slice());
                    try!(writeln!(self.output, "\n[{}]",
                                  self.stack.connect(".")));
                    try!(self.print(inner));
                    self.stack.pop();
                }
                Array(ref inner) => {
                    match inner.as_slice().head() {
                        Some(&Table(..)) => {}
                        _ => continue
                    }
                    self.stack.push(k.as_slice());
                    for inner in inner.iter() {
                        try!(writeln!(self.output, "\n[[{}]]",
                                      self.stack.connect(".")));
                        match *inner {
                            Table(ref inner) => try!(self.print(inner)),
                            _ => panic!("non-heterogeneous toml array"),
                        }
                    }
                    self.stack.pop();
                }
                _ => {},
            }
        }
        Ok(())
    }
}

#[cfg(test)]
#[allow(warnings)]
mod tests {
    use Value;
    use Value::{String, Integer, Float, Boolean, Datetime, Array, Table};
    use std::collections::TreeMap;

    macro_rules! map( ($($k:expr: $v:expr),*) => ({
        let mut _m = TreeMap::new();
        $(_m.insert($k.to_string(), $v);)*
        _m
    }) );

    #[test]
    fn simple_show() {
        assert_eq!(String("foo".to_string()).to_string().as_slice(),
                   "\"foo\"");
        assert_eq!(Integer(10).to_string().as_slice(),
                   "10");
        assert_eq!(Float(10.0).to_string().as_slice(),
                   "10.0");
        assert_eq!(Float(2.4).to_string().as_slice(),
                   "2.4");
        assert_eq!(Boolean(true).to_string().as_slice(),
                   "true");
        assert_eq!(Datetime("test".to_string()).to_string().as_slice(),
                   "test");
        assert_eq!(Array(vec![]).to_string().as_slice(),
                   "[]");
        assert_eq!(Array(vec![Integer(1), Integer(2)]).to_string().as_slice(),
                   "[1, 2]");
    }

    #[test]
    fn table() {
        assert_eq!(Table(map! { }).to_string().as_slice(),
                   "");
        assert_eq!(Table(map! { "test": Integer(2) }).to_string().as_slice(),
                   "test = 2\n");
        assert_eq!(Table(map! {
                        "test": Integer(2),
                        "test2": Table(map! {
                            "test": String("wut".to_string())
                        })
                   }).to_string().as_slice(),
                   "test = 2\n\
                    \n\
                    [test2]\n\
                    test = \"wut\"\n");
        assert_eq!(Table(map! {
                        "test": Integer(2),
                        "test2": Table(map! {
                            "test": String("wut".to_string())
                        })
                   }).to_string().as_slice(),
                   "test = 2\n\
                    \n\
                    [test2]\n\
                    test = \"wut\"\n");
        assert_eq!(Table(map! {
                        "test": Integer(2),
                        "test2": Array(vec![Table(map! {
                            "test": String("wut".to_string())
                        })])
                   }).to_string().as_slice(),
                   "test = 2\n\
                    \n\
                    [[test2]]\n\
                    test = \"wut\"\n");
    }
}
<commit_msg>Remove weird 'invalid toml array of tables' printing<commit_after>use std::fmt;

use Table as TomlTable;
use Value::{mod, String, Integer, Float, Boolean, Datetime, Array, Table};

struct Printer<'a, 'b:'a> {
    output: &'a mut fmt::Formatter<'b>,
    stack: Vec<&'a str>,
}

impl fmt::Show for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            String(ref s) => {
                try!(write!(f, "\""));
                for ch in s.as_slice().chars() {
                    match ch {
                        '\u{8}' => try!(write!(f, "\\b")),
                        '\u{9}' => try!(write!(f, "\\t")),
                        '\u{a}' => try!(write!(f, "\\n")),
                        '\u{c}' => try!(write!(f, "\\f")),
                        '\u{d}' => try!(write!(f, "\\r")),
                        '\u{22}' => try!(write!(f, "\\\"")),
                        '\u{5c}' => try!(write!(f, "\\\\")),
                        ch => try!(write!(f, "{}", ch)),
                    }
                }
                write!(f, "\"")
            }
            Integer(i) => write!(f, "{}", i),
            Float(fp) => {
                try!(write!(f, "{}", fp));
                if fp % 1.0 == 0.0 { try!(write!(f, ".0")) }
                Ok(())
            }
            Boolean(b) => write!(f, "{}", b),
            Datetime(ref s) => write!(f, "{}", s),
            Table(ref t) => {
                let mut p = Printer { output: f, stack: Vec::new() };
                p.print(t)
            }
            Array(ref a) => write!(f, "{}", a),
        }
    }
}

impl<'a, 'b> Printer<'a, 'b> {
    fn print(&mut self, table: &'a TomlTable) -> fmt::Result {
        for (k, v) in table.iter() {
            match *v {
                Table(..) => continue,
                Array(ref a) => {
                    match a.as_slice().head() {
                        Some(&Table(..)) => continue,
                        _ => {}
                    }
                }
                _ => {}
            }
            try!(writeln!(self.output, "{} = {}", k, v));
        }
        for (k, v) in table.iter() {
            match *v {
                Table(ref inner) => {
                    self.stack.push(k.as_slice());
                    try!(writeln!(self.output, "\n[{}]",
                                  self.stack.connect(".")));
                    try!(self.print(inner));
                    self.stack.pop();
                }
                Array(ref inner) => {
                    match inner.as_slice().head() {
                        Some(&Table(..)) => {}
                        _ => continue
                    }
                    self.stack.push(k.as_slice());
                    for inner in inner.iter() {
                        try!(writeln!(self.output, "\n[[{}]]",
                                      self.stack.connect(".")));
                        match *inner {
                            Table(ref inner) => try!(self.print(inner)),
                            _ => panic!("non-heterogeneous toml array"),
                        }
                    }
                    self.stack.pop();
                }
                _ => {},
            }
        }
        Ok(())
    }
}

#[cfg(test)]
#[allow(warnings)]
mod tests {
    use Value;
    use Value::{String, Integer, Float, Boolean, Datetime, Array, Table};
    use std::collections::TreeMap;

    macro_rules! map( ($($k:expr: $v:expr),*) => ({
        let mut _m = TreeMap::new();
        $(_m.insert($k.to_string(), $v);)*
        _m
    }) );

    #[test]
    fn simple_show() {
        assert_eq!(String("foo".to_string()).to_string().as_slice(),
                   "\"foo\"");
        assert_eq!(Integer(10).to_string().as_slice(),
                   "10");
        assert_eq!(Float(10.0).to_string().as_slice(),
                   "10.0");
        assert_eq!(Float(2.4).to_string().as_slice(),
                   "2.4");
        assert_eq!(Boolean(true).to_string().as_slice(),
                   "true");
        assert_eq!(Datetime("test".to_string()).to_string().as_slice(),
                   "test");
        assert_eq!(Array(vec![]).to_string().as_slice(),
                   "[]");
        assert_eq!(Array(vec![Integer(1), Integer(2)]).to_string().as_slice(),
                   "[1, 2]");
    }

    #[test]
    fn table() {
        assert_eq!(Table(map! { }).to_string().as_slice(),
                   "");
        assert_eq!(Table(map! { "test": Integer(2) }).to_string().as_slice(),
                   "test = 2\n");
        assert_eq!(Table(map! {
                        "test": Integer(2),
                        "test2": Table(map! {
                            "test": String("wut".to_string())
                        })
                   }).to_string().as_slice(),
                   "test = 2\n\
                    \n\
                    [test2]\n\
                    test = \"wut\"\n");
        assert_eq!(Table(map! {
                        "test": Integer(2),
                        "test2": Table(map! {
                            "test": String("wut".to_string())
                        })
                   }).to_string().as_slice(),
                   "test = 2\n\
                    \n\
                    [test2]\n\
                    test = \"wut\"\n");
        assert_eq!(Table(map! {
                        "test": Integer(2),
                        "test2": Array(vec![Table(map! {
                            "test": String("wut".to_string())
                        })])
                   }).to_string().as_slice(),
                   "test = 2\n\
                    \n\
                    [[test2]]\n\
                    test = \"wut\"\n");
    }
}
<|endoftext|>


<commit_before>//! Bit level parsers and combinators
//!
//! Bit parsing is handled by tweaking the input in most macros.
//! In byte level parsing, the input is generally a `&[u8]` passed from combinator
//! to combinator until the slices are manipulated.
//!
//! Bit parsers take a `(&[u8], usize)` as input. The first part of the tuple is an byte slice,
//! the second part is a bit offset in the first byte of the slice.
//!
//! By passing a pair like this, we can leverage most of the combinators, and avoid
//! transforming the whole slice to a vector of booleans. This should make it easy
//! to see a byte slice as a bit stream, and parse code points of arbitrary bit length.

/// `bits!( parser ) => ( &[u8], (&[u8], usize) -> IResult<(&[u8], usize), T> ) -> IResult<&[u8], T>`
/// transforms its byte slice input in a bit stream for the underlying parsers
///
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::IResult::Done;
/// # fn main() {
///  named!( take_3_bits<u8>, bits!( take_bits!( u8, 3 ) ) );
///
///  let input = vec![0b10101010, 0b11110000, 0b00110011];
///  let sl    = &input[..];
///
///  assert_eq!(take_3_bits( sl ), Done(&sl[1..], 5) );
/// # }
#[macro_export]
macro_rules! bits (
  ($i:expr, $submac:ident!( $($args:tt)* )) => (
    bits_impl!($i, $submac!($($args)*));
  );
  ($i:expr, $f:expr, $g:expr) => (
    bits_impl!($i, call!($f));
  );
);

/// Internal parser, do not use directly
#[macro_export]
macro_rules! bits_impl (
  ($i:expr, $submac:ident!( $($args:tt)* )) => (
    {
      let input = ($i, 0usize);
      match $submac!(input, $($args)*) {
        $crate::IResult::Error(e)                            => {
          let err = match e {
            $crate::Err::Code(k) | $crate::Err::Node(k, _) | $crate::Err::Position(k, _) | $crate::Err::NodePosition(k, _, _) => {
              $crate::Err::Position(k, $i)
            }
          };
          $crate::IResult::Error(err)
        }
        $crate::IResult::Incomplete($crate::Needed::Unknown) => $crate::IResult::Incomplete($crate::Needed::Unknown),
        $crate::IResult::Incomplete($crate::Needed::Size(i)) => $crate::IResult::Incomplete($crate::Needed::Size(i)),
        $crate::IResult::Done((i, bit_index), o)             => {
          let byte_index = if bit_index == 0 { 0 } else { 1 };

          $crate::IResult::Done(&i[byte_index..], o)
        }
      }
    }
  );
);

/// `take_bits!(type, nb) => ( (&[T], usize), U, usize) -> IResult<(&[T], usize), U>`
/// generates a parser consuming the specified number of bytes
///
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::IResult::Done;
/// # fn main() {
///  named!( take_pair<(u8, u8)>, bits!( pair!( take_bits!( u8, 3 ), take_bits!(u8, 5) ) ) );
///
///  let input = vec![0b10101010, 0b11110000, 0b00110011];
///  let sl    = &input[..];
///
///  assert_eq!(take_pair( sl ),       Done(&sl[1..], (5, 10)) );
///  assert_eq!(take_pair( &sl[1..] ), Done(&sl[2..], (7, 16)) );
/// # }
/// ```
#[macro_export]
macro_rules! take_bits (
  ($i:expr, $t:ty, $count:expr) => (
    {
      use std::ops::Div;
      let (input, bit_offset) = $i;
      let res : $crate::IResult<(&[u8],usize), $t> = if $count == 0 {
        $crate::IResult::Done( (input, bit_offset), 0)
      } else {
        let cnt = ($count as usize + bit_offset).div(8);
        if input.len() * 8 < $count as usize + bit_offset {
          $crate::IResult::Incomplete($crate::Needed::Size(cnt+1))
        } else {
          let mut acc:$t            = 0;
          let mut offset: usize     = bit_offset;
          let mut remaining: usize  = $count;
          let mut end_offset: usize = 0;

          for it in 0..cnt+1 {
            if remaining == 0 {
              break;
            }
            let val: $t = if offset == 0 {
              input[it] as $t
            } else {
              ((input[it] << offset) as u8 >> offset) as $t
            };

            if remaining < 8 - offset {
              acc += val >> (8 - offset - remaining);
              end_offset = remaining + offset;
              break;
            } else {
              acc += val << remaining - (8 - offset);
              remaining -= 8 - offset;
              offset = 0;
            }
          }
          $crate::IResult::Done( (&input[cnt..], end_offset) , acc)
        }
      };
      res
    }
  );
);

#[macro_export]
macro_rules! tag_bits (
  ($i:expr, $t:ty, $count:expr, $p: pat) => (
    {
      match take_bits!($i, $t, $count) {
        $crate::IResult::Incomplete(i) => $crate::IResult::Incomplete(i),
        $crate::IResult::Done(i, o)    => {
          if let $p = o {
            let res: $crate::IResult<(&[u8],usize),$t> = $crate::IResult::Done(i, o);
            res
          } else {
            $crate::IResult::Error($crate::Err::Code($crate::ErrorKind::TagBits))
          }
        },
        _                              => {
          $crate::IResult::Error($crate::Err::Code($crate::ErrorKind::TagBits))
        }
      }
    }
  )
);

#[cfg(test)]
mod tests {
  use internal::{IResult,Needed};

  #[test]
  fn take_bits() {
    let input = vec![0b10101010, 0b11110000, 0b00110011];
    let sl    = &input[..];

    assert_eq!(take_bits!( (sl, 0), u8,   0 ), IResult::Done((sl, 0), 0));
    assert_eq!(take_bits!( (sl, 0), u8,   8 ), IResult::Done((&sl[1..], 0), 170));
    assert_eq!(take_bits!( (sl, 0), u8,   3 ), IResult::Done((&sl[0..], 3), 5));
    assert_eq!(take_bits!( (sl, 0), u8,   6 ), IResult::Done((&sl[0..], 6), 42));
    assert_eq!(take_bits!( (sl, 1), u8,   1 ), IResult::Done((&sl[0..], 2), 0));
    assert_eq!(take_bits!( (sl, 1), u8,   2 ), IResult::Done((&sl[0..], 3), 1));
    assert_eq!(take_bits!( (sl, 1), u8,   3 ), IResult::Done((&sl[0..], 4), 2));
    assert_eq!(take_bits!( (sl, 6), u8,   3 ), IResult::Done((&sl[1..], 1), 5));
    assert_eq!(take_bits!( (sl, 0), u16, 10 ), IResult::Done((&sl[1..], 2), 683));
    assert_eq!(take_bits!( (sl, 0), u16,  8 ), IResult::Done((&sl[1..], 0), 170));
    assert_eq!(take_bits!( (sl, 6), u16, 10 ), IResult::Done((&sl[2..], 0), 752));
    assert_eq!(take_bits!( (sl, 6), u16, 11 ), IResult::Done((&sl[2..], 1), 1504));
    assert_eq!(take_bits!( (sl, 0), u32, 20 ), IResult::Done((&sl[2..], 4), 700163));
    assert_eq!(take_bits!( (sl, 4), u32, 20 ), IResult::Done((&sl[3..], 0), 716851));
    assert_eq!(take_bits!( (sl, 4), u32, 22 ), IResult::Incomplete(Needed::Size(4)));
  }

  #[test]
  fn tag_bits() {
    let input = vec![0b10101010, 0b11110000, 0b00110011];
    let sl    = &input[..];

    assert_eq!(tag_bits!( (sl, 0), u8,   3, 0b101), IResult::Done((&sl[0..], 3), 5));
    assert_eq!(tag_bits!( (sl, 0), u8,   4, 0b1010), IResult::Done((&sl[0..], 4), 10));
  }
}
<commit_msg>Fix bits! argument parsing<commit_after>//! Bit level parsers and combinators
//!
//! Bit parsing is handled by tweaking the input in most macros.
//! In byte level parsing, the input is generally a `&[u8]` passed from combinator
//! to combinator until the slices are manipulated.
//!
//! Bit parsers take a `(&[u8], usize)` as input. The first part of the tuple is an byte slice,
//! the second part is a bit offset in the first byte of the slice.
//!
//! By passing a pair like this, we can leverage most of the combinators, and avoid
//! transforming the whole slice to a vector of booleans. This should make it easy
//! to see a byte slice as a bit stream, and parse code points of arbitrary bit length.

/// `bits!( parser ) => ( &[u8], (&[u8], usize) -> IResult<(&[u8], usize), T> ) -> IResult<&[u8], T>`
/// transforms its byte slice input in a bit stream for the underlying parsers
///
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::IResult::Done;
/// # fn main() {
///  named!( take_3_bits<u8>, bits!( take_bits!( u8, 3 ) ) );
///
///  let input = vec![0b10101010, 0b11110000, 0b00110011];
///  let sl    = &input[..];
///
///  assert_eq!(take_3_bits( sl ), Done(&sl[1..], 5) );
/// # }
#[macro_export]
macro_rules! bits (
  ($i:expr, $submac:ident!( $($args:tt)* )) => (
    bits_impl!($i, $submac!($($args)*));
  );
  ($i:expr, $f:expr) => (
    bits_impl!($i, call!($f));
  );
);

/// Internal parser, do not use directly
#[macro_export]
macro_rules! bits_impl (
  ($i:expr, $submac:ident!( $($args:tt)* )) => (
    {
      let input = ($i, 0usize);
      match $submac!(input, $($args)*) {
        $crate::IResult::Error(e)                            => {
          let err = match e {
            $crate::Err::Code(k) | $crate::Err::Node(k, _) | $crate::Err::Position(k, _) | $crate::Err::NodePosition(k, _, _) => {
              $crate::Err::Position(k, $i)
            }
          };
          $crate::IResult::Error(err)
        }
        $crate::IResult::Incomplete($crate::Needed::Unknown) => $crate::IResult::Incomplete($crate::Needed::Unknown),
        $crate::IResult::Incomplete($crate::Needed::Size(i)) => $crate::IResult::Incomplete($crate::Needed::Size(i)),
        $crate::IResult::Done((i, bit_index), o)             => {
          let byte_index = if bit_index == 0 { 0 } else { 1 };

          $crate::IResult::Done(&i[byte_index..], o)
        }
      }
    }
  );
);

/// `take_bits!(type, nb) => ( (&[T], usize), U, usize) -> IResult<(&[T], usize), U>`
/// generates a parser consuming the specified number of bytes
///
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::IResult::Done;
/// # fn main() {
///  named!( take_pair<(u8, u8)>, bits!( pair!( take_bits!( u8, 3 ), take_bits!(u8, 5) ) ) );
///
///  let input = vec![0b10101010, 0b11110000, 0b00110011];
///  let sl    = &input[..];
///
///  assert_eq!(take_pair( sl ),       Done(&sl[1..], (5, 10)) );
///  assert_eq!(take_pair( &sl[1..] ), Done(&sl[2..], (7, 16)) );
/// # }
/// ```
#[macro_export]
macro_rules! take_bits (
  ($i:expr, $t:ty, $count:expr) => (
    {
      use std::ops::Div;
      let (input, bit_offset) = $i;
      let res : $crate::IResult<(&[u8],usize), $t> = if $count == 0 {
        $crate::IResult::Done( (input, bit_offset), 0)
      } else {
        let cnt = ($count as usize + bit_offset).div(8);
        if input.len() * 8 < $count as usize + bit_offset {
          $crate::IResult::Incomplete($crate::Needed::Size(cnt+1))
        } else {
          let mut acc:$t            = 0;
          let mut offset: usize     = bit_offset;
          let mut remaining: usize  = $count;
          let mut end_offset: usize = 0;

          for it in 0..cnt+1 {
            if remaining == 0 {
              break;
            }
            let val: $t = if offset == 0 {
              input[it] as $t
            } else {
              ((input[it] << offset) as u8 >> offset) as $t
            };

            if remaining < 8 - offset {
              acc += val >> (8 - offset - remaining);
              end_offset = remaining + offset;
              break;
            } else {
              acc += val << remaining - (8 - offset);
              remaining -= 8 - offset;
              offset = 0;
            }
          }
          $crate::IResult::Done( (&input[cnt..], end_offset) , acc)
        }
      };
      res
    }
  );
);

#[macro_export]
macro_rules! tag_bits (
  ($i:expr, $t:ty, $count:expr, $p: pat) => (
    {
      match take_bits!($i, $t, $count) {
        $crate::IResult::Incomplete(i) => $crate::IResult::Incomplete(i),
        $crate::IResult::Done(i, o)    => {
          if let $p = o {
            let res: $crate::IResult<(&[u8],usize),$t> = $crate::IResult::Done(i, o);
            res
          } else {
            $crate::IResult::Error($crate::Err::Code($crate::ErrorKind::TagBits))
          }
        },
        _                              => {
          $crate::IResult::Error($crate::Err::Code($crate::ErrorKind::TagBits))
        }
      }
    }
  )
);

#[cfg(test)]
mod tests {
  use internal::{IResult,Needed};

  #[test]
  fn take_bits() {
    let input = vec![0b10101010, 0b11110000, 0b00110011];
    let sl    = &input[..];

    assert_eq!(take_bits!( (sl, 0), u8,   0 ), IResult::Done((sl, 0), 0));
    assert_eq!(take_bits!( (sl, 0), u8,   8 ), IResult::Done((&sl[1..], 0), 170));
    assert_eq!(take_bits!( (sl, 0), u8,   3 ), IResult::Done((&sl[0..], 3), 5));
    assert_eq!(take_bits!( (sl, 0), u8,   6 ), IResult::Done((&sl[0..], 6), 42));
    assert_eq!(take_bits!( (sl, 1), u8,   1 ), IResult::Done((&sl[0..], 2), 0));
    assert_eq!(take_bits!( (sl, 1), u8,   2 ), IResult::Done((&sl[0..], 3), 1));
    assert_eq!(take_bits!( (sl, 1), u8,   3 ), IResult::Done((&sl[0..], 4), 2));
    assert_eq!(take_bits!( (sl, 6), u8,   3 ), IResult::Done((&sl[1..], 1), 5));
    assert_eq!(take_bits!( (sl, 0), u16, 10 ), IResult::Done((&sl[1..], 2), 683));
    assert_eq!(take_bits!( (sl, 0), u16,  8 ), IResult::Done((&sl[1..], 0), 170));
    assert_eq!(take_bits!( (sl, 6), u16, 10 ), IResult::Done((&sl[2..], 0), 752));
    assert_eq!(take_bits!( (sl, 6), u16, 11 ), IResult::Done((&sl[2..], 1), 1504));
    assert_eq!(take_bits!( (sl, 0), u32, 20 ), IResult::Done((&sl[2..], 4), 700163));
    assert_eq!(take_bits!( (sl, 4), u32, 20 ), IResult::Done((&sl[3..], 0), 716851));
    assert_eq!(take_bits!( (sl, 4), u32, 22 ), IResult::Incomplete(Needed::Size(4)));
  }

  #[test]
  fn tag_bits() {
    let input = vec![0b10101010, 0b11110000, 0b00110011];
    let sl    = &input[..];

    assert_eq!(tag_bits!( (sl, 0), u8,   3, 0b101), IResult::Done((&sl[0..], 3), 5));
    assert_eq!(tag_bits!( (sl, 0), u8,   4, 0b1010), IResult::Done((&sl[0..], 4), 10));
  }
}
<|endoftext|>


<commit_before>//! Filters, Approximate Membership Queries (AMQs).

pub mod bloomfilter;
pub mod cuckoofilter;
pub mod quotientfilter;

use std::hash::Hash;

/// A filter is a set-like data structure, that keeps track of elements it has seen without
/// the need to store them. Looking up values has a certain false positive rate, but a false
/// negative rate of 0%.
///
/// This kind of lookup is also referred to as Approximate Membership Queries (AMQs).
pub trait Filter {
    /// Error type that may occur during insertion.
    type InsertErr;

    /// Clear state of the filter, so that it behaves like a fresh one.
    fn clear(&mut self);

    /// Insert new element into the filter.
    ///
    /// The method may return an error under certain conditions. When this happens, the
    /// user-visible state is not altered, i.e. the element was not added to the filter. The
    /// internal state may have changed though.
    fn insert<T>(&mut self, obj: &T) -> Result<(), Self::InsertErr>
    where
        T: Hash;

    /// Check if filters is empty, i.e. contains no elements.
    fn is_empty(&self) -> bool;

    /// Return guessed number of elements in the filter.
    fn len(&self) -> usize;

    /// Guess if the given element was added to the filter.
    fn query<T>(&self, obj: &T) -> bool
    where
        T: Hash;
}
<commit_msg>filters: InsertErr must impl fmt::Debug<commit_after>//! Filters, Approximate Membership Queries (AMQs).

pub mod bloomfilter;
pub mod cuckoofilter;
pub mod quotientfilter;

use std::fmt::Debug;
use std::hash::Hash;

/// A filter is a set-like data structure, that keeps track of elements it has seen without
/// the need to store them. Looking up values has a certain false positive rate, but a false
/// negative rate of 0%.
///
/// This kind of lookup is also referred to as Approximate Membership Queries (AMQs).
pub trait Filter {
    /// Error type that may occur during insertion.
    type InsertErr: Debug;

    /// Clear state of the filter, so that it behaves like a fresh one.
    fn clear(&mut self);

    /// Insert new element into the filter.
    ///
    /// The method may return an error under certain conditions. When this happens, the
    /// user-visible state is not altered, i.e. the element was not added to the filter. The
    /// internal state may have changed though.
    fn insert<T>(&mut self, obj: &T) -> Result<(), Self::InsertErr>
    where
        T: Hash;

    /// Check if filters is empty, i.e. contains no elements.
    fn is_empty(&self) -> bool;

    /// Return guessed number of elements in the filter.
    fn len(&self) -> usize;

    /// Guess if the given element was added to the filter.
    fn query<T>(&self, obj: &T) -> bool
    where
        T: Hash;
}
<|endoftext|>


<commit_before>//! Defines a series of convenience modifiers for editing Responses
//!
//! Modifiers can be used to edit Responses through the owning
//! method `set` or the mutating `set_mut`, both of which are
//! defined in the `Set` trait.
//!
//! Instead of having a combinatorial explosion of Response methods
//! and constructors, this provides a series of modifiers that
//! can be used through the `Set` trait.
//!
//! For instance, instead of `Response::redirect` constructing a
//! redirect response, we provide a `Redirect` modifier, so you
//! can just do:
//!
//! ```
//! # use iron::prelude::*;
//! # use iron::status;
//! # use iron::modifiers::Redirect;
//! # use iron::Url;
//!
//! let url = Url::parse("http://doc.rust-lang.org").unwrap();
//! Response::with((status::Found, Redirect(url)));
//! ```
//!
//! This is more extensible as it allows you to combine
//! arbitrary modifiers without having a massive number of
//! Response constructors.
//!
//! For more information about the modifier system, see
//! [rust-modifier](https://github.com/reem/rust-modifier).

use std::io::{Read, Cursor};
use std::fs::File;
use std::path::PathBuf;

use modifier::Modifier;

use hyper::mime::Mime;

use {status, headers, Request, Response, Url};

impl Modifier<Response> for Mime {
    #[inline]
    fn modify(self, res: &mut Response) {
        res.headers.set(headers::ContentType(self))
    }
}

impl Modifier<Response> for Box<Read + Send> {
    #[inline]
    fn modify(self, res: &mut Response) {
        res.body = Some(self);
    }
}

impl Modifier<Response> for String {
    #[inline]
    fn modify(self, res: &mut Response) {
        self.into_bytes().modify(res);
    }
}

impl Modifier<Response> for Vec<u8> {
    #[inline]
    fn modify(self, res: &mut Response) {
        res.headers.set(headers::ContentLength(self.len() as u64));
        res.body = Some(Box::new(Cursor::new(self)) as Box<Read + Send>);
    }
}

impl<'a> Modifier<Response> for &'a str {
    #[inline]
    fn modify(self, res: &mut Response) {
        self.to_string().modify(res);
    }
}

impl<'a> Modifier<Response> for &'a [u8] {
    #[inline]
    fn modify(self, res: &mut Response) {
        self.to_vec().modify(res);
    }
}

impl Modifier<Response> for File {
    #[inline]
    fn modify(self, res: &mut Response) {
        // Also set the content type.
        // self.path().extension_str()
        //     .and_then(get_content_type)
        //     .and_then(|ct| { res.set_mut(ct) });

        if let Ok(metadata) = self.metadata() {
            res.headers.set(headers::ContentLength(metadata.len()));
        }

        res.body = Some(Box::new(self) as Box<Read + Send>);
    }
}

impl Modifier<Response> for PathBuf {
    /// Set the body to the contents of the File at this path.
    ///
    /// ## Panics
    ///
    /// Panics if there is no file at the passed-in Path.
    fn modify(self, res: &mut Response) {
        File::open(&self)
            .ok().expect(format!("No such file: {}", self.display()).as_slice())
            .modify(res);
    }
}

impl Modifier<Response> for status::Status {
    fn modify(self, res: &mut Response) {
        res.status = Some(self);
    }
}

/// A modifier for changing headers on requests and responses.
pub struct Header<H: headers::Header + headers::HeaderFormat>(pub H);

impl<H> Modifier<Response> for Header<H>
where H: headers::Header + headers::HeaderFormat {
    fn modify(self, res: &mut Response) {
        res.headers.set(self.0);
    }
}

impl<'a, H> Modifier<Request<'a>> for Header<H>
where H: headers::Header + headers::HeaderFormat {
    fn modify(self, res: &mut Request) {
        res.headers.set(self.0);
    }
}

/// A modifier for creating redirect responses.
pub struct Redirect(pub Url);

impl Modifier<Response> for Redirect {
    fn modify(self, res: &mut Response) {
        let Redirect(url) = self;
        res.headers.set(headers::Location(url.to_string()));
    }
}

<commit_msg>Implement Modifier for &Path<commit_after>//! Defines a series of convenience modifiers for editing Responses
//!
//! Modifiers can be used to edit Responses through the owning
//! method `set` or the mutating `set_mut`, both of which are
//! defined in the `Set` trait.
//!
//! Instead of having a combinatorial explosion of Response methods
//! and constructors, this provides a series of modifiers that
//! can be used through the `Set` trait.
//!
//! For instance, instead of `Response::redirect` constructing a
//! redirect response, we provide a `Redirect` modifier, so you
//! can just do:
//!
//! ```
//! # use iron::prelude::*;
//! # use iron::status;
//! # use iron::modifiers::Redirect;
//! # use iron::Url;
//!
//! let url = Url::parse("http://doc.rust-lang.org").unwrap();
//! Response::with((status::Found, Redirect(url)));
//! ```
//!
//! This is more extensible as it allows you to combine
//! arbitrary modifiers without having a massive number of
//! Response constructors.
//!
//! For more information about the modifier system, see
//! [rust-modifier](https://github.com/reem/rust-modifier).

use std::io::{Read, Cursor};
use std::fs::File;
use std::path::{Path, PathBuf};

use modifier::Modifier;

use hyper::mime::Mime;

use {status, headers, Request, Response, Url};

impl Modifier<Response> for Mime {
    #[inline]
    fn modify(self, res: &mut Response) {
        res.headers.set(headers::ContentType(self))
    }
}

impl Modifier<Response> for Box<Read + Send> {
    #[inline]
    fn modify(self, res: &mut Response) {
        res.body = Some(self);
    }
}

impl Modifier<Response> for String {
    #[inline]
    fn modify(self, res: &mut Response) {
        self.into_bytes().modify(res);
    }
}

impl Modifier<Response> for Vec<u8> {
    #[inline]
    fn modify(self, res: &mut Response) {
        res.headers.set(headers::ContentLength(self.len() as u64));
        res.body = Some(Box::new(Cursor::new(self)) as Box<Read + Send>);
    }
}

impl<'a> Modifier<Response> for &'a str {
    #[inline]
    fn modify(self, res: &mut Response) {
        self.to_string().modify(res);
    }
}

impl<'a> Modifier<Response> for &'a [u8] {
    #[inline]
    fn modify(self, res: &mut Response) {
        self.to_vec().modify(res);
    }
}

impl Modifier<Response> for File {
    #[inline]
    fn modify(self, res: &mut Response) {
        // Also set the content type.
        // self.path().extension_str()
        //     .and_then(get_content_type)
        //     .and_then(|ct| { res.set_mut(ct) });

        if let Ok(metadata) = self.metadata() {
            res.headers.set(headers::ContentLength(metadata.len()));
        }

        res.body = Some(Box::new(self) as Box<Read + Send>);
    }
}

impl<'a> Modifier<Response> for &'a Path {
    /// Set the body to the contents of the File at this path.
    ///
    /// ## Panics
    ///
    /// Panics if there is no file at the passed-in Path.
    fn modify(self, res: &mut Response) {
        File::open(self)
            .ok().expect(format!("No such file: {}", self.display()).as_slice())
            .modify(res);
    }
}

impl Modifier<Response> for PathBuf {
    /// Set the body to the contents of the File at this path.
    ///
    /// ## Panics
    ///
    /// Panics if there is no file at the passed-in Path.
    fn modify(self, res: &mut Response) {
        File::open(&self)
            .ok().expect(format!("No such file: {}", self.display()).as_slice())
            .modify(res);
    }
}

impl Modifier<Response> for status::Status {
    fn modify(self, res: &mut Response) {
        res.status = Some(self);
    }
}

/// A modifier for changing headers on requests and responses.
pub struct Header<H: headers::Header + headers::HeaderFormat>(pub H);

impl<H> Modifier<Response> for Header<H>
where H: headers::Header + headers::HeaderFormat {
    fn modify(self, res: &mut Response) {
        res.headers.set(self.0);
    }
}

impl<'a, H> Modifier<Request<'a>> for Header<H>
where H: headers::Header + headers::HeaderFormat {
    fn modify(self, res: &mut Request) {
        res.headers.set(self.0);
    }
}

/// A modifier for creating redirect responses.
pub struct Redirect(pub Url);

impl Modifier<Response> for Redirect {
    fn modify(self, res: &mut Response) {
        let Redirect(url) = self;
        res.headers.set(headers::Location(url.to_string()));
    }
}

<|endoftext|>


<commit_before>use test_utils::tested_by;
use ra_db::SourceDatabase;
use ra_syntax::{
    AstNode, SyntaxNode, TextUnit,
    SyntaxKind::FN_DEF,
    ast::{self, ArgListOwner},
    algo::find_node_at_offset,
};
use hir::Docs;

use crate::{FilePosition, CallInfo, db::RootDatabase};

/// Computes parameter information for the given call expression.
pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<CallInfo> {
    let file = db.parse(position.file_id);
    let syntax = file.syntax();

    // Find the calling expression and it's NameRef
    let calling_node = FnCallNode::with_node(syntax, position.offset)?;
    let name_ref = calling_node.name_ref()?;

    // Resolve the function's NameRef (NOTE: this isn't entirely accurate).
    let file_symbols = crate::symbol_index::index_resolve(db, name_ref);
    let symbol = file_symbols.into_iter().find(|it| it.ptr.kind() == FN_DEF)?;
    let fn_file = db.parse(symbol.file_id);
    let fn_def = symbol.ptr.to_node(&fn_file);
    let fn_def = ast::FnDef::cast(fn_def).unwrap();
    let function = hir::source_binder::function_from_source(db, symbol.file_id, fn_def)?;

    let mut call_info = CallInfo::new(db, function, fn_def)?;
    // If we have a calling expression let's find which argument we are on
    let num_params = call_info.parameters.len();
    let has_self = fn_def.param_list().and_then(|l| l.self_param()).is_some();

    if num_params == 1 {
        if !has_self {
            call_info.active_parameter = Some(0);
        }
    } else if num_params > 1 {
        // Count how many parameters into the call we are.
        if let Some(ref arg_list) = calling_node.arg_list() {
            let arg_list_range = arg_list.syntax().range();
            if !arg_list_range.contains_inclusive(position.offset) {
                tested_by!(call_info_bad_offset);
                return None;
            }

            let param = arg_list
                .args()
                .position(|arg| arg.syntax().range().contains(position.offset))
                .or(Some(num_params - 1))
                .unwrap();

            call_info.active_parameter = Some(param);
        }
    }

    Some(call_info)
}

enum FnCallNode<'a> {
    CallExpr(&'a ast::CallExpr),
    MethodCallExpr(&'a ast::MethodCallExpr),
}

impl<'a> FnCallNode<'a> {
    pub fn with_node(syntax: &'a SyntaxNode, offset: TextUnit) -> Option<FnCallNode<'a>> {
        if let Some(expr) = find_node_at_offset::<ast::CallExpr>(syntax, offset) {
            return Some(FnCallNode::CallExpr(expr));
        }
        if let Some(expr) = find_node_at_offset::<ast::MethodCallExpr>(syntax, offset) {
            return Some(FnCallNode::MethodCallExpr(expr));
        }
        None
    }

    pub fn name_ref(&self) -> Option<&'a ast::NameRef> {
        match *self {
            FnCallNode::CallExpr(call_expr) => Some(match call_expr.expr()?.kind() {
                ast::ExprKind::PathExpr(path_expr) => path_expr.path()?.segment()?.name_ref()?,
                _ => return None,
            }),

            FnCallNode::MethodCallExpr(call_expr) => {
                call_expr.syntax().children().filter_map(ast::NameRef::cast).nth(0)
            }
        }
    }

    pub fn arg_list(&self) -> Option<&'a ast::ArgList> {
        match *self {
            FnCallNode::CallExpr(expr) => expr.arg_list(),
            FnCallNode::MethodCallExpr(expr) => expr.arg_list(),
        }
    }
}

impl CallInfo {
    fn new(db: &RootDatabase, function: hir::Function, node: &ast::FnDef) -> Option<Self> {
        let label = crate::completion::function_label(node)?;
        let doc = function.docs(db);

        Some(CallInfo { parameters: param_list(node), label, doc, active_parameter: None })
    }
}

fn param_list(node: &ast::FnDef) -> Vec<String> {
    let mut res = vec![];
    if let Some(param_list) = node.param_list() {
        if let Some(self_param) = param_list.self_param() {
            res.push(self_param.syntax().text().to_string())
        }

        // Maybe use param.pat here? See if we can just extract the name?
        //res.extend(param_list.params().map(|p| p.syntax().text().to_string()));
        res.extend(
            param_list.params().filter_map(|p| p.pat()).map(|pat| pat.syntax().text().to_string()),
        );
    }
    res
}

#[cfg(test)]
mod tests {
    use test_utils::covers;

    use crate::mock_analysis::single_file_with_position;

    use super::*;

    fn call_info(text: &str) -> CallInfo {
        let (analysis, position) = single_file_with_position(text);
        analysis.call_info(position).unwrap().unwrap()
    }

    #[test]
    fn test_fn_signature_two_args_first() {
        let info = call_info(
            r#"fn foo(x: u32, y: u32) -> u32 {x + y}
fn bar() { foo(<|>3, ); }"#,
        );

        assert_eq!(info.parameters, vec!("x".to_string(), "y".to_string()));
        assert_eq!(info.active_parameter, Some(0));
    }

    #[test]
    fn test_fn_signature_two_args_second() {
        let info = call_info(
            r#"fn foo(x: u32, y: u32) -> u32 {x + y}
fn bar() { foo(3, <|>); }"#,
        );

        assert_eq!(info.parameters, vec!("x".to_string(), "y".to_string()));
        assert_eq!(info.active_parameter, Some(1));
    }

    #[test]
    fn test_fn_signature_for_impl() {
        let info = call_info(
            r#"struct F; impl F { pub fn new() { F{}} }
fn bar() {let _ : F = F::new(<|>);}"#,
        );

        assert_eq!(info.parameters, Vec::<String>::new());
        assert_eq!(info.active_parameter, None);
    }

    #[test]
    fn test_fn_signature_for_method_self() {
        let info = call_info(
            r#"struct F;
impl F {
    pub fn new() -> F{
        F{}
    }

    pub fn do_it(&self) {}
}

fn bar() {
    let f : F = F::new();
    f.do_it(<|>);
}"#,
        );

        assert_eq!(info.parameters, vec!["&self".to_string()]);
        assert_eq!(info.active_parameter, None);
    }

    #[test]
    fn test_fn_signature_for_method_with_arg() {
        let info = call_info(
            r#"struct F;
impl F {
    pub fn new() -> F{
        F{}
    }

    pub fn do_it(&self, x: i32) {}
}

fn bar() {
    let f : F = F::new();
    f.do_it(<|>);
}"#,
        );

        assert_eq!(info.parameters, vec!["&self".to_string(), "x".to_string()]);
        assert_eq!(info.active_parameter, Some(1));
    }

    #[test]
    fn test_fn_signature_with_docs_simple() {
        let info = call_info(
            r#"
/// test
// non-doc-comment
fn foo(j: u32) -> u32 {
    j
}

fn bar() {
    let _ = foo(<|>);
}
"#,
        );

        assert_eq!(info.parameters, vec!["j".to_string()]);
        assert_eq!(info.active_parameter, Some(0));
        assert_eq!(info.label, "fn foo(j: u32) -> u32".to_string());
        assert_eq!(info.doc.map(|it| it.into()), Some("test".to_string()));
    }

    #[test]
    fn test_fn_signature_with_docs() {
        let info = call_info(
            r#"
/// Adds one to the number given.
///
/// # Examples
///
/// ```
/// let five = 5;
///
/// assert_eq!(6, my_crate::add_one(5));
/// ```
pub fn add_one(x: i32) -> i32 {
    x + 1
}

pub fn do() {
    add_one(<|>
}"#,
        );

        assert_eq!(info.parameters, vec!["x".to_string()]);
        assert_eq!(info.active_parameter, Some(0));
        assert_eq!(info.label, "pub fn add_one(x: i32) -> i32".to_string());
        assert_eq!(
            info.doc.map(|it| it.into()),
            Some(
                r#"Adds one to the number given.

# Examples

```
let five = 5;

assert_eq!(6, my_crate::add_one(5));
```"#
                    .to_string()
            )
        );
    }

    #[test]
    fn test_fn_signature_with_docs_impl() {
        let info = call_info(
            r#"
struct addr;
impl addr {
    /// Adds one to the number given.
    ///
    /// # Examples
    ///
    /// ```
    /// let five = 5;
    ///
    /// assert_eq!(6, my_crate::add_one(5));
    /// ```
    pub fn add_one(x: i32) -> i32 {
        x + 1
    }
}

pub fn do_it() {
    addr {};
    addr::add_one(<|>);
}"#,
        );

        assert_eq!(info.parameters, vec!["x".to_string()]);
        assert_eq!(info.active_parameter, Some(0));
        assert_eq!(info.label, "pub fn add_one(x: i32) -> i32".to_string());
        assert_eq!(
            info.doc.map(|it| it.into()),
            Some(
                r#"Adds one to the number given.

# Examples

```
let five = 5;

assert_eq!(6, my_crate::add_one(5));
```"#
                    .to_string()
            )
        );
    }

    #[test]
    fn test_fn_signature_with_docs_from_actix() {
        let info = call_info(
            r#"
pub trait WriteHandler<E>
where
    Self: Actor,
    Self::Context: ActorContext,
{
    /// Method is called when writer emits error.
    ///
    /// If this method returns `ErrorAction::Continue` writer processing
    /// continues otherwise stream processing stops.
    fn error(&mut self, err: E, ctx: &mut Self::Context) -> Running {
        Running::Stop
    }

    /// Method is called when writer finishes.
    ///
    /// By default this method stops actor's `Context`.
    fn finished(&mut self, ctx: &mut Self::Context) {
        ctx.stop()
    }
}

pub fn foo() {
    WriteHandler r;
    r.finished(<|>);
}

"#,
        );

        assert_eq!(info.parameters, vec!["&mut self".to_string(), "ctx".to_string()]);
        assert_eq!(info.active_parameter, Some(1));
        assert_eq!(
            info.doc.map(|it| it.into()),
            Some(
                r#"Method is called when writer finishes.

By default this method stops actor's `Context`."#
                    .to_string()
            )
        );
    }

    #[test]
    fn call_info_bad_offset() {
        covers!(call_info_bad_offset);
        let (analysis, position) = single_file_with_position(
            r#"fn foo(x: u32, y: u32) -> u32 {x + y}
               fn bar() { foo <|> (3, ); }"#,
        );
        let call_info = analysis.call_info(position).unwrap();
        assert!(call_info.is_none());
    }
}
<commit_msg>Take number of arguments at the call-site into account for signature help<commit_after>use test_utils::tested_by;
use ra_db::SourceDatabase;
use ra_syntax::{
    AstNode, SyntaxNode, TextUnit,
    SyntaxKind::FN_DEF,
    ast::{self, ArgListOwner},
    algo::find_node_at_offset,
};
use hir::Docs;

use crate::{FilePosition, CallInfo, db::RootDatabase};

/// Computes parameter information for the given call expression.
pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<CallInfo> {
    let file = db.parse(position.file_id);
    let syntax = file.syntax();

    // Find the calling expression and it's NameRef
    let calling_node = FnCallNode::with_node(syntax, position.offset)?;
    let name_ref = calling_node.name_ref()?;

    // Resolve the function's NameRef (NOTE: this isn't entirely accurate).
    let file_symbols = crate::symbol_index::index_resolve(db, name_ref);
    let symbol = file_symbols.into_iter().find(|it| it.ptr.kind() == FN_DEF)?;
    let fn_file = db.parse(symbol.file_id);
    let fn_def = symbol.ptr.to_node(&fn_file);
    let fn_def = ast::FnDef::cast(fn_def).unwrap();
    let function = hir::source_binder::function_from_source(db, symbol.file_id, fn_def)?;

    let mut call_info = CallInfo::new(db, function, fn_def)?;

    // If we have a calling expression let's find which argument we are on
    let num_params = call_info.parameters.len();
    let has_self = fn_def.param_list().and_then(|l| l.self_param()).is_some();

    if num_params == 1 {
        if !has_self {
            call_info.active_parameter = Some(0);
        }
    } else if num_params > 1 {
        // Count how many parameters into the call we are.
        if let Some(arg_list) = calling_node.arg_list() {
            // Number of arguments specified at the caller site
            let mut num_args_of_call = arg_list.args().count();

            // If we are calling a method account for the `self` argument.
            if has_self {
                num_args_of_call = num_args_of_call + 1;
            }

            let arg_list_range = arg_list.syntax().range();
            if !arg_list_range.contains_inclusive(position.offset) {
                tested_by!(call_info_bad_offset);
                return None;
            }

            let param = arg_list
                .args()
                .position(|arg| arg.syntax().range().contains(position.offset))
                .or(Some(num_params - 1))
                .min(Some(num_args_of_call))
                .unwrap();

            call_info.active_parameter = Some(param);
        }
    }

    Some(call_info)
}

enum FnCallNode<'a> {
    CallExpr(&'a ast::CallExpr),
    MethodCallExpr(&'a ast::MethodCallExpr),
}

impl<'a> FnCallNode<'a> {
    pub fn with_node(syntax: &'a SyntaxNode, offset: TextUnit) -> Option<FnCallNode<'a>> {
        if let Some(expr) = find_node_at_offset::<ast::CallExpr>(syntax, offset) {
            return Some(FnCallNode::CallExpr(expr));
        }
        if let Some(expr) = find_node_at_offset::<ast::MethodCallExpr>(syntax, offset) {
            return Some(FnCallNode::MethodCallExpr(expr));
        }
        None
    }

    pub fn name_ref(&self) -> Option<&'a ast::NameRef> {
        match *self {
            FnCallNode::CallExpr(call_expr) => Some(match call_expr.expr()?.kind() {
                ast::ExprKind::PathExpr(path_expr) => path_expr.path()?.segment()?.name_ref()?,
                _ => return None,
            }),

            FnCallNode::MethodCallExpr(call_expr) => {
                call_expr.syntax().children().filter_map(ast::NameRef::cast).nth(0)
            }
        }
    }

    pub fn arg_list(&self) -> Option<&'a ast::ArgList> {
        match *self {
            FnCallNode::CallExpr(expr) => expr.arg_list(),
            FnCallNode::MethodCallExpr(expr) => expr.arg_list(),
        }
    }
}

impl CallInfo {
    fn new(db: &RootDatabase, function: hir::Function, node: &ast::FnDef) -> Option<Self> {
        let label = crate::completion::function_label(node)?;
        let doc = function.docs(db);

        Some(CallInfo { parameters: param_list(node), label, doc, active_parameter: None })
    }
}

fn param_list(node: &ast::FnDef) -> Vec<String> {
    let mut res = vec![];
    if let Some(param_list) = node.param_list() {
        if let Some(self_param) = param_list.self_param() {
            res.push(self_param.syntax().text().to_string())
        }

        // Maybe use param.pat here? See if we can just extract the name?
        //res.extend(param_list.params().map(|p| p.syntax().text().to_string()));
        res.extend(
            param_list.params().filter_map(|p| p.pat()).map(|pat| pat.syntax().text().to_string()),
        );
    }
    res
}

#[cfg(test)]
mod tests {
    use test_utils::covers;

    use crate::mock_analysis::single_file_with_position;

    use super::*;

    fn call_info(text: &str) -> CallInfo {
        let (analysis, position) = single_file_with_position(text);
        analysis.call_info(position).unwrap().unwrap()
    }

    #[test]
    fn test_fn_signature_two_args_first() {
        let info = call_info(
            r#"fn foo(x: u32, y: u32) -> u32 {x + y}
fn bar() { foo(<|>3, ); }"#,
        );

        assert_eq!(info.parameters, vec!("x".to_string(), "y".to_string()));
        assert_eq!(info.active_parameter, Some(0));
    }

    #[test]
    fn test_fn_signature_two_args_second() {
        let info = call_info(
            r#"fn foo(x: u32, y: u32) -> u32 {x + y}
fn bar() { foo(3, <|>); }"#,
        );

        assert_eq!(info.parameters, vec!("x".to_string(), "y".to_string()));
        assert_eq!(info.active_parameter, Some(1));
    }

    #[test]
    fn test_fn_signature_two_args_empty() {
        let info = call_info(
            r#"fn foo(x: u32, y: u32) -> u32 {x + y}
fn bar() { foo(<|>); }"#,
        );

        assert_eq!(info.parameters, vec!("x".to_string(), "y".to_string()));
        assert_eq!(info.active_parameter, Some(0));
    }

    #[test]
    fn test_fn_signature_for_impl() {
        let info = call_info(
            r#"struct F; impl F { pub fn new() { F{}} }
fn bar() {let _ : F = F::new(<|>);}"#,
        );

        assert_eq!(info.parameters, Vec::<String>::new());
        assert_eq!(info.active_parameter, None);
    }

    #[test]
    fn test_fn_signature_for_method_self() {
        let info = call_info(
            r#"struct F;
impl F {
    pub fn new() -> F{
        F{}
    }

    pub fn do_it(&self) {}
}

fn bar() {
    let f : F = F::new();
    f.do_it(<|>);
}"#,
        );

        assert_eq!(info.parameters, vec!["&self".to_string()]);
        assert_eq!(info.active_parameter, None);
    }

    #[test]
    fn test_fn_signature_for_method_with_arg() {
        let info = call_info(
            r#"struct F;
impl F {
    pub fn new() -> F{
        F{}
    }

    pub fn do_it(&self, x: i32) {}
}

fn bar() {
    let f : F = F::new();
    f.do_it(<|>);
}"#,
        );

        assert_eq!(info.parameters, vec!["&self".to_string(), "x".to_string()]);
        assert_eq!(info.active_parameter, Some(1));
    }

    #[test]
    fn test_fn_signature_with_docs_simple() {
        let info = call_info(
            r#"
/// test
// non-doc-comment
fn foo(j: u32) -> u32 {
    j
}

fn bar() {
    let _ = foo(<|>);
}
"#,
        );

        assert_eq!(info.parameters, vec!["j".to_string()]);
        assert_eq!(info.active_parameter, Some(0));
        assert_eq!(info.label, "fn foo(j: u32) -> u32".to_string());
        assert_eq!(info.doc.map(|it| it.into()), Some("test".to_string()));
    }

    #[test]
    fn test_fn_signature_with_docs() {
        let info = call_info(
            r#"
/// Adds one to the number given.
///
/// # Examples
///
/// ```
/// let five = 5;
///
/// assert_eq!(6, my_crate::add_one(5));
/// ```
pub fn add_one(x: i32) -> i32 {
    x + 1
}

pub fn do() {
    add_one(<|>
}"#,
        );

        assert_eq!(info.parameters, vec!["x".to_string()]);
        assert_eq!(info.active_parameter, Some(0));
        assert_eq!(info.label, "pub fn add_one(x: i32) -> i32".to_string());
        assert_eq!(
            info.doc.map(|it| it.into()),
            Some(
                r#"Adds one to the number given.

# Examples

```
let five = 5;

assert_eq!(6, my_crate::add_one(5));
```"#
                    .to_string()
            )
        );
    }

    #[test]
    fn test_fn_signature_with_docs_impl() {
        let info = call_info(
            r#"
struct addr;
impl addr {
    /// Adds one to the number given.
    ///
    /// # Examples
    ///
    /// ```
    /// let five = 5;
    ///
    /// assert_eq!(6, my_crate::add_one(5));
    /// ```
    pub fn add_one(x: i32) -> i32 {
        x + 1
    }
}

pub fn do_it() {
    addr {};
    addr::add_one(<|>);
}"#,
        );

        assert_eq!(info.parameters, vec!["x".to_string()]);
        assert_eq!(info.active_parameter, Some(0));
        assert_eq!(info.label, "pub fn add_one(x: i32) -> i32".to_string());
        assert_eq!(
            info.doc.map(|it| it.into()),
            Some(
                r#"Adds one to the number given.

# Examples

```
let five = 5;

assert_eq!(6, my_crate::add_one(5));
```"#
                    .to_string()
            )
        );
    }

    #[test]
    fn test_fn_signature_with_docs_from_actix() {
        let info = call_info(
            r#"
pub trait WriteHandler<E>
where
    Self: Actor,
    Self::Context: ActorContext,
{
    /// Method is called when writer emits error.
    ///
    /// If this method returns `ErrorAction::Continue` writer processing
    /// continues otherwise stream processing stops.
    fn error(&mut self, err: E, ctx: &mut Self::Context) -> Running {
        Running::Stop
    }

    /// Method is called when writer finishes.
    ///
    /// By default this method stops actor's `Context`.
    fn finished(&mut self, ctx: &mut Self::Context) {
        ctx.stop()
    }
}

pub fn foo() {
    WriteHandler r;
    r.finished(<|>);
}

"#,
        );

        assert_eq!(info.parameters, vec!["&mut self".to_string(), "ctx".to_string()]);
        assert_eq!(info.active_parameter, Some(1));
        assert_eq!(
            info.doc.map(|it| it.into()),
            Some(
                r#"Method is called when writer finishes.

By default this method stops actor's `Context`."#
                    .to_string()
            )
        );
    }

    #[test]
    fn call_info_bad_offset() {
        covers!(call_info_bad_offset);
        let (analysis, position) = single_file_with_position(
            r#"fn foo(x: u32, y: u32) -> u32 {x + y}
               fn bar() { foo <|> (3, ); }"#,
        );
        let call_info = analysis.call_info(position).unwrap();
        assert!(call_info.is_none());
    }
}
<|endoftext|>


<commit_before>//! Defines a bunch of data-less enums for unary and binary operators.
//!
//! Types here don't know about AST, this allows re-using them for both AST and
//! HIR.
use std::fmt;

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum RangeOp {
    /// `..`
    Exclusive,
    /// `..=`
    Inclusive,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum UnaryOp {
    /// `*`
    Deref,
    /// `!`
    Not,
    /// `-`
    Neg,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum BinaryOp {
    LogicOp(LogicOp),
    ArithOp(ArithOp),
    CmpOp(CmpOp),
    Assignment { op: Option<ArithOp> },
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum LogicOp {
    And,
    Or,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum CmpOp {
    Eq { negated: bool },
    Ord { ordering: Ordering, strict: bool },
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum Ordering {
    Less,
    Greater,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum ArithOp {
    Add,
    Mul,
    Sub,
    Div,
    Rem,
    Shl,
    Shr,
    BitXor,
    BitOr,
    BitAnd,
}

impl fmt::Display for LogicOp {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let res = match self {
            LogicOp::And => "&&",
            LogicOp::Or => "||",
        };
        f.write_str(res)
    }
}

impl fmt::Display for ArithOp {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let res = match self {
            ArithOp::Add => "+",
            ArithOp::Mul => "*",
            ArithOp::Sub => "-",
            ArithOp::Div => "/",
            ArithOp::Rem => "%",
            ArithOp::Shl => "<<",
            ArithOp::Shr => ">>",
            ArithOp::BitXor => "^",
            ArithOp::BitOr => "|",
            ArithOp::BitAnd => "&",
        };
        f.write_str(res)
    }
}

impl fmt::Display for CmpOp {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let res = match self {
            CmpOp::Eq { negated: false } => "==",
            CmpOp::Eq { negated: true } => "!=",
            CmpOp::Ord { ordering: Ordering::Less, strict: false } => "<=",
            CmpOp::Ord { ordering: Ordering::Less, strict: true } => "<",
            CmpOp::Ord { ordering: Ordering::Greater, strict: false } => ">=",
            CmpOp::Ord { ordering: Ordering::Greater, strict: true } => ">",
        };
        f.write_str(res)
    }
}

impl fmt::Display for BinaryOp {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            BinaryOp::LogicOp(op) => fmt::Display::fmt(op, f),
            BinaryOp::ArithOp(op) => fmt::Display::fmt(op, f),
            BinaryOp::CmpOp(op) => fmt::Display::fmt(op, f),
            BinaryOp::Assignment { op } => {
                f.write_str("=")?;
                if let Some(op) = op {
                    fmt::Display::fmt(op, f)?;
                }
                Ok(())
            }
        }
    }
}
<commit_msg>Auto merge of #12974 - fprasx:master, r=lnicola<commit_after>//! Defines a bunch of data-less enums for unary and binary operators.
//!
//! Types here don't know about AST, this allows re-using them for both AST and
//! HIR.
use std::fmt;

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum RangeOp {
    /// `..`
    Exclusive,
    /// `..=`
    Inclusive,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum UnaryOp {
    /// `*`
    Deref,
    /// `!`
    Not,
    /// `-`
    Neg,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum BinaryOp {
    LogicOp(LogicOp),
    ArithOp(ArithOp),
    CmpOp(CmpOp),
    Assignment { op: Option<ArithOp> },
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum LogicOp {
    And,
    Or,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum CmpOp {
    Eq { negated: bool },
    Ord { ordering: Ordering, strict: bool },
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum Ordering {
    Less,
    Greater,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum ArithOp {
    Add,
    Mul,
    Sub,
    Div,
    Rem,
    Shl,
    Shr,
    BitXor,
    BitOr,
    BitAnd,
}

impl fmt::Display for LogicOp {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let res = match self {
            LogicOp::And => "&&",
            LogicOp::Or => "||",
        };
        f.write_str(res)
    }
}

impl fmt::Display for ArithOp {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let res = match self {
            ArithOp::Add => "+",
            ArithOp::Mul => "*",
            ArithOp::Sub => "-",
            ArithOp::Div => "/",
            ArithOp::Rem => "%",
            ArithOp::Shl => "<<",
            ArithOp::Shr => ">>",
            ArithOp::BitXor => "^",
            ArithOp::BitOr => "|",
            ArithOp::BitAnd => "&",
        };
        f.write_str(res)
    }
}

impl fmt::Display for CmpOp {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let res = match self {
            CmpOp::Eq { negated: false } => "==",
            CmpOp::Eq { negated: true } => "!=",
            CmpOp::Ord { ordering: Ordering::Less, strict: false } => "<=",
            CmpOp::Ord { ordering: Ordering::Less, strict: true } => "<",
            CmpOp::Ord { ordering: Ordering::Greater, strict: false } => ">=",
            CmpOp::Ord { ordering: Ordering::Greater, strict: true } => ">",
        };
        f.write_str(res)
    }
}

impl fmt::Display for BinaryOp {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            BinaryOp::LogicOp(op) => fmt::Display::fmt(op, f),
            BinaryOp::ArithOp(op) => fmt::Display::fmt(op, f),
            BinaryOp::CmpOp(op) => fmt::Display::fmt(op, f),
            BinaryOp::Assignment { op } => {
                if let Some(op) = op {
                    fmt::Display::fmt(op, f)?;
                }
                f.write_str("=")?;
                Ok(())
            }
        }
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code, unused_variables)]

use {Action, InputTranslator, RebindBuilder, InputRebind};
use window::Size;

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Ord, PartialOrd)]
enum TestAction {
    Action1, Action2, Action3, Action4, Action5,
    Action6, Action7, Action8, Action9, Action10
}

impl Action for TestAction { }

type TestBuilder = RebindBuilder<TestAction>;
type TestTranslator = InputTranslator<TestAction>;
type TestRebind = InputRebind<TestAction>;

const TEST_SIZE: Size = Size {
    width:  800,
    height: 600
};

fn create_prepopulated_builder() -> TestBuilder {
    use input::keyboard::Key;
    use input::Button::Keyboard;

    RebindBuilder::new(TEST_SIZE)
        .with_action_mapping(Keyboard(Key::Up),    TestAction::Action1)
        .with_action_mapping(Keyboard(Key::W),     TestAction::Action1)
        .with_action_mapping(Keyboard(Key::Down),  TestAction::Action2)
        .with_action_mapping(Keyboard(Key::S),     TestAction::Action2)
        .with_action_mapping(Keyboard(Key::Left),  TestAction::Action3)
        .with_action_mapping(Keyboard(Key::A),     TestAction::Action3)
        .with_action_mapping(Keyboard(Key::Right), TestAction::Action4)
        .with_action_mapping(Keyboard(Key::D),     TestAction::Action4)
}

#[test]
fn test_conversion_from_rebind_to_translator() {
    let translator = create_prepopulated_builder().build_translator();

    let translator_clone = translator.clone();
    let converted_translator = Into::<TestTranslator>::into(
            Into::<TestRebind>::into(translator));

    assert_eq!(translator_clone, converted_translator);
}
<commit_msg>Create the Builder using default, and remove the TEST_SIZE constant<commit_after>#![allow(dead_code, unused_variables)]

use {Action, InputTranslator, RebindBuilder, InputRebind};

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Ord, PartialOrd)]
enum TestAction {
    Action1, Action2, Action3, Action4, Action5,
    Action6, Action7, Action8, Action9, Action10
}

impl Action for TestAction { }

type TestBuilder = RebindBuilder<TestAction>;
type TestTranslator = InputTranslator<TestAction>;
type TestRebind = InputRebind<TestAction>;

fn create_prepopulated_builder() -> TestBuilder {
    use input::keyboard::Key;
    use input::Button::Keyboard;

    RebindBuilder::default()
        .with_action_mapping(Keyboard(Key::Up),    TestAction::Action1)
        .with_action_mapping(Keyboard(Key::W),     TestAction::Action1)
        .with_action_mapping(Keyboard(Key::Down),  TestAction::Action2)
        .with_action_mapping(Keyboard(Key::S),     TestAction::Action2)
        .with_action_mapping(Keyboard(Key::Left),  TestAction::Action3)
        .with_action_mapping(Keyboard(Key::A),     TestAction::Action3)
        .with_action_mapping(Keyboard(Key::Right), TestAction::Action4)
        .with_action_mapping(Keyboard(Key::D),     TestAction::Action4)
}

#[test]
fn test_conversion_from_rebind_to_translator() {
    let translator = create_prepopulated_builder().build_translator();

    let translator_clone = translator.clone();
    let converted_translator = Into::<TestTranslator>::into(
            Into::<TestRebind>::into(translator));

    assert_eq!(translator_clone, converted_translator);
}
<|endoftext|>


<commit_before>// Tree + HashMap = Homogeneous Trie
use std::collections::HashMap;
use std::hash::Hash;

#[derive(Debug)]
pub struct Trie<T: Eq + Hash, S> {
    node: HashMap<T, Trie<T, S>>,
    value: Option<S>,
}

impl<T: Eq + Hash, S> Trie<T, S> {
    pub fn new() -> Trie<T, S> {
        Trie {
            value: None,
            node: HashMap::new(),
        }
    }

    pub fn insert<I: Iterator<Item = T>>(&mut self, mut iterator: I, value: S) {
        match iterator.next() {
            Some(thing) => {
                let mut entry = (&mut self.node).entry(thing).or_insert(Trie::new());
                entry.insert(iterator, value);
            },
            None => {
                self.value = Some(value);
            },
        }
    }

    pub fn get<I: Iterator<Item = T>>(&self, iterator: I) -> Option<&S> {
        let mut current_node = self;
        for thing in iterator {
            if let Some(map) = current_node.node.get(&thing) {
                current_node = ↦
            } else {
                return None
            }
        }

        current_node.value.as_ref()
    }
}
<commit_msg>Add option for marking traced paths<commit_after>// Tree + HashMap = Homogeneous Trie
use std::collections::HashMap;
use std::hash::Hash;

#[derive(Debug)]
pub struct Trie<T: Eq + Hash, S> {
    // Since we're using HashMap, it's better if we have the depth
    // as minimum as possible to avoid clutter.
    node: HashMap<T, Trie<T, S>>,
    value: Option<S>,
    // Marker type to remember overwritten values. This is useful when
    // we're interested in unique values. Getting and replacing values is
    // probably a bad idea, since it takes O(n) time.
    pub is_traced_path: bool,
}

impl<T: Eq + Hash, S> Trie<T, S> {
    pub fn new() -> Trie<T, S> {
        Trie {
            value: None,
            node: HashMap::new(),
            is_traced_path: false,
        }
    }

    pub fn insert<I: Iterator<Item = T>>(&mut self, mut iterator: I, value: S) {
        match iterator.next() {
            Some(thing) => {
                let mut entry = (&mut self.node).entry(thing).or_insert(Trie::new());
                entry.insert(iterator, value);
            },
            None => {   // End of iteration: Mark if there's a value already
                if self.value.is_some() && self.node.is_empty() {
                    self.is_traced_path = true;
                } else {
                    self.value = Some(value);
                }
            },
        }
    }

    pub fn get<I: Iterator<Item = T>>(&self, iterator: I, check_unique: bool) -> Option<&S> {
        let mut current_node = self;
        for thing in iterator {
            if let Some(trie) = current_node.node.get(&thing) {
                current_node = ≜
            } else {
                return None
            }
        }

        if check_unique && current_node.is_traced_path {
            None
        } else {
            current_node.value.as_ref()
        }
    }
}
<|endoftext|>