<commit_before>// Copyright 2014 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.

use std::collections::HashSet;
use std::ffi;
use std::fmt;
use std::mem;
use std::str;
use super::gl;

use gfx::device::Capabilities;
use gfx::device::shade;

/// A version number for a specific component of an OpenGL implementation
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Version {
    pub major: u32,
    pub minor: u32,
    pub revision: Option<u32>,
    pub vendor_info: &'static str,
}

// FIXME https://github.com/rust-lang/rust/issues/18738
// derive

#[automatically_derived]
impl ::std::cmp::Ord for Version {
    #[inline]
    fn cmp(&self, other: &Version) -> ::std::cmp::Ordering {
        (&self.major, &self.minor, &self.revision, self.vendor_info)
            .cmp(&(&other.major, &other.minor, &other.revision, other.vendor_info))
    }
}
#[automatically_derived]
impl ::std::cmp::PartialOrd for Version {
    #[inline]
    fn partial_cmp(&self, other: &Version) -> ::std::option::Option<::std::cmp::Ordering> {
        (&self.major, &self.minor, &self.revision, self.vendor_info)
            .partial_cmp(&(&other.major, &other.minor, &other.revision, other.vendor_info))
    }
}

impl Version {
    /// Create a new OpenGL version number
    pub fn new(major: u32, minor: u32, revision: Option<u32>,
               vendor_info: &'static str) -> Version {
        Version {
            major: major,
            minor: minor,
            revision: revision,
            vendor_info: vendor_info,
        }
    }

    /// According to the OpenGL specification, the version information is
    /// expected to follow the following syntax:
    ///
    /// ~~~bnf
    /// <major>       ::= <number>
    /// <minor>       ::= <number>
    /// <revision>    ::= <number>
    /// <vendor-info> ::= <string>
    /// <release>     ::= <major> "." <minor> ["." <release>]
    /// <version>     ::= <release> [" " <vendor-info>]
    /// ~~~
    ///
    /// Note that this function is intentionally lenient in regards to parsing,
    /// and will try to recover at least the first two version numbers without
    /// resulting in an `Err`.
    pub fn parse(src: &'static str) -> Result<Version, &'static str> {
        let (version, vendor_info) = match src.find(' ') {
            Some(i) => (&src[..i], &src[(i + 1)..]),
            None => (src, ""),
        };

        // TODO: make this even more lenient so that we can also accept
        // `<major> "." <minor> [<???>]`
        let mut it = version.split('.');
        let major = it.next().and_then(|s| s.parse().ok());
        let minor = it.next().and_then(|s| s.parse().ok());
        let revision = it.next().and_then(|s| s.parse().ok());

        match (major, minor, revision) {
            (Some(major), Some(minor), revision) => Ok(Version {
                major: major,
                minor: minor,
                revision: revision,
                vendor_info: vendor_info,
            }),
            (_, _, _) => Err(src),
        }
    }
}

impl fmt::Debug for Version {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match (self.major, self.minor, self.revision, self.vendor_info) {
            (major, minor, Some(revision), "") =>
                write!(f, "{}.{}.{}", major, minor, revision),
            (major, minor, None, "") =>
                write!(f, "{}.{}", major, minor),
            (major, minor, Some(revision), vendor_info) =>
                write!(f, "{}.{}.{}, {}", major, minor, revision, vendor_info),
            (major, minor, None, vendor_info) =>
                write!(f, "{}.{}, {}", major, minor, vendor_info),
        }
    }
}

const EMPTY_STRING: &'static str = "";

/// Get a statically allocated string from the implementation using
/// `glGetString`. Fails if it `GLenum` cannot be handled by the
/// implementation's `gl.GetString` function.
fn get_string(gl: &gl::Gl, name: gl::types::GLenum) -> &'static str {
    let ptr = unsafe { gl.GetString(name) } as *const i8;
    if !ptr.is_null() {
        // This should be safe to mark as statically allocated because
        // GlGetString only returns static strings.
        unsafe { c_str_as_static_str(ptr) }
    } else {
        error!("Invalid GLenum passed to `get_string`: {:x}", name);
        EMPTY_STRING
    }
}

fn get_usize(gl: &gl::Gl, name: gl::types::GLenum) -> usize {
    let mut value = 0 as gl::types::GLint;
    unsafe { gl.GetIntegerv(name, &mut value) };
    value as usize
}

unsafe fn c_str_as_static_str(c_str: *const i8) -> &'static str {
    mem::transmute(str::from_utf8(ffi::CStr::from_ptr(c_str).to_bytes()).unwrap())
}

/// A unique platform identifier that does not change between releases
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct PlatformName {
    /// The company responsible for the OpenGL implementation
    pub vendor: &'static str,
    /// The name of the renderer
    pub renderer: &'static str,
}

impl PlatformName {
    fn get(gl: &gl::Gl) -> PlatformName {
        PlatformName {
            vendor: get_string(gl, gl::VENDOR),
            renderer: get_string(gl, gl::RENDERER),
        }
    }
}

/// OpenGL implementation information
#[derive(Debug)]
pub struct Info {
    /// The platform identifier
    pub platform_name: PlatformName,
    /// The OpenGL API vesion number
    pub version: Version,
    /// The GLSL vesion number
    pub shading_language: Version,
    /// The extensions supported by the implementation
    pub extensions: HashSet<&'static str>,
}

impl Info {
    fn get(gl: &gl::Gl) -> Info {
        let platform_name = PlatformName::get(gl);
        let version = Version::parse(get_string(gl, gl::VERSION)).unwrap();
        let shading_language = Version::parse(get_string(gl, gl::SHADING_LANGUAGE_VERSION)).unwrap();
        let extensions = if version >= Version::new(3, 2, None, "") {
            let num_exts = get_usize(gl, gl::NUM_EXTENSIONS) as gl::types::GLuint;
            (0..num_exts)
                .map(|i| unsafe { c_str_as_static_str(gl.GetStringi(gl::EXTENSIONS, i) as *const i8) })
                .collect()
        } else {
            // Fallback
            get_string(gl, gl::EXTENSIONS).split(' ').collect()
        };
        Info {
            platform_name: platform_name,
            version: version,
            shading_language: shading_language,
            extensions: extensions,
        }
    }

    /// Returns `true` if the implementation supports the extension
    pub fn is_extension_supported(&self, s: &'static str) -> bool {
        self.extensions.contains(&s)
    }

    pub fn is_version_or_extension_supported(&self, major: u32, minor: u32, ext: &'static str) -> bool {
        self.version >= Version::new(major, minor, None, "") || self.is_extension_supported(ext)
    }
}

fn to_shader_model(v: &Version) -> shade::ShaderModel {
    use gfx::device::shade::ShaderModel;
    match v {
        v if *v < Version::new(1, 20, None, "") => ShaderModel::Unsupported,
        v if *v < Version::new(1, 50, None, "") => ShaderModel::Version30,
        v if *v < Version::new(3,  0, None, "") => ShaderModel::Version40,
        v if *v < Version::new(4, 30, None, "") => ShaderModel::Version41,
        _                                       => ShaderModel::Version50,
    }
}

/// Load the information pertaining to the driver and the corresponding device
/// capabilities.
pub fn get(gl: &gl::Gl) -> (Info, Capabilities) {
    let info = Info::get(gl);
    let caps = Capabilities {
        shader_model:                   to_shader_model(&info.shading_language),

        max_vertex_count:               get_usize(gl, gl::MAX_ELEMENTS_VERTICES),
        max_index_count:                get_usize(gl, gl::MAX_ELEMENTS_INDICES),
        max_draw_buffers:               get_usize(gl, gl::MAX_DRAW_BUFFERS),
        max_texture_size:               get_usize(gl, gl::MAX_TEXTURE_SIZE),
        max_vertex_attributes:          get_usize(gl, gl::MAX_VERTEX_ATTRIBS),

        buffer_role_change_allowed:     true, //TODO

        array_buffer_supported:         info.is_version_or_extension_supported(3, 0, "GL_ARB_vertex_array_object"),
        fragment_output_supported:      info.is_version_or_extension_supported(3, 0, "GL_ARB_gpu_shader4"),
        immutable_storage_supported:    info.is_version_or_extension_supported(4, 2, "GL_ARB_texture_storage"),
        instance_base_supported:        info.is_version_or_extension_supported(4, 2, "GL_ARB_base_instance"),
        instance_call_supported:        info.is_version_or_extension_supported(3, 1, "GL_ARB_draw_instanced"),
        instance_rate_supported:        info.is_version_or_extension_supported(3, 3, "GL_ARB_instanced_arrays"),
        render_targets_supported:       info.is_version_or_extension_supported(3, 0, "GL_ARB_framebuffer_object"),
        srgb_color_supported:           info.is_version_or_extension_supported(3, 2, "GL_ARB_framebuffer_sRGB"),
        sampler_objects_supported:      info.is_version_or_extension_supported(3, 3, "GL_ARB_sampler_objects"),
        uniform_block_supported:        info.is_version_or_extension_supported(3, 0, "GL_ARB_uniform_buffer_object"),
        vertex_base_supported:          info.is_version_or_extension_supported(3, 2, "GL_ARB_draw_elements_base_vertex"),
    };
    (info, caps)
}

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

    #[test]
    fn test_version_parse() {
        assert_eq!(Version::parse("1"), Err("1"));
        assert_eq!(Version::parse("1."), Err("1."));
        assert_eq!(Version::parse("1 h3l1o. W0rld"), Err("1 h3l1o. W0rld"));
        assert_eq!(Version::parse("1. h3l1o. W0rld"), Err("1. h3l1o. W0rld"));
        assert_eq!(Version::parse("1.2.3"), Ok(Version::new(1, 2, Some(3), "")));
        assert_eq!(Version::parse("1.2"), Ok(Version::new(1, 2, None, "")));
        assert_eq!(Version::parse("1.2 h3l1o. W0rld"), Ok(Version::new(1, 2, None, "h3l1o. W0rld")));
        assert_eq!(Version::parse("1.2.h3l1o. W0rld"), Ok(Version::new(1, 2, None, "W0rld")));
        assert_eq!(Version::parse("1.2. h3l1o. W0rld"), Ok(Version::new(1, 2, None, "h3l1o. W0rld")));
        assert_eq!(Version::parse("1.2.3.h3l1o. W0rld"), Ok(Version::new(1, 2, Some(3), "W0rld")));
        assert_eq!(Version::parse("1.2.3 h3l1o. W0rld"), Ok(Version::new(1, 2, Some(3), "h3l1o. W0rld")));
    }

    #[test]
    fn test_shader_model() {
        use gfx::device::shade::ShaderModel;
        assert_eq!(to_shader_model(&Version::parse("1.10").unwrap()), ShaderModel::Unsupported);
        assert_eq!(to_shader_model(&Version::parse("1.20").unwrap()), ShaderModel::Version30);
        assert_eq!(to_shader_model(&Version::parse("1.50").unwrap()), ShaderModel::Version40);
        assert_eq!(to_shader_model(&Version::parse("3.00").unwrap()), ShaderModel::Version41);
        assert_eq!(to_shader_model(&Version::parse("4.30").unwrap()), ShaderModel::Version50);
    }
}
<commit_msg>Auto merge of #781 - fkaa:fix-typo, r=kvark<commit_after>// Copyright 2014 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.

use std::collections::HashSet;
use std::ffi;
use std::fmt;
use std::mem;
use std::str;
use super::gl;

use gfx::device::Capabilities;
use gfx::device::shade;

/// A version number for a specific component of an OpenGL implementation
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Version {
    pub major: u32,
    pub minor: u32,
    pub revision: Option<u32>,
    pub vendor_info: &'static str,
}

// FIXME https://github.com/rust-lang/rust/issues/18738
// derive

#[automatically_derived]
impl ::std::cmp::Ord for Version {
    #[inline]
    fn cmp(&self, other: &Version) -> ::std::cmp::Ordering {
        (&self.major, &self.minor, &self.revision, self.vendor_info)
            .cmp(&(&other.major, &other.minor, &other.revision, other.vendor_info))
    }
}
#[automatically_derived]
impl ::std::cmp::PartialOrd for Version {
    #[inline]
    fn partial_cmp(&self, other: &Version) -> ::std::option::Option<::std::cmp::Ordering> {
        (&self.major, &self.minor, &self.revision, self.vendor_info)
            .partial_cmp(&(&other.major, &other.minor, &other.revision, other.vendor_info))
    }
}

impl Version {
    /// Create a new OpenGL version number
    pub fn new(major: u32, minor: u32, revision: Option<u32>,
               vendor_info: &'static str) -> Version {
        Version {
            major: major,
            minor: minor,
            revision: revision,
            vendor_info: vendor_info,
        }
    }

    /// According to the OpenGL specification, the version information is
    /// expected to follow the following syntax:
    ///
    /// ~~~bnf
    /// <major>       ::= <number>
    /// <minor>       ::= <number>
    /// <revision>    ::= <number>
    /// <vendor-info> ::= <string>
    /// <release>     ::= <major> "." <minor> ["." <release>]
    /// <version>     ::= <release> [" " <vendor-info>]
    /// ~~~
    ///
    /// Note that this function is intentionally lenient in regards to parsing,
    /// and will try to recover at least the first two version numbers without
    /// resulting in an `Err`.
    pub fn parse(src: &'static str) -> Result<Version, &'static str> {
        let (version, vendor_info) = match src.find(' ') {
            Some(i) => (&src[..i], &src[(i + 1)..]),
            None => (src, ""),
        };

        // TODO: make this even more lenient so that we can also accept
        // `<major> "." <minor> [<???>]`
        let mut it = version.split('.');
        let major = it.next().and_then(|s| s.parse().ok());
        let minor = it.next().and_then(|s| s.parse().ok());
        let revision = it.next().and_then(|s| s.parse().ok());

        match (major, minor, revision) {
            (Some(major), Some(minor), revision) => Ok(Version {
                major: major,
                minor: minor,
                revision: revision,
                vendor_info: vendor_info,
            }),
            (_, _, _) => Err(src),
        }
    }
}

impl fmt::Debug for Version {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match (self.major, self.minor, self.revision, self.vendor_info) {
            (major, minor, Some(revision), "") =>
                write!(f, "{}.{}.{}", major, minor, revision),
            (major, minor, None, "") =>
                write!(f, "{}.{}", major, minor),
            (major, minor, Some(revision), vendor_info) =>
                write!(f, "{}.{}.{}, {}", major, minor, revision, vendor_info),
            (major, minor, None, vendor_info) =>
                write!(f, "{}.{}, {}", major, minor, vendor_info),
        }
    }
}

const EMPTY_STRING: &'static str = "";

/// Get a statically allocated string from the implementation using
/// `glGetString`. Fails if it `GLenum` cannot be handled by the
/// implementation's `gl.GetString` function.
fn get_string(gl: &gl::Gl, name: gl::types::GLenum) -> &'static str {
    let ptr = unsafe { gl.GetString(name) } as *const i8;
    if !ptr.is_null() {
        // This should be safe to mark as statically allocated because
        // GlGetString only returns static strings.
        unsafe { c_str_as_static_str(ptr) }
    } else {
        error!("Invalid GLenum passed to `get_string`: {:x}", name);
        EMPTY_STRING
    }
}

fn get_usize(gl: &gl::Gl, name: gl::types::GLenum) -> usize {
    let mut value = 0 as gl::types::GLint;
    unsafe { gl.GetIntegerv(name, &mut value) };
    value as usize
}

unsafe fn c_str_as_static_str(c_str: *const i8) -> &'static str {
    mem::transmute(str::from_utf8(ffi::CStr::from_ptr(c_str).to_bytes()).unwrap())
}

/// A unique platform identifier that does not change between releases
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct PlatformName {
    /// The company responsible for the OpenGL implementation
    pub vendor: &'static str,
    /// The name of the renderer
    pub renderer: &'static str,
}

impl PlatformName {
    fn get(gl: &gl::Gl) -> PlatformName {
        PlatformName {
            vendor: get_string(gl, gl::VENDOR),
            renderer: get_string(gl, gl::RENDERER),
        }
    }
}

/// OpenGL implementation information
#[derive(Debug)]
pub struct Info {
    /// The platform identifier
    pub platform_name: PlatformName,
    /// The OpenGL API vesion number
    pub version: Version,
    /// The GLSL vesion number
    pub shading_language: Version,
    /// The extensions supported by the implementation
    pub extensions: HashSet<&'static str>,
}

impl Info {
    fn get(gl: &gl::Gl) -> Info {
        let platform_name = PlatformName::get(gl);
        let version = Version::parse(get_string(gl, gl::VERSION)).unwrap();
        let shading_language = Version::parse(get_string(gl, gl::SHADING_LANGUAGE_VERSION)).unwrap();
        let extensions = if version >= Version::new(3, 2, None, "") {
            let num_exts = get_usize(gl, gl::NUM_EXTENSIONS) as gl::types::GLuint;
            (0..num_exts)
                .map(|i| unsafe { c_str_as_static_str(gl.GetStringi(gl::EXTENSIONS, i) as *const i8) })
                .collect()
        } else {
            // Fallback
            get_string(gl, gl::EXTENSIONS).split(' ').collect()
        };
        Info {
            platform_name: platform_name,
            version: version,
            shading_language: shading_language,
            extensions: extensions,
        }
    }

    /// Returns `true` if the implementation supports the extension
    pub fn is_extension_supported(&self, s: &'static str) -> bool {
        self.extensions.contains(&s)
    }

    pub fn is_version_or_extension_supported(&self, major: u32, minor: u32, ext: &'static str) -> bool {
        self.version >= Version::new(major, minor, None, "") || self.is_extension_supported(ext)
    }
}

fn to_shader_model(v: &Version) -> shade::ShaderModel {
    use gfx::device::shade::ShaderModel;
    match v {
        v if *v < Version::new(1, 20, None, "") => ShaderModel::Unsupported,
        v if *v < Version::new(1, 50, None, "") => ShaderModel::Version30,
        v if *v < Version::new(3,  0, None, "") => ShaderModel::Version40,
        v if *v < Version::new(4, 30, None, "") => ShaderModel::Version41,
        _                                       => ShaderModel::Version50,
    }
}

/// Load the information pertaining to the driver and the corresponding device
/// capabilities.
pub fn get(gl: &gl::Gl) -> (Info, Capabilities) {
    let info = Info::get(gl);
    let caps = Capabilities {
        shader_model:                   to_shader_model(&info.shading_language),

        max_vertex_count:               get_usize(gl, gl::MAX_ELEMENTS_VERTICES),
        max_index_count:                get_usize(gl, gl::MAX_ELEMENTS_INDICES),
        max_draw_buffers:               get_usize(gl, gl::MAX_DRAW_BUFFERS),
        max_texture_size:               get_usize(gl, gl::MAX_TEXTURE_SIZE),
        max_vertex_attributes:          get_usize(gl, gl::MAX_VERTEX_ATTRIBS),

        buffer_role_change_allowed:     true, //TODO

        array_buffer_supported:         info.is_version_or_extension_supported(3, 0, "GL_ARB_vertex_array_object"),
        fragment_output_supported:      info.is_version_or_extension_supported(3, 0, "GL_EXT_gpu_shader4"),
        immutable_storage_supported:    info.is_version_or_extension_supported(4, 2, "GL_ARB_texture_storage"),
        instance_base_supported:        info.is_version_or_extension_supported(4, 2, "GL_ARB_base_instance"),
        instance_call_supported:        info.is_version_or_extension_supported(3, 1, "GL_ARB_draw_instanced"),
        instance_rate_supported:        info.is_version_or_extension_supported(3, 3, "GL_ARB_instanced_arrays"),
        render_targets_supported:       info.is_version_or_extension_supported(3, 0, "GL_ARB_framebuffer_object"),
        srgb_color_supported:           info.is_version_or_extension_supported(3, 2, "GL_ARB_framebuffer_sRGB"),
        sampler_objects_supported:      info.is_version_or_extension_supported(3, 3, "GL_ARB_sampler_objects"),
        uniform_block_supported:        info.is_version_or_extension_supported(3, 0, "GL_ARB_uniform_buffer_object"),
        vertex_base_supported:          info.is_version_or_extension_supported(3, 2, "GL_ARB_draw_elements_base_vertex"),
    };
    (info, caps)
}

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

    #[test]
    fn test_version_parse() {
        assert_eq!(Version::parse("1"), Err("1"));
        assert_eq!(Version::parse("1."), Err("1."));
        assert_eq!(Version::parse("1 h3l1o. W0rld"), Err("1 h3l1o. W0rld"));
        assert_eq!(Version::parse("1. h3l1o. W0rld"), Err("1. h3l1o. W0rld"));
        assert_eq!(Version::parse("1.2.3"), Ok(Version::new(1, 2, Some(3), "")));
        assert_eq!(Version::parse("1.2"), Ok(Version::new(1, 2, None, "")));
        assert_eq!(Version::parse("1.2 h3l1o. W0rld"), Ok(Version::new(1, 2, None, "h3l1o. W0rld")));
        assert_eq!(Version::parse("1.2.h3l1o. W0rld"), Ok(Version::new(1, 2, None, "W0rld")));
        assert_eq!(Version::parse("1.2. h3l1o. W0rld"), Ok(Version::new(1, 2, None, "h3l1o. W0rld")));
        assert_eq!(Version::parse("1.2.3.h3l1o. W0rld"), Ok(Version::new(1, 2, Some(3), "W0rld")));
        assert_eq!(Version::parse("1.2.3 h3l1o. W0rld"), Ok(Version::new(1, 2, Some(3), "h3l1o. W0rld")));
    }

    #[test]
    fn test_shader_model() {
        use gfx::device::shade::ShaderModel;
        assert_eq!(to_shader_model(&Version::parse("1.10").unwrap()), ShaderModel::Unsupported);
        assert_eq!(to_shader_model(&Version::parse("1.20").unwrap()), ShaderModel::Version30);
        assert_eq!(to_shader_model(&Version::parse("1.50").unwrap()), ShaderModel::Version40);
        assert_eq!(to_shader_model(&Version::parse("3.00").unwrap()), ShaderModel::Version41);
        assert_eq!(to_shader_model(&Version::parse("4.30").unwrap()), ShaderModel::Version50);
    }
}
<|endoftext|>


<commit_before>// Code from snake-ncurses by Johannes Schickling <schickling.j@gmail.com>,
// https://github.com/schickling/rust-examples/tree/master/snake-ncurses
// minor revisions accoring to changed rust-spedicifactions were made in
// order to successfully compile the code, game.rs and main.rs were
// merged into specialcrate.rs. Snake-Ncurses was published under MIT license.

extern crate rand;

use self::rand::Rng;

pub enum GameError { Wall, Suicide }

#[derive(PartialEq, Copy)]
pub struct Vector {
    pub x: i32,
    pub y: i32,
}

impl Vector {
    fn next (&self, dir: Direction) -> Vector {
        let (dx, dy) = match dir {
            Direction::Up => (0, -1),
            Direction::Down => (0, 1),
            Direction::Left => (-1, 0),
            Direction::Right => (1, 0),
        };

        Vector {
            x: self.x + dx,
            y: self.y + dy,
        }
    }

    fn random (bounds: Vector) -> Vector {
        let mut rng = rand::thread_rng();
        Vector {
            x: rng.gen_range::<>(0, bounds.x),
            y: rng.gen_range::<>(0, bounds.y),
        }
    }
}

impl Clone for Vector {

    fn clone(&self) -> Self {
        Vector { x : self.x, y : self.y}
    }

    fn clone_from(&mut self, source: &Self) {
        self.x = source.x;
        self.y = source.y;
    }

}

pub struct Board {
    bounds: Vector,
    snake: Snake,
    bullet: Vector,
}

impl Board {

    pub fn new (bounds: Vector) -> Board {
        Board {
            bounds: bounds,
            snake: Snake::new(Vector { x: bounds.x / 2, y: bounds.y / 2 }),
            bullet: Vector::random(bounds),
        }
    }

    pub fn set_direction (&mut self, dir: Direction) {
        self.snake.direction = dir;
    }

    pub fn tick (&mut self) -> Result<(), GameError> {

        self.snake.step();

        if self.snake.eats_bullet(self.bullet) {
            self.snake.grow();
            self.bullet = Vector::random(self.bounds);
        }

        if self.snake.hits_wall(self.bounds) {
            Err(GameError::Wall)
        } else if self.snake.hits_itself() {
            Err(GameError::Suicide)
        } else {
            Ok(())
        }

    }

    pub fn get_snake_vectors (&self) -> &[Vector] {
        let ref v = self.snake.segments;
        &v[..]
    }

    pub fn get_bullet_vector (&self) -> &Vector {
        &self.bullet
    }

}

struct Snake {
    segments: Vec<Vector>,
    direction: Direction,
    popped_segment: Vector,
}

impl Snake {

    fn new (pos: Vector) -> Snake {
        Snake {
            segments: vec!(pos),
            direction: Direction::Up,
            popped_segment: Vector { x: 0, y: 0 }
        }
    }

    fn step (&mut self) {
        let new_head = self.segments[0].next(self.direction);
        self.segments.insert(0, new_head);
        self.popped_segment = self.segments.pop().unwrap();
    }

    fn hits_wall (&self, bounds: Vector) -> bool {
        let head = self.segments[0];
        head.x < 0 || head.x == bounds.x || head.y < 0 || head.y == bounds.y
    }

    fn hits_itself (&self) -> bool {
        self.segments.iter().skip(1).any(|s| *s == self.segments[0] )
    }

    fn grow (&mut self) {
        self.segments.push(self.popped_segment);
    }

    fn eats_bullet (&self, bullet: Vector) -> bool {
        self.segments[0] == bullet
    }

}

// This was the code in main.rs

extern crate ncurses;
//extern crate rand;

use std::thread::sleep_ms as sleep;
//use std::time::duration::Duration;
use self::ncurses::*;
//use game::*;

//mod game;

pub fn snake()
{
    initscr();
    cbreak(); // enable <Ctrl+C> to kill game
    noecho(); // don't show input
    keypad(stdscr, true); // make keys work
    curs_set(CURSOR_VISIBILITY::CURSOR_INVISIBLE);
    timeout(100); // tick speed

    let mut bounds = Vector { x: 0, y: 0 };
    getmaxyx(stdscr, &mut bounds.y, &mut bounds.x);

    let mut board = Board::new(bounds);

    let mut direction = Direction::Up;

    loop {
        erase();

        {
            let bullet = board.get_bullet_vector();
            draw_char(bullet, 'o');
        }

        {
            let segments = board.get_snake_vectors();
            for segment in segments.iter() {
                draw_char(segment, '#');
            }
        }

        direction = get_new_direction(direction);
        board.set_direction(direction);

        match board.tick() {
            Err(err) => {
                match err {
                    GameError::Wall => show_text("You hit the wall, stupid."),
                    GameError::Suicide => show_text("Damn it. Stop eating yourself."),
                }
                //let two_secs = Duration::new(2, 0);
                sleep(2000);
                break;
            },
            Ok(_) => (),
        };
    }

    endwin();
}

fn draw_char (pos: &Vector, c: char) {
    mvaddch(pos.y, pos.x, c as u64);
}

fn get_new_direction (prev_dir: Direction) -> Direction {
    match getch() {
        KEY_UP if prev_dir != Direction::Down => Direction::Up,
        KEY_DOWN if prev_dir != Direction::Up => Direction::Down,
        KEY_LEFT if prev_dir != Direction::Right => Direction::Left,
        KEY_RIGHT if prev_dir != Direction::Left => Direction::Right,
        _ => prev_dir,
    }
}

fn show_text (s: &str) {
    erase();
    addstr(s);
    refresh();
}

// Below is space invaders code

#[derive(PartialEq,Copy,Clone)]
pub enum Direction { Up, Down, Left, Right }

pub enum GameStatus { Win, Running, Dead }

pub struct Game {
    bounds: Vector,
    invaders: Vec<Invader>,
    player: Player,
    bullets: Vec<Bullet>,
}

impl Game {

    pub fn new (bounds: Vector) -> Game {

        let mut invaders = vec!();
        //for i in range(0i32, bounds.x / 3) {
        for i in 0i32..(bounds.x / 3) {
            invaders.push(Invader::new( Vector { x: 2 * i, y: 0 }));
        }

        Game {
            bounds: bounds,
            invaders: invaders,
            player: Player::new(Vector { x: bounds.x / 2, y: bounds.y - 1 }),
            bullets: vec!(),
        }
    }

    pub fn tick (&mut self) -> GameStatus {

        for invader in self.invaders.iter_mut() {
            match invader.give_chance_to_fire() {
                Some(bullet) => self.bullets.push(bullet),
                None => (),
            };
            invader.tick(self.bounds);
        }

        for bullet in self.bullets.iter_mut() {
            bullet.tick(self.bounds);

            self.invaders.retain(|i| !bullet.check_collision(i.position));

            if bullet.check_collision(self.player.position) {
                return GameStatus::Dead;
            }
        }

        if self.invaders.is_empty() {
            GameStatus::Win
        } else {
            GameStatus::Running
        }

    }

    pub fn shift (&mut self, dir: Direction) {
        self.player.shift(dir, self.bounds);
    }

    pub fn fire (&mut self) {
        self.bullets.push(self.player.fire());
    }

    pub fn get_player_vector (&self) -> &Vector {
        &self.player.position
    }

    pub fn get_invader_vectors (&self) -> Vec<Vector> {
        self.invaders.iter().map(|i| i.position).collect()
    }

    pub fn get_bullet_vectors (&self) -> Vec<Vector> {
        self.bullets.iter().map(|b| b.position).collect()
    }

}

struct Invader {
    position: Vector,
    direction: Direction,
}

impl Invader {

    fn new (pos: Vector) -> Invader {
        Invader {
            position: pos,
            direction: Direction::Left,
        }
    }

    fn tick (&mut self, bounds: Vector) {
        let x = &mut self.position.x;
        self.direction = match self.direction {
            Direction::Left if *x < 0 => Direction::Right,
            Direction::Right if *x == bounds.x => Direction::Left,
            _ => self.direction.clone()
        };
        match self.direction {
            Direction::Left => *x = *x - 1,
            Direction::Right => *x = *x + 1,
            _ => (),
        };
    }

    fn give_chance_to_fire (&self) -> Option<Bullet> {
        let mut rng = rand::thread_rng();
        let temp: f32 = rng.gen_range(0.0, 1.0);
        if temp > 0.996 {
            Some(Bullet::new(Vector { x: self.position.x, y: self.position.y + 1 }, Direction::Down))
        } else {
            None
        }
    }

}

struct Player {
    position: Vector,
}

impl Player {

    fn new (pos: Vector) -> Player {
        Player { position: pos }
    }

    fn shift (&mut self, dir: Direction, bounds: Vector) {
        let x = &mut self.position.x;
        match dir {
            Direction::Left if *x > 0 => *x = *x - 1,
            Direction::Right if *x < bounds.x - 1 => *x = *x + 1,
            _ => (),
        }
    }

    fn fire (&self) -> Bullet {
        Bullet::new(Vector { x: self.position.x, y: self.position.y - 1 }, Direction::Up)
    }

}

struct Bullet {
    position: Vector,
    direction: Direction,
}

impl Bullet {

    fn new (pos: Vector, dir: Direction) -> Bullet {
        Bullet {
            position: pos,
            direction: dir,
        }
    }

    fn tick (&mut self, bounds: Vector) {
        match self.direction {
            Direction::Up => self.position.y -= 1,
            Direction::Down => self.position.y += 1,
            _ => (),
        };
        if self.position.y < 0 || self.position.y == bounds.y {
            drop(self);
        }
    }

    fn check_collision (&self, other: Vector) -> bool {
        self.position == other
    }

}
// blow is code from main.rs

pub fn space_invaders()
{
    initscr();
    cbreak(); // enable <Ctrl+C> to kill game
    noecho(); // don't show input
    keypad(stdscr, true); // make keys work
    curs_set(CURSOR_VISIBILITY::CURSOR_INVISIBLE);
    timeout(1);

    let mut bounds = Vector { x: 0, y: 0};
    getmaxyx(stdscr, &mut bounds.y, &mut bounds.x);

    let mut game = Box::new(Game::new(bounds));

    // TODO rewrite async
    let mut tick_count = 0u8;

    loop {
        tick_count += 1;
        tick_count %= 30;

        erase();

        {
            let player = game.get_player_vector();
            draw_char(player, 'X');
        }

        {
            let invaders = game.get_invader_vectors();
            for invader in invaders.iter() {
                draw_char(invader, '#');
            }
        }

        {
            let bullets = game.get_bullet_vectors();
            for bullet in bullets.iter() {
                draw_char(bullet, '.');
            }
        }

        match getch() {
            KEY_LEFT => game.shift(Direction::Left),
            KEY_RIGHT => game.shift(Direction::Right),
            KEY_UP => game.fire(),
            _ => (),
        }

        if tick_count == 0 {
            match game.tick() {
                GameStatus::Dead => {
                    show_text("Puny human!");
                    sleep(2000);
                    break;
                },
                GameStatus::Win => {
                    show_text("Garglargl");
                    sleep(2000);
                    break;
                },
                GameStatus::Running => (),
            };
        }
    }

    endwin();
}
<commit_msg>Update specialcrate.rs<commit_after>// Code by Johannes Schickling <schickling.j@gmail.com>,
// https://github.com/schickling/rust-examples/tree/master/snake-ncurses
// minor revisions accoring to changed rust-spedicifactions were made in
// order to successfully compile the code, game.rs and main.rs were
// merged into specialcrate.rs. Code was published under MIT license.

extern crate rand;

use self::rand::Rng;

pub enum GameError { Wall, Suicide }

#[derive(PartialEq, Copy)]
pub struct Vector {
    pub x: i32,
    pub y: i32,
}

impl Vector {
    fn next (&self, dir: Direction) -> Vector {
        let (dx, dy) = match dir {
            Direction::Up => (0, -1),
            Direction::Down => (0, 1),
            Direction::Left => (-1, 0),
            Direction::Right => (1, 0),
        };

        Vector {
            x: self.x + dx,
            y: self.y + dy,
        }
    }

    fn random (bounds: Vector) -> Vector {
        let mut rng = rand::thread_rng();
        Vector {
            x: rng.gen_range::<>(0, bounds.x),
            y: rng.gen_range::<>(0, bounds.y),
        }
    }
}

impl Clone for Vector {

    fn clone(&self) -> Self {
        Vector { x : self.x, y : self.y}
    }

    fn clone_from(&mut self, source: &Self) {
        self.x = source.x;
        self.y = source.y;
    }

}

pub struct Board {
    bounds: Vector,
    snake: Snake,
    bullet: Vector,
}

impl Board {

    pub fn new (bounds: Vector) -> Board {
        Board {
            bounds: bounds,
            snake: Snake::new(Vector { x: bounds.x / 2, y: bounds.y / 2 }),
            bullet: Vector::random(bounds),
        }
    }

    pub fn set_direction (&mut self, dir: Direction) {
        self.snake.direction = dir;
    }

    pub fn tick (&mut self) -> Result<(), GameError> {

        self.snake.step();

        if self.snake.eats_bullet(self.bullet) {
            self.snake.grow();
            self.bullet = Vector::random(self.bounds);
        }

        if self.snake.hits_wall(self.bounds) {
            Err(GameError::Wall)
        } else if self.snake.hits_itself() {
            Err(GameError::Suicide)
        } else {
            Ok(())
        }

    }

    pub fn get_snake_vectors (&self) -> &[Vector] {
        let ref v = self.snake.segments;
        &v[..]
    }

    pub fn get_bullet_vector (&self) -> &Vector {
        &self.bullet
    }

}

struct Snake {
    segments: Vec<Vector>,
    direction: Direction,
    popped_segment: Vector,
}

impl Snake {

    fn new (pos: Vector) -> Snake {
        Snake {
            segments: vec!(pos),
            direction: Direction::Up,
            popped_segment: Vector { x: 0, y: 0 }
        }
    }

    fn step (&mut self) {
        let new_head = self.segments[0].next(self.direction);
        self.segments.insert(0, new_head);
        self.popped_segment = self.segments.pop().unwrap();
    }

    fn hits_wall (&self, bounds: Vector) -> bool {
        let head = self.segments[0];
        head.x < 0 || head.x == bounds.x || head.y < 0 || head.y == bounds.y
    }

    fn hits_itself (&self) -> bool {
        self.segments.iter().skip(1).any(|s| *s == self.segments[0] )
    }

    fn grow (&mut self) {
        self.segments.push(self.popped_segment);
    }

    fn eats_bullet (&self, bullet: Vector) -> bool {
        self.segments[0] == bullet
    }

}

// This was the code in main.rs

extern crate ncurses;
//extern crate rand;

use std::thread::sleep_ms as sleep;
//use std::time::duration::Duration;
use self::ncurses::*;
//use game::*;

//mod game;

pub fn snake()
{
    initscr();
    cbreak(); // enable <Ctrl+C> to kill game
    noecho(); // don't show input
    keypad(stdscr, true); // make keys work
    curs_set(CURSOR_VISIBILITY::CURSOR_INVISIBLE);
    timeout(100); // tick speed

    let mut bounds = Vector { x: 0, y: 0 };
    getmaxyx(stdscr, &mut bounds.y, &mut bounds.x);

    let mut board = Board::new(bounds);

    let mut direction = Direction::Up;

    loop {
        erase();

        {
            let bullet = board.get_bullet_vector();
            draw_char(bullet, 'o');
        }

        {
            let segments = board.get_snake_vectors();
            for segment in segments.iter() {
                draw_char(segment, '#');
            }
        }

        direction = get_new_direction(direction);
        board.set_direction(direction);

        match board.tick() {
            Err(err) => {
                match err {
                    GameError::Wall => show_text("You hit the wall, stupid."),
                    GameError::Suicide => show_text("Damn it. Stop eating yourself."),
                }
                //let two_secs = Duration::new(2, 0);
                sleep(2000);
                break;
            },
            Ok(_) => (),
        };
    }

    endwin();
}

fn draw_char (pos: &Vector, c: char) {
    mvaddch(pos.y, pos.x, c as u64);
}

fn get_new_direction (prev_dir: Direction) -> Direction {
    match getch() {
        KEY_UP if prev_dir != Direction::Down => Direction::Up,
        KEY_DOWN if prev_dir != Direction::Up => Direction::Down,
        KEY_LEFT if prev_dir != Direction::Right => Direction::Left,
        KEY_RIGHT if prev_dir != Direction::Left => Direction::Right,
        _ => prev_dir,
    }
}

fn show_text (s: &str) {
    erase();
    addstr(s);
    refresh();
}

// Below is space invaders code

#[derive(PartialEq,Copy,Clone)]
pub enum Direction { Up, Down, Left, Right }

pub enum GameStatus { Win, Running, Dead }

pub struct Game {
    bounds: Vector,
    invaders: Vec<Invader>,
    player: Player,
    bullets: Vec<Bullet>,
}

impl Game {

    pub fn new (bounds: Vector) -> Game {

        let mut invaders = vec!();
        //for i in range(0i32, bounds.x / 3) {
        for i in 0i32..(bounds.x / 3) {
            invaders.push(Invader::new( Vector { x: 2 * i, y: 0 }));
        }

        Game {
            bounds: bounds,
            invaders: invaders,
            player: Player::new(Vector { x: bounds.x / 2, y: bounds.y - 1 }),
            bullets: vec!(),
        }
    }

    pub fn tick (&mut self) -> GameStatus {

        for invader in self.invaders.iter_mut() {
            match invader.give_chance_to_fire() {
                Some(bullet) => self.bullets.push(bullet),
                None => (),
            };
            invader.tick(self.bounds);
        }

        for bullet in self.bullets.iter_mut() {
            bullet.tick(self.bounds);

            self.invaders.retain(|i| !bullet.check_collision(i.position));

            if bullet.check_collision(self.player.position) {
                return GameStatus::Dead;
            }
        }

        if self.invaders.is_empty() {
            GameStatus::Win
        } else {
            GameStatus::Running
        }

    }

    pub fn shift (&mut self, dir: Direction) {
        self.player.shift(dir, self.bounds);
    }

    pub fn fire (&mut self) {
        self.bullets.push(self.player.fire());
    }

    pub fn get_player_vector (&self) -> &Vector {
        &self.player.position
    }

    pub fn get_invader_vectors (&self) -> Vec<Vector> {
        self.invaders.iter().map(|i| i.position).collect()
    }

    pub fn get_bullet_vectors (&self) -> Vec<Vector> {
        self.bullets.iter().map(|b| b.position).collect()
    }

}

struct Invader {
    position: Vector,
    direction: Direction,
}

impl Invader {

    fn new (pos: Vector) -> Invader {
        Invader {
            position: pos,
            direction: Direction::Left,
        }
    }

    fn tick (&mut self, bounds: Vector) {
        let x = &mut self.position.x;
        self.direction = match self.direction {
            Direction::Left if *x < 0 => Direction::Right,
            Direction::Right if *x == bounds.x => Direction::Left,
            _ => self.direction.clone()
        };
        match self.direction {
            Direction::Left => *x = *x - 1,
            Direction::Right => *x = *x + 1,
            _ => (),
        };
    }

    fn give_chance_to_fire (&self) -> Option<Bullet> {
        let mut rng = rand::thread_rng();
        let temp: f32 = rng.gen_range(0.0, 1.0);
        if temp > 0.996 {
            Some(Bullet::new(Vector { x: self.position.x, y: self.position.y + 1 }, Direction::Down))
        } else {
            None
        }
    }

}

struct Player {
    position: Vector,
}

impl Player {

    fn new (pos: Vector) -> Player {
        Player { position: pos }
    }

    fn shift (&mut self, dir: Direction, bounds: Vector) {
        let x = &mut self.position.x;
        match dir {
            Direction::Left if *x > 0 => *x = *x - 1,
            Direction::Right if *x < bounds.x - 1 => *x = *x + 1,
            _ => (),
        }
    }

    fn fire (&self) -> Bullet {
        Bullet::new(Vector { x: self.position.x, y: self.position.y - 1 }, Direction::Up)
    }

}

struct Bullet {
    position: Vector,
    direction: Direction,
}

impl Bullet {

    fn new (pos: Vector, dir: Direction) -> Bullet {
        Bullet {
            position: pos,
            direction: dir,
        }
    }

    fn tick (&mut self, bounds: Vector) {
        match self.direction {
            Direction::Up => self.position.y -= 1,
            Direction::Down => self.position.y += 1,
            _ => (),
        };
        if self.position.y < 0 || self.position.y == bounds.y {
            drop(self);
        }
    }

    fn check_collision (&self, other: Vector) -> bool {
        self.position == other
    }

}
// blow is code from main.rs

pub fn space_invaders()
{
    initscr();
    cbreak(); // enable <Ctrl+C> to kill game
    noecho(); // don't show input
    keypad(stdscr, true); // make keys work
    curs_set(CURSOR_VISIBILITY::CURSOR_INVISIBLE);
    timeout(1);

    let mut bounds = Vector { x: 0, y: 0};
    getmaxyx(stdscr, &mut bounds.y, &mut bounds.x);

    let mut game = Box::new(Game::new(bounds));

    // TODO rewrite async
    let mut tick_count = 0u8;

    loop {
        tick_count += 1;
        tick_count %= 30;

        erase();

        {
            let player = game.get_player_vector();
            draw_char(player, 'X');
        }

        {
            let invaders = game.get_invader_vectors();
            for invader in invaders.iter() {
                draw_char(invader, '#');
            }
        }

        {
            let bullets = game.get_bullet_vectors();
            for bullet in bullets.iter() {
                draw_char(bullet, '.');
            }
        }

        match getch() {
            KEY_LEFT => game.shift(Direction::Left),
            KEY_RIGHT => game.shift(Direction::Right),
            KEY_UP => game.fire(),
            _ => (),
        }

        if tick_count == 0 {
            match game.tick() {
                GameStatus::Dead => {
                    show_text("Puny human!");
                    sleep(2000);
                    break;
                },
                GameStatus::Win => {
                    show_text("Garglargl");
                    sleep(2000);
                    break;
                },
                GameStatus::Running => (),
            };
        }
    }

    endwin();
}
<|endoftext|>


<commit_before>import util.common.span;
import std._uint;

obj session() {
    fn span_err(span sp, str msg) {
        let str s =  sp.filename;
        s += ':' as u8;
        // We really need #fmt soon!
        s += _uint.to_str(sp.lo.line, 10u);
        s += ':' as u8;
        s += _uint.to_str(sp.lo.col, 10u);
        s += ':' as u8;
        s += _uint.to_str(sp.hi.line, 10u);
        s += ':' as u8;
        s += _uint.to_str(sp.hi.col, 10u);
        s += ": error: ";
        s += msg;
        log s;
        fail;
    }

    fn err(str msg) {
        let str s = "error: ";
        s += msg;
        log s;
        fail;
    }

    fn unimpl(str msg) {
        let str s = "error: unimplemented ";
        s += msg;
        log s;
        fail;
    }
}

// Local Variables:
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>Rewrite session formatting to use #fmt extension.<commit_after>import util.common.span;
import std._uint;

obj session() {
    fn span_err(span sp, str msg) {
        log #fmt("%s:%u:%u:%u:%u: error: %s",
                 sp.filename,
                 sp.lo.line, sp.lo.col,
                 sp.hi.line, sp.hi.col,
                 msg);
        fail;
    }

    fn err(str msg) {
        log #fmt("error: %s", msg);
        fail;
    }

    fn unimpl(str msg) {
        log #fmt("error: unimplemented %s", msg);
        fail;
    }
}

// Local Variables:
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before>import core::{vec, uint, str, option, result};
import option::{some, none};

type filename = str;

type file_pos = {ch: uint, byte: uint};

/* A codemap is a thing that maps uints to file/line/column positions
 * in a crate. This to make it possible to represent the positions
 * with single-word things, rather than passing records all over the
 * compiler.
 */
type filemap =
    @{name: filename, src: @str,
      start_pos: file_pos, mutable lines: [file_pos]};

type codemap = @{mutable files: [filemap]};

type loc = {filename: filename, line: uint, col: uint};

fn new_codemap() -> codemap { ret @{mutable files: []}; }

fn new_filemap(filename: filename, src: @str,
               start_pos_ch: uint, start_pos_byte: uint)
   -> filemap {
    ret @{name: filename, src: src,
          start_pos: {ch: start_pos_ch, byte: start_pos_byte},
          mutable lines: [{ch: start_pos_ch, byte: start_pos_byte}]};
}

fn next_line(file: filemap, chpos: uint, byte_pos: uint) {
    file.lines += [{ch: chpos, byte: byte_pos}];
}

type lookup_fn = fn@(file_pos) -> uint;

fn lookup_pos(map: codemap, pos: uint, lookup: lookup_fn) -> loc {
    let len = vec::len(map.files);
    let a = 0u;
    let b = len;
    while b - a > 1u {
        let m = (a + b) / 2u;
        if lookup(map.files[m].start_pos) > pos { b = m; } else { a = m; }
    }
    if (a >= len) {
        ret { filename: "-", line: 0u, col: 0u };
    }
    let f = map.files[a];
    a = 0u;
    b = vec::len(f.lines);
    while b - a > 1u {
        let m = (a + b) / 2u;
        if lookup(f.lines[m]) > pos { b = m; } else { a = m; }
    }
    ret {filename: f.name, line: a + 1u, col: pos - lookup(f.lines[a])};
}

fn lookup_char_pos(map: codemap, pos: uint) -> loc {
    fn lookup(pos: file_pos) -> uint { ret pos.ch; }
    ret lookup_pos(map, pos, lookup);
}

fn lookup_byte_pos(map: codemap, pos: uint) -> loc {
    fn lookup(pos: file_pos) -> uint { ret pos.byte; }
    ret lookup_pos(map, pos, lookup);
}

enum opt_span {

    //hack (as opposed to option), to make `span` compile
    os_none,
    os_some(@span),
}
type span = {lo: uint, hi: uint, expanded_from: opt_span};

fn span_to_str(sp: span, cm: codemap) -> str {
    let cur = sp;
    let res = "";
    let prev_file = none;
    while true {
        let lo = lookup_char_pos(cm, cur.lo);
        let hi = lookup_char_pos(cm, cur.hi);
        res +=
            #fmt["%s:%u:%u: %u:%u",
                 if some(lo.filename) == prev_file {
                     "-"
                 } else { lo.filename }, lo.line, lo.col, hi.line, hi.col];
        alt cur.expanded_from {
          os_none { break; }
          os_some(new_sp) {
            cur = *new_sp;
            prev_file = some(lo.filename);
            res += "<<";
          }
        }
    }

    ret res;
}

type file_lines = {name: str, lines: [uint]};

fn span_to_lines(sp: span, cm: codemap::codemap) -> @file_lines {
    let lo = lookup_char_pos(cm, sp.lo);
    let hi = lookup_char_pos(cm, sp.hi);
    let lines = [];
    uint::range(lo.line - 1u, hi.line as uint) {|i| lines += [i]; };
    ret @{name: lo.filename, lines: lines};
}

fn get_line(fm: filemap, line: int) -> str unsafe {
    let begin: uint = fm.lines[line].byte - fm.start_pos.byte;
    let end: uint;
    if line as uint < vec::len(fm.lines) - 1u {
        end = fm.lines[line + 1].byte - fm.start_pos.byte;
    } else {
        // If we're not done parsing the file, we're at the limit of what's
        // parsed. If we just slice the rest of the string, we'll print out
        // the remainder of the file, which is undesirable.
        end = str::byte_len(*fm.src);
        let rest = str::unsafe::slice_bytes(*fm.src, begin, end);
        let newline = str::index(rest, '\n' as u8);
        if newline != -1 { end = begin + (newline as uint); }
    }
    ret str::unsafe::slice_bytes(*fm.src, begin, end);
}

fn get_filemap(cm: codemap, filename: str) -> filemap {
    for fm: filemap in cm.files { if fm.name == filename { ret fm; } }
    //XXjdm the following triggers a mismatched type bug
    //      (or expected function, found _|_)
    fail; // ("asking for " + filename + " which we don't know about");
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//
<commit_msg>Add function to get a code snippet from a span, and also to get the byte offset within a string from a span chpos.<commit_after>import core::{vec, uint, str, option, result};
import option::{some, none};

type filename = str;

type file_pos = {ch: uint, byte: uint};

/* A codemap is a thing that maps uints to file/line/column positions
 * in a crate. This to make it possible to represent the positions
 * with single-word things, rather than passing records all over the
 * compiler.
 */
type filemap =
    @{name: filename, src: @str,
      start_pos: file_pos, mutable lines: [file_pos]};

type codemap = @{mutable files: [filemap]};

type loc = {filename: filename, line: uint, col: uint};

fn new_codemap() -> codemap { ret @{mutable files: []}; }

fn new_filemap(filename: filename, src: @str,
               start_pos_ch: uint, start_pos_byte: uint)
   -> filemap {
    ret @{name: filename, src: src,
          start_pos: {ch: start_pos_ch, byte: start_pos_byte},
          mutable lines: [{ch: start_pos_ch, byte: start_pos_byte}]};
}

fn next_line(file: filemap, chpos: uint, byte_pos: uint) {
    file.lines += [{ch: chpos, byte: byte_pos}];
}

type lookup_fn = fn@(file_pos) -> uint;

fn lookup_line(map: codemap, pos: uint, lookup: lookup_fn)
    -> option::t<{fm: filemap, line: uint}>
{
    let len = vec::len(map.files);
    let a = 0u;
    let b = len;
    while b - a > 1u {
        let m = (a + b) / 2u;
        if lookup(map.files[m].start_pos) > pos { b = m; } else { a = m; }
    }
    if (a >= len) {
        ret none;
    }
    let f = map.files[a];
    a = 0u;
    b = vec::len(f.lines);
    while b - a > 1u {
        let m = (a + b) / 2u;
        if lookup(f.lines[m]) > pos { b = m; } else { a = m; }
    }
    ret some({fm: f, line: a});
}

fn lookup_pos(map: codemap, pos: uint, lookup: lookup_fn) -> loc {
    alt lookup_line(map, pos, lookup) {
      some({fm: f, line: a}) {
        {filename: f.name, line: a + 1u, col: pos - lookup(f.lines[a])}
      }
      none {
        { filename: "-", line: 0u, col: 0u }
      }
    }
}

fn lookup_char_pos(map: codemap, pos: uint) -> loc {
    fn lookup(pos: file_pos) -> uint { ret pos.ch; }
    ret lookup_pos(map, pos, lookup);
}

fn lookup_byte_pos(map: codemap, pos: uint) -> loc {
    fn lookup(pos: file_pos) -> uint { ret pos.byte; }
    ret lookup_pos(map, pos, lookup);
}

enum opt_span {

    //hack (as opposed to option), to make `span` compile
    os_none,
    os_some(@span),
}
type span = {lo: uint, hi: uint, expanded_from: opt_span};

fn span_to_str(sp: span, cm: codemap) -> str {
    let cur = sp;
    let res = "";
    let prev_file = none;
    while true {
        let lo = lookup_char_pos(cm, cur.lo);
        let hi = lookup_char_pos(cm, cur.hi);
        res +=
            #fmt["%s:%u:%u: %u:%u",
                 if some(lo.filename) == prev_file {
                     "-"
                 } else { lo.filename }, lo.line, lo.col, hi.line, hi.col];
        alt cur.expanded_from {
          os_none { break; }
          os_some(new_sp) {
            cur = *new_sp;
            prev_file = some(lo.filename);
            res += "<<";
          }
        }
    }

    ret res;
}

type file_lines = {name: str, lines: [uint]};

fn span_to_lines(sp: span, cm: codemap::codemap) -> @file_lines {
    let lo = lookup_char_pos(cm, sp.lo);
    let hi = lookup_char_pos(cm, sp.hi);
    let lines = [];
    uint::range(lo.line - 1u, hi.line as uint) {|i| lines += [i]; };
    ret @{name: lo.filename, lines: lines};
}

fn get_line(fm: filemap, line: int) -> str unsafe {
    let begin: uint = fm.lines[line].byte - fm.start_pos.byte;
    let end: uint;
    if line as uint < vec::len(fm.lines) - 1u {
        end = fm.lines[line + 1].byte - fm.start_pos.byte;
    } else {
        // If we're not done parsing the file, we're at the limit of what's
        // parsed. If we just slice the rest of the string, we'll print out
        // the remainder of the file, which is undesirable.
        end = str::byte_len(*fm.src);
        let rest = str::unsafe::slice_bytes(*fm.src, begin, end);
        let newline = str::index(rest, '\n' as u8);
        if newline != -1 { end = begin + (newline as uint); }
    }
    ret str::unsafe::slice_bytes(*fm.src, begin, end);
}

fn lookup_byte_offset(cm: codemap::codemap, chpos: uint)
    -> {fm: filemap, pos: uint}
{
    fn lookup(pos: file_pos) -> uint { ret pos.ch; }
    let {fm,line} = option::get(lookup_line(cm,chpos,lookup));
    let line_offset = fm.lines[line].byte;
    let col = chpos - fm.lines[line].ch;
    let col_offset = str::byte_len_range(*fm.src, line_offset, col);
    ret {fm: fm, pos: line_offset + col_offset};
}

fn span_to_snippet(sp: span, cm: codemap::codemap) -> str {
    let begin = lookup_byte_offset(cm,sp.lo);
    let end   = lookup_byte_offset(cm,sp.hi);
    assert begin.fm == end.fm;
    ret str::slice(*begin.fm.src, begin.pos, end.pos);
}

fn get_snippet(cm: codemap::codemap, fidx: uint, lo: uint, hi: uint) -> str
{
    let fm = cm.files[fidx];
    ret str::slice(*fm.src, lo, hi)
}

fn get_filemap(cm: codemap, filename: str) -> filemap {
    for fm: filemap in cm.files { if fm.name == filename { ret fm; } }
    //XXjdm the following triggers a mismatched type bug
    //      (or expected function, found _|_)
    fail; // ("asking for " + filename + " which we don't know about");
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//
<|endoftext|>


<commit_before>extern crate sdl2;

use sdl2::audio::{AudioCallback, AudioSpecDesired};
use sdl2::AudioSubsystem;
use std::time::Duration;
use std::sync::mpsc;
use std::i16;

const RECORDING_LENGTH_SECONDS: usize = 3;

struct Recording {
    record_buffer: Vec<i16>,
    pos: usize,
    done_sender: mpsc::Sender<Vec<i16>>,
    done: bool,
}

// Append the input of the callback to the record_buffer.
// When the record_buffer is full, send it to the main thread via done_sender.
impl AudioCallback for Recording {
    type Channel = i16;

    fn callback(&mut self, input: &mut [i16]) {
        if self.done {
            return;
        }

        for x in input {
            self.record_buffer[self.pos] = *x;
            self.pos += 1;
            if self.pos >= self.record_buffer.len() {
                self.done = true;
                self.done_sender.send(self.record_buffer.clone()).unwrap();
                break;
            }
        }
    }
}

fn record(audio_subsystem: &AudioSubsystem, desired_spec: &AudioSpecDesired) -> Vec<i16> {
    println!("Capturing {:} seconds... Please rock!", RECORDING_LENGTH_SECONDS);

    let (done_sender, done_receiver) = mpsc::channel();

    let capture_device = audio_subsystem.open_capture(None, &desired_spec, |spec| {
        println!("Capture Spec = {:?}", spec);
        Recording {
            record_buffer: vec![0; spec.freq as usize * RECORDING_LENGTH_SECONDS * spec.channels as usize],
            pos: 0,
            done_sender,
            done: false
        }
    }).unwrap();

    println!("AudioDriver: {:?}", capture_device.subsystem().current_audio_driver());
    capture_device.resume();

    // Wait until the recording is done.
    let recorded_vec = done_receiver.recv().unwrap();

    capture_device.pause();

    // Device is automatically closed when dropped.
    // Depending on your system it might be even important that the capture_device is dropped
    // before the playback starts.

    recorded_vec
}

/// Returns a percent value
fn calculate_average_volume(recorded_vec: &[i16]) -> f32 {
    let sum: i64 = recorded_vec.iter().map(|&x| (x as i64).abs()).sum();
    (sum as f32) / (recorded_vec.len() as f32) / (i16::MAX as f32) * 100.0
}

/// Returns a percent value
fn calculate_max_volume(recorded_vec: &[i16]) -> f32 {
    let max: i64 = recorded_vec.iter().map(|&x| (x as i64).abs()).max().unwrap();
    (max as f32) / (i16::MAX as f32) * 100.0
}

struct SoundPlayback {
    data: Vec<i16>,
    pos: usize,
}

impl AudioCallback for SoundPlayback {
    type Channel = i16;

    fn callback(&mut self, out: &mut [i16]) {
        for dst in out.iter_mut() {
            *dst = *self.data.get(self.pos).unwrap_or(&0);
            self.pos += 1;
        }
    }
}

fn replay_recorded_vec(audio_subsystem: &AudioSubsystem, desired_spec: &AudioSpecDesired, recorded_vec: Vec<i16>) {
    println!("Playing...");

    let playback_device = audio_subsystem.open_playback(None, &desired_spec, |spec| {
        println!("Playback Spec = {:?}", spec);
        SoundPlayback {
            data: recorded_vec,
            pos: 0,
        }
    }).unwrap();

    // Start playback
    playback_device.resume();

    std::thread::sleep(Duration::from_secs(RECORDING_LENGTH_SECONDS as u64));
    // Device is automatically closed when dropped
}

fn main() {
    let sdl_context = sdl2::init().unwrap();
    let audio_subsystem = sdl_context.audio().unwrap();

    let desired_spec = AudioSpecDesired {
        freq: Some(44100),
        channels: None,
        samples: None
    };

    let recorded_vec = record(&audio_subsystem, &desired_spec);

    println!("Average Volume of your Recording = {:?}%", calculate_average_volume(&recorded_vec));
    println!("Max Volume of your Recording = {:?}%", calculate_max_volume(&recorded_vec));

    replay_recorded_vec(&audio_subsystem, &desired_spec, recorded_vec);
}
<commit_msg>Do not specify AudioSpecDesired.freq in audio-capture-and-replay example in order to avoid problems with sound cards, which might not be able to record with 44100 hz.<commit_after>extern crate sdl2;

use sdl2::audio::{AudioCallback, AudioSpecDesired};
use sdl2::AudioSubsystem;
use std::time::Duration;
use std::sync::mpsc;
use std::i16;

const RECORDING_LENGTH_SECONDS: usize = 3;

struct Recording {
    record_buffer: Vec<i16>,
    pos: usize,
    done_sender: mpsc::Sender<Vec<i16>>,
    done: bool,
}

// Append the input of the callback to the record_buffer.
// When the record_buffer is full, send it to the main thread via done_sender.
impl AudioCallback for Recording {
    type Channel = i16;

    fn callback(&mut self, input: &mut [i16]) {
        if self.done {
            return;
        }

        for x in input {
            self.record_buffer[self.pos] = *x;
            self.pos += 1;
            if self.pos >= self.record_buffer.len() {
                self.done = true;
                self.done_sender.send(self.record_buffer.clone()).unwrap();
                break;
            }
        }
    }
}

fn record(audio_subsystem: &AudioSubsystem, desired_spec: &AudioSpecDesired) -> Vec<i16> {
    println!("Capturing {:} seconds... Please rock!", RECORDING_LENGTH_SECONDS);

    let (done_sender, done_receiver) = mpsc::channel();

    let capture_device = audio_subsystem.open_capture(None, &desired_spec, |spec| {
        println!("Capture Spec = {:?}", spec);
        Recording {
            record_buffer: vec![0; spec.freq as usize * RECORDING_LENGTH_SECONDS * spec.channels as usize],
            pos: 0,
            done_sender,
            done: false
        }
    }).unwrap();

    println!("AudioDriver: {:?}", capture_device.subsystem().current_audio_driver());
    capture_device.resume();

    // Wait until the recording is done.
    let recorded_vec = done_receiver.recv().unwrap();

    capture_device.pause();

    // Device is automatically closed when dropped.
    // Depending on your system it might be even important that the capture_device is dropped
    // before the playback starts.

    recorded_vec
}

/// Returns a percent value
fn calculate_average_volume(recorded_vec: &[i16]) -> f32 {
    let sum: i64 = recorded_vec.iter().map(|&x| (x as i64).abs()).sum();
    (sum as f32) / (recorded_vec.len() as f32) / (i16::MAX as f32) * 100.0
}

/// Returns a percent value
fn calculate_max_volume(recorded_vec: &[i16]) -> f32 {
    let max: i64 = recorded_vec.iter().map(|&x| (x as i64).abs()).max().unwrap();
    (max as f32) / (i16::MAX as f32) * 100.0
}

struct SoundPlayback {
    data: Vec<i16>,
    pos: usize,
}

impl AudioCallback for SoundPlayback {
    type Channel = i16;

    fn callback(&mut self, out: &mut [i16]) {
        for dst in out.iter_mut() {
            *dst = *self.data.get(self.pos).unwrap_or(&0);
            self.pos += 1;
        }
    }
}

fn replay_recorded_vec(audio_subsystem: &AudioSubsystem, desired_spec: &AudioSpecDesired, recorded_vec: Vec<i16>) {
    println!("Playing...");

    let playback_device = audio_subsystem.open_playback(None, &desired_spec, |spec| {
        println!("Playback Spec = {:?}", spec);
        SoundPlayback {
            data: recorded_vec,
            pos: 0,
        }
    }).unwrap();

    // Start playback
    playback_device.resume();

    std::thread::sleep(Duration::from_secs(RECORDING_LENGTH_SECONDS as u64));
    // Device is automatically closed when dropped
}

fn main() {
    let sdl_context = sdl2::init().unwrap();
    let audio_subsystem = sdl_context.audio().unwrap();

    let desired_spec = AudioSpecDesired {
        freq: None,
        channels: None,
        samples: None
    };

    let recorded_vec = record(&audio_subsystem, &desired_spec);

    println!("Average Volume of your Recording = {:?}%", calculate_average_volume(&recorded_vec));
    println!("Max Volume of your Recording = {:?}%", calculate_max_volume(&recorded_vec));

    replay_recorded_vec(&audio_subsystem, &desired_spec, recorded_vec);
}
<|endoftext|>


<commit_before>//! Structures for describing and storing collision-related events.

use std::slice::Iter;
use std::iter::IntoIterator;
use query::Proximity;
use pipeline::world::CollisionObjectHandle;

// FIXME: we want a structure where we can add elements, iterate on them, but not remove them
// without clearing the whole structure.
/// A set of events.
pub struct EventPool<E> {
    events: Vec<E>,
}

/// A set of contact events.
pub type ContactEvents = EventPool<ContactEvent>;
/// A set of proximity events.
pub type ProximityEvents = EventPool<ProximityEvent>;

impl<E> EventPool<E> {
    /// Creates a new empty set of events.
    pub fn new() -> EventPool<E> {
        EventPool { events: Vec::new() }
    }

    /// Emties this set of events.
    pub fn clear(&mut self) {
        self.events.clear();
    }

    /// Adds the given event at the end of this set.
    pub fn push(&mut self, event: E) {
        self.events.push(event);
    }

    /// Iterates through all events contained on this set in a FIFO maneer.
    pub fn iter(&self) -> Iter<E> {
        self.events.iter()
    }

    /// Removes from this set all events for which `filter` returns `false`.
    pub fn retain<F>(&mut self, filter: F)
    where
        F: FnMut(&E) -> bool,
    {
        self.events.retain(filter)
    }
}

impl<'a, E> IntoIterator for &'a EventPool<E> {
    type Item = &'a E;
    type IntoIter = Iter<'a, E>;

    fn into_iter(self) -> Iter<'a, E> {
        (&self.events).into_iter()
    }
}

#[derive(Copy, Clone, Hash, Debug)]
/// Events occuring when two collision objects start or stop being in contact (or penetration).
pub enum ContactEvent {
    /// Event occuring when two collision objects start being in contact.
    ///
    /// This event is generated whenever the narrow-phase finds a contact between two collision objects that did not have any contact at the last update.
    Started(CollisionObjectHandle, CollisionObjectHandle),
    /// Event occuring when two collision objects stop being in contact.
    ///
    /// This event is generated whenever the narrow-phase fails to find any contact between two collision objects thit did have at least one contact at the last update.
    Stopped(CollisionObjectHandle, CollisionObjectHandle),
}

#[derive(Copy, Clone, Debug)]
/// Events occuring when two collision objects start or stop being in close proximity, contact, or disjoint.
pub struct ProximityEvent {
    /// The first collider to which the proximity event applies.
    pub collider1: CollisionObjectHandle,
    /// The second collider to which the proximity event applies.
    pub collider2: CollisionObjectHandle,
    /// The previous state of proximity between the two collision objects.
    pub prev_status: Proximity,
    /// The new state of proximity between the two collision objects.
    pub new_status: Proximity,
}

impl ProximityEvent {
    /// Instaciates a new proximity event.
    ///
    /// Panics if `prev_status` is equal to `new_status`.
    pub fn new(
        collider1: CollisionObjectHandle,
        collider2: CollisionObjectHandle,
        prev_status: Proximity,
        new_status: Proximity,
    ) -> ProximityEvent {
        assert!(prev_status != new_status);
        ProximityEvent {
            collider1,
            collider2,
            prev_status,
            new_status,
        }
    }
}
<commit_msg>Fix spelling mistake in ContactEvent documentation.<commit_after>//! Structures for describing and storing collision-related events.

use std::slice::Iter;
use std::iter::IntoIterator;
use query::Proximity;
use pipeline::world::CollisionObjectHandle;

// FIXME: we want a structure where we can add elements, iterate on them, but not remove them
// without clearing the whole structure.
/// A set of events.
pub struct EventPool<E> {
    events: Vec<E>,
}

/// A set of contact events.
pub type ContactEvents = EventPool<ContactEvent>;
/// A set of proximity events.
pub type ProximityEvents = EventPool<ProximityEvent>;

impl<E> EventPool<E> {
    /// Creates a new empty set of events.
    pub fn new() -> EventPool<E> {
        EventPool { events: Vec::new() }
    }

    /// Emties this set of events.
    pub fn clear(&mut self) {
        self.events.clear();
    }

    /// Adds the given event at the end of this set.
    pub fn push(&mut self, event: E) {
        self.events.push(event);
    }

    /// Iterates through all events contained on this set in a FIFO maneer.
    pub fn iter(&self) -> Iter<E> {
        self.events.iter()
    }

    /// Removes from this set all events for which `filter` returns `false`.
    pub fn retain<F>(&mut self, filter: F)
    where
        F: FnMut(&E) -> bool,
    {
        self.events.retain(filter)
    }
}

impl<'a, E> IntoIterator for &'a EventPool<E> {
    type Item = &'a E;
    type IntoIter = Iter<'a, E>;

    fn into_iter(self) -> Iter<'a, E> {
        (&self.events).into_iter()
    }
}

#[derive(Copy, Clone, Hash, Debug)]
/// Events occuring when two collision objects start or stop being in contact (or penetration).
pub enum ContactEvent {
    /// Event occuring when two collision objects start being in contact.
    ///
    /// This event is generated whenever the narrow-phase finds a contact between two collision objects that did not have any contact at the last update.
    Started(CollisionObjectHandle, CollisionObjectHandle),
    /// Event occuring when two collision objects stop being in contact.
    ///
    /// This event is generated whenever the narrow-phase fails to find any contact between two collision objects that did have at least one contact at the last update.
    Stopped(CollisionObjectHandle, CollisionObjectHandle),
}

#[derive(Copy, Clone, Debug)]
/// Events occuring when two collision objects start or stop being in close proximity, contact, or disjoint.
pub struct ProximityEvent {
    /// The first collider to which the proximity event applies.
    pub collider1: CollisionObjectHandle,
    /// The second collider to which the proximity event applies.
    pub collider2: CollisionObjectHandle,
    /// The previous state of proximity between the two collision objects.
    pub prev_status: Proximity,
    /// The new state of proximity between the two collision objects.
    pub new_status: Proximity,
}

impl ProximityEvent {
    /// Instaciates a new proximity event.
    ///
    /// Panics if `prev_status` is equal to `new_status`.
    pub fn new(
        collider1: CollisionObjectHandle,
        collider2: CollisionObjectHandle,
        prev_status: Proximity,
        new_status: Proximity,
    ) -> ProximityEvent {
        assert!(prev_status != new_status);
        ProximityEvent {
            collider1,
            collider2,
            prev_status,
            new_status,
        }
    }
}
<|endoftext|>


<commit_before>#![crate_name = "bindgen"]
#![crate_type = "bin"]

extern crate bindgen;
#[macro_use]
extern crate docopt;
#[macro_use]
extern crate log;
extern crate clang_sys;
extern crate rustc_serialize;

use bindgen::{Bindings, BindgenOptions, LinkType, Logger};
use std::io;
use std::path;
use std::env;
use std::default::Default;
use std::fs;
use std::process::exit;

struct StdLogger;

impl Logger for StdLogger {
    fn error(&self, msg: &str) {
        println!("{}", msg);
    }

    fn warn(&self, msg: &str) {
        println!("{}", msg);
    }
}

const USAGE: &'static str = "
Usage:
    bindgen [options] \
        [--link=<lib>...] \
        [--static-link=<lib>...] \
        [--framework-link=<framework>...] \
        [--match=<name>...] \
        [--raw-line=<raw>...] \
        [--dtor-attr=<attr>...] \
        [--opaque-type=<type>...] \
        [--blacklist-type=<type>...] \
        <input-header> \
        [-- <clang-args>...]

    bindgen (-h | --help)

Options:
    -h, --help                    Display this help message.

    -l=<lib>, --link=<lib>        Link to a dynamic library, can be provided
                                  multiple times.

    --static-link=<lib>           Link to a static library, can be provided
                                  multiple times.

    --framework-link=<framework>  Link to a framework.

    -o=<output-rust-file>         Write bindings to <output-rust-file>
                                  (defaults to stdout)

    --match=<name>                Only output bindings for definitions from
                                  files whose name contains <name>. If multiple
                                  match options are provided, files matching any
                                  rule are bound to.

    --builtins                    Output bindings for builtin definitions (for
                                  example __builtin_va_list)

    --ignore-functions            Don't generate bindings for functions and
                                  methods. This is useful when you only care
                                  about struct layouts.

    --enable-cxx-namespaces       Enable support for C++ namespaces.

    --no-type-renaming            Don't rename types.

    --allow-unknown-types         Don't fail if we encounter types we do not
                                  support, instead treat them as void

    --emit-clang-ast              Output the ast (for debugging purposes)

    --use-msvc-mangling           Handle MSVC C++ ABI mangling; requires that
                                  target be set to (i686|x86_64)-pc-win32

    --override-enum-type=<type>   Override enum type, type name could be
                                    uchar
                                    schar
                                    ushort
                                    sshort
                                    uint
                                    sint
                                    ulong
                                    slong
                                    ulonglong
                                    slonglong

    --raw-line=<raw>              TODO
    --dtor-attr=<attr>            TODO
    --no-class-constants          TODO
    --no-unstable-rust            TODO
    --no-namespaced-constants     TODO
    --no-bitfield-methods         TODO
    --ignore-methods              TODO
    --opaque-type=<type>          TODO
    --blacklist-type=<type>       TODO

    <clang-args>                  Options other than stated above are passed
                                  directly through to clang.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_input_header: String,
    flag_link: Vec<String>,
    flag_static_link: Vec<String>,
    flag_framework_link: Vec<String>,
    flag_o: Option<String>,
    flag_match: Vec<String>,
    flag_builtins: bool,
    flag_ignore_functions: bool,
    flag_enable_cxx_namespaces: bool,
    flag_no_type_renaming: bool,
    flag_allow_unknown_types: bool,
    flag_emit_clang_ast: bool,
    flag_use_msvc_mangling: bool,
    flag_override_enum_type: String,
    flag_raw_line: Vec<String>,
    flag_dtor_attr: Vec<String>,
    flag_no_class_constants: bool,
    flag_no_unstable_rust: bool,
    flag_no_namespaced_constants: bool,
    flag_no_bitfield_methods: bool,
    flag_ignore_methods: bool,
    flag_opaque_type: Vec<String>,
    flag_blacklist_type: Vec<String>,
    arg_clang_args: Vec<String>,
}

type ParseResult<T> = Result<T, String>;

impl Into<ParseResult<(BindgenOptions, Box<io::Write>)>> for Args {
    fn into(mut self) -> Result<(BindgenOptions, Box<io::Write>), String> {
        let mut options: BindgenOptions = Default::default();

        for lib in self.flag_link.drain(..) {
            options.links.push((lib, LinkType::Default));
        }

        for lib in self.flag_static_link.drain(..) {
            options.links.push((lib, LinkType::Static));
        }

        for lib in self.flag_framework_link.drain(..) {
            options.links.push((lib, LinkType::Framework));
        }

        let out = if let Some(ref path_name) = self.flag_o {
            let path = path::Path::new(path_name);
            let file = try!(fs::File::create(path).map_err(|_| {
                format!("Opening {} failed", path_name)
            }));
            Box::new(io::BufWriter::new(file)) as Box<io::Write>
        } else {
            Box::new(io::BufWriter::new(io::stdout())) as Box<io::Write>
        };

        options.match_pat.extend(self.flag_match.drain(..));
        options.builtins = self.flag_builtins;
        options.ignore_functions = self.flag_ignore_functions;
        options.enable_cxx_namespaces = self.flag_enable_cxx_namespaces;
        options.rename_types = !self.flag_no_type_renaming;
        options.fail_on_unknown_type = !self.flag_allow_unknown_types;
        options.emit_ast = self.flag_emit_clang_ast;
        options.msvc_mangling = self.flag_use_msvc_mangling;
        options.override_enum_ty = self.flag_override_enum_type;
        options.raw_lines.extend(self.flag_raw_line.drain(..));
        options.dtor_attrs.extend(self.flag_dtor_attr.drain(..));
        options.class_constants = !self.flag_no_class_constants;
        options.unstable_rust = !self.flag_no_unstable_rust;
        options.namespaced_constants = !self.flag_no_namespaced_constants;
        options.gen_bitfield_methods = !self.flag_no_bitfield_methods;
        options.ignore_methods = self.flag_ignore_methods;
        options.opaque_types.extend(self.flag_opaque_type.drain(..));
        options.blacklist_type.extend(self.flag_blacklist_type.drain(..));
        options.clang_args.extend(self.arg_clang_args.drain(..));
        options.clang_args.push(self.arg_input_header);

        Ok((options, out))
    }
}

pub fn main() {
    let mut bind_args: Vec<_> = env::args().collect();

    if let Some(clang) = clang_sys::support::Clang::find(None) {
        let has_clang_args = bind_args.iter().rposition(|arg| *arg == "--").is_some();
        if !has_clang_args {
            bind_args.push("--".to_owned());
        }

        // TODO: distinguish C and C++ paths? C++'s should be enough, I guess.
        for path in clang.cpp_search_paths.into_iter() {
            if let Ok(path) = path.into_os_string().into_string() {
                bind_args.push("-isystem".to_owned());
                bind_args.push(path);
            }
        }
    }

    let args: Args = docopt::Docopt::new(USAGE)
        .and_then(|d| d.argv(bind_args.iter()).decode())
        .unwrap_or_else(|e| e.exit());

    let logger = StdLogger;
    let result: ParseResult<_> = args.into();
    let (options, out) = result.unwrap_or_else(|msg| {
        logger.error(&msg);
        exit(-1);
    });

    match Bindings::generate(&options, Some(&logger as &Logger), None) {
        Ok(bindings) => match bindings.write(out) {
            Ok(()) => (),
            Err(e) => {
                logger.error(&format!("Unable to write bindings to file. {}", e));
                exit(-1);
            }
        },
        Err(()) => {
            logger.error("Failed to generate bindings".into());
            exit(-1);
        }
    }
}
<commit_msg>Don't add -isystem header args when --target is specified<commit_after>#![crate_name = "bindgen"]
#![crate_type = "bin"]

extern crate bindgen;
#[macro_use]
extern crate docopt;
#[macro_use]
extern crate log;
extern crate clang_sys;
extern crate rustc_serialize;

use bindgen::{Bindings, BindgenOptions, LinkType, Logger};
use std::io;
use std::path;
use std::env;
use std::default::Default;
use std::fs;
use std::process::exit;

struct StdLogger;

impl Logger for StdLogger {
    fn error(&self, msg: &str) {
        println!("{}", msg);
    }

    fn warn(&self, msg: &str) {
        println!("{}", msg);
    }
}

const USAGE: &'static str = "
Usage:
    bindgen [options] \
        [--link=<lib>...] \
        [--static-link=<lib>...] \
        [--framework-link=<framework>...] \
        [--match=<name>...] \
        [--raw-line=<raw>...] \
        [--dtor-attr=<attr>...] \
        [--opaque-type=<type>...] \
        [--blacklist-type=<type>...] \
        <input-header> \
        [-- <clang-args>...]

    bindgen (-h | --help)

Options:
    -h, --help                    Display this help message.

    -l=<lib>, --link=<lib>        Link to a dynamic library, can be provided
                                  multiple times.

    --static-link=<lib>           Link to a static library, can be provided
                                  multiple times.

    --framework-link=<framework>  Link to a framework.

    -o=<output-rust-file>         Write bindings to <output-rust-file>
                                  (defaults to stdout)

    --match=<name>                Only output bindings for definitions from
                                  files whose name contains <name>. If multiple
                                  match options are provided, files matching any
                                  rule are bound to.

    --builtins                    Output bindings for builtin definitions (for
                                  example __builtin_va_list)

    --ignore-functions            Don't generate bindings for functions and
                                  methods. This is useful when you only care
                                  about struct layouts.

    --enable-cxx-namespaces       Enable support for C++ namespaces.

    --no-type-renaming            Don't rename types.

    --allow-unknown-types         Don't fail if we encounter types we do not
                                  support, instead treat them as void

    --emit-clang-ast              Output the ast (for debugging purposes)

    --use-msvc-mangling           Handle MSVC C++ ABI mangling; requires that
                                  target be set to (i686|x86_64)-pc-win32

    --override-enum-type=<type>   Override enum type, type name could be
                                    uchar
                                    schar
                                    ushort
                                    sshort
                                    uint
                                    sint
                                    ulong
                                    slong
                                    ulonglong
                                    slonglong

    --raw-line=<raw>              TODO
    --dtor-attr=<attr>            TODO
    --no-class-constants          TODO
    --no-unstable-rust            TODO
    --no-namespaced-constants     TODO
    --no-bitfield-methods         TODO
    --ignore-methods              TODO
    --opaque-type=<type>          TODO
    --blacklist-type=<type>       TODO

    <clang-args>                  Options other than stated above are passed
                                  directly through to clang.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_input_header: String,
    flag_link: Vec<String>,
    flag_static_link: Vec<String>,
    flag_framework_link: Vec<String>,
    flag_o: Option<String>,
    flag_match: Vec<String>,
    flag_builtins: bool,
    flag_ignore_functions: bool,
    flag_enable_cxx_namespaces: bool,
    flag_no_type_renaming: bool,
    flag_allow_unknown_types: bool,
    flag_emit_clang_ast: bool,
    flag_use_msvc_mangling: bool,
    flag_override_enum_type: String,
    flag_raw_line: Vec<String>,
    flag_dtor_attr: Vec<String>,
    flag_no_class_constants: bool,
    flag_no_unstable_rust: bool,
    flag_no_namespaced_constants: bool,
    flag_no_bitfield_methods: bool,
    flag_ignore_methods: bool,
    flag_opaque_type: Vec<String>,
    flag_blacklist_type: Vec<String>,
    arg_clang_args: Vec<String>,
}

type ParseResult<T> = Result<T, String>;

impl Into<ParseResult<(BindgenOptions, Box<io::Write>)>> for Args {
    fn into(mut self) -> Result<(BindgenOptions, Box<io::Write>), String> {
        let mut options: BindgenOptions = Default::default();

        for lib in self.flag_link.drain(..) {
            options.links.push((lib, LinkType::Default));
        }

        for lib in self.flag_static_link.drain(..) {
            options.links.push((lib, LinkType::Static));
        }

        for lib in self.flag_framework_link.drain(..) {
            options.links.push((lib, LinkType::Framework));
        }

        let out = if let Some(ref path_name) = self.flag_o {
            let path = path::Path::new(path_name);
            let file = try!(fs::File::create(path).map_err(|_| {
                format!("Opening {} failed", path_name)
            }));
            Box::new(io::BufWriter::new(file)) as Box<io::Write>
        } else {
            Box::new(io::BufWriter::new(io::stdout())) as Box<io::Write>
        };

        options.match_pat.extend(self.flag_match.drain(..));
        options.builtins = self.flag_builtins;
        options.ignore_functions = self.flag_ignore_functions;
        options.enable_cxx_namespaces = self.flag_enable_cxx_namespaces;
        options.rename_types = !self.flag_no_type_renaming;
        options.fail_on_unknown_type = !self.flag_allow_unknown_types;
        options.emit_ast = self.flag_emit_clang_ast;
        options.msvc_mangling = self.flag_use_msvc_mangling;
        options.override_enum_ty = self.flag_override_enum_type;
        options.raw_lines.extend(self.flag_raw_line.drain(..));
        options.dtor_attrs.extend(self.flag_dtor_attr.drain(..));
        options.class_constants = !self.flag_no_class_constants;
        options.unstable_rust = !self.flag_no_unstable_rust;
        options.namespaced_constants = !self.flag_no_namespaced_constants;
        options.gen_bitfield_methods = !self.flag_no_bitfield_methods;
        options.ignore_methods = self.flag_ignore_methods;
        options.opaque_types.extend(self.flag_opaque_type.drain(..));
        options.blacklist_type.extend(self.flag_blacklist_type.drain(..));
        options.clang_args.extend(self.arg_clang_args.drain(..));
        options.clang_args.push(self.arg_input_header);

        Ok((options, out))
    }
}

pub fn main() {
    let mut bind_args: Vec<_> = env::args().collect();

    if let Some(clang) = clang_sys::support::Clang::find(None) {
        let has_clang_args = bind_args.iter().rposition(|arg| *arg == "--").is_some();
        if !has_clang_args {
            bind_args.push("--".to_owned());
        }

        // If --target is specified, assume caller knows what they're doing and don't mess with
        // include paths for them
        let has_target_arg = bind_args.iter().rposition(|arg| arg.starts_with("--target")).is_some();
        if !has_target_arg {
            // TODO: distinguish C and C++ paths? C++'s should be enough, I guess.
            for path in clang.cpp_search_paths.into_iter() {
                if let Ok(path) = path.into_os_string().into_string() {
                    bind_args.push("-isystem".to_owned());
                    bind_args.push(path);
                }
            }
        }
    }

    let args: Args = docopt::Docopt::new(USAGE)
        .and_then(|d| d.argv(bind_args.iter()).decode())
        .unwrap_or_else(|e| e.exit());

    let logger = StdLogger;
    let result: ParseResult<_> = args.into();
    let (options, out) = result.unwrap_or_else(|msg| {
        logger.error(&msg);
        exit(-1);
    });

    match Bindings::generate(&options, Some(&logger as &Logger), None) {
        Ok(bindings) => match bindings.write(out) {
            Ok(()) => (),
            Err(e) => {
                logger.error(&format!("Unable to write bindings to file. {}", e));
                exit(-1);
            }
        },
        Err(()) => {
            logger.error("Failed to generate bindings".into());
            exit(-1);
        }
    }
}
<|endoftext|>