<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: Option<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)
    }
}
<commit_msg>bigquery: add time_partitioning info<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: Option<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 time_partitioning: Option<TimePartitioning>,

    #[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 TimePartitioning {
    #[serde(rename = "type")]
    // Always "DAY"
    pub type0: String,
    // Partitions older than this will be deleted automatically
    #[serde(skip_serializing_if = "Option::is_none")]
    pub expiration_ms: Option<i64>,
    // If unset, the table is partitioned by the pseudo column "_PARTITIONTIME"
    #[serde(skip_serializing_if = "Option::is_none")]
    pub field: Option<String>,
}

#[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::collections::HashMap;
use std::cmp::{max, min};
use utils::calculate_ratio;
use std::fmt::Debug;

#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord)]
pub struct Match {
    pub first_start: usize,
    pub second_start: usize,
    pub size: usize,
}

impl Match {
    fn new(first_start: usize, second_start: usize, size: usize) -> Match {
        Match {
            first_start: first_start,
            second_start: second_start,
            size: size,
        }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct Opcode {
    pub tag: String,
    pub first_start: usize,
    pub first_end: usize,
    pub second_start: usize,
    pub second_end: usize,
}

impl Opcode {
    fn new(tag: String,
           first_start: usize,
           first_end: usize,
           second_start: usize,
           second_end: usize)
           -> Opcode {
        Opcode {
            tag: tag,
            first_start: first_start,
            first_end: first_end,
            second_start: second_start,
            second_end: second_end,
        }
    }
}

pub trait Sequence: Debug {
    fn len(&self) -> usize;
    fn at_index(&self, index: usize) -> Option<&str>;
}

impl Sequence for str {
    fn len(&self) -> usize {
        self.len()
    }

    fn at_index(&self, index: usize) -> Option<&str> {
        if index > self.len() {
            return None;
        }
        unsafe { Some(self.slice_unchecked(index, index + 1)) }
    }
}

impl<'a> Sequence for Vec<&'a str> {
    fn len(&self) -> usize {
        self.len()
    }

    fn at_index(&self, index: usize) -> Option<&str> {
        if index < self.len() {
            return Some(self[index]);
        }
        None
    }
}

impl Sequence for String {
    fn len(&self) -> usize {
        self.len()
    }

    fn at_index(&self, index: usize) -> Option<&str> {
        if index > self.len() {
            return None;
        }
        unsafe { Some(self.slice_unchecked(index, index + 1)) }
    }
}

impl<'a> Sequence for Vec<String> {
    fn len(&self) -> usize {
        self.len()
    }

    fn at_index(&self, index: usize) -> Option<&str> {
        if index < self.len() {
            return Some(&self[index]);
        }
        None
    }
}

pub struct SequenceMatcher<'a, T: 'a + ?Sized + Sequence> {
    first_sequence: &'a T,
    second_sequence: &'a T,
    matching_blocks: Option<Vec<Match>>,
    opcodes: Option<Vec<Opcode>>,
    is_junk: Option<fn(&str) -> bool>,
    second_sequence_elements: HashMap<&'a str, Vec<usize>>,
    second_sequence_popular: Vec<&'a str>,
}

impl<'a, T: ?Sized + Sequence> SequenceMatcher<'a, T> {
    pub fn new(first_sequence: &'a T, second_sequence: &'a T) -> SequenceMatcher<'a, T> {
        let mut matcher = SequenceMatcher {
            first_sequence: first_sequence,
            second_sequence: second_sequence,
            matching_blocks: None,
            opcodes: None,
            is_junk: None,
            second_sequence_elements: HashMap::new(),
            second_sequence_popular: Vec::new(),
        };
        matcher.set_seqs(first_sequence, second_sequence);
        matcher
    }

    pub fn set_is_junk(&mut self, is_junk: Option<fn(&str) -> bool>) {
        self.is_junk = is_junk;
        self.set_second_seq(self.second_sequence);
    }

    pub fn set_seqs(&mut self, first_sequence: &'a T, second_sequence: &'a T) {
        self.set_first_seq(first_sequence);
        self.set_second_seq(second_sequence);
    }

    pub fn set_first_seq(&mut self, sequence: &'a T) {
        self.first_sequence = sequence;
        self.matching_blocks = None;
        self.opcodes = None;
    }

    pub fn set_second_seq(&mut self, sequence: &'a T) {
        self.second_sequence = sequence;
        self.matching_blocks = None;
        self.opcodes = None;
        self.chain_second_seq();
    }

    fn chain_second_seq(&mut self) {
        let second_sequence = self.second_sequence;
        let mut second_sequence_elements = HashMap::new();
        for i in 0..second_sequence.len() {
            let mut counter = second_sequence_elements.entry(second_sequence.at_index(i).unwrap())
                .or_insert(Vec::new());
            counter.push(i);
        }
        if self.is_junk.is_some() {
            let mut junk = Vec::new();
            for element in second_sequence_elements.keys() {
                if (self.is_junk.unwrap())(element) {
                    junk.push(element.clone());
                }
            }
            for element in &junk {
                second_sequence_elements.remove(element);
            }
        }
        let mut popular = Vec::new();
        let len = second_sequence.len();
        if len >= 200 {
            let test_len = (len as f32 / 100.0).floor() as usize + 1;
            for (element, indexes) in second_sequence_elements.iter() {
                if indexes.len() > test_len {
                    popular.push(element.clone());
                }
            }
            for element in &popular {
                second_sequence_elements.remove(element);
            }
        }
        self.second_sequence_elements = second_sequence_elements;
        self.second_sequence_popular = popular;
    }

    pub fn find_longest_match(&self,
                              first_start: usize,
                              first_end: usize,
                              second_start: usize,
                              second_end: usize)
                              -> Match {
        let first_sequence = &self.first_sequence;
        let second_sequence = &self.second_sequence;
        let second_sequence_elements = &self.second_sequence_elements;
        let (mut best_i, mut best_j, mut best_size) = (first_start, second_start, 0);
        let mut j2len: HashMap<usize, usize> = HashMap::new();
        for i in first_start..first_end {
            let mut new_j2len: HashMap<usize, usize> = HashMap::new();
            match second_sequence_elements.get(first_sequence.at_index(i).unwrap()) {
                Some(indexes) => {
                    for j in indexes {
                        let j = j.clone();
                        if j < second_start {
                            continue;
                        };
                        if j >= second_end {
                            break;
                        };
                        let mut size = 0;
                        if j > 0 {
                            match j2len.get(&(j - 1)) {
                                Some(k) => {
                                    size = k.clone();
                                }
                                None => {}
                            }
                        }
                        size += 1;
                        new_j2len.insert(j, size);
                        if size > best_size {
                            best_i = i + 1 - size;
                            best_j = j + 1 - size;
                            best_size = size;
                        }
                    }
                }
                None => {}
            }
            j2len = new_j2len;
        }
        for _ in 0..2 {
            while best_i > first_start && best_j > second_start &&
                  first_sequence.at_index(best_i - 1) == second_sequence.at_index(best_j - 1) {
                best_i = best_i - 1;
                best_j = best_j - 1;
                best_size = best_size + 1;
            }
            while best_i + best_size < first_end && best_j + best_size < second_end &&
                  first_sequence.at_index(best_i + best_size) ==
                  second_sequence.at_index(best_j + best_size) {
                best_size += 1;
            }
        }
        Match::new(best_i, best_j, best_size)
    }

    pub fn get_matching_blocks(&mut self) -> Vec<Match> {
        if self.matching_blocks.as_ref().is_some() {
            return self.matching_blocks.as_ref().unwrap().clone();
        }
        let (first_length, second_length) = (self.first_sequence.len(), self.second_sequence.len());
        let mut matches = Vec::new();
        let mut queue = vec![(0, first_length, 0, second_length)];
        while !queue.is_empty() {
            let (first_start, first_end, second_start, second_end) = queue.pop().unwrap();
            let m = self.find_longest_match(first_start, first_end, second_start, second_end);
            match m.size {
                0 => {}
                _ => {
                    if first_start < m.first_start && second_start < m.second_start {
                        queue.push((first_start, m.first_start, second_start, m.second_start));
                    }
                    if m.first_start + m.size < first_end && m.second_start + m.size < second_end {
                        queue.push((m.first_start + m.size,
                                    first_end,
                                    m.second_start + m.size,
                                    second_end));
                    }
                    matches.push(m);
                }
            }
        }
        matches.sort_by(|a, b| a.cmp(b));
        let (mut first_start, mut second_start, mut size) = (0, 0, 0);
        let mut non_adjacent = Vec::new();
        for m in &matches {
            if first_start + size == m.first_start && second_start + size == m.second_start {
                size += m.size
            } else {
                if size != 0 {
                    non_adjacent.push(Match::new(first_start, second_start, size));
                }
                first_start = m.first_start;
                second_start = m.second_start;
                size = m.size;
            }
        }
        if size != 0 {
            non_adjacent.push(Match::new(first_start, second_start, size));
        }
        non_adjacent.push(Match::new(first_length, second_length, 0));
        self.matching_blocks = Some(non_adjacent);
        self.matching_blocks.as_ref().unwrap().clone()
    }

    pub fn get_opcodes(&mut self) -> Vec<Opcode> {
        if self.opcodes.as_ref().is_some() {
            return self.opcodes.as_ref().unwrap().clone();
        }
        let mut opcodes = Vec::new();
        let (mut i, mut j) = (0, 0);
        for m in self.get_matching_blocks() {
            let mut tag = String::new();
            if i < m.first_start && j < m.second_start {
                tag = String::from("replace");
            } else if i < m.first_start {
                tag = String::from("delete");
            } else if j < m.second_start {
                tag = String::from("insert");
            }
            if !tag.is_empty() {
                opcodes.push(Opcode::new(tag, i, m.first_start, j, m.second_start));
            }
            i = m.first_start + m.size;
            j = m.second_start + m.size;
            if m.size != 0 {
                opcodes.push(
Opcode::new(String::from("equal"), m.first_start, i, m.second_start, j)
);
            }
        }
        self.opcodes = Some(opcodes);
        return self.opcodes.as_ref().unwrap().clone();
    }

    pub fn get_grouped_opcodes(&mut self, n: usize) -> Vec<Vec<Opcode>> {
        let mut res = Vec::new();
        let mut codes = self.get_opcodes();
        if codes.is_empty() {
            codes.push(Opcode::new("equal".to_string(), 0, 1, 0, 1));
        }

        if codes.first().unwrap().tag == "equal" {
            let mut opcode = codes.first_mut().unwrap();
            opcode.first_start = max(opcode.first_start, opcode.first_end - n);
            opcode.second_start = max(opcode.second_start, opcode.second_end - n);
        }
        if codes.last().unwrap().tag == "equal" {
            let mut opcode = codes.last_mut().unwrap();
            opcode.first_end = min(opcode.first_start + n, opcode.first_end);
            opcode.second_end = min(opcode.second_start + n, opcode.second_end);
        }
        let nn = n + n;
        let mut group = Vec::new();
        for code in &codes {
            let (mut first_start, mut second_start) = (code.first_start, code.second_start);
            if code.tag == "equal" && code.first_end - code.first_start > nn {
                group.push(Opcode::new(code.tag.clone(),
                                       code.first_start,
                                       min(code.first_end, code.first_start + n),
                                       code.second_start,
                                       min(code.second_end, code.second_start + n)));
                res.push(group.clone());
                group.clear();
                first_start = max(first_start, code.first_end - n);
                second_start = max(second_start, code.second_end - n);
            }
            group.push(Opcode::new(code.tag.clone(),
                                   first_start,
                                   code.first_end,
                                   second_start,
                                   code.second_end));
        }
        if !group.is_empty() && !(group.len() == 1 && group.first().unwrap().tag == "equal") {
            res.push(group.clone());
        }
        res
    }

    pub fn ratio(&mut self) -> f32 {
        let matches = self.get_matching_blocks().iter().fold(0, |res, &m| res + m.size);
        calculate_ratio(matches,
                        self.first_sequence.len() + self.second_sequence.len())
    }
}
<commit_msg>Fixed a bug with subtraction in the opcode code<commit_after>use std::collections::HashMap;
use std::cmp::{max, min};
use utils::calculate_ratio;
use std::fmt::Debug;

#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord)]
pub struct Match {
    pub first_start: usize,
    pub second_start: usize,
    pub size: usize,
}

impl Match {
    fn new(first_start: usize, second_start: usize, size: usize) -> Match {
        Match {
            first_start: first_start,
            second_start: second_start,
            size: size,
        }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct Opcode {
    pub tag: String,
    pub first_start: usize,
    pub first_end: usize,
    pub second_start: usize,
    pub second_end: usize,
}

impl Opcode {
    fn new(tag: String,
           first_start: usize,
           first_end: usize,
           second_start: usize,
           second_end: usize)
           -> Opcode {
        Opcode {
            tag: tag,
            first_start: first_start,
            first_end: first_end,
            second_start: second_start,
            second_end: second_end,
        }
    }
}

pub trait Sequence: Debug {
    fn len(&self) -> usize;
    fn at_index(&self, index: usize) -> Option<&str>;
}

impl Sequence for str {
    fn len(&self) -> usize {
        self.len()
    }

    fn at_index(&self, index: usize) -> Option<&str> {
        if index > self.len() {
            return None;
        }
        unsafe { Some(self.slice_unchecked(index, index + 1)) }
    }
}

impl<'a> Sequence for Vec<&'a str> {
    fn len(&self) -> usize {
        self.len()
    }

    fn at_index(&self, index: usize) -> Option<&str> {
        if index < self.len() {
            return Some(self[index]);
        }
        None
    }
}

impl Sequence for String {
    fn len(&self) -> usize {
        self.len()
    }

    fn at_index(&self, index: usize) -> Option<&str> {
        if index > self.len() {
            return None;
        }
        unsafe { Some(self.slice_unchecked(index, index + 1)) }
    }
}

impl<'a> Sequence for Vec<String> {
    fn len(&self) -> usize {
        self.len()
    }

    fn at_index(&self, index: usize) -> Option<&str> {
        if index < self.len() {
            return Some(&self[index]);
        }
        None
    }
}

pub struct SequenceMatcher<'a, T: 'a + ?Sized + Sequence> {
    first_sequence: &'a T,
    second_sequence: &'a T,
    matching_blocks: Option<Vec<Match>>,
    opcodes: Option<Vec<Opcode>>,
    is_junk: Option<fn(&str) -> bool>,
    second_sequence_elements: HashMap<&'a str, Vec<usize>>,
    second_sequence_popular: Vec<&'a str>,
}

impl<'a, T: ?Sized + Sequence> SequenceMatcher<'a, T> {
    pub fn new(first_sequence: &'a T, second_sequence: &'a T) -> SequenceMatcher<'a, T> {
        let mut matcher = SequenceMatcher {
            first_sequence: first_sequence,
            second_sequence: second_sequence,
            matching_blocks: None,
            opcodes: None,
            is_junk: None,
            second_sequence_elements: HashMap::new(),
            second_sequence_popular: Vec::new(),
        };
        matcher.set_seqs(first_sequence, second_sequence);
        matcher
    }

    pub fn set_is_junk(&mut self, is_junk: Option<fn(&str) -> bool>) {
        self.is_junk = is_junk;
        self.set_second_seq(self.second_sequence);
    }

    pub fn set_seqs(&mut self, first_sequence: &'a T, second_sequence: &'a T) {
        self.set_first_seq(first_sequence);
        self.set_second_seq(second_sequence);
    }

    pub fn set_first_seq(&mut self, sequence: &'a T) {
        self.first_sequence = sequence;
        self.matching_blocks = None;
        self.opcodes = None;
    }

    pub fn set_second_seq(&mut self, sequence: &'a T) {
        self.second_sequence = sequence;
        self.matching_blocks = None;
        self.opcodes = None;
        self.chain_second_seq();
    }

    fn chain_second_seq(&mut self) {
        let second_sequence = self.second_sequence;
        let mut second_sequence_elements = HashMap::new();
        for i in 0..second_sequence.len() {
            let mut counter = second_sequence_elements.entry(second_sequence.at_index(i).unwrap())
                .or_insert(Vec::new());
            counter.push(i);
        }
        if self.is_junk.is_some() {
            let mut junk = Vec::new();
            for element in second_sequence_elements.keys() {
                if (self.is_junk.unwrap())(element) {
                    junk.push(element.clone());
                }
            }
            for element in &junk {
                second_sequence_elements.remove(element);
            }
        }
        let mut popular = Vec::new();
        let len = second_sequence.len();
        if len >= 200 {
            let test_len = (len as f32 / 100.0).floor() as usize + 1;
            for (element, indexes) in second_sequence_elements.iter() {
                if indexes.len() > test_len {
                    popular.push(element.clone());
                }
            }
            for element in &popular {
                second_sequence_elements.remove(element);
            }
        }
        self.second_sequence_elements = second_sequence_elements;
        self.second_sequence_popular = popular;
    }

    pub fn find_longest_match(&self,
                              first_start: usize,
                              first_end: usize,
                              second_start: usize,
                              second_end: usize)
                              -> Match {
        let first_sequence = &self.first_sequence;
        let second_sequence = &self.second_sequence;
        let second_sequence_elements = &self.second_sequence_elements;
        let (mut best_i, mut best_j, mut best_size) = (first_start, second_start, 0);
        let mut j2len: HashMap<usize, usize> = HashMap::new();
        for i in first_start..first_end {
            let mut new_j2len: HashMap<usize, usize> = HashMap::new();
            match second_sequence_elements.get(first_sequence.at_index(i).unwrap()) {
                Some(indexes) => {
                    for j in indexes {
                        let j = j.clone();
                        if j < second_start {
                            continue;
                        };
                        if j >= second_end {
                            break;
                        };
                        let mut size = 0;
                        if j > 0 {
                            match j2len.get(&(j - 1)) {
                                Some(k) => {
                                    size = k.clone();
                                }
                                None => {}
                            }
                        }
                        size += 1;
                        new_j2len.insert(j, size);
                        if size > best_size {
                            best_i = i + 1 - size;
                            best_j = j + 1 - size;
                            best_size = size;
                        }
                    }
                }
                None => {}
            }
            j2len = new_j2len;
        }
        for _ in 0..2 {
            while best_i > first_start && best_j > second_start &&
                  first_sequence.at_index(best_i - 1) == second_sequence.at_index(best_j - 1) {
                best_i = best_i - 1;
                best_j = best_j - 1;
                best_size = best_size + 1;
            }
            while best_i + best_size < first_end && best_j + best_size < second_end &&
                  first_sequence.at_index(best_i + best_size) ==
                  second_sequence.at_index(best_j + best_size) {
                best_size += 1;
            }
        }
        Match::new(best_i, best_j, best_size)
    }

    pub fn get_matching_blocks(&mut self) -> Vec<Match> {
        if self.matching_blocks.as_ref().is_some() {
            return self.matching_blocks.as_ref().unwrap().clone();
        }
        let (first_length, second_length) = (self.first_sequence.len(), self.second_sequence.len());
        let mut matches = Vec::new();
        let mut queue = vec![(0, first_length, 0, second_length)];
        while !queue.is_empty() {
            let (first_start, first_end, second_start, second_end) = queue.pop().unwrap();
            let m = self.find_longest_match(first_start, first_end, second_start, second_end);
            match m.size {
                0 => {}
                _ => {
                    if first_start < m.first_start && second_start < m.second_start {
                        queue.push((first_start, m.first_start, second_start, m.second_start));
                    }
                    if m.first_start + m.size < first_end && m.second_start + m.size < second_end {
                        queue.push((m.first_start + m.size,
                                    first_end,
                                    m.second_start + m.size,
                                    second_end));
                    }
                    matches.push(m);
                }
            }
        }
        matches.sort_by(|a, b| a.cmp(b));
        let (mut first_start, mut second_start, mut size) = (0, 0, 0);
        let mut non_adjacent = Vec::new();
        for m in &matches {
            if first_start + size == m.first_start && second_start + size == m.second_start {
                size += m.size
            } else {
                if size != 0 {
                    non_adjacent.push(Match::new(first_start, second_start, size));
                }
                first_start = m.first_start;
                second_start = m.second_start;
                size = m.size;
            }
        }
        if size != 0 {
            non_adjacent.push(Match::new(first_start, second_start, size));
        }
        non_adjacent.push(Match::new(first_length, second_length, 0));
        self.matching_blocks = Some(non_adjacent);
        self.matching_blocks.as_ref().unwrap().clone()
    }

    pub fn get_opcodes(&mut self) -> Vec<Opcode> {
        if self.opcodes.as_ref().is_some() {
            return self.opcodes.as_ref().unwrap().clone();
        }
        let mut opcodes = Vec::new();
        let (mut i, mut j) = (0, 0);
        for m in self.get_matching_blocks() {
            let mut tag = String::new();
            if i < m.first_start && j < m.second_start {
                tag = String::from("replace");
            } else if i < m.first_start {
                tag = String::from("delete");
            } else if j < m.second_start {
                tag = String::from("insert");
            }
            if !tag.is_empty() {
                opcodes.push(Opcode::new(tag, i, m.first_start, j, m.second_start));
            }
            i = m.first_start + m.size;
            j = m.second_start + m.size;
            if m.size != 0 {
                opcodes.push(
Opcode::new(String::from("equal"), m.first_start, i, m.second_start, j)
);
            }
        }
        self.opcodes = Some(opcodes);
        return self.opcodes.as_ref().unwrap().clone();
    }

    pub fn get_grouped_opcodes(&mut self, n: usize) -> Vec<Vec<Opcode>> {
        let mut res = Vec::new();
        let mut codes = self.get_opcodes();
        if codes.is_empty() {
            codes.push(Opcode::new("equal".to_string(), 0, 1, 0, 1));
        }

        if codes.first().unwrap().tag == "equal" {
            let mut opcode = codes.first_mut().unwrap();
            opcode.first_start = max(opcode.first_start, opcode.first_end.saturating_sub(n));
            opcode.second_start = max(opcode.second_start, opcode.second_end.saturating_sub(n));
        }
        if codes.last().unwrap().tag == "equal" {
            let mut opcode = codes.last_mut().unwrap();
            opcode.first_end = min(opcode.first_start + n, opcode.first_end);
            opcode.second_end = min(opcode.second_start + n, opcode.second_end);
        }
        let nn = n + n;
        let mut group = Vec::new();
        for code in &codes {
            let (mut first_start, mut second_start) = (code.first_start, code.second_start);
            if code.tag == "equal" && code.first_end - code.first_start > nn {
                group.push(Opcode::new(code.tag.clone(),
                                       code.first_start,
                                       min(code.first_end, code.first_start + n),
                                       code.second_start,
                                       min(code.second_end, code.second_start + n)));
                res.push(group.clone());
                group.clear();
                first_start = max(first_start, code.first_end.saturating_sub(n));
                second_start = max(second_start, code.second_end.saturating_sub(n));
            }
            group.push(Opcode::new(code.tag.clone(),
                                   first_start,
                                   code.first_end,
                                   second_start,
                                   code.second_end));
        }
        if !group.is_empty() && !(group.len() == 1 && group.first().unwrap().tag == "equal") {
            res.push(group.clone());
        }
        res
    }

    pub fn ratio(&mut self) -> f32 {
        let matches = self.get_matching_blocks().iter().fold(0, |res, &m| res + m.size);
        calculate_ratio(matches,
                        self.first_sequence.len() + self.second_sequence.len())
    }
}
<|endoftext|>


<commit_before>use nalgebra::DMatrix;
use std::ops::{Index, IndexMut};

/// The game's grid, internally represented by matrices provided by the nalgebra crate.
pub struct Grid {
    matrix: DMatrix<bool>,
}

impl Grid {
    /// Create a new grid with the specified dimensions. All cells default to `false`.
    pub fn new(rows: usize, columns: usize) -> Grid {
        Grid { matrix: DMatrix::from_element(rows, columns, false) }
    }

    /// The number of columns in the grid.
    pub fn cols(&self) -> usize {
        self.matrix.ncols()
    }

    /// The number of rows in the grid.
    pub fn rows(&self) -> usize {
        self.matrix.nrows()
    }
}

impl Index<(usize, usize)> for Grid {
    type Output = bool;

    fn index(&self, index: (usize, usize)) -> &bool {
        &self.matrix[index]
    }
}

impl IndexMut<(usize, usize)> for Grid {
    fn index_mut(&mut self, index: (usize, usize)) -> &mut bool {
        &mut self.matrix[index]
    }
}

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

    #[test]
    fn bounds_are_reported_correctly() {
        let grid = Grid::new(10, 10);

        assert_eq!(10, grid.rows());
        assert_eq!(10, grid.cols());

        assert_eq!(false, grid[(9, 9)]);
    }

    #[test]
    #[should_panic]
    fn horizontal_bound_should_overflow() {
        let grid = Grid::new(10, 10);

        grid[(10, 9)];
    }

    #[test]
    #[should_panic]
    fn vertical_bound_should_overflow() {
        let grid = Grid::new(10, 10);

        grid[(9, 10)];
    }

    #[test]
    fn indexing_works() {
        let mut grid = Grid::new(10, 10);

        for i in 0..10 {
            grid[(i, 0)] = true;
        }

        for x in 0..10 {
            for y in 0..10 {
                if y == 0 {
                    assert_eq!(true, grid[(x, y)])
                } else {
                    assert_eq!(false, grid[(x, y)])
                }
            }
        }
    }
}
<commit_msg>Voeg een functie toe voor het krijgen van het aantal buren<commit_after>use nalgebra::DMatrix;
use std::cmp::{min, max};
use std::ops::{Index, IndexMut};

/// The game's grid, internally represented by matrices provided by the nalgebra crate.
pub struct Grid {
    matrix: DMatrix<bool>,
}

impl Grid {
    /// Create a new grid with the specified dimensions. All cells default to `false`.
    pub fn new(rows: usize, columns: usize) -> Grid {
        Grid { matrix: DMatrix::from_element(rows, columns, false) }
    }

    /// The number of columns in the grid.
    pub fn cols(&self) -> usize {
        self.matrix.ncols()
    }

    /// The number of rows in the grid.
    pub fn rows(&self) -> usize {
        self.matrix.nrows()
    }

    pub fn neighbours(&self, (x, y): (usize, usize)) -> u8 {
        let mut total = 0;

        for p in max(x, 1) - 1..min(x + 2, self.rows() - 1) {
            for q in max(y, 1) - 1..min(y + 2, self.cols() - 1) {
                if self[(p, q)] {
                    total += 1;
                }
            }
        }

        total
    }
}

impl Index<(usize, usize)> for Grid {
    type Output = bool;

    fn index(&self, index: (usize, usize)) -> &bool {
        &self.matrix[index]
    }
}

impl IndexMut<(usize, usize)> for Grid {
    fn index_mut(&mut self, index: (usize, usize)) -> &mut bool {
        &mut self.matrix[index]
    }
}

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

    #[test]
    fn bounds_are_reported_correctly() {
        let grid = Grid::new(10, 10);

        assert_eq!(10, grid.rows());
        assert_eq!(10, grid.cols());

        assert_eq!(false, grid[(9, 9)]);
    }

    #[test]
    #[should_panic]
    fn horizontal_bound_should_overflow() {
        let grid = Grid::new(10, 10);

        grid[(10, 9)];
    }

    #[test]
    #[should_panic]
    fn vertical_bound_should_overflow() {
        let grid = Grid::new(10, 10);

        grid[(9, 10)];
    }

    #[test]
    fn indexing_works() {
        let mut grid = Grid::new(10, 10);

        for i in 0..10 {
            grid[(i, 0)] = true;
        }

        for x in 0..10 {
            for y in 0..10 {
                if y == 0 {
                    assert_eq!(true, grid[(x, y)])
                } else {
                    assert_eq!(false, grid[(x, y)])
                }
            }
        }
    }

    #[test]
    fn neighbours_are_reported_correctly() {
        let mut grid = Grid::new(10, 10);
        grid[(4, 4)] = true;
        grid[(5, 4)] = true;
        grid[(6, 4)] = true;
        grid[(4, 6)] = true;

        assert_eq!(4, grid.neighbours((5, 5)));
    }

    #[test]
    fn neighbours_are_reported_correctly_for_corners() {
        let mut grid = Grid::new(10, 10);
        grid[(1, 0)] = true;
        grid[(1, 1)] = true;
        grid[(0, 1)] = true;

        assert_eq!(3, grid.neighbours((0, 0)));
    }
}
<|endoftext|>


<commit_before>/*!
Rust bindings to the [sodium library](https://github.com/jedisct1/libsodium).

Sodium is a portable implementation of Dan Bernsteins [NaCl: Networking and
Cryptography library](http://nacl.cr.yp.to)

For most users, if you want public-key (asymmetric) cryptography you should use
the functions in `crypto::asymmetricbox` for encryption/decryption.

If you want secret-key (symmetric) cryptography you should be using the
functions in `crypto::secretbox` for encryption/decryption.

For public-key signatures you should use the functions in `crypto::sign` for
signature creation and verification.

Unless you know what you're doing you most certainly don't want to use the
functions in `crypto::scalarmult`, `crypto::stream`, `crypto::auth` and
`crypto::onetimeauth`.

## Thread Safety
All functions in this library are thread-safe provided that the `init()`
function has been called during program execution.

If `init()` hasn't been called then all functions except the random-number
generation functions and the key-generation functions are thread-safe.

# Public-key cryptography
 `crypto::asymmetricbox`

 `crypto::sign`

# Secret-key cryptography
 `crypto::secretbox`

 `crypto::stream`

 `crypto::auth`

 `crypto::onetimeauth`

# Low-level functions
 `crypto::hash`

 `crypto::verify`

 `crypto::shorthash`
 */
#![crate_id = "sodiumoxide#0.1"]
#![comment = "Fast cryptographic library"]
#![license = "MIT"]
#![crate_type = "lib"]
#![warn(missing_doc)]
#![warn(non_uppercase_statics)]
#![warn(non_camel_case_types)]
#![warn(managed_heap_memory)]
#![warn(unnecessary_qualification)]
#![feature(globs)]
#![feature(macro_rules)]
extern crate libc;
use libc::c_int;

#[link(name = "sodium")]
extern {
    fn sodium_init() -> c_int;
}

/**
 * `init()` initializes the sodium library and chooses faster versions of
 * the primitives if possible. `init()` also makes the random number generation
 * functions (`gen_key`, `gen_keypair`, `gen_nonce`, `randombytes`, `randombytes_into`)
 * thread-safe
 */
pub fn init() -> bool {
    unsafe {
        sodium_init() == 0
    }
}

/**
 * Cryptographic functions
 */
pub mod crypto {
    pub mod asymmetricbox;
    pub mod sign;
    pub mod scalarmult;
    pub mod auth;
    pub mod hash;
    pub mod secretbox;
    pub mod onetimeauth;
    pub mod stream;
    pub mod shorthash;

    pub mod verify;
}

pub mod randombytes;
mod utils;
<commit_msg>crate_id -> crate_name<commit_after>/*!
Rust bindings to the [sodium library](https://github.com/jedisct1/libsodium).

Sodium is a portable implementation of Dan Bernsteins [NaCl: Networking and
Cryptography library](http://nacl.cr.yp.to)

For most users, if you want public-key (asymmetric) cryptography you should use
the functions in `crypto::asymmetricbox` for encryption/decryption.

If you want secret-key (symmetric) cryptography you should be using the
functions in `crypto::secretbox` for encryption/decryption.

For public-key signatures you should use the functions in `crypto::sign` for
signature creation and verification.

Unless you know what you're doing you most certainly don't want to use the
functions in `crypto::scalarmult`, `crypto::stream`, `crypto::auth` and
`crypto::onetimeauth`.

## Thread Safety
All functions in this library are thread-safe provided that the `init()`
function has been called during program execution.

If `init()` hasn't been called then all functions except the random-number
generation functions and the key-generation functions are thread-safe.

# Public-key cryptography
 `crypto::asymmetricbox`

 `crypto::sign`

# Secret-key cryptography
 `crypto::secretbox`

 `crypto::stream`

 `crypto::auth`

 `crypto::onetimeauth`

# Low-level functions
 `crypto::hash`

 `crypto::verify`

 `crypto::shorthash`
 */
#![crate_name = "sodiumoxide"]
#![comment = "Fast cryptographic library"]
#![license = "MIT"]
#![crate_type = "lib"]
#![warn(missing_doc)]
#![warn(non_uppercase_statics)]
#![warn(non_camel_case_types)]
#![warn(managed_heap_memory)]
#![warn(unnecessary_qualification)]
#![feature(globs)]
#![feature(macro_rules)]
extern crate libc;
use libc::c_int;

#[link(name = "sodium")]
extern {
    fn sodium_init() -> c_int;
}

/**
 * `init()` initializes the sodium library and chooses faster versions of
 * the primitives if possible. `init()` also makes the random number generation
 * functions (`gen_key`, `gen_keypair`, `gen_nonce`, `randombytes`, `randombytes_into`)
 * thread-safe
 */
pub fn init() -> bool {
    unsafe {
        sodium_init() == 0
    }
}

/**
 * Cryptographic functions
 */
pub mod crypto {
    pub mod asymmetricbox;
    pub mod sign;
    pub mod scalarmult;
    pub mod auth;
    pub mod hash;
    pub mod secretbox;
    pub mod onetimeauth;
    pub mod stream;
    pub mod shorthash;

    pub mod verify;
}

pub mod randombytes;
mod utils;
<|endoftext|>


<commit_before>extern crate rand;
extern crate time;
use std::io;
use std::f64;
use std::thread;
use std::sync::{Arc, Mutex};
use std::io::prelude::*;
use std::str::FromStr;
use rand::thread_rng;
use rand::distributions::{IndependentSample, Range};

fn f(x: f64) -> f64 {
    1.0 / (x * x + 1.0)
}

fn monte_carlo(a: f64, b: f64, n: i64) -> f64 {
    let between = Range::new(a, b);
    let mut rng = rand::thread_rng();
    let mut sum = 0.0;
    for _ in 0..n {
        let x = between.ind_sample(&mut rng);
        sum += f(x);
    }
    (b - a) * sum / n as f64
}

fn read_line<T: FromStr>(text: &str) -> Result<T, T::Err> {
    let mut buffer = String::new();
    print!("{}", text);
    io::stdout()
        .flush()
        .ok()
        .expect("[error] Can't flush to stdout!");
    io::stdin()
        .read_line(&mut buffer)
        .ok()
        .expect("[error] Can't read line!");
    buffer.trim().parse::<T>()
}

fn main() {
    let (a, b) = (0.0, 1.0);
    let iterations = read_line("Enter iteration count: ").unwrap_or(10000);
    let thread_count = read_line("Enter thread count: ").unwrap_or(8);
    let h = (b - a) / thread_count as f64;
    let step = iterations / thread_count;
    let result: Arc<Mutex<f64>> = Arc::new(Mutex::new(0.0));
    let mut threads = Vec::new();
    println!("iteration count: {}", iterations);
    let start_time = time::get_time();
    for i in (0..iterations).filter(|&x| x % step == 0) {
        let result = result.clone();
        threads.push(thread::spawn(move || {
            let xk = |k: i64| a + k as f64 * h;
            let (x0, x1) = (xk(i / step), xk(i / step + 1));
            let result_thread = monte_carlo(x0, x1, step);
            let mut result = result.lock().unwrap();
            *result += result_thread;
            println!("#{} result = {:.50}", i / step, result_thread);
        }));
    }
    for thread in threads {
        thread.join()
              .ok()
              .expect("Can't join to thread!");
    }
    let end_time = time::get_time();
    let result = result.lock().unwrap();
    let pi = *result * 4.0;
    println!("> real pi = {:.50}", f64::consts::PI);
    println!(">> result = {:.50}", pi);
    println!("> epsilon = {:.50}", (pi - f64::consts::PI).abs());
    println!("> {:?}", end_time - start_time);
}
<commit_msg>[upd] use channel instead Arc+Mutex<commit_after>extern crate rand;
extern crate time;
use std::io;
use std::f64;
use std::thread;
use std::sync::mpsc::{self, Sender, Receiver};
use std::io::prelude::*;
use std::str::FromStr;
use rand::thread_rng;
use rand::distributions::{IndependentSample, Range};

fn f(x: f64) -> f64 {
    (x.powf(2.0) + 1.0).recip()
}

fn monte_carlo(a: f64, b: f64, n: i64) -> f64 {
    let between = Range::new(a, b);
    let mut rng = rand::thread_rng();
    let mut sum = 0.0;
    for _ in 0..n {
        let x = between.ind_sample(&mut rng);
        sum += f(x);
    }
    (b - a) * sum / n as f64
}

fn read_line<T: FromStr>(text: &str) -> Result<T, T::Err> {
    let mut buffer = String::new();
    print!("{}", text);
    io::stdout()
        .flush()
        .ok()
        .expect("[error] Can't flush to stdout!");
    io::stdin()
        .read_line(&mut buffer)
        .ok()
        .expect("[error] Can't read line!");
    buffer.trim().parse::<T>()
}

fn main() {
    let (a, b) = (0.0, 1.0);
    let iterations = read_line("Enter iteration count: ").unwrap_or(10000);
    let thread_count = read_line("Enter thread count: ").unwrap_or(8);
    let h = (b - a) / thread_count as f64;
    let step = iterations / thread_count;
    let mut threads = Vec::new();
    let (tx, rx): (Sender<f64>, Receiver<f64>) = mpsc::channel();
    println!("iteration count: {}", iterations);
    let start_time = time::get_time();
    for i in (0..iterations).filter(|&x| x % step == 0) {
        let thread_tx = tx.clone();
        threads.push(thread::spawn(move || {
            let xk = |k: i64| a + k as f64 * h;
            let (x0, x1) = (xk(i / step), xk(i / step + 1));
            let result_thread = monte_carlo(x0, x1, step);
            thread_tx.send(result_thread).unwrap();
            println!("#{} result = {:.50}", i / step, result_thread);
        }));
    }
    let mut result = 0.0;
    for thread in threads {
        thread.join()
              .ok()
              .expect("Can't join to thread!");
        result += rx.recv().unwrap();
    }
    let end_time = time::get_time();
    let pi = result * 4.0;
    println!("> real pi = {:.50}", f64::consts::PI);
    println!(">> result = {:.50}", pi);
    println!("> epsilon = {:.50}", (pi - f64::consts::PI).abs());
    println!("> {:?}", end_time - start_time);
}
<|endoftext|>


<commit_before>

use types::cursor::XCursorImage;

use wayland_sys::server::WAYLAND_SERVER_HANDLE;
use wlroots_sys::{wl_list, wlr_output, wlr_output_events, wlr_output_layout,
                  wlr_output_layout_add_auto, wlr_output_layout_create, wlr_output_layout_destroy,
                  wlr_output_layout_remove, wlr_output_make_current, wlr_output_mode,
                  wlr_output_set_cursor, wlr_output_set_mode, wlr_output_swap_buffers};

use std::cell::RefCell;
use std::ffi::CStr;
use std::rc::Rc;

pub struct OutputState {
    pub layout: Option<Rc<RefCell<OutputLayout>>>
}

/// A wrapper around a wlr_output.
#[derive(Debug)]
pub struct Output {
    output: *mut wlr_output
}

#[derive(Debug)]
pub struct OutputLayout {
    layout: *mut wlr_output_layout
}

impl Output {
    pub unsafe fn set_user_data(&mut self, data: Rc<OutputState>) {
        (*self.output).data = Rc::into_raw(data) as *mut _
    }

    pub unsafe fn user_data(&mut self) -> *mut OutputState {
        (*self.output).data as *mut _
    }

    // TODO Prove all of this is sound, including user_data
    pub unsafe fn layout(&mut self) -> Option<Rc<RefCell<OutputLayout>>> {
        let data = self.user_data();
        if data.is_null() {
            None
        } else {
            (*data).layout.clone()
        }
    }

    pub fn add_layout_auto(&mut self, layout: Rc<RefCell<OutputLayout>>) {
        unsafe {
            wlr_output_layout_add_auto(layout.borrow_mut().to_ptr(), self.output);
            let user_data = self.user_data();
            if user_data.is_null() {
                self.set_user_data(Rc::new(OutputState {
                    layout: Some(layout)
                }));
            } else {
                (*user_data).layout = Some(layout);
            }
        }
    }

    pub fn set_cursor<'cursor>(&mut self, image: &'cursor XCursorImage<'cursor>) -> Result<(), ()> {
        unsafe {
            match wlr_output_set_cursor(self.output,
                                        image.buffer.as_ptr(),
                                        image.width as i32,
                                        image.width,
                                        image.height,
                                        image.hotspot_x as i32,
                                        image.hotspot_y as i32)
            {
                true => Ok(()),
                false => Err(())
            }
        }
    }

    /// Sets the best modesetting for an output.
    pub fn choose_best_mode(&mut self) {
        unsafe {
            let length = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_list_length, self.modes() as _);
            if length > 0 {
                // TODO Better logging
                wlr_log!(L_DEBUG, "output added {:?}", self);
                let first_mode_ptr: *mut wlr_output_mode;
                first_mode_ptr = container_of!(&mut (*(*self.modes()).prev) as *mut _,
                                               wlr_output_mode,
                                               link);
                wlr_output_set_mode(self.to_ptr(), first_mode_ptr);
            }
        }
    }

    /// Gets the name of the output in UTF-8.
    pub fn name(&self) -> String {
        unsafe {
            CStr::from_ptr((*self.output).name.as_ptr())
                .to_string_lossy()
                .into_owned()
        }
    }

    /// Gets the make of the output in UTF-8.
    pub fn make(&self) -> String {
        unsafe {
            CStr::from_ptr((*self.output).make.as_ptr())
                .to_string_lossy()
                .into_owned()
        }
    }

    /// Gets the model of the output in UTF-8.
    pub fn model(&self) -> String {
        unsafe {
            CStr::from_ptr((*self.output).model.as_ptr())
                .to_string_lossy()
                .into_owned()
        }
    }

    pub fn make_current(&mut self) {
        unsafe { wlr_output_make_current(self.output) }
    }

    pub fn swap_buffers(&mut self) {
        unsafe { wlr_output_swap_buffers(self.output) }
    }

    /// Get the dimensions of the output as (width, height).
    pub fn dimensions(&self) -> (i32, i32) {
        unsafe { ((*self.output).width, (*self.output).height) }
    }

    /// Get the physical dimensions of the output as (width, height).
    pub fn physical_dimensions(&self) -> (i32, i32) {
        unsafe { ((*self.output).phys_width, (*self.output).phys_height) }
    }

    // TODO Wrap this somehow? Hmm
    pub unsafe fn modes(&self) -> *mut wl_list {
        &mut (*self.output).modes
    }

    pub unsafe fn events(&self) -> wlr_output_events {
        (*self.output).events
    }

    pub unsafe fn from_ptr(output: *mut wlr_output) -> Self {
        Output { output }
    }

    pub unsafe fn to_ptr(&self) -> *mut wlr_output {
        self.output
    }
}

impl Drop for Output {
    fn drop(&mut self) {
        // TODO Implement
        // Also need to make sure it's not dropped except in the remove callback,
        // since right now there's actually a lot of Output destruction which we don't want
        // e.g need to make the from_ptr return ManuallyDrop<Output> now
    }
}

impl OutputLayout {
    pub fn new() -> Self {
        unsafe {
            OutputLayout {
                layout: wlr_output_layout_create()
            }
        }
    }

    pub unsafe fn to_ptr(&self) -> *mut wlr_output_layout {
        self.layout
    }

    pub unsafe fn from_ptr(layout: *mut wlr_output_layout) -> Self {
        OutputLayout { layout }
    }

    /// # Unsafety
    /// The underlying function hasn't been proven to be stable if you
    /// pass it an invalid Output (e.g one that has already been freed).
    /// For now, this function is unsafe
    pub unsafe fn remove(&mut self, output: &mut Output) {
        // TODO Double check we can pass any output in here and not cause unsafety
        unsafe { wlr_output_layout_remove(self.layout, output.to_ptr()) }
    }
}

impl Drop for OutputLayout {
    fn drop(&mut self) {
        unsafe { wlr_output_layout_destroy(self.layout) }
    }
}
<commit_msg>Fixed TODOs, made layout safe<commit_after>

use types::cursor::XCursorImage;

use wayland_sys::server::WAYLAND_SERVER_HANDLE;
use wlroots_sys::{wl_list, wlr_output, wlr_output_events, wlr_output_layout,
                  wlr_output_layout_add_auto, wlr_output_layout_create, wlr_output_layout_destroy,
                  wlr_output_layout_remove, wlr_output_make_current, wlr_output_mode,
                  wlr_output_set_cursor, wlr_output_set_mode, wlr_output_swap_buffers};

use std::cell::RefCell;
use std::ffi::CStr;
use std::rc::Rc;

pub struct OutputState {
    pub layout: Option<Rc<RefCell<OutputLayout>>>
}

/// A wrapper around a wlr_output.
#[derive(Debug)]
pub struct Output {
    output: *mut wlr_output
}

#[derive(Debug)]
pub struct OutputLayout {
    layout: *mut wlr_output_layout
}

impl Output {
    pub unsafe fn set_user_data(&mut self, data: Rc<OutputState>) {
        (*self.output).data = Rc::into_raw(data) as *mut _
    }

    pub unsafe fn user_data(&mut self) -> *mut OutputState {
        (*self.output).data as *mut _
    }

    pub fn layout(&mut self) -> Option<Rc<RefCell<OutputLayout>>> {
        unsafe {
            let data = self.user_data();
            if data.is_null() {
                None
            } else {
                (*data).layout.clone()
            }
        }
    }

    pub fn add_layout_auto(&mut self, layout: Rc<RefCell<OutputLayout>>) {
        unsafe {
            wlr_output_layout_add_auto(layout.borrow_mut().to_ptr(), self.output);
            let user_data = self.user_data();
            if user_data.is_null() {
                self.set_user_data(Rc::new(OutputState {
                    layout: Some(layout)
                }));
            } else {
                (*user_data).layout = Some(layout);
            }
        }
    }

    pub fn set_cursor<'cursor>(&mut self, image: &'cursor XCursorImage<'cursor>) -> Result<(), ()> {
        unsafe {
            match wlr_output_set_cursor(self.output,
                                        image.buffer.as_ptr(),
                                        image.width as i32,
                                        image.width,
                                        image.height,
                                        image.hotspot_x as i32,
                                        image.hotspot_y as i32)
            {
                true => Ok(()),
                false => Err(())
            }
        }
    }

    /// Sets the best modesetting for an output.
    pub fn choose_best_mode(&mut self) {
        unsafe {
            let length = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_list_length, self.modes() as _);
            if length > 0 {
                // TODO Better logging
                wlr_log!(L_DEBUG, "output added {:?}", self);
                let first_mode_ptr: *mut wlr_output_mode;
                first_mode_ptr = container_of!(&mut (*(*self.modes()).prev) as *mut _,
                                               wlr_output_mode,
                                               link);
                wlr_output_set_mode(self.to_ptr(), first_mode_ptr);
            }
        }
    }

    /// Gets the name of the output in UTF-8.
    pub fn name(&self) -> String {
        unsafe {
            CStr::from_ptr((*self.output).name.as_ptr())
                .to_string_lossy()
                .into_owned()
        }
    }

    /// Gets the make of the output in UTF-8.
    pub fn make(&self) -> String {
        unsafe {
            CStr::from_ptr((*self.output).make.as_ptr())
                .to_string_lossy()
                .into_owned()
        }
    }

    /// Gets the model of the output in UTF-8.
    pub fn model(&self) -> String {
        unsafe {
            CStr::from_ptr((*self.output).model.as_ptr())
                .to_string_lossy()
                .into_owned()
        }
    }

    pub fn make_current(&mut self) {
        unsafe { wlr_output_make_current(self.output) }
    }

    pub fn swap_buffers(&mut self) {
        unsafe { wlr_output_swap_buffers(self.output) }
    }

    /// Get the dimensions of the output as (width, height).
    pub fn dimensions(&self) -> (i32, i32) {
        unsafe { ((*self.output).width, (*self.output).height) }
    }

    /// Get the physical dimensions of the output as (width, height).
    pub fn physical_dimensions(&self) -> (i32, i32) {
        unsafe { ((*self.output).phys_width, (*self.output).phys_height) }
    }

    // TODO Wrap this somehow? Hmm
    pub unsafe fn modes(&self) -> *mut wl_list {
        &mut (*self.output).modes
    }

    pub unsafe fn events(&self) -> wlr_output_events {
        (*self.output).events
    }

    pub unsafe fn from_ptr(output: *mut wlr_output) -> Self {
        Output { output }
    }

    pub unsafe fn to_ptr(&self) -> *mut wlr_output {
        self.output
    }
}

impl Drop for Output {
    fn drop(&mut self) {
        // TODO Implement
        // Also need to make sure it's not dropped except in the remove callback,
        // since right now there's actually a lot of Output destruction which we don't want
        // e.g need to make the from_ptr return ManuallyDrop<Output> now
    }
}

impl OutputLayout {
    pub fn new() -> Self {
        unsafe {
            OutputLayout {
                layout: wlr_output_layout_create()
            }
        }
    }

    pub unsafe fn to_ptr(&self) -> *mut wlr_output_layout {
        self.layout
    }

    pub unsafe fn from_ptr(layout: *mut wlr_output_layout) -> Self {
        OutputLayout { layout }
    }

    /// # Unsafety
    /// The underlying function hasn't been proven to be stable if you
    /// pass it an invalid Output (e.g one that has already been freed).
    /// For now, this function is unsafe
    pub unsafe fn remove(&mut self, output: &mut Output) {
        wlr_output_layout_remove(self.layout, output.to_ptr())
    }
}

impl Drop for OutputLayout {
    fn drop(&mut self) {
        unsafe { wlr_output_layout_destroy(self.layout) }
    }
}
<|endoftext|>


<commit_before><commit_msg>Add benchmarks for uniform usize samples<commit_after><|endoftext|>