<commit_before>#[derive(Default, Serialize)]
pub struct CardParams {
    pub object: &'static str, // must be "card"
    pub exp_month: String,    // eg. "12"
    pub exp_year: String,     // eg. "17" or 2017"

    pub number: String,       // card number
    pub cvc: Option<String>,  // card security code
    pub name: Option<String>, // cardholder's full name
}

#[derive(Debug, Deserialize)]
pub struct Card {
    pub id: String,
    pub address_city: Option<String>,
    pub address_country: Option<String>,
    pub address_line1: Option<String>,
    pub address_line1_check: Option<String>, // (pass, fail, unavailable, unchecked)
    pub address_line2: Option<String>,
    pub address_state: Option<String>,
    pub address_zip: Option<String>,
    pub address_zip_check: Option<String>, // (pass, fail, unavailable, unchecked)
    pub brand: String, // (Visa, American Express, MasterCard, Discover, JCB, Diners Club, or Unknown)
    pub country: String, // eg. "US"
    pub customer: Option<String>,
    pub cvc_check: Option<String>, // (pass, fail, unavailable, unchecked)
    pub exp_month: u32,
    pub exp_year: u32,
    pub fingerprint: String,
    pub funding: String, // (credit, debit, prepaid, unknown)
}
<commit_msg>Fix default for CardParams w/ object="card"<commit_after>#[derive(Serialize)]
pub struct CardParams {
    pub object: &'static str, // must be "card"
    pub exp_month: String,    // eg. "12"
    pub exp_year: String,     // eg. "17" or 2017"

    pub number: String,       // card number
    pub name: Option<String>, // cardholder's full name
    pub cvc: Option<String>,  // card security code
}

impl Default for CardParams {
    fn default() -> Self {
        CardParams{
            object: "card",
            exp_month: String::new(),
            exp_year: String::new(),
            number: String::new(),
            name: None,
            cvc: None,
        }
    }
}

#[derive(Debug, Deserialize)]
pub struct Card {
    pub id: String,
    pub address_city: Option<String>,
    pub address_country: Option<String>,
    pub address_line1: Option<String>,
    pub address_line1_check: Option<String>, // (pass, fail, unavailable, unchecked)
    pub address_line2: Option<String>,
    pub address_state: Option<String>,
    pub address_zip: Option<String>,
    pub address_zip_check: Option<String>, // (pass, fail, unavailable, unchecked)
    pub brand: String, // (Visa, American Express, MasterCard, Discover, JCB, Diners Club, or Unknown)
    pub country: String, // eg. "US"
    pub customer: Option<String>,
    pub cvc_check: Option<String>, // (pass, fail, unavailable, unchecked)
    pub exp_month: u32,
    pub exp_year: u32,
    pub fingerprint: String,
    pub funding: String, // (credit, debit, prepaid, unknown)
}
<|endoftext|>


<commit_before>/// Bindings for ssl.h

#[allow(dead_code, non_camel_case_types, non_snake_case, non_upper_case_globals)]
mod bindings;
pub mod constants;
pub mod error;

mod ssl_context;
mod ssl_config;
mod x509_cert;

pub use self::ssl_context::*;
pub use self::ssl_config::*;
pub use self::x509_cert::*;

use std::slice;
use std::ffi::CStr;

pub enum SSLAlertLevel { Fatal, Warning }

pub fn list_ciphersuites() -> &'static [i32] {
    unsafe {
        let suite_ids = bindings::mbedtls_ssl_list_ciphersuites();

        let mut length = 0;
        while *suite_ids.offset(length as isize) != 0 {
            length += 1;
        }

        slice::from_raw_parts(suite_ids, length)
    }
}

pub fn get_ciphersuite_name(suite_id: i32) -> &'static CStr {
    unsafe {
        let name = bindings::mbedtls_ssl_get_ciphersuite_name(suite_id);

        CStr::from_ptr(name)
    }
}

pub fn get_ciphersuite_id(ciphersuite_name: &CStr) -> i32 {
    unsafe {
        bindings::mbedtls_ssl_get_ciphersuite_id(ciphersuite_name.as_ptr())
    }
}
<commit_msg>Docstrings<commit_after>/// Bindings for ssl.h

#[allow(dead_code, non_camel_case_types, non_snake_case, non_upper_case_globals)]
mod bindings;
pub mod constants;
pub mod error;

mod ssl_context;
mod ssl_config;
mod x509_cert;

pub use self::ssl_context::*;
pub use self::ssl_config::*;
pub use self::x509_cert::*;

use std::slice;
use std::ffi::CStr;

pub enum SSLAlertLevel { Fatal, Warning }

/// Returns the list of ciphersuites supported by the SSL/TLS module.
pub fn list_ciphersuites() -> &'static [i32] {
    unsafe {
        let suite_ids = bindings::mbedtls_ssl_list_ciphersuites();

        let mut length = 0;
        while *suite_ids.offset(length as isize) != 0 {
            length += 1;
        }

        slice::from_raw_parts(suite_ids, length)
    }
}

/// Return the name of the ciphersuite associated with the given ID.
pub fn get_ciphersuite_name(suite_id: i32) -> &'static CStr {
    unsafe {
        let name = bindings::mbedtls_ssl_get_ciphersuite_name(suite_id);

        CStr::from_ptr(name)
    }
}

/// Return the ID of the ciphersuite associated with the given name.
pub fn get_ciphersuite_id(ciphersuite_name: &CStr) -> i32 {
    unsafe {
        bindings::mbedtls_ssl_get_ciphersuite_id(ciphersuite_name.as_ptr())
    }
}
<|endoftext|>


<commit_before>#![allow(unused_variables)]
use std::str::FromStr;

use hyper::{self, Uri};

use serde::{Serialize, Deserialize};
use serde_json;

use client::{self, ApiClient};
use svc::common;

static BIGQUERY_ROOT: &str = "https://www.googleapis.com/bigquery/v2/projects";

pub struct BigQueryService {}
pub type Hub<'a> = client::Hub<'a, BigQueryService>;

#[derive(Default, Debug)]
pub struct ListDatasetsRequest {
    pub all: bool,
    pub filter: Option<String>,
    pub max_results: Option<usize>,
    pub page_token: Option<String>,
}

impl ListDatasetsRequest {
    fn to_query(&self) -> String {
        let mut params = vec![("all", self.all.to_string())];
        if let Some(ref filter) = self.filter {
            params.push(("filter", filter.clone()));
        }
        if let Some(ref max_results) = self.max_results {
            params.push(("maxResults", max_results.to_string()));
        }
        if let Some(ref page_token) = self.page_token {
            params.push(("pageToken", page_token.clone()));
        }
        client::encode_query_params(params)
    }
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ListDatasetsResponse {
    pub next_page_token: Option<String>,

    pub datasets: Vec<DatasetMeta>,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct DatasetMeta {
    pub id: String,
    pub dataset_reference: DatasetReference,
    pub friendly_name: Option<String>,
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct DatasetReference {
    pub project_id: String,
    pub dataset_id: String,
}

#[derive(Default, Debug)]
pub struct ListTablesRequest {
    pub max_results: Option<usize>,
    pub page_token: Option<String>,
}

impl ListTablesRequest {
    fn to_query(&self) -> String {
        let mut params = vec![];
        if let Some(ref max_results) = self.max_results {
            params.push(("maxResults", max_results.to_string()));
        }
        if let Some(ref page_token) = self.page_token {
            params.push(("pageToken", page_token.clone()));
        }
        client::encode_query_params(params)
    }
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ListTablesResponse {
    pub next_page_token: Option<String>,
    pub tables: Vec<TableMeta>,
    pub total_items: usize,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TableMeta {
    pub id: String,
    pub table_reference: TableReference,
    pub friendly_name: Option<String>,
    pub view: Option<ViewMeta>,

    #[serde(rename = "type")]
    pub type0: String,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ViewMeta {
    pub query: String,
    #[serde(default = "default_view_use_legacy_sql")]
    pub use_legacy_sql: bool,
}

fn default_view_use_legacy_sql() -> bool {
    true
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TableReference {
    pub project_id: String,
    pub dataset_id: String,
    pub table_id: String,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct DescribeTableResponse {
    pub id: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub schema: Option<TableFieldSchema>,

    #[serde(rename = "type")]
    pub type0: String,

    pub table_reference: TableReference,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub friendly_name: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub external_data_configuration: Option<ExtDataConfig>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub view: Option<ViewMeta>,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ExtDataConfig {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub schema: Option<TableFieldSchema>,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TableFieldSchema {
    pub fields: Vec<TableField>,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TableField {
    pub name: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default = "default_table_field_mode")]
    pub mode: String,

    #[serde(rename = "type")]
    pub type0: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub fields: Option<Vec<TableField>>,
}

fn default_table_field_mode() -> String {
    "NULLABLE".into()
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct JobResource {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub kind: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub id: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub dry_run: Option<bool>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub job_reference: Option<JobReference>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub status: Option<JobStatus>,

    pub configuration: JobConfiguration,
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct JobConfiguration {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub query: Option<QueryResource>,
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct QueryResource {
    pub query: String,
    pub use_legacy_sql: bool,
    pub use_query_cache: bool,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub destination_table: Option<TableReference>,
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct JobStatus {
    pub state: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub error_result: Option<QueryError>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub errors: Option<Vec<QueryError>>,
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct JobReference {
    pub project_id: String,

    pub job_id: String,
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct QueryError {
    pub reason: Option<String>,
    pub location: Option<String>,
    pub message: Option<String>,
    pub debug_info: Option<String>,
}

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct GetQueryResultsRequest {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub timeout_ms: Option<usize>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub max_results: Option<usize>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub start_index: Option<usize>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub page_token: Option<String>,
}

impl GetQueryResultsRequest {
    fn to_query(&self) -> String {
        let mut params = Vec::new();
        if let Some(ref timeout_ms) = self.timeout_ms {
            params.push(("timeoutMs", timeout_ms.to_string()));
        }
        if let Some(ref max_results) = self.max_results {
            params.push(("maxResults", max_results.to_string()));
        }
        if let Some(ref page_token) = self.page_token {
            params.push(("pageToken", page_token.clone()));
        }
        if let Some(ref start_index) = self.start_index {
            params.push(("startIndex", start_index.to_string()));
        }
        client::encode_query_params(params)
    }
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct GetQueryResultsResponse {
    pub schema: Option<TableFieldSchema>,
    pub job_reference: Option<JobReference>,
    pub total_rows: Option<String>,
    pub rows: Option<Vec<TableRow>>,
    pub job_complete: bool,
    pub page_token: Option<String>,
    pub errors: Option<Vec<QueryError>>,
}

#[derive(Serialize, Deserialize, Default, Debug)]
pub struct TableRow {
    pub f: Vec<TableCell>,
}

#[derive(Serialize, Deserialize, Default, Debug)]
pub struct TableCell {
    pub v: Cell,
}

#[serde(untagged)]
#[derive(Serialize, Deserialize, Debug)]
pub enum Cell {
    Value(Option<String>),
    Repeat(Vec<TableCell>),
    Row(TableRow),
}

impl Default for Cell {
    fn default() -> Self {
        Cell::Value(None)
    }
}

impl<'a> Hub<'a> {
    pub fn list_datasets(
        &self,
        token: &str,
        project_id: &str,
        req: &ListDatasetsRequest,
    ) -> client::Result<ListDatasetsResponse> {
        let path = format!(
            "{}/{}/datasets?{}",
            BIGQUERY_ROOT,
            project_id,
            req.to_query()
        );

        let uri = Uri::from_str(&path).expect("uri to be valid");
        self.get_bq::<ListDatasetsResponse>(&uri, token.to_string())
    }

    pub fn list_tables(
        &self,
        token: &str,
        project_id: &str,
        dataset_id: &str,
        req: &ListTablesRequest,
    ) -> client::Result<ListTablesResponse> {
        let path = format!(
            "{}/{}/datasets/{}/tables?{}",
            BIGQUERY_ROOT,
            project_id,
            dataset_id,
            req.to_query()
        );
        let uri = Uri::from_str(&path).expect("uri to be valid");
        self.get_bq::<ListTablesResponse>(&uri, token.to_string())
    }

    pub fn describe_table(
        &self,
        token: &str,
        project_id: &str,
        dataset_id: &str,
        table_id: &str,
    ) -> client::Result<DescribeTableResponse> {
        let path = format!(
            "{}/{}/datasets/{}/tables/{}",
            BIGQUERY_ROOT,
            project_id,
            dataset_id,
            table_id
        );
        let uri = Uri::from_str(&path).expect("uri to be valid");
        self.get_bq::<DescribeTableResponse>(&uri, token.to_string())
    }

    pub fn create_job(
        &self,
        token: &str,
        project_id: &str,
        req: &JobResource,
    ) -> client::Result<JobResource> {
        let path = format!("{}/{}/jobs", BIGQUERY_ROOT, project_id);
        let uri = Uri::from_str(&path).expect("uri to be valid");
        self.post_bq::<_, _>(&uri, req, token.to_string())
    }

    pub fn cancel_job(
        &self,
        token: &str,
        project_id: &str,
        job_id: &str,
    ) -> client::Result<JobResource> {
        let path = format!("{}/{}/jobs/{}/cancel", BIGQUERY_ROOT, project_id, job_id);
        let uri = Uri::from_str(&path).expect("uri to be valid");

        #[derive(Deserialize, Debug)]
        #[serde(rename_all = "camelCase")]
        struct Response {
            pub job: JobResource,
        }

        self.post_bq::<_, Response>(&uri, common::Empty {}, token.to_string())
            .map(|r| r.job)
    }

    pub fn get_job(
        &self,
        token: &str,
        project_id: &str,
        job_id: &str,
    ) -> client::Result<JobResource> {
        let path = format!("{}/{}/jobs/{}", BIGQUERY_ROOT, project_id, job_id);
        let uri = Uri::from_str(&path).expect("uri to be valid");
        self.get_bq::<_>(&uri, token.to_string())
    }

    pub fn get_query_results(
        &self,
        token: &str,
        project_id: &str,
        job_id: &str,
        req: &GetQueryResultsRequest,
    ) -> client::Result<GetQueryResultsResponse> {
        let path = format!(
            "{}/{}/queries/{}?{}",
            BIGQUERY_ROOT,
            project_id,
            job_id,
            req.to_query()
        );
        let uri = Uri::from_str(&path).expect("uri to be valid");
        self.get_bq::<_>(&uri, token.to_string())
    }

    // helper method for making a GET request
    fn get_bq<D>(&self, uri: &hyper::Uri, token: String) -> client::Result<D>
    where
        for<'de> D: 'static + Send + Deserialize<'de>,
    {
        let mut req = hyper::Request::new(hyper::Method::Get, uri.clone());
        let auth = hyper::header::Authorization(hyper::header::Bearer { token });
        req.headers_mut().set(auth);

        self.request(req).map(|(_, res)| res)
    }

    // helper method for making a POST request with a JSON body
    fn post_bq<B: Serialize, D>(
        &self,
        uri: &hyper::Uri,
        body: B,
        token: String,
    ) -> client::Result<D>
    where
        for<'de> D: 'static + Send + Deserialize<'de>,
    {
        let mut req = hyper::Request::new(hyper::Method::Post, uri.clone());
        req.headers_mut().set(hyper::header::ContentType::json());

        let auth = hyper::header::Authorization(hyper::header::Bearer { token });
        req.headers_mut().set(auth);

        let body = serde_json::to_string(&body).unwrap();
        req.set_body(body);

        self.request(req).map(|(_, res)| res)
    }
}
<commit_msg>compensate for overloading struct<commit_after>#![allow(unused_variables)]
use std::str::FromStr;

use hyper::{self, Uri};

use serde::{Serialize, Deserialize};
use serde_json;

use client::{self, ApiClient};
use svc::common;

static BIGQUERY_ROOT: &str = "https://www.googleapis.com/bigquery/v2/projects";

pub struct BigQueryService {}
pub type Hub<'a> = client::Hub<'a, BigQueryService>;

#[derive(Default, Debug)]
pub struct ListDatasetsRequest {
    pub all: bool,
    pub filter: Option<String>,
    pub max_results: Option<usize>,
    pub page_token: Option<String>,
}

impl ListDatasetsRequest {
    fn to_query(&self) -> String {
        let mut params = vec![("all", self.all.to_string())];
        if let Some(ref filter) = self.filter {
            params.push(("filter", filter.clone()));
        }
        if let Some(ref max_results) = self.max_results {
            params.push(("maxResults", max_results.to_string()));
        }
        if let Some(ref page_token) = self.page_token {
            params.push(("pageToken", page_token.clone()));
        }
        client::encode_query_params(params)
    }
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ListDatasetsResponse {
    pub next_page_token: Option<String>,

    pub datasets: Vec<DatasetMeta>,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct DatasetMeta {
    pub id: String,
    pub dataset_reference: DatasetReference,
    pub friendly_name: Option<String>,
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct DatasetReference {
    pub project_id: String,
    pub dataset_id: String,
}

#[derive(Default, Debug)]
pub struct ListTablesRequest {
    pub max_results: Option<usize>,
    pub page_token: Option<String>,
}

impl ListTablesRequest {
    fn to_query(&self) -> String {
        let mut params = vec![];
        if let Some(ref max_results) = self.max_results {
            params.push(("maxResults", max_results.to_string()));
        }
        if let Some(ref page_token) = self.page_token {
            params.push(("pageToken", page_token.clone()));
        }
        client::encode_query_params(params)
    }
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ListTablesResponse {
    pub next_page_token: Option<String>,
    pub tables: Vec<TableMeta>,
    pub total_items: usize,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TableMeta {
    pub id: String,
    pub table_reference: TableReference,
    pub friendly_name: Option<String>,
    pub view: Option<ViewMeta>,

    #[serde(rename = "type")]
    pub type0: String,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ViewMeta {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub query: Option<String>,

    #[serde(default = "default_view_use_legacy_sql")]
    pub use_legacy_sql: bool,
}

fn default_view_use_legacy_sql() -> bool {
    true
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TableReference {
    pub project_id: String,
    pub dataset_id: String,
    pub table_id: String,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct DescribeTableResponse {
    pub id: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub schema: Option<TableFieldSchema>,

    #[serde(rename = "type")]
    pub type0: String,

    pub table_reference: TableReference,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub friendly_name: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub external_data_configuration: Option<ExtDataConfig>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub view: Option<ViewMeta>,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ExtDataConfig {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub schema: Option<TableFieldSchema>,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TableFieldSchema {
    pub fields: Vec<TableField>,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TableField {
    pub name: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default = "default_table_field_mode")]
    pub mode: String,

    #[serde(rename = "type")]
    pub type0: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub fields: Option<Vec<TableField>>,
}

fn default_table_field_mode() -> String {
    "NULLABLE".into()
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct JobResource {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub kind: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub id: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub dry_run: Option<bool>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub job_reference: Option<JobReference>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub status: Option<JobStatus>,

    pub configuration: JobConfiguration,
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct JobConfiguration {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub query: Option<QueryResource>,
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct QueryResource {
    pub query: String,
    pub use_legacy_sql: bool,
    pub use_query_cache: bool,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub destination_table: Option<TableReference>,
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct JobStatus {
    pub state: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub error_result: Option<QueryError>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub errors: Option<Vec<QueryError>>,
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct JobReference {
    pub project_id: String,

    pub job_id: String,
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct QueryError {
    pub reason: Option<String>,
    pub location: Option<String>,
    pub message: Option<String>,
    pub debug_info: Option<String>,
}

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct GetQueryResultsRequest {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub timeout_ms: Option<usize>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub max_results: Option<usize>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub start_index: Option<usize>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub page_token: Option<String>,
}

impl GetQueryResultsRequest {
    fn to_query(&self) -> String {
        let mut params = Vec::new();
        if let Some(ref timeout_ms) = self.timeout_ms {
            params.push(("timeoutMs", timeout_ms.to_string()));
        }
        if let Some(ref max_results) = self.max_results {
            params.push(("maxResults", max_results.to_string()));
        }
        if let Some(ref page_token) = self.page_token {
            params.push(("pageToken", page_token.clone()));
        }
        if let Some(ref start_index) = self.start_index {
            params.push(("startIndex", start_index.to_string()));
        }
        client::encode_query_params(params)
    }
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct GetQueryResultsResponse {
    pub schema: Option<TableFieldSchema>,
    pub job_reference: Option<JobReference>,
    pub total_rows: Option<String>,
    pub rows: Option<Vec<TableRow>>,
    pub job_complete: bool,
    pub page_token: Option<String>,
    pub errors: Option<Vec<QueryError>>,
}

#[derive(Serialize, Deserialize, Default, Debug)]
pub struct TableRow {
    pub f: Vec<TableCell>,
}

#[derive(Serialize, Deserialize, Default, Debug)]
pub struct TableCell {
    pub v: Cell,
}

#[serde(untagged)]
#[derive(Serialize, Deserialize, Debug)]
pub enum Cell {
    Value(Option<String>),
    Repeat(Vec<TableCell>),
    Row(TableRow),
}

impl Default for Cell {
    fn default() -> Self {
        Cell::Value(None)
    }
}

impl<'a> Hub<'a> {
    pub fn list_datasets(
        &self,
        token: &str,
        project_id: &str,
        req: &ListDatasetsRequest,
    ) -> client::Result<ListDatasetsResponse> {
        let path = format!(
            "{}/{}/datasets?{}",
            BIGQUERY_ROOT,
            project_id,
            req.to_query()
        );

        let uri = Uri::from_str(&path).expect("uri to be valid");
        self.get_bq::<ListDatasetsResponse>(&uri, token.to_string())
    }

    pub fn list_tables(
        &self,
        token: &str,
        project_id: &str,
        dataset_id: &str,
        req: &ListTablesRequest,
    ) -> client::Result<ListTablesResponse> {
        let path = format!(
            "{}/{}/datasets/{}/tables?{}",
            BIGQUERY_ROOT,
            project_id,
            dataset_id,
            req.to_query()
        );
        let uri = Uri::from_str(&path).expect("uri to be valid");
        self.get_bq::<ListTablesResponse>(&uri, token.to_string())
    }

    pub fn describe_table(
        &self,
        token: &str,
        project_id: &str,
        dataset_id: &str,
        table_id: &str,
    ) -> client::Result<DescribeTableResponse> {
        let path = format!(
            "{}/{}/datasets/{}/tables/{}",
            BIGQUERY_ROOT,
            project_id,
            dataset_id,
            table_id
        );
        let uri = Uri::from_str(&path).expect("uri to be valid");
        self.get_bq::<DescribeTableResponse>(&uri, token.to_string())
    }

    pub fn create_job(
        &self,
        token: &str,
        project_id: &str,
        req: &JobResource,
    ) -> client::Result<JobResource> {
        let path = format!("{}/{}/jobs", BIGQUERY_ROOT, project_id);
        let uri = Uri::from_str(&path).expect("uri to be valid");
        self.post_bq::<_, _>(&uri, req, token.to_string())
    }

    pub fn cancel_job(
        &self,
        token: &str,
        project_id: &str,
        job_id: &str,
    ) -> client::Result<JobResource> {
        let path = format!("{}/{}/jobs/{}/cancel", BIGQUERY_ROOT, project_id, job_id);
        let uri = Uri::from_str(&path).expect("uri to be valid");

        #[derive(Deserialize, Debug)]
        #[serde(rename_all = "camelCase")]
        struct Response {
            pub job: JobResource,
        }

        self.post_bq::<_, Response>(&uri, common::Empty {}, token.to_string())
            .map(|r| r.job)
    }

    pub fn get_job(
        &self,
        token: &str,
        project_id: &str,
        job_id: &str,
    ) -> client::Result<JobResource> {
        let path = format!("{}/{}/jobs/{}", BIGQUERY_ROOT, project_id, job_id);
        let uri = Uri::from_str(&path).expect("uri to be valid");
        self.get_bq::<_>(&uri, token.to_string())
    }

    pub fn get_query_results(
        &self,
        token: &str,
        project_id: &str,
        job_id: &str,
        req: &GetQueryResultsRequest,
    ) -> client::Result<GetQueryResultsResponse> {
        let path = format!(
            "{}/{}/queries/{}?{}",
            BIGQUERY_ROOT,
            project_id,
            job_id,
            req.to_query()
        );
        let uri = Uri::from_str(&path).expect("uri to be valid");
        self.get_bq::<_>(&uri, token.to_string())
    }

    // helper method for making a GET request
    fn get_bq<D>(&self, uri: &hyper::Uri, token: String) -> client::Result<D>
    where
        for<'de> D: 'static + Send + Deserialize<'de>,
    {
        let mut req = hyper::Request::new(hyper::Method::Get, uri.clone());
        let auth = hyper::header::Authorization(hyper::header::Bearer { token });
        req.headers_mut().set(auth);

        self.request(req).map(|(_, res)| res)
    }

    // helper method for making a POST request with a JSON body
    fn post_bq<B: Serialize, D>(
        &self,
        uri: &hyper::Uri,
        body: B,
        token: String,
    ) -> client::Result<D>
    where
        for<'de> D: 'static + Send + Deserialize<'de>,
    {
        let mut req = hyper::Request::new(hyper::Method::Post, uri.clone());
        req.headers_mut().set(hyper::header::ContentType::json());

        let auth = hyper::header::Authorization(hyper::header::Bearer { token });
        req.headers_mut().set(auth);

        let body = serde_json::to_string(&body).unwrap();
        req.set_body(body);

        self.request(req).map(|(_, res)| res)
    }
}
<|endoftext|>


<commit_before>use std::prelude::v1::*;
use std::sync::Arc;
use std::cell::UnsafeCell;

// One critical piece of this module's contents are the `TaskRc<A>` handles.
// The purpose of this is to conceptually be able to store data in a task,
// allowing it to be accessed within multiple futures at once. For example if
// you have some concurrent futures working, they may all want mutable access to
// some data. We already know that when the futures are being poll'ed that we're
// entirely synchronized (aka `&mut Task`), so you shouldn't require an
// `Arc<Mutex<T>>` to share as the synchronization isn't necessary!
//
// So the idea here is that you insert data into a task via `Task::insert`, and
// a handle to that data is then returned to you. That handle can later get
// presented to the task itself to actually retrieve the underlying data. The
// invariant is that the data can only ever be accessed with the task present,
// and the lifetime of the actual data returned is connected to the lifetime of
// the task itself.
//
// Conceptually I at least like to think of this as "dynamically adding more
// struct fields to a `Task`". Each call to insert creates a new "name" for the
// struct field, a `TaskRc<A>`, and then you can access the fields of a struct
// with the struct itself (`Task`) as well as the name of the field
// (`TaskRc<A>`). If that analogy doesn't make sense then oh well, it at least
// helped me!
//
// So anyway, we do some interesting trickery here to actually get it to work.
// Each `TaskRc<A>` handle stores `Arc<UnsafeCell<A>>`. So it turns out, we're
// not even adding data to the `Task`! Each `TaskRc<A>` contains a reference
// to this `Arc`, and `TaskRc` handles can be cloned which just bumps the
// reference count on the `Arc` itself.
//
// As before, though, you can present the `Arc` to a `Task` and if they
// originated from the same place you're allowed safe access to the internals.
// We allow but shared and mutable access without the `Sync` bound on the data,
// crucially noting that a `Task` itself is not `Sync`.
//
// So hopefully I've convinced you of this point that the `get` and `get_mut`
// methods below are indeed safe. The data is always valid as it's stored in an
// `Arc`, and access is only allowed with the proof of the associated `Task`.
// One thing you might be asking yourself though is what exactly is this "proof
// of a task"? Right now it's a `usize` corresponding to the `Task`'s
// `TaskHandle` arc allocation.
//
// Wait a minute, isn't that the ABA problem! That is, we create a task A, add
// some data to it, destroy task A, do some work, create a task B, and then ask
// to get the data from task B. In this case though the point of the
// `task_inner` "proof" field is simply that there's some non-`Sync` token
// proving that you can get access to the data. So while weird, this case should
// still be safe, as the data's not stored in the task itself.

/// A reference to a piece of data that's accessible only within a specific
/// `Task`.
///
/// This data is `Send` even when `A` is not `Sync`, because the data stored
/// within is accessed in a single-threaded way. The thread accessing it may
/// change over time, if the task migrates, so `A` must be `Send`.
pub struct TaskRc<A> {
    task_id: usize,
    ptr: Arc<UnsafeCell<A>>,
}

// for safety here, see docs at the top of this module
unsafe impl<A: Send> Send for TaskRc<A> {}
unsafe impl<A: Sync> Sync for TaskRc<A> {}

impl<A> TaskRc<A> {
    /// Inserts a new piece of task-local data into this task, returning a
    /// reference to it.
    ///
    /// Ownership of the data will be transferred to the task, and the data will
    /// be destroyed when the task itself is destroyed. The returned value can
    /// be passed to the `with` method to get a reference back to the original
    /// data.
    ///
    /// Note that the returned handle is cloneable and copyable and can be sent
    /// to other futures which will be associated with the same task. All
    /// futures will then have access to this data when passed the reference
    /// back.
    ///
    /// # Panics
    ///
    /// This function will panic if a task is not currently running.
    pub fn new(a: A) -> TaskRc<A> {
        super::with(|task, _| {
            TaskRc {
                task_id: task.id,
                ptr: Arc::new(UnsafeCell::new(a)),
            }
        })
    }

    /// Operate with a reference to the underlying data.
    ///
    /// This method should be passed a handle previously returned by
    /// `Task::insert`. That handle, when passed back into this method, will
    /// retrieve a reference to the original data.
    ///
    /// # Panics
    ///
    /// This method will panic if a task is not currently running or if `self`
    /// does not belong to the task that is currently running. That is, if
    /// another task generated the `data` handle passed in, this method will
    /// panic.
    pub fn with<F, R>(&self, f: F) -> R
        where F: FnOnce(&A) -> R
    {
        // for safety here, see docs at the top of this module
        super::with(|task, _| {
            assert_eq!(self.task_id, task.id,
                       "TaskRc being accessed on task it does not belong to");
            f(unsafe { &*self.ptr.get() })
        })
    }
}

impl<A> Clone for TaskRc<A> {
    fn clone(&self) -> TaskRc<A> {
        TaskRc {
            task_id: self.task_id,
            ptr: self.ptr.clone(),
        }
    }
}
<commit_msg>Compat with 1.10.0<commit_after>use std::prelude::v1::*;
use std::sync::Arc;
use std::cell::UnsafeCell;

// One critical piece of this module's contents are the `TaskRc<A>` handles.
// The purpose of this is to conceptually be able to store data in a task,
// allowing it to be accessed within multiple futures at once. For example if
// you have some concurrent futures working, they may all want mutable access to
// some data. We already know that when the futures are being poll'ed that we're
// entirely synchronized (aka `&mut Task`), so you shouldn't require an
// `Arc<Mutex<T>>` to share as the synchronization isn't necessary!
//
// So the idea here is that you insert data into a task via `Task::insert`, and
// a handle to that data is then returned to you. That handle can later get
// presented to the task itself to actually retrieve the underlying data. The
// invariant is that the data can only ever be accessed with the task present,
// and the lifetime of the actual data returned is connected to the lifetime of
// the task itself.
//
// Conceptually I at least like to think of this as "dynamically adding more
// struct fields to a `Task`". Each call to insert creates a new "name" for the
// struct field, a `TaskRc<A>`, and then you can access the fields of a struct
// with the struct itself (`Task`) as well as the name of the field
// (`TaskRc<A>`). If that analogy doesn't make sense then oh well, it at least
// helped me!
//
// So anyway, we do some interesting trickery here to actually get it to work.
// Each `TaskRc<A>` handle stores `Arc<UnsafeCell<A>>`. So it turns out, we're
// not even adding data to the `Task`! Each `TaskRc<A>` contains a reference
// to this `Arc`, and `TaskRc` handles can be cloned which just bumps the
// reference count on the `Arc` itself.
//
// As before, though, you can present the `Arc` to a `Task` and if they
// originated from the same place you're allowed safe access to the internals.
// We allow but shared and mutable access without the `Sync` bound on the data,
// crucially noting that a `Task` itself is not `Sync`.
//
// So hopefully I've convinced you of this point that the `get` and `get_mut`
// methods below are indeed safe. The data is always valid as it's stored in an
// `Arc`, and access is only allowed with the proof of the associated `Task`.
// One thing you might be asking yourself though is what exactly is this "proof
// of a task"? Right now it's a `usize` corresponding to the `Task`'s
// `TaskHandle` arc allocation.
//
// Wait a minute, isn't that the ABA problem! That is, we create a task A, add
// some data to it, destroy task A, do some work, create a task B, and then ask
// to get the data from task B. In this case though the point of the
// `task_inner` "proof" field is simply that there's some non-`Sync` token
// proving that you can get access to the data. So while weird, this case should
// still be safe, as the data's not stored in the task itself.

/// A reference to a piece of data that's accessible only within a specific
/// `Task`.
///
/// This data is `Send` even when `A` is not `Sync`, because the data stored
/// within is accessed in a single-threaded way. The thread accessing it may
/// change over time, if the task migrates, so `A` must be `Send`.
pub struct TaskRc<A> {
    task_id: usize,
    ptr: Arc<UnsafeCell<A>>,
}

// for safety here, see docs at the top of this module
unsafe impl<A: Send> Send for TaskRc<A> {}
unsafe impl<A: Sync> Sync for TaskRc<A> {}

impl<A> TaskRc<A> {
    /// Inserts a new piece of task-local data into this task, returning a
    /// reference to it.
    ///
    /// Ownership of the data will be transferred to the task, and the data will
    /// be destroyed when the task itself is destroyed. The returned value can
    /// be passed to the `with` method to get a reference back to the original
    /// data.
    ///
    /// Note that the returned handle is cloneable and copyable and can be sent
    /// to other futures which will be associated with the same task. All
    /// futures will then have access to this data when passed the reference
    /// back.
    ///
    /// # Panics
    ///
    /// This function will panic if a task is not currently running.
    pub fn new(a: A) -> TaskRc<A> {
        super::with(|task, _| {
            TaskRc {
                task_id: task.id,
                ptr: Arc::new(UnsafeCell::new(a)),
            }
        })
    }

    /// Operate with a reference to the underlying data.
    ///
    /// This method should be passed a handle previously returned by
    /// `Task::insert`. That handle, when passed back into this method, will
    /// retrieve a reference to the original data.
    ///
    /// # Panics
    ///
    /// This method will panic if a task is not currently running or if `self`
    /// does not belong to the task that is currently running. That is, if
    /// another task generated the `data` handle passed in, this method will
    /// panic.
    pub fn with<F, R>(&self, f: F) -> R
        where F: FnOnce(&A) -> R
    {
        // for safety here, see docs at the top of this module
        super::with(|task, _| {
            assert!(self.task_id == task.id,
                    "TaskRc being accessed on task it does not belong to");
            f(unsafe { &*self.ptr.get() })
        })
    }
}

impl<A> Clone for TaskRc<A> {
    fn clone(&self) -> TaskRc<A> {
        TaskRc {
            task_id: self.task_id,
            ptr: self.ptr.clone(),
        }
    }
}
<|endoftext|>


<commit_before>use crate::{
    add_team_to_crate, app,
    builders::{CrateBuilder, PublishBuilder},
    new_team, new_user, req, sign_in_as,
    util::RequestHelper,
    TestApp,
};
use cargo_registry::{
    models::{Crate, NewCrateOwnerInvitation},
    schema::crate_owner_invitations,
    views::{
        EncodableCrateOwnerInvitation, EncodableOwner, EncodablePublicUser, InvitationResponse,
    },
};

use conduit::{Handler, Method};
use diesel::prelude::*;

#[derive(Deserialize)]
struct TeamResponse {
    teams: Vec<EncodableOwner>,
}
#[derive(Deserialize)]
struct UserResponse {
    users: Vec<EncodableOwner>,
}
#[derive(Deserialize)]
struct InvitationListResponse {
    crate_owner_invitations: Vec<EncodableCrateOwnerInvitation>,
}

// Implementing locally for now, unless these are needed elsewhere
impl crate::util::MockCookieUser {
    /// As the currently logged in user, accept an invitation to become an owner of the named
    /// crate.
    fn accept_ownership_invitation(&self, krate_name: &str, krate_id: i32) {
        let body = json!({
            "crate_owner_invite": {
                "invited_by_username": "",
                "crate_name": krate_name,
                "crate_id": krate_id,
                "created_at": "",
                "accepted": true
            }
        });

        #[derive(Deserialize)]
        struct CrateOwnerInvitation {
            crate_owner_invitation: InvitationResponse,
        }

        let url = format!("/api/v1/me/crate_owner_invitations/{}", krate_id);
        let crate_owner_invite: CrateOwnerInvitation =
            self.put(&url, body.to_string().as_bytes()).good();
        assert!(crate_owner_invite.crate_owner_invitation.accepted);
        assert_eq!(crate_owner_invite.crate_owner_invitation.crate_id, krate_id);
    }
}

#[test]
fn new_crate_owner() {
    let (app, _, _, token) = TestApp::full().with_token();

    // Create a crate under one user
    let crate_to_publish = PublishBuilder::new("foo_owner").version("1.0.0");
    token.enqueue_publish(crate_to_publish).good();

    // Add the second user as an owner
    let user2 = app.db_new_user("bar");
    token.add_user_owner("foo_owner", user2.as_model());

    // accept invitation for user to be added as owner
    let crate_id = app.db(|conn| Crate::by_name("foo_owner").first::<Crate>(conn).unwrap().id);
    user2.accept_ownership_invitation("foo_owner", crate_id);

    // Make sure this shows up as one of their crates.
    let crates = user2.search_by_user_id(user2.as_model().id);
    assert_eq!(crates.crates.len(), 1);

    // And upload a new crate as the second user
    let crate_to_publish = PublishBuilder::new("foo_owner").version("2.0.0");
    user2
        .db_new_token("bar_token")
        .enqueue_publish(crate_to_publish)
        .good();
}

// Ensures that so long as at least one owner remains associated with the crate,
// a user can still remove their own login as an owner
#[test]
fn owners_can_remove_self() {
    let (app, _, user, token) = TestApp::init().with_token();

    let krate = app
        .db(|conn| CrateBuilder::new("owners_selfremove", user.as_model().id).expect_build(conn));

    // Deleting yourself when you're the only owner isn't allowed.
    let json = token
        .remove_named_owner("owners_selfremove", &user.as_model().gh_login)
        .bad_with_status(200);
    assert!(json.errors[0]
        .detail
        .contains("cannot remove the sole owner of a crate"));

    let user2 = app.db_new_user("secondowner");
    token.add_user_owner("owners_selfremove", user2.as_model());
    user2.accept_ownership_invitation("owners_selfremove", krate.id);

    // Deleting yourself when there are other owners is allowed.
    let json = token
        .remove_named_owner("owners_selfremove", &user.as_model().gh_login)
        .good();
    assert!(json.ok);

    // After you delete yourself, you no longer have permisions to manage the crate.
    let json = token
        .remove_named_owner("owners_selfremove", &user2.as_model().gh_login)
        .bad_with_status(200);

    assert!(json.errors[0]
        .detail
        .contains("only owners have permission to modify owners",));
}

/*  Testing the crate ownership between two crates and one team.
    Given two crates, one crate owned by both a team and a user,
    one only owned by a user, check that the CrateList returned
    for the user_id contains only the crates owned by that user,
    and that the CrateList returned for the team_id contains
    only crates owned by that team.
*/
#[test]
fn check_ownership_two_crates() {
    let (app, anon, user) = TestApp::init().with_user();
    let user = user.as_model();

    let (krate_owned_by_team, team) = app.db(|conn| {
        let t = new_team("team_foo").create_or_update(conn).unwrap();
        let krate = CrateBuilder::new("foo", user.id).expect_build(conn);
        add_team_to_crate(&t, &krate, user, conn).unwrap();
        (krate, t)
    });

    let user2 = app.db_new_user("user_bar");
    let user2 = user2.as_model();
    let krate_not_owned_by_team =
        app.db(|conn| CrateBuilder::new("bar", user2.id).expect_build(conn));

    let json = anon.search_by_user_id(user2.id);
    assert_eq!(json.crates[0].name, krate_not_owned_by_team.name);
    assert_eq!(json.crates.len(), 1);

    let query = format!("team_id={}", team.id);
    let json = anon.search(&query);
    assert_eq!(json.crates.len(), 1);
    assert_eq!(json.crates[0].name, krate_owned_by_team.name);
}

/*  Given a crate owned by both a team and a user, check that the
    JSON returned by the /owner_team route and /owner_user route
    contains the correct kind of owner

    Note that in this case function new_team must take a team name
    of form github:org_name:team_name as that is the format
    EncodableOwner::encodable is expecting
*/
#[test]
fn check_ownership_one_crate() {
    let (app, anon, user) = TestApp::init().with_user();
    let user = user.as_model();

    let team = app.db(|conn| {
        let t = new_team("github:test_org:team_sloth")
            .create_or_update(conn)
            .unwrap();
        let krate = CrateBuilder::new("best_crate", user.id).expect_build(conn);
        add_team_to_crate(&t, &krate, user, conn).unwrap();
        t
    });

    let json: TeamResponse = anon.get("/api/v1/crates/best_crate/owner_team").good();
    assert_eq!(json.teams[0].kind, "team");
    assert_eq!(json.teams[0].name, team.name);

    let json: UserResponse = anon.get("/api/v1/crates/best_crate/owner_user").good();
    assert_eq!(json.users[0].kind, "user");
    assert_eq!(json.users[0].name, user.name);
}

#[test]
fn invitations_are_empty_by_default() {
    let (_, _, user) = TestApp::init().with_user();

    let json: InvitationListResponse = user.get("/api/v1/me/crate_owner_invitations").good();
    assert_eq!(json.crate_owner_invitations.len(), 0);
}

#[test]
fn invitations_list() {
    let (app, _, owner, token) = TestApp::init().with_token();
    let owner = owner.as_model();

    let krate = app.db(|conn| CrateBuilder::new("invited_crate", owner.id).expect_build(conn));

    let user = app.db_new_user("invited_user");
    token.add_user_owner("invited_crate", user.as_model());

    let json: InvitationListResponse = user.get("/api/v1/me/crate_owner_invitations").good();
    assert_eq!(json.crate_owner_invitations.len(), 1);
    assert_eq!(
        json.crate_owner_invitations[0].invited_by_username,
        owner.gh_login
    );
    assert_eq!(json.crate_owner_invitations[0].crate_name, "invited_crate");
    assert_eq!(json.crate_owner_invitations[0].crate_id, krate.id);
}

/*  Given a user inviting a different user to be a crate
    owner, check that the user invited can accept their
    invitation, the invitation will be deleted from
    the invitations table, and a new crate owner will be
    inserted into the table for the given crate.
*/
#[test]
fn test_accept_invitation() {
    #[derive(Deserialize)]
    struct Q {
        users: Vec<EncodablePublicUser>,
    }

    #[derive(Deserialize)]
    struct T {
        crate_owner_invitation: InvitationResponse,
    }

    let (app, middle) = app();
    let mut req = req(Method::Get, "/api/v1/me/crate_owner_invitations");
    let (krate, user) = {
        let conn = app.diesel_database.get().unwrap();
        let owner = new_user("inviting_user").create_or_update(&conn).unwrap();
        let user = new_user("invited_user").create_or_update(&conn).unwrap();
        let krate = CrateBuilder::new("invited_crate", owner.id).expect_build(&conn);

        // This should be replaced by an actual call to the route that `owner --add` hits once
        // that route creates an invitation.
        diesel::insert_into(crate_owner_invitations::table)
            .values(&NewCrateOwnerInvitation {
                invited_by_user_id: owner.id,
                invited_user_id: user.id,
                crate_id: krate.id,
            })
            .execute(&*conn)
            .unwrap();
        (krate, user)
    };
    sign_in_as(&mut req, &user);

    let body = json!({
        "crate_owner_invite": {
            "invited_by_username": "inviting_user",
            "crate_name": "invited_crate",
            "crate_id": krate.id,
            "created_at": "",
            "accepted": true
        }
    });

    // first check that response from inserting new crate owner
    // and deleting crate_owner_invitation is okay
    let mut response = ok_resp!(middle.call(
        req.with_path(&format!("api/v1/me/crate_owner_invitations/{}", krate.id))
            .with_method(Method::Put)
            .with_body(body.to_string().as_bytes()),
    ));

    let json: T = crate::json(&mut response);
    assert_eq!(json.crate_owner_invitation.accepted, true);
    assert_eq!(json.crate_owner_invitation.crate_id, krate.id);

    // then check to make sure that accept_invite did what it
    // was supposed to
    // crate_owner_invitation was deleted
    let mut response = ok_resp!(middle.call(
        req.with_path("api/v1/me/crate_owner_invitations")
            .with_method(Method::Get)
    ));
    let json: InvitationListResponse = crate::json(&mut response);
    assert_eq!(json.crate_owner_invitations.len(), 0);

    // new crate owner was inserted
    let mut response = ok_resp!(middle.call(
        req.with_path("/api/v1/crates/invited_crate/owners")
            .with_method(Method::Get)
    ));
    let json: Q = crate::json(&mut response);
    assert_eq!(json.users.len(), 2);
}

/*  Given a user inviting a different user to be a crate
    owner, check that the user invited can decline their
    invitation and the invitation will be deleted from
    the invitations table.
*/
#[test]
fn test_decline_invitation() {
    #[derive(Deserialize)]
    struct Q {
        users: Vec<EncodablePublicUser>,
    }

    #[derive(Deserialize)]
    struct T {
        crate_owner_invitation: InvitationResponse,
    }

    let (app, middle) = app();
    let mut req = req(Method::Get, "/api/v1/me/crate_owner_invitations");
    let (krate, user) = {
        let conn = app.diesel_database.get().unwrap();
        let owner = new_user("inviting_user").create_or_update(&conn).unwrap();
        let user = new_user("invited_user").create_or_update(&conn).unwrap();
        let krate = CrateBuilder::new("invited_crate", owner.id).expect_build(&conn);

        // This should be replaced by an actual call to the route that `owner --add` hits once
        // that route creates an invitation.
        diesel::insert_into(crate_owner_invitations::table)
            .values(&NewCrateOwnerInvitation {
                invited_by_user_id: owner.id,
                invited_user_id: user.id,
                crate_id: krate.id,
            })
            .execute(&*conn)
            .unwrap();
        (krate, user)
    };
    sign_in_as(&mut req, &user);

    let body = json!({
        "crate_owner_invite": {
            "invited_by_username": "inviting_user",
            "crate_name": "invited_crate",
            "crate_id": krate.id,
            "created_at": "",
            "accepted": false
        }
    });

    // first check that response from deleting
    // crate_owner_invitation is okay
    let mut response = ok_resp!(middle.call(
        req.with_path(&format!("api/v1/me/crate_owner_invitations/{}", krate.id))
            .with_method(Method::Put)
            .with_body(body.to_string().as_bytes()),
    ));

    let json: T = crate::json(&mut response);
    assert_eq!(json.crate_owner_invitation.accepted, false);
    assert_eq!(json.crate_owner_invitation.crate_id, krate.id);

    // then check to make sure that decline_invite did what it
    // was supposed to
    // crate_owner_invitation was deleted
    let mut response = ok_resp!(middle.call(
        req.with_path("api/v1/me/crate_owner_invitations")
            .with_method(Method::Get)
    ));
    let json: InvitationListResponse = crate::json(&mut response);
    assert_eq!(json.crate_owner_invitations.len(), 0);

    // new crate owner was not inserted
    let mut response = ok_resp!(middle.call(
        req.with_path("/api/v1/crates/invited_crate/owners")
            .with_method(Method::Get)
    ));
    let json: Q = crate::json(&mut response);
    assert_eq!(json.users.len(), 1);
}
<commit_msg>Extract a test helper function for listing invitations<commit_after>use crate::{
    add_team_to_crate, app,
    builders::{CrateBuilder, PublishBuilder},
    new_team, new_user, req, sign_in_as,
    util::RequestHelper,
    TestApp,
};
use cargo_registry::{
    models::{Crate, NewCrateOwnerInvitation},
    schema::crate_owner_invitations,
    views::{
        EncodableCrateOwnerInvitation, EncodableOwner, EncodablePublicUser, InvitationResponse,
    },
};

use conduit::{Handler, Method};
use diesel::prelude::*;

#[derive(Deserialize)]
struct TeamResponse {
    teams: Vec<EncodableOwner>,
}
#[derive(Deserialize)]
struct UserResponse {
    users: Vec<EncodableOwner>,
}
#[derive(Deserialize)]
struct InvitationListResponse {
    crate_owner_invitations: Vec<EncodableCrateOwnerInvitation>,
}

// Implementing locally for now, unless these are needed elsewhere
impl crate::util::MockCookieUser {
    /// As the currently logged in user, accept an invitation to become an owner of the named
    /// crate.
    fn accept_ownership_invitation(&self, krate_name: &str, krate_id: i32) {
        let body = json!({
            "crate_owner_invite": {
                "invited_by_username": "",
                "crate_name": krate_name,
                "crate_id": krate_id,
                "created_at": "",
                "accepted": true
            }
        });

        #[derive(Deserialize)]
        struct CrateOwnerInvitation {
            crate_owner_invitation: InvitationResponse,
        }

        let url = format!("/api/v1/me/crate_owner_invitations/{}", krate_id);
        let crate_owner_invite: CrateOwnerInvitation =
            self.put(&url, body.to_string().as_bytes()).good();
        assert!(crate_owner_invite.crate_owner_invitation.accepted);
        assert_eq!(crate_owner_invite.crate_owner_invitation.crate_id, krate_id);
    }

    /// As the currently logged in user, list my pending invitations.
    fn list_invitations(&self) -> InvitationListResponse {
        self.get("/api/v1/me/crate_owner_invitations").good()
    }
}

#[test]
fn new_crate_owner() {
    let (app, _, _, token) = TestApp::full().with_token();

    // Create a crate under one user
    let crate_to_publish = PublishBuilder::new("foo_owner").version("1.0.0");
    token.enqueue_publish(crate_to_publish).good();

    // Add the second user as an owner
    let user2 = app.db_new_user("bar");
    token.add_user_owner("foo_owner", user2.as_model());

    // accept invitation for user to be added as owner
    let crate_id = app.db(|conn| Crate::by_name("foo_owner").first::<Crate>(conn).unwrap().id);
    user2.accept_ownership_invitation("foo_owner", crate_id);

    // Make sure this shows up as one of their crates.
    let crates = user2.search_by_user_id(user2.as_model().id);
    assert_eq!(crates.crates.len(), 1);

    // And upload a new crate as the second user
    let crate_to_publish = PublishBuilder::new("foo_owner").version("2.0.0");
    user2
        .db_new_token("bar_token")
        .enqueue_publish(crate_to_publish)
        .good();
}

// Ensures that so long as at least one owner remains associated with the crate,
// a user can still remove their own login as an owner
#[test]
fn owners_can_remove_self() {
    let (app, _, user, token) = TestApp::init().with_token();

    let krate = app
        .db(|conn| CrateBuilder::new("owners_selfremove", user.as_model().id).expect_build(conn));

    // Deleting yourself when you're the only owner isn't allowed.
    let json = token
        .remove_named_owner("owners_selfremove", &user.as_model().gh_login)
        .bad_with_status(200);
    assert!(json.errors[0]
        .detail
        .contains("cannot remove the sole owner of a crate"));

    let user2 = app.db_new_user("secondowner");
    token.add_user_owner("owners_selfremove", user2.as_model());
    user2.accept_ownership_invitation("owners_selfremove", krate.id);

    // Deleting yourself when there are other owners is allowed.
    let json = token
        .remove_named_owner("owners_selfremove", &user.as_model().gh_login)
        .good();
    assert!(json.ok);

    // After you delete yourself, you no longer have permisions to manage the crate.
    let json = token
        .remove_named_owner("owners_selfremove", &user2.as_model().gh_login)
        .bad_with_status(200);

    assert!(json.errors[0]
        .detail
        .contains("only owners have permission to modify owners",));
}

/*  Testing the crate ownership between two crates and one team.
    Given two crates, one crate owned by both a team and a user,
    one only owned by a user, check that the CrateList returned
    for the user_id contains only the crates owned by that user,
    and that the CrateList returned for the team_id contains
    only crates owned by that team.
*/
#[test]
fn check_ownership_two_crates() {
    let (app, anon, user) = TestApp::init().with_user();
    let user = user.as_model();

    let (krate_owned_by_team, team) = app.db(|conn| {
        let t = new_team("team_foo").create_or_update(conn).unwrap();
        let krate = CrateBuilder::new("foo", user.id).expect_build(conn);
        add_team_to_crate(&t, &krate, user, conn).unwrap();
        (krate, t)
    });

    let user2 = app.db_new_user("user_bar");
    let user2 = user2.as_model();
    let krate_not_owned_by_team =
        app.db(|conn| CrateBuilder::new("bar", user2.id).expect_build(conn));

    let json = anon.search_by_user_id(user2.id);
    assert_eq!(json.crates[0].name, krate_not_owned_by_team.name);
    assert_eq!(json.crates.len(), 1);

    let query = format!("team_id={}", team.id);
    let json = anon.search(&query);
    assert_eq!(json.crates.len(), 1);
    assert_eq!(json.crates[0].name, krate_owned_by_team.name);
}

/*  Given a crate owned by both a team and a user, check that the
    JSON returned by the /owner_team route and /owner_user route
    contains the correct kind of owner

    Note that in this case function new_team must take a team name
    of form github:org_name:team_name as that is the format
    EncodableOwner::encodable is expecting
*/
#[test]
fn check_ownership_one_crate() {
    let (app, anon, user) = TestApp::init().with_user();
    let user = user.as_model();

    let team = app.db(|conn| {
        let t = new_team("github:test_org:team_sloth")
            .create_or_update(conn)
            .unwrap();
        let krate = CrateBuilder::new("best_crate", user.id).expect_build(conn);
        add_team_to_crate(&t, &krate, user, conn).unwrap();
        t
    });

    let json: TeamResponse = anon.get("/api/v1/crates/best_crate/owner_team").good();
    assert_eq!(json.teams[0].kind, "team");
    assert_eq!(json.teams[0].name, team.name);

    let json: UserResponse = anon.get("/api/v1/crates/best_crate/owner_user").good();
    assert_eq!(json.users[0].kind, "user");
    assert_eq!(json.users[0].name, user.name);
}

#[test]
fn invitations_are_empty_by_default() {
    let (_, _, user) = TestApp::init().with_user();

    let json = user.list_invitations();
    assert_eq!(json.crate_owner_invitations.len(), 0);
}

#[test]
fn invitations_list() {
    let (app, _, owner, token) = TestApp::init().with_token();
    let owner = owner.as_model();

    let krate = app.db(|conn| CrateBuilder::new("invited_crate", owner.id).expect_build(conn));

    let user = app.db_new_user("invited_user");
    token.add_user_owner("invited_crate", user.as_model());

    let json = user.list_invitations();
    assert_eq!(json.crate_owner_invitations.len(), 1);
    assert_eq!(
        json.crate_owner_invitations[0].invited_by_username,
        owner.gh_login
    );
    assert_eq!(json.crate_owner_invitations[0].crate_name, "invited_crate");
    assert_eq!(json.crate_owner_invitations[0].crate_id, krate.id);
}

/*  Given a user inviting a different user to be a crate
    owner, check that the user invited can accept their
    invitation, the invitation will be deleted from
    the invitations table, and a new crate owner will be
    inserted into the table for the given crate.
*/
#[test]
fn test_accept_invitation() {
    #[derive(Deserialize)]
    struct Q {
        users: Vec<EncodablePublicUser>,
    }

    #[derive(Deserialize)]
    struct T {
        crate_owner_invitation: InvitationResponse,
    }

    let (app, middle) = app();
    let mut req = req(Method::Get, "/api/v1/me/crate_owner_invitations");
    let (krate, user) = {
        let conn = app.diesel_database.get().unwrap();
        let owner = new_user("inviting_user").create_or_update(&conn).unwrap();
        let user = new_user("invited_user").create_or_update(&conn).unwrap();
        let krate = CrateBuilder::new("invited_crate", owner.id).expect_build(&conn);

        // This should be replaced by an actual call to the route that `owner --add` hits once
        // that route creates an invitation.
        diesel::insert_into(crate_owner_invitations::table)
            .values(&NewCrateOwnerInvitation {
                invited_by_user_id: owner.id,
                invited_user_id: user.id,
                crate_id: krate.id,
            })
            .execute(&*conn)
            .unwrap();
        (krate, user)
    };
    sign_in_as(&mut req, &user);

    let body = json!({
        "crate_owner_invite": {
            "invited_by_username": "inviting_user",
            "crate_name": "invited_crate",
            "crate_id": krate.id,
            "created_at": "",
            "accepted": true
        }
    });

    // first check that response from inserting new crate owner
    // and deleting crate_owner_invitation is okay
    let mut response = ok_resp!(middle.call(
        req.with_path(&format!("api/v1/me/crate_owner_invitations/{}", krate.id))
            .with_method(Method::Put)
            .with_body(body.to_string().as_bytes()),
    ));

    let json: T = crate::json(&mut response);
    assert_eq!(json.crate_owner_invitation.accepted, true);
    assert_eq!(json.crate_owner_invitation.crate_id, krate.id);

    // then check to make sure that accept_invite did what it
    // was supposed to
    // crate_owner_invitation was deleted
    let mut response = ok_resp!(middle.call(
        req.with_path("api/v1/me/crate_owner_invitations")
            .with_method(Method::Get)
    ));
    let json: InvitationListResponse = crate::json(&mut response);
    assert_eq!(json.crate_owner_invitations.len(), 0);

    // new crate owner was inserted
    let mut response = ok_resp!(middle.call(
        req.with_path("/api/v1/crates/invited_crate/owners")
            .with_method(Method::Get)
    ));
    let json: Q = crate::json(&mut response);
    assert_eq!(json.users.len(), 2);
}

/*  Given a user inviting a different user to be a crate
    owner, check that the user invited can decline their
    invitation and the invitation will be deleted from
    the invitations table.
*/
#[test]
fn test_decline_invitation() {
    #[derive(Deserialize)]
    struct Q {
        users: Vec<EncodablePublicUser>,
    }

    #[derive(Deserialize)]
    struct T {
        crate_owner_invitation: InvitationResponse,
    }

    let (app, middle) = app();
    let mut req = req(Method::Get, "/api/v1/me/crate_owner_invitations");
    let (krate, user) = {
        let conn = app.diesel_database.get().unwrap();
        let owner = new_user("inviting_user").create_or_update(&conn).unwrap();
        let user = new_user("invited_user").create_or_update(&conn).unwrap();
        let krate = CrateBuilder::new("invited_crate", owner.id).expect_build(&conn);

        // This should be replaced by an actual call to the route that `owner --add` hits once
        // that route creates an invitation.
        diesel::insert_into(crate_owner_invitations::table)
            .values(&NewCrateOwnerInvitation {
                invited_by_user_id: owner.id,
                invited_user_id: user.id,
                crate_id: krate.id,
            })
            .execute(&*conn)
            .unwrap();
        (krate, user)
    };
    sign_in_as(&mut req, &user);

    let body = json!({
        "crate_owner_invite": {
            "invited_by_username": "inviting_user",
            "crate_name": "invited_crate",
            "crate_id": krate.id,
            "created_at": "",
            "accepted": false
        }
    });

    // first check that response from deleting
    // crate_owner_invitation is okay
    let mut response = ok_resp!(middle.call(
        req.with_path(&format!("api/v1/me/crate_owner_invitations/{}", krate.id))
            .with_method(Method::Put)
            .with_body(body.to_string().as_bytes()),
    ));

    let json: T = crate::json(&mut response);
    assert_eq!(json.crate_owner_invitation.accepted, false);
    assert_eq!(json.crate_owner_invitation.crate_id, krate.id);

    // then check to make sure that decline_invite did what it
    // was supposed to
    // crate_owner_invitation was deleted
    let mut response = ok_resp!(middle.call(
        req.with_path("api/v1/me/crate_owner_invitations")
            .with_method(Method::Get)
    ));
    let json: InvitationListResponse = crate::json(&mut response);
    assert_eq!(json.crate_owner_invitations.len(), 0);

    // new crate owner was not inserted
    let mut response = ok_resp!(middle.call(
        req.with_path("/api/v1/crates/invited_crate/owners")
            .with_method(Method::Get)
    ));
    let json: Q = crate::json(&mut response);
    assert_eq!(json.users.len(), 1);
}
<|endoftext|>


<commit_before>//! Error Reporting for `impl` items that do not match the obligations from their `trait`.

use crate::infer::error_reporting::nice_region_error::NiceRegionError;
use crate::infer::lexical_region_resolve::RegionResolutionError;
use crate::infer::{Subtype, TyCtxtInferExt, ValuePairs};
use crate::traits::ObligationCauseCode::CompareImplMethodObligation;
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::ErrorReported;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::ItemKind;
use rustc_middle::ty::error::ExpectedFound;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::Span;

impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
    /// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`.
    pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option<ErrorReported> {
        if let Some(ref error) = self.error {
            debug!("try_report_impl_not_conforming_to_trait {:?}", error);
            if let RegionResolutionError::SubSupConflict(
                _,
                var_origin,
                sub_origin,
                _sub,
                sup_origin,
                _sup,
            ) = error.clone()
            {
                if let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) =
                    (&sup_origin, &sub_origin)
                {
                    if let (
                        ValuePairs::Types(sub_expected_found),
                        ValuePairs::Types(sup_expected_found),
                        CompareImplMethodObligation { trait_item_def_id, .. },
                    ) = (&sub_trace.values, &sup_trace.values, &sub_trace.cause.code)
                    {
                        if sup_expected_found == sub_expected_found {
                            self.emit_err(
                                var_origin.span(),
                                sub_expected_found.expected,
                                sub_expected_found.found,
                                *trait_item_def_id,
                            );
                            return Some(ErrorReported);
                        }
                    }
                }
            }
        }
        None
    }

    fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>, trait_def_id: DefId) {
        let tcx = self.tcx();
        let trait_sp = self.tcx().def_span(trait_def_id);
        let mut err = self
            .tcx()
            .sess
            .struct_span_err(sp, "`impl` item signature doesn't match `trait` item signature");
        err.span_label(sp, &format!("found `{:?}`", found));
        err.span_label(trait_sp, &format!("expected `{:?}`", expected));
        let trait_fn_sig = tcx.fn_sig(trait_def_id);

        // Check the `trait`'s method's output to look for type parameters that might have
        // unconstrained lifetimes. If the method returns a type parameter and the `impl` has a
        // borrow as the type parameter being implemented, the lifetimes will not match because
        // a new lifetime is being introduced in the `impl` that is not present in the `trait`.
        // Because this is confusing as hell the first time you see it, we give a short message
        // explaining the situation and proposing constraining the type param with a named lifetime
        // so that the `impl` will have one to tie them together.
        struct AssocTypeFinder(FxIndexSet<ty::ParamTy>);
        impl<'tcx> ty::fold::TypeVisitor<'tcx> for AssocTypeFinder {
            fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
                if let ty::Param(param) = ty.kind {
                    self.0.insert(param);
                }
                ty.super_visit_with(self)
            }
        }
        let mut visitor = AssocTypeFinder(FxIndexSet::default());
        trait_fn_sig.output().visit_with(&mut visitor);
        if let Some(id) = tcx.hir().as_local_hir_id(trait_def_id) {
            let parent_id = tcx.hir().get_parent_item(id);
            let trait_item = tcx.hir().expect_item(parent_id);
            if let ItemKind::Trait(_, _, generics, _, _) = &trait_item.kind {
                for param_ty in &visitor.0 {
                    if let Some(generic) = generics.get_named(param_ty.name) {
                        err.span_label(
                            generic.span,
                            "this type parameter might not have a lifetime compatible with the \
                             `impl`",
                        );
                    }
                }
            }
        }

        // Get the span of all the used type parameters in the method.
        let assoc_item = self.tcx().associated_item(trait_def_id);
        let mut visitor = TypeParamSpanVisitor { tcx: self.tcx(), types: vec![] };
        match assoc_item.kind {
            ty::AssocKind::Method => {
                let hir = self.tcx().hir();
                if let Some(hir_id) = hir.as_local_hir_id(assoc_item.def_id) {
                    if let Some(decl) = hir.fn_decl_by_hir_id(hir_id) {
                        visitor.visit_fn_decl(decl);
                    }
                }
            }
            _ => {}
        }
        for span in visitor.types {
            err.span_label(
                span,
                "you might want to borrow this type parameter in the trait to make it match the \
                 `impl`",
            );
        }

        if let Some((expected, found)) = tcx
            .infer_ctxt()
            .enter(|infcx| infcx.expected_found_str_ty(&ExpectedFound { expected, found }))
        {
            // Highlighted the differences when showing the "expected/found" note.
            err.note_expected_found(&"", expected, &"", found);
        } else {
            // This fallback shouldn't be necessary, but let's keep it in just in case.
            err.note(&format!("expected `{:?}`\n   found `{:?}`", expected, found));
        }
        err.note("the lifetime requirements from the `trait` could not be satisfied by the `impl`");
        err.help(
            "verify the lifetime relationships in the `trait` and `impl` between the `self` \
             argument, the other inputs and its output",
        );
        err.emit();
    }
}

struct TypeParamSpanVisitor<'tcx> {
    tcx: TyCtxt<'tcx>,
    types: Vec<Span>,
}

impl Visitor<'tcx> for TypeParamSpanVisitor<'tcx> {
    type Map = hir::intravisit::Map<'tcx>;

    fn nested_visit_map<'this>(
        &'this mut self,
    ) -> hir::intravisit::NestedVisitorMap<'this, Self::Map> {
        hir::intravisit::NestedVisitorMap::OnlyBodies(&self.tcx.hir())
    }

    fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) {
        match arg.kind {
            hir::TyKind::Slice(_) | hir::TyKind::Tup(_) | hir::TyKind::Array(..) => {
                hir::intravisit::walk_ty(self, arg);
            }
            hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments {
                [segment]
                    if segment
                        .res
                        .map(|res| match res {
                            hir::def::Res::Def(hir::def::DefKind::TyParam, _) => true,
                            _ => false,
                        })
                        .unwrap_or(false) =>
                {
                    self.types.push(path.span);
                }
                _ => {}
            },
            _ => {}
        }
    }
}
<commit_msg>fix rebase<commit_after>//! Error Reporting for `impl` items that do not match the obligations from their `trait`.

use crate::infer::error_reporting::nice_region_error::NiceRegionError;
use crate::infer::lexical_region_resolve::RegionResolutionError;
use crate::infer::{Subtype, TyCtxtInferExt, ValuePairs};
use crate::traits::ObligationCauseCode::CompareImplMethodObligation;
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::ErrorReported;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::ItemKind;
use rustc_middle::ty::error::ExpectedFound;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::Span;

impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
    /// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`.
    pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option<ErrorReported> {
        if let Some(ref error) = self.error {
            debug!("try_report_impl_not_conforming_to_trait {:?}", error);
            if let RegionResolutionError::SubSupConflict(
                _,
                var_origin,
                sub_origin,
                _sub,
                sup_origin,
                _sup,
            ) = error.clone()
            {
                if let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) =
                    (&sup_origin, &sub_origin)
                {
                    if let (
                        ValuePairs::Types(sub_expected_found),
                        ValuePairs::Types(sup_expected_found),
                        CompareImplMethodObligation { trait_item_def_id, .. },
                    ) = (&sub_trace.values, &sup_trace.values, &sub_trace.cause.code)
                    {
                        if sup_expected_found == sub_expected_found {
                            self.emit_err(
                                var_origin.span(),
                                sub_expected_found.expected,
                                sub_expected_found.found,
                                *trait_item_def_id,
                            );
                            return Some(ErrorReported);
                        }
                    }
                }
            }
        }
        None
    }

    fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>, trait_def_id: DefId) {
        let tcx = self.tcx();
        let trait_sp = self.tcx().def_span(trait_def_id);
        let mut err = self
            .tcx()
            .sess
            .struct_span_err(sp, "`impl` item signature doesn't match `trait` item signature");
        err.span_label(sp, &format!("found `{:?}`", found));
        err.span_label(trait_sp, &format!("expected `{:?}`", expected));
        let trait_fn_sig = tcx.fn_sig(trait_def_id);

        // Check the `trait`'s method's output to look for type parameters that might have
        // unconstrained lifetimes. If the method returns a type parameter and the `impl` has a
        // borrow as the type parameter being implemented, the lifetimes will not match because
        // a new lifetime is being introduced in the `impl` that is not present in the `trait`.
        // Because this is confusing as hell the first time you see it, we give a short message
        // explaining the situation and proposing constraining the type param with a named lifetime
        // so that the `impl` will have one to tie them together.
        struct AssocTypeFinder(FxIndexSet<ty::ParamTy>);
        impl<'tcx> ty::fold::TypeVisitor<'tcx> for AssocTypeFinder {
            fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
                if let ty::Param(param) = ty.kind {
                    self.0.insert(param);
                }
                ty.super_visit_with(self)
            }
        }
        let mut visitor = AssocTypeFinder(FxIndexSet::default());
        trait_fn_sig.output().visit_with(&mut visitor);
        if let Some(id) = tcx.hir().as_local_hir_id(trait_def_id) {
            let parent_id = tcx.hir().get_parent_item(id);
            let trait_item = tcx.hir().expect_item(parent_id);
            if let ItemKind::Trait(_, _, generics, _, _) = &trait_item.kind {
                for param_ty in &visitor.0 {
                    if let Some(generic) = generics.get_named(param_ty.name) {
                        err.span_label(
                            generic.span,
                            "this type parameter might not have a lifetime compatible with the \
                             `impl`",
                        );
                    }
                }
            }
        }

        // Get the span of all the used type parameters in the method.
        let assoc_item = self.tcx().associated_item(trait_def_id);
        let mut visitor = TypeParamSpanVisitor { tcx: self.tcx(), types: vec![] };
        match assoc_item.kind {
            ty::AssocKind::Method => {
                let hir = self.tcx().hir();
                if let Some(hir_id) = hir.as_local_hir_id(assoc_item.def_id) {
                    if let Some(decl) = hir.fn_decl_by_hir_id(hir_id) {
                        visitor.visit_fn_decl(decl);
                    }
                }
            }
            _ => {}
        }
        for span in visitor.types {
            err.span_label(
                span,
                "you might want to borrow this type parameter in the trait to make it match the \
                 `impl`",
            );
        }

        if let Some((expected, found)) = tcx
            .infer_ctxt()
            .enter(|infcx| infcx.expected_found_str_ty(&ExpectedFound { expected, found }))
        {
            // Highlighted the differences when showing the "expected/found" note.
            err.note_expected_found(&"", expected, &"", found);
        } else {
            // This fallback shouldn't be necessary, but let's keep it in just in case.
            err.note(&format!("expected `{:?}`\n   found `{:?}`", expected, found));
        }
        err.note("the lifetime requirements from the `trait` could not be satisfied by the `impl`");
        err.help(
            "verify the lifetime relationships in the `trait` and `impl` between the `self` \
             argument, the other inputs and its output",
        );
        err.emit();
    }
}

struct TypeParamSpanVisitor<'tcx> {
    tcx: TyCtxt<'tcx>,
    types: Vec<Span>,
}

impl Visitor<'tcx> for TypeParamSpanVisitor<'tcx> {
    type Map = hir::intravisit::Map<'tcx>;

    fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<Self::Map> {
        hir::intravisit::NestedVisitorMap::OnlyBodies(self.tcx.hir())
    }

    fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) {
        match arg.kind {
            hir::TyKind::Slice(_) | hir::TyKind::Tup(_) | hir::TyKind::Array(..) => {
                hir::intravisit::walk_ty(self, arg);
            }
            hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments {
                [segment]
                    if segment
                        .res
                        .map(|res| match res {
                            hir::def::Res::Def(hir::def::DefKind::TyParam, _) => true,
                            _ => false,
                        })
                        .unwrap_or(false) =>
                {
                    self.types.push(path.span);
                }
                _ => {}
            },
            _ => {}
        }
    }
}
<|endoftext|>


<commit_before>//! A Tokio aware channel `Receiver` wrapping a `mio::Receiver`.

use io::Ready;
use reactor::{self, Source};
use mio::channel as mio;
use std::io;
use std::sync::mpsc::{RecvError, TryRecvError};

/// A Tokio aware channel `Receiver` wrapping a `mio::Receiver`.
pub struct Receiver<T> {
    mio: mio::Receiver<T>,
    source: Source,
}

impl<T> Receiver<T> {
    /// Create and return a new Tokio aware `Receiver` backed by the given Mio
    /// receiver
    pub fn watch(mio: mio::Receiver<T>) -> io::Result<Receiver<T>> {
        let source = try!(reactor::register_source(&mio, Ready::readable()));

        Ok(Receiver {
            mio: mio,
            source: source,
        })
    }

    /// Attempts to return a pending value on this receiver without blocking.
    ///
    /// This method will never block the caller in order to wait for data to
    /// become available. Instead, it will return `Ok(None)` and register
    /// interest with the `Reactor`.
    pub fn recv(&self) -> Result<Option<T>, RecvError> {
        if !self.source.is_readable() {
            return Ok(None);
        }

        match self.mio.try_recv() {
            Ok(val) => {
                self.source.advance();
                Ok(Some(val))
            }
            Err(TryRecvError::Empty) => {
                self.source.unset_readable();
                Ok(None)
            }
            Err(TryRecvError::Disconnected) => {
                self.source.advance();
                Err(RecvError)
            }
        }
    }
}
<commit_msg>Implement Readiness for Receiver<commit_after>//! A Tokio aware channel `Receiver` wrapping a `mio::Receiver`.

use io::{Ready, Readiness};
use reactor::{self, Source};
use mio::channel as mio;
use std::io;
use std::sync::mpsc::{RecvError, TryRecvError};

/// A Tokio aware channel `Receiver` wrapping a `mio::Receiver`.
pub struct Receiver<T> {
    mio: mio::Receiver<T>,
    source: Source,
}

impl<T> Receiver<T> {
    /// Create and return a new Tokio aware `Receiver` backed by the given Mio
    /// receiver
    pub fn watch(mio: mio::Receiver<T>) -> io::Result<Receiver<T>> {
        let source = try!(reactor::register_source(&mio, Ready::readable()));

        Ok(Receiver {
            mio: mio,
            source: source,
        })
    }

    /// Attempts to return a pending value on this receiver without blocking.
    ///
    /// This method will never block the caller in order to wait for data to
    /// become available. Instead, it will return `Ok(None)` and register
    /// interest with the `Reactor`.
    pub fn recv(&self) -> Result<Option<T>, RecvError> {
        if !self.source.is_readable() {
            return Ok(None);
        }

        match self.mio.try_recv() {
            Ok(val) => {
                self.source.advance();
                Ok(Some(val))
            }
            Err(TryRecvError::Empty) => {
                self.source.unset_readable();
                Ok(None)
            }
            Err(TryRecvError::Disconnected) => {
                self.source.advance();
                Err(RecvError)
            }
        }
    }
}

impl<T> Readiness for Receiver<T> {
    fn is_readable(&self) -> bool {
        self.source.is_readable()
    }

    fn is_writable(&self) -> bool {
        self.source.is_writable()
    }
}
<|endoftext|>


<commit_before>/*
 * $Id: pad.d,v 1.1.1.1 2006/11/19 07:54:55 kenta Exp $
 *
 * Copyright 2006 Kenta Cho. Some rights reserved.
 */
/*
module src.util.sdl.pad;

private import std.string;
private import std.stream;

private import derelict.sdl.sdl;

private import src.util.sdl.input;
private import src.util.sdl.recordableinput;
*/

/**
 * Inputs from a joystick and a keyboard.
 */

let JOYSTICK_AXIS : i32 = 16384;

struct Pad: Input {
  keys : &u8;
  buttonsExchanged : bool;
  stick : &SDL_Joystick, //= null;
  state : PadState;
}

impl Pad {
  fn new() -> Pad {
    Pad{keys : SDL_GetKeyState(null),
      buttonsExchanged : false,
      stick : SDL_JoystickOpen(0),
      state : PadState::default(),
    }
  }

  fn openJoystick(&mut self, st &SDL_Joystick /*= null*/) -> &SDL_Joystick {
    if st == null {
      if SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0 {
        return null;
      }
      self.stick = SDL_JoystickOpen(0);
    } else {
      self.stick = st;
    }
    self.stick;
  }

  fn handleEvent(&mut self, event : &SDL_Event) {
    self.keys = SDL_GetKeyState(null);
  }

  fn getState(&mut self) -> &PadState {
    let x : i32 = 0;
    let y : i32 = 0;
    self.state.dir = 0;
    if self.stick {
      x = SDL_JoystickGetAxis(self.stick, 0);
      y = SDL_JoystickGetAxis(self.stick, 1);
    }
    if (self.keys[SDLK_RIGHT] == SDL_PRESSED || self.keys[SDLK_KP6] == SDL_PRESSED ||
        self.keys[SDLK_d] == SDL_PRESSED || self.keys[SDLK_l] == SDL_PRESSED ||
        x > JOYSTICK_AXIS) {
      self.state.dir |= PadState.Dir.RIGHT;
    }
    if (self.keys[SDLK_LEFT] == SDL_PRESSED || self.keys[SDLK_KP4] == SDL_PRESSED ||
        self.keys[SDLK_a] == SDL_PRESSED || self.keys[SDLK_j] == SDL_PRESSED ||
        x < -JOYSTICK_AXIS) {
      self.state.dir |= PadState.Dir.LEFT;
    }
    if (self.keys[SDLK_DOWN] == SDL_PRESSED || self.keys[SDLK_KP2] == SDL_PRESSED ||
        self.keys[SDLK_s] == SDL_PRESSED || self.keys[SDLK_k] == SDL_PRESSED ||
        y > JOYSTICK_AXIS) {
      self.state.dir |= PadState.Dir.DOWN;
    }
    if (self.keys[SDLK_UP] == SDL_PRESSED ||  self.keys[SDLK_KP8] == SDL_PRESSED ||
        self.keys[SDLK_w] == SDL_PRESSED || self.keys[SDLK_i] == SDL_PRESSED ||
        y < -JOYSTICK_AXIS) {
      self.state.dir |= PadState.Dir.UP;
    }
    self.state.button = 0;
    let btn1 : i32 = 0;
    let btn2 : i32 = 0;
    let leftTrigger : f32 = 0.0;
    let rightTrigger : f32  = 0.0;
    if self.stick {
      btn1 = SDL_JoystickGetButton(stick, 0) + SDL_JoystickGetButton(stick, 2) +
             SDL_JoystickGetButton(stick, 4) + SDL_JoystickGetButton(stick, 6) +
             SDL_JoystickGetButton(stick, 8) + SDL_JoystickGetButton(stick, 10);
      btn2 = SDL_JoystickGetButton(stick, 1) + SDL_JoystickGetButton(stick, 3) +
             SDL_JoystickGetButton(stick, 5) + SDL_JoystickGetButton(stick, 7) +
             SDL_JoystickGetButton(stick, 9) + SDL_JoystickGetButton(stick, 11);
    }
    if self.keys[SDLK_z] == SDL_PRESSED || self.keys[SDLK_PERIOD] == SDL_PRESSED ||
        self.keys[SDLK_LCTRL] == SDL_PRESSED || self.keys[SDLK_RCTRL] == SDL_PRESSED ||
        btn1 {
      if !self.buttonsExchanged {
        self.state.button |= PadState.Button.A;
      } else {
        self.state.button |= PadState.Button.B;
      }
    }
    if self.keys[SDLK_x] == SDL_PRESSED || self.keys[SDLK_SLASH] == SDL_PRESSED ||
        self.keys[SDLK_LALT] == SDL_PRESSED || self.keys[SDLK_RALT] == SDL_PRESSED ||
        self.keys[SDLK_LSHIFT] == SDL_PRESSED || self.keys[SDLK_RSHIFT] == SDL_PRESSED ||
        self.keys[SDLK_RETURN] == SDL_PRESSED ||
        btn2 {
      if !self.buttonsExchanged {
        self.state.button |= PadState.Button.B;
      } else {
        self.state.button |= PadState.Button.A;
      }
    }
    self.state
  }

  fn getNullState(&mut self) -> &self {
    self.state.clear();
    self.state;
  }
}

enum Dir {
  NONE,
  UP, // = 1,
  DOWN, // = 2,
  LEFT, // = 4,
  RIGHT, // = 8,
};

enum Button {
  NONE,
  A, // = 16,
  B, // = 32,
  ANY, // = 48,
};

struct PadState {
  dir : Dir,
  button : Button,
}

impl PadState {
  fn new() -> PadState {
    PadState{dir : Dir::NONE, button : Button::NONE}
  }

/*
  public static PadState newInstance() {
    return new PadState;
  }

  public static PadState newInstance(PadState s) {
    return new PadState(s);
  }

  public this() {
  }

  public this(PadState s) {
    this();
    set(s);
  }
*/

  fn set(&mut self, s : &PadState) {
    self.dir = s.dir;
    self.button = s.button;
  }

  fn clear(&mut self) {
    self.dir = Dir::NONE;
    self.button = Button::NONE;
  }

  fn read(&mut self, fd : &File) {
    let mut s; : i32;
    fd.read(s);
    self.dir = s & (Dir.UP | Dir.DOWN | Dir.LEFT | Dir.RIGHT);
    self.button = s & Button.ANY;
  }

  fn write(&mut self, fd : &File) {
    let s : i32 = self.dir | self.button;
    fd.write(s);
  }

  fn equals(&self, s : &PadState) -> bool {
    (self.dir == s.dir && self.button == s.button)
  }
}

trait RecordablePad : Pad {
  //mixin RecordableInput!(PadState);

  fn getState(&self, bool doRecord /*= true*/) -> PadState {
    let s : PadState = super.getState();
    if doRecord {
      self.record(s);
    }
    s
  }
}
<commit_msg>some pad cleanup<commit_after>/*
 * $Id: pad.d,v 1.1.1.1 2006/11/19 07:54:55 kenta Exp $
 *
 * Copyright 2006 Kenta Cho. Some rights reserved.
 */
/*
module src.util.sdl.pad;

private import std.string;
private import std.stream;

private import derelict.sdl.sdl;

private import src.util.sdl.input;
private import src.util.sdl.recordableinput;
*/

use util::sdl::input::*;

/**
 * Inputs from a joystick and a keyboard.
 */

const JOYSTICK_AXIS : i32 = 16384;

struct Pad {
  keys : &u8,
  buttonsExchanged : bool,
  stick : Some(&SDL_Joystick), //= null;
  state : PadState,
}

impl Pad {
  fn new() -> Pad {
    Pad{
      keys : SDL_GetKeyState(0),
      buttonsExchanged : false,
      stick : Some(SDL_JoystickOpen(0)),
      state : PadState::new(),
    }
  }

  fn openJoystick(&mut self, st : Option(&SDL_Joystick) /*= null*/) -> Option(&SDL_Joystick) {
    if st == None {
      if SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0 {
        return None;
      }
      self.stick = Some(SDL_JoystickOpen(0));
    } else {
      self.stick = st;
    }
    self.stick
  }

  fn handleEvent(&mut self, event : &SDL_Event) {
    self.keys = SDL_GetKeyState(null);
  }

  fn getState(&mut self) -> &PadState {
    let x : i32 = 0;
    let y : i32 = 0;
    self.state.dir = 0;
    if let Some(stick) = self.stick {
      x = SDL_JoystickGetAxis(stick, 0);
      y = SDL_JoystickGetAxis(stick, 1);
    }
    if self.keys[SDLK_RIGHT] == SDL_PRESSED || self.keys[SDLK_KP6] == SDL_PRESSED ||
        self.keys[SDLK_d] == SDL_PRESSED || self.keys[SDLK_l] == SDL_PRESSED ||
        x > JOYSTICK_AXIS {
      self.state.dir |= Dir::RIGHT;
    }
    if self.keys[SDLK_LEFT] == SDL_PRESSED || self.keys[SDLK_KP4] == SDL_PRESSED ||
        self.keys[SDLK_a] == SDL_PRESSED || self.keys[SDLK_j] == SDL_PRESSED ||
        x < -JOYSTICK_AXIS {
      self.state.dir |= Dir::LEFT;
    }
    if self.keys[SDLK_DOWN] == SDL_PRESSED || self.keys[SDLK_KP2] == SDL_PRESSED ||
        self.keys[SDLK_s] == SDL_PRESSED || self.keys[SDLK_k] == SDL_PRESSED ||
        y > JOYSTICK_AXIS {
      self.state.dir |= Dir::DOWN;
    }
    if self.keys[SDLK_UP] == SDL_PRESSED ||  self.keys[SDLK_KP8] == SDL_PRESSED ||
        self.keys[SDLK_w] == SDL_PRESSED || self.keys[SDLK_i] == SDL_PRESSED ||
        y < -JOYSTICK_AXIS {
      self.state.dir |= Dir::UP;
    }
    self.state.button = 0;
    let btn1 : i32 = 0;
    let btn2 : i32 = 0;
    let leftTrigger : f32 = 0.0;
    let rightTrigger : f32  = 0.0;
    if let Some(stick) = self.stick {
      btn1 = SDL_JoystickGetButton(stick, 0) + SDL_JoystickGetButton(stick, 2) +
             SDL_JoystickGetButton(stick, 4) + SDL_JoystickGetButton(stick, 6) +
             SDL_JoystickGetButton(stick, 8) + SDL_JoystickGetButton(stick, 10);
      btn2 = SDL_JoystickGetButton(stick, 1) + SDL_JoystickGetButton(stick, 3) +
             SDL_JoystickGetButton(stick, 5) + SDL_JoystickGetButton(stick, 7) +
             SDL_JoystickGetButton(stick, 9) + SDL_JoystickGetButton(stick, 11);
    }
    if self.keys[SDLK_z] == SDL_PRESSED || self.keys[SDLK_PERIOD] == SDL_PRESSED ||
        self.keys[SDLK_LCTRL] == SDL_PRESSED || self.keys[SDLK_RCTRL] == SDL_PRESSED ||
        btn1 {
      if !self.buttonsExchanged {
        self.state.button |= Button::A;
      } else {
        self.state.button |= Button::B;
      }
    }
    if self.keys[SDLK_x] == SDL_PRESSED || self.keys[SDLK_SLASH] == SDL_PRESSED ||
        self.keys[SDLK_LALT] == SDL_PRESSED || self.keys[SDLK_RALT] == SDL_PRESSED ||
        self.keys[SDLK_LSHIFT] == SDL_PRESSED || self.keys[SDLK_RSHIFT] == SDL_PRESSED ||
        self.keys[SDLK_RETURN] == SDL_PRESSED ||
        btn2 {
      if !self.buttonsExchanged {
        self.state.button |= Button::B;
      } else {
        self.state.button |= Button::A;
      }
    }
    self.state
  }

  fn getNullState(&mut self) -> &self {
    self.state.clear();
    self.state;
  }
}

impl Inut for Pad {

}

enum Dir {
  NONE,
  UP, // = 1,
  DOWN, // = 2,
  LEFT, // = 4,
  RIGHT, // = 8,
}

enum Button {
  NONE,
  A, // = 16,
  B, // = 32,
  ANY, // = 48,
}

struct PadState {
  dir : Dir,
  button : Button,
}

impl PadState {
  fn new() -> PadState {
    PadState{dir : Dir::NONE, button : Button::NONE}
  }

/*
  public static PadState newInstance() {
    return new PadState;
  }

  public static PadState newInstance(PadState s) {
    return new PadState(s);
  }

  public this() {
  }

  public this(PadState s) {
    this();
    set(s);
  }
*/

  fn set(&mut self, s : &PadState) {
    self.dir = s.dir;
    self.button = s.button;
  }

  fn clear(&mut self) {
    self.dir = Dir::NONE;
    self.button = Button::NONE;
  }

  fn read(&mut self, fd : &File) {
    let mut s : i32;
    fd.read(s);
    self.dir = s & (Dir::UP | Dir::DOWN | Dir::LEFT | Dir::RIGHT);
    self.button = s & Button::ANY;
  }

  fn write(&mut self, fd : &File) {
    let s : i32 = self.dir | self.button;
    fd.write(s);
  }

  fn equals(&self, s : &PadState) -> bool {
    (self.dir == s.dir && self.button == s.button)
  }
}

trait RecordablePad : Pad {
  //mixin RecordableInput!(PadState);

  fn getState(&self, doRecord : bool /*= true*/) -> PadState {
    let s : PadState = super.getState();
    if doRecord {
      self.record(s);
    }
    s
  }
}
<|endoftext|>