<commit_before>use std::collections::HashMap;
use std::str::FromStr;

use hyper::Uri;

use client::{self, ApiClient};

static DATASTORE_ROOT: &str = "https://datastore.googleapis.com/v1";

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

pub type ValueMap = HashMap<String, Value>;

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct BeginTransactionRequest {}

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

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RollbackTransactionRequest {
    pub transaction: String,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RollbackTransactionResponse {}

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

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

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

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct CommitResponse {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub mutation_results: Option<Vec<MutationResult>>,

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

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
struct RunQueryRequest {
    partition_id: PartitionId,
    read_options: ReadOptions,

    #[serde(skip_serializing_if = "Option::is_none")]
    gql_query: Option<GqlQuery>,
}

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
struct GqlQuery {
    query_string: String,
    allow_literals: bool,
    named_bindings: HashMap<String, GqlQueryParameter>,
}

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
struct GqlQueryParameter {
    value: Value,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RunQueryResponse {
    pub batch: QueryResultBatch,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct QueryResultBatch {
    pub entity_results: Option<Vec<EntityResult>>,
}

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

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

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

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

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

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

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

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

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct LookupRequest {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub keys: Option<Vec<Key>>,

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

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct LookupResponse {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub found: Option<Vec<EntityResult>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub missing: Option<Vec<EntityResult>>,

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

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

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

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

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

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

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

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

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Key {
    pub path: Vec<PathElement>,

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    //#[serde(rename="geoPointValue")]
    //#[serde(skip_serializing_if = "Option::is_none")]
    //pub geo_point_value: Option<LatLng>,

    //#[serde(rename="arrayValue")]
    //#[serde(skip_serializing_if = "Option::is_none")]
    //pub array_value: Option<ArrayValue>,
}

impl<'a> Hub<'a> {
    //
    // api-level operations

    pub fn begin_transaction(&self) -> client::Result<String> {
        let uri = self.mk_uri("beginTransaction");
        let req = BeginTransactionRequest::default();
        self.post::<_, BeginTransactionResponse>(&uri, req, &[])
            .map(|r| r.transaction)
    }

    pub fn rollback(&self, txn: &str) -> client::Result<()> {
        let uri = self.mk_uri("rollback");
        let req = RollbackTransactionRequest { transaction: txn.to_string() };
        self.post::<_, RollbackTransactionResponse>(&uri, req, &[])
            .map(|_| ())
    }

    pub fn commit(&self, req: CommitRequest) -> client::Result<CommitResponse> {
        debug_assert!(!req.transaction.is_empty());
        let uri = self.mk_uri("commit");
        self.post(&uri, req, &[])
    }

    //
    // high-level operations

    pub fn insert_entity_auto_id(
        &self,
        kind: &str,
        ns: &str,
        ancestors: Vec<PathElement>,
        props: ValueMap,
    ) -> client::Result<String> {
        let key = self.mk_key(kind, Some(ns), ancestors, None, None);
        let res = self.insert(key, props)?;
        let mut results = res.mutation_results.expect("mutations to be valid");

        let mut key = results.remove(0).key.expect("key to be valid");
        Ok(key.path.pop().expect("path to be non-empty").id.expect(
            "id to be valid",
        ))
    }

    pub fn insert_entity_by_name(
        &self,
        kind: &str,
        ns: &str,
        ancestors: Vec<PathElement>,
        name: &str,
        props: ValueMap,
    ) -> client::Result<()> {
        let key = self.mk_key(kind, Some(ns), ancestors, Some(name), None);
        self.insert(key, props)?;
        Ok(())
    }

    fn insert(&self, key: Key, props: ValueMap) -> client::Result<CommitResponse> {
        let entity = Entity {
            key: Some(key),
            properties: Some(props),
        };

        let insert = Mutation {
            insert: Some(entity),
            ..Default::default()
        };

        let req = CommitRequest {
            transaction: self.begin_transaction()?,
            mutations: Some(vec![insert]),
            ..Default::default()
        };

        self.commit(req)
    }

    pub fn lookup_by_id(
        &self,
        kind: &str,
        ns: &str,
        ancestors: Vec<PathElement>,
        id: &str,
        txn: Option<&str>,
    ) -> client::Result<Option<ValueMap>> {
        let key = self.mk_key(kind, Some(ns), ancestors, None, Some(id));
        self.lookup_one(key, txn)
    }

    pub fn lookup_by_name(
        &self,
        kind: &str,
        ns: &str,
        ancestors: Vec<PathElement>,
        name: &str,
        txn: Option<&str>,
    ) -> client::Result<Option<ValueMap>> {
        let key = self.mk_key(kind, Some(ns), ancestors, Some(name), None);
        self.lookup_one(key, txn)
    }

    pub fn gql<B>(
        &self,
        ns: &str,
        q: &str,
        txn: Option<&str>,
        bindings: B,
    ) -> client::Result<RunQueryResponse>
    where
        B: IntoIterator<Item = (String, Value)>,
    {
        let query = GqlQuery {
            query_string: q.to_string(),
            allow_literals: false,
            named_bindings: bindings
                .into_iter()
                .map(|(k, v)| (k, GqlQueryParameter { value: v }))
                .collect(),
        };

        let req = RunQueryRequest {
            partition_id: PartitionId {
                project_id: self.project_id().to_string(),
                namespace_id: Some(ns.to_string()),
            },
            read_options: ReadOptions {
                transaction: txn.map(|t| t.to_string()),
                ..Default::default()
            },
            gql_query: Some(query),
        };

        let uri = self.mk_uri("runQuery");
        self.post::<_, RunQueryResponse>(&uri, req, &[])
    }

    // Lookup a key using default read options:
    // https://cloud.google.com/datastore/docs/reference/rest/v1/ReadOptions
    fn lookup_one(&self, key: Key, txn: Option<&str>) -> client::Result<Option<ValueMap>> {
        let req = LookupRequest {
            keys: Some(vec![key]),
            read_options: Some(ReadOptions {
                transaction: txn.map(|t| t.to_string()),
                ..Default::default()
            }),
        };

        let uri = self.mk_uri("lookup");
        let res = self.post::<_, LookupResponse>(&uri, req, &[])?;

        Ok(
            res.found
                .and_then(|mut f| if f.len() != 1 {
                    None
                } else {
                    f.remove(0).entity
                })
                .and_then(|e| e.properties),
        )
    }

    pub fn update_by_id(
        &self,
        kind: &str,
        ns: &str,
        ancestors: Vec<PathElement>,
        id: &str,
        props: ValueMap,
    ) -> client::Result<()> {
        let key = self.mk_key(kind, Some(ns), ancestors, None, Some(id));

        let entity = Entity {
            key: Some(key),
            properties: Some(props),
        };

        let update = Mutation {
            update: Some(entity),
            ..Default::default()
        };

        let req = CommitRequest {
            transaction: self.begin_transaction()?,
            mutations: Some(vec![update]),
            ..Default::default()
        };

        self.commit(req).map(|_| ())
    }

    pub fn delete_by_id(
        &self,
        kind: &str,
        ns: &str,
        ancestors: Vec<PathElement>,
        id: &str,
    ) -> client::Result<()> {
        let key = self.mk_key(kind, Some(ns), ancestors, None, Some(id));

        let delete = Mutation {
            delete: Some(key),
            ..Default::default()
        };

        let req = CommitRequest {
            transaction: self.begin_transaction()?,
            mutations: Some(vec![delete]),
            ..Default::default()
        };

        self.commit(req).map(|_| ())
    }

    fn mk_uri(&self, action: &str) -> Uri {
        let path = format!(
            "{}/projects/{}:{}",
            DATASTORE_ROOT,
            self.project_id(),
            action
        );
        Uri::from_str(&path).expect("uri to be valid")
    }

    fn mk_key(
        &self,
        kind: &str,
        ns: Option<&str>,
        mut path: Vec<PathElement>,
        name: Option<&str>,
        id: Option<&str>,
    ) -> Key {
        let partition_id = PartitionId {
            project_id: self.project_id().to_string(),
            namespace_id: ns.map(|ns| ns.to_string()),
        };

        path.push(PathElement {
            kind: kind.to_string(),
            name: name.map(|name| name.to_string()),
            id: id.map(|id| id.to_string()),
        });

        Key {
            path: path,
            partition_id: Some(partition_id),
        }
    }
}
<commit_msg>add allocate_ids<commit_after>use std::collections::HashMap;
use std::str::FromStr;

use hyper::Uri;

use client::{self, ApiClient};

static DATASTORE_ROOT: &str = "https://datastore.googleapis.com/v1";

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

pub type ValueMap = HashMap<String, Value>;

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct BeginTransactionRequest {}

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

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RollbackTransactionRequest {
    pub transaction: String,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RollbackTransactionResponse {}

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct AllocateIdsRequest {
    keys: Vec<Key>,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct AllocateIdsResponse {
    keys: Vec<Key>,
}

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

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

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

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct CommitResponse {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub mutation_results: Option<Vec<MutationResult>>,

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

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
struct RunQueryRequest {
    partition_id: PartitionId,
    read_options: ReadOptions,

    #[serde(skip_serializing_if = "Option::is_none")]
    gql_query: Option<GqlQuery>,
}

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
struct GqlQuery {
    query_string: String,
    allow_literals: bool,
    named_bindings: HashMap<String, GqlQueryParameter>,
}

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
struct GqlQueryParameter {
    value: Value,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RunQueryResponse {
    pub batch: QueryResultBatch,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct QueryResultBatch {
    pub entity_results: Option<Vec<EntityResult>>,
}

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

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

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

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

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

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

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

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

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct LookupRequest {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub keys: Option<Vec<Key>>,

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

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct LookupResponse {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub found: Option<Vec<EntityResult>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub missing: Option<Vec<EntityResult>>,

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

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

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

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

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

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

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

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

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Key {
    pub path: Vec<PathElement>,

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    //#[serde(rename="geoPointValue")]
    //#[serde(skip_serializing_if = "Option::is_none")]
    //pub geo_point_value: Option<LatLng>,

    //#[serde(rename="arrayValue")]
    //#[serde(skip_serializing_if = "Option::is_none")]
    //pub array_value: Option<ArrayValue>,
}

impl<'a> Hub<'a> {
    //
    // api-level operations

    pub fn begin_transaction(&self) -> client::Result<String> {
        let uri = self.mk_uri("beginTransaction");
        let req = BeginTransactionRequest::default();
        self.post::<_, BeginTransactionResponse>(&uri, req, &[])
            .map(|r| r.transaction)
    }

    pub fn rollback(&self, txn: &str) -> client::Result<()> {
        let uri = self.mk_uri("rollback");
        let req = RollbackTransactionRequest { transaction: txn.to_string() };
        self.post::<_, RollbackTransactionResponse>(&uri, req, &[])
            .map(|_| ())
    }

    pub fn commit(&self, req: CommitRequest) -> client::Result<CommitResponse> {
        debug_assert!(!req.transaction.is_empty());
        let uri = self.mk_uri("commit");
        self.post(&uri, req, &[])
    }

    pub fn allocate_ids(&self, keys: Vec<Key>) -> client::Result<Vec<Key>> {
        let uri = self.mk_uri("allocateIds");
        let req = AllocateIdsRequest { keys: keys };
        self.post::<_, AllocateIdsResponse>(&uri, req, &[]).map(
            |r| {
                r.keys
            },
        )
    }

    //
    // high-level operations

    pub fn insert_entity_auto_id(
        &self,
        kind: &str,
        ns: &str,
        ancestors: Vec<PathElement>,
        props: ValueMap,
    ) -> client::Result<String> {
        let key = self.mk_key(kind, Some(ns), ancestors, None, None);
        let res = self.insert(key, props)?;
        let mut results = res.mutation_results.expect("mutations to be valid");

        let mut key = results.remove(0).key.expect("key to be valid");
        Ok(key.path.pop().expect("path to be non-empty").id.expect(
            "id to be valid",
        ))
    }

    pub fn insert_entity_by_name(
        &self,
        kind: &str,
        ns: &str,
        ancestors: Vec<PathElement>,
        name: &str,
        props: ValueMap,
    ) -> client::Result<()> {
        let key = self.mk_key(kind, Some(ns), ancestors, Some(name), None);
        self.insert(key, props)?;
        Ok(())
    }

    fn insert(&self, key: Key, props: ValueMap) -> client::Result<CommitResponse> {
        let entity = Entity {
            key: Some(key),
            properties: Some(props),
        };

        let insert = Mutation {
            insert: Some(entity),
            ..Default::default()
        };

        let req = CommitRequest {
            transaction: self.begin_transaction()?,
            mutations: Some(vec![insert]),
            ..Default::default()
        };

        self.commit(req)
    }

    pub fn lookup_by_id(
        &self,
        kind: &str,
        ns: &str,
        ancestors: Vec<PathElement>,
        id: &str,
        txn: Option<&str>,
    ) -> client::Result<Option<ValueMap>> {
        let key = self.mk_key(kind, Some(ns), ancestors, None, Some(id));
        self.lookup_one(key, txn)
    }

    pub fn lookup_by_name(
        &self,
        kind: &str,
        ns: &str,
        ancestors: Vec<PathElement>,
        name: &str,
        txn: Option<&str>,
    ) -> client::Result<Option<ValueMap>> {
        let key = self.mk_key(kind, Some(ns), ancestors, Some(name), None);
        self.lookup_one(key, txn)
    }

    pub fn gql<B>(
        &self,
        ns: &str,
        q: &str,
        txn: Option<&str>,
        bindings: B,
    ) -> client::Result<RunQueryResponse>
    where
        B: IntoIterator<Item = (String, Value)>,
    {
        let query = GqlQuery {
            query_string: q.to_string(),
            allow_literals: false,
            named_bindings: bindings
                .into_iter()
                .map(|(k, v)| (k, GqlQueryParameter { value: v }))
                .collect(),
        };

        let req = RunQueryRequest {
            partition_id: PartitionId {
                project_id: self.project_id().to_string(),
                namespace_id: Some(ns.to_string()),
            },
            read_options: ReadOptions {
                transaction: txn.map(|t| t.to_string()),
                ..Default::default()
            },
            gql_query: Some(query),
        };

        let uri = self.mk_uri("runQuery");
        self.post::<_, RunQueryResponse>(&uri, req, &[])
    }

    // Lookup a key using default read options:
    // https://cloud.google.com/datastore/docs/reference/rest/v1/ReadOptions
    fn lookup_one(&self, key: Key, txn: Option<&str>) -> client::Result<Option<ValueMap>> {
        let req = LookupRequest {
            keys: Some(vec![key]),
            read_options: Some(ReadOptions {
                transaction: txn.map(|t| t.to_string()),
                ..Default::default()
            }),
        };

        let uri = self.mk_uri("lookup");
        let res = self.post::<_, LookupResponse>(&uri, req, &[])?;

        Ok(
            res.found
                .and_then(|mut f| if f.len() != 1 {
                    None
                } else {
                    f.remove(0).entity
                })
                .and_then(|e| e.properties),
        )
    }

    pub fn update_by_id(
        &self,
        kind: &str,
        ns: &str,
        ancestors: Vec<PathElement>,
        id: &str,
        props: ValueMap,
    ) -> client::Result<()> {
        let key = self.mk_key(kind, Some(ns), ancestors, None, Some(id));

        let entity = Entity {
            key: Some(key),
            properties: Some(props),
        };

        let update = Mutation {
            update: Some(entity),
            ..Default::default()
        };

        let req = CommitRequest {
            transaction: self.begin_transaction()?,
            mutations: Some(vec![update]),
            ..Default::default()
        };

        self.commit(req).map(|_| ())
    }

    pub fn delete_by_id(
        &self,
        kind: &str,
        ns: &str,
        ancestors: Vec<PathElement>,
        id: &str,
    ) -> client::Result<()> {
        let key = self.mk_key(kind, Some(ns), ancestors, None, Some(id));

        let delete = Mutation {
            delete: Some(key),
            ..Default::default()
        };

        let req = CommitRequest {
            transaction: self.begin_transaction()?,
            mutations: Some(vec![delete]),
            ..Default::default()
        };

        self.commit(req).map(|_| ())
    }

    fn mk_uri(&self, action: &str) -> Uri {
        let path = format!(
            "{}/projects/{}:{}",
            DATASTORE_ROOT,
            self.project_id(),
            action
        );
        Uri::from_str(&path).expect("uri to be valid")
    }

    fn mk_key(
        &self,
        kind: &str,
        ns: Option<&str>,
        mut path: Vec<PathElement>,
        name: Option<&str>,
        id: Option<&str>,
    ) -> Key {
        let partition_id = PartitionId {
            project_id: self.project_id().to_string(),
            namespace_id: ns.map(|ns| ns.to_string()),
        };

        path.push(PathElement {
            kind: kind.to_string(),
            name: name.map(|name| name.to_string()),
            id: id.map(|id| id.to_string()),
        });

        Key {
            path: path,
            partition_id: Some(partition_id),
        }
    }
}
<|endoftext|>


<commit_before>/*
 Copyright (c) 2013, Sébastien Crozet
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

3. Neither the name of the author nor the names of its contributors may be used
   to endorse or promote products derived from this software without specific
   prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Edit Takashi Ogura <t.ogura@gmail.com>
 */

use std::f32;
use glfw::{Action, Key, MouseButton};
use glfw;
use glfw::WindowEvent;
use na::{Isometry3, Matrix4, Perspective3, Point3, Vector2, Vector3};
use na;
use kiss3d::camera::Camera;

/// Arc-ball camera mode.
///
/// An arc-ball camera is a camera rotating around a fixed point (the focus point) and always
/// looking at it. The following inputs are handled:
///
/// * Left button press + drag - rotates the camera around the focus point
/// * Right button press + drag - translates the focus point on the plane orthogonal to the view
/// direction
/// * Scroll in/out - zoom in/out
/// * Enter key - set the focus point to the origin
#[derive(Clone, Debug)]
pub struct ArcBall {
    /// The focus point.
    at: Point3<f32>,
    /// Yaw of the camera (rotation along the y axis).
    yaw: f32,
    /// Pitch of the camera (rotation along the x axis).
    pitch: f32,
    /// Distance from the camera to the `at` focus point.
    dist: f32,

    /// Increment of the yaw per unit mouse movement. The default value is 0.005.
    yaw_step: f32,
    /// Increment of the pitch per unit mouse movement. The default value is 0.005.
    pitch_step: f32,
    /// Increment of the distance per unit scrolling. The default value is 40.0.
    dist_step: f32,
    rotate_button: Option<MouseButton>,
    drag_button: Option<MouseButton>,
    reset_key: Option<Key>,

    projection: Perspective3<f32>,
    proj_view: Matrix4<f32>,
    inverse_proj_view: Matrix4<f32>,
    last_cursor_pos: Vector2<f32>,
}

impl ArcBall {
    /// Create a new arc-ball camera.
    pub fn new(eye: Point3<f32>, at: Point3<f32>) -> ArcBall {
        ArcBall::new_with_frustrum(f32::consts::PI / 4.0, 0.1, 1024.0, eye, at)
    }

    /// Creates a new arc ball camera with default sensitivity values.
    pub fn new_with_frustrum(
        fov: f32,
        znear: f32,
        zfar: f32,
        eye: Point3<f32>,
        at: Point3<f32>,
    ) -> ArcBall {
        let mut res = ArcBall {
            at: Point3::new(0.0, 0.0, 0.0),
            yaw: 0.0,
            pitch: 0.0,
            dist: 0.0,
            yaw_step: 0.005,
            pitch_step: 0.005,
            dist_step: 40.0,
            rotate_button: Some(glfw::MouseButtonLeft),
            drag_button: Some(glfw::MouseButtonRight),
            reset_key: Some(Key::Enter),
            projection: Perspective3::new(800.0 / 600.0, fov, znear, zfar),
            proj_view: na::zero(),
            inverse_proj_view: na::zero(),
            last_cursor_pos: na::zero(),
        };

        res.look_at(eye, at);

        res
    }

    /// The point the arc-ball is looking at.
    pub fn at(&self) -> Point3<f32> {
        self.at
    }

    /// Get a mutable reference to the point the camera is looking at.
    pub fn set_at(&mut self, at: Point3<f32>) {
        self.at = at;
        self.update_projviews();
    }

    /// The arc-ball camera `yaw`.
    pub fn yaw(&self) -> f32 {
        self.yaw
    }

    /// Sets the camera `yaw`. Change this to modify the rotation along the `up` axis.
    pub fn set_yaw(&mut self, yaw: f32) {
        self.yaw = yaw;

        self.update_restrictions();
        self.update_projviews();
    }

    /// The arc-ball camera `pitch`.
    pub fn pitch(&self) -> f32 {
        self.pitch
    }

    /// Sets the camera `pitch`.
    pub fn set_pitch(&mut self, pitch: f32) {
        self.pitch = pitch;

        self.update_restrictions();
        self.update_projviews();
    }

    /// The distance from the camera position to its view point.
    pub fn dist(&self) -> f32 {
        self.dist
    }

    /// Move the camera such that it is at a given distance from the view point.
    pub fn set_dist(&mut self, dist: f32) {
        self.dist = dist;

        self.update_restrictions();
        self.update_projviews();
    }

    /// Move and orient the camera such that it looks at a specific point.
    pub fn look_at(&mut self, eye: Point3<f32>, at: Point3<f32>) {
        let dist = na::norm(&(eye - at));
        let pitch = ((eye.z - at.z) / dist).acos();
        let yaw = (eye.x - at.x).atan2(eye.y - at.y);

        self.at = at;
        self.dist = dist;
        self.yaw = yaw;
        self.pitch = pitch;

        self.update_restrictions();
        self.update_projviews();
    }

    /// Transformation applied by the camera without perspective.
    fn update_restrictions(&mut self) {
        if self.dist < 0.00001 {
            self.dist = 0.00001
        }

        if self.pitch <= 0.01 {
            self.pitch = 0.01
        }

        let _pi: f32 = f32::consts::PI;
        if self.pitch > _pi - 0.01 {
            self.pitch = _pi - 0.01
        }
    }

    /// The button used to rotate the ArcBall camera.
    pub fn rotate_button(&self) -> Option<MouseButton> {
        self.rotate_button
    }

    /// Set the button used to rotate the ArcBall camera.
    /// Use None to disable rotation.
    pub fn rebind_rotate_button(&mut self, new_button: Option<MouseButton>) {
        self.rotate_button = new_button;
    }

    /// The button used to drag the ArcBall camera.
    pub fn drag_button(&self) -> Option<MouseButton> {
        self.drag_button
    }

    /// Set the button used to drag the ArcBall camera.
    /// Use None to disable dragging.
    pub fn rebind_drag_button(&mut self, new_button: Option<MouseButton>) {
        self.drag_button = new_button;
    }

    /// The key used to reset the ArcBall camera.
    pub fn reset_key(&self) -> Option<Key> {
        self.reset_key
    }

    /// Set the key used to reset the ArcBall camera.
    /// Use None to disable reset.
    pub fn rebind_reset_key(&mut self, new_key: Option<Key>) {
        self.reset_key = new_key;
    }

    fn handle_left_button_displacement(&mut self, dpos: &Vector2<f32>) {
        self.yaw = self.yaw + dpos.x * self.yaw_step;
        self.pitch = self.pitch - dpos.y * self.pitch_step;

        self.update_restrictions();
        self.update_projviews();
    }

    fn handle_right_button_displacement(&mut self, dpos: &Vector2<f32>) {
        let eye = self.eye();
        let dir = na::normalize(&(self.at - eye));
        let tangent = na::normalize(&Vector3::z().cross(&dir));
        let bitangent = dir.cross(&tangent);
        let mult = self.dist / 1000.0;

        self.at = self.at + tangent * (dpos.x * mult) + bitangent * (dpos.y * mult);
        self.update_projviews();
    }

    fn handle_scroll(&mut self, off: f32) {
        self.dist = self.dist + self.dist_step * (off) / 120.0;
        self.update_restrictions();
        self.update_projviews();
    }

    fn update_projviews(&mut self) {
        self.proj_view = *self.projection.as_matrix() * self.view_transform().to_homogeneous();
        self.inverse_proj_view = self.proj_view.try_inverse().unwrap();
    }
}

impl Camera for ArcBall {
    fn clip_planes(&self) -> (f32, f32) {
        (self.projection.znear(), self.projection.zfar())
    }

    fn view_transform(&self) -> Isometry3<f32> {
        Isometry3::look_at_rh(&self.eye(), &self.at, &Vector3::z())
    }

    fn eye(&self) -> Point3<f32> {
        let py = self.at.x + self.dist * self.yaw.cos() * self.pitch.sin();
        let pz = self.at.y + self.dist * self.pitch.cos();
        let px = self.at.z + self.dist * self.yaw.sin() * self.pitch.sin();

        Point3::new(px, py, pz)
    }

    fn handle_event(&mut self, window: &glfw::Window, event: &WindowEvent) {
        match *event {
            WindowEvent::CursorPos(x, y) => {
                let curr_pos = Vector2::new(x as f32, y as f32);

                if let Some(rotate_button) = self.rotate_button {
                    if window.get_mouse_button(rotate_button) == Action::Press {
                        let dpos = curr_pos - self.last_cursor_pos;
                        self.handle_left_button_displacement(&dpos)
                    }
                }

                if let Some(drag_button) = self.drag_button {
                    if window.get_mouse_button(drag_button) == Action::Press {
                        let dpos = curr_pos - self.last_cursor_pos;
                        self.handle_right_button_displacement(&dpos)
                    }
                }

                self.last_cursor_pos = curr_pos;
            }
            WindowEvent::Key(key, _, Action::Press, _) if Some(key) == self.reset_key => {
                self.at = Point3::origin();
                self.update_projviews();
            }
            WindowEvent::Scroll(_, off) => self.handle_scroll(off as f32),
            WindowEvent::FramebufferSize(w, h) => {
                self.projection.set_aspect(w as f32 / h as f32);
                self.update_projviews();
            }
            _ => {}
        }
    }

    fn transformation(&self) -> Matrix4<f32> {
        self.proj_view
    }

    fn inverse_transformation(&self) -> Matrix4<f32> {
        self.inverse_proj_view
    }

    fn update(&mut self, _: &glfw::Window) {}
}
<commit_msg>Fix eye position bug caused by mouse scroll<commit_after>/*
 Copyright (c) 2013, Sébastien Crozet
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

3. Neither the name of the author nor the names of its contributors may be used
   to endorse or promote products derived from this software without specific
   prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Edit Takashi Ogura <t.ogura@gmail.com>
 */

use glfw;
use glfw::WindowEvent;
use glfw::{Action, Key, MouseButton};
use kiss3d::camera::Camera;
use na;
use na::{Isometry3, Matrix4, Perspective3, Point3, Vector2, Vector3};
use std::f32;

/// Arc-ball camera mode.
///
/// An arc-ball camera is a camera rotating around a fixed point (the focus point) and always
/// looking at it. The following inputs are handled:
///
/// * Left button press + drag - rotates the camera around the focus point
/// * Right button press + drag - translates the focus point on the plane orthogonal to the view
/// direction
/// * Scroll in/out - zoom in/out
/// * Enter key - set the focus point to the origin
#[derive(Clone, Debug)]
pub struct ArcBall {
    /// The focus point.
    at: Point3<f32>,
    /// Yaw of the camera (rotation along the y axis).
    yaw: f32,
    /// Pitch of the camera (rotation along the x axis).
    pitch: f32,
    /// Distance from the camera to the `at` focus point.
    dist: f32,

    /// Increment of the yaw per unit mouse movement. The default value is 0.005.
    yaw_step: f32,
    /// Increment of the pitch per unit mouse movement. The default value is 0.005.
    pitch_step: f32,
    /// Increment of the distance per unit scrolling. The default value is 40.0.
    dist_step: f32,
    rotate_button: Option<MouseButton>,
    drag_button: Option<MouseButton>,
    reset_key: Option<Key>,

    projection: Perspective3<f32>,
    proj_view: Matrix4<f32>,
    inverse_proj_view: Matrix4<f32>,
    last_cursor_pos: Vector2<f32>,
}

impl ArcBall {
    /// Create a new arc-ball camera.
    pub fn new(eye: Point3<f32>, at: Point3<f32>) -> ArcBall {
        ArcBall::new_with_frustrum(f32::consts::PI / 4.0, 0.1, 1024.0, eye, at)
    }

    /// Creates a new arc ball camera with default sensitivity values.
    pub fn new_with_frustrum(
        fov: f32,
        znear: f32,
        zfar: f32,
        eye: Point3<f32>,
        at: Point3<f32>,
    ) -> ArcBall {
        let mut res = ArcBall {
            at: Point3::new(0.0, 0.0, 0.0),
            yaw: 0.0,
            pitch: 0.0,
            dist: 0.0,
            yaw_step: 0.005,
            pitch_step: 0.005,
            dist_step: 40.0,
            rotate_button: Some(glfw::MouseButtonLeft),
            drag_button: Some(glfw::MouseButtonRight),
            reset_key: Some(Key::Enter),
            projection: Perspective3::new(800.0 / 600.0, fov, znear, zfar),
            proj_view: na::zero(),
            inverse_proj_view: na::zero(),
            last_cursor_pos: na::zero(),
        };

        res.look_at(eye, at);

        res
    }

    /// The point the arc-ball is looking at.
    pub fn at(&self) -> Point3<f32> {
        self.at
    }

    /// Get a mutable reference to the point the camera is looking at.
    pub fn set_at(&mut self, at: Point3<f32>) {
        self.at = at;
        self.update_projviews();
    }

    /// The arc-ball camera `yaw`.
    pub fn yaw(&self) -> f32 {
        self.yaw
    }

    /// Sets the camera `yaw`. Change this to modify the rotation along the `up` axis.
    pub fn set_yaw(&mut self, yaw: f32) {
        self.yaw = yaw;

        self.update_restrictions();
        self.update_projviews();
    }

    /// The arc-ball camera `pitch`.
    pub fn pitch(&self) -> f32 {
        self.pitch
    }

    /// Sets the camera `pitch`.
    pub fn set_pitch(&mut self, pitch: f32) {
        self.pitch = pitch;

        self.update_restrictions();
        self.update_projviews();
    }

    /// The distance from the camera position to its view point.
    pub fn dist(&self) -> f32 {
        self.dist
    }

    /// Move the camera such that it is at a given distance from the view point.
    pub fn set_dist(&mut self, dist: f32) {
        self.dist = dist;

        self.update_restrictions();
        self.update_projviews();
    }

    /// Move and orient the camera such that it looks at a specific point.
    pub fn look_at(&mut self, eye: Point3<f32>, at: Point3<f32>) {
        let dist = na::norm(&(eye - at));
        let pitch = ((eye.z - at.z) / dist).acos();
        let yaw = (eye.y - at.y).atan2(eye.x - at.x);

        self.at = at;
        self.dist = dist;
        self.yaw = yaw;
        self.pitch = pitch;

        self.update_restrictions();
        self.update_projviews();
    }

    /// Transformation applied by the camera without perspective.
    fn update_restrictions(&mut self) {
        if self.dist < 0.00001 {
            self.dist = 0.00001
        }

        if self.pitch <= 0.01 {
            self.pitch = 0.01
        }

        let _pi: f32 = f32::consts::PI;
        if self.pitch > _pi - 0.01 {
            self.pitch = _pi - 0.01
        }
    }

    /// The button used to rotate the ArcBall camera.
    pub fn rotate_button(&self) -> Option<MouseButton> {
        self.rotate_button
    }

    /// Set the button used to rotate the ArcBall camera.
    /// Use None to disable rotation.
    pub fn rebind_rotate_button(&mut self, new_button: Option<MouseButton>) {
        self.rotate_button = new_button;
    }

    /// The button used to drag the ArcBall camera.
    pub fn drag_button(&self) -> Option<MouseButton> {
        self.drag_button
    }

    /// Set the button used to drag the ArcBall camera.
    /// Use None to disable dragging.
    pub fn rebind_drag_button(&mut self, new_button: Option<MouseButton>) {
        self.drag_button = new_button;
    }

    /// The key used to reset the ArcBall camera.
    pub fn reset_key(&self) -> Option<Key> {
        self.reset_key
    }

    /// Set the key used to reset the ArcBall camera.
    /// Use None to disable reset.
    pub fn rebind_reset_key(&mut self, new_key: Option<Key>) {
        self.reset_key = new_key;
    }

    fn handle_left_button_displacement(&mut self, dpos: &Vector2<f32>) {
        self.yaw = self.yaw - dpos.x * self.yaw_step;
        self.pitch = self.pitch - dpos.y * self.pitch_step;

        self.update_restrictions();
        self.update_projviews();
    }

    fn handle_right_button_displacement(&mut self, dpos: &Vector2<f32>) {
        let eye = self.eye();
        let dir = na::normalize(&(self.at - eye));
        let tangent = na::normalize(&Vector3::z().cross(&dir));
        let bitangent = dir.cross(&tangent);
        let mult = self.dist / 1000.0;

        self.at = self.at + tangent * (dpos.x * mult) + bitangent * (dpos.y * mult);
        self.update_projviews();
    }

    fn handle_scroll(&mut self, off: f32) {
        self.dist = self.dist + self.dist_step * (off) / 120.0;
        self.update_restrictions();
        self.update_projviews();
    }

    fn update_projviews(&mut self) {
        self.proj_view = *self.projection.as_matrix() * self.view_transform().to_homogeneous();
        self.inverse_proj_view = self.proj_view.try_inverse().unwrap();
    }
}

impl Camera for ArcBall {
    fn clip_planes(&self) -> (f32, f32) {
        (self.projection.znear(), self.projection.zfar())
    }

    fn view_transform(&self) -> Isometry3<f32> {
        Isometry3::look_at_rh(&self.eye(), &self.at, &Vector3::z())
    }

    fn eye(&self) -> Point3<f32> {
        let px = self.at.x + self.dist * self.yaw.cos() * self.pitch.sin();
        let py = self.at.y + self.dist * self.yaw.sin() * self.pitch.sin();
        let pz = self.at.z + self.dist * self.pitch.cos();

        Point3::new(px, py, pz)
    }

    fn handle_event(&mut self, window: &glfw::Window, event: &WindowEvent) {
        match *event {
            WindowEvent::CursorPos(x, y) => {
                let curr_pos = Vector2::new(x as f32, y as f32);

                if let Some(rotate_button) = self.rotate_button {
                    if window.get_mouse_button(rotate_button) == Action::Press {
                        let dpos = curr_pos - self.last_cursor_pos;
                        self.handle_left_button_displacement(&dpos)
                    }
                }

                if let Some(drag_button) = self.drag_button {
                    if window.get_mouse_button(drag_button) == Action::Press {
                        let dpos = curr_pos - self.last_cursor_pos;
                        self.handle_right_button_displacement(&dpos)
                    }
                }

                self.last_cursor_pos = curr_pos;
            }
            WindowEvent::Key(key, _, Action::Press, _) if Some(key) == self.reset_key => {
                self.at = Point3::origin();
                self.update_projviews();
            }
            WindowEvent::Scroll(_, off) => self.handle_scroll(off as f32),
            WindowEvent::FramebufferSize(w, h) => {
                self.projection.set_aspect(w as f32 / h as f32);
                self.update_projviews();
            }
            _ => {}
        }
    }

    fn transformation(&self) -> Matrix4<f32> {
        self.proj_view
    }

    fn inverse_transformation(&self) -> Matrix4<f32> {
        self.inverse_proj_view
    }

    fn update(&mut self, _: &glfw::Window) {}
}
<|endoftext|>


<commit_before>extern crate examples;
extern crate spirv_cross;
use spirv_cross::{msl, spirv};
use examples::words_from_bytes;

fn main() {
    let module = spirv::Module::from_words(words_from_bytes(include_bytes!("../vertex.spv")));

    // Parse a SPIR-V module
    let mut ast = spirv::Ast::<msl::Target>::parse(&module).unwrap();

    let mut compiler_options = msl::CompilerOptions::default();

    // Set some overrides
    compiler_options.resource_binding_overrides.insert(
        msl::ResourceBindingLocation {
            stage: spirv::ExecutionModel::Vertex,
            desc_set: 0,
            binding: 0,
        },
        msl::ResourceBinding {
            buffer_id: 5,
            texture_id: 6,
            sampler_id: 7,
            force_used: false,
        },
    );

    compiler_options.vertex_attribute_overrides.insert(
        msl::VertexAttributeLocation(1),
        msl::VertexAttribute {
            buffer_id: 1,
            offset: 2,
            stride: 3,
            step: spirv::VertexAttributeStep::Instance,
            force_used: true,
        },
    );

    ast.set_compiler_options(&compiler_options).unwrap();

    // List all entry points
    for entry_point in &ast.get_entry_points().unwrap() {
        println!("{:?}", entry_point);
    }

    // Compile to MSL
    let shader = ast.compile().unwrap();
    println!("{}", shader);
}
<commit_msg>Update MSL example<commit_after>extern crate examples;
extern crate spirv_cross;
use spirv_cross::{msl, spirv};
use examples::words_from_bytes;

fn main() {
    let module = spirv::Module::from_words(words_from_bytes(include_bytes!("../vertex.spv")));

    // Parse a SPIR-V module
    let mut ast = spirv::Ast::<msl::Target>::parse(&module).unwrap();

    let mut compiler_options = msl::CompilerOptions::default();

    // Set some overrides
    compiler_options.resource_binding_overrides.insert(
        msl::ResourceBindingLocation {
            stage: spirv::ExecutionModel::Vertex,
            desc_set: 0,
            binding: 0,
        },
        msl::ResourceBinding {
            buffer_id: 5,
            texture_id: 6,
            sampler_id: 7,
            force_used: false,
        },
    );

    compiler_options.vertex_attribute_overrides.insert(
        msl::VertexAttributeLocation(1),
        msl::VertexAttribute {
            buffer_id: 1,
            offset: 2,
            stride: 3,
            step: spirv::VertexAttributeStep::Instance,
            force_used: true,
            format: msl::Format::Other,
        },
    );

    ast.set_compiler_options(&compiler_options).unwrap();

    // List all entry points
    for entry_point in &ast.get_entry_points().unwrap() {
        println!("{:?}", entry_point);
    }

    // Compile to MSL
    let shader = ast.compile().unwrap();
    println!("{}", shader);
}
<|endoftext|>


<commit_before>//! Implementation of a simple uTP client and server.

extern crate utp;
use std::io::net::ip::{Ipv4Addr, SocketAddr};

fn usage() {
    println!("Usage: utp [-s|-c] <address> <port>");
}

fn main() {
    use utp::UtpStream;
    use std::from_str::FromStr;
    use std::io::{stdin, stdout};

    // Defaults
    let mut addr = SocketAddr { ip: Ipv4Addr(127,0,0,1), port: 8080 };

    let args = std::os::args();

    if args.len() != 2 && args.len() != 4 {
        usage();
        return;
    }

    if args.len() == 4 {
        addr = SocketAddr {
            ip:   FromStr::from_str(args[2].as_slice()).unwrap(),
            port: FromStr::from_str(args[3].as_slice()).unwrap(),
        };
    }

    match args[1].as_slice() {
        "-s" => {
            let mut stream = UtpStream::bind(addr);
            let mut writer = stdout();
            println!("Serving on {}", addr);

            let payload = match stream.read_to_end() {
                Ok(v) => v,
                Err(e) => fail!("{}", e),
            };

            match writer.write(payload.as_slice()) {
                Ok(_) => {},
                Err(e) => fail!("{}", e),
            }
        }
        "-c" => {
            let mut stream = UtpStream::connect(addr);
            let mut reader = stdin();

            let payload = match reader.read_to_end() {
                Ok(v) => v,
                Err(e) => fail!("{}", e),
            };

            match stream.write(payload.as_slice()) {
                Ok(_) => {},
                Err(e) => fail!("{}", e),
            };

            match stream.close() {
                Ok(_) => {},
                Err(e) => fail!("{}", e),
            }
            drop(stream);
        }
        _ => usage(),
    }
}
<commit_msg>Write debug information to stderr.<commit_after>//! Implementation of a simple uTP client and server.

extern crate utp;
use std::io::net::ip::{Ipv4Addr, SocketAddr};

fn usage() {
    println!("Usage: utp [-s|-c] <address> <port>");
}

fn main() {
    use utp::UtpStream;
    use std::from_str::FromStr;
    use std::io::{stdin, stdout, stderr};

    // Defaults
    let mut addr = SocketAddr { ip: Ipv4Addr(127,0,0,1), port: 8080 };

    let args = std::os::args();

    if args.len() != 2 && args.len() != 4 {
        usage();
        return;
    }

    if args.len() == 4 {
        addr = SocketAddr {
            ip:   FromStr::from_str(args[2].as_slice()).unwrap(),
            port: FromStr::from_str(args[3].as_slice()).unwrap(),
        };
    }

    match args[1].as_slice() {
        "-s" => {
            let mut stream = UtpStream::bind(addr);
            let mut writer = stdout();
            let _ = writeln!(stderr(), "Serving on {}", addr);

            let payload = match stream.read_to_end() {
                Ok(v) => v,
                Err(e) => fail!("{}", e),
            };

            match writer.write(payload.as_slice()) {
                Ok(_) => {},
                Err(e) => fail!("{}", e),
            }
        }
        "-c" => {
            let mut stream = UtpStream::connect(addr);
            let mut reader = stdin();

            let payload = match reader.read_to_end() {
                Ok(v) => v,
                Err(e) => fail!("{}", e),
            };

            match stream.write(payload.as_slice()) {
                Ok(_) => {},
                Err(e) => fail!("{}", e),
            };

            match stream.close() {
                Ok(_) => {},
                Err(e) => fail!("{}", e),
            }
            drop(stream);
        }
        _ => usage(),
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]

// TODO support reading from standard input

extern crate extra;
extern crate termion;

use std::env::args;
use std::fs::File;
use std::io::{self, Write, Read, StdoutLock, Stderr};
use std::path::Path;

use extra::option::OptionalExt;

use termion::{terminal_size, TermRead, TermWrite, IntoRawMode, Color, Key, RawTerminal};

static LONG_HELP: &'static str = /* @MANSTART{less} */ r#"
NAME
    less - view a text file.

SYNOPSIS
    less [-h | --help] [input]

DESCRIPTION
    This utility views text files. If no input file is specified as an argument, standard input is
    used.

OPTIONS
    --help, -h
        Print this manual page.

AUTHOR
    This program was written by MovingtoMars for Redox OS. Bugs, issues, or feature requests should
    be reported in the Github repository, 'redox-os/extrautils'.

COPYRIGHT
    Copyright (c) 2016 MovingtoMars

    Permission is hereby granted, free of charge, to any person obtaining a copy of this software
    and associated documentation files (the "Software"), to deal in the Software without
    restriction, including without limitation the rights to use, copy, modify, merge, publish,
    distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all copies or
    substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
    BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
    DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"#; /* @MANEND */

fn main() {
    let mut args = args().skip(1);
    let stdout = io::stdout();
    let mut stdout = stdout.lock();
    let stdin = io::stdin();
    let mut stdin = stdin.lock();
    let mut stderr = io::stderr();

    if let Some(x) = args.next() {
        match x.as_str() {
            "--help" | "-h" => {
                // Print help.
                stdout.write(LONG_HELP.as_bytes()).try(&mut stderr);
                return;
            },
            filename => {
                let mut file = File::open(Path::new(filename)).try(&mut stderr);
                run(filename, &mut file, &mut stdin, &mut stdout, &mut stderr);
            }
        }

        if let Some(x) = args.next() {
            let mut file = File::open(Path::new(x.as_str())).try(&mut stderr);
            run(x.as_str(), &mut file, &mut stdin, &mut stdout, &mut stderr);
        }
    } else {
        writeln!(stderr, "Readin from stdin is not yet supported").try(&mut stderr);
        //run(&mut stdin, &mut stdin, &mut stdout, &mut stderr);
    };
}

struct Buffer {
    lines: Vec<String>,
    y_off: u16,
}

impl Buffer {
    fn new() -> Buffer {
        Buffer{
            lines: Vec::new(),
            y_off: 0,
        }
    }

    fn read(&mut self, from: &mut Read) -> std::io::Result<usize> {
        let mut tmp = String::new();
        let res = from.read_to_string(&mut tmp);
        try!(res);

        self.lines.append(&mut tmp
            .as_str()
            .split("\n")
            .map(|x| {String::from(x)})
            .collect());

        return res;
    }

    fn draw(&self, to: &mut RawTerminal<&mut StdoutLock>, w: u16, h: u16) -> std::io::Result<usize> {
        try!(to.goto(0, 0));

        let mut y = 0;
        let mut bytes_written = 0;

        let lines = if self.lines.len() <= h as usize {
            &self.lines
        } else if self.y_off as usize >= self.lines.len() {
            &self.lines[0..0]
        } else {
            &self.lines[self.y_off as usize..]
        };

        for line in lines {
            if line.len() > w as usize {
                bytes_written += try!(to.write(line[..w as usize].as_bytes()));
            } else {
                bytes_written += try!(to.write(line.as_bytes()));
            }

            y += 1;
            try!(to.goto(0, y));
            if y >= h {
                break;
            }
        }

        Ok(bytes_written)
    }

    fn scroll_up(&mut self) {
        if self.y_off > 0 {
            self.y_off -= 1;
        }
    }

    fn scroll_down(&mut self, height: u16) {
        if ((self.y_off + height) as usize) <= self.lines.len() {
            self.y_off += 1;
        }
    }
}

fn run(path: &str, file: &mut Read, controls: &mut Read, stdout: &mut StdoutLock, stderr: &mut Stderr) {
    let mut stdout = stdout.into_raw_mode().try(stderr);

    let (w, h) = {
        let (w, h) = terminal_size().try(stderr);
        (w as u16, h as u16)
    };

    stdout.clear().try(stderr);
    stdout.reset().try(stderr);

    let mut buffer = Buffer::new();
    buffer.read(file).try(stderr);

    buffer.draw(&mut stdout, w, h - 1).try(stderr);
    stdout.goto(0, h - 1).try(stderr);
    stdout.bg_color(Color::White).try(stderr);
    stdout.color(Color::Black).try(stderr);
    stdout.write(path.as_bytes()).try(stderr);
    stdout.write(b" Press q to exit.").try(stderr);
    stdout.reset().try(stderr);
    stdout.flush().try(stderr);

    for c in controls.keys() {
        match c {
            Key::Char('q') => {
                stdout.clear().try(stderr);
                stdout.reset().try(stderr);
                stdout.goto(0, 0).try(stderr);
                return
            },
            Key::Char('b') => for _i in 1..h {
                buffer.scroll_up()
            },
            Key::Char(' ') => for _i in 1..h {
                buffer.scroll_down(h)
            },
            Key::Up | Key::Char('k') => buffer.scroll_up(),
            Key::Down | Key::Char('j') => buffer.scroll_down(h),
            _ => {},
        }

        stdout.clear().try(stderr);
        stdout.reset().try(stderr);
        buffer.draw(&mut stdout, w, h - 1).try(stderr);
        stdout.goto(0, h - 1).try(stderr);
        stdout.bg_color(Color::White).try(stderr);
        stdout.color(Color::Black).try(stderr);
        stdout.write(path.as_bytes()).try(stderr);
        stdout.write(b" Press q to exit.").try(stderr);
        stdout.reset().try(stderr);
        stdout.flush().try(stderr);
    }
}
<commit_msg>Update for new termion<commit_after>#![deny(warnings)]

// TODO support reading from standard input

extern crate extra;
extern crate termion;

use std::env::args;
use std::fs::File;
use std::io::{self, Write, Read, StdoutLock, Stderr};
use std::path::Path;

use extra::option::OptionalExt;

use termion::{terminal_size, TermRead, TermWrite, IntoRawMode, Color, Key, RawTerminal};

static LONG_HELP: &'static str = /* @MANSTART{less} */ r#"
NAME
    less - view a text file.

SYNOPSIS
    less [-h | --help] [input]

DESCRIPTION
    This utility views text files. If no input file is specified as an argument, standard input is
    used.

OPTIONS
    --help, -h
        Print this manual page.

AUTHOR
    This program was written by MovingtoMars for Redox OS. Bugs, issues, or feature requests should
    be reported in the Github repository, 'redox-os/extrautils'.

COPYRIGHT
    Copyright (c) 2016 MovingtoMars

    Permission is hereby granted, free of charge, to any person obtaining a copy of this software
    and associated documentation files (the "Software"), to deal in the Software without
    restriction, including without limitation the rights to use, copy, modify, merge, publish,
    distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all copies or
    substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
    BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
    DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"#; /* @MANEND */

fn main() {
    let mut args = args().skip(1);
    let stdout = io::stdout();
    let mut stdout = stdout.lock();
    let stdin = io::stdin();
    let mut stdin = stdin.lock();
    let mut stderr = io::stderr();

    if let Some(x) = args.next() {
        match x.as_str() {
            "--help" | "-h" => {
                // Print help.
                stdout.write(LONG_HELP.as_bytes()).try(&mut stderr);
                return;
            },
            filename => {
                let mut file = File::open(Path::new(filename)).try(&mut stderr);
                run(filename, &mut file, &mut stdin, &mut stdout, &mut stderr);
            }
        }

        if let Some(x) = args.next() {
            let mut file = File::open(Path::new(x.as_str())).try(&mut stderr);
            run(x.as_str(), &mut file, &mut stdin, &mut stdout, &mut stderr);
        }
    } else {
        writeln!(stderr, "Readin from stdin is not yet supported").try(&mut stderr);
        //run(&mut stdin, &mut stdin, &mut stdout, &mut stderr);
    };
}

struct Buffer {
    lines: Vec<String>,
    y_off: u16,
}

impl Buffer {
    fn new() -> Buffer {
        Buffer{
            lines: Vec::new(),
            y_off: 0,
        }
    }

    fn read(&mut self, from: &mut Read) -> std::io::Result<usize> {
        let mut tmp = String::new();
        let res = from.read_to_string(&mut tmp);
        try!(res);

        self.lines.append(&mut tmp
            .as_str()
            .split("\n")
            .map(|x| {String::from(x)})
            .collect());

        return res;
    }

    fn draw(&self, to: &mut RawTerminal<&mut StdoutLock>, w: u16, h: u16) -> std::io::Result<usize> {
        try!(to.goto(0, 0));

        let mut y = 0;
        let mut bytes_written = 0;

        let lines = if self.lines.len() <= h as usize {
            &self.lines
        } else if self.y_off as usize >= self.lines.len() {
            &self.lines[0..0]
        } else {
            &self.lines[self.y_off as usize..]
        };

        for line in lines {
            if line.len() > w as usize {
                bytes_written += try!(to.write(line[..w as usize].as_bytes()));
            } else {
                bytes_written += try!(to.write(line.as_bytes()));
            }

            y += 1;
            try!(to.goto(0, y));
            if y >= h {
                break;
            }
        }

        Ok(bytes_written)
    }

    fn scroll_up(&mut self) {
        if self.y_off > 0 {
            self.y_off -= 1;
        }
    }

    fn scroll_down(&mut self, height: u16) {
        if ((self.y_off + height) as usize) <= self.lines.len() {
            self.y_off += 1;
        }
    }
}

fn run(path: &str, file: &mut Read, controls: &mut Read, stdout: &mut StdoutLock, stderr: &mut Stderr) {
    let mut stdout = stdout.into_raw_mode().try(stderr);

    let (w, h) = {
        let (w, h) = terminal_size().try(stderr);
        (w as u16, h as u16)
    };

    stdout.clear().try(stderr);
    stdout.reset().try(stderr);

    let mut buffer = Buffer::new();
    buffer.read(file).try(stderr);

    buffer.draw(&mut stdout, w, h - 1).try(stderr);
    stdout.goto(0, h - 1).try(stderr);
    stdout.bg_color(Color::White).try(stderr);
    stdout.color(Color::Black).try(stderr);
    stdout.write(path.as_bytes()).try(stderr);
    stdout.write(b" Press q to exit.").try(stderr);
    stdout.reset().try(stderr);
    stdout.flush().try(stderr);

    for c in controls.keys() {
        match c.unwrap() {
            Key::Char('q') => {
                stdout.clear().try(stderr);
                stdout.reset().try(stderr);
                stdout.goto(0, 0).try(stderr);
                return
            },
            Key::Char('b') => for _i in 1..h {
                buffer.scroll_up()
            },
            Key::Char(' ') => for _i in 1..h {
                buffer.scroll_down(h)
            },
            Key::Up | Key::Char('k') => buffer.scroll_up(),
            Key::Down | Key::Char('j') => buffer.scroll_down(h),
            _ => {},
        }

        stdout.clear().try(stderr);
        stdout.reset().try(stderr);
        buffer.draw(&mut stdout, w, h - 1).try(stderr);
        stdout.goto(0, h - 1).try(stderr);
        stdout.bg_color(Color::White).try(stderr);
        stdout.color(Color::Black).try(stderr);
        stdout.write(path.as_bytes()).try(stderr);
        stdout.write(b" Press q to exit.").try(stderr);
        stdout.reset().try(stderr);
        stdout.flush().try(stderr);
    }
}
<|endoftext|>


<commit_before>
extern crate mprovision;
#[macro_use(version)]
extern crate version;
extern crate chrono;
#[cfg(test)]
#[macro_use(expect)]
extern crate expectest;
extern crate clap;

use mprovision as mp;
use cli::Command;
use std::env;
use chrono::*;

mod cli;

fn main() {
    let result = cli::parse(env::args()).and_then(|command| {
        match command {
            Command::List(list_params) => Ok(()),
            Command::ShowUuid(uuid, directory) => Ok(()),
            Command::ShowPath(file_path) => Ok(()),
            Command::RemoveUuid(uuid, directory) => Ok(()),
            Command::RemovePath(file_path) => Ok(()),
            Command::Cleanup(directory) => {
                let info = mp::with_dir(directory, |dir| mp::expired_profiles(dir, UTC::now()))?;
                if info.profiles.is_empty() {
                    Ok(println!("All provisioning profiles are valid"))
                } else {
                    let mut errors_counter = 0;
                    let mut removals_counter = 0;
                    for profile in info.profiles {
                        match std::fs::remove_file(&profile.path) {
                            Ok(_) => {
                                removals_counter += 1;
                                println!("'{}' was removed", profile.uuid)
                            }
                            Err(e) => {
                                errors_counter += 1;
                                println!("Error while trying to remove '{}'", profile.uuid);
                                println!("{}", e);
                            }
                        }
                    }
                    println!("Removed {} of {}", removals_counter, info.total);
                    if errors_counter > 0 {
                        Err(cli::Error::Custom("There were some errors while removing \
                                                provisioning profiles"
                            .into()))
                    } else {
                        Ok(())
                    }
                }
            }
        }
    });
    if let Err(e) = result {
        e.exit();
    }
}

// fn search(args: &::docopt::ArgvMap) -> CliResult {
//    let text = args.get_str("<text>");
//    if text.is_empty() {
//        return Err(CliError::EmptyParameter("<text>"));
//    }
//
//    let info = mp::with_dir(directory(args), |dir| mp::search(dir, text))?;
//    if info.profiles.is_empty() {
//        println!("Nothing found for '{}'", text);
//    } else {
//        for profile in &info.profiles {
//            println!("\n{}", profile.description());
//        }
//        println!("\nFound {} of {}", info.profiles.len(), info.total);
//    }
//    Ok(())
// }
//
// fn remove(args: &::docopt::ArgvMap) -> CliResult {
//    let uuid = args.get_str("<uuid>");
//    if uuid.is_empty() {
//        return Err(CliError::EmptyParameter("<uuid>"));
//    }
//
//    mp::with_dir(directory(args), |dir| mp::remove(dir, uuid))?;
//    println!("'{}' was removed", uuid);
//    Ok(())
// }
//
// fn show_xml(args: &::docopt::ArgvMap) -> CliResult {
//    let uuid = args.get_str("<uuid>");
//    if uuid.is_empty() {
//        return Err(CliError::EmptyParameter("<uuid>"));
//    }
//
//    let xml = mp::with_dir(directory(args), |dir| mp::xml(dir, uuid))?;
//    println!("{}", xml);
//    Ok(())
// }
//
// fn show_expired(args: &::docopt::ArgvMap) -> CliResult {
//    use chrono::*;
//
//    let mut date = UTC::now();
//    if let Some(days) = args.get_str("<days>").parse::<i64>().ok() {
//        if days < 0 || days > 365 {
//            return Err(CliError::Custom("<days> should be between 0 and 365".to_string()));
//        }
//        date = date + Duration::days(days);
//    }
//
//    let info = mp::with_dir(directory(args), |dir| mp::expired_profiles(dir, date))?;
//    if info.profiles.is_empty() {
//        println!("All provisioning profiles are valid");
//    } else {
//        for profile in &info.profiles {
//            println!("\n{}", profile.description());
//        }
//        println!("\nFound {} of {}", info.profiles.len(), info.total);
//    }
//    Ok(())
// }
<commit_msg>Handle the remove uuid command<commit_after>
extern crate mprovision;
#[macro_use(version)]
extern crate version;
extern crate chrono;
#[cfg(test)]
#[macro_use(expect)]
extern crate expectest;
extern crate clap;

use mprovision as mp;
use cli::Command;
use std::env;
use chrono::*;

mod cli;

fn main() {
    let result = cli::parse(env::args()).and_then(|command| {
        match command {
            Command::List(list_params) => Ok(()),
            Command::ShowUuid(uuid, directory) => Ok(()),
            Command::ShowPath(file_path) => Ok(()),
            Command::RemoveUuid(uuid, directory) => {
                mp::with_dir(directory, |dir| mp::remove(dir, &uuid))?;
                Ok(println!("'{}' was removed", uuid))
            }
            Command::RemovePath(file_path) => Ok(()),
            Command::Cleanup(directory) => {
                let info = mp::with_dir(directory, |dir| mp::expired_profiles(dir, UTC::now()))?;
                if info.profiles.is_empty() {
                    Ok(println!("All provisioning profiles are valid"))
                } else {
                    let mut errors_counter = 0;
                    let mut removals_counter = 0;
                    for profile in info.profiles {
                        match std::fs::remove_file(&profile.path) {
                            Ok(_) => {
                                removals_counter += 1;
                                println!("'{}' was removed", profile.uuid)
                            }
                            Err(e) => {
                                errors_counter += 1;
                                println!("Error while trying to remove '{}'", profile.uuid);
                                println!("{}", e);
                            }
                        }
                    }
                    println!("Removed {} of {}", removals_counter, info.total);
                    if errors_counter > 0 {
                        Err(cli::Error::Custom("There were some errors while removing \
                                                provisioning profiles"
                            .into()))
                    } else {
                        Ok(())
                    }
                }
            }
        }
    });
    if let Err(e) = result {
        e.exit();
    }
}

// fn search(args: &::docopt::ArgvMap) -> CliResult {
//    let text = args.get_str("<text>");
//    if text.is_empty() {
//        return Err(CliError::EmptyParameter("<text>"));
//    }
//
//    let info = mp::with_dir(directory(args), |dir| mp::search(dir, text))?;
//    if info.profiles.is_empty() {
//        println!("Nothing found for '{}'", text);
//    } else {
//        for profile in &info.profiles {
//            println!("\n{}", profile.description());
//        }
//        println!("\nFound {} of {}", info.profiles.len(), info.total);
//    }
//    Ok(())
// }
//
// fn show_xml(args: &::docopt::ArgvMap) -> CliResult {
//    let uuid = args.get_str("<uuid>");
//    if uuid.is_empty() {
//        return Err(CliError::EmptyParameter("<uuid>"));
//    }
//
//    let xml = mp::with_dir(directory(args), |dir| mp::xml(dir, uuid))?;
//    println!("{}", xml);
//    Ok(())
// }
//
// fn show_expired(args: &::docopt::ArgvMap) -> CliResult {
//    use chrono::*;
//
//    let mut date = UTC::now();
//    if let Some(days) = args.get_str("<days>").parse::<i64>().ok() {
//        if days < 0 || days > 365 {
//            return Err(CliError::Custom("<days> should be between 0 and 365".to_string()));
//        }
//        date = date + Duration::days(days);
//    }
//
//    let info = mp::with_dir(directory(args), |dir| mp::expired_profiles(dir, date))?;
//    if info.profiles.is_empty() {
//        println!("All provisioning profiles are valid");
//    } else {
//        for profile in &info.profiles {
//            println!("\n{}", profile.description());
//        }
//        println!("\nFound {} of {}", info.profiles.len(), info.total);
//    }
//    Ok(())
// }
<|endoftext|>


<commit_before>//! Streaming bodies for Requests and Responses
//!
//! For both [Clients](crate::client) and [Servers](crate::server), requests and
//! responses use streaming bodies, instead of complete buffering. This
//! allows applications to not use memory they don't need, and allows exerting
//! back-pressure on connections by only reading when asked.
//!
//! There are two pieces to this in hyper:
//!
//! - **The [`HttpBody`](HttpBody) trait** describes all possible bodies.
//!   hyper allows any body type that implements `HttpBody`, allowing
//!   applications to have fine-grained control over their streaming.
//! - **The [`Body`](Body) concrete type**, which is an implementation of
//!   `HttpBody`, and returned by hyper as a "receive stream" (so, for server
//!   requests and client responses). It is also a decent default implementation
//!   if you don't have very custom needs of your send streams.

pub use bytes::{Buf, Bytes};
pub use http_body::Body as HttpBody;

pub use self::aggregate::aggregate;
pub use self::body::{Body, Sender};
pub(crate) use self::length::DecodedLength;
pub use self::to_bytes::to_bytes;

mod aggregate;
mod body;
mod length;
mod to_bytes;

/// An optimization to try to take a full body if immediately available.
///
/// This is currently limited to *only* `hyper::Body`s.
#[cfg(feature = "http1")]
pub(crate) fn take_full_data<T: HttpBody + 'static>(body: &mut T) -> Option<T::Data> {
    use std::any::{Any, TypeId};

    // This static type check can be optimized at compile-time.
    if TypeId::of::<T>() == TypeId::of::<Body>() {
        let mut full = (body as &mut dyn Any)
            .downcast_mut::<Body>()
            .expect("must be Body")
            .take_full_data();
        // This second cast is required to make the type system happy.
        // Without it, the compiler cannot reason that the type is actually
        // `T::Data`. Oh wells.
        //
        // It's still a measurable win!
        (&mut full as &mut dyn Any)
            .downcast_mut::<Option<T::Data>>()
            .expect("must be T::Data")
            .take()
    } else {
        None
    }
}

fn _assert_send_sync() {
    fn _assert_send<T: Send>() {}
    fn _assert_sync<T: Sync>() {}

    _assert_send::<Body>();
    _assert_sync::<Body>();
}
<commit_msg>feat(body): reexport `hyper::body::SizeHint` (#2404)<commit_after>//! Streaming bodies for Requests and Responses
//!
//! For both [Clients](crate::client) and [Servers](crate::server), requests and
//! responses use streaming bodies, instead of complete buffering. This
//! allows applications to not use memory they don't need, and allows exerting
//! back-pressure on connections by only reading when asked.
//!
//! There are two pieces to this in hyper:
//!
//! - **The [`HttpBody`](HttpBody) trait** describes all possible bodies.
//!   hyper allows any body type that implements `HttpBody`, allowing
//!   applications to have fine-grained control over their streaming.
//! - **The [`Body`](Body) concrete type**, which is an implementation of
//!   `HttpBody`, and returned by hyper as a "receive stream" (so, for server
//!   requests and client responses). It is also a decent default implementation
//!   if you don't have very custom needs of your send streams.

pub use bytes::{Buf, Bytes};
pub use http_body::Body as HttpBody;
pub use http_body::SizeHint;

pub use self::aggregate::aggregate;
pub use self::body::{Body, Sender};
pub(crate) use self::length::DecodedLength;
pub use self::to_bytes::to_bytes;

mod aggregate;
mod body;
mod length;
mod to_bytes;

/// An optimization to try to take a full body if immediately available.
///
/// This is currently limited to *only* `hyper::Body`s.
#[cfg(feature = "http1")]
pub(crate) fn take_full_data<T: HttpBody + 'static>(body: &mut T) -> Option<T::Data> {
    use std::any::{Any, TypeId};

    // This static type check can be optimized at compile-time.
    if TypeId::of::<T>() == TypeId::of::<Body>() {
        let mut full = (body as &mut dyn Any)
            .downcast_mut::<Body>()
            .expect("must be Body")
            .take_full_data();
        // This second cast is required to make the type system happy.
        // Without it, the compiler cannot reason that the type is actually
        // `T::Data`. Oh wells.
        //
        // It's still a measurable win!
        (&mut full as &mut dyn Any)
            .downcast_mut::<Option<T::Data>>()
            .expect("must be T::Data")
            .take()
    } else {
        None
    }
}

fn _assert_send_sync() {
    fn _assert_send<T: Send>() {}
    fn _assert_sync<T: Sync>() {}

    _assert_send::<Body>();
    _assert_sync::<Body>();
}
<|endoftext|>


<commit_before>// parng/build.rs

extern crate gcc;

use gcc::Config;
use std::env;
use std::process::Command;

#[cfg(target_os="windows")]
fn nasm(out_path: &str, in_path: &str) {
    Command::new(&format!("nasm")).arg("-f").arg("win64")
                                  .arg("-o").arg(out_path)
                                  .arg(in_path)
                                  .status()
                                  .unwrap();
}

#[cfg(target_os="macos")]
fn nasm(out_path: &str, in_path: &str) {
    Command::new(&format!("nasm")).arg("-f").arg("macho64")
                                  .arg("--prefix").arg("_")
                                  .arg("-o").arg(out_path)
                                  .arg(in_path)
                                  .status()
                                  .unwrap();
}

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();

    let predict_o = format!("{}/prediction-x86_64-avx.o", out_dir);
    nasm(&predict_o, "prediction-x86_64-avx.asm");

    Config::new().object(&predict_o).compile("libparngacceleration.a")
}

<commit_msg>One fix for the build on ARM<commit_after>// parng/build.rs

extern crate gcc;

use gcc::Config;
use std::env;
use std::process::Command;

#[cfg(target_arch="x86_64")]
static PREDICTION_OBJ: &'static str = "prediction-x86_64-avx.o";
#[cfg(target_arch="x86_64")]
static PREDICTION_SOURCE: &'static str = "prediction-x86_64-avx.asm";
#[cfg(target_arch="arm")]
static PREDICTION_OBJ: &'static str = "prediction-arm-neon.o";
#[cfg(target_arch="arm")]
static PREDICTION_SOURCE: &'static str = "prediction-arm-neon.asm";

#[cfg(all(target_arch="x86_64", target_os="windows"))]
fn assemble(out_path: &str, in_path: &str) {
    Command::new(&format!("nasm")).arg("-f").arg("win64")
                                  .arg("-o").arg(out_path)
                                  .arg(in_path)
                                  .status()
                                  .unwrap();
}

#[cfg(all(target_arch="x86_64", target_os="macos"))]
fn assemble(out_path: &str, in_path: &str) {
    Command::new(&format!("nasm")).arg("-f").arg("macho64")
                                  .arg("--prefix").arg("_")
                                  .arg("-o").arg(out_path)
                                  .arg(in_path)
                                  .status()
                                  .unwrap();
}

#[cfg(all(target_arch="arm", target_os="linux"))]
fn assemble(out_path: &str, in_path: &str) {
    let temp_path = format!("{}.s", out_path);
    Command::new(&format!("cpp")).arg("-o").arg(&temp_path)
                                 .arg(in_path)
                                 .status()
                                 .unwrap();
    Command::new(&format!("as")).arg("-o").arg(out_path)
                                .arg("-mfpu=neon")
                                .arg(temp_path)
                                .status()
                                .unwrap();
}

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();

    let predict_o = format!("{}/{}", out_dir, PREDICTION_OBJ);
    assemble(&predict_o, PREDICTION_SOURCE);

    Config::new().object(&predict_o).compile("libparngacceleration.a")
}

<|endoftext|>


<commit_before>extern crate git2;
extern crate rustc_version;

use git2::{Repository, DescribeOptions, DescribeFormatOptions};
use std::env;
use std::path::Path;
use std::fs::File;
use std::io::{self, Write};
use std::process::exit;
use rustc_version::version_matches;

fn main() {
  if !version_matches(">= 1.8.0") {
    writeln!(&mut io::stderr(), "bins requires at least Rust 1.8.0").unwrap();
    exit(1);
  }
  let profile = env::var("PROFILE").unwrap();
  let version = if profile == "release" {
    String::from("")
  } else {
    let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let repo = match Repository::open(&manifest_dir) {
      Ok(r) => r,
      Err(e) => {
        writeln!(&mut io::stderr(), "Could not read git repository in {}: {}", manifest_dir, e).unwrap();
        exit(1);
      }
    };
    let version = repo
    .describe(
      DescribeOptions::new().describe_tags().show_commit_oid_as_fallback(true)
    )
    .unwrap()
    .format(
      Some(DescribeFormatOptions::new().dirty_suffix("-dirty"))
    )
    .unwrap();
    String::from("-") + &version
  };

  let out_dir = env::var("OUT_DIR").unwrap();
  let dest_path = Path::new(&out_dir).join("git_short_tag.rs");
  let mut f = File::create(&dest_path).unwrap();
  f.write_all(format!("
      fn git_short_tag() -> &'static str {{
          \"{}\"
      }}
  ", version).as_bytes()).unwrap();
}
<commit_msg>fix(build): allow building outside of a git repository<commit_after>extern crate git2;
extern crate rustc_version;

use git2::{Repository, DescribeOptions, DescribeFormatOptions};
use std::env;
use std::path::Path;
use std::fs::File;
use std::io::{self, Write};
use std::process::exit;
use rustc_version::version_matches;

fn get_version() -> String {
  let profile = env::var("PROFILE").unwrap();
  if profile == "release" {
    String::new()
  } else {
    let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let repo = match Repository::open(&manifest_dir) {
      Ok(r) => r,
      Err(_) => return String::new()
    };
    let version = repo
    .describe(
      DescribeOptions::new().describe_tags().show_commit_oid_as_fallback(true)
    )
    .unwrap()
    .format(
      Some(DescribeFormatOptions::new().dirty_suffix("-dirty"))
    )
    .unwrap();
    String::from("-") + &version
  }
}

fn main() {
  if !version_matches(">= 1.8.0") {
    writeln!(&mut io::stderr(), "bins requires at least Rust 1.8.0").unwrap();
    exit(1);
  }
  let profile = env::var("PROFILE").unwrap();
  let version = get_version();
  let out_dir = env::var("OUT_DIR").unwrap();
  let dest_path = Path::new(&out_dir).join("git_short_tag.rs");
  let mut f = File::create(&dest_path).unwrap();
  f.write_all(format!("
      fn git_short_tag() -> &'static str {{
          \"{}\"
      }}
  ", version).as_bytes()).unwrap();
}
<|endoftext|>


<commit_before>use std::os;
use std::io::Command;
use std::io::process::InheritFd;

fn main() {
    let dst = Path::new(os::getenv("OUT_DIR").unwrap());

    init();
    submodule_init();
    submodule_update();
    configure();
    build();
    install(&dst);
    println!("cargo:rustc-flags=-L {} -l termbox:static", dst.join("lib").display());
}

fn init() {
    let mut cmd = git();
    cmd.arg("init");
    run(&mut cmd);
}

fn submodule_init() {
    let mut cmd = git();
    cmd.arg("submodule");
    cmd.arg("init");
    run(&mut cmd);
}

fn submodule_update() {
    let mut cmd = git();
    cmd.arg("submodule");
    cmd.arg("update");
    run(&mut cmd);
}

fn git() -> Command {
    let cargo_dir = Path::new(os::getenv("CARGO_MANIFEST_DIR").unwrap());
    let mut cmd = Command::new("git");
    cmd.cwd(&cargo_dir);
    cmd
}

fn configure() {
    let mut cmd = waf();
    cmd.arg("configure");
    cmd.arg("--prefix=/");

    let target = os::getenv("TARGET").unwrap();
    let mut cflags;
    if target.as_slice().contains("i686") {
        cflags = "-m32"
    } else if target.as_slice().contains("x86_64") {
        cflags = "-m64 -fPIC"
    } else {
        cflags = ""
    }
    println!("waf configure: setting CFLAGS to: `{}`", cflags);
    os::setenv("CFLAGS", cflags);

    run(&mut cmd);
    os::unsetenv("CFLAGS");
}

fn build() {
    let mut cmd = waf();
    cmd.arg("build");
    cmd.arg("--targets=termbox_static");
    run(&mut cmd);
}

fn install(dst: &Path) {
    let mut cmd = waf();
    cmd.arg("install");
    cmd.arg("--targets=termbox_static");
    cmd.arg(format!("--destdir={}", dst.display()));
    run(&mut cmd);
}

fn waf() -> Command {
    let cargo_dir = Path::new(os::getenv("CARGO_MANIFEST_DIR").unwrap());
    let termbox_dir = cargo_dir.join("termbox");
    let mut cmd = Command::new("./waf");
    cmd.cwd(&termbox_dir);
    cmd
}

fn run(cmd: &mut Command) {
    println!("running: {}", cmd);
    assert!(cmd.stdout(InheritFd(1))
                .stderr(InheritFd(2))
                .status()
                .unwrap()
                .success());
}
<commit_msg>Remove git commands<commit_after>use std::os;
use std::io::Command;
use std::io::process::InheritFd;

fn main() {
    let dst = Path::new(os::getenv("OUT_DIR").unwrap());

    configure();
    build();
    install(&dst);
    println!("cargo:rustc-flags=-L {} -l termbox:static", dst.join("lib").display());
}

fn configure() {
    let mut cmd = waf();
    cmd.arg("configure");
    cmd.arg("--prefix=/");

    let target = os::getenv("TARGET").unwrap();
    let mut cflags;
    if target.as_slice().contains("i686") {
        cflags = "-m32"
    } else if target.as_slice().contains("x86_64") {
        cflags = "-m64 -fPIC"
    } else {
        cflags = ""
    }
    println!("waf configure: setting CFLAGS to: `{}`", cflags);
    os::setenv("CFLAGS", cflags);

    run(&mut cmd);
    os::unsetenv("CFLAGS");
}

fn build() {
    let mut cmd = waf();
    cmd.arg("build");
    cmd.arg("--targets=termbox_static");
    run(&mut cmd);
}

fn install(dst: &Path) {
    let mut cmd = waf();
    cmd.arg("install");
    cmd.arg("--targets=termbox_static");
    cmd.arg(format!("--destdir={}", dst.display()));
    run(&mut cmd);
}

fn waf() -> Command {
    let cargo_dir = Path::new(os::getenv("CARGO_MANIFEST_DIR").unwrap());
    let termbox_dir = cargo_dir.join("termbox");
    let mut cmd = Command::new("./waf");
    cmd.cwd(&termbox_dir);
    cmd
}

fn run(cmd: &mut Command) {
    println!("running: {}", cmd);
    assert!(cmd.stdout(InheritFd(1))
                .stderr(InheritFd(2))
                .status()
                .unwrap()
                .success());
}
<|endoftext|>