<commit_before>use futures::future::Future;
use futures::stream::Stream;
use glob::glob;
use hyper::{header, Chunk, Client, Method, Request, Response};
use hyper_rustls::HttpsConnector;
use serde_json;
use statics::TEMP_DIRNAME;
use std;
use std::collections::HashMap;
use std::fs::File;
use std::io::prelude::*;
use structs::{CliError, Config, Member, PublicKey, Repo, Sector, SectorGroup, Team};
use tokio_core::reactor;

pub struct GithubClient {
    pub conf: Config,
}

impl GithubClient {
    pub fn new(config: &Config) -> GithubClient {
        if std::env::var("SSL_CERT_FILE").is_err() {
            std::env::set_var("SSL_CERT_FILE", &config.cert_path);
        }
        GithubClient { conf: config.clone() }
    }

    fn get_cache_path(url: &str) -> std::path::PathBuf {
        let mut path = std::env::temp_dir();
        path.push(TEMP_DIRNAME);
        path.push(url);
        path
    }

    fn load_contents_from_cache(&self, url: &str) -> Result<(std::fs::Metadata, String), CliError> {
        let path = Self::get_cache_path(url);
        let metadata = std::fs::metadata(path.to_str().unwrap())?;
        let mut f = File::open(path.to_str().unwrap())?;
        let mut contents = String::new();
        f.read_to_string(&mut contents)?;
        Ok((metadata, contents))
    }

    fn store_contents_to_cache(&self, url: &str, contents: &str) -> Result<(), CliError> {
        let path = Self::get_cache_path(url);
        std::fs::create_dir_all(path.parent().unwrap_or(std::path::Path::new("/")))?;
        let mut f = File::create(path.to_str().unwrap())?;
        f.write(contents.as_bytes())?;
        Ok(())
    }

    fn get_contents_from_url(&self, url: &str) -> Result<String, CliError> {
        let mut all_contents: Vec<serde_json::value::Value> = Vec::new();
        let mut page = 1;
        loop {
            let mut new_array = self.get_contents_from_url_page(url, page)?;
            if new_array.is_empty() {
                break;
            }
            all_contents.append(&mut new_array);
            page += 1;
        }
        let contents = serde_json::ser::to_string(&all_contents)?;
        self.store_contents_to_cache(url, &contents)?;
        Ok(contents)
    }

    fn build_request(&self, url: &str) -> Request {
        let token = String::from("token ") + &self.conf.token;
        let mut req: Request = Request::new(Method::Get, url.parse().unwrap());
        req.headers_mut().set(header::Authorization(token));
        req.headers_mut().set(header::UserAgent::new("sectora"));
        req
    }

    fn build_page_request(&self, url: &str, page: u64) -> Request {
        let sep = if url.contains("?") { "&" } else { "?" };
        let url_p = format!("{}{}page={}", url, sep, page);
        self.build_request(&url_p)
    }

    fn run_request(&self, req: Request) -> Result<serde_json::value::Value, CliError> {
        let mut core = reactor::Core::new()?;
        let client = Client::configure().connector(HttpsConnector::new(4, &core.handle()))
                                        .build(&core.handle());
        let to_io = |e| std::io::Error::new(std::io::ErrorKind::Other, e);
        let parse_body = |body: Chunk| Ok(serde_json::from_slice(&body).map_err(to_io)?);
        let handle_response = |res: Response| res.body().concat2().and_then(parse_body);
        Ok(core.run(client.request(req).and_then(handle_response))?)
    }

    fn get_contents_from_url_page(&self, url: &str, page: u64) -> Result<Vec<serde_json::value::Value>, CliError> {
        let req = self.build_page_request(url, page);
        self.run_request(req).and_then(|v| serde_json::from_value(v).map_err(CliError::from))
    }

    fn get_contents(&self, url: &str) -> Result<String, CliError> {
        match self.load_contents_from_cache(url) {
            Ok((metadata, cache_contents)) => match std::time::SystemTime::now().duration_since(metadata.modified()?) {
                Ok(caching_duration) => {
                    if caching_duration.as_secs() > self.conf.cache_duration {
                        match self.get_contents_from_url(url) {
                            Ok(contents_from_url) => Ok(contents_from_url),
                            Err(_) => Ok(cache_contents),
                        }
                    } else {
                        Ok(cache_contents)
                    }
                }
                Err(_) => Ok(cache_contents),
            },
            Err(_) => self.get_contents_from_url(url),
        }
    }

    #[allow(dead_code)]
    pub fn print_user_public_key(&self, user: &str) -> Result<(), CliError> {
        let keys = self.get_user_public_key(user)?;
        println!("{}", keys);
        Ok(())
    }

    fn get_user_public_key(&self, user: &str) -> Result<String, CliError> {
        let url = format!("{}/users/{}/keys", self.conf.endpoint, user);
        let contents = self.get_contents(&url)?;
        let keys = serde_json::from_str::<Vec<PublicKey>>(&contents)?;
        Ok(keys.iter().map(|k| k.key.clone()).collect::<Vec<String>>().join("\n"))
    }

    #[allow(dead_code)]
    pub fn check_pam(&self, user: &str) -> Result<bool, CliError> {
        let sectors = self.get_sectors()?;
        Ok(sectors.iter().any(|team| team.members.contains_key(user)))
    }

    pub fn get_sectors(&self) -> Result<Vec<SectorGroup>, CliError> {
        let mut sectors: Vec<SectorGroup> = self.get_teams_result()?;
        sectors.append(&mut self.get_repos_result()?);
        Ok(sectors)
    }

    fn get_teams_result(&self) -> Result<Vec<SectorGroup>, CliError> {
        let gh_teams = self.get_team_map()?;
        let mut teams = Vec::new();
        for team_conf in &self.conf.team {
            if let &Some(gh_team) = &gh_teams.get(&team_conf.name) {
                teams.push(SectorGroup { sector: Sector::from(gh_team.clone()),
                                         gid: team_conf.gid.clone(),
                                         group: team_conf.group.clone(),
                                         members: self.get_team_members(gh_team.id)?, });
            }
        }
        Ok(teams)
    }

    fn get_team_map(&self) -> Result<HashMap<String, Team>, CliError> {
        let url = format!("{}/orgs/{}/teams", self.conf.endpoint, self.conf.org);
        let contents = self.get_contents(&url)?;
        let teams = serde_json::from_str::<Vec<Team>>(&contents)?;
        Ok(teams.iter().map(|t| (t.name.clone(), t.clone())).collect())
    }

    fn get_team_members(&self, mid: u64) -> Result<HashMap<String, Member>, CliError> {
        let url = format!("{}/teams/{}/members", self.conf.endpoint, mid);
        let contents = self.get_contents(&url)?;
        let members = serde_json::from_str::<Vec<Member>>(&contents)?;
        Ok(members.iter().map(|m| (m.login.clone(), m.clone())).collect())
    }

    fn get_repos_result(&self) -> Result<Vec<SectorGroup>, CliError> {
        let gh_repos = self.get_repo_map()?;
        let mut repos = Vec::new();
        for repo_conf in &self.conf.repo {
            if let &Some(gh_repo) = &gh_repos.get(&repo_conf.name) {
                repos.push(SectorGroup { sector: Sector::from(gh_repo.clone()),
                                         gid: repo_conf.gid.clone(),
                                         group: repo_conf.group.clone(),
                                         members: self.get_repo_collaborators(&gh_repo.name)?, });
            }
        }
        Ok(repos)
    }

    fn get_repo_map(&self) -> Result<HashMap<String, Repo>, CliError> {
        let url = format!("{}/orgs/{}/repos", self.conf.endpoint, self.conf.org);
        let contents = self.get_contents(&url)?;
        let repos = serde_json::from_str::<Vec<Repo>>(&contents)?;
        Ok(repos.iter().map(|t| (t.name.clone(), t.clone())).collect())
    }

    fn get_repo_collaborators(&self, repo_name: &str) -> Result<HashMap<String, Member>, CliError> {
        let url = format!("{}/repos/{}/{}/collaborators?affiliation=outside",
                          self.conf.endpoint, self.conf.org, repo_name);
        let contents = self.get_contents(&url)?;
        let members = serde_json::from_str::<Vec<Member>>(&contents)?;
        Ok(members.iter().map(|m| (m.login.clone(), m.clone())).collect())
    }

    #[allow(dead_code)]
    pub fn clear_all_caches(&self) -> Result<(), CliError> {
        let mut path = std::env::temp_dir();
        path.push(TEMP_DIRNAME);
        path.push("**/*");
        for entry in glob(&path.to_str().unwrap()).unwrap() {
            match entry {
                Ok(path) => {
                    if path.is_file() {
                        std::fs::remove_file(path)?
                    }
                }
                Err(e) => println!("{:?}", e),
            }
        }
        Ok(())
    }
}
<commit_msg>Add a method to get rate_limit of github api<commit_after>use futures::future::Future;
use futures::stream::Stream;
use glob::glob;
use hyper::{header, Chunk, Client, Method, Request, Response};
use hyper_rustls::HttpsConnector;
use serde_json;
use statics::TEMP_DIRNAME;
use std;
use std::collections::HashMap;
use std::fs::File;
use std::io::prelude::*;
use structs::{CliError, Config, Member, PublicKey, RateLimit, Repo, Sector, SectorGroup, Team};
use tokio_core::reactor;

pub struct GithubClient {
    pub conf: Config,
}

impl GithubClient {
    pub fn new(config: &Config) -> GithubClient {
        if std::env::var("SSL_CERT_FILE").is_err() {
            std::env::set_var("SSL_CERT_FILE", &config.cert_path);
        }
        GithubClient { conf: config.clone() }
    }

    fn get_cache_path(url: &str) -> std::path::PathBuf {
        let mut path = std::env::temp_dir();
        path.push(TEMP_DIRNAME);
        path.push(url);
        path
    }

    fn load_contents_from_cache(&self, url: &str) -> Result<(std::fs::Metadata, String), CliError> {
        let path = Self::get_cache_path(url);
        let metadata = std::fs::metadata(path.to_str().unwrap())?;
        let mut f = File::open(path.to_str().unwrap())?;
        let mut contents = String::new();
        f.read_to_string(&mut contents)?;
        Ok((metadata, contents))
    }

    fn store_contents_to_cache(&self, url: &str, contents: &str) -> Result<(), CliError> {
        let path = Self::get_cache_path(url);
        std::fs::create_dir_all(path.parent().unwrap_or(std::path::Path::new("/")))?;
        let mut f = File::create(path.to_str().unwrap())?;
        f.write(contents.as_bytes())?;
        Ok(())
    }

    fn get_contents_from_url(&self, url: &str) -> Result<String, CliError> {
        let mut all_contents: Vec<serde_json::value::Value> = Vec::new();
        let mut page = 1;
        loop {
            let mut new_array = self.get_contents_from_url_page(url, page)?;
            if new_array.is_empty() {
                break;
            }
            all_contents.append(&mut new_array);
            page += 1;
        }
        let contents = serde_json::ser::to_string(&all_contents)?;
        self.store_contents_to_cache(url, &contents)?;
        Ok(contents)
    }

    fn build_request(&self, url: &str) -> Request {
        let token = String::from("token ") + &self.conf.token;
        let mut req: Request = Request::new(Method::Get, url.parse().unwrap());
        req.headers_mut().set(header::Authorization(token));
        req.headers_mut().set(header::UserAgent::new("sectora"));
        req
    }

    fn build_page_request(&self, url: &str, page: u64) -> Request {
        let sep = if url.contains("?") { "&" } else { "?" };
        let url_p = format!("{}{}page={}", url, sep, page);
        self.build_request(&url_p)
    }

    fn run_request(&self, req: Request) -> Result<serde_json::value::Value, CliError> {
        let mut core = reactor::Core::new()?;
        let client = Client::configure().connector(HttpsConnector::new(4, &core.handle()))
                                        .build(&core.handle());
        let to_io = |e| std::io::Error::new(std::io::ErrorKind::Other, e);
        let parse_body = |body: Chunk| Ok(serde_json::from_slice(&body).map_err(to_io)?);
        let handle_response = |res: Response| res.body().concat2().and_then(parse_body);
        Ok(core.run(client.request(req).and_then(handle_response))?)
    }

    fn get_contents_from_url_page(&self, url: &str, page: u64) -> Result<Vec<serde_json::value::Value>, CliError> {
        let req = self.build_page_request(url, page);
        self.run_request(req).and_then(|v| serde_json::from_value(v).map_err(CliError::from))
    }

    fn get_contents(&self, url: &str) -> Result<String, CliError> {
        match self.load_contents_from_cache(url) {
            Ok((metadata, cache_contents)) => match std::time::SystemTime::now().duration_since(metadata.modified()?) {
                Ok(caching_duration) => {
                    if caching_duration.as_secs() > self.conf.cache_duration {
                        match self.get_contents_from_url(url) {
                            Ok(contents_from_url) => Ok(contents_from_url),
                            Err(_) => Ok(cache_contents),
                        }
                    } else {
                        Ok(cache_contents)
                    }
                }
                Err(_) => Ok(cache_contents),
            },
            Err(_) => self.get_contents_from_url(url),
        }
    }

    #[allow(dead_code)]
    pub fn print_user_public_key(&self, user: &str) -> Result<(), CliError> {
        let keys = self.get_user_public_key(user)?;
        println!("{}", keys);
        Ok(())
    }

    fn get_user_public_key(&self, user: &str) -> Result<String, CliError> {
        let url = format!("{}/users/{}/keys", self.conf.endpoint, user);
        let contents = self.get_contents(&url)?;
        let keys = serde_json::from_str::<Vec<PublicKey>>(&contents)?;
        Ok(keys.iter().map(|k| k.key.clone()).collect::<Vec<String>>().join("\n"))
    }

    #[allow(dead_code)]
    pub fn check_pam(&self, user: &str) -> Result<bool, CliError> {
        let sectors = self.get_sectors()?;
        Ok(sectors.iter().any(|team| team.members.contains_key(user)))
    }

    pub fn get_sectors(&self) -> Result<Vec<SectorGroup>, CliError> {
        let mut sectors: Vec<SectorGroup> = self.get_teams_result()?;
        sectors.append(&mut self.get_repos_result()?);
        Ok(sectors)
    }

    fn get_teams_result(&self) -> Result<Vec<SectorGroup>, CliError> {
        let gh_teams = self.get_team_map()?;
        let mut teams = Vec::new();
        for team_conf in &self.conf.team {
            if let &Some(gh_team) = &gh_teams.get(&team_conf.name) {
                teams.push(SectorGroup { sector: Sector::from(gh_team.clone()),
                                         gid: team_conf.gid.clone(),
                                         group: team_conf.group.clone(),
                                         members: self.get_team_members(gh_team.id)?, });
            }
        }
        Ok(teams)
    }

    fn get_team_map(&self) -> Result<HashMap<String, Team>, CliError> {
        let url = format!("{}/orgs/{}/teams", self.conf.endpoint, self.conf.org);
        let contents = self.get_contents(&url)?;
        let teams = serde_json::from_str::<Vec<Team>>(&contents)?;
        Ok(teams.iter().map(|t| (t.name.clone(), t.clone())).collect())
    }

    fn get_team_members(&self, mid: u64) -> Result<HashMap<String, Member>, CliError> {
        let url = format!("{}/teams/{}/members", self.conf.endpoint, mid);
        let contents = self.get_contents(&url)?;
        let members = serde_json::from_str::<Vec<Member>>(&contents)?;
        Ok(members.iter().map(|m| (m.login.clone(), m.clone())).collect())
    }

    fn get_repos_result(&self) -> Result<Vec<SectorGroup>, CliError> {
        let gh_repos = self.get_repo_map()?;
        let mut repos = Vec::new();
        for repo_conf in &self.conf.repo {
            if let &Some(gh_repo) = &gh_repos.get(&repo_conf.name) {
                repos.push(SectorGroup { sector: Sector::from(gh_repo.clone()),
                                         gid: repo_conf.gid.clone(),
                                         group: repo_conf.group.clone(),
                                         members: self.get_repo_collaborators(&gh_repo.name)?, });
            }
        }
        Ok(repos)
    }

    fn get_repo_map(&self) -> Result<HashMap<String, Repo>, CliError> {
        let url = format!("{}/orgs/{}/repos", self.conf.endpoint, self.conf.org);
        let contents = self.get_contents(&url)?;
        let repos = serde_json::from_str::<Vec<Repo>>(&contents)?;
        Ok(repos.iter().map(|t| (t.name.clone(), t.clone())).collect())
    }

    fn get_repo_collaborators(&self, repo_name: &str) -> Result<HashMap<String, Member>, CliError> {
        let url = format!("{}/repos/{}/{}/collaborators?affiliation=outside",
                          self.conf.endpoint, self.conf.org, repo_name);
        let contents = self.get_contents(&url)?;
        let members = serde_json::from_str::<Vec<Member>>(&contents)?;
        Ok(members.iter().map(|m| (m.login.clone(), m.clone())).collect())
    }

    fn get_rate_limit(&self) -> Result<RateLimit, CliError> {
        let url = format!("{}/rate_limit", self.conf.endpoint);
        let req = self.build_request(&url);
        self.run_request(req).and_then(|v| serde_json::from_value(v).map_err(CliError::from))
    }

    #[allow(dead_code)]
    pub fn print_rate_limit(&self) -> Result<(), CliError> {
        let rate_limit = self.get_rate_limit()?;
        println!("{:?}", rate_limit);
        Ok(())
    }

    #[allow(dead_code)]
    pub fn clear_all_caches(&self) -> Result<(), CliError> {
        let mut path = std::env::temp_dir();
        path.push(TEMP_DIRNAME);
        path.push("**/*");
        for entry in glob(&path.to_str().unwrap()).unwrap() {
            match entry {
                Ok(path) => {
                    if path.is_file() {
                        std::fs::remove_file(path)?
                    }
                }
                Err(e) => println!("{:?}", e),
            }
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>extern crate clap;
#[macro_use] extern crate log;
extern crate semver;
extern crate toml;
#[macro_use] extern crate version;

extern crate libimagstore;
extern crate libimagrt;
extern crate libimagentrytag;
extern crate libimagerror;

use std::process::exit;

use libimagrt::runtime::Runtime;
use libimagentrytag::tagable::Tagable;
use libimagstore::storeid::build_entry_path;
use libimagerror::trace::trace_error;

mod ui;

use ui::build_ui;

fn main() {
    let name = "imag-store";
    let version = &version!()[..];
    let about = "Direct interface to the store. Use with great care!";
    let ui = build_ui(Runtime::get_default_cli_builder(name, version, about));
    let rt = {
        let rt = Runtime::new(ui);
        if rt.is_ok() {
            rt.unwrap()
        } else {
            println!("Could not set up Runtime");
            println!("{:?}", rt.unwrap_err());
            exit(1);
        }
    };

    let id = rt.cli().value_of("id").unwrap(); // enforced by clap
    rt.cli()
        .subcommand_name()
        .map_or_else(
            || {
                let add = rt.cli().values_of("add").map(|o| o.map(String::from));
                let rem = rt.cli().values_of("remove").map(|o| o.map(String::from));

                alter(&rt, id, add, rem);
            },
            |name| {
                debug!("Call: {}", name);
                match name {
                    "list" => list(id, &rt),
                    _ => {
                        warn!("Unknown command");
                        // More error handling
                    },
                };
            });
}

fn alter<SI: Iterator<Item = String>>(rt: &Runtime, id: &str, add: Option<SI>, rem: Option<SI>) {
    let path = {
        match build_entry_path(rt.store(), id) {
            Err(e) => {
                trace_error(&e);
                exit(1);
            },
            Ok(s) => s,
        }
    };
    debug!("path = {:?}", path);

    rt.store()
        // "id" must be present, enforced via clap spec
        .retrieve(path)
        .map(|mut e| {
            add.map(|tags| {
                for tag in tags {
                    debug!("Adding tag '{:?}'", tag);
                    if let Err(e) = e.add_tag(tag) {
                        trace_error(&e);
                    }
                }
            }); // it is okay to ignore a None here

            rem.map(|tags| {
                for tag in tags {
                    debug!("Removing tag '{:?}'", tag);
                    if let Err(e) = e.remove_tag(tag) {
                        trace_error(&e);
                    }
                }
            }); // it is okay to ignore a None here
        })
        .map_err(|e| {
            info!("No entry.");
            trace_error(&e);
        })
        .ok();
}

fn list(id: &str, rt: &Runtime) {
    let path = {
        match build_entry_path(rt.store(), id) {
            Err(e) => {
                trace_error(&e);
                exit(1);
            },
            Ok(s) => s,
        }
    };
    debug!("path = {:?}", path);

    let entry = rt.store().retrieve(path.clone());
    if entry.is_err() {
        debug!("Could not retrieve '{:?}' => {:?}", id, path);
        warn!("Could not retrieve entry '{}'", id);
        trace_error(&entry.unwrap_err());
        exit(1);
    }
    let entry = entry.unwrap();

    let scmd = rt.cli().subcommand_matches("list").unwrap(); // safe, we checked in main()

    let json_out = scmd.is_present("json");
    let line_out = scmd.is_present("linewise");
    let sepp_out = scmd.is_present("sep");
    let mut comm_out = scmd.is_present("commasep");

    if !vec![json_out, line_out, comm_out, sepp_out].iter().any(|v| *v) {
        // None of the flags passed, go to default
        comm_out = true;
    }

    let tags = entry.get_tags();
    if tags.is_err() {
        trace_error(&tags.unwrap_err());
        exit(1);
    }
    let tags = tags.unwrap();

    if json_out {
        unimplemented!()
    }

    if line_out {
        for tag in &tags {
            println!("{}", tag);
        }
    }

    if sepp_out {
        let sepp = scmd.value_of("sep").unwrap(); // we checked before
        println!("{}", tags.join(sepp));
    }

    if comm_out {
        println!("{}", tags.join(", "));
    }
}

<commit_msg>imag-tag: Remove setup code and use helper<commit_after>extern crate clap;
#[macro_use] extern crate log;
extern crate semver;
extern crate toml;
#[macro_use] extern crate version;

extern crate libimagstore;
extern crate libimagrt;
extern crate libimagentrytag;
extern crate libimagerror;

use std::process::exit;

use libimagrt::runtime::Runtime;
use libimagrt::setup::generate_runtime_setup;
use libimagentrytag::tagable::Tagable;
use libimagstore::storeid::build_entry_path;
use libimagerror::trace::trace_error;

mod ui;

use ui::build_ui;

fn main() {
    let rt = generate_runtime_setup("imag-store",
                                    &version!()[..],
                                    "Direct interface to the store. Use with great care!",
                                    build_ui);

    let id = rt.cli().value_of("id").unwrap(); // enforced by clap
    rt.cli()
        .subcommand_name()
        .map_or_else(
            || {
                let add = rt.cli().values_of("add").map(|o| o.map(String::from));
                let rem = rt.cli().values_of("remove").map(|o| o.map(String::from));

                alter(&rt, id, add, rem);
            },
            |name| {
                debug!("Call: {}", name);
                match name {
                    "list" => list(id, &rt),
                    _ => {
                        warn!("Unknown command");
                        // More error handling
                    },
                };
            });
}

fn alter<SI: Iterator<Item = String>>(rt: &Runtime, id: &str, add: Option<SI>, rem: Option<SI>) {
    let path = {
        match build_entry_path(rt.store(), id) {
            Err(e) => {
                trace_error(&e);
                exit(1);
            },
            Ok(s) => s,
        }
    };
    debug!("path = {:?}", path);

    rt.store()
        // "id" must be present, enforced via clap spec
        .retrieve(path)
        .map(|mut e| {
            add.map(|tags| {
                for tag in tags {
                    debug!("Adding tag '{:?}'", tag);
                    if let Err(e) = e.add_tag(tag) {
                        trace_error(&e);
                    }
                }
            }); // it is okay to ignore a None here

            rem.map(|tags| {
                for tag in tags {
                    debug!("Removing tag '{:?}'", tag);
                    if let Err(e) = e.remove_tag(tag) {
                        trace_error(&e);
                    }
                }
            }); // it is okay to ignore a None here
        })
        .map_err(|e| {
            info!("No entry.");
            trace_error(&e);
        })
        .ok();
}

fn list(id: &str, rt: &Runtime) {
    let path = {
        match build_entry_path(rt.store(), id) {
            Err(e) => {
                trace_error(&e);
                exit(1);
            },
            Ok(s) => s,
        }
    };
    debug!("path = {:?}", path);

    let entry = rt.store().retrieve(path.clone());
    if entry.is_err() {
        debug!("Could not retrieve '{:?}' => {:?}", id, path);
        warn!("Could not retrieve entry '{}'", id);
        trace_error(&entry.unwrap_err());
        exit(1);
    }
    let entry = entry.unwrap();

    let scmd = rt.cli().subcommand_matches("list").unwrap(); // safe, we checked in main()

    let json_out = scmd.is_present("json");
    let line_out = scmd.is_present("linewise");
    let sepp_out = scmd.is_present("sep");
    let mut comm_out = scmd.is_present("commasep");

    if !vec![json_out, line_out, comm_out, sepp_out].iter().any(|v| *v) {
        // None of the flags passed, go to default
        comm_out = true;
    }

    let tags = entry.get_tags();
    if tags.is_err() {
        trace_error(&tags.unwrap_err());
        exit(1);
    }
    let tags = tags.unwrap();

    if json_out {
        unimplemented!()
    }

    if line_out {
        for tag in &tags {
            println!("{}", tag);
        }
    }

    if sepp_out {
        let sepp = scmd.value_of("sep").unwrap(); // we checked before
        println!("{}", tags.join(sepp));
    }

    if comm_out {
        println!("{}", tags.join(", "));
    }
}

<|endoftext|>


<commit_before>//! Related to out filenames of compilation (e.g. save analysis, binaries).
use crate::config::{CrateType, Input, OutputFilenames, OutputType};
use crate::Session;
use rustc_ast as ast;
use rustc_span::symbol::sym;
use rustc_span::Span;
use std::path::{Path, PathBuf};

pub fn out_filename(
    sess: &Session,
    crate_type: CrateType,
    outputs: &OutputFilenames,
    crate_name: &str,
) -> PathBuf {
    let default_filename = filename_for_input(sess, crate_type, crate_name, outputs);
    let out_filename = outputs
        .outputs
        .get(&OutputType::Exe)
        .and_then(|s| s.to_owned())
        .or_else(|| outputs.single_output_file.clone())
        .unwrap_or(default_filename);

    check_file_is_writeable(&out_filename, sess);

    out_filename
}

/// Make sure files are writeable.  Mac, FreeBSD, and Windows system linkers
/// check this already -- however, the Linux linker will happily overwrite a
/// read-only file.  We should be consistent.
pub fn check_file_is_writeable(file: &Path, sess: &Session) {
    if !is_writeable(file) {
        sess.fatal(&format!(
            "output file {} is not writeable -- check its \
                            permissions",
            file.display()
        ));
    }
}

fn is_writeable(p: &Path) -> bool {
    match p.metadata() {
        Err(..) => true,
        Ok(m) => !m.permissions().readonly(),
    }
}

pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input) -> String {
    let validate = |s: String, span: Option<Span>| {
        validate_crate_name(sess, &s, span);
        s
    };

    // Look in attributes 100% of the time to make sure the attribute is marked
    // as used. After doing this, however, we still prioritize a crate name from
    // the command line over one found in the #[crate_name] attribute. If we
    // find both we ensure that they're the same later on as well.
    let attr_crate_name =
        sess.find_by_name(attrs, sym::crate_name).and_then(|at| at.value_str().map(|s| (at, s)));

    if let Some(ref s) = sess.opts.crate_name {
        if let Some((attr, name)) = attr_crate_name {
            if name.as_str() != *s {
                let msg = format!(
                    "`--crate-name` and `#[crate_name]` are \
                                   required to match, but `{}` != `{}`",
                    s, name
                );
                sess.span_err(attr.span, &msg);
            }
        }
        return validate(s.clone(), None);
    }

    if let Some((attr, s)) = attr_crate_name {
        return validate(s.to_string(), Some(attr.span));
    }
    if let Input::File(ref path) = *input {
        if let Some(s) = path.file_stem().and_then(|s| s.to_str()) {
            if s.starts_with('-') {
                let msg = format!(
                    "crate names cannot start with a `-`, but \
                                   `{}` has a leading hyphen",
                    s
                );
                sess.err(&msg);
            } else {
                return validate(s.replace("-", "_"), None);
            }
        }
    }

    "rust_out".to_string()
}

pub fn validate_crate_name(sess: &Session, s: &str, sp: Option<Span>) {
    let mut err_count = 0;
    {
        let mut say = |s: &str| {
            match sp {
                Some(sp) => sess.span_err(sp, s),
                None => sess.err(s),
            }
            err_count += 1;
        };
        if s.is_empty() {
            say("crate name must not be empty");
        }
        for c in s.chars() {
            if c.is_alphanumeric() {
                continue;
            }
            if c == '_' {
                continue;
            }
            say(&format!("invalid character `{}` in crate name: `{}`", c, s));
        }
    }

    if err_count > 0 {
        sess.abort_if_errors();
    }
}

pub fn filename_for_metadata(
    sess: &Session,
    crate_name: &str,
    outputs: &OutputFilenames,
) -> PathBuf {
    let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename);

    let out_filename = outputs
        .single_output_file
        .clone()
        .unwrap_or_else(|| outputs.out_directory.join(&format!("lib{}.rmeta", libname)));

    check_file_is_writeable(&out_filename, sess);

    out_filename
}

pub fn filename_for_input(
    sess: &Session,
    crate_type: CrateType,
    crate_name: &str,
    outputs: &OutputFilenames,
) -> PathBuf {
    let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename);

    match crate_type {
        CrateType::Rlib => outputs.out_directory.join(&format!("lib{}.rlib", libname)),
        CrateType::Cdylib | CrateType::ProcMacro | CrateType::Dylib => {
            let (prefix, suffix) = (&sess.target.dll_prefix, &sess.target.dll_suffix);
            outputs.out_directory.join(&format!("{}{}{}", prefix, libname, suffix))
        }
        CrateType::Staticlib => {
            let (prefix, suffix) = (&sess.target.staticlib_prefix, &sess.target.staticlib_suffix);
            outputs.out_directory.join(&format!("{}{}{}", prefix, libname, suffix))
        }
        CrateType::Executable => {
            let suffix = &sess.target.exe_suffix;
            let out_filename = outputs.path(OutputType::Exe);
            if suffix.is_empty() { out_filename } else { out_filename.with_extension(&suffix[1..]) }
        }
    }
}

/// Returns default crate type for target
///
/// Default crate type is used when crate type isn't provided neither
/// through cmd line arguments nor through crate attributes
///
/// It is CrateType::Executable for all platforms but iOS as there is no
/// way to run iOS binaries anyway without jailbreaking and
/// interaction with Rust code through static library is the only
/// option for now
pub fn default_output_for_target(sess: &Session) -> CrateType {
    if !sess.target.executables { CrateType::Staticlib } else { CrateType::Executable }
}

/// Checks if target supports crate_type as output
pub fn invalid_output_for_target(sess: &Session, crate_type: CrateType) -> bool {
    match crate_type {
        CrateType::Cdylib | CrateType::Dylib | CrateType::ProcMacro => {
            if !sess.target.dynamic_linking {
                return true;
            }
            if sess.crt_static(Some(crate_type)) && !sess.target.crt_static_allows_dylibs {
                return true;
            }
        }
        _ => {}
    }
    if sess.target.only_cdylib {
        match crate_type {
            CrateType::ProcMacro | CrateType::Dylib => return true,
            _ => {}
        }
    }
    if !sess.target.executables && crate_type == CrateType::Executable {
        return true;
    }

    false
}
<commit_msg>Use command line metadata path if provided<commit_after>//! Related to out filenames of compilation (e.g. save analysis, binaries).
use crate::config::{CrateType, Input, OutputFilenames, OutputType};
use crate::Session;
use rustc_ast as ast;
use rustc_span::symbol::sym;
use rustc_span::Span;
use std::path::{Path, PathBuf};

pub fn out_filename(
    sess: &Session,
    crate_type: CrateType,
    outputs: &OutputFilenames,
    crate_name: &str,
) -> PathBuf {
    let default_filename = filename_for_input(sess, crate_type, crate_name, outputs);
    let out_filename = outputs
        .outputs
        .get(&OutputType::Exe)
        .and_then(|s| s.to_owned())
        .or_else(|| outputs.single_output_file.clone())
        .unwrap_or(default_filename);

    check_file_is_writeable(&out_filename, sess);

    out_filename
}

/// Make sure files are writeable.  Mac, FreeBSD, and Windows system linkers
/// check this already -- however, the Linux linker will happily overwrite a
/// read-only file.  We should be consistent.
pub fn check_file_is_writeable(file: &Path, sess: &Session) {
    if !is_writeable(file) {
        sess.fatal(&format!(
            "output file {} is not writeable -- check its \
                            permissions",
            file.display()
        ));
    }
}

fn is_writeable(p: &Path) -> bool {
    match p.metadata() {
        Err(..) => true,
        Ok(m) => !m.permissions().readonly(),
    }
}

pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input) -> String {
    let validate = |s: String, span: Option<Span>| {
        validate_crate_name(sess, &s, span);
        s
    };

    // Look in attributes 100% of the time to make sure the attribute is marked
    // as used. After doing this, however, we still prioritize a crate name from
    // the command line over one found in the #[crate_name] attribute. If we
    // find both we ensure that they're the same later on as well.
    let attr_crate_name =
        sess.find_by_name(attrs, sym::crate_name).and_then(|at| at.value_str().map(|s| (at, s)));

    if let Some(ref s) = sess.opts.crate_name {
        if let Some((attr, name)) = attr_crate_name {
            if name.as_str() != *s {
                let msg = format!(
                    "`--crate-name` and `#[crate_name]` are \
                                   required to match, but `{}` != `{}`",
                    s, name
                );
                sess.span_err(attr.span, &msg);
            }
        }
        return validate(s.clone(), None);
    }

    if let Some((attr, s)) = attr_crate_name {
        return validate(s.to_string(), Some(attr.span));
    }
    if let Input::File(ref path) = *input {
        if let Some(s) = path.file_stem().and_then(|s| s.to_str()) {
            if s.starts_with('-') {
                let msg = format!(
                    "crate names cannot start with a `-`, but \
                                   `{}` has a leading hyphen",
                    s
                );
                sess.err(&msg);
            } else {
                return validate(s.replace("-", "_"), None);
            }
        }
    }

    "rust_out".to_string()
}

pub fn validate_crate_name(sess: &Session, s: &str, sp: Option<Span>) {
    let mut err_count = 0;
    {
        let mut say = |s: &str| {
            match sp {
                Some(sp) => sess.span_err(sp, s),
                None => sess.err(s),
            }
            err_count += 1;
        };
        if s.is_empty() {
            say("crate name must not be empty");
        }
        for c in s.chars() {
            if c.is_alphanumeric() {
                continue;
            }
            if c == '_' {
                continue;
            }
            say(&format!("invalid character `{}` in crate name: `{}`", c, s));
        }
    }

    if err_count > 0 {
        sess.abort_if_errors();
    }
}

pub fn filename_for_metadata(
    sess: &Session,
    crate_name: &str,
    outputs: &OutputFilenames,
) -> PathBuf {
    // If the command-line specified the path, use that directly.
    if let Some(Some(out_filename)) = sess.opts.output_types.get(&OutputType::Metadata) {
        return out_filename.clone();
    }

    let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename);

    let out_filename = outputs
        .single_output_file
        .clone()
        .unwrap_or_else(|| outputs.out_directory.join(&format!("lib{}.rmeta", libname)));

    check_file_is_writeable(&out_filename, sess);

    out_filename
}

pub fn filename_for_input(
    sess: &Session,
    crate_type: CrateType,
    crate_name: &str,
    outputs: &OutputFilenames,
) -> PathBuf {
    let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename);

    match crate_type {
        CrateType::Rlib => outputs.out_directory.join(&format!("lib{}.rlib", libname)),
        CrateType::Cdylib | CrateType::ProcMacro | CrateType::Dylib => {
            let (prefix, suffix) = (&sess.target.dll_prefix, &sess.target.dll_suffix);
            outputs.out_directory.join(&format!("{}{}{}", prefix, libname, suffix))
        }
        CrateType::Staticlib => {
            let (prefix, suffix) = (&sess.target.staticlib_prefix, &sess.target.staticlib_suffix);
            outputs.out_directory.join(&format!("{}{}{}", prefix, libname, suffix))
        }
        CrateType::Executable => {
            let suffix = &sess.target.exe_suffix;
            let out_filename = outputs.path(OutputType::Exe);
            if suffix.is_empty() { out_filename } else { out_filename.with_extension(&suffix[1..]) }
        }
    }
}

/// Returns default crate type for target
///
/// Default crate type is used when crate type isn't provided neither
/// through cmd line arguments nor through crate attributes
///
/// It is CrateType::Executable for all platforms but iOS as there is no
/// way to run iOS binaries anyway without jailbreaking and
/// interaction with Rust code through static library is the only
/// option for now
pub fn default_output_for_target(sess: &Session) -> CrateType {
    if !sess.target.executables { CrateType::Staticlib } else { CrateType::Executable }
}

/// Checks if target supports crate_type as output
pub fn invalid_output_for_target(sess: &Session, crate_type: CrateType) -> bool {
    match crate_type {
        CrateType::Cdylib | CrateType::Dylib | CrateType::ProcMacro => {
            if !sess.target.dynamic_linking {
                return true;
            }
            if sess.crt_static(Some(crate_type)) && !sess.target.crt_static_allows_dylibs {
                return true;
            }
        }
        _ => {}
    }
    if sess.target.only_cdylib {
        match crate_type {
            CrateType::ProcMacro | CrateType::Dylib => return true,
            _ => {}
        }
    }
    if !sess.target.executables && crate_type == CrateType::Executable {
        return true;
    }

    false
}
<|endoftext|>


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

use actor::{Actor, ActorMessageStatus, ActorRegistry};
use serde_json::{Map, Value};
use std::net::TcpStream;
use protocol::{ActorDescription,  Method};
use protocol::JsonPacketStream;

#[derive(Serialize)]
struct GetDescriptionReply {
    from: String,
    value: SystemInfo,
}

#[derive(Serialize)]
struct SystemInfo {
    apptype: String,
    platformVersion: String,
}

pub struct DeviceActor {
    pub name: String,
}

impl Actor for DeviceActor {
    fn name(&self) -> String {
        self.name.clone()
    }
    fn handle_message(
        &self,
        _registry: &ActorRegistry,
        msg_type: &str,
        _msg: &Map<String, Value>,
        stream: &mut TcpStream,
    ) -> Result<ActorMessageStatus, ()> {

        Ok(match msg_type {
            "getDescription" => {

                let msg = GetDescriptionReply {
                    from: self.name(),
                    value: SystemInfo {
                        apptype: "servo".to_string(),
                        platformVersion: "63.0".to_string(),
                    }
                };
                stream.write_json_packet(&msg);
                ActorMessageStatus::Processed
            },

            _ => ActorMessageStatus::Ignored,
        })
    }
}

impl DeviceActor {
    pub fn new(name: String) -> DeviceActor {
        DeviceActor { name: name }
    }

    pub fn description() -> ActorDescription {
        ActorDescription {
            category: "actor",
            typeName: "device",
            methods: vec![Method {
                name: "getDescription",
                request: Value::Null,
                response: Value::Object(
                    vec![(
                        "value".to_owned(),
                        Value::Object(
                            vec![("_retval".to_owned(), Value::String("json".to_owned()))]
                                .into_iter()
                                .collect(),
                        ),
                    )].into_iter()
                    .collect(),
                ),
            }],
        }
    }
}

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

use actor::{Actor, ActorMessageStatus, ActorRegistry};
use protocol::{ActorDescription,  Method};
use protocol::JsonPacketStream;
use serde_json::{Map, Value};
use std::net::TcpStream;

#[derive(Serialize)]
struct GetDescriptionReply {
    from: String,
    value: SystemInfo,
}

#[derive(Serialize)]
struct SystemInfo {
    apptype: String,
    platformVersion: String,
}

pub struct DeviceActor {
    pub name: String,
}

impl Actor for DeviceActor {
    fn name(&self) -> String {
        self.name.clone()
    }
    fn handle_message(
        &self,
        _registry: &ActorRegistry,
        msg_type: &str,
        _msg: &Map<String, Value>,
        stream: &mut TcpStream,
    ) -> Result<ActorMessageStatus, ()> {
        Ok(match msg_type {
            "getDescription" => {
                let msg = GetDescriptionReply {
                    from: self.name(),
                    value: SystemInfo {
                        apptype: "servo".to_string(),
                        platformVersion: "63.0".to_string(),
                    }
                };
                stream.write_json_packet(&msg);
                ActorMessageStatus::Processed
            },

            _ => ActorMessageStatus::Ignored,
        })
    }
}

impl DeviceActor {
    pub fn new(name: String) -> DeviceActor {
        DeviceActor { name: name }
    }

    pub fn description() -> ActorDescription {
        ActorDescription {
            category: "actor",
            typeName: "device",
            methods: vec![Method {
                name: "getDescription",
                request: Value::Null,
                response: Value::Object(
                    vec![(
                        "value".to_owned(),
                        Value::Object(
                            vec![("_retval".to_owned(), Value::String("json".to_owned()))]
                                .into_iter()
                                .collect(),
                        ),
                    )].into_iter()
                    .collect(),
                ),
            }],
        }
    }
}

<|endoftext|>


<commit_before>use std::net::{Ipv4Addr, Ipv6Addr};
use Ipv4Network;
use Ipv6Network;
use helpers;

#[cfg(target_pointer_width = "16")]
const POINTER_WIDTH: u32 = 16;
#[cfg(target_pointer_width = "32")]
const POINTER_WIDTH: u32 = 32;
#[cfg(target_pointer_width = "64")]
const POINTER_WIDTH: u32 = 64;
#[cfg(target_pointer_width = "128")]
const POINTER_WIDTH: u32 = 128;

/// IPv4 range iterator
pub struct Ipv4RangeIterator {
    current: u32,
    to: u32,
    is_done: bool,
}

impl Ipv4RangeIterator {
    /// Constructs new `Ipv4RangeIterator`, both `from` and `to` address are inclusive.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::net::Ipv4Addr;
    /// use ip_network::iterator::Ipv4RangeIterator;
    ///
    /// let mut iterator = Ipv4RangeIterator::new(
    ///     Ipv4Addr::new(192, 168, 2, 0),
    ///     Ipv4Addr::new(192, 168, 2, 255)
    /// );
    /// assert_eq!(iterator.next().unwrap(), Ipv4Addr::new(192, 168, 2, 0));
    /// assert_eq!(iterator.next().unwrap(), Ipv4Addr::new(192, 168, 2, 1));
    /// assert_eq!(iterator.last().unwrap(), Ipv4Addr::new(192, 168, 2, 255));
    /// ```
    pub fn new(from: Ipv4Addr, to: Ipv4Addr) -> Self {
        let current = u32::from(from);
        let to = u32::from(to);
        assert!(to >= current);
        Self { current, to, is_done: false }
    }
}

impl Iterator for Ipv4RangeIterator {
    type Item = Ipv4Addr;

    fn next(&mut self) -> Option<Self::Item> {
        if self.current <= self.to && !self.is_done {
            let output = self.current;

            match self.current.checked_add(1) {
                Some(x) => self.current = x,
                None => self.is_done = true,
            };

            Some(Self::Item::from(output))
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        if self.is_done {
            return (0, Some(0))
        }

        let remaining = (self.to - self.current + 1) as usize;
        (remaining, Some(remaining))
    }
}

impl ExactSizeIterator for Ipv4RangeIterator {}

/// Iterates over new created IPv4 network from given network
pub struct Ipv4NetworkIterator {
    current: u32,
    to: u32,
    new_netmask: u8,
    is_done: bool,
}

impl Ipv4NetworkIterator {
    // TODO: Change assert to error?
    pub fn new(network: Ipv4Network, new_netmask: u8) -> Self {
        assert!(network.get_netmask() < new_netmask);
        assert!(new_netmask <= 32);

        let current = u32::from(network.get_network_address());
        let mask = !helpers::get_bite_mask(32 - (new_netmask - network.get_netmask())) << (32 - new_netmask);
        let to = current | mask;

        Self {
            current,
            to,
            new_netmask,
            is_done: false,
        }
    }

    #[inline]
    fn step(&self) -> u32 {
        1 << (32 - self.new_netmask)
    }
}

impl Iterator for Ipv4NetworkIterator {
    type Item = Ipv4Network;

    fn next(&mut self) -> Option<Self::Item> {
        if self.current <= self.to && !self.is_done {
            let output = self.current;

            match self.current.checked_add(self.step()) {
                Some(x) => self.current = x,
                None => self.is_done = true,
            };

            Some(Self::Item::from(Ipv4Addr::from(output), self.new_netmask).unwrap())
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        if self.is_done {
            return (0, Some(0))
        }

        let remaining = ((self.to - self.current) / self.step() + 1) as usize;
        (remaining, Some(remaining))
    }
}

impl ExactSizeIterator for Ipv4NetworkIterator {}

/// Iterates over new created IPv6 network from given network
pub struct Ipv6NetworkIterator {
    current: u128,
    to: u128,
    new_netmask: u8,
    is_done: bool,
}

impl Ipv6NetworkIterator {
    // TODO: Change assert to error?
    pub fn new(network: Ipv6Network, new_netmask: u8) -> Self {
        assert!(network.get_netmask() < new_netmask);
        assert!(new_netmask <= 128);

        let current = u128::from(network.get_network_address());
        let mask = !helpers::get_bite_mask_u128(128 - (new_netmask - network.get_netmask())) << (128 - new_netmask);
        let to = current | mask;

        Self {
            current,
            to,
            new_netmask,
            is_done: false,
        }
    }

    #[inline]
    fn step(&self) -> u128 {
        1 << (128 - self.new_netmask)
    }

    pub fn real_len(&self) -> u128 {
        if self.is_done {
            return 0;
        }

        ((self.to - self.current) / self.step()).saturating_add(1)
    }
}

impl Iterator for Ipv6NetworkIterator {
    type Item = Ipv6Network;

    fn next(&mut self) -> Option<Self::Item> {
        if self.current <= self.to && !self.is_done {
            let output = self.current;

            match self.current.checked_add(self.step()) {
                Some(x) => self.current = x,
                None => self.is_done = true,
            };

            Some(Self::Item::from(Ipv6Addr::from(output), self.new_netmask).unwrap())
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let remaining = self.real_len();

        if 128 - remaining.leading_zeros() > POINTER_WIDTH {
            (::std::usize::MAX, None)
        } else {
            let remaining_u64 = remaining as u64;
            (remaining_u64 as usize, Some(remaining_u64 as usize))
        }
    }
}

impl ExactSizeIterator for Ipv6NetworkIterator {}

#[cfg(test)]
mod tests {
    use std::net::{Ipv4Addr, Ipv6Addr};
    use {Ipv4Network, Ipv6Network};
    use super::{Ipv4NetworkIterator, Ipv4RangeIterator, Ipv6NetworkIterator};

    #[test]
    fn test_ipv4_range_iterator() {
        let mut iterator = Ipv4RangeIterator::new(
            Ipv4Addr::new(192, 168, 2, 0),
            Ipv4Addr::new(192, 168, 2, 255)
        );
        assert_eq!(iterator.next().unwrap(), Ipv4Addr::new(192, 168, 2, 0));
        assert_eq!(iterator.next().unwrap(), Ipv4Addr::new(192, 168, 2, 1));
        assert_eq!(iterator.last().unwrap(), Ipv4Addr::new(192, 168, 2, 255));
    }

    #[test]
    fn test_ipv4_range_iterator_length() {
        let mut iterator = Ipv4RangeIterator::new(
            Ipv4Addr::new(192, 168, 2, 0),
            Ipv4Addr::new(192, 168, 2, 255)
        );
        assert_eq!(iterator.len(), 256);
        iterator.next().unwrap();
        assert_eq!(iterator.len(), 255);
        assert_eq!(iterator.collect::<Vec<_>>().len(), 255);
    }

    #[test]
    fn test_ipv4_range_iterator_same_values() {
        let mut iterator = Ipv4RangeIterator::new(
            Ipv4Addr::new(255, 255, 255, 255),
            Ipv4Addr::new(255, 255, 255, 255)
        );
        assert_eq!(iterator.len(), 1);
        assert_eq!(iterator.next().unwrap(), Ipv4Addr::new(255, 255, 255, 255));
        assert!(iterator.next().is_none());
        assert_eq!(iterator.len(), 0);
    }

    #[test]
    fn test_ipv4_network_iterator() {
        let network = Ipv4Network::from(Ipv4Addr::new(127, 0, 0, 0), 8).unwrap();
        let mut iterator = Ipv4NetworkIterator::new(network, 16);

        assert_eq!(iterator.len(), 256);
        assert_eq!(iterator.next().unwrap(), Ipv4Network::from(Ipv4Addr::new(127, 0, 0, 0), 16).unwrap());
        assert_eq!(iterator.next().unwrap(), Ipv4Network::from(Ipv4Addr::new(127, 1, 0, 0), 16).unwrap());
        assert_eq!(iterator.next().unwrap(), Ipv4Network::from(Ipv4Addr::new(127, 2, 0, 0), 16).unwrap());
        assert_eq!(iterator.last().unwrap(), Ipv4Network::from(Ipv4Addr::new(127, 255, 0, 0), 16).unwrap());
    }

    #[test]
    fn test_ipv4_network_iterator_len() {
        let network = Ipv4Network::from(Ipv4Addr::new(127, 0, 0, 0), 8).unwrap();
        let iterator = Ipv4NetworkIterator::new(network, 16);
        assert_eq!(256, iterator.len());
    }

    #[test]
    fn test_ipv6_network_iterator() {
        let ip = Ipv6Addr::new(0x2001, 0, 0, 0, 0, 0, 0, 0);
        let network = Ipv6Network::from(ip, 16).unwrap();
        let mut iterator = Ipv6NetworkIterator::new(network, 17);

        assert_eq!(2, iterator.len());
        assert_eq!(iterator.next().unwrap(), Ipv6Network::from(ip, 17).unwrap());
        assert_eq!(iterator.next().unwrap(), Ipv6Network::from(Ipv6Addr::new(0x2001, 0x8000, 0, 0, 0, 0, 0, 0), 17).unwrap());
        assert!(iterator.next().is_none());
    }

    #[test]
    #[should_panic] // because range is bigger than `usize` on 64bit machine
    fn test_ipv6_network_iterator_whole_range_len() {
        let ip = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
        let network = Ipv6Network::from(ip, 0).unwrap();
        let iterator = Ipv6NetworkIterator::new(network, 128);

        iterator.len();
    }

    #[test]
    fn test_ipv6_network_iterator_whole_range_real_len() {
        let ip = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
        let network = Ipv6Network::from(ip, 0).unwrap();
        let iterator = Ipv6NetworkIterator::new(network, 128);

        assert_eq!(iterator.real_len(), u128::max_value());
    }

    #[test]
    fn test_ipv6_network_iterator_whole_range() {
        let ip = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
        let network = Ipv6Network::from(ip, 0).unwrap();
        let mut iterator = Ipv6NetworkIterator::new(network, 128);

        assert_eq!(iterator.next().unwrap(), Ipv6Network::from(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 128).unwrap());
        assert_eq!(iterator.next().unwrap(), Ipv6Network::from(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 128).unwrap());
    }
}
<commit_msg>Removed unnecessary `inline` from iterator step function<commit_after>use std::net::{Ipv4Addr, Ipv6Addr};
use Ipv4Network;
use Ipv6Network;
use helpers;

#[cfg(target_pointer_width = "16")]
const POINTER_WIDTH: u32 = 16;
#[cfg(target_pointer_width = "32")]
const POINTER_WIDTH: u32 = 32;
#[cfg(target_pointer_width = "64")]
const POINTER_WIDTH: u32 = 64;
#[cfg(target_pointer_width = "128")]
const POINTER_WIDTH: u32 = 128;

/// IPv4 range iterator
pub struct Ipv4RangeIterator {
    current: u32,
    to: u32,
    is_done: bool,
}

impl Ipv4RangeIterator {
    /// Constructs new `Ipv4RangeIterator`, both `from` and `to` address are inclusive.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::net::Ipv4Addr;
    /// use ip_network::iterator::Ipv4RangeIterator;
    ///
    /// let mut iterator = Ipv4RangeIterator::new(
    ///     Ipv4Addr::new(192, 168, 2, 0),
    ///     Ipv4Addr::new(192, 168, 2, 255)
    /// );
    /// assert_eq!(iterator.next().unwrap(), Ipv4Addr::new(192, 168, 2, 0));
    /// assert_eq!(iterator.next().unwrap(), Ipv4Addr::new(192, 168, 2, 1));
    /// assert_eq!(iterator.last().unwrap(), Ipv4Addr::new(192, 168, 2, 255));
    /// ```
    pub fn new(from: Ipv4Addr, to: Ipv4Addr) -> Self {
        let current = u32::from(from);
        let to = u32::from(to);
        assert!(to >= current);
        Self { current, to, is_done: false }
    }
}

impl Iterator for Ipv4RangeIterator {
    type Item = Ipv4Addr;

    fn next(&mut self) -> Option<Self::Item> {
        if self.current <= self.to && !self.is_done {
            let output = self.current;

            match self.current.checked_add(1) {
                Some(x) => self.current = x,
                None => self.is_done = true,
            };

            Some(Self::Item::from(output))
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        if self.is_done {
            return (0, Some(0))
        }

        let remaining = (self.to - self.current + 1) as usize;
        (remaining, Some(remaining))
    }
}

impl ExactSizeIterator for Ipv4RangeIterator {}

/// Iterates over new created IPv4 network from given network
pub struct Ipv4NetworkIterator {
    current: u32,
    to: u32,
    new_netmask: u8,
    is_done: bool,
}

impl Ipv4NetworkIterator {
    // TODO: Change assert to error?
    pub fn new(network: Ipv4Network, new_netmask: u8) -> Self {
        assert!(network.get_netmask() < new_netmask);
        assert!(new_netmask <= 32);

        let current = u32::from(network.get_network_address());
        let mask = !helpers::get_bite_mask(32 - (new_netmask - network.get_netmask())) << (32 - new_netmask);
        let to = current | mask;

        Self {
            current,
            to,
            new_netmask,
            is_done: false,
        }
    }

    fn step(&self) -> u32 {
        1 << (32 - self.new_netmask)
    }
}

impl Iterator for Ipv4NetworkIterator {
    type Item = Ipv4Network;

    fn next(&mut self) -> Option<Self::Item> {
        if self.current <= self.to && !self.is_done {
            let output = self.current;

            match self.current.checked_add(self.step()) {
                Some(x) => self.current = x,
                None => self.is_done = true,
            };

            Some(Self::Item::from(Ipv4Addr::from(output), self.new_netmask).unwrap())
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        if self.is_done {
            return (0, Some(0))
        }

        let remaining = ((self.to - self.current) / self.step() + 1) as usize;
        (remaining, Some(remaining))
    }
}

impl ExactSizeIterator for Ipv4NetworkIterator {}

/// Iterates over new created IPv6 network from given network
pub struct Ipv6NetworkIterator {
    current: u128,
    to: u128,
    new_netmask: u8,
    is_done: bool,
}

impl Ipv6NetworkIterator {
    // TODO: Change assert to error?
    pub fn new(network: Ipv6Network, new_netmask: u8) -> Self {
        assert!(network.get_netmask() < new_netmask);
        assert!(new_netmask <= 128);

        let current = u128::from(network.get_network_address());
        let mask = !helpers::get_bite_mask_u128(128 - (new_netmask - network.get_netmask())) << (128 - new_netmask);
        let to = current | mask;

        Self {
            current,
            to,
            new_netmask,
            is_done: false,
        }
    }

    fn step(&self) -> u128 {
        1 << (128 - self.new_netmask)
    }

    pub fn real_len(&self) -> u128 {
        if self.is_done {
            return 0;
        }

        ((self.to - self.current) / self.step()).saturating_add(1)
    }
}

impl Iterator for Ipv6NetworkIterator {
    type Item = Ipv6Network;

    fn next(&mut self) -> Option<Self::Item> {
        if self.current <= self.to && !self.is_done {
            let output = self.current;

            match self.current.checked_add(self.step()) {
                Some(x) => self.current = x,
                None => self.is_done = true,
            };

            Some(Self::Item::from(Ipv6Addr::from(output), self.new_netmask).unwrap())
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let remaining = self.real_len();

        if 128 - remaining.leading_zeros() > POINTER_WIDTH {
            (::std::usize::MAX, None)
        } else {
            let remaining_u64 = remaining as u64;
            (remaining_u64 as usize, Some(remaining_u64 as usize))
        }
    }
}

impl ExactSizeIterator for Ipv6NetworkIterator {}

#[cfg(test)]
mod tests {
    use std::net::{Ipv4Addr, Ipv6Addr};
    use {Ipv4Network, Ipv6Network};
    use super::{Ipv4NetworkIterator, Ipv4RangeIterator, Ipv6NetworkIterator};

    #[test]
    fn test_ipv4_range_iterator() {
        let mut iterator = Ipv4RangeIterator::new(
            Ipv4Addr::new(192, 168, 2, 0),
            Ipv4Addr::new(192, 168, 2, 255)
        );
        assert_eq!(iterator.next().unwrap(), Ipv4Addr::new(192, 168, 2, 0));
        assert_eq!(iterator.next().unwrap(), Ipv4Addr::new(192, 168, 2, 1));
        assert_eq!(iterator.last().unwrap(), Ipv4Addr::new(192, 168, 2, 255));
    }

    #[test]
    fn test_ipv4_range_iterator_length() {
        let mut iterator = Ipv4RangeIterator::new(
            Ipv4Addr::new(192, 168, 2, 0),
            Ipv4Addr::new(192, 168, 2, 255)
        );
        assert_eq!(iterator.len(), 256);
        iterator.next().unwrap();
        assert_eq!(iterator.len(), 255);
        assert_eq!(iterator.collect::<Vec<_>>().len(), 255);
    }

    #[test]
    fn test_ipv4_range_iterator_same_values() {
        let mut iterator = Ipv4RangeIterator::new(
            Ipv4Addr::new(255, 255, 255, 255),
            Ipv4Addr::new(255, 255, 255, 255)
        );
        assert_eq!(iterator.len(), 1);
        assert_eq!(iterator.next().unwrap(), Ipv4Addr::new(255, 255, 255, 255));
        assert!(iterator.next().is_none());
        assert_eq!(iterator.len(), 0);
    }

    #[test]
    fn test_ipv4_network_iterator() {
        let network = Ipv4Network::from(Ipv4Addr::new(127, 0, 0, 0), 8).unwrap();
        let mut iterator = Ipv4NetworkIterator::new(network, 16);

        assert_eq!(iterator.len(), 256);
        assert_eq!(iterator.next().unwrap(), Ipv4Network::from(Ipv4Addr::new(127, 0, 0, 0), 16).unwrap());
        assert_eq!(iterator.next().unwrap(), Ipv4Network::from(Ipv4Addr::new(127, 1, 0, 0), 16).unwrap());
        assert_eq!(iterator.next().unwrap(), Ipv4Network::from(Ipv4Addr::new(127, 2, 0, 0), 16).unwrap());
        assert_eq!(iterator.last().unwrap(), Ipv4Network::from(Ipv4Addr::new(127, 255, 0, 0), 16).unwrap());
    }

    #[test]
    fn test_ipv4_network_iterator_len() {
        let network = Ipv4Network::from(Ipv4Addr::new(127, 0, 0, 0), 8).unwrap();
        let iterator = Ipv4NetworkIterator::new(network, 16);
        assert_eq!(256, iterator.len());
    }

    #[test]
    fn test_ipv6_network_iterator() {
        let ip = Ipv6Addr::new(0x2001, 0, 0, 0, 0, 0, 0, 0);
        let network = Ipv6Network::from(ip, 16).unwrap();
        let mut iterator = Ipv6NetworkIterator::new(network, 17);

        assert_eq!(2, iterator.len());
        assert_eq!(iterator.next().unwrap(), Ipv6Network::from(ip, 17).unwrap());
        assert_eq!(iterator.next().unwrap(), Ipv6Network::from(Ipv6Addr::new(0x2001, 0x8000, 0, 0, 0, 0, 0, 0), 17).unwrap());
        assert!(iterator.next().is_none());
    }

    #[test]
    #[should_panic] // because range is bigger than `usize` on 64bit machine
    fn test_ipv6_network_iterator_whole_range_len() {
        let ip = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
        let network = Ipv6Network::from(ip, 0).unwrap();
        let iterator = Ipv6NetworkIterator::new(network, 128);

        iterator.len();
    }

    #[test]
    fn test_ipv6_network_iterator_whole_range_real_len() {
        let ip = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
        let network = Ipv6Network::from(ip, 0).unwrap();
        let iterator = Ipv6NetworkIterator::new(network, 128);

        assert_eq!(iterator.real_len(), u128::max_value());
    }

    #[test]
    fn test_ipv6_network_iterator_whole_range() {
        let ip = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
        let network = Ipv6Network::from(ip, 0).unwrap();
        let mut iterator = Ipv6NetworkIterator::new(network, 128);

        assert_eq!(iterator.next().unwrap(), Ipv6Network::from(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 128).unwrap());
        assert_eq!(iterator.next().unwrap(), Ipv6Network::from(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 128).unwrap());
    }
}
<|endoftext|>


<commit_before>extern crate rocket;
extern crate config as lib;

use rocket::config::{self, Environment};
use rocket::http::Method;
use rocket::LoggingLevel;
use rocket::testing::MockRequest;

pub fn test_config(environment: Environment) {
    // Manually set the config environment variable. Rocket will initialize the
    // environment in `ignite()`.
    ::std::env::set_var("ROCKET_ENV", environment.to_string());
    rocket::ignite().mount("/hello", routes![lib::hello]);

    // Get the active environment and ensure that it matches our expectations.
    let config = config::active().unwrap();
    match environment {
        Environment::Development => {
            assert_eq!(config.address, "localhost".to_string());
            assert_eq!(config.port, 8000);
            assert_eq!(config.log_level, LoggingLevel::Normal);
            assert_eq!(config.env, config::Environment::Development);
            assert_eq!(config.extras().count(), 2);
            assert_eq!(config.get_str("hi"), Ok("Hello!"));
            assert_eq!(config.get_bool("is_extra"), Ok(true));
        }
        Environment::Staging => {
            assert_eq!(config.address, "0.0.0.0".to_string());
            assert_eq!(config.port, 80);
            assert_eq!(config.log_level, LoggingLevel::Normal);
            assert_eq!(config.env, config::Environment::Staging);
            assert_eq!(config.extras().count(), 0);
        }
        Environment::Production => {
            assert_eq!(config.address, "0.0.0.0".to_string());
            assert_eq!(config.port, 80);
            assert_eq!(config.log_level, LoggingLevel::Critical);
            assert_eq!(config.env, config::Environment::Production);
            assert_eq!(config.extras().count(), 0);
        }
    }

    // Rocket `take`s the key, so this should always be `None`.
    assert_eq!(config.take_session_key(), None);
}

pub fn test_hello() {
    let rocket = rocket::ignite().mount("/hello", routes![lib::hello]);
    let mut request = MockRequest::new(Method::Get, "/hello");
    let mut response = request.dispatch_with(&rocket);

    assert_eq!(response.body().and_then(|b| b.into_string()),
               Some("Hello, world!".to_string()));
}
<commit_msg>Fix config example tests for new Config structure.<commit_after>extern crate rocket;
extern crate config as lib;

use rocket::config::{self, Environment};
use rocket::http::Method;
use rocket::LoggingLevel;
use rocket::testing::MockRequest;

pub fn test_config(environment: Environment) {
    // Manually set the config environment variable. Rocket will initialize the
    // environment in `ignite()`.
    ::std::env::set_var("ROCKET_ENV", environment.to_string());
    rocket::ignite().mount("/hello", routes![lib::hello]);

    // Get the active environment and ensure that it matches our expectations.
    let config = config::active().unwrap();
    match environment {
        Environment::Development => {
            assert_eq!(config.address, "localhost".to_string());
            assert_eq!(config.port, 8000);
            assert_eq!(config.workers, 1);
            assert_eq!(config.log_level, LoggingLevel::Normal);
            assert_eq!(config.environment, config::Environment::Development);
            assert_eq!(config.extras().count(), 2);
            assert_eq!(config.get_str("hi"), Ok("Hello!"));
            assert_eq!(config.get_bool("is_extra"), Ok(true));
        }
        Environment::Staging => {
            assert_eq!(config.address, "0.0.0.0".to_string());
            assert_eq!(config.port, 80);
            assert_eq!(config.workers, 8);
            assert_eq!(config.log_level, LoggingLevel::Normal);
            assert_eq!(config.environment, config::Environment::Staging);
            assert_eq!(config.extras().count(), 0);
        }
        Environment::Production => {
            assert_eq!(config.address, "0.0.0.0".to_string());
            assert_eq!(config.port, 80);
            assert_eq!(config.workers, 12);
            assert_eq!(config.log_level, LoggingLevel::Critical);
            assert_eq!(config.environment, config::Environment::Production);
            assert_eq!(config.extras().count(), 0);
        }
    }

    // Rocket `take`s the key, so this should always be `None`.
    assert_eq!(config.take_session_key(), None);
}

pub fn test_hello() {
    let rocket = rocket::ignite().mount("/hello", routes![lib::hello]);
    let mut request = MockRequest::new(Method::Get, "/hello");
    let mut response = request.dispatch_with(&rocket);

    assert_eq!(response.body().and_then(|b| b.into_string()),
               Some("Hello, world!".to_string()));
}
<|endoftext|>


<commit_before>use proc_macro2::{Ident, Span};
use std::cmp::Ordering;
use std::fmt::{self, Display};
use std::hash::{Hash, Hasher};

#[cfg(feature = "parsing")]
use crate::lookahead;

/// A Rust lifetime: `'a`.
///
/// Lifetime names must conform to the following rules:
///
/// - Must start with an apostrophe.
/// - Must not consist of just an apostrophe: `'`.
/// - Character after the apostrophe must be `_` or a Unicode code point with
///   the XID_Start property.
/// - All following characters must be Unicode code points with the XID_Continue
///   property.
pub struct Lifetime {
    pub apostrophe: Span,
    pub ident: Ident,
}

impl Lifetime {
    /// # Panics
    ///
    /// Panics if the lifetime does not conform to the bulleted rules above.
    ///
    /// # Invocation
    ///
    /// ```
    /// # use proc_macro2::Span;
    /// # use syn::Lifetime;
    /// #
    /// # fn f() -> Lifetime {
    /// Lifetime::new("'a", Span::call_site())
    /// # }
    /// ```
    pub fn new(symbol: &str, span: Span) -> Self {
        if !symbol.starts_with('\'') {
            panic!(
                "lifetime name must start with apostrophe as in \"'a\", got {:?}",
                symbol
            );
        }

        if symbol == "'" {
            panic!("lifetime name must not be empty");
        }

        if !crate::ident::xid_ok(&symbol[1..]) {
            panic!("{:?} is not a valid lifetime name", symbol);
        }

        Lifetime {
            apostrophe: span,
            ident: Ident::new(&symbol[1..], span),
        }
    }
}

impl Display for Lifetime {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        "'".fmt(formatter)?;
        self.ident.fmt(formatter)
    }
}

impl Clone for Lifetime {
    fn clone(&self) -> Self {
        Lifetime {
            apostrophe: self.apostrophe,
            ident: self.ident.clone(),
        }
    }
}

impl PartialEq for Lifetime {
    fn eq(&self, other: &Lifetime) -> bool {
        self.ident.eq(&other.ident)
    }
}

impl Eq for Lifetime {}

impl PartialOrd for Lifetime {
    fn partial_cmp(&self, other: &Lifetime) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for Lifetime {
    fn cmp(&self, other: &Lifetime) -> Ordering {
        self.ident.cmp(&other.ident)
    }
}

impl Hash for Lifetime {
    fn hash<H: Hasher>(&self, h: &mut H) {
        self.ident.hash(h)
    }
}

#[cfg(feature = "parsing")]
#[doc(hidden)]
#[allow(non_snake_case)]
pub fn Lifetime(marker: lookahead::TokenMarker) -> Lifetime {
    match marker {}
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use crate::parse::{Parse, ParseStream, Result};

    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
    impl Parse for Lifetime {
        fn parse(input: ParseStream) -> Result<Self> {
            input.step(|cursor| {
                cursor
                    .lifetime()
                    .ok_or_else(|| cursor.error("expected lifetime"))
            })
        }
    }
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use proc_macro2::{Punct, Spacing, TokenStream};
    use quote::{ToTokens, TokenStreamExt};

    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
    impl ToTokens for Lifetime {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            let mut apostrophe = Punct::new('\'', Spacing::Joint);
            apostrophe.set_span(self.apostrophe);
            tokens.append(apostrophe);
            self.ident.to_tokens(tokens);
        }
    }
}
<commit_msg>Add Lifetime span getter and setter<commit_after>use proc_macro2::{Ident, Span};
use std::cmp::Ordering;
use std::fmt::{self, Display};
use std::hash::{Hash, Hasher};

#[cfg(feature = "parsing")]
use crate::lookahead;

/// A Rust lifetime: `'a`.
///
/// Lifetime names must conform to the following rules:
///
/// - Must start with an apostrophe.
/// - Must not consist of just an apostrophe: `'`.
/// - Character after the apostrophe must be `_` or a Unicode code point with
///   the XID_Start property.
/// - All following characters must be Unicode code points with the XID_Continue
///   property.
pub struct Lifetime {
    pub apostrophe: Span,
    pub ident: Ident,
}

impl Lifetime {
    /// # Panics
    ///
    /// Panics if the lifetime does not conform to the bulleted rules above.
    ///
    /// # Invocation
    ///
    /// ```
    /// # use proc_macro2::Span;
    /// # use syn::Lifetime;
    /// #
    /// # fn f() -> Lifetime {
    /// Lifetime::new("'a", Span::call_site())
    /// # }
    /// ```
    pub fn new(symbol: &str, span: Span) -> Self {
        if !symbol.starts_with('\'') {
            panic!(
                "lifetime name must start with apostrophe as in \"'a\", got {:?}",
                symbol
            );
        }

        if symbol == "'" {
            panic!("lifetime name must not be empty");
        }

        if !crate::ident::xid_ok(&symbol[1..]) {
            panic!("{:?} is not a valid lifetime name", symbol);
        }

        Lifetime {
            apostrophe: span,
            ident: Ident::new(&symbol[1..], span),
        }
    }

    pub fn span(&self) -> Span {
        self.apostrophe
            .join(self.ident.span())
            .unwrap_or(self.apostrophe)
    }

    pub fn set_span(&mut self, span: Span) {
        self.apostrophe = span;
        self.ident.set_span(span);
    }
}

impl Display for Lifetime {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        "'".fmt(formatter)?;
        self.ident.fmt(formatter)
    }
}

impl Clone for Lifetime {
    fn clone(&self) -> Self {
        Lifetime {
            apostrophe: self.apostrophe,
            ident: self.ident.clone(),
        }
    }
}

impl PartialEq for Lifetime {
    fn eq(&self, other: &Lifetime) -> bool {
        self.ident.eq(&other.ident)
    }
}

impl Eq for Lifetime {}

impl PartialOrd for Lifetime {
    fn partial_cmp(&self, other: &Lifetime) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for Lifetime {
    fn cmp(&self, other: &Lifetime) -> Ordering {
        self.ident.cmp(&other.ident)
    }
}

impl Hash for Lifetime {
    fn hash<H: Hasher>(&self, h: &mut H) {
        self.ident.hash(h)
    }
}

#[cfg(feature = "parsing")]
#[doc(hidden)]
#[allow(non_snake_case)]
pub fn Lifetime(marker: lookahead::TokenMarker) -> Lifetime {
    match marker {}
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use crate::parse::{Parse, ParseStream, Result};

    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
    impl Parse for Lifetime {
        fn parse(input: ParseStream) -> Result<Self> {
            input.step(|cursor| {
                cursor
                    .lifetime()
                    .ok_or_else(|| cursor.error("expected lifetime"))
            })
        }
    }
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use proc_macro2::{Punct, Spacing, TokenStream};
    use quote::{ToTokens, TokenStreamExt};

    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
    impl ToTokens for Lifetime {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            let mut apostrophe = Punct::new('\'', Spacing::Joint);
            apostrophe.set_span(self.apostrophe);
            tokens.append(apostrophe);
            self.ident.to_tokens(tokens);
        }
    }
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate lua;
extern crate time;

use self::lua::ffi::lua_State;
use std::path;
use std::rc::Rc;
use std::cell::RefCell;
use task::{Task, ShellTask, ShellCommand};

// TODO(sirver): This whole file is quite the hack. If a LuaDictionary would get a proper
// abstraction, this could be expressed more tightly. This is a bit tricky with the correct
// lifetimes.

fn get_value_in_dict(key: &str, state: &mut lua::State) {
    // S: D
    state.push_string(key); // S: D <key>
    state.get_table(-2); // S: D <value>
}

fn pop_string(state: &mut lua::State) -> Option<String> {
    let rv = if state.is_string(-1) {
        Some(state.check_string(-1).to_string())
    } else {
        None
    };
    state.pop(1);
    rv
}

fn pop_int(state: &mut lua::State) -> Option<i64> {
    let rv = if state.is_integer(-1) {
        Some(state.check_integer(-1))
    } else {
        None
    };
    state.pop(1);
    rv
}

fn pop_bool(state: &mut lua::State) -> Option<bool> {
    let rv = if state.is_bool(-1) {
        Some(state.to_bool(-1))
    } else {
        None
    };
    state.pop(1);
    rv
}

struct LuaTask {
    state: Rc<RefCell<lua::State>>,
    key: i64,
}

impl LuaTask {
    fn new(state: Rc<RefCell<lua::State>>, key: i64) -> LuaTask {
        LuaTask {
            state: state,
            key: key,
        }
    }

    fn get_value_in_our_dict(&self, key: &str, state: &mut lua::State) {
        // S: D
        state.push_integer(self.key); // S: D key
        state.get_table(1); // S: D d
        state.push_string(key); // S: D d <key>
        state.get_table(-2); // S: D d <value>
    }

    fn get_string(&self, key: &str) -> Option<String> {
        let mut state = self.state.borrow_mut();
        self.get_value_in_our_dict(key, &mut state); // S: D d <value>
        let rv = pop_string(&mut state);
        state.pop(1);
        rv
    }

    fn get_int(&self, key: &str) -> Option<i64> {
        let mut state = self.state.borrow_mut();
        self.get_value_in_our_dict(key, &mut state); // S: D d <value>
        let rv = pop_int(&mut state);
        state.pop(1);
        rv
    }

    fn get_bool(&self, key: &str) -> Option<bool> {
        let mut state = self.state.borrow_mut();
        self.get_value_in_our_dict(key, &mut state); // S: D d <value>
        let rv = pop_bool(&mut state);
        state.pop(1);
        rv
    }
}

impl Task for LuaTask {
    fn should_run(&self, path: &path::Path) -> bool {
        let mut state = self.state.borrow_mut();
        self.get_value_in_our_dict("should_run", &mut state);
        if state.is_nil(-1) {
            // should_run not in dictionary.
            state.pop(2);
            return true;
        }
        state.push_string(&path.to_string_lossy()); // S: D d function path
        state.call(1, 1); // S: D d <result>
        let rv = state.to_bool(-1);
        state.pop(2);
        rv
    }

    fn start_delay(&self) -> time::Duration {
        if let Some(delay_ms) = self.get_int("start_delay") {
            return time::Duration::milliseconds(delay_ms);
        }
        time::Duration::milliseconds(50)
    }
}

impl ShellTask for LuaTask {
    // TODO(sirver): If there is only one command in a chain, a short form should be acceptable in
    // the Lua file.
    fn commands(&self) -> Vec<ShellCommand> {
        let mut state = self.state.borrow_mut();
        self.get_value_in_our_dict("commands", &mut state);
        if state.is_nil(-1) {
            panic!("Expected commands, but was not found.");
        }
        let mut result = Vec::new();
        state.push_nil(); // S: D "commands dict" nil
        while state.next(-2) {
            // S: D "commands dict" key value
            get_value_in_dict("name", &mut state);
            let name = pop_string(&mut state).expect("name in commands.");
            get_value_in_dict("command", &mut state);
            let command = pop_string(&mut state).expect("command in commands.");
            get_value_in_dict("work_directory", &mut state);
            let work_directory = pop_string(&mut state).map(path::PathBuf::from);
            state.pop(1); // S: D "commands dict" key
            result.push(ShellCommand { name, command, work_directory });
        }
        state.pop(1); // S: D
        result
    }

    fn redirect_stdout(&self) -> Option<path::PathBuf> {
        if let Some(redirect_stdout) = self.get_string("redirect_stdout") {
            return Some(path::PathBuf::from(redirect_stdout));
        }
        None
    }

    fn redirect_stderr(&self) -> Option<path::PathBuf> {
        if let Some(redirect_stderr) = self.get_string("redirect_stderr") {
            return Some(path::PathBuf::from(redirect_stderr));
        }
        None
    }

    fn supress_stderr(&self) -> bool {
        if let Some(redirect_stderr) = self.get_bool("supress_stderr") {
            return redirect_stderr;
        }
        false
    }

    fn supress_stdout(&self) -> bool {
        if let Some(redirect_stdout) = self.get_bool("supress_stdout") {
            return redirect_stdout;
        }
        false
    }
}

#[allow(non_snake_case)]
unsafe extern "C" fn basename(L: *mut lua_State) -> libc::c_int {
    let mut state = lua::State::from_ptr(L);
    let string: String = state.check_string(-1).to_string();
    let p = path::Path::new(&string);
    match p.file_name() {
        Some(s) => {
            state.push_string(&s.to_string_lossy());
            1
        }
        None => 0,
    }
}

#[allow(non_snake_case)]
unsafe extern "C" fn dirname(L: *mut lua_State) -> libc::c_int {
    let mut state = lua::State::from_ptr(L);
    let string: String = state.check_string(-1).to_string();
    let p = path::Path::new(&string);
    match p.parent() {
        Some(s) => {
            state.push_string(&s.to_string_lossy());
            1
        }
        None => 0,
    }
}

#[allow(non_snake_case)]
unsafe extern "C" fn ext(L: *mut lua_State) -> libc::c_int {
    let mut state = lua::State::from_ptr(L);
    let string: String = state.check_string(-1).to_string();
    let p = path::Path::new(&string);
    match p.extension() {
        Some(ext) => {
            state.push_string(&ext.to_string_lossy());
            1
        }
        None => 0,
    }
}

fn inject_path_functions(state: &mut lua::State) {
    state.get_global("string"); // S: <string>

    state.push_string("ext");
    state.push_fn(Some(ext));
    state.set_table(-3);

    state.push_string("basename");
    state.push_fn(Some(basename));
    state.set_table(-3);

    state.push_string("dirname");
    state.push_fn(Some(dirname));
    state.set_table(-3);

    state.pop(1);
}

pub fn run_file(path: &path::Path) -> Vec<Box<Task>> {
    let mut state = lua::State::new();
    state.open_libs();

    let path_utf8 = path.to_string_lossy();
    match state.do_file(&path_utf8) {
        lua::ThreadStatus::Ok => (),
        _ => {
            let error_message = pop_string(&mut state).unwrap();
            panic!("{}", error_message);
        }
    };

    inject_path_functions(&mut state);

    let mut tasks = Vec::new();
    let state_rc = Rc::new(RefCell::new(state));
    let mut state = state_rc.borrow_mut();

    state.push_nil(); // S: D nil
    while state.next(-2) {
        let key = state.check_integer(-2); // S: D key value
        state.pop(1); // S: D key
        tasks.push(Box::new(LuaTask::new(state_rc.clone(), key)) as Box<Task>);
    }
    // S: D
    tasks
}
<commit_msg>Small simplifications.<commit_after>extern crate libc;
extern crate lua;
extern crate time;

use self::lua::ffi::lua_State;
use std::path;
use std::rc::Rc;
use std::cell::RefCell;
use task::{Task, ShellTask, ShellCommand};

// TODO(sirver): This whole file is quite the hack. If a LuaDictionary would get a proper
// abstraction, this could be expressed more tightly. This is a bit tricky with the correct
// lifetimes.

fn get_value_in_dict(key: &str, state: &mut lua::State) {
    // S: D
    state.push_string(key); // S: D <key>
    state.get_table(-2); // S: D <value>
}

fn pop_string(state: &mut lua::State) -> Option<String> {
    let rv = if state.is_string(-1) {
        Some(state.check_string(-1).to_string())
    } else {
        None
    };
    state.pop(1);
    rv
}

fn pop_int(state: &mut lua::State) -> Option<i64> {
    let rv = if state.is_integer(-1) {
        Some(state.check_integer(-1))
    } else {
        None
    };
    state.pop(1);
    rv
}

fn pop_bool(state: &mut lua::State) -> Option<bool> {
    let rv = if state.is_bool(-1) {
        Some(state.to_bool(-1))
    } else {
        None
    };
    state.pop(1);
    rv
}

struct LuaTask {
    state: Rc<RefCell<lua::State>>,
    key: i64,
}

impl LuaTask {
    fn new(state: Rc<RefCell<lua::State>>, key: i64) -> LuaTask {
        LuaTask {
            state: state,
            key: key,
        }
    }

    fn get_value_in_our_dict(&self, key: &str, state: &mut lua::State) {
        // S: D
        state.push_integer(self.key); // S: D key
        state.get_table(1); // S: D d
        state.push_string(key); // S: D d <key>
        state.get_table(-2); // S: D d <value>
    }

    fn get_string(&self, key: &str) -> Option<String> {
        let mut state = self.state.borrow_mut();
        self.get_value_in_our_dict(key, &mut state); // S: D d <value>
        let rv = pop_string(&mut state);
        state.pop(1);
        rv
    }

    fn get_int(&self, key: &str) -> Option<i64> {
        let mut state = self.state.borrow_mut();
        self.get_value_in_our_dict(key, &mut state); // S: D d <value>
        let rv = pop_int(&mut state);
        state.pop(1);
        rv
    }

    fn get_bool(&self, key: &str) -> Option<bool> {
        let mut state = self.state.borrow_mut();
        self.get_value_in_our_dict(key, &mut state); // S: D d <value>
        let rv = pop_bool(&mut state);
        state.pop(1);
        rv
    }
}

impl Task for LuaTask {
    fn should_run(&self, path: &path::Path) -> bool {
        let mut state = self.state.borrow_mut();
        self.get_value_in_our_dict("should_run", &mut state);
        if state.is_nil(-1) {
            // should_run not in dictionary.
            state.pop(2);
            return true;
        }
        state.push_string(&path.to_string_lossy()); // S: D d function path
        state.call(1, 1); // S: D d <result>
        let rv = state.to_bool(-1);
        state.pop(2);
        rv
    }

    fn start_delay(&self) -> time::Duration {
        self.get_int("start_delay")
            .map(time::Duration::milliseconds)
            .unwrap_or(time::Duration::milliseconds(50))
    }
}

impl ShellTask for LuaTask {
    // TODO(sirver): If there is only one command in a chain, a short form should be acceptable in
    // the Lua file.
    fn commands(&self) -> Vec<ShellCommand> {
        let mut state = self.state.borrow_mut();
        self.get_value_in_our_dict("commands", &mut state);
        if state.is_nil(-1) {
            panic!("Expected commands, but was not found.");
        }
        let mut result = Vec::new();
        state.push_nil(); // S: D "commands dict" nil
        while state.next(-2) {
            // S: D "commands dict" key value
            get_value_in_dict("name", &mut state);
            let name = pop_string(&mut state).expect("name in commands.");
            get_value_in_dict("command", &mut state);
            let command = pop_string(&mut state).expect("command in commands.");
            get_value_in_dict("work_directory", &mut state);
            let work_directory = pop_string(&mut state).map(path::PathBuf::from);
            state.pop(1); // S: D "commands dict" key
            result.push(ShellCommand {
                            name,
                            command,
                            work_directory,
                        });
        }
        state.pop(1); // S: D
        result
    }

    fn redirect_stdout(&self) -> Option<path::PathBuf> {
        self.get_string("redirect_stdout").map(path::PathBuf::from)
    }

    fn redirect_stderr(&self) -> Option<path::PathBuf> {
        self.get_string("redirect_stderr").map(path::PathBuf::from)
    }

    fn supress_stderr(&self) -> bool {
        self.get_bool("suppress_stderr").unwrap_or(false)
    }

    fn supress_stdout(&self) -> bool {
        self.get_bool("suppress_stdout").unwrap_or(false)
    }
}

#[allow(non_snake_case)]
unsafe extern "C" fn basename(L: *mut lua_State) -> libc::c_int {
    let mut state = lua::State::from_ptr(L);
    let string: String = state.check_string(-1).to_string();
    let p = path::Path::new(&string);
    match p.file_name() {
        Some(s) => {
            state.push_string(&s.to_string_lossy());
            1
        }
        None => 0,
    }
}

#[allow(non_snake_case)]
unsafe extern "C" fn dirname(L: *mut lua_State) -> libc::c_int {
    let mut state = lua::State::from_ptr(L);
    let string: String = state.check_string(-1).to_string();
    let p = path::Path::new(&string);
    match p.parent() {
        Some(s) => {
            state.push_string(&s.to_string_lossy());
            1
        }
        None => 0,
    }
}

#[allow(non_snake_case)]
unsafe extern "C" fn ext(L: *mut lua_State) -> libc::c_int {
    let mut state = lua::State::from_ptr(L);
    let string: String = state.check_string(-1).to_string();
    let p = path::Path::new(&string);
    match p.extension() {
        Some(ext) => {
            state.push_string(&ext.to_string_lossy());
            1
        }
        None => 0,
    }
}

fn inject_path_functions(state: &mut lua::State) {
    state.get_global("string"); // S: <string>

    state.push_string("ext");
    state.push_fn(Some(ext));
    state.set_table(-3);

    state.push_string("basename");
    state.push_fn(Some(basename));
    state.set_table(-3);

    state.push_string("dirname");
    state.push_fn(Some(dirname));
    state.set_table(-3);

    state.pop(1);
}

pub fn run_file(path: &path::Path) -> Vec<Box<Task>> {
    let mut state = lua::State::new();
    state.open_libs();

    let path_utf8 = path.to_string_lossy();
    match state.do_file(&path_utf8) {
        lua::ThreadStatus::Ok => (),
        _ => {
            let error_message = pop_string(&mut state).unwrap();
            panic!("{}", error_message);
        }
    };

    inject_path_functions(&mut state);

    let mut tasks = Vec::new();
    let state_rc = Rc::new(RefCell::new(state));
    let mut state = state_rc.borrow_mut();

    state.push_nil(); // S: D nil
    while state.next(-2) {
        let key = state.check_integer(-2); // S: D key value
        state.pop(1); // S: D key
        tasks.push(Box::new(LuaTask::new(state_rc.clone(), key)) as Box<Task>);
    }
    // S: D
    tasks
}
<|endoftext|>


<commit_before>use std::num::{Zero, One};
use mat::{Mat1, Mat2, Mat3};
use traits::division_ring::DivisionRing;
use traits::inv::Inv;

// some specializations:
impl<N: DivisionRing + Clone>
Inv for Mat1<N> {
  #[inline]
  fn inverse(&self) -> Option<Mat1<N>> {
    let mut res : Mat1<N> = self.clone();

    if res.inplace_inverse() {
        Some(res)
    }
    else {
        None
    }
  }

  #[inline]
  fn inplace_inverse(&mut self) -> bool {
    if self.m11.is_zero() {
        false
    }
    else {
      self.m11 = One::one::<N>() / self.m11;
      true
    }
  }
}

impl<N: DivisionRing + Clone>
Inv for Mat2<N> {
  #[inline]
  fn inverse(&self) -> Option<Mat2<N>> {
    let mut res : Mat2<N> = self.clone();

    if res.inplace_inverse() {
        Some(res)
    }
    else {
        None
    }
  }

  #[inline]
  fn inplace_inverse(&mut self) -> bool {
    let det = self.m11 * self.m22 - self.m21 * self.m12;

    if det.is_zero() {
        false
    }
    else {
      *self = Mat2::new(self.m22 / det , -self.m12 / det,
                        -self.m21 / det, self.m11 / det);

      true
    }
  }
}

impl<N: DivisionRing + Clone>
Inv for Mat3<N> {
  #[inline]
  fn inverse(&self) -> Option<Mat3<N>> {
    let mut res = self.clone();

    if res.inplace_inverse() {
        Some(res)
    }
    else {
        None
    }
  }

  #[inline]
  fn inplace_inverse(&mut self) -> bool {
    let minor_m12_m23 = self.m22 * self.m33 - self.m32 * self.m23;
    let minor_m11_m23 = self.m21 * self.m33 - self.m31 * self.m23;
    let minor_m11_m22 = self.m21 * self.m32 - self.m31 * self.m22;

    let det = self.m11 * minor_m12_m23
              - self.m12 * minor_m11_m23
              + self.m13 * minor_m11_m22;

    if det.is_zero() {
        false
    }
    else {
      *self = Mat3::new(
        (minor_m12_m23  / det),
        ((self.m13 * self.m32 - self.m33 * self.m12) / det),
        ((self.m12 * self.m23 - self.m22 * self.m13) / det),

        (-minor_m11_m23 / det),
        ((self.m11 * self.m33 - self.m31 * self.m13) / det),
        ((self.m13 * self.m21 - self.m23 * self.m11) / det),

        (minor_m11_m22  / det),
        ((self.m12 * self.m31 - self.m32 * self.m11) / det),
        ((self.m11 * self.m22 - self.m21 * self.m12) / det)
      );

      true
    }
  }
}
<commit_msg>Further coding style fixes.<commit_after>use std::num::{Zero, One};
use mat::{Mat1, Mat2, Mat3};
use traits::division_ring::DivisionRing;
use traits::inv::Inv;

// some specializations:
impl<N: DivisionRing + Clone>
Inv for Mat1<N> {
    #[inline]
    fn inverse(&self) -> Option<Mat1<N>> {
        let mut res : Mat1<N> = self.clone();

        if res.inplace_inverse() {
            Some(res)
        }
        else {
            None
        }
    }

    #[inline]
    fn inplace_inverse(&mut self) -> bool {
        if self.m11.is_zero() {
            false
        }
        else {
            self.m11 = One::one::<N>() / self.m11;
            true
        }
    }
}

impl<N: DivisionRing + Clone>
Inv for Mat2<N> {
    #[inline]
    fn inverse(&self) -> Option<Mat2<N>> {
        let mut res : Mat2<N> = self.clone();

        if res.inplace_inverse() {
            Some(res)
        }
        else {
            None
        }
    }

    #[inline]
    fn inplace_inverse(&mut self) -> bool {
        let det = self.m11 * self.m22 - self.m21 * self.m12;

        if det.is_zero() {
            false
        }
        else {
            *self = Mat2::new(self.m22 / det , -self.m12 / det,
            -self.m21 / det, self.m11 / det);

            true
        }
    }
}

impl<N: DivisionRing + Clone>
Inv for Mat3<N> {
    #[inline]
    fn inverse(&self) -> Option<Mat3<N>> {
        let mut res = self.clone();

        if res.inplace_inverse() {
            Some(res)
        }
        else {
            None
        }
    }

    #[inline]
    fn inplace_inverse(&mut self) -> bool {
        let minor_m12_m23 = self.m22 * self.m33 - self.m32 * self.m23;
        let minor_m11_m23 = self.m21 * self.m33 - self.m31 * self.m23;
        let minor_m11_m22 = self.m21 * self.m32 - self.m31 * self.m22;

        let det = self.m11 * minor_m12_m23
                  - self.m12 * minor_m11_m23
                  + self.m13 * minor_m11_m22;

        if det.is_zero() {
            false
        }
        else {
            *self = Mat3::new(
                (minor_m12_m23  / det),
                ((self.m13 * self.m32 - self.m33 * self.m12) / det),
                ((self.m12 * self.m23 - self.m22 * self.m13) / det),

                (-minor_m11_m23 / det),
                ((self.m11 * self.m33 - self.m31 * self.m13) / det),
                ((self.m13 * self.m21 - self.m23 * self.m11) / det),

                (minor_m11_m22  / det),
                ((self.m12 * self.m31 - self.m32 * self.m11) / det),
                ((self.m11 * self.m22 - self.m21 * self.m12) / det)
                );

            true
        }
    }
}
<|endoftext|>