<commit_before>//! This pass replaces a drop of a type that does not need dropping, with a goto

use crate::transform::MirPass;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::*;
use rustc_middle::ty::{ParamEnv, TyCtxt};

use super::simplify::simplify_cfg;

pub struct RemoveUnneededDrops;

impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops {
    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
        trace!("Running RemoveUnneededDrops on {:?}", body.source);
        let mut opt_finder = RemoveUnneededDropsOptimizationFinder {
            tcx,
            body,
            param_env: tcx.param_env(body.source.def_id()),
            optimizations: vec![],
        };
        opt_finder.visit_body(body);
        let should_simplify = !opt_finder.optimizations.is_empty();
        for (loc, target) in opt_finder.optimizations {
            if !tcx
                .consider_optimizing(|| format!("RemoveUnneededDrops {:?} ", body.source.def_id()))
            {
                break;
            }

            let terminator = body.basic_blocks_mut()[loc.block].terminator_mut();
            debug!("SUCCESS: replacing `drop` with goto({:?})", target);
            terminator.kind = TerminatorKind::Goto { target };
        }

        // if we applied optimizations, we potentially have some cfg to cleanup to
        // make it easier for further passes
        if should_simplify {
            simplify_cfg(body);
        }
    }
}

impl<'a, 'tcx> Visitor<'tcx> for RemoveUnneededDropsOptimizationFinder<'a, 'tcx> {
    fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
        match terminator.kind {
            TerminatorKind::Drop { place, target, .. } => {
                let ty = place.ty(self.body, self.tcx);
                let needs_drop = ty.ty.needs_drop(self.tcx, self.param_env);
                if !needs_drop {
                    self.optimizations.push((location, target));
                }
            }
            _ => {}
        }
        self.super_terminator(terminator, location);
    }
}
pub struct RemoveUnneededDropsOptimizationFinder<'a, 'tcx> {
    tcx: TyCtxt<'tcx>,
    body: &'a Body<'tcx>,
    optimizations: Vec<(Location, BasicBlock)>,
    param_env: ParamEnv<'tcx>,
}
<commit_msg>Visit only terminators when removing unneeded drops<commit_after>//! This pass replaces a drop of a type that does not need dropping, with a goto

use crate::transform::MirPass;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;

use super::simplify::simplify_cfg;

pub struct RemoveUnneededDrops;

impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops {
    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
        trace!("Running RemoveUnneededDrops on {:?}", body.source);

        let did = body.source.def_id();
        let param_env = tcx.param_env(did);
        let mut should_simplify = false;

        let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
        for block in basic_blocks {
            let terminator = block.terminator_mut();
            if let TerminatorKind::Drop { place, target, .. } = terminator.kind {
                let ty = place.ty(local_decls, tcx);
                if ty.ty.needs_drop(tcx, param_env) {
                    continue;
                }
                if !tcx.consider_optimizing(|| format!("RemoveUnneededDrops {:?} ", did)) {
                    continue;
                }
                debug!("SUCCESS: replacing `drop` with goto({:?})", target);
                terminator.kind = TerminatorKind::Goto { target };
                should_simplify = true;
            }
        }

        // if we applied optimizations, we potentially have some cfg to cleanup to
        // make it easier for further passes
        if should_simplify {
            simplify_cfg(body);
        }
    }
}
<|endoftext|>


<commit_before>
// Copyright 2017 The gltf Library Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use v2::{buffer, Extras, Index, Root};

/// Contains data structures for sparse storage.
pub mod sparse {
    use super::*;

    enum_number! {
        ComponentType {
            U8 = 5121,
            U16 = 5123,
            U32 = 5125,
        }
    }

    /// Extension specific data for `Indices`.
    #[derive(Clone, Debug, Default, Deserialize, Serialize)]
    pub struct IndicesExtensions {
        #[serde(default)]
        _allow_extra_fields: (),
    }

    /// Indices of those attributes that deviate from their initialization value.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Indices<E: Extras> {
        /// The parent `BufferView` containing the sparse indices.
        ///
        /// The referenced `BufferView` must not have `ArrayBuffer` nor
        /// `ElementArrayBuffer` as its target.
        #[serde(rename = "bufferView")]
        pub buffer_view: Index<buffer::BufferView<E>>,

        /// The offset relative to the start of the parent `BufferView` in bytes.
        #[serde(default, rename = "byteOffset")]
        pub byte_offset: u32,

        /// The data type of each index.
        pub component_type: ComponentType,

        /// Extension specific data.
        pub extensions: IndicesExtensions,

        /// Optional application specific data.
        pub extras: <E as Extras>::AccessorSparseIndices,
    }

    /// Extension specific data for `Storage`.
    #[derive(Clone, Debug, Default, Deserialize, Serialize)]
    pub struct StorageExtensions {
        #[serde(default)]
        _allow_extra_fields: (),
    }

    /// Sparse storage of attributes that deviate from their initialization value.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct Storage<E: Extras> {
        /// The number of attributes encoded in this sparse accessor.
        pub count: u32,

        /// Index array of size `count` that points to those accessor attributes
        /// that deviate from their initialization value.
        ///
        /// Indices must strictly increase.
        pub indices: Indices<E>,

        /// Array of size `count * number_of_components` storing the displaced
        /// accessor attributes pointed by `indices`.
        ///
        /// Substituted values must have the same `component_type` and number of
        /// components as the base `Accessor`.
        pub values: Values<E>,

        /// Extension specific data.
        pub extensions: StorageExtensions,

        /// Optional application specific data.
        pub extras: <E as Extras>::AccessorSparseStorage,
    }

    /// Extension specific data for `Values`.
    #[derive(Clone, Debug, Default, Deserialize, Serialize)]
    pub struct ValuesExtensions {
        #[serde(default)]
        _allow_extra_fields: (),
    }

    /// Array of size `count * number_of_components` storing the displaced
    /// accessor attributes pointed by `accessor::sparse::Indices`.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Values<E: Extras> {
        /// The parent `BufferView` containing the sparse indices.
        ///
        /// The referenced `BufferView` must not have `ArrayBuffer` nor
        /// `ElementArrayBuffer` as its target.
        #[serde(rename = "bufferView")]
        pub buffer_view: Index<buffer::BufferView<E>>,

        /// The offset relative to the start of the parent `BufferView` in bytes.
        #[serde(default, rename = "byteOffset")]
        pub byte_offset: u32,

        /// Extension specific data.
        pub extensions: ValuesExtensions,

        /// Optional application specific data.
        pub extras: <E as Extras>::AccessorSparseValues,
    }
}

/// Extension specific data for an `Accessor`.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct AccessorExtensions {
    #[serde(default)]
    _allow_extra_fields: (),
}

/// A typed view into a `BufferView`.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Accessor<E: Extras> {
    /// The parent `BufferView` this accessor reads from.
    #[serde(rename = "bufferView")]
    pub buffer_view: Index<buffer::BufferView<E>>,

    /// The offset relative to the start of the parent `BufferView` in bytes.
    #[serde(rename = "byteOffset")]
    pub byte_offset: u32,

    /// The number of components within the `BufferView` - not to be confused
    /// with the number of bytes in the `BufferView`.
    pub count: u32,

    /// The data type of each component.
    #[serde(rename = "componentType")]
    pub component_type: ComponentType,

    /// Extension specific data.
    #[serde(default)]
    pub extensions: AccessorExtensions,

    /// Optional application specific data.
    #[serde(default)]
    pub extras: <E as Extras>::Accessor,

    /// The multiplicity of each component.
    #[serde(rename = "type")]
    pub kind: Kind,

    /// Minimum value of each element in this attribute.
    #[serde(default)]
    pub min: Vec<f32>,

    /// Maximum value of each element in this attribute.
    #[serde(default)]
    pub max: Vec<f32>,

    /// Optional user-defined name for this object.
    pub name: Option<String>,

    /// Specifies whether integer data values should be normalized.
    #[serde(default)]
    pub normalized: bool,

    /// Sparse storage of attributes that deviate from their initialization
    /// value.
    pub sparse: Option<sparse::Storage<E>>,
}

impl<E: Extras> Accessor<E> {
    /// Returns `Ok(())` if all indices are in range of the maximums.
    #[doc(hidden)]
    pub fn range_check(&self, root: &Root<E>) -> Result<(), ()> {
        if let Some(ref sparse) = self.sparse {
            let _ = root.try_get(&sparse.indices.buffer_view)?;
            let _ = root.try_get(&sparse.values.buffer_view)?;
        }
        let _ = root.try_get(&self.buffer_view)?;
        Ok(())
    }
}

enum_number! {
    ComponentType {
        I8 = 5120,
        U8 = 5121,
        I16 = 5122,
        U16 = 5123,
        U32 = 5125,
        F32 = 5126,
    }
}

enum_string! {
    Kind {
        Scalar = "SCALAR",
        Vec2 = "VEC2",
        Vec3 = "VEC3",
        Vec4 = "VEC4",
        Mat2 = "MAT2",
        Mat3 = "MAT3",
        Mat4 = "MAT4",
    }
}
<commit_msg>Added default value for `accessor.byteOffset`<commit_after>
// Copyright 2017 The gltf Library Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use v2::{buffer, Extras, Index, Root};

/// Contains data structures for sparse storage.
pub mod sparse {
    use super::*;

    enum_number! {
        ComponentType {
            U8 = 5121,
            U16 = 5123,
            U32 = 5125,
        }
    }

    /// Extension specific data for `Indices`.
    #[derive(Clone, Debug, Default, Deserialize, Serialize)]
    pub struct IndicesExtensions {
        #[serde(default)]
        _allow_extra_fields: (),
    }

    /// Indices of those attributes that deviate from their initialization value.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Indices<E: Extras> {
        /// The parent `BufferView` containing the sparse indices.
        ///
        /// The referenced `BufferView` must not have `ArrayBuffer` nor
        /// `ElementArrayBuffer` as its target.
        #[serde(rename = "bufferView")]
        pub buffer_view: Index<buffer::BufferView<E>>,

        /// The offset relative to the start of the parent `BufferView` in bytes.
        #[serde(default, rename = "byteOffset")]
        pub byte_offset: u32,

        /// The data type of each index.
        pub component_type: ComponentType,

        /// Extension specific data.
        pub extensions: IndicesExtensions,

        /// Optional application specific data.
        pub extras: <E as Extras>::AccessorSparseIndices,
    }

    /// Extension specific data for `Storage`.
    #[derive(Clone, Debug, Default, Deserialize, Serialize)]
    pub struct StorageExtensions {
        #[serde(default)]
        _allow_extra_fields: (),
    }

    /// Sparse storage of attributes that deviate from their initialization value.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct Storage<E: Extras> {
        /// The number of attributes encoded in this sparse accessor.
        pub count: u32,

        /// Index array of size `count` that points to those accessor attributes
        /// that deviate from their initialization value.
        ///
        /// Indices must strictly increase.
        pub indices: Indices<E>,

        /// Array of size `count * number_of_components` storing the displaced
        /// accessor attributes pointed by `indices`.
        ///
        /// Substituted values must have the same `component_type` and number of
        /// components as the base `Accessor`.
        pub values: Values<E>,

        /// Extension specific data.
        pub extensions: StorageExtensions,

        /// Optional application specific data.
        pub extras: <E as Extras>::AccessorSparseStorage,
    }

    /// Extension specific data for `Values`.
    #[derive(Clone, Debug, Default, Deserialize, Serialize)]
    pub struct ValuesExtensions {
        #[serde(default)]
        _allow_extra_fields: (),
    }

    /// Array of size `count * number_of_components` storing the displaced
    /// accessor attributes pointed by `accessor::sparse::Indices`.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Values<E: Extras> {
        /// The parent `BufferView` containing the sparse indices.
        ///
        /// The referenced `BufferView` must not have `ArrayBuffer` nor
        /// `ElementArrayBuffer` as its target.
        #[serde(rename = "bufferView")]
        pub buffer_view: Index<buffer::BufferView<E>>,

        /// The offset relative to the start of the parent `BufferView` in bytes.
        #[serde(default, rename = "byteOffset")]
        pub byte_offset: u32,

        /// Extension specific data.
        pub extensions: ValuesExtensions,

        /// Optional application specific data.
        pub extras: <E as Extras>::AccessorSparseValues,
    }
}

/// Extension specific data for an `Accessor`.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct AccessorExtensions {
    #[serde(default)]
    _allow_extra_fields: (),
}

/// A typed view into a `BufferView`.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Accessor<E: Extras> {
    /// The parent `BufferView` this accessor reads from.
    #[serde(rename = "bufferView")]
    pub buffer_view: Index<buffer::BufferView<E>>,

    /// The offset relative to the start of the parent `BufferView` in bytes.
    #[serde(default, rename = "byteOffset")]
    pub byte_offset: u32,

    /// The number of components within the `BufferView` - not to be confused
    /// with the number of bytes in the `BufferView`.
    pub count: u32,

    /// The data type of each component.
    #[serde(rename = "componentType")]
    pub component_type: ComponentType,

    /// Extension specific data.
    #[serde(default)]
    pub extensions: AccessorExtensions,

    /// Optional application specific data.
    #[serde(default)]
    pub extras: <E as Extras>::Accessor,

    /// The multiplicity of each component.
    #[serde(rename = "type")]
    pub kind: Kind,

    /// Minimum value of each element in this attribute.
    #[serde(default)]
    pub min: Vec<f32>,

    /// Maximum value of each element in this attribute.
    #[serde(default)]
    pub max: Vec<f32>,

    /// Optional user-defined name for this object.
    pub name: Option<String>,

    /// Specifies whether integer data values should be normalized.
    #[serde(default)]
    pub normalized: bool,

    /// Sparse storage of attributes that deviate from their initialization
    /// value.
    pub sparse: Option<sparse::Storage<E>>,
}

impl<E: Extras> Accessor<E> {
    /// Returns `Ok(())` if all indices are in range of the maximums.
    #[doc(hidden)]
    pub fn range_check(&self, root: &Root<E>) -> Result<(), ()> {
        if let Some(ref sparse) = self.sparse {
            let _ = root.try_get(&sparse.indices.buffer_view)?;
            let _ = root.try_get(&sparse.values.buffer_view)?;
        }
        let _ = root.try_get(&self.buffer_view)?;
        Ok(())
    }
}

enum_number! {
    ComponentType {
        I8 = 5120,
        U8 = 5121,
        I16 = 5122,
        U16 = 5123,
        U32 = 5125,
        F32 = 5126,
    }
}

enum_string! {
    Kind {
        Scalar = "SCALAR",
        Vec2 = "VEC2",
        Vec3 = "VEC3",
        Vec4 = "VEC4",
        Mat2 = "MAT2",
        Mat3 = "MAT3",
        Mat4 = "MAT4",
    }
}
<|endoftext|>


<commit_before>use std::io::Read;
use hyper;
use hyper::header::{Accept, Authorization, Bearer, ContentType, qitem};
use hyper::method::Method;
use hyper::mime::{Mime, TopLevel, SubLevel};
use serde_json;
use serde::ser::Serialize;
use serde::de::Deserialize;

use github::models::*;

pub struct Session {
    client: GithubClient,
    user: User,
}

impl Session {
    pub fn new(host: &str, token: &str) -> Result<Session, String> {
        let api_base = if host == "github.com" {
            "https://api.github.com".to_string()
        } else {
            format!("https://{}/api/v3", host)
        };

        let client = GithubClient {
            host: host.to_string(),
            token: token.to_string(),
            api_base: api_base,
        };

        // make sure we can auth as this user befor handing out session.
        let user: User = match client.get("/user") {
            Ok(u) => u,
            Err(e) => return Err(format!("Error authenticating with token: {}", e)),
        };

        Ok(Session {
            client: client,
            user: user,
        })
    }

    pub fn user(&self) -> &User {
        return &self.user;
    }

    pub fn github_host(&self) -> &str {
        &self.client.host
    }

    pub fn github_token(&self) -> &str {
        &self.client.token
    }

    pub fn get_pull_request(&self, owner: &str, repo: &str, number: u32)
                            -> Result<PullRequest, String> {
        self.client.get(&format!("repos/{}/{}/pulls/{}", owner, repo, number))
    }

    pub fn get_pull_requests(&self, owner: &str, repo: &str, state: Option<&str>,
                             head: Option<&str>)
                             -> Result<Vec<PullRequest>, String> {
        let prs: Vec<PullRequest> = try!(self.client
            .get(&format!("repos/{}/{}/pulls?state={}&head={}",
                          owner,
                          repo,
                          state.unwrap_or(""),
                          head.unwrap_or(""))));

        let prs: Vec<PullRequest> = prs.into_iter()
            .filter(|p| {
                if let Some(head) = head {
                    p.head.ref_name == head || p.head.sha == head
                } else {
                    true
                }
            })
            .collect();
        Ok(prs)
    }

    pub fn create_pull_request(&self, owner: &str, repo: &str, title: &str, body: &str,
                               head: &str, base: &str)
                               -> Result<PullRequest, String> {
        #[derive(Serialize)]
        struct CreatePR {
            title: String,
            body: String,
            head: String,
            base: String,
        }
        let pr = CreatePR {
            title: title.to_string(),
            body: body.to_string(),
            head: head.to_string(),
            base: base.to_string(),
        };

        self.client.post(&format!("repos/{}/{}/pulls", owner, repo), &pr)
    }

    pub fn get_pull_request_labels(&self, owner: &str, repo: &str, number: u32)
                                   -> Result<Vec<Label>, String> {

        self.client.get(&format!("repos/{}/{}/issues/{}/labels", owner, repo, number))
    }

    pub fn assign_pull_request(&self, owner: &str, repo: &str, number: u32,
                               assignees: Vec<String>)
                               -> Result<AssignResponse, String> {
        #[derive(Serialize)]
        struct AssignPR {
            assignees: Vec<String>,
        }

        let body = AssignPR { assignees: assignees };

        self.client.post(&format!("repos/{}/{}/issues/{}/assignees", owner, repo, number),
                         &body)
    }

    pub fn comment_pull_request(&self, owner: &str, repo: &str, number: u32, comment: &str)
                                -> Result<(), String> {
        #[derive(Serialize)]
        struct CommentPR {
            body: String,
        }
        let body = CommentPR { body: comment.to_string() };

        self.client.post(&format!("repos/{}/{}/issues/{}/comments", owner, repo, number),
                         &body)
    }
}

pub struct GithubClient {
    host: String,
    api_base: String,
    token: String,
}

impl GithubClient {
    pub fn get<T: Deserialize>(&self, path: &str) -> Result<T, String> {
        self.request::<T, String>(Method::Get, path, None)
    }

    pub fn post<T: Deserialize, E: Serialize>(&self, path: &str, body: &E) -> Result<T, String> {
        self.request::<T, E>(Method::Post, path, Some(body))
    }

    fn request<T: Deserialize, E: Serialize>(&self, method: Method, path: &str, body: Option<&E>)
                                             -> Result<T, String> {
        let url;
        if path.starts_with("/") {
            url = self.api_base.clone() + path;
        } else {
            url = self.api_base.clone() + "/" + path;
        }

        let body_json: String;

        let client = hyper::client::Client::new();
        let mut req = client.request(method, url.as_str())
            .header(Accept(vec![qitem(Mime(TopLevel::Application, SubLevel::Json, vec![]))]))
            .header(ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![])))
            .header(Authorization(Bearer { token: self.token.clone() }));

        if let Some(body) = body {
            body_json = match serde_json::to_string(&body) {
                Ok(j) => j,
                Err(e) => return Err(format!("Error json-encoding body: {}", e)),
            };
            req = req.body(&body_json)
        }

        let res = req.send();

        match res {
            Ok(mut res) => {
                let mut res_str = String::new();
                res.read_to_string(&mut res_str).unwrap_or(0);
                if res.status.is_success() {
                    let obj: T = match serde_json::from_str(&res_str) {
                        Ok(obj) => obj,
                        Err(e) => return Err(format!("Coudl not parse response: {}", e)),
                    };
                    Ok(obj)
                } else {
                    Err(format!("HTTP {} -- {}", res.status, res_str))
                }
            }
            Err(e) => Err(format!("Error sending to request github: {}", e)),
        }
    }
}
<commit_msg>Add User-Agent header for github.com (#28)<commit_after>use std::io::Read;
use hyper;
use hyper::header::{Accept, Authorization, Bearer, ContentType, qitem, UserAgent};
use hyper::method::Method;
use hyper::mime::{Mime, TopLevel, SubLevel};
use serde_json;
use serde::ser::Serialize;
use serde::de::Deserialize;

use github::models::*;

pub struct Session {
    client: GithubClient,
    user: User,
}

impl Session {
    pub fn new(host: &str, token: &str) -> Result<Session, String> {
        let api_base = if host == "github.com" {
            "https://api.github.com".to_string()
        } else {
            format!("https://{}/api/v3", host)
        };

        let client = GithubClient {
            host: host.to_string(),
            token: token.to_string(),
            api_base: api_base,
        };

        // make sure we can auth as this user befor handing out session.
        let user: User = match client.get("/user") {
            Ok(u) => u,
            Err(e) => return Err(format!("Error authenticating with token: {}", e)),
        };

        Ok(Session {
            client: client,
            user: user,
        })
    }

    pub fn user(&self) -> &User {
        return &self.user;
    }

    pub fn github_host(&self) -> &str {
        &self.client.host
    }

    pub fn github_token(&self) -> &str {
        &self.client.token
    }

    pub fn get_pull_request(&self, owner: &str, repo: &str, number: u32)
                            -> Result<PullRequest, String> {
        self.client.get(&format!("repos/{}/{}/pulls/{}", owner, repo, number))
    }

    pub fn get_pull_requests(&self, owner: &str, repo: &str, state: Option<&str>,
                             head: Option<&str>)
                             -> Result<Vec<PullRequest>, String> {
        let prs: Vec<PullRequest> = try!(self.client
            .get(&format!("repos/{}/{}/pulls?state={}&head={}",
                          owner,
                          repo,
                          state.unwrap_or(""),
                          head.unwrap_or(""))));

        let prs: Vec<PullRequest> = prs.into_iter()
            .filter(|p| {
                if let Some(head) = head {
                    p.head.ref_name == head || p.head.sha == head
                } else {
                    true
                }
            })
            .collect();
        Ok(prs)
    }

    pub fn create_pull_request(&self, owner: &str, repo: &str, title: &str, body: &str,
                               head: &str, base: &str)
                               -> Result<PullRequest, String> {
        #[derive(Serialize)]
        struct CreatePR {
            title: String,
            body: String,
            head: String,
            base: String,
        }
        let pr = CreatePR {
            title: title.to_string(),
            body: body.to_string(),
            head: head.to_string(),
            base: base.to_string(),
        };

        self.client.post(&format!("repos/{}/{}/pulls", owner, repo), &pr)
    }

    pub fn get_pull_request_labels(&self, owner: &str, repo: &str, number: u32)
                                   -> Result<Vec<Label>, String> {

        self.client.get(&format!("repos/{}/{}/issues/{}/labels", owner, repo, number))
    }

    pub fn assign_pull_request(&self, owner: &str, repo: &str, number: u32,
                               assignees: Vec<String>)
                               -> Result<AssignResponse, String> {
        #[derive(Serialize)]
        struct AssignPR {
            assignees: Vec<String>,
        }

        let body = AssignPR { assignees: assignees };

        self.client.post(&format!("repos/{}/{}/issues/{}/assignees", owner, repo, number),
                         &body)
    }

    pub fn comment_pull_request(&self, owner: &str, repo: &str, number: u32, comment: &str)
                                -> Result<(), String> {
        #[derive(Serialize)]
        struct CommentPR {
            body: String,
        }
        let body = CommentPR { body: comment.to_string() };

        self.client.post(&format!("repos/{}/{}/issues/{}/comments", owner, repo, number),
                         &body)
    }
}

pub struct GithubClient {
    host: String,
    api_base: String,
    token: String,
}

impl GithubClient {
    pub fn get<T: Deserialize>(&self, path: &str) -> Result<T, String> {
        self.request::<T, String>(Method::Get, path, None)
    }

    pub fn post<T: Deserialize, E: Serialize>(&self, path: &str, body: &E) -> Result<T, String> {
        self.request::<T, E>(Method::Post, path, Some(body))
    }

    fn request<T: Deserialize, E: Serialize>(&self, method: Method, path: &str, body: Option<&E>)
                                             -> Result<T, String> {
        let url;
        if path.starts_with("/") {
            url = self.api_base.clone() + path;
        } else {
            url = self.api_base.clone() + "/" + path;
        }

        let body_json: String;

        let client = hyper::client::Client::new();
        let mut req = client.request(method, url.as_str())
            .header(UserAgent("octobot".to_string()))
            .header(Accept(vec![qitem(Mime(TopLevel::Application, SubLevel::Json, vec![]))]))
            .header(ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![])))
            .header(Authorization(Bearer { token: self.token.clone() }));

        if let Some(body) = body {
            body_json = match serde_json::to_string(&body) {
                Ok(j) => j,
                Err(e) => return Err(format!("Error json-encoding body: {}", e)),
            };
            req = req.body(&body_json)
        }

        let res = req.send();

        match res {
            Ok(mut res) => {
                let mut res_str = String::new();
                res.read_to_string(&mut res_str).unwrap_or(0);
                if res.status.is_success() {
                    let obj: T = match serde_json::from_str(&res_str) {
                        Ok(obj) => obj,
                        Err(e) => return Err(format!("Coudl not parse response: {}", e)),
                    };
                    Ok(obj)
                } else {
                    Err(format!("HTTP {} -- {}", res.status, res_str))
                }
            }
            Err(e) => Err(format!("Error sending to request github: {}", e)),
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::env;
use std::ffi::{OsStr, OsString};
use std::fmt::{self, Debug, Formatter};
use std::iter::FromIterator;
use std::path::PathBuf;

use indexmap::IndexSet;
use nix::NixPath;

#[derive(Clone)]
pub struct PathVec {
    vec: VecDeque<PathBuf>,
}

impl Debug for PathVec {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        let mut f = f.debug_list();
        for p in self.iter() {
            f.entry(p);
        }
        f.finish()
    }
}

impl PathVec {
    pub fn make(&self) -> OsString {
        return env::join_paths(self.clone().unique()).expect("join path error");
    }

    pub fn iter(&self) -> impl Iterator<Item = &PathBuf> {
        self.vec.iter()
    }

    pub fn unique(self) -> Self {
        Self::from_iter(IndexSet::<_>::from_iter(self.vec))
    }

    pub fn no_version_managers(self) -> Self {
        self.vec
            .into_iter()
            .filter(|p| !p.ends_with(".pyenv/shims") && !p.ends_with(".rbenv/shims"))
            .collect()
    }

    pub fn push_front<T: Into<PathBuf>>(&mut self, path: T) {
        self.vec.push_front(path.into())
    }

    #[allow(dead_code)]
    pub fn push_back<T: Into<PathBuf>>(&mut self, path: T) {
        self.vec.push_back(path.into())
    }

    pub fn parse<T: AsRef<OsStr>>(input: T) -> Self {
        env::split_paths(input.as_ref())
            .filter(|p| p.len() > 0)
            .collect()
    }

    pub fn new() -> Self {
        Self {
            vec: VecDeque::new(),
        }
    }
}

impl FromIterator<PathBuf> for PathVec {
    fn from_iter<T: IntoIterator<Item = PathBuf>>(iter: T) -> Self {
        Self {
            vec: FromIterator::from_iter(iter),
        }
    }
}

impl IntoIterator for PathVec {
    type Item = PathBuf;
    type IntoIter = std::collections::vec_deque::IntoIter<PathBuf>;

    fn into_iter(self) -> Self::IntoIter {
        self.vec.into_iter()
    }
}

#[cfg(test)]
mod tests {
    // Note this useful idiom: importing names from outer (for mod tests) scope.
    use super::*;

    const FOO: &str = "/foo";
    const BAR: &str = "/bar";

    #[test]
    fn test() {
        // no item
        let ps = PathVec::parse(OsString::new());
        let actual = ps.make();
        assert_eq!(actual, "");

        // no item add one to front
        let mut ps = PathVec::parse(OsString::new());
        ps.push_front(FOO.to_string());
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // no item add one to back
        let mut ps = PathVec::parse(OsString::new());
        ps.push_back(FOO.to_string());
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // no item add two items to back
        let mut ps = PathVec::parse(OsString::new());
        ps.push_back(FOO.to_string());
        ps.push_back(BAR.to_string());
        let actual = ps.make();
        let expected = OsString::from(format!("{}:{}", FOO, BAR));
        assert_eq!(actual, expected);

        // one item
        let ps = PathVec::parse(OsString::from(FOO));
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // should fix following cases
        let ps = PathVec::parse(OsString::from(":/foo"));
        let actual = ps.make();
        assert_eq!(actual, "/foo");
        let ps = PathVec::parse(OsString::from("/foo:"));
        let actual = ps.make();
        assert_eq!(actual, "/foo");

        // two items
        let input = OsString::from(format!("{}:{}", FOO, BAR));
        let ps = PathVec::parse(&input);
        let actual = ps.make();
        assert_eq!(actual, input);

        // move order correctly
        let input = OsString::from("/a:/b:/c");
        let mut ps = PathVec::parse(&input);
        ps.push_front("/c".to_string());
        let actual = ps.make();
        let expect = OsString::from("/c:/a:/b");
        assert_eq!(actual, expect);

        // remove pyenv, rbenv, and node path
        let input = OsString::from("/a:/home/.pyenv/shims:/home/.rbenv/shims");
        let ps = PathVec::parse(&input).no_version_managers();
        let actual = ps.make();
        assert_eq!(actual, OsString::from("/a"))
    }

    #[test]
    fn test_unique() {
        let input = OsString::from("/a:/b:/a");
        let ps = PathVec::parse(&input);
        let actual = ps.make();
        assert_eq!(actual, OsString::from("/a:/b"))
    }
}
<commit_msg>Use inner debug impl for PathVec<commit_after>use std::collections::VecDeque;
use std::env;
use std::ffi::{OsStr, OsString};
use std::fmt::{self, Debug, Formatter};
use std::iter::FromIterator;
use std::path::PathBuf;

use indexmap::IndexSet;
use nix::NixPath;

#[derive(Clone)]
pub struct PathVec {
    vec: VecDeque<PathBuf>,
}

impl Debug for PathVec {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        Debug::fmt(&self.vec, f)
    }
}

impl PathVec {
    pub fn make(&self) -> OsString {
        return env::join_paths(self.clone().unique()).expect("join path error");
    }

    pub fn unique(self) -> Self {
        Self::from_iter(IndexSet::<_>::from_iter(self.vec))
    }

    pub fn no_version_managers(self) -> Self {
        self.vec
            .into_iter()
            .filter(|p| !p.ends_with(".pyenv/shims") && !p.ends_with(".rbenv/shims"))
            .collect()
    }

    pub fn push_front<T: Into<PathBuf>>(&mut self, path: T) {
        self.vec.push_front(path.into())
    }

    #[allow(dead_code)]
    pub fn push_back<T: Into<PathBuf>>(&mut self, path: T) {
        self.vec.push_back(path.into())
    }

    pub fn parse<T: AsRef<OsStr>>(input: T) -> Self {
        env::split_paths(input.as_ref())
            .filter(|p| p.len() > 0)
            .collect()
    }

    pub fn new() -> Self {
        Self {
            vec: VecDeque::new(),
        }
    }
}

impl FromIterator<PathBuf> for PathVec {
    fn from_iter<T: IntoIterator<Item = PathBuf>>(iter: T) -> Self {
        Self {
            vec: FromIterator::from_iter(iter),
        }
    }
}

impl IntoIterator for PathVec {
    type Item = PathBuf;
    type IntoIter = std::collections::vec_deque::IntoIter<PathBuf>;

    fn into_iter(self) -> Self::IntoIter {
        self.vec.into_iter()
    }
}

#[cfg(test)]
mod tests {
    // Note this useful idiom: importing names from outer (for mod tests) scope.
    use super::*;

    const FOO: &str = "/foo";
    const BAR: &str = "/bar";

    #[test]
    fn test() {
        // no item
        let ps = PathVec::parse(OsString::new());
        let actual = ps.make();
        assert_eq!(actual, "");

        // no item add one to front
        let mut ps = PathVec::parse(OsString::new());
        ps.push_front(FOO.to_string());
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // no item add one to back
        let mut ps = PathVec::parse(OsString::new());
        ps.push_back(FOO.to_string());
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // no item add two items to back
        let mut ps = PathVec::parse(OsString::new());
        ps.push_back(FOO.to_string());
        ps.push_back(BAR.to_string());
        let actual = ps.make();
        let expected = OsString::from(format!("{}:{}", FOO, BAR));
        assert_eq!(actual, expected);

        // one item
        let ps = PathVec::parse(OsString::from(FOO));
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // should fix following cases
        let ps = PathVec::parse(OsString::from(":/foo"));
        let actual = ps.make();
        assert_eq!(actual, "/foo");
        let ps = PathVec::parse(OsString::from("/foo:"));
        let actual = ps.make();
        assert_eq!(actual, "/foo");

        // two items
        let input = OsString::from(format!("{}:{}", FOO, BAR));
        let ps = PathVec::parse(&input);
        let actual = ps.make();
        assert_eq!(actual, input);

        // move order correctly
        let input = OsString::from("/a:/b:/c");
        let mut ps = PathVec::parse(&input);
        ps.push_front("/c".to_string());
        let actual = ps.make();
        let expect = OsString::from("/c:/a:/b");
        assert_eq!(actual, expect);

        // remove pyenv, rbenv, and node path
        let input = OsString::from("/a:/home/.pyenv/shims:/home/.rbenv/shims");
        let ps = PathVec::parse(&input).no_version_managers();
        let actual = ps.make();
        assert_eq!(actual, OsString::from("/a"))
    }

    #[test]
    fn test_unique() {
        let input = OsString::from("/a:/b:/a");
        let ps = PathVec::parse(&input);
        let actual = ps.make();
        assert_eq!(actual, OsString::from("/a:/b"))
    }
}
<|endoftext|>


<commit_before>// Tests that one can't run a destructor twice with the repeated vector
// literal syntax.

struct Foo {
    x: int;

    drop {
        io::println("Goodbye!");
    }
}

fn main() {
    let a = Foo { x: 3 };
    let b = [ a, ..5 ];     //~ ERROR copying a noncopyable value
}

<commit_msg>test: Fix unused variable warning in repeat-to-run-dtor-twice.rs.<commit_after>// Tests that one can't run a destructor twice with the repeated vector
// literal syntax.

struct Foo {
    x: int;

    drop {
        io::println("Goodbye!");
    }
}

fn main() {
    let a = Foo { x: 3 };
    let _ = [ a, ..5 ];     //~ ERROR copying a noncopyable value
}

<|endoftext|>


<commit_before>use camera;
use color::{Color3, Color4};
use gl::types::*;
use nalgebra::{Vec2, Pnt3};
use light::{Light, set_point_light, set_ambient_light};
use std::iter::repeat;
use terrain::terrain_block::{BlockPosition, TerrainBlock};
use vertex::{ColoredVertex, TextureVertex};
use view::View;
use world::EntityId;

// TODO: Make the view updates resemble updates that would come from a server.
#[derive(Clone)]
pub enum ViewUpdate {
  PushHudTriangles(Vec<ColoredVertex>),
  PushTextTriangles(Vec<TextureVertex>),
  PushText((Color4<u8>, String)),
  PushMob((EntityId, Vec<ColoredVertex>)),
  UpdateMob((EntityId, Vec<ColoredVertex>)),
  SetPointLight(Light),
  SetAmbientLight(Color3<GLfloat>),
  SetBackgroundColor(Color3<GLfloat>),
  MoveCamera(Pnt3<GLfloat>),
  RotateCamera(Vec2<GLfloat>),
  RemoveTerrain(EntityId),
  PushBlock((BlockPosition, TerrainBlock, u32)),
  FreeBlock((BlockPosition, u32)),
}

impl ViewUpdate {
  pub fn apply(self, view: &mut View) {
    match self {
      ViewUpdate::PushHudTriangles(triangles) => {
        view.hud_triangles.bind(&mut view.gl);
        view.hud_triangles.push(&mut view.gl, triangles.as_slice());
      },
      ViewUpdate::PushTextTriangles(triangles) => {
        view.text_triangles.bind(&mut view.gl);
        view.text_triangles.push(&mut view.gl, triangles.as_slice());
      },
      ViewUpdate::PushText((color, s)) => {
        view.fontloader.sans.render(
          &view.gl,
          s.as_slice(),
          color,
        );
      },
      ViewUpdate::PushMob((id, triangles)) => {
        view.mob_buffers.push(&mut view.gl, id, triangles.as_slice());
      },
      ViewUpdate::UpdateMob((id, triangles)) => {
        view.mob_buffers.update(&mut view.gl, id, triangles.as_slice());
      },
      ViewUpdate::SetPointLight(light) => {
        set_point_light(
          &mut view.shaders.terrain_shader.shader,
          &mut view.gl,
          &light,
        );
      },
      ViewUpdate::SetAmbientLight(color) => {
        set_ambient_light(
          &mut view.shaders.terrain_shader.shader,
          &mut view.gl,
          color,
        );
      },
      ViewUpdate::SetBackgroundColor(color) => {
        view.gl.set_background_color(color.r, color.g, color.b, 1.0);
      },
      ViewUpdate::MoveCamera(pos) => {
        view.camera.translation = camera::translation(-pos.to_vec());
      },
      ViewUpdate::RotateCamera(rot) => {
        view.rotate_lateral(rot.x);
        view.rotate_vertical(rot.y);
      },
      ViewUpdate::RemoveTerrain(id) => {
        view.terrain_buffers.swap_remove(&mut view.gl, id);
      },
      ViewUpdate::PushBlock((block_position, block, lod)) => {
        if !block.ids.is_empty() {
          let block_index =
            view.terrain_buffers.push_block_data(
              &mut view.gl,
              block_position,
              block.pixels.as_slice(),
              lod,
            );

          let block_indices: Vec<_> =
            repeat(block_index).take(block.ids.len()).collect();

          view.terrain_buffers.push(
            &mut view.gl,
            block.vertex_coordinates.as_slice(),
            block.normals.as_slice(),
            block.coords.as_slice(),
            block_indices.as_slice(),
            block.ids.as_slice(),
          );
        }
      },
      ViewUpdate::FreeBlock((block_position, lod)) => {
        view.terrain_buffers.free_block_data(lod, &block_position);
      },
    };
  }
}

unsafe impl Send for ViewUpdate {}
<commit_msg>Fix text rendering.<commit_after>use camera;
use color::{Color3, Color4};
use gl::types::*;
use nalgebra::{Vec2, Pnt3};
use light::{Light, set_point_light, set_ambient_light};
use std::iter::repeat;
use terrain::terrain_block::{BlockPosition, TerrainBlock};
use vertex::{ColoredVertex, TextureVertex};
use view::View;
use world::EntityId;

// TODO: Make the view updates resemble updates that would come from a server.
#[derive(Clone)]
pub enum ViewUpdate {
  PushHudTriangles(Vec<ColoredVertex>),
  PushTextTriangles(Vec<TextureVertex>),
  PushText((Color4<u8>, String)),
  PushMob((EntityId, Vec<ColoredVertex>)),
  UpdateMob((EntityId, Vec<ColoredVertex>)),
  SetPointLight(Light),
  SetAmbientLight(Color3<GLfloat>),
  SetBackgroundColor(Color3<GLfloat>),
  MoveCamera(Pnt3<GLfloat>),
  RotateCamera(Vec2<GLfloat>),
  RemoveTerrain(EntityId),
  PushBlock((BlockPosition, TerrainBlock, u32)),
  FreeBlock((BlockPosition, u32)),
}

impl ViewUpdate {
  pub fn apply(self, view: &mut View) {
    match self {
      ViewUpdate::PushHudTriangles(triangles) => {
        view.hud_triangles.bind(&mut view.gl);
        view.hud_triangles.push(&mut view.gl, triangles.as_slice());
      },
      ViewUpdate::PushTextTriangles(triangles) => {
        view.text_triangles.bind(&mut view.gl);
        view.text_triangles.push(&mut view.gl, triangles.as_slice());
      },
      ViewUpdate::PushText((color, s)) => {
        let tex = view.fontloader.sans.render(
          &view.gl,
          s.as_slice(),
          color,
        );
        view.text_textures.push(tex);
      },
      ViewUpdate::PushMob((id, triangles)) => {
        view.mob_buffers.push(&mut view.gl, id, triangles.as_slice());
      },
      ViewUpdate::UpdateMob((id, triangles)) => {
        view.mob_buffers.update(&mut view.gl, id, triangles.as_slice());
      },
      ViewUpdate::SetPointLight(light) => {
        set_point_light(
          &mut view.shaders.terrain_shader.shader,
          &mut view.gl,
          &light,
        );
      },
      ViewUpdate::SetAmbientLight(color) => {
        set_ambient_light(
          &mut view.shaders.terrain_shader.shader,
          &mut view.gl,
          color,
        );
      },
      ViewUpdate::SetBackgroundColor(color) => {
        view.gl.set_background_color(color.r, color.g, color.b, 1.0);
      },
      ViewUpdate::MoveCamera(pos) => {
        view.camera.translation = camera::translation(-pos.to_vec());
      },
      ViewUpdate::RotateCamera(rot) => {
        view.rotate_lateral(rot.x);
        view.rotate_vertical(rot.y);
      },
      ViewUpdate::RemoveTerrain(id) => {
        view.terrain_buffers.swap_remove(&mut view.gl, id);
      },
      ViewUpdate::PushBlock((block_position, block, lod)) => {
        if !block.ids.is_empty() {
          let block_index =
            view.terrain_buffers.push_block_data(
              &mut view.gl,
              block_position,
              block.pixels.as_slice(),
              lod,
            );

          let block_indices: Vec<_> =
            repeat(block_index).take(block.ids.len()).collect();

          view.terrain_buffers.push(
            &mut view.gl,
            block.vertex_coordinates.as_slice(),
            block.normals.as_slice(),
            block.coords.as_slice(),
            block_indices.as_slice(),
            block.ids.as_slice(),
          );
        }
      },
      ViewUpdate::FreeBlock((block_position, lod)) => {
        view.terrain_buffers.free_block_data(lod, &block_position);
      },
    };
  }
}

unsafe impl Send for ViewUpdate {}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2014 Kashyap
//
// 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.

pub fn earlyinit () {
	super::x86asm::outb(0x3f8+2 , 0);
	super::x86asm::outb(0x3f8+3, 0x80);    // Unlock divisor
	super::x86asm::outb(0x3f8+0, 12);
	super::x86asm::outb(0x3f8+1, 0);
	super::x86asm::outb(0x3f8+3, 0x03);    // Lock divisor, 8 data bits.
	super::x86asm::outb(0x3f8+4, 0);
	super::x86asm::outb(0x3f8+1, 0x01);    // Enable receive interrupts.

	let r = super::x86asm::inb(0x3f8+5);

	super::x86asm::outb(0x3f8, 65);
}
<commit_msg>added a const COM1<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2014 Kashyap
//
// 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.

const COM1 : u16 = 0x3f8;

pub fn earlyinit () {
	super::x86asm::outb(COM1+2 , 0);
	super::x86asm::outb(COM1+3, 0x80);    // Unlock divisor
	super::x86asm::outb(COM1+0, 12);
	super::x86asm::outb(COM1+1, 0);
	super::x86asm::outb(COM1+3, 0x03);    // Lock divisor, 8 data bits.
	super::x86asm::outb(COM1+4, 0);
	super::x86asm::outb(COM1+1, 0x01);    // Enable receive interrupts.

	let r = super::x86asm::inb(COM1+5);

	super::x86asm::outb(COM1, 65);
}
<|endoftext|>


<commit_before>use std;
use std::ffi::CString;
use gl;
use gl::types::{GLint, GLuint};
use super::vertex::Attrib;

/// Encapsulates an OpenGL shader.
///
/// The shader may be a vertex or fragment shader.
pub struct Shader {
    pub id: GLuint
}
impl Drop for Shader {
    /// Deletes the shader (`glDeleteShader()`)
    fn drop(&mut self) {
        unsafe { gl::DeleteShader(self.id) };
    }
}
impl Shader {
    /// Compiles a vertex shader from source.
    pub fn vertex_from_source(source: &str) -> Result<Shader, String> {
        Shader::from_source(source, gl::VERTEX_SHADER)
    }

    /// Compiles a fragment shader from source.
    pub fn fragment_from_source(source: &str) -> Result<Shader, String> {
        Shader::from_source(source, gl::FRAGMENT_SHADER)
    }

    fn from_source(source: &str, shader_type: GLuint) -> Result<Shader, String> {
        let shader = Shader {
            id: unsafe { gl::CreateShader(shader_type) }
        };
        unsafe {
            let c_source = CString::from_slice(source.as_bytes());
            let ptr = c_source.as_slice_with_nul().as_ptr();
            gl::ShaderSource(shader.id, 1, &ptr, std::ptr::null());
        }

        let successful = unsafe {
            gl::CompileShader(shader.id);

            let mut result: GLint = 0;
            gl::GetShaderiv(shader.id, gl::COMPILE_STATUS, &mut result);
            result != 0
        };

        if successful {
            Ok(shader)
        } else {
            Err(shader.get_compilation_log())
        }
    }

    fn get_compilation_log(&self) -> String {
        let mut len = 0;
        unsafe { gl::GetShaderiv(self.id, gl::INFO_LOG_LENGTH, &mut len) };
        assert!(len > 0);

        let mut buf = Vec::with_capacity(len as usize);
        let buf_ptr = buf.as_mut_slice().as_mut_ptr() as *mut gl::types::GLchar;
        unsafe {
            gl::GetShaderInfoLog(self.id, len, std::ptr::null_mut(), buf_ptr);
            buf.set_len(len as usize);
        };

        match String::from_utf8(buf) {
            Ok(log) => log,
            Err(vec) => panic!("Could not convert compilation log from buffer: {}", vec)
        }
    }
}

/// Encapsulates an OpenGL shader program.
pub struct Program {
    pub name: String,
    pub id: GLuint
}
impl Drop for Program {
    /// Deletes the program (`glDeleteProgram()`)
    fn drop(&mut self) {
        unsafe { gl::DeleteProgram(self.id) };
    }
}
impl Program {
    /// Links a new program with the provided shaders.
    ///
    /// Uses `glAttachShader()` and `glLinkProgram()`
    pub fn link(name: String, shaders: &[&Shader]) -> Result<Program, String> {
        let program = Program {
            name: name,
            id: unsafe { gl::CreateProgram() }
        };

        let successful: bool;

        unsafe {
            for shader in shaders.iter() {
                gl::AttachShader(program.id, shader.id);
            }
            gl::LinkProgram(program.id);

            successful = {
                let mut result: GLint = 0;
                gl::GetProgramiv(program.id, gl::LINK_STATUS, &mut result);
                result != 0
            };
        }

        if successful {
            Ok(program)
        } else {
            Err(program.get_link_log())
        }
    }

    /// Calls `glUseProgram()` and then calls the `cb` closure, which is
    /// sent a context for assigning program uniforms.
    pub fn use_program<F>(&self, cb: F) where
        F: FnOnce(ProgramUniformContext)
    {
        unsafe { gl::UseProgram(self.id) };
        cb(ProgramUniformContext);
    }

    pub fn get_attrib(&self, name: &str) -> Attrib {
        let c_name = CString::from_slice(name.as_bytes());
        let ptr = c_name.as_ptr();
        match unsafe { gl::GetAttribLocation(self.id, ptr) } {
            -1 => panic!("Could not find attribute \"{}\" in shader program \"{}\"", name, self.name),
            attr => Attrib { id: attr as GLuint }
        }
    }

    pub fn get_uniform(&self, name: &str) -> Uniform {
        match self.get_uniform_option(name) {
            Some(uniform) => uniform,
            None => panic!("Could not find uniform \"{}\" in shader program \"{}\"", name, self.name)
        }
    }

    pub fn get_uniform_option(&self, name: &str) -> Option<Uniform> {
        let c_name = CString::from_slice(name.as_bytes());
        let ptr = c_name.as_ptr();
        match unsafe { gl::GetUniformLocation(self.id, ptr) } {
            -1 => None,
            id => Some(Uniform { id: id })
        }
    }

    fn get_link_log(&self) -> String {
        let mut len = 0;
        unsafe { gl::GetProgramiv(self.id, gl::INFO_LOG_LENGTH, &mut len) };
        assert!(len > 0);

        let mut buf = Vec::with_capacity(len as usize);
        let buf_ptr = buf.as_mut_slice().as_mut_ptr() as *mut gl::types::GLchar;
        unsafe {
            gl::GetProgramInfoLog(self.id, len, std::ptr::null_mut(), buf_ptr);
            buf.set_len(len as usize);
        };

        match String::from_utf8(buf) {
            Ok(log) => log,
            Err(vec) => panic!("Could not convert link log from buffer: {}", vec)
        }
    }
}

/// ProgramUniformContext represents a valid context for assigning Program uniforms
///
/// The motivation for `ProgramUniformContext` is to limit access to Program
/// uniform setters for once a Program is in use.
/// The `glUniform...()` functions must be called after a `glUseProgram()`.
/// It's easy to invoke OpenGL functions in the wrong order, so this is a way
/// to enforce the correct order.
pub struct ProgramUniformContext;
impl ProgramUniformContext {
    /// Corresponds to `glUniform1i()`
    pub fn set_i32(&self, u: Uniform, v: i32) { unsafe { gl::Uniform1i(u.id, v); }; }
    /// Corresponds to `glUniform1f()`
    pub fn set_float(&self, u: Uniform, v: f32) { unsafe { gl::Uniform1f(u.id, v); }; }
    /// Corresponds with `glUniform1i()`
    pub fn set_bool(&self, u: Uniform, v: bool) {
        unsafe { gl::Uniform1i(u.id, match v { true => 1, false => 0 } ); };
    }

    /// Corresponds to `glUniform3f()`
    pub fn set_vec3(&self, u: Uniform, v: (f32,f32,f32)) {
        let (x,y,z) = v;
        unsafe { gl::Uniform3f(u.id, x,y,z); };
    }

    /// Corresponds to `glUniformMatrix4fv()`
    pub fn set_mat4(&self, u: Uniform, mat: &[[f32; 4]; 4]) {
        unsafe {
            let ptr: *const f32 = std::mem::transmute(mat);
            gl::UniformMatrix4fv(u.id, 1, gl::FALSE, ptr);
        };
    }
}

/// Encapsulates an OpenGL program uniform.
#[derive(Copy)]
pub struct Uniform {
    pub id: GLint
}
<commit_msg>Don't use CString<commit_after>use std;
use std::ffi::CString;
use gl;
use gl::types::{GLint, GLuint};
use super::vertex::Attrib;

/// Encapsulates an OpenGL shader.
///
/// The shader may be a vertex or fragment shader.
pub struct Shader {
    pub id: GLuint
}
impl Drop for Shader {
    /// Deletes the shader (`glDeleteShader()`)
    fn drop(&mut self) {
        unsafe { gl::DeleteShader(self.id) };
    }
}
impl Shader {
    /// Compiles a vertex shader from source.
    pub fn vertex_from_source(source: &str) -> Result<Shader, String> {
        Shader::from_source(source, gl::VERTEX_SHADER)
    }

    /// Compiles a fragment shader from source.
    pub fn fragment_from_source(source: &str) -> Result<Shader, String> {
        Shader::from_source(source, gl::FRAGMENT_SHADER)
    }

    fn from_source(source: &str, shader_type: GLuint) -> Result<Shader, String> {
        let shader = Shader {
            id: unsafe { gl::CreateShader(shader_type) }
        };
        unsafe {
            let ptr: *const u8 = source.as_bytes().as_ptr();
            let ptr_i8: *const i8 = std::mem::transmute(ptr);
            let len = source.len() as GLint;
            gl::ShaderSource(shader.id, 1, &ptr_i8, &len);
        }

        let successful = unsafe {
            gl::CompileShader(shader.id);

            let mut result: GLint = 0;
            gl::GetShaderiv(shader.id, gl::COMPILE_STATUS, &mut result);
            result != 0
        };

        if successful {
            Ok(shader)
        } else {
            Err(shader.get_compilation_log())
        }
    }

    fn get_compilation_log(&self) -> String {
        let mut len = 0;
        unsafe { gl::GetShaderiv(self.id, gl::INFO_LOG_LENGTH, &mut len) };
        assert!(len > 0);

        let mut buf = Vec::with_capacity(len as usize);
        let buf_ptr = buf.as_mut_slice().as_mut_ptr() as *mut gl::types::GLchar;
        unsafe {
            gl::GetShaderInfoLog(self.id, len, std::ptr::null_mut(), buf_ptr);
            buf.set_len(len as usize);
        };

        match String::from_utf8(buf) {
            Ok(log) => log,
            Err(vec) => panic!("Could not convert compilation log from buffer: {}", vec)
        }
    }
}

/// Encapsulates an OpenGL shader program.
pub struct Program {
    pub name: String,
    pub id: GLuint
}
impl Drop for Program {
    /// Deletes the program (`glDeleteProgram()`)
    fn drop(&mut self) {
        unsafe { gl::DeleteProgram(self.id) };
    }
}
impl Program {
    /// Links a new program with the provided shaders.
    ///
    /// Uses `glAttachShader()` and `glLinkProgram()`
    pub fn link(name: String, shaders: &[&Shader]) -> Result<Program, String> {
        let program = Program {
            name: name,
            id: unsafe { gl::CreateProgram() }
        };

        let successful: bool;

        unsafe {
            for shader in shaders.iter() {
                gl::AttachShader(program.id, shader.id);
            }
            gl::LinkProgram(program.id);

            successful = {
                let mut result: GLint = 0;
                gl::GetProgramiv(program.id, gl::LINK_STATUS, &mut result);
                result != 0
            };
        }

        if successful {
            Ok(program)
        } else {
            Err(program.get_link_log())
        }
    }

    /// Calls `glUseProgram()` and then calls the `cb` closure, which is
    /// sent a context for assigning program uniforms.
    pub fn use_program<F>(&self, cb: F) where
        F: FnOnce(ProgramUniformContext)
    {
        unsafe { gl::UseProgram(self.id) };
        cb(ProgramUniformContext);
    }

    pub fn get_attrib(&self, name: &str) -> Attrib {
        let c_name = CString::from_slice(name.as_bytes());
        let ptr = c_name.as_ptr();
        match unsafe { gl::GetAttribLocation(self.id, ptr) } {
            -1 => panic!("Could not find attribute \"{}\" in shader program \"{}\"", name, self.name),
            attr => Attrib { id: attr as GLuint }
        }
    }

    pub fn get_uniform(&self, name: &str) -> Uniform {
        match self.get_uniform_option(name) {
            Some(uniform) => uniform,
            None => panic!("Could not find uniform \"{}\" in shader program \"{}\"", name, self.name)
        }
    }

    pub fn get_uniform_option(&self, name: &str) -> Option<Uniform> {
        let c_name = CString::from_slice(name.as_bytes());
        let ptr = c_name.as_ptr();
        match unsafe { gl::GetUniformLocation(self.id, ptr) } {
            -1 => None,
            id => Some(Uniform { id: id })
        }
    }

    fn get_link_log(&self) -> String {
        let mut len = 0;
        unsafe { gl::GetProgramiv(self.id, gl::INFO_LOG_LENGTH, &mut len) };
        assert!(len > 0);

        let mut buf = Vec::with_capacity(len as usize);
        let buf_ptr = buf.as_mut_slice().as_mut_ptr() as *mut gl::types::GLchar;
        unsafe {
            gl::GetProgramInfoLog(self.id, len, std::ptr::null_mut(), buf_ptr);
            buf.set_len(len as usize);
        };

        match String::from_utf8(buf) {
            Ok(log) => log,
            Err(vec) => panic!("Could not convert link log from buffer: {}", vec)
        }
    }
}

/// ProgramUniformContext represents a valid context for assigning Program uniforms
///
/// The motivation for `ProgramUniformContext` is to limit access to Program
/// uniform setters for once a Program is in use.
/// The `glUniform...()` functions must be called after a `glUseProgram()`.
/// It's easy to invoke OpenGL functions in the wrong order, so this is a way
/// to enforce the correct order.
pub struct ProgramUniformContext;
impl ProgramUniformContext {
    /// Corresponds to `glUniform1i()`
    pub fn set_i32(&self, u: Uniform, v: i32) { unsafe { gl::Uniform1i(u.id, v); }; }
    /// Corresponds to `glUniform1f()`
    pub fn set_float(&self, u: Uniform, v: f32) { unsafe { gl::Uniform1f(u.id, v); }; }
    /// Corresponds with `glUniform1i()`
    pub fn set_bool(&self, u: Uniform, v: bool) {
        unsafe { gl::Uniform1i(u.id, match v { true => 1, false => 0 } ); };
    }

    /// Corresponds to `glUniform3f()`
    pub fn set_vec3(&self, u: Uniform, v: (f32,f32,f32)) {
        let (x,y,z) = v;
        unsafe { gl::Uniform3f(u.id, x,y,z); };
    }

    /// Corresponds to `glUniformMatrix4fv()`
    pub fn set_mat4(&self, u: Uniform, mat: &[[f32; 4]; 4]) {
        unsafe {
            let ptr: *const f32 = std::mem::transmute(mat);
            gl::UniformMatrix4fv(u.id, 1, gl::FALSE, ptr);
        };
    }
}

/// Encapsulates an OpenGL program uniform.
#[derive(Copy)]
pub struct Uniform {
    pub id: GLint
}
<|endoftext|>


<commit_before>use super::nif_interface;
use super::nif_interface::{ NIF_ENV, NIF_TERM };
use std::mem;

pub fn get_map_value(env: NIF_ENV, map: NIF_TERM, key: NIF_TERM) -> Option<NIF_TERM> {
    let mut result: NIF_TERM = unsafe { mem::uninitialized() };
    let success = unsafe { nif_interface::enif_get_map_value(env, map, key, &mut result as *mut NIF_TERM) };

    if success != 1 {
        return None;
    }
    Some(result)
}

pub fn get_map_size(env: NIF_ENV, map: NIF_TERM) -> Option<u64> {
    let mut size: nif_interface::size_t = unsafe { mem::uninitialized() };
    let success = unsafe { nif_interface::enif_get_map_size(env, map, &mut size as *mut nif_interface::size_t) };

    if success != 1 {
        return None;
    }
    Some(size)
}

pub fn map_new(env: NIF_ENV) -> NIF_TERM {
    unsafe { nif_interface::enif_make_new_map(env) }
}

pub fn map_put(env: NIF_ENV, map: NIF_TERM, key: NIF_TERM, value: NIF_TERM) -> Option<NIF_TERM> {
    let mut result: NIF_TERM = unsafe { mem::uninitialized() };
    let success = unsafe { nif_interface::enif_make_map_put(env, map, key, value, &mut result as *mut NIF_TERM) };

    if success != 1 {
        return None;
    }
    Some(result)
}
<commit_msg>fix compile error<commit_after>use super::nif_interface;
use super::nif_interface::{ NIF_ENV, NIF_TERM };
use std::mem;

pub fn get_map_value(env: NIF_ENV, map: NIF_TERM, key: NIF_TERM) -> Option<NIF_TERM> {
    let mut result: NIF_TERM = unsafe { mem::uninitialized() };
    let success = unsafe { nif_interface::enif_get_map_value(env, map, key, &mut result as *mut NIF_TERM) };

    if success != 1 {
        return None;
    }
    Some(result)
}

pub fn get_map_size(env: NIF_ENV, map: NIF_TERM) -> Option<usize> {
    let mut size: nif_interface::size_t = unsafe { mem::uninitialized() };
    let success = unsafe { nif_interface::enif_get_map_size(env, map, &mut size as *mut nif_interface::size_t) };

    if success != 1 {
        return None;
    }
    Some(size)
}

pub fn map_new(env: NIF_ENV) -> NIF_TERM {
    unsafe { nif_interface::enif_make_new_map(env) }
}

pub fn map_put(env: NIF_ENV, map: NIF_TERM, key: NIF_TERM, value: NIF_TERM) -> Option<NIF_TERM> {
    let mut result: NIF_TERM = unsafe { mem::uninitialized() };
    let success = unsafe { nif_interface::enif_make_map_put(env, map, key, value, &mut result as *mut NIF_TERM) };

    if success != 1 {
        return None;
    }
    Some(result)
}
<|endoftext|>


<commit_before>use sys;
use bullet_vector3::BulletVector3;
use collision::collision_shapes::Shape;
use mint::{Vector3, Vector4};

#[repr(u8)]
pub enum ActivationState {
    /// Means active so that the object having the state could be moved in a step simulation.
    /// This is the "normal" state for an object to be in.
    /// Use btCollisionObject::activate() to activate an object,
    /// not btCollisionObject::setActivationState(ACTIVATE_TAG),
    /// or it may get disabled again right away, as the deactivation timer has not been reset.
    ActiveTag = 1,
    /// Makes a body active forever, used for something like a player-controlled object.
    DisableDeactivation = 4,
    /// Making a body deactivated forever.
    DisableSimulation = 5,
    /// Means the body, and it's island, are asleep, since Bullet sleeps objects per-island. You probably don't want or need to set this one manually.
    IslandSleeping = 2,
    /// Means that it's an active object trying to fall asleep,
    /// and Bullet is keeping an eye on its velocity for the next few frames
    /// to see if it's a good candidate.
    /// You probably don't want or need to set this one manually.
    WantsDeactivation = 3,
}

pub struct RigidBody {
    rigid_body: Box<sys::btRigidBody>,
    shape: Box<Shape>,
    motion_state: Box<sys::btDefaultMotionState>,
    construction_info: Box<sys::btRigidBody_btRigidBodyConstructionInfo>,
}

impl RigidBody {
    pub fn new<T1: Into<Vector3<f64>>, T2: Into<Vector3<f64>>, T3: Into<Vector4<f64>>>(
        mass: f64,
        inertia: T1,
        shape: Shape,
        translation: T2,
        orientation: T3,
    ) -> RigidBody {
        let mut inertia: BulletVector3 = inertia.into().into();
        let shape_box = Box::new(shape);
        let translation: BulletVector3 = translation.into().into();
        let orientation: [f64; 4] = orientation.into().into();
        let transform = unsafe {
            sys::btTransform::new1(
                &orientation as *const _ as *const _,
                &translation as *const _ as *const _,
            )
        };
        let mut motion_state_box = Box::new(unsafe {
            sys::btDefaultMotionState::new(&transform as *const _, sys::btTransform::getIdentity())
        });

        let construction_info_box = Box::new(unsafe {
            sys::btRigidBody_btRigidBodyConstructionInfo::new(
                mass,
                &mut *motion_state_box as *mut _ as *mut _,
                shape_box.as_ptr(),
                inertia.0.as_mut_ptr() as *mut _,
            )
        });
        RigidBody {
            rigid_body: Box::new(unsafe {
                sys::btRigidBody::new(&*construction_info_box as *const _)
            }),
            shape: shape_box,
            motion_state: motion_state_box,
            construction_info: construction_info_box,
        }
    }

    pub(crate) unsafe fn motion_state_ptr(&self) -> *mut sys::btDefaultMotionState {
        &*self.motion_state as *const _ as *mut _
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut sys::btRigidBody {
        &*self.rigid_body as *const _ as *mut _
    }
}

impl Drop for RigidBody {
    fn drop(&mut self) {
        unsafe {
            ::sys::btMotionState_btMotionState_destructor(
                &mut *self.motion_state as *mut _ as *mut _,
            );
            ::sys::btRigidBody_btRigidBody_destructor(&mut *self.rigid_body as *mut _);
        }
    }
}

#[derive(Clone)]
pub struct RigidBodyHandle {
    pub(in dynamics) ptr: *mut sys::btRigidBody,
    motion_state: *mut sys::btDefaultMotionState,
    temp_transform: sys::btTransform,
}

impl RigidBodyHandle {
    pub fn new(ptr: *mut sys::btRigidBody, motion_state: *mut sys::btDefaultMotionState) -> Self {
        let temp_transform = unsafe { sys::btTransform::new() };

        RigidBodyHandle {
            ptr,
            motion_state,
            temp_transform,
        }
    }
    pub fn set_restitution(&mut self, restitution: f64) {
        unsafe {
            sys::btCollisionObject_setRestitution(self.ptr as *mut _, restitution);
        }
    }
    pub fn set_friction(&mut self, friction: f64) {
        unsafe {
            sys::btCollisionObject_setFriction(self.ptr as *mut _, friction);
        }
    }
    pub fn set_gravity<T: Into<Vector3<f64>>>(&mut self, gravity: T) {
        let gravity: BulletVector3 = gravity.into().into();
        unsafe {
            sys::btRigidBody_setGravity(self.ptr, gravity.0.as_ptr() as *const _);
        }
    }

    pub fn set_angular_factor<T: Into<Vector3<f64>>>(&mut self, angular_factor: T) {
        let angular_factor: BulletVector3 = angular_factor.into().into();
        unsafe {
            sys::btRigidBody_setAngularFactor(self.ptr, angular_factor.0.as_ptr() as *const _);
        }
    }

    pub fn set_sleeping_thresholds(&mut self, linear: f64, angular: f64) {
        unsafe { sys::btRigidBody_setSleepingThresholds(self.ptr, linear, angular) }
    }

    pub fn set_activation_state(&mut self, activation_state: ActivationState) {
        unsafe {
            sys::btCollisionObject_setActivationState(self.ptr as *mut _, activation_state as i32)
        }
    }

    pub fn apply_central_impulse<T: Into<Vector3<f64>>>(&mut self, impulse: T) {
        let impulse: BulletVector3 = impulse.into().into();
        unsafe {
            sys::btRigidBody_applyCentralImpulse(self.ptr, impulse.0.as_ptr() as *const _);
        }
    }

    pub fn get_linear_velocity(&self) -> Vector3<f64> {
        let velocity = unsafe { sys::btRigidBody_getLinearVelocity(self.ptr) };

        ::bullet_vector3::vector_from_slice(unsafe {
            ::std::slice::from_raw_parts(velocity as *const _, 4)
        })
    }

    /// Override velocity vector.
    pub fn reset_linear_velocity<T>(&mut self, velocity: T)
    where
        T: Into<Vector3<f64>>,
    {
        let velocity: BulletVector3 = velocity.into().into();
        unsafe {
            sys::btRigidBody_setLinearVelocity(self.ptr, velocity.0.as_ptr() as *const _);
        }
    }

    /// Override position vector and rotation quaternion.
    pub fn reset_position_and_orientation<T, T1>(&mut self, position: T, orientation: T1)
    where
        T: Into<Vector3<f64>>,
        T1: Into<Vector4<f64>>,
    {
        let orientation: [f64; 4] = orientation.into().into();
        let position: BulletVector3 = position.into().into();
        let transform = unsafe {
            sys::btTransform::new1(
                &orientation as *const _ as *const _,
                &position as *const _ as *const _,
            )
        };

        unsafe { (*self.ptr)._base.m_worldTransform = transform };
    }

    /// Get position in world space and orientation quaternion
    pub fn get_world_position_and_orientation(&self) -> (Vector3<f64>, Vector4<f64>) {
        unsafe {
            sys::btDefaultMotionState_getWorldTransform(
                &*self.motion_state as *const _ as *mut _,
                &self.temp_transform as *const _ as *mut _,
            );
        }
        let origin = unsafe { self.temp_transform.getOrigin1().as_ref().unwrap() };

        let rotation = unsafe { self.temp_transform.getRotation() };

        (
            ::bullet_vector3::vector_from_slice(&origin.m_floats[0..3]),
            ::bullet_vector3::vector4_from_slice(&rotation._base.m_floats),
        )
    }

    /// Place data on heap as a box and set to rigid body as user pointer
    pub fn set_user_data<T: 'static>(&mut self, data: T) {
        let data_box = Box::new(data);
        unsafe {
            sys::btCollisionObject_setUserPointer(
                self.ptr as *mut _,
                Box::into_raw(data_box) as *mut _,
            )
        };
    }

    /// Get data from rigidbody's user pointer
    /// Getting data from body without previously setted data is fine.
    /// Getting wrong typed data is unsafe and will cause mem::transmute to wrong pointer type.
    pub unsafe fn get_user_data<T: 'static>(&self) -> Option<&T> {
        let pointer = sys::btCollisionObject_getUserPointer(self.ptr as *mut _);
        let pointer: *const T = ::std::mem::transmute(pointer);
        return pointer.as_ref();
    }

    /// Set user index. This will not be used in bullet and this is not related to user_data.
    pub fn set_user_index(&mut self, index: i32) {
        unsafe { sys::btCollisionObject_setUserIndex(self.ptr as *mut _, index) };
    }

    /// Get previously setted user index
    /// If index was not set - will return "-1"
    pub fn get_user_index(&self) -> i32 {
        unsafe { sys::btCollisionObject_getUserIndex(self.ptr as *mut _) }
    }

    /// Was that rigid_body removed with DynamicsWorld::remove_body()
    /// Probably may return true also for any not-added bodys
    pub fn removed(&self) -> bool {
        unsafe { (*self.ptr)._base.m_worldArrayIndex == -1 }
    }
}
<commit_msg>fixed the way of setting rigid body position<commit_after>use sys;
use bullet_vector3::BulletVector3;
use collision::collision_shapes::Shape;
use mint::{Vector3, Vector4};

#[repr(u8)]
pub enum ActivationState {
    /// Means active so that the object having the state could be moved in a step simulation.
    /// This is the "normal" state for an object to be in.
    /// Use btCollisionObject::activate() to activate an object,
    /// not btCollisionObject::setActivationState(ACTIVATE_TAG),
    /// or it may get disabled again right away, as the deactivation timer has not been reset.
    ActiveTag = 1,
    /// Makes a body active forever, used for something like a player-controlled object.
    DisableDeactivation = 4,
    /// Making a body deactivated forever.
    DisableSimulation = 5,
    /// Means the body, and it's island, are asleep, since Bullet sleeps objects per-island. You probably don't want or need to set this one manually.
    IslandSleeping = 2,
    /// Means that it's an active object trying to fall asleep,
    /// and Bullet is keeping an eye on its velocity for the next few frames
    /// to see if it's a good candidate.
    /// You probably don't want or need to set this one manually.
    WantsDeactivation = 3,
}

pub struct RigidBody {
    rigid_body: Box<sys::btRigidBody>,
    shape: Box<Shape>,
    motion_state: Box<sys::btDefaultMotionState>,
    construction_info: Box<sys::btRigidBody_btRigidBodyConstructionInfo>,
}

impl RigidBody {
    pub fn new<T1: Into<Vector3<f64>>, T2: Into<Vector3<f64>>, T3: Into<Vector4<f64>>>(
        mass: f64,
        inertia: T1,
        shape: Shape,
        translation: T2,
        orientation: T3,
    ) -> RigidBody {
        let mut inertia: BulletVector3 = inertia.into().into();
        let shape_box = Box::new(shape);
        let translation: BulletVector3 = translation.into().into();
        let orientation: [f64; 4] = orientation.into().into();
        let transform = unsafe {
            sys::btTransform::new1(
                &orientation as *const _ as *const _,
                &translation as *const _ as *const _,
            )
        };
        let mut motion_state_box = Box::new(unsafe {
            sys::btDefaultMotionState::new(&transform as *const _, sys::btTransform::getIdentity())
        });

        let construction_info_box = Box::new(unsafe {
            sys::btRigidBody_btRigidBodyConstructionInfo::new(
                mass,
                &mut *motion_state_box as *mut _ as *mut _,
                shape_box.as_ptr(),
                inertia.0.as_mut_ptr() as *mut _,
            )
        });
        RigidBody {
            rigid_body: Box::new(unsafe {
                sys::btRigidBody::new(&*construction_info_box as *const _)
            }),
            shape: shape_box,
            motion_state: motion_state_box,
            construction_info: construction_info_box,
        }
    }

    pub(crate) unsafe fn motion_state_ptr(&self) -> *mut sys::btDefaultMotionState {
        &*self.motion_state as *const _ as *mut _
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut sys::btRigidBody {
        &*self.rigid_body as *const _ as *mut _
    }
}

impl Drop for RigidBody {
    fn drop(&mut self) {
        unsafe {
            ::sys::btMotionState_btMotionState_destructor(
                &mut *self.motion_state as *mut _ as *mut _,
            );
            ::sys::btRigidBody_btRigidBody_destructor(&mut *self.rigid_body as *mut _);
        }
    }
}

#[derive(Clone)]
pub struct RigidBodyHandle {
    pub(in dynamics) ptr: *mut sys::btRigidBody,
    motion_state: *mut sys::btDefaultMotionState,
    temp_transform: sys::btTransform,
}

impl RigidBodyHandle {
    pub fn new(ptr: *mut sys::btRigidBody, motion_state: *mut sys::btDefaultMotionState) -> Self {
        let temp_transform = unsafe { sys::btTransform::new() };

        RigidBodyHandle {
            ptr,
            motion_state,
            temp_transform,
        }
    }
    pub fn set_restitution(&mut self, restitution: f64) {
        unsafe {
            sys::btCollisionObject_setRestitution(self.ptr as *mut _, restitution);
        }
    }
    pub fn set_friction(&mut self, friction: f64) {
        unsafe {
            sys::btCollisionObject_setFriction(self.ptr as *mut _, friction);
        }
    }
    pub fn set_gravity<T: Into<Vector3<f64>>>(&mut self, gravity: T) {
        let gravity: BulletVector3 = gravity.into().into();
        unsafe {
            sys::btRigidBody_setGravity(self.ptr, gravity.0.as_ptr() as *const _);
        }
    }

    pub fn set_angular_factor<T: Into<Vector3<f64>>>(&mut self, angular_factor: T) {
        let angular_factor: BulletVector3 = angular_factor.into().into();
        unsafe {
            sys::btRigidBody_setAngularFactor(self.ptr, angular_factor.0.as_ptr() as *const _);
        }
    }

    pub fn set_sleeping_thresholds(&mut self, linear: f64, angular: f64) {
        unsafe { sys::btRigidBody_setSleepingThresholds(self.ptr, linear, angular) }
    }

    pub fn set_activation_state(&mut self, activation_state: ActivationState) {
        unsafe {
            sys::btCollisionObject_setActivationState(self.ptr as *mut _, activation_state as i32)
        }
    }

    pub fn apply_central_impulse<T: Into<Vector3<f64>>>(&mut self, impulse: T) {
        let impulse: BulletVector3 = impulse.into().into();
        unsafe {
            sys::btRigidBody_applyCentralImpulse(self.ptr, impulse.0.as_ptr() as *const _);
        }
    }

    pub fn get_linear_velocity(&self) -> Vector3<f64> {
        let velocity = unsafe { sys::btRigidBody_getLinearVelocity(self.ptr) };

        ::bullet_vector3::vector_from_slice(unsafe {
            ::std::slice::from_raw_parts(velocity as *const _, 4)
        })
    }

    /// Override velocity vector.
    pub fn reset_linear_velocity<T>(&mut self, velocity: T)
    where
        T: Into<Vector3<f64>>,
    {
        let velocity: BulletVector3 = velocity.into().into();
        unsafe {
            sys::btRigidBody_setLinearVelocity(self.ptr, velocity.0.as_ptr() as *const _);
        }
    }

    /// Override position vector and rotation quaternion.
    pub fn reset_position_and_orientation<T, T1>(&mut self, position: T, orientation: T1)
    where
        T: Into<Vector3<f64>>,
        T1: Into<Vector4<f64>>,
    {
        let orientation: [f64; 4] = orientation.into().into();
        let position: BulletVector3 = position.into().into();
        let transform = unsafe {
            sys::btTransform::new1(
                &orientation as *const _ as *const _,
                &position as *const _ as *const _,
            )
        };

        unsafe {
            sys::btDefaultMotionState_setWorldTransform(
                &*self.motion_state as *const _ as *mut _,
                &transform as *const _ as *const _,
            );
        }

        unsafe { (*self.ptr)._base.m_worldTransform = transform };
    }

    /// Get position in world space and orientation quaternion
    pub fn get_world_position_and_orientation(&self) -> (Vector3<f64>, Vector4<f64>) {
        unsafe {
            sys::btDefaultMotionState_getWorldTransform(
                &*self.motion_state as *const _ as *mut _,
                &self.temp_transform as *const _ as *mut _,
            );
        }
        let origin = unsafe { self.temp_transform.getOrigin1().as_ref().unwrap() };

        let rotation = unsafe { self.temp_transform.getRotation() };

        (
            ::bullet_vector3::vector_from_slice(&origin.m_floats[0..3]),
            ::bullet_vector3::vector4_from_slice(&rotation._base.m_floats),
        )
    }

    /// Place data on heap as a box and set to rigid body as user pointer
    pub fn set_user_data<T: 'static>(&mut self, data: T) {
        let data_box = Box::new(data);
        unsafe {
            sys::btCollisionObject_setUserPointer(
                self.ptr as *mut _,
                Box::into_raw(data_box) as *mut _,
            )
        };
    }

    /// Get data from rigidbody's user pointer
    /// Getting data from body without previously setted data is fine.
    /// Getting wrong typed data is unsafe and will cause mem::transmute to wrong pointer type.
    pub unsafe fn get_user_data<T: 'static>(&self) -> Option<&T> {
        let pointer = sys::btCollisionObject_getUserPointer(self.ptr as *mut _);
        let pointer: *const T = ::std::mem::transmute(pointer);
        return pointer.as_ref();
    }

    /// Set user index. This will not be used in bullet and this is not related to user_data.
    pub fn set_user_index(&mut self, index: i32) {
        unsafe { sys::btCollisionObject_setUserIndex(self.ptr as *mut _, index) };
    }

    /// Get previously setted user index
    /// If index was not set - will return "-1"
    pub fn get_user_index(&self) -> i32 {
        unsafe { sys::btCollisionObject_getUserIndex(self.ptr as *mut _) }
    }

    /// Was that rigid_body removed with DynamicsWorld::remove_body()
    /// Probably may return true also for any not-added bodys
    pub fn removed(&self) -> bool {
        unsafe { (*self.ptr)._base.m_worldArrayIndex == -1 }
    }
}
<|endoftext|>