<commit_before>// Copyright 2017 Dmitry Tantsur <divius.inside@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Foundation bits exposing the Compute API.

use std::collections::HashMap;
use std::fmt::Debug;

use reqwest::{Method, Url};
use reqwest::header::Headers;
use serde::Serialize;
use serde_json;

use super::super::Result;
use super::super::auth::AuthMethod;
use super::super::common::{self, ApiVersion};
use super::super::common::protocol::Ref;
use super::super::session::{Session, ServiceInfo, ServiceType};
use super::super::utils::{self, ResultExt};
use super::protocol;

/// Extensions for Session.
pub trait V2API {
    /// Create a server.
    fn create_server(&self, request: protocol::ServerCreate) -> Result<Ref>;

    /// Delete a server.
    fn delete_server<S: AsRef<str>>(&self, id: S) -> Result<()>;

    /// Get a flavor by its ID.
    fn get_flavor_by_id<S: AsRef<str>>(&self, id: S) -> Result<protocol::Flavor>;

    /// Get a flavor by its name.
    fn get_flavor_by_name<S: AsRef<str>>(&self, name: S) -> Result<protocol::Flavor>;

    /// Get a flavor.
    fn get_flavor<S: AsRef<str>>(&self, id_or_name: S) -> Result<protocol::Flavor> {
        let s = id_or_name.as_ref();
        self.get_flavor_by_id(s).if_not_found_then(|| self.get_flavor_by_name(s))
    }

    /// Get a server.
    fn get_server<S: AsRef<str>>(&self, id: S) -> Result<protocol::Server>;

    /// List flavors.
    fn list_flavors<Q: Serialize + Debug>(&self, query: &Q)
        -> Result<Vec<common::protocol::IdAndName>>;

    /// List flavors with details.
    fn list_flavors_detail<Q: Serialize + Debug>(&self, query: &Q)
        -> Result<Vec<protocol::Flavor>>;

    /// List servers.
    fn list_servers<Q: Serialize + Debug>(&self, query: &Q)
        -> Result<Vec<common::protocol::IdAndName>>;

    /// List servers with details.
    fn list_servers_detail<Q: Serialize + Debug>(&self, query: &Q)
        -> Result<Vec<protocol::Server>>;

    /// Run an action while providing some arguments.
    fn server_action_with_args<S1, S2, Q>(&self, id: S1, action: S2, args: Q)
        -> Result<()> where S1: AsRef<str>, S2: AsRef<str>, Q: Serialize + Debug;

    /// Run an action on the server.
    fn server_simple_action<S1, S2>(&self, id: S1, action: S2) -> Result<()>
            where S1: AsRef<str>, S2: AsRef<str> {
        self.server_action_with_args(id, action, serde_json::Value::Null)
    }
}

/// Service type of Compute API V2.
#[derive(Copy, Clone, Debug)]
pub struct V2;

const SERVICE_TYPE: &'static str = "compute";
const VERSION_ID: &'static str = "v2.1";

impl V2API for Session {
    fn create_server(&self, request: protocol::ServerCreate) -> Result<Ref> {
        debug!("Creating a server with {:?}", request);
        let body = protocol::ServerCreateRoot { server: request };
        let server = self.request::<V2>(Method::Post, &["servers"], None)?
            .json(&body).receive_json::<protocol::CreatedServerRoot>()?.server;
        trace!("Requested creation of server {:?}", server);
        Ok(server)
    }

    fn delete_server<S: AsRef<str>>(&self, id: S) -> Result<()> {
        trace!("Deleting server {}", id.as_ref());
        let _ = self.request::<V2>(Method::Delete,
                                   &["servers", id.as_ref()],
                                   None)?
            .send()?;
        debug!("Successfully requested deletion of server {}", id.as_ref());
        Ok(())
    }

    fn get_flavor_by_id<S: AsRef<str>>(&self, id: S) -> Result<protocol::Flavor> {
        trace!("Get compute flavor by ID {}", id.as_ref());
        let flavor = self.request::<V2>(Method::Get,
                                        &["flavors", id.as_ref()],
                                        None)?
           .receive_json::<protocol::FlavorRoot>()?.flavor;
        trace!("Received {:?}", flavor);
        Ok(flavor)
    }

    fn get_flavor_by_name<S: AsRef<str>>(&self, name: S) -> Result<protocol::Flavor> {
        trace!("Get compute flavor by name {}", name.as_ref());
        let items = self.request::<V2>(Method::Get, &["flavors"], None)?
            .receive_json::<protocol::FlavorsRoot>()?.flavors
            .into_iter().filter(|item| item.name == name.as_ref());
        utils::one(items, "Flavor with given name or ID not found",
                   "Too many flavors found with given name")
            .and_then(|item| self.get_flavor(item.id))
    }

    fn get_server<S: AsRef<str>>(&self, id: S) -> Result<protocol::Server> {
        trace!("Get compute server with ID {}", id.as_ref());
        let server = self.request::<V2>(Method::Get,
                                        &["servers", id.as_ref()],
                                        None)?
           .receive_json::<protocol::ServerRoot>()?.server;
        trace!("Received {:?}", server);
        Ok(server)
    }

    fn list_flavors<Q: Serialize + Debug>(&self, query: &Q)
            -> Result<Vec<common::protocol::IdAndName>> {
        trace!("Listing compute flavors with {:?}", query);
        let result = self.request::<V2>(Method::Get, &["flavors"], None)?
           .query(query).receive_json::<protocol::FlavorsRoot>()?.flavors;
        trace!("Received flavors: {:?}", result);
        Ok(result)
    }

    fn list_flavors_detail<Q: Serialize + Debug>(&self, query: &Q)
            -> Result<Vec<protocol::Flavor>> {
        trace!("Listing compute flavors with {:?}", query);
        let result = self.request::<V2>(Method::Get,
                                        &["flavors", "detail"],
                                        None)?
           .query(query).receive_json::<protocol::FlavorsDetailRoot>()?.flavors;
        trace!("Received flavors: {:?}", result);
        Ok(result)
    }

    fn list_servers<Q: Serialize + Debug>(&self, query: &Q)
            -> Result<Vec<common::protocol::IdAndName>> {
        trace!("Listing compute servers with {:?}", query);
        let result = self.request::<V2>(Method::Get, &["servers"], None)?
           .query(query).receive_json::<protocol::ServersRoot>()?.servers;
        trace!("Received servers: {:?}", result);
        Ok(result)
    }

    fn list_servers_detail<Q: Serialize + Debug>(&self, query: &Q)
            -> Result<Vec<protocol::Server>> {
        trace!("Listing compute servers with {:?}", query);
        let result = self.request::<V2>(Method::Get,
                                        &["servers", "detail"],
                                        None)?
           .query(query).receive_json::<protocol::ServersDetailRoot>()?.servers;
        trace!("Received servers: {:?}", result);
        Ok(result)
    }

    fn server_action_with_args<S1, S2, Q>(&self, id: S1, action: S2, args: Q)
            -> Result<()>
            where S1: AsRef<str>, S2: AsRef<str>, Q: Serialize + Debug {
        trace!("Running {} on server {} with args {:?}",
               action.as_ref(), id.as_ref(), args);
        let mut body = HashMap::new();
        let _ = body.insert(action.as_ref(), args);
        let _ = self.request::<V2>(Method::Post,
                                   &["servers", id.as_ref(), "action"],
                                   None)?
            .json(&body).send()?;
        debug!("Successfully ran {} on server {}", action.as_ref(), id.as_ref());
        Ok(())
    }
}

impl ServiceType for V2 {
    fn catalog_type() -> &'static str {
        SERVICE_TYPE
    }

    fn service_info(endpoint: Url, auth: &AuthMethod) -> Result<ServiceInfo> {
        common::protocol::fetch_service_info(endpoint, auth, SERVICE_TYPE, VERSION_ID)
    }

    fn api_version_headers(version: ApiVersion) -> Option<Headers> {
        let mut hdrs = Headers::new();
        // TODO: typed header, new-style header support
        hdrs.set_raw("x-openstack-nova-api-version", version.to_string());
        Some(hdrs)
    }
}
<commit_msg>fix(compute): potential infinite recursion in get_flavor<commit_after>// Copyright 2017 Dmitry Tantsur <divius.inside@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Foundation bits exposing the Compute API.

use std::collections::HashMap;
use std::fmt::Debug;

use reqwest::{Method, Url};
use reqwest::header::Headers;
use serde::Serialize;
use serde_json;

use super::super::Result;
use super::super::auth::AuthMethod;
use super::super::common::{self, ApiVersion};
use super::super::common::protocol::Ref;
use super::super::session::{Session, ServiceInfo, ServiceType};
use super::super::utils::{self, ResultExt};
use super::protocol;

/// Extensions for Session.
pub trait V2API {
    /// Create a server.
    fn create_server(&self, request: protocol::ServerCreate) -> Result<Ref>;

    /// Delete a server.
    fn delete_server<S: AsRef<str>>(&self, id: S) -> Result<()>;

    /// Get a flavor.
    fn get_flavor<S: AsRef<str>>(&self, id_or_name: S) -> Result<protocol::Flavor> {
        let s = id_or_name.as_ref();
        self.get_flavor_by_id(s).if_not_found_then(|| self.get_flavor_by_name(s))
    }

    /// Get a flavor by its ID.
    fn get_flavor_by_id<S: AsRef<str>>(&self, id: S) -> Result<protocol::Flavor>;

    /// Get a flavor by its name.
    fn get_flavor_by_name<S: AsRef<str>>(&self, name: S) -> Result<protocol::Flavor>;

    /// Get a server.
    fn get_server<S: AsRef<str>>(&self, id: S) -> Result<protocol::Server>;

    /// List flavors.
    fn list_flavors<Q: Serialize + Debug>(&self, query: &Q)
        -> Result<Vec<common::protocol::IdAndName>>;

    /// List flavors with details.
    fn list_flavors_detail<Q: Serialize + Debug>(&self, query: &Q)
        -> Result<Vec<protocol::Flavor>>;

    /// List servers.
    fn list_servers<Q: Serialize + Debug>(&self, query: &Q)
        -> Result<Vec<common::protocol::IdAndName>>;

    /// List servers with details.
    fn list_servers_detail<Q: Serialize + Debug>(&self, query: &Q)
        -> Result<Vec<protocol::Server>>;

    /// Run an action while providing some arguments.
    fn server_action_with_args<S1, S2, Q>(&self, id: S1, action: S2, args: Q)
        -> Result<()> where S1: AsRef<str>, S2: AsRef<str>, Q: Serialize + Debug;

    /// Run an action on the server.
    fn server_simple_action<S1, S2>(&self, id: S1, action: S2) -> Result<()>
            where S1: AsRef<str>, S2: AsRef<str> {
        self.server_action_with_args(id, action, serde_json::Value::Null)
    }
}

/// Service type of Compute API V2.
#[derive(Copy, Clone, Debug)]
pub struct V2;

const SERVICE_TYPE: &'static str = "compute";
const VERSION_ID: &'static str = "v2.1";

impl V2API for Session {
    fn create_server(&self, request: protocol::ServerCreate) -> Result<Ref> {
        debug!("Creating a server with {:?}", request);
        let body = protocol::ServerCreateRoot { server: request };
        let server = self.request::<V2>(Method::Post, &["servers"], None)?
            .json(&body).receive_json::<protocol::CreatedServerRoot>()?.server;
        trace!("Requested creation of server {:?}", server);
        Ok(server)
    }

    fn delete_server<S: AsRef<str>>(&self, id: S) -> Result<()> {
        trace!("Deleting server {}", id.as_ref());
        let _ = self.request::<V2>(Method::Delete,
                                   &["servers", id.as_ref()],
                                   None)?
            .send()?;
        debug!("Successfully requested deletion of server {}", id.as_ref());
        Ok(())
    }

    fn get_flavor_by_id<S: AsRef<str>>(&self, id: S) -> Result<protocol::Flavor> {
        trace!("Get compute flavor by ID {}", id.as_ref());
        let flavor = self.request::<V2>(Method::Get,
                                        &["flavors", id.as_ref()],
                                        None)?
           .receive_json::<protocol::FlavorRoot>()?.flavor;
        trace!("Received {:?}", flavor);
        Ok(flavor)
    }

    fn get_flavor_by_name<S: AsRef<str>>(&self, name: S) -> Result<protocol::Flavor> {
        trace!("Get compute flavor by name {}", name.as_ref());
        let items = self.request::<V2>(Method::Get, &["flavors"], None)?
            .receive_json::<protocol::FlavorsRoot>()?.flavors
            .into_iter().filter(|item| item.name == name.as_ref());
        utils::one(items, "Flavor with given name or ID not found",
                   "Too many flavors found with given name")
            .and_then(|item| self.get_flavor_by_id(item.id))
    }

    fn get_server<S: AsRef<str>>(&self, id: S) -> Result<protocol::Server> {
        trace!("Get compute server with ID {}", id.as_ref());
        let server = self.request::<V2>(Method::Get,
                                        &["servers", id.as_ref()],
                                        None)?
           .receive_json::<protocol::ServerRoot>()?.server;
        trace!("Received {:?}", server);
        Ok(server)
    }

    fn list_flavors<Q: Serialize + Debug>(&self, query: &Q)
            -> Result<Vec<common::protocol::IdAndName>> {
        trace!("Listing compute flavors with {:?}", query);
        let result = self.request::<V2>(Method::Get, &["flavors"], None)?
           .query(query).receive_json::<protocol::FlavorsRoot>()?.flavors;
        trace!("Received flavors: {:?}", result);
        Ok(result)
    }

    fn list_flavors_detail<Q: Serialize + Debug>(&self, query: &Q)
            -> Result<Vec<protocol::Flavor>> {
        trace!("Listing compute flavors with {:?}", query);
        let result = self.request::<V2>(Method::Get,
                                        &["flavors", "detail"],
                                        None)?
           .query(query).receive_json::<protocol::FlavorsDetailRoot>()?.flavors;
        trace!("Received flavors: {:?}", result);
        Ok(result)
    }

    fn list_servers<Q: Serialize + Debug>(&self, query: &Q)
            -> Result<Vec<common::protocol::IdAndName>> {
        trace!("Listing compute servers with {:?}", query);
        let result = self.request::<V2>(Method::Get, &["servers"], None)?
           .query(query).receive_json::<protocol::ServersRoot>()?.servers;
        trace!("Received servers: {:?}", result);
        Ok(result)
    }

    fn list_servers_detail<Q: Serialize + Debug>(&self, query: &Q)
            -> Result<Vec<protocol::Server>> {
        trace!("Listing compute servers with {:?}", query);
        let result = self.request::<V2>(Method::Get,
                                        &["servers", "detail"],
                                        None)?
           .query(query).receive_json::<protocol::ServersDetailRoot>()?.servers;
        trace!("Received servers: {:?}", result);
        Ok(result)
    }

    fn server_action_with_args<S1, S2, Q>(&self, id: S1, action: S2, args: Q)
            -> Result<()>
            where S1: AsRef<str>, S2: AsRef<str>, Q: Serialize + Debug {
        trace!("Running {} on server {} with args {:?}",
               action.as_ref(), id.as_ref(), args);
        let mut body = HashMap::new();
        let _ = body.insert(action.as_ref(), args);
        let _ = self.request::<V2>(Method::Post,
                                   &["servers", id.as_ref(), "action"],
                                   None)?
            .json(&body).send()?;
        debug!("Successfully ran {} on server {}", action.as_ref(), id.as_ref());
        Ok(())
    }
}

impl ServiceType for V2 {
    fn catalog_type() -> &'static str {
        SERVICE_TYPE
    }

    fn service_info(endpoint: Url, auth: &AuthMethod) -> Result<ServiceInfo> {
        common::protocol::fetch_service_info(endpoint, auth, SERVICE_TYPE, VERSION_ID)
    }

    fn api_version_headers(version: ApiVersion) -> Option<Headers> {
        let mut hdrs = Headers::new();
        // TODO: typed header, new-style header support
        hdrs.set_raw("x-openstack-nova-api-version", version.to_string());
        Some(hdrs)
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![deny(missing_docs)]

//! Low-level graphics abstraction for Rust. Mostly operates on data, not types.
//! Designed for use by libraries and higher-level abstractions only.

#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate log;
extern crate draw_state;
//extern crate num;

use std::fmt::Debug;
use std::hash::Hash;
use std::any::Any;

pub use draw_state::{state, target};
pub use self::factory::Factory;

pub mod buffer;
pub mod command;
pub mod dummy;
pub mod factory;
pub mod format;
pub mod handle;
pub mod mapping;
pub mod memory;
pub mod pso;
pub mod shade;
pub mod texture;

/// Compile-time maximum number of vertex attributes.
pub const MAX_VERTEX_ATTRIBUTES: usize = 16;
/// Compile-time maximum number of color targets.
pub const MAX_COLOR_TARGETS: usize = 4;
/// Compile-time maximum number of constant buffers.
pub const MAX_CONSTANT_BUFFERS: usize = 14;
/// Compile-time maximum number of shader resource views (SRV).
pub const MAX_RESOURCE_VIEWS: usize = 32;
/// Compile-time maximum number of unordered access views (UAV).
pub const MAX_UNORDERED_VIEWS: usize = 4;
/// Compile-time maximum number of samplers.
pub const MAX_SAMPLERS: usize = 16;

/// Draw vertex count.
pub type VertexCount = u32;
/// Draw number of instances
pub type InstanceCount = u32;
/// Number of vertices in a patch
pub type PatchSize = u8;

/// Slot for an attribute.
pub type AttributeSlot = u8;
/// Slot for a constant buffer object.
pub type ConstantBufferSlot = u8;
/// Slot for a shader resource view.
pub type ResourceViewSlot = u8;
/// Slot for an unordered access object.
pub type UnorderedViewSlot = u8;
/// Slot for an active color buffer.
pub type ColorSlot = u8;
/// Slot for a sampler.
pub type SamplerSlot = u8;

macro_rules! define_shaders {
    ($($name:ident),+) => {$(
        #[allow(missing_docs)]
        #[derive(Clone, Debug, Eq, Hash, PartialEq)]
        pub struct $name<R: Resources>(handle::Shader<R>);
        impl<R: Resources> $name<R> {
            #[allow(missing_docs)]
            pub fn reference(&self, man: &mut handle::Manager<R>) -> &R::Shader {
                man.ref_shader(&self.0)
            }
        }
    )+}
}

define_shaders!(VertexShader, HullShader, DomainShader, GeometryShader, PixelShader);

/// A complete set of shaders to link a program.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum ShaderSet<R: Resources> {
    /// Simple program: Vs-Ps
    Simple(VertexShader<R>, PixelShader<R>),
    /// Geometry shader programs: Vs-Gs-Ps
    Geometry(VertexShader<R>, GeometryShader<R>, PixelShader<R>),
    /// Tessellated TODO: Tessellated, TessellatedGeometry, TransformFeedback
    Tessellated(VertexShader<R>, HullShader<R>, DomainShader<R>, PixelShader<R>),

}

impl<R: Resources> ShaderSet<R> {
    /// Return the aggregated stage usage for the set.
    pub fn get_usage(&self) -> shade::Usage {
        match self {
            &ShaderSet::Simple(..) => shade::VERTEX | shade::PIXEL,
            &ShaderSet::Geometry(..) => shade::VERTEX | shade::GEOMETRY | shade::PIXEL,
            &ShaderSet::Tessellated(..) => shade::VERTEX | shade::HULL | shade::DOMAIN | shade::PIXEL,
        }
    }
}

//TODO: use the appropriate units for max vertex count, etc
/// Features that the device supports.
#[derive(Copy, Clone, Debug)]
#[allow(missing_docs)] // pretty self-explanatory fields!
pub struct Capabilities {
    pub max_vertex_count: usize,
    pub max_index_count: usize,
    pub max_texture_size: usize,
    pub max_patch_size: usize,

    pub instance_base_supported: bool,
    pub instance_call_supported: bool,
    pub instance_rate_supported: bool,
    pub vertex_base_supported: bool,
    pub srgb_color_supported: bool,
    pub constant_buffer_supported: bool,
    pub unordered_access_view_supported: bool,
    pub separate_blending_slots_supported: bool,
}

/// Describes what geometric primitives are created from vertex data.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
#[repr(u8)]
pub enum Primitive {
    /// Each vertex represents a single point.
    PointList,
    /// Each pair of vertices represent a single line segment. For example, with `[a, b, c, d,
    /// e]`, `a` and `b` form a line, `c` and `d` form a line, and `e` is discarded.
    LineList,
    /// Every two consecutive vertices represent a single line segment. Visually forms a "path" of
    /// lines, as they are all connected. For example, with `[a, b, c]`, `a` and `b` form a line
    /// line, and `b` and `c` form a line.
    LineStrip,
    /// Each triplet of vertices represent a single triangle. For example, with `[a, b, c, d, e]`,
    /// `a`, `b`, and `c` form a triangle, `d` and `e` are discarded.
    TriangleList,
    /// Every three consecutive vertices represent a single triangle. For example, with `[a, b, c,
    /// d]`, `a`, `b`, and `c` form a triangle, and `b`, `c`, and `d` form a triangle.
    TriangleStrip,
    /// Each quadtruplet of vertices represent a single line segment with adjacency information.
    /// For example, with `[a, b, c, d]`, `b` and `c` form a line, and `a` and `d` are the adjacent
    /// vertices.
    LineListAdjacency,
    /// Every four consecutive vertices represent a single line segment with adjacency information.
    /// For example, with `[a, b, c, d, e]`, `[a, b, c, d]` form a line segment with adjacency, and
    /// `[b, c, d, e]` form a line segment with adjacency.
    LineStripAdjacency,
    /// Each sextuplet of vertices represent a single traingle with adjacency information. For
    /// example, with `[a, b, c, d, e, f]`, `a`, `c`, and `e` form a traingle, and `b`, `d`, and
    /// `f` are the adjacent vertices, where `b` is adjacent to the edge formed by `a` and `c`, `d`
    /// is adjacent to the edge `c` and `e`, and `f` is adjacent to the edge `e` and `a`.
    TriangleListAdjacency,
    /// Every even-numbered vertex (every other starting from the first) represents an additional
    /// vertex for the triangle strip, while odd-numbered vertices (every other starting from the
    /// second) represent adjacent vertices. For example, with `[a, b, c, d, e, f, g, h]`, `[a, c,
    /// e, g]` form a triangle strip, and `[b, d, f, h]` are the adjacent vertices, where `b`, `d`,
    /// and `f` are adjacent to the first triangle in the strip, and `d`, `f`, and `h` are adjacent
    /// to the second.
    TriangleStripAdjacency,
    /// Patch list,
    /// used with shaders capable of producing primitives on their own (tessellation)
    PatchList(PatchSize),
}

/// A type of each index value in the slice's index buffer
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
#[allow(missing_docs)]
#[repr(u8)]
pub enum IndexType {
    U16,
    U32,
}

/// Different types of a specific API.
#[allow(missing_docs)]
pub trait Resources:          Clone + Hash + Debug + Eq + PartialEq + Any {
    type Buffer:              Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync + Copy;
    type Shader:              Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync;
    type Program:             Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync;
    type PipelineStateObject: Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync;
    type Texture:             Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync;
    type ShaderResourceView:  Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync + Copy;
    type UnorderedAccessView: Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync + Copy;
    type RenderTargetView:    Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync + Copy;
    type DepthStencilView:    Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync;
    type Sampler:             Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync + Copy;
    type Fence:               Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync;
    type Mapping:             Hash + Debug + Eq + PartialEq + Any + Send + Sync + mapping::Gate<Self>;
}

/// A `Device` is responsible for submitting `CommandBuffer`s to the GPU.
pub trait Device: Sized {
    /// Associated `Resources` type.
    type Resources: Resources;
    /// Associated `CommandBuffer` type. Every `Device` type can only work with one `CommandBuffer`
    /// type.
    type CommandBuffer: command::Buffer<Self::Resources>;

    /// Returns the capabilities of this `Ðevice`.
    fn get_capabilities(&self) -> &Capabilities;

    /// Pin everything from this handle manager to live for a frame.
    fn pin_submitted_resources(&mut self, &handle::Manager<Self::Resources>);

    /// Submits a `CommandBuffer` to the GPU for execution.

    fn submit(&mut self, &mut Self::CommandBuffer,
                         access: &command::AccessInfo<Self::Resources>);

    /// Submits a `CommandBuffer` to the GPU for execution.
    /// returns a fence that is signaled after the GPU has executed all commands
    fn fenced_submit(&mut self,
                     &mut Self::CommandBuffer,
                     access: &command::AccessInfo<Self::Resources>,
                     after: Option<handle::Fence<Self::Resources>>)
                     -> handle::Fence<Self::Resources>;

    /// Stalls the current thread until the fence is satisfied
    fn wait_fence(&mut self, &handle::Fence<Self::Resources>);

    /// Cleanup unused resources. This should be called between frames.
    fn cleanup(&mut self);
}
<commit_msg>Migrate low level core API changes to core.<commit_after>// Copyright 2015 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![deny(missing_docs)]

//! Low-level graphics abstraction for Rust. Mostly operates on data, not types.
//! Designed for use by libraries and higher-level abstractions only.

#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate log;
extern crate draw_state;
//extern crate num;

use std::fmt::Debug;
use std::hash::Hash;
use std::any::Any;
use std::slice::Iter;

pub use draw_state::{state, target};
pub use self::factory::Factory;

pub mod buffer;
pub mod command;
pub mod dummy;
pub mod factory;
pub mod format;
pub mod handle;
pub mod mapping;
pub mod memory;
pub mod pso;
pub mod shade;
pub mod texture;

/// Compile-time maximum number of vertex attributes.
pub const MAX_VERTEX_ATTRIBUTES: usize = 16;
/// Compile-time maximum number of color targets.
pub const MAX_COLOR_TARGETS: usize = 4;
/// Compile-time maximum number of constant buffers.
pub const MAX_CONSTANT_BUFFERS: usize = 14;
/// Compile-time maximum number of shader resource views (SRV).
pub const MAX_RESOURCE_VIEWS: usize = 32;
/// Compile-time maximum number of unordered access views (UAV).
pub const MAX_UNORDERED_VIEWS: usize = 4;
/// Compile-time maximum number of samplers.
pub const MAX_SAMPLERS: usize = 16;

/// Draw vertex count.
pub type VertexCount = u32;
/// Draw number of instances
pub type InstanceCount = u32;
/// Number of vertices in a patch
pub type PatchSize = u8;

/// Slot for an attribute.
pub type AttributeSlot = u8;
/// Slot for a constant buffer object.
pub type ConstantBufferSlot = u8;
/// Slot for a shader resource view.
pub type ResourceViewSlot = u8;
/// Slot for an unordered access object.
pub type UnorderedViewSlot = u8;
/// Slot for an active color buffer.
pub type ColorSlot = u8;
/// Slot for a sampler.
pub type SamplerSlot = u8;

macro_rules! define_shaders {
    ($($name:ident),+) => {$(
        #[allow(missing_docs)]
        #[derive(Clone, Debug, Eq, Hash, PartialEq)]
        pub struct $name<R: Resources>(handle::Shader<R>);
        impl<R: Resources> $name<R> {
            #[allow(missing_docs)]
            pub fn reference(&self, man: &mut handle::Manager<R>) -> &R::Shader {
                man.ref_shader(&self.0)
            }
        }
    )+}
}

define_shaders!(VertexShader, HullShader, DomainShader, GeometryShader, PixelShader);

/// A complete set of shaders to link a program.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum ShaderSet<R: Resources> {
    /// Simple program: Vs-Ps
    Simple(VertexShader<R>, PixelShader<R>),
    /// Geometry shader programs: Vs-Gs-Ps
    Geometry(VertexShader<R>, GeometryShader<R>, PixelShader<R>),
    /// Tessellated TODO: Tessellated, TessellatedGeometry, TransformFeedback
    Tessellated(VertexShader<R>, HullShader<R>, DomainShader<R>, PixelShader<R>),

}

impl<R: Resources> ShaderSet<R> {
    /// Return the aggregated stage usage for the set.
    pub fn get_usage(&self) -> shade::Usage {
        match self {
            &ShaderSet::Simple(..) => shade::VERTEX | shade::PIXEL,
            &ShaderSet::Geometry(..) => shade::VERTEX | shade::GEOMETRY | shade::PIXEL,
            &ShaderSet::Tessellated(..) => shade::VERTEX | shade::HULL | shade::DOMAIN | shade::PIXEL,
        }
    }
}

//TODO: use the appropriate units for max vertex count, etc
/// Features that the device supports.
#[derive(Copy, Clone, Debug)]
#[allow(missing_docs)] // pretty self-explanatory fields!
pub struct Capabilities {
    pub max_vertex_count: usize,
    pub max_index_count: usize,
    pub max_texture_size: usize,
    pub max_patch_size: usize,

    pub instance_base_supported: bool,
    pub instance_call_supported: bool,
    pub instance_rate_supported: bool,
    pub vertex_base_supported: bool,
    pub srgb_color_supported: bool,
    pub constant_buffer_supported: bool,
    pub unordered_access_view_supported: bool,
    pub separate_blending_slots_supported: bool,
}

/// Describes what geometric primitives are created from vertex data.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
#[repr(u8)]
pub enum Primitive {
    /// Each vertex represents a single point.
    PointList,
    /// Each pair of vertices represent a single line segment. For example, with `[a, b, c, d,
    /// e]`, `a` and `b` form a line, `c` and `d` form a line, and `e` is discarded.
    LineList,
    /// Every two consecutive vertices represent a single line segment. Visually forms a "path" of
    /// lines, as they are all connected. For example, with `[a, b, c]`, `a` and `b` form a line
    /// line, and `b` and `c` form a line.
    LineStrip,
    /// Each triplet of vertices represent a single triangle. For example, with `[a, b, c, d, e]`,
    /// `a`, `b`, and `c` form a triangle, `d` and `e` are discarded.
    TriangleList,
    /// Every three consecutive vertices represent a single triangle. For example, with `[a, b, c,
    /// d]`, `a`, `b`, and `c` form a triangle, and `b`, `c`, and `d` form a triangle.
    TriangleStrip,
    /// Each quadtruplet of vertices represent a single line segment with adjacency information.
    /// For example, with `[a, b, c, d]`, `b` and `c` form a line, and `a` and `d` are the adjacent
    /// vertices.
    LineListAdjacency,
    /// Every four consecutive vertices represent a single line segment with adjacency information.
    /// For example, with `[a, b, c, d, e]`, `[a, b, c, d]` form a line segment with adjacency, and
    /// `[b, c, d, e]` form a line segment with adjacency.
    LineStripAdjacency,
    /// Each sextuplet of vertices represent a single traingle with adjacency information. For
    /// example, with `[a, b, c, d, e, f]`, `a`, `c`, and `e` form a traingle, and `b`, `d`, and
    /// `f` are the adjacent vertices, where `b` is adjacent to the edge formed by `a` and `c`, `d`
    /// is adjacent to the edge `c` and `e`, and `f` is adjacent to the edge `e` and `a`.
    TriangleListAdjacency,
    /// Every even-numbered vertex (every other starting from the first) represents an additional
    /// vertex for the triangle strip, while odd-numbered vertices (every other starting from the
    /// second) represent adjacent vertices. For example, with `[a, b, c, d, e, f, g, h]`, `[a, c,
    /// e, g]` form a triangle strip, and `[b, d, f, h]` are the adjacent vertices, where `b`, `d`,
    /// and `f` are adjacent to the first triangle in the strip, and `d`, `f`, and `h` are adjacent
    /// to the second.
    TriangleStripAdjacency,
    /// Patch list,
    /// used with shaders capable of producing primitives on their own (tessellation)
    PatchList(PatchSize),
}

/// A type of each index value in the slice's index buffer
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
#[allow(missing_docs)]
#[repr(u8)]
pub enum IndexType {
    U16,
    U32,
}

/// Different types of a specific API.
#[allow(missing_docs)]
pub trait Resources:          Clone + Hash + Debug + Eq + PartialEq + Any {
    type Buffer:              Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync + Copy;
    type Shader:              Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync;
    type Program:             Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync;
    type PipelineStateObject: Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync;
    type Texture:             Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync;
    type ShaderResourceView:  Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync + Copy;
    type UnorderedAccessView: Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync + Copy;
    type RenderTargetView:    Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync + Copy;
    type DepthStencilView:    Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync;
    type Sampler:             Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync + Copy;
    type Fence:               Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync;
    type Mapping:             Hash + Debug + Eq + PartialEq + Any + Send + Sync + mapping::Gate<Self>;
}

/// A `Device` is responsible for submitting `CommandBuffer`s to the GPU.
pub trait Device: Sized {
    /// Associated `Resources` type.
    type Resources: Resources;
    /// Associated `CommandBuffer` type. Every `Device` type can only work with one `CommandBuffer`
    /// type.
    type CommandBuffer: command::Buffer<Self::Resources>;

    /// Returns the capabilities of this `Ðevice`.
    fn get_capabilities(&self) -> &Capabilities;

    /// Pin everything from this handle manager to live for a frame.
    fn pin_submitted_resources(&mut self, &handle::Manager<Self::Resources>);

    /// Submits a `CommandBuffer` to the GPU for execution.

    fn submit(&mut self, &mut Self::CommandBuffer,
                         access: &command::AccessInfo<Self::Resources>);

    /// Submits a `CommandBuffer` to the GPU for execution.
    /// returns a fence that is signaled after the GPU has executed all commands
    fn fenced_submit(&mut self,
                     &mut Self::CommandBuffer,
                     access: &command::AccessInfo<Self::Resources>,
                     after: Option<handle::Fence<Self::Resources>>)
                     -> handle::Fence<Self::Resources>;

    /// Stalls the current thread until the fence is satisfied
    fn wait_fence(&mut self, &handle::Fence<Self::Resources>);

    /// Cleanup unused resources. This should be called between frames.
    fn cleanup(&mut self);
}

/// An `Instance` holds per-application state for a specific backend
pub trait Instance {
    /// Associated `Adapter` type.
    type Adapter: Adapter;
    /// Associated `Surface` type.
    type Surface: Surface;

    /// Associated native `Window` type.
    type Window;

    /// Instantiate a new `Instance`, this is our entry point for applications
    fn create() -> Self;

    /// Enumerate all available adapters supporting this backend
    fn enumerate_adapters(&self) -> Vec<Self::Adapter>;

    /// Create a new surface from a native window.
    fn create_surface(&self, window: &Self::Window) -> Self::Surface;
}

/// Represents a physical or virtual device, which is capable of running the backend.
pub trait Adapter {
    /// Associated `CommandQueue` type.
    type CommandQueue: CommandQueue;
    /// Associated `Device` type.
    type Device: Device;
    /// Associated `QueueFamily` type.
    type QueueFamily: QueueFamily;

    /// Create a new device and command queues.
    fn open<'a, I>(&self, queue_descs: I) -> (Self::Device, Vec<Self::CommandQueue>)
        where I: Iterator<Item=(&'a Self::QueueFamily, u32)>;

    /// Get the `AdapterInfo` for this adapater.
    fn get_info(&self) -> &AdapterInfo;

    /// Return the supported queue families for this adapter.
    fn get_queue_families(&self) -> Iter<Self::QueueFamily>;
}

/// Information about a backend adapater.
#[derive(Clone, Debug)]
pub struct AdapterInfo {
    /// Adapter name
    pub name: String,
    /// Vendor PCI id of the adapter
    pub vendor: usize,
    /// PCI id of the adapter
    pub device: usize,
    /// The device is based on a software rasterizer
    pub software_rendering: bool,
}

/// `QueueFamily` denotes a group of command queues provided by the backend
/// with the same properties/type.
pub trait QueueFamily: 'static {
    /// Associated `Surface` type.
    type Surface: Surface;

    /// Check if the queue family supports presentation to a surface
    fn supports_present(&self, surface: &Self::Surface) -> bool;

    /// Return the number of available queues of this family
    // TODO: some backends like d3d12 support infinite software queues (verify)
    fn num_queues(&self) -> u32;
}

/// Dummy trait for command queues.
/// CommandBuffers will be later submitted to command queues instead of the device.
pub trait CommandQueue { }

/// A `Surface` abstracts the surface of a native window, which will be presented
pub trait Surface {
    /// Associated `CommandQueue` type.
    type CommandQueue: CommandQueue;
    /// Associated `SwapChain` type.
    type SwapChain: SwapChain;

    /// Create a new swapchain from the current surface with an associated present queue.
    fn build_swapchain<T: format::RenderFormat>(&self, present_queue: &Self::CommandQueue)
        -> Self::SwapChain;
}

/// Handle to a backbuffer of the swapchain.
pub struct Frame(usize);

impl Frame {
    #[doc(hidden)]
    pub fn new(id: usize) -> Self {
        Frame(id)
    }
}

/// The `SwapChain` is the backend representation of the surface.
/// It consists of multiple buffers, which will be presented on the surface.
pub trait SwapChain {
    /// Acquire a new frame for rendering. This needs to be called before presenting.
    fn acquire_frame(&mut self) -> Frame;

    /// Present one acquired frame in FIFO order.
    fn present(&mut self);
}
<|endoftext|>


<commit_before>use std::fmt::{Display, Formatter, Result};
use std::ops::Deref;

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Debug)]
#[repr(transparent)]
pub(crate) struct Version {
    version: u64,
}

impl Version {
    #[inline]
    #[allow(dead_code)]
    fn new(major: u16, minor: u16, patch: u32) -> Self {
        let mut v_u64 = 0u64;
        v_u64 |= u64::from(major) << 48;
        v_u64 |= u64::from(minor) << 32;
        v_u64 |= u64::from(patch);
        Version { version: v_u64 }
    }

    #[inline]
    pub fn major(self) -> u16 {
        (self.version >> 48) as u16
    }

    #[inline]
    pub fn minor(self) -> u16 {
        ((self.version << 16) >> 48) as u16
    }

    #[inline]
    pub fn patch(self) -> u32 {
        (self.version & 0x0000_0000_FFFF_FFFF) as u32
    }

    #[inline]
    pub fn is_compatible(self, other: Version) -> bool {
        self >= other
    }

    #[inline]
    pub fn latest() -> Version {
        Version::new(1, 0, 0)
    }
}

impl Into<u64> for Version {
    #[inline]
    fn into(self) -> u64 {
        self.version
    }
}

impl From<u64> for Version {
    fn from(version: u64) -> Self {
        Version { version }
    }
}

impl Deref for Version {
    type Target = u64;
    #[inline]
    fn deref(&self) -> &Self::Target {
        &self.version
    }
}

impl Display for Version {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        write!(f, "{}.{}.{}", self.major(), self.minor(), self.patch())
    }
}

#[cfg(test)]
mod tests {
    use super::Version;
    #[test]
    fn check_version_creation() {
        for i in 1..1024 {
            let v = Version::new(i, i, i as u32);
            assert!(v.major() == i as u16);
            assert!(v.minor() == i as u16);
            assert!(v.patch() == i as u32);
            let v_u64: u64 = v.into();
            assert!(v_u64 == *v);
            assert!(format!("{}", v) == format!("{}.{}.{}", i, i, i));
        }
    }
}
<commit_msg>Replace Into<u64> with From<Version><commit_after>use std::fmt::{Display, Formatter, Result};
use std::ops::Deref;

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Debug)]
#[repr(transparent)]
pub(crate) struct Version {
    version: u64,
}

impl Version {
    #[inline]
    #[allow(dead_code)]
    fn new(major: u16, minor: u16, patch: u32) -> Self {
        let mut v_u64 = 0u64;
        v_u64 |= u64::from(major) << 48;
        v_u64 |= u64::from(minor) << 32;
        v_u64 |= u64::from(patch);
        Version { version: v_u64 }
    }

    #[inline]
    pub fn major(self) -> u16 {
        (self.version >> 48) as u16
    }

    #[inline]
    pub fn minor(self) -> u16 {
        ((self.version << 16) >> 48) as u16
    }

    #[inline]
    pub fn patch(self) -> u32 {
        (self.version & 0x0000_0000_FFFF_FFFF) as u32
    }

    #[inline]
    pub fn is_compatible(self, other: Version) -> bool {
        self >= other
    }

    #[inline]
    pub fn latest() -> Version {
        Version::new(1, 0, 0)
    }
}

// impl Into<u64> for Version {
//     #[inline]
//     fn into(self) -> u64 {
//         self.version
//     }
// }

impl From<Version> for u64 {
    fn from(version: Version) -> Self {
        version.version
    }
}

impl From<u64> for Version {
    fn from(version: u64) -> Self {
        Version { version }
    }
}

impl Deref for Version {
    type Target = u64;
    #[inline]
    fn deref(&self) -> &Self::Target {
        &self.version
    }
}

impl Display for Version {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        write!(f, "{}.{}.{}", self.major(), self.minor(), self.patch())
    }
}

#[cfg(test)]
mod tests {
    use super::Version;
    #[test]
    fn check_version_creation() {
        for i in 1..1024 {
            let v = Version::new(i, i, i as u32);
            assert!(v.major() == i as u16);
            assert!(v.minor() == i as u16);
            assert!(v.patch() == i as u32);
            let v_u64: u64 = v.into();
            assert!(v_u64 == *v);
            assert!(format!("{}", v) == format!("{}.{}.{}", i, i, i));
        }
    }

    #[test]
    fn check_conversion() {
        let v1 = Version::new(1, 2, 3);
        let v_u64: u64 = v1.into();
        let v2 = Version::from(v_u64);
        assert_eq!(v1, v2);
        let v3: Version = v_u64.into();
        assert_eq!(v1, v3);
    }
}
<|endoftext|>


<commit_before>use std::rc::Rc;

use workload::Element;
use {Config, Result};

/// A workload pattern.
#[derive(Clone, Debug)]
pub struct Pattern(Rc<Content>);

deref! { Pattern::0 => Content }

/// The content of a workload pattern.
#[derive(Clone, Debug)]
pub struct Content {
    /// The name.
    pub name: String,
    /// The number of processing elements.
    pub units: usize,
    /// The number of time steps.
    pub steps: usize,
    /// The time step (sampling interval).
    pub time_step: f64,
    /// The processing elements.
    pub elements: Vec<Element>,
}

impl Pattern {
    /// Create a pattern.
    pub fn new(config: &Config) -> Result<Pattern> {
        let path = path!(config, "a workload-pattern database is required");

        let name = match config.get::<String>("name") {
            Some(name) => name.to_string(),
            _ => path.file_stem().unwrap().to_str().unwrap().to_string(),
        };
        let time_step = *some!(config.get::<f64>("time_step"), "a time step is required");

        info!(target: "Workload", "Reading a pattern from {:?}...", &path);
        let elements = try!(Element::collect(&path));

        let units = elements.len();
        if units == 0 {
            raise!("found a workload pattern without processing elements");
        }
        let steps = elements[0].dynamic_power.len();
        if steps == 0 {
            raise!("found a workload pattern without dynamic-power data");
        }

        Ok(Pattern(Rc::new(Content {
            name: name,
            units: units,
            steps: steps,
            time_step: time_step,
            elements: elements,
        })))
    }

    /// Return the time duration.
    #[inline]
    pub fn duration(&self) -> f64 {
        self.steps as f64 * self.time_step
    }
}
<commit_msg>Workload: adjust a description<commit_after>use std::rc::Rc;

use workload::Element;
use {Config, Result};

/// A workload pattern.
#[derive(Clone, Debug)]
pub struct Pattern(Rc<Content>);

deref! { Pattern::0 => Content }

/// The content of a workload pattern.
#[derive(Clone, Debug)]
pub struct Content {
    /// The name.
    pub name: String,
    /// The number of processing elements.
    pub units: usize,
    /// The number of time steps.
    pub steps: usize,
    /// The time step (sampling interval).
    pub time_step: f64,
    /// The processing elements.
    pub elements: Vec<Element>,
}

impl Pattern {
    /// Create a pattern.
    pub fn new(config: &Config) -> Result<Pattern> {
        let path = path!(config, "a workload-pattern database is required");

        let name = match config.get::<String>("name") {
            Some(name) => name.to_string(),
            _ => path.file_stem().unwrap().to_str().unwrap().to_string(),
        };
        let time_step = *some!(config.get::<f64>("time_step"), "a time step is required");

        info!(target: "Workload", "Reading a pattern from {:?}...", &path);
        let elements = try!(Element::collect(&path));

        let units = elements.len();
        if units == 0 {
            raise!("found a workload pattern without processing elements");
        }
        let steps = elements[0].dynamic_power.len();
        if steps == 0 {
            raise!("found a workload pattern without dynamic-power data");
        }

        Ok(Pattern(Rc::new(Content {
            name: name,
            units: units,
            steps: steps,
            time_step: time_step,
            elements: elements,
        })))
    }

    /// Return the duration.
    #[inline]
    pub fn duration(&self) -> f64 {
        self.steps as f64 * self.time_step
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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 stb_image::bindgen::*;

use std::any::Any;
use libc;
use libc::{c_void, c_int};
use std::slice::raw::buf_as_slice;

pub struct Image<T> {
    pub width   : uint,
    pub height  : uint,
    pub depth   : uint,
    pub data    : Vec<T>,
}

pub fn new_image<T>(width: uint, height: uint, depth: uint, data: Vec<T>) -> Image<T> {
    Image::<T> {
        width   : width,
        height  : height,
        depth   : depth,
        data    : data,
    }
}

pub enum LoadResult {
    Error(String),
    ImageU8(Image<u8>),
    ImageF32(Image<f32>),
}

impl LoadResult {
    pub fn from_result(res: Result<LoadResult,Box<Any>>)-> LoadResult {
        match res {
            Ok(res) => res,
            Err(e)  => Error(e.to_str()),
        }
    }
}

pub fn load(path: &Path) -> LoadResult {
    let force_depth = 0;
    load_with_depth(path, force_depth, false)
}

fn load_internal<T: Clone>(buf : *T, w : c_int, h : c_int, d : c_int) -> Image<T> {
    unsafe {
        // FIXME: Shouldn't copy; instead we should use a sendable resource. They
        // aren't particularly safe yet though.
        let data = buf_as_slice(buf, (w * h * d) as uint, |s| { Vec::from_slice(s) });
        libc::free(buf as *mut c_void);
        Image::<T>{
            width   : w as uint,
            height  : h as uint,
            depth   : d as uint,
            data    : data}
    }
}

pub fn load_with_depth(path: &Path, force_depth: uint, convert_hdr: bool) -> LoadResult {
    unsafe {
        let mut width = 0 as c_int;
        let mut height = 0 as c_int;
        let mut depth = 0 as c_int;
        let path_as_str = match path.as_str() {
            Some(s) => s,
            None => return Error("path is not valid utf8".to_owned()),
        };
        path_as_str.with_c_str(|bytes| {
            if !convert_hdr && stbi_is_hdr(bytes)!=0   {
                let buffer = stbi_loadf(bytes,
                                        &mut width,
                                        &mut height,
                                        &mut depth,
                                        force_depth as c_int);
                if buffer.is_null() {
                    Error("stbi_loadf failed".to_owned())
                } else {
                    ImageF32(load_internal(buffer, width, height, depth))
                }
            } else {
                let buffer = stbi_load(bytes,
                                       &mut width,
                                       &mut height,
                                       &mut depth,
                                       force_depth as c_int);
                if buffer.is_null() {
                    Error("stbi_load failed".to_owned())
                } else {
                    ImageU8(load_internal(buffer, width, height, depth))
                }
            }
        })
    }
}

pub fn load_from_memory(buffer: &[u8]) -> LoadResult {
    let force_depth = 0;
    load_from_memory_with_depth(buffer, force_depth, false)
}

pub fn load_from_memory_with_depth(buffer: &[u8], force_depth: uint, convert_hdr:bool) -> LoadResult {
    unsafe {
        let mut width = 0 as c_int;
        let mut height = 0 as c_int;
        let mut depth = 0 as c_int;
        if !convert_hdr && stbi_is_hdr_from_memory(buffer.as_ptr(), buffer.len() as c_int) != 0 {
            let buffer = stbi_loadf_from_memory(buffer.as_ptr(),
                                                buffer.len() as c_int,
                                                &mut width,
                                                &mut height,
                                                &mut depth,
                                                force_depth as c_int);
            if buffer.is_null() {
                Error("stbi_loadf_from_memory failed".to_owned())
            } else {
                let actual_depth = if force_depth != 0 { force_depth as c_int } else { depth };
                ImageF32(load_internal(buffer, width, height, actual_depth))
            }
        } else {
            let buffer = stbi_load_from_memory(buffer.as_ptr(),
                                               buffer.len() as c_int,
                                               &mut width,
                                               &mut height,
                                               &mut depth,
                                               force_depth as c_int);
            if buffer.is_null() {
                Error("stbi_load_from_memory failed".to_owned())
            } else {
                let actual_depth = if force_depth != 0 { force_depth as c_int } else { depth };
                ImageU8(load_internal(buffer, width, height, actual_depth))
            }
        }
    }
}
<commit_msg>Fix deprecation warnings<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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 stb_image::bindgen::*;

use std::any::Any;
use libc;
use libc::{c_void, c_int};
use std::slice::raw::buf_as_slice;

pub struct Image<T> {
    pub width   : uint,
    pub height  : uint,
    pub depth   : uint,
    pub data    : Vec<T>,
}

pub fn new_image<T>(width: uint, height: uint, depth: uint, data: Vec<T>) -> Image<T> {
    Image::<T> {
        width   : width,
        height  : height,
        depth   : depth,
        data    : data,
    }
}

pub enum LoadResult {
    Error(String),
    ImageU8(Image<u8>),
    ImageF32(Image<f32>),
}

impl LoadResult {
    pub fn from_result(res: Result<LoadResult,Box<Any>>)-> LoadResult {
        match res {
            Ok(res) => res,
            Err(e)  => Error(e.to_str()),
        }
    }
}

pub fn load(path: &Path) -> LoadResult {
    let force_depth = 0;
    load_with_depth(path, force_depth, false)
}

fn load_internal<T: Clone>(buf : *T, w : c_int, h : c_int, d : c_int) -> Image<T> {
    unsafe {
        // FIXME: Shouldn't copy; instead we should use a sendable resource. They
        // aren't particularly safe yet though.
        let data = buf_as_slice(buf, (w * h * d) as uint, |s| { Vec::from_slice(s) });
        libc::free(buf as *mut c_void);
        Image::<T>{
            width   : w as uint,
            height  : h as uint,
            depth   : d as uint,
            data    : data}
    }
}

pub fn load_with_depth(path: &Path, force_depth: uint, convert_hdr: bool) -> LoadResult {
    unsafe {
        let mut width = 0 as c_int;
        let mut height = 0 as c_int;
        let mut depth = 0 as c_int;
        let path_as_str = match path.as_str() {
            Some(s) => s,
            None => return Error("path is not valid utf8".to_string()),
        };
        path_as_str.with_c_str(|bytes| {
            if !convert_hdr && stbi_is_hdr(bytes)!=0   {
                let buffer = stbi_loadf(bytes,
                                        &mut width,
                                        &mut height,
                                        &mut depth,
                                        force_depth as c_int);
                if buffer.is_null() {
                    Error("stbi_loadf failed".to_string())
                } else {
                    ImageF32(load_internal(buffer, width, height, depth))
                }
            } else {
                let buffer = stbi_load(bytes,
                                       &mut width,
                                       &mut height,
                                       &mut depth,
                                       force_depth as c_int);
                if buffer.is_null() {
                    Error("stbi_load failed".to_string())
                } else {
                    ImageU8(load_internal(buffer, width, height, depth))
                }
            }
        })
    }
}

pub fn load_from_memory(buffer: &[u8]) -> LoadResult {
    let force_depth = 0;
    load_from_memory_with_depth(buffer, force_depth, false)
}

pub fn load_from_memory_with_depth(buffer: &[u8], force_depth: uint, convert_hdr:bool) -> LoadResult {
    unsafe {
        let mut width = 0 as c_int;
        let mut height = 0 as c_int;
        let mut depth = 0 as c_int;
        if !convert_hdr && stbi_is_hdr_from_memory(buffer.as_ptr(), buffer.len() as c_int) != 0 {
            let buffer = stbi_loadf_from_memory(buffer.as_ptr(),
                                                buffer.len() as c_int,
                                                &mut width,
                                                &mut height,
                                                &mut depth,
                                                force_depth as c_int);
            if buffer.is_null() {
                Error("stbi_loadf_from_memory failed".to_string())
            } else {
                let actual_depth = if force_depth != 0 { force_depth as c_int } else { depth };
                ImageF32(load_internal(buffer, width, height, actual_depth))
            }
        } else {
            let buffer = stbi_load_from_memory(buffer.as_ptr(),
                                               buffer.len() as c_int,
                                               &mut width,
                                               &mut height,
                                               &mut depth,
                                               force_depth as c_int);
            if buffer.is_null() {
                Error("stbi_load_from_memory failed".to_string())
            } else {
                let actual_depth = if force_depth != 0 { force_depth as c_int } else { depth };
                ImageU8(load_internal(buffer, width, height, actual_depth))
            }
        }
    }
}
<|endoftext|>


<commit_before>use crate::ty::{self, Ty, TyCtxt, TyVid, IntVid, FloatVid, RegionVid};
use crate::ty::fold::{TypeFoldable, TypeFolder};

use super::InferCtxt;
use super::RegionVariableOrigin;

use std::ops::Range;

impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
    /// This rather funky routine is used while processing expected
    /// types. What happens here is that we want to propagate a
    /// coercion through the return type of a fn to its
    /// argument. Consider the type of `Option::Some`, which is
    /// basically `for<T> fn(T) -> Option<T>`. So if we have an
    /// expression `Some(&[1, 2, 3])`, and that has the expected type
    /// `Option<&[u32]>`, we would like to type check `&[1, 2, 3]`
    /// with the expectation of `&[u32]`. This will cause us to coerce
    /// from `&[u32; 3]` to `&[u32]` and make the users life more
    /// pleasant.
    ///
    /// The way we do this is using `fudge_inference_if_ok`. What the
    /// routine actually does is to start a snapshot and execute the
    /// closure `f`. In our example above, what this closure will do
    /// is to unify the expectation (`Option<&[u32]>`) with the actual
    /// return type (`Option<?T>`, where `?T` represents the variable
    /// instantiated for `T`). This will cause `?T` to be unified
    /// with `&?a [u32]`, where `?a` is a fresh lifetime variable. The
    /// input type (`?T`) is then returned by `f()`.
    ///
    /// At this point, `fudge_inference_if_ok` will normalize all type
    /// variables, converting `?T` to `&?a [u32]` and end the
    /// snapshot. The problem is that we can't just return this type
    /// out, because it references the region variable `?a`, and that
    /// region variable was popped when we popped the snapshot.
    ///
    /// So what we do is to keep a list (`region_vars`, in the code below)
    /// of region variables created during the snapshot (here, `?a`). We
    /// fold the return value and replace any such regions with a *new*
    /// region variable (e.g., `?b`) and return the result (`&?b [u32]`).
    /// This can then be used as the expectation for the fn argument.
    ///
    /// The important point here is that, for soundness purposes, the
    /// regions in question are not particularly important. We will
    /// use the expected types to guide coercions, but we will still
    /// type-check the resulting types from those coercions against
    /// the actual types (`?T`, `Option<?T>`) -- and remember that
    /// after the snapshot is popped, the variable `?T` is no longer
    /// unified.
    pub fn fudge_inference_if_ok<T, E, F>(
        &self,
        origin: &RegionVariableOrigin,
        f: F,
    ) -> Result<T, E> where
        F: FnOnce() -> Result<T, E>,
        T: TypeFoldable<'tcx>,
    {
        debug!("fudge_inference_if_ok(origin={:?})", origin);

        let (type_vars, int_vars, float_vars, region_vars, value) = self.probe(|snapshot| {
            match f() {
                Ok(value) => {
                    let value = self.resolve_type_vars_if_possible(&value);

                    // At this point, `value` could in principle refer
                    // to types/regions that have been created during
                    // the snapshot. Once we exit `probe()`, those are
                    // going to be popped, so we will have to
                    // eliminate any references to them.

                    let type_vars = self.type_variables.borrow_mut().vars_since_snapshot(
                        &snapshot.type_snapshot,
                    );
                    let int_vars = self.int_unification_table.borrow_mut().vars_since_snapshot(
                        &snapshot.int_snapshot,
                    );
                    let float_vars = self.float_unification_table.borrow_mut().vars_since_snapshot(
                        &snapshot.float_snapshot,
                    );
                    let region_vars = self.borrow_region_constraints().vars_since_snapshot(
                        &snapshot.region_constraints_snapshot,
                    );

                    Ok((type_vars, int_vars, float_vars, region_vars, value))
                }
                Err(e) => Err(e),
            }
        })?;

        // At this point, we need to replace any of the now-popped
        // type/region variables that appear in `value` with a fresh
        // variable of the appropriate kind. We can't do this during
        // the probe because they would just get popped then too. =)

        // Micro-optimization: if no variables have been created, then
        // `value` can't refer to any of them. =) So we can just return it.
        if type_vars.is_empty() &&
            int_vars.is_empty() &&
            float_vars.is_empty() &&
            region_vars.is_empty() {
            return Ok(value);
        }

        let mut fudger = InferenceFudger {
            infcx: self,
            type_vars: &type_vars,
            int_vars: &int_vars,
            float_vars: &float_vars,
            region_vars: &region_vars,
            origin,
        };

        Ok(value.fold_with(&mut fudger))
    }
}

pub struct InferenceFudger<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
    type_vars: &'a Range<TyVid>,
    int_vars: &'a Range<IntVid>,
    float_vars: &'a Range<FloatVid>,
    region_vars: &'a Range<RegionVid>,
    origin: &'a RegionVariableOrigin,
}

impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for InferenceFudger<'a, 'gcx, 'tcx> {
    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
        self.infcx.tcx
    }

    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
        match ty.sty {
            ty::Infer(ty::InferTy::TyVar(vid)) => {
                if self.type_vars.contains(&vid) {
                    // This variable was created during the fudging.
                    // Recreate it with a fresh variable here.
                    let origin = self.infcx.type_variables.borrow().var_origin(vid).clone();
                    self.infcx.next_ty_var(origin)
                } else {
                    // This variable was created before the
                    // "fudging".  Since we refresh all type
                    // variables to their binding anyhow, we know
                    // that it is unbound, so we can just return
                    // it.
                    debug_assert!(self.infcx.type_variables.borrow_mut()
                                  .probe(vid)
                                  .is_unknown());
                    ty
                }
            }
            ty::Infer(ty::InferTy::IntVar(vid)) => {
                if self.int_vars.contains(&vid) {
                    self.infcx.tcx.mk_int_var(self.infcx.next_int_var_id())
                } else {
                    ty
                }
            }
            ty::Infer(ty::InferTy::FloatVar(vid)) => {
                if self.float_vars.contains(&vid) {
                    self.infcx.tcx.mk_float_var(self.infcx.next_float_var_id())
                } else {
                    ty
                }
            }
            _ => ty.super_fold_with(self),
        }
    }

    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
        match *r {
            ty::ReVar(vid) if self.region_vars.contains(&vid) => {
                self.infcx.next_region_var(self.origin.clone())
            }
            _ => r,
        }
    }
}
<commit_msg>Simplify `fudge_inference_if_ok`<commit_after>use crate::ty::{self, Ty, TyCtxt, TyVid, IntVid, FloatVid, RegionVid};
use crate::ty::fold::{TypeFoldable, TypeFolder};

use super::InferCtxt;
use super::RegionVariableOrigin;

use std::ops::Range;

impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
    /// This rather funky routine is used while processing expected
    /// types. What happens here is that we want to propagate a
    /// coercion through the return type of a fn to its
    /// argument. Consider the type of `Option::Some`, which is
    /// basically `for<T> fn(T) -> Option<T>`. So if we have an
    /// expression `Some(&[1, 2, 3])`, and that has the expected type
    /// `Option<&[u32]>`, we would like to type check `&[1, 2, 3]`
    /// with the expectation of `&[u32]`. This will cause us to coerce
    /// from `&[u32; 3]` to `&[u32]` and make the users life more
    /// pleasant.
    ///
    /// The way we do this is using `fudge_inference_if_ok`. What the
    /// routine actually does is to start a snapshot and execute the
    /// closure `f`. In our example above, what this closure will do
    /// is to unify the expectation (`Option<&[u32]>`) with the actual
    /// return type (`Option<?T>`, where `?T` represents the variable
    /// instantiated for `T`). This will cause `?T` to be unified
    /// with `&?a [u32]`, where `?a` is a fresh lifetime variable. The
    /// input type (`?T`) is then returned by `f()`.
    ///
    /// At this point, `fudge_inference_if_ok` will normalize all type
    /// variables, converting `?T` to `&?a [u32]` and end the
    /// snapshot. The problem is that we can't just return this type
    /// out, because it references the region variable `?a`, and that
    /// region variable was popped when we popped the snapshot.
    ///
    /// So what we do is to keep a list (`region_vars`, in the code below)
    /// of region variables created during the snapshot (here, `?a`). We
    /// fold the return value and replace any such regions with a *new*
    /// region variable (e.g., `?b`) and return the result (`&?b [u32]`).
    /// This can then be used as the expectation for the fn argument.
    ///
    /// The important point here is that, for soundness purposes, the
    /// regions in question are not particularly important. We will
    /// use the expected types to guide coercions, but we will still
    /// type-check the resulting types from those coercions against
    /// the actual types (`?T`, `Option<?T>`) -- and remember that
    /// after the snapshot is popped, the variable `?T` is no longer
    /// unified.
    pub fn fudge_inference_if_ok<T, E, F>(
        &self,
        origin: &RegionVariableOrigin,
        f: F,
    ) -> Result<T, E> where
        F: FnOnce() -> Result<T, E>,
        T: TypeFoldable<'tcx>,
    {
        debug!("fudge_inference_if_ok(origin={:?})", origin);

        let (mut fudger, value) = self.probe(|snapshot| {
            match f() {
                Ok(value) => {
                    let value = self.resolve_type_vars_if_possible(&value);

                    // At this point, `value` could in principle refer
                    // to types/regions that have been created during
                    // the snapshot. Once we exit `probe()`, those are
                    // going to be popped, so we will have to
                    // eliminate any references to them.

                    let type_vars = self.type_variables.borrow_mut().vars_since_snapshot(
                        &snapshot.type_snapshot,
                    );
                    let int_vars = self.int_unification_table.borrow_mut().vars_since_snapshot(
                        &snapshot.int_snapshot,
                    );
                    let float_vars = self.float_unification_table.borrow_mut().vars_since_snapshot(
                        &snapshot.float_snapshot,
                    );
                    let region_vars = self.borrow_region_constraints().vars_since_snapshot(
                        &snapshot.region_constraints_snapshot,
                    );

                    let fudger = InferenceFudger {
                        infcx: self,
                        type_vars,
                        int_vars,
                        float_vars,
                        region_vars,
                        origin,
                    };

                    Ok((fudger, value))
                }
                Err(e) => Err(e),
            }
        })?;

        // At this point, we need to replace any of the now-popped
        // type/region variables that appear in `value` with a fresh
        // variable of the appropriate kind. We can't do this during
        // the probe because they would just get popped then too. =)

        // Micro-optimization: if no variables have been created, then
        // `value` can't refer to any of them. =) So we can just return it.
        if fudger.type_vars.is_empty() &&
            fudger.int_vars.is_empty() &&
            fudger.float_vars.is_empty() &&
            fudger.region_vars.is_empty() {
            return Ok(value);
        }

        Ok(value.fold_with(&mut fudger))
    }
}

pub struct InferenceFudger<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
    type_vars: Range<TyVid>,
    int_vars: Range<IntVid>,
    float_vars: Range<FloatVid>,
    region_vars: Range<RegionVid>,
    origin: &'a RegionVariableOrigin,
}

impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for InferenceFudger<'a, 'gcx, 'tcx> {
    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
        self.infcx.tcx
    }

    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
        match ty.sty {
            ty::Infer(ty::InferTy::TyVar(vid)) => {
                if self.type_vars.contains(&vid) {
                    // This variable was created during the fudging.
                    // Recreate it with a fresh variable here.
                    let origin = self.infcx.type_variables.borrow().var_origin(vid).clone();
                    self.infcx.next_ty_var(origin)
                } else {
                    // This variable was created before the
                    // "fudging".  Since we refresh all type
                    // variables to their binding anyhow, we know
                    // that it is unbound, so we can just return
                    // it.
                    debug_assert!(self.infcx.type_variables.borrow_mut()
                                  .probe(vid)
                                  .is_unknown());
                    ty
                }
            }
            ty::Infer(ty::InferTy::IntVar(vid)) => {
                if self.int_vars.contains(&vid) {
                    self.infcx.tcx.mk_int_var(self.infcx.next_int_var_id())
                } else {
                    ty
                }
            }
            ty::Infer(ty::InferTy::FloatVar(vid)) => {
                if self.float_vars.contains(&vid) {
                    self.infcx.tcx.mk_float_var(self.infcx.next_float_var_id())
                } else {
                    ty
                }
            }
            _ => ty.super_fold_with(self),
        }
    }

    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
        match *r {
            ty::ReVar(vid) if self.region_vars.contains(&vid) => {
                self.infcx.next_region_var(self.origin.clone())
            }
            _ => r,
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

//! An "interner" is a data structure that associates values with usize tags and
//! allows bidirectional lookup; i.e. given a value, one can easily find the
//! type, and vice versa.

use hygiene::SyntaxContext;

use serialize::{Decodable, Decoder, Encodable, Encoder};
use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt;

#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct Ident {
    pub name: Symbol,
    pub ctxt: SyntaxContext,
}

impl Ident {
    pub const fn with_empty_ctxt(name: Symbol) -> Ident {
        Ident { name: name, ctxt: SyntaxContext::empty() }
    }

    /// Maps a string to an identifier with an empty syntax context.
    pub fn from_str(string: &str) -> Ident {
        Ident::with_empty_ctxt(Symbol::intern(string))
    }

    pub fn modern(self) -> Ident {
        Ident { name: self.name, ctxt: self.ctxt.modern() }
    }
}

impl fmt::Debug for Ident {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}{:?}", self.name, self.ctxt)
    }
}

impl fmt::Display for Ident {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.name, f)
    }
}

impl Encodable for Ident {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        if self.ctxt.modern() == SyntaxContext::empty() {
            s.emit_str(&self.name.as_str())
        } else { // FIXME(jseyfried) intercrate hygiene
            let mut string = "#".to_owned();
            string.push_str(&self.name.as_str());
            s.emit_str(&string)
        }
    }
}

impl Decodable for Ident {
    fn decode<D: Decoder>(d: &mut D) -> Result<Ident, D::Error> {
        let string = d.read_str()?;
        Ok(if !string.starts_with('#') {
            Ident::from_str(&string)
        } else { // FIXME(jseyfried) intercrate hygiene
            Ident::with_empty_ctxt(Symbol::gensym(&string[1..]))
        })
    }
}

/// A symbol is an interned or gensymed string.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Symbol(u32);

// The interner in thread-local, so `Symbol` shouldn't move between threads.
impl !Send for Symbol { }
impl !Sync for Symbol { }

impl Symbol {
    /// Maps a string to its interned representation.
    pub fn intern(string: &str) -> Self {
        with_interner(|interner| interner.intern(string))
    }

    pub fn interned(self) -> Self {
        with_interner(|interner| interner.interned(self))
    }

    /// gensym's a new usize, using the current interner.
    pub fn gensym(string: &str) -> Self {
        with_interner(|interner| interner.gensym(string))
    }

    pub fn gensymed(self) -> Self {
        with_interner(|interner| interner.gensymed(self))
    }

    pub fn as_str(self) -> InternedString {
        with_interner(|interner| unsafe {
            InternedString {
                string: ::std::mem::transmute::<&str, &str>(interner.get(self))
            }
        })
    }

    pub fn as_u32(self) -> u32 {
        self.0
    }
}

impl fmt::Debug for Symbol {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}({})", self, self.0)
    }
}

impl fmt::Display for Symbol {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.as_str(), f)
    }
}

impl Encodable for Symbol {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_str(&self.as_str())
    }
}

impl Decodable for Symbol {
    fn decode<D: Decoder>(d: &mut D) -> Result<Symbol, D::Error> {
        Ok(Symbol::intern(&d.read_str()?))
    }
}

impl<T: ::std::ops::Deref<Target=str>> PartialEq<T> for Symbol {
    fn eq(&self, other: &T) -> bool {
        self.as_str() == other.deref()
    }
}

#[derive(Default)]
pub struct Interner {
    names: HashMap<Box<str>, Symbol>,
    strings: Vec<Box<str>>,
    gensyms: Vec<Symbol>,
}

impl Interner {
    pub fn new() -> Self {
        Interner::default()
    }

    fn prefill(init: &[&str]) -> Self {
        let mut this = Interner::new();
        for &string in init {
            this.intern(string);
        }
        this
    }

    pub fn intern(&mut self, string: &str) -> Symbol {
        if let Some(&name) = self.names.get(string) {
            return name;
        }

        let name = Symbol(self.strings.len() as u32);
        let string = string.to_string().into_boxed_str();
        self.strings.push(string.clone());
        self.names.insert(string, name);
        name
    }

    pub fn interned(&self, symbol: Symbol) -> Symbol {
        if (symbol.0 as usize) < self.strings.len() {
            symbol
        } else {
            self.interned(self.gensyms[(!0 - symbol.0) as usize])
        }
    }

    fn gensym(&mut self, string: &str) -> Symbol {
        let symbol = self.intern(string);
        self.gensymed(symbol)
    }

    fn gensymed(&mut self, symbol: Symbol) -> Symbol {
        self.gensyms.push(symbol);
        Symbol(!0 - self.gensyms.len() as u32 + 1)
    }

    pub fn get(&self, symbol: Symbol) -> &str {
        match self.strings.get(symbol.0 as usize) {
            Some(ref string) => string,
            None => self.get(self.gensyms[(!0 - symbol.0) as usize]),
        }
    }
}

// In this macro, there is the requirement that the name (the number) must be monotonically
// increasing by one in the special identifiers, starting at 0; the same holds for the keywords,
// except starting from the next number instead of zero.
macro_rules! declare_keywords {(
    $( ($index: expr, $konst: ident, $string: expr) )*
) => {
    pub mod keywords {
        use super::{Symbol, Ident};
        #[derive(Clone, Copy, PartialEq, Eq)]
        pub struct Keyword {
            ident: Ident,
        }
        impl Keyword {
            #[inline] pub fn ident(self) -> Ident { self.ident }
            #[inline] pub fn name(self) -> Symbol { self.ident.name }
        }
        $(
            #[allow(non_upper_case_globals)]
            pub const $konst: Keyword = Keyword {
                ident: Ident::with_empty_ctxt(super::Symbol($index))
            };
        )*
    }

    impl Interner {
        fn fresh() -> Self {
            Interner::prefill(&[$($string,)*])
        }
    }
}}

// NB: leaving holes in the ident table is bad! a different ident will get
// interned with the id from the hole, but it will be between the min and max
// of the reserved words, and thus tagged as "reserved".
// After modifying this list adjust `is_special_ident`, `is_used_keyword`/`is_unused_keyword`,
// this should be rarely necessary though if the keywords are kept in alphabetic order.
declare_keywords! {
    // Special reserved identifiers used internally for elided lifetimes,
    // unnamed method parameters, crate root module, error recovery etc.
    (0,  Invalid,        "")
    (1,  CrateRoot,      "{{root}}")
    (2,  DollarCrate,    "$crate")

    // Keywords used in the language.
    (3,  As,             "as")
    (4,  Box,            "box")
    (5,  Break,          "break")
    (6,  Const,          "const")
    (7,  Continue,       "continue")
    (8,  Crate,          "crate")
    (9,  Else,           "else")
    (10, Enum,           "enum")
    (11, Extern,         "extern")
    (12, False,          "false")
    (13, Fn,             "fn")
    (14, For,            "for")
    (15, If,             "if")
    (16, Impl,           "impl")
    (17, In,             "in")
    (18, Let,            "let")
    (19, Loop,           "loop")
    (20, Match,          "match")
    (21, Mod,            "mod")
    (22, Move,           "move")
    (23, Mut,            "mut")
    (24, Pub,            "pub")
    (25, Ref,            "ref")
    (26, Return,         "return")
    (27, SelfValue,      "self")
    (28, SelfType,       "Self")
    (29, Static,         "static")
    (30, Struct,         "struct")
    (31, Super,          "super")
    (32, Trait,          "trait")
    (33, True,           "true")
    (34, Type,           "type")
    (35, Unsafe,         "unsafe")
    (36, Use,            "use")
    (37, Where,          "where")
    (38, While,          "while")

    // Keywords reserved for future use.
    (39, Abstract,       "abstract")
    (40, Alignof,        "alignof")
    (41, Become,         "become")
    (42, Do,             "do")
    (43, Final,          "final")
    (44, Macro,          "macro")
    (45, Offsetof,       "offsetof")
    (46, Override,       "override")
    (47, Priv,           "priv")
    (48, Proc,           "proc")
    (49, Pure,           "pure")
    (50, Sizeof,         "sizeof")
    (51, Typeof,         "typeof")
    (52, Unsized,        "unsized")
    (53, Virtual,        "virtual")
    (54, Yield,          "yield")

    // Weak keywords, have special meaning only in specific contexts.
    (55, Default,        "default")
    (56, StaticLifetime, "'static")
    (57, Union,          "union")
    (58, Catch,          "catch")
}

// If an interner exists in TLS, return it. Otherwise, prepare a fresh one.
fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
    thread_local!(static INTERNER: RefCell<Interner> = {
        RefCell::new(Interner::fresh())
    });
    INTERNER.with(|interner| f(&mut *interner.borrow_mut()))
}

/// Represents a string stored in the thread-local interner. Because the
/// interner lives for the life of the thread, this can be safely treated as an
/// immortal string, as long as it never crosses between threads.
///
/// FIXME(pcwalton): You must be careful about what you do in the destructors
/// of objects stored in TLS, because they may run after the interner is
/// destroyed. In particular, they must not access string contents. This can
/// be fixed in the future by just leaking all strings until thread death
/// somehow.
#[derive(Clone, Copy, Hash, PartialOrd, Eq, Ord)]
pub struct InternedString {
    string: &'static str,
}

impl<U: ?Sized> ::std::convert::AsRef<U> for InternedString where str: ::std::convert::AsRef<U> {
    fn as_ref(&self) -> &U {
        self.string.as_ref()
    }
}

impl<T: ::std::ops::Deref<Target = str>> ::std::cmp::PartialEq<T> for InternedString {
    fn eq(&self, other: &T) -> bool {
        self.string == other.deref()
    }
}

impl ::std::cmp::PartialEq<InternedString> for str {
    fn eq(&self, other: &InternedString) -> bool {
        self == other.string
    }
}

impl<'a> ::std::cmp::PartialEq<InternedString> for &'a str {
    fn eq(&self, other: &InternedString) -> bool {
        *self == other.string
    }
}

impl ::std::cmp::PartialEq<InternedString> for String {
    fn eq(&self, other: &InternedString) -> bool {
        self == other.string
    }
}

impl<'a> ::std::cmp::PartialEq<InternedString> for &'a String {
    fn eq(&self, other: &InternedString) -> bool {
        *self == other.string
    }
}

impl !Send for InternedString { }

impl ::std::ops::Deref for InternedString {
    type Target = str;
    fn deref(&self) -> &str { self.string }
}

impl fmt::Debug for InternedString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(self.string, f)
    }
}

impl fmt::Display for InternedString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self.string, f)
    }
}

impl Decodable for InternedString {
    fn decode<D: Decoder>(d: &mut D) -> Result<InternedString, D::Error> {
        Ok(Symbol::intern(&d.read_str()?).as_str())
    }
}

impl Encodable for InternedString {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_str(self.string)
    }
}

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

    #[test]
    fn interner_tests() {
        let mut i: Interner = Interner::new();
        // first one is zero:
        assert_eq!(i.intern("dog"), Symbol(0));
        // re-use gets the same entry:
        assert_eq!(i.intern ("dog"), Symbol(0));
        // different string gets a different #:
        assert_eq!(i.intern("cat"), Symbol(1));
        assert_eq!(i.intern("cat"), Symbol(1));
        // dog is still at zero
        assert_eq!(i.intern("dog"), Symbol(0));
        assert_eq!(i.gensym("zebra"), Symbol(4294967295));
        // gensym of same string gets new number :
        assert_eq!(i.gensym("zebra"), Symbol(4294967294));
        // gensym of *existing* string gets new number:
        assert_eq!(i.gensym("dog"), Symbol(4294967293));
    }
}
<commit_msg>Rollup merge of #44223 - eddyb:symbol-from-str, r=jseyfried<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

//! An "interner" is a data structure that associates values with usize tags and
//! allows bidirectional lookup; i.e. given a value, one can easily find the
//! type, and vice versa.

use hygiene::SyntaxContext;

use serialize::{Decodable, Decoder, Encodable, Encoder};
use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt;

#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct Ident {
    pub name: Symbol,
    pub ctxt: SyntaxContext,
}

impl Ident {
    pub const fn with_empty_ctxt(name: Symbol) -> Ident {
        Ident { name: name, ctxt: SyntaxContext::empty() }
    }

    /// Maps a string to an identifier with an empty syntax context.
    pub fn from_str(string: &str) -> Ident {
        Ident::with_empty_ctxt(Symbol::intern(string))
    }

    pub fn modern(self) -> Ident {
        Ident { name: self.name, ctxt: self.ctxt.modern() }
    }
}

impl fmt::Debug for Ident {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}{:?}", self.name, self.ctxt)
    }
}

impl fmt::Display for Ident {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.name, f)
    }
}

impl Encodable for Ident {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        if self.ctxt.modern() == SyntaxContext::empty() {
            s.emit_str(&self.name.as_str())
        } else { // FIXME(jseyfried) intercrate hygiene
            let mut string = "#".to_owned();
            string.push_str(&self.name.as_str());
            s.emit_str(&string)
        }
    }
}

impl Decodable for Ident {
    fn decode<D: Decoder>(d: &mut D) -> Result<Ident, D::Error> {
        let string = d.read_str()?;
        Ok(if !string.starts_with('#') {
            Ident::from_str(&string)
        } else { // FIXME(jseyfried) intercrate hygiene
            Ident::with_empty_ctxt(Symbol::gensym(&string[1..]))
        })
    }
}

/// A symbol is an interned or gensymed string.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Symbol(u32);

// The interner in thread-local, so `Symbol` shouldn't move between threads.
impl !Send for Symbol { }
impl !Sync for Symbol { }

impl Symbol {
    /// Maps a string to its interned representation.
    pub fn intern(string: &str) -> Self {
        with_interner(|interner| interner.intern(string))
    }

    pub fn interned(self) -> Self {
        with_interner(|interner| interner.interned(self))
    }

    /// gensym's a new usize, using the current interner.
    pub fn gensym(string: &str) -> Self {
        with_interner(|interner| interner.gensym(string))
    }

    pub fn gensymed(self) -> Self {
        with_interner(|interner| interner.gensymed(self))
    }

    pub fn as_str(self) -> InternedString {
        with_interner(|interner| unsafe {
            InternedString {
                string: ::std::mem::transmute::<&str, &str>(interner.get(self))
            }
        })
    }

    pub fn as_u32(self) -> u32 {
        self.0
    }
}

impl<'a> From<&'a str> for Symbol {
    fn from(string: &'a str) -> Symbol {
        Symbol::intern(string)
    }
}

impl fmt::Debug for Symbol {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}({})", self, self.0)
    }
}

impl fmt::Display for Symbol {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.as_str(), f)
    }
}

impl Encodable for Symbol {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_str(&self.as_str())
    }
}

impl Decodable for Symbol {
    fn decode<D: Decoder>(d: &mut D) -> Result<Symbol, D::Error> {
        Ok(Symbol::intern(&d.read_str()?))
    }
}

impl<T: ::std::ops::Deref<Target=str>> PartialEq<T> for Symbol {
    fn eq(&self, other: &T) -> bool {
        self.as_str() == other.deref()
    }
}

#[derive(Default)]
pub struct Interner {
    names: HashMap<Box<str>, Symbol>,
    strings: Vec<Box<str>>,
    gensyms: Vec<Symbol>,
}

impl Interner {
    pub fn new() -> Self {
        Interner::default()
    }

    fn prefill(init: &[&str]) -> Self {
        let mut this = Interner::new();
        for &string in init {
            this.intern(string);
        }
        this
    }

    pub fn intern(&mut self, string: &str) -> Symbol {
        if let Some(&name) = self.names.get(string) {
            return name;
        }

        let name = Symbol(self.strings.len() as u32);
        let string = string.to_string().into_boxed_str();
        self.strings.push(string.clone());
        self.names.insert(string, name);
        name
    }

    pub fn interned(&self, symbol: Symbol) -> Symbol {
        if (symbol.0 as usize) < self.strings.len() {
            symbol
        } else {
            self.interned(self.gensyms[(!0 - symbol.0) as usize])
        }
    }

    fn gensym(&mut self, string: &str) -> Symbol {
        let symbol = self.intern(string);
        self.gensymed(symbol)
    }

    fn gensymed(&mut self, symbol: Symbol) -> Symbol {
        self.gensyms.push(symbol);
        Symbol(!0 - self.gensyms.len() as u32 + 1)
    }

    pub fn get(&self, symbol: Symbol) -> &str {
        match self.strings.get(symbol.0 as usize) {
            Some(ref string) => string,
            None => self.get(self.gensyms[(!0 - symbol.0) as usize]),
        }
    }
}

// In this macro, there is the requirement that the name (the number) must be monotonically
// increasing by one in the special identifiers, starting at 0; the same holds for the keywords,
// except starting from the next number instead of zero.
macro_rules! declare_keywords {(
    $( ($index: expr, $konst: ident, $string: expr) )*
) => {
    pub mod keywords {
        use super::{Symbol, Ident};
        #[derive(Clone, Copy, PartialEq, Eq)]
        pub struct Keyword {
            ident: Ident,
        }
        impl Keyword {
            #[inline] pub fn ident(self) -> Ident { self.ident }
            #[inline] pub fn name(self) -> Symbol { self.ident.name }
        }
        $(
            #[allow(non_upper_case_globals)]
            pub const $konst: Keyword = Keyword {
                ident: Ident::with_empty_ctxt(super::Symbol($index))
            };
        )*
    }

    impl Interner {
        fn fresh() -> Self {
            Interner::prefill(&[$($string,)*])
        }
    }
}}

// NB: leaving holes in the ident table is bad! a different ident will get
// interned with the id from the hole, but it will be between the min and max
// of the reserved words, and thus tagged as "reserved".
// After modifying this list adjust `is_special_ident`, `is_used_keyword`/`is_unused_keyword`,
// this should be rarely necessary though if the keywords are kept in alphabetic order.
declare_keywords! {
    // Special reserved identifiers used internally for elided lifetimes,
    // unnamed method parameters, crate root module, error recovery etc.
    (0,  Invalid,        "")
    (1,  CrateRoot,      "{{root}}")
    (2,  DollarCrate,    "$crate")

    // Keywords used in the language.
    (3,  As,             "as")
    (4,  Box,            "box")
    (5,  Break,          "break")
    (6,  Const,          "const")
    (7,  Continue,       "continue")
    (8,  Crate,          "crate")
    (9,  Else,           "else")
    (10, Enum,           "enum")
    (11, Extern,         "extern")
    (12, False,          "false")
    (13, Fn,             "fn")
    (14, For,            "for")
    (15, If,             "if")
    (16, Impl,           "impl")
    (17, In,             "in")
    (18, Let,            "let")
    (19, Loop,           "loop")
    (20, Match,          "match")
    (21, Mod,            "mod")
    (22, Move,           "move")
    (23, Mut,            "mut")
    (24, Pub,            "pub")
    (25, Ref,            "ref")
    (26, Return,         "return")
    (27, SelfValue,      "self")
    (28, SelfType,       "Self")
    (29, Static,         "static")
    (30, Struct,         "struct")
    (31, Super,          "super")
    (32, Trait,          "trait")
    (33, True,           "true")
    (34, Type,           "type")
    (35, Unsafe,         "unsafe")
    (36, Use,            "use")
    (37, Where,          "where")
    (38, While,          "while")

    // Keywords reserved for future use.
    (39, Abstract,       "abstract")
    (40, Alignof,        "alignof")
    (41, Become,         "become")
    (42, Do,             "do")
    (43, Final,          "final")
    (44, Macro,          "macro")
    (45, Offsetof,       "offsetof")
    (46, Override,       "override")
    (47, Priv,           "priv")
    (48, Proc,           "proc")
    (49, Pure,           "pure")
    (50, Sizeof,         "sizeof")
    (51, Typeof,         "typeof")
    (52, Unsized,        "unsized")
    (53, Virtual,        "virtual")
    (54, Yield,          "yield")

    // Weak keywords, have special meaning only in specific contexts.
    (55, Default,        "default")
    (56, StaticLifetime, "'static")
    (57, Union,          "union")
    (58, Catch,          "catch")
}

// If an interner exists in TLS, return it. Otherwise, prepare a fresh one.
fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
    thread_local!(static INTERNER: RefCell<Interner> = {
        RefCell::new(Interner::fresh())
    });
    INTERNER.with(|interner| f(&mut *interner.borrow_mut()))
}

/// Represents a string stored in the thread-local interner. Because the
/// interner lives for the life of the thread, this can be safely treated as an
/// immortal string, as long as it never crosses between threads.
///
/// FIXME(pcwalton): You must be careful about what you do in the destructors
/// of objects stored in TLS, because they may run after the interner is
/// destroyed. In particular, they must not access string contents. This can
/// be fixed in the future by just leaking all strings until thread death
/// somehow.
#[derive(Clone, Copy, Hash, PartialOrd, Eq, Ord)]
pub struct InternedString {
    string: &'static str,
}

impl<U: ?Sized> ::std::convert::AsRef<U> for InternedString where str: ::std::convert::AsRef<U> {
    fn as_ref(&self) -> &U {
        self.string.as_ref()
    }
}

impl<T: ::std::ops::Deref<Target = str>> ::std::cmp::PartialEq<T> for InternedString {
    fn eq(&self, other: &T) -> bool {
        self.string == other.deref()
    }
}

impl ::std::cmp::PartialEq<InternedString> for str {
    fn eq(&self, other: &InternedString) -> bool {
        self == other.string
    }
}

impl<'a> ::std::cmp::PartialEq<InternedString> for &'a str {
    fn eq(&self, other: &InternedString) -> bool {
        *self == other.string
    }
}

impl ::std::cmp::PartialEq<InternedString> for String {
    fn eq(&self, other: &InternedString) -> bool {
        self == other.string
    }
}

impl<'a> ::std::cmp::PartialEq<InternedString> for &'a String {
    fn eq(&self, other: &InternedString) -> bool {
        *self == other.string
    }
}

impl !Send for InternedString { }

impl ::std::ops::Deref for InternedString {
    type Target = str;
    fn deref(&self) -> &str { self.string }
}

impl fmt::Debug for InternedString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(self.string, f)
    }
}

impl fmt::Display for InternedString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self.string, f)
    }
}

impl Decodable for InternedString {
    fn decode<D: Decoder>(d: &mut D) -> Result<InternedString, D::Error> {
        Ok(Symbol::intern(&d.read_str()?).as_str())
    }
}

impl Encodable for InternedString {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_str(self.string)
    }
}

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

    #[test]
    fn interner_tests() {
        let mut i: Interner = Interner::new();
        // first one is zero:
        assert_eq!(i.intern("dog"), Symbol(0));
        // re-use gets the same entry:
        assert_eq!(i.intern ("dog"), Symbol(0));
        // different string gets a different #:
        assert_eq!(i.intern("cat"), Symbol(1));
        assert_eq!(i.intern("cat"), Symbol(1));
        // dog is still at zero
        assert_eq!(i.intern("dog"), Symbol(0));
        assert_eq!(i.gensym("zebra"), Symbol(4294967295));
        // gensym of same string gets new number :
        assert_eq!(i.gensym("zebra"), Symbol(4294967294));
        // gensym of *existing* string gets new number:
        assert_eq!(i.gensym("dog"), Symbol(4294967293));
    }
}
<|endoftext|>