<commit_before>#![deny(missing_docs)]
#![warn(dead_code)]

//! A user friendly game engine written in Rust.

#[cfg(feature = "include_gfx")]
extern crate libc;
#[cfg(feature = "include_gfx")]
extern crate gfx;
#[cfg(feature = "include_gfx")]
extern crate gfx_device_gl;
#[cfg(feature = "include_gfx")]
extern crate gfx_graphics;
#[cfg(feature = "include_opengl")]
extern crate opengl_graphics;
#[cfg(feature = "include_glium")]
extern crate glium_graphics;
#[cfg(feature = "include_sdl2")]
extern crate sdl2;
#[cfg(feature = "include_sdl2")]
extern crate sdl2_window;
#[cfg(feature = "include_glfw")]
extern crate glfw;
#[cfg(feature = "include_glfw")]
extern crate glfw_window;
#[cfg(feature = "include_glutin")]
extern crate glutin;
#[cfg(feature = "include_glutin")]
extern crate glutin_window;
extern crate graphics;
extern crate fps_counter;
extern crate current;
extern crate shader_version;

extern crate piston;

#[cfg(feature = "include_sdl2")]
pub use sdl2_window::Sdl2Window as WindowBackEnd;
#[cfg(feature = "include_glfw")]
pub use glfw_window::GlfwWindow as WindowBackEnd;
#[cfg(feature = "include_glutin")]
pub use glutin_window::GlutinWindow as WindowBackEnd;

#[cfg(feature = "include_gfx")]
use gfx_graphics::Gfx2d;
#[cfg(feature = "include_gfx")]
use gfx_device_gl::{ Device, Resources, CommandBuffer, Output };

#[cfg(feature = "include_opengl")]
use opengl_graphics::GlGraphics;
#[cfg(feature = "include_glium")]
use glium_graphics::{ Glium2d, GliumWindow };
use fps_counter::FPSCounter;

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

use piston::window::WindowSettings;
use current::{ Current, CurrentGuard };

fn start_window<F>(
    window_settings: WindowSettings,
    mut f: F
)
    where
        F: FnMut()
{
    let mut window: WindowBackEnd = window_settings.into();
    let mut fps_counter = Rc::new(RefCell::new(FPSCounter::new()));

    let window_guard = CurrentGuard::new(&mut window);
    let fps_counter_guard = CurrentGuard::new(&mut fps_counter);

    f();

    drop(window_guard);
    drop(fps_counter_guard);
}

#[cfg(feature = "include_opengl")]
fn start_opengl<F>(opengl: shader_version::OpenGL, mut f: F)
    where
        F: FnMut()
{
    let mut gl = Rc::new(RefCell::new(GlGraphics::new(opengl)));

    let gl_guard = CurrentGuard::new(&mut gl);

    f();

    drop(gl_guard);
}

#[cfg(not(feature = "include_opengl"))]
fn start_opengl<F>(_opengl: shader_version::OpenGL, mut f: F)
    where
        F: FnMut()
{
    f();
}

#[cfg(feature = "include_glium")]
fn start_glium<F>(opengl: shader_version::OpenGL, mut f: F)
    where
        F: FnMut()
{
    let window = current_window();
    let mut glium_window = Rc::new(RefCell::new(GliumWindow::new(&window).unwrap()));
    let mut glium2d = Rc::new(RefCell::new(Glium2d::new(opengl, &*glium_window.borrow())));

    let glium_window_guard = CurrentGuard::new(&mut glium_window);
    let glium2d_guard = CurrentGuard::new(&mut glium2d);

    f();

    drop(glium2d_guard);
    drop(glium_window_guard);
}

#[cfg(not(feature = "include_glium"))]
fn start_glium<F>(_opengl: shader_version::OpenGL, mut f: F)
    where
        F: FnMut()
{
    f();
}

#[cfg(feature = "include_gfx")]
fn start_gfx<F>(mut f: F)
    where
        F: FnMut()
{
    use piston::window::Window;
    use gfx::render::RenderFactory;

    let window = current_window();

    let (device, mut factory) = gfx_device_gl::create(|s| {
        #[cfg(feature = "include_sdl2")]
        fn get_proc_address(_: &WindowBackEnd, s: &str) ->
            *const libc::types::common::c95::c_void {
            unsafe { std::mem::transmute(sdl2::video::gl_get_proc_address(s)) }
        }

        #[cfg(feature = "include_glfw")]
        fn get_proc_address(window: &mut WindowBackEnd, s: &str) ->
            *const libc::types::common::c95::c_void {
            window.window.get_proc_address(s)
        }

        #[cfg(feature = "include_glutin")]
        fn get_proc_address(window: &WindowBackEnd, s: &str) ->
            *const libc::types::common::c95::c_void {
            window.window.get_proc_address(s)
        }

        get_proc_address(&mut *window.borrow_mut(), s)
    });
    let mut renderer: Rc<RefCell<
        gfx::Renderer<gfx_device_gl::Resources,
        <gfx_device_gl::Device as gfx::Device>::CommandBuffer
    >>> =
        Rc::new(RefCell::new(factory.create_renderer()));
    let mut device = Rc::new(RefCell::new(device));
    let factory = Rc::new(RefCell::new(factory));
    let mut g2d = Rc::new(RefCell::new(Gfx2d::new(&mut *factory.borrow_mut())));
    let size = window.borrow().size();
    let mut output = Rc::new(RefCell::new(factory.borrow_mut().make_fake_output(
        size.width as u16, size.height as u16)));

    let device_guard = CurrentGuard::new(&mut device);
    let g2d_guard = CurrentGuard::new(&mut g2d);
    let renderer_guard = CurrentGuard::new(&mut renderer);
    let output_guard = CurrentGuard::new(&mut output);

    f();

    drop(g2d_guard);
    drop(renderer_guard);
    drop(output_guard);
    drop(device_guard);
}

#[cfg(not(feature = "include_gfx"))]
fn start_gfx<F>(mut f: F)
    where
        F: FnMut()
{
    f();
}

/// Initializes window and sets up current objects.
pub fn start<F>(
    window_settings: WindowSettings,
    mut f: F
)
    where
        F: FnMut()
{
    use shader_version::OpenGL;

    let opengl = window_settings.get_maybe_opengl().unwrap_or(OpenGL::_3_2);
    start_window(window_settings, || {
        start_opengl(opengl, || {
            start_gfx(|| {
                start_glium(opengl, || f());
            })
        })
    });
}

/// The current window
pub fn current_window() -> Rc<RefCell<WindowBackEnd>> {
    unsafe {
        Current::<Rc<RefCell<WindowBackEnd>>>::new().clone()
    }
}
/// The current Gfx device
#[cfg(feature = "include_gfx")]
pub fn current_gfx_device() -> Rc<RefCell<Device>> {
    unsafe {
        Current::<Rc<RefCell<Device>>>::new().clone()
    }
}
/// The current opengl_graphics back-end
#[cfg(feature = "include_opengl")]
pub fn current_gl_graphics() -> Rc<RefCell<GlGraphics>> {
    unsafe {
        Current::<Rc<RefCell<GlGraphics>>>::new().clone()
    }
}
/// The current gfx_graphics back-end
#[cfg(feature = "include_gfx")]
pub fn current_gfx_graphics() -> Rc<RefCell<Gfx2d<Resources>>> {
    unsafe {
        Current::<Rc<RefCell<Gfx2d<Resources>>>>::new().clone()
    }
}
/// The current glium window.
#[cfg(feature = "include_glium")]
pub fn current_glium_window() -> Rc<RefCell<GliumWindow>> {
    unsafe {
        Current::<Rc<RefCell<GliumWindow>>>::new().clone()
    }
}
/// The current glium 2d.
#[cfg(feature = "include_glium")]
pub fn current_glium_2d() -> Rc<RefCell<Glium2d>> {
    unsafe {
        Current::<Rc<RefCell<Glium2d>>>::new().clone()
    }
}
/// The current Gfx renderer
#[cfg(feature = "include_gfx")]
pub fn current_renderer() -> Rc<RefCell<gfx::Renderer<Resources, CommandBuffer>>> {
    unsafe {
        Current::<Rc<RefCell<gfx::Renderer<Resources, CommandBuffer>>>>::new().clone()
    }
}
/// The current Gfx frame
#[cfg(feature = "include_gfx")]
pub fn current_output() -> Rc<RefCell<Output>> {
    unsafe {
        Current::<Rc<RefCell<Output>>>::new().clone()
    }
}
/// The current FPS counter
pub fn current_fps_counter() -> Rc<RefCell<FPSCounter>> {
    unsafe {
        Current::<Rc<RefCell<FPSCounter>>>::new().clone()
    }
}

/// Returns an event iterator for the event loop
pub fn events() -> piston::event::WindowEvents<WindowBackEnd, piston::event::Event> {
    use piston::event::Events;

    current_window().events()
}

/// Updates the FPS counter and gets the frames per second.
pub fn fps_tick() -> usize {
    let fps_counter = current_fps_counter();
    let mut fps_counter = fps_counter.borrow_mut();
    fps_counter.tick()
}

/// Sets title of the current window.
pub fn set_title(text: String) {
    use piston::window::AdvancedWindow;

    let window = current_window();
    let mut window = window.borrow_mut();
    window.set_title(text);
}

/// Returns true if the current window should be closed.
pub fn should_close() -> bool {
    use piston::window::Window;

    let window = current_window();
    let window = window.borrow();
    window.should_close()
}

/// Renders 2D graphics using Gfx.
#[cfg(feature = "include_gfx")]
pub fn render_2d_gfx<F>(
    bg_color: Option<[f32; 4]>,
    mut f: F
)
    where
        F: FnMut(graphics::Context,
            &mut gfx_graphics::GfxGraphics<Resources, CommandBuffer, Output>)
{
    use gfx::Device;
    use piston::window::Window;
    use graphics::Viewport;

    let window = current_window();
    let window = window.borrow();
    let size = window.size();
    let draw_size = window.draw_size();
    let renderer = current_renderer();
    let mut renderer = renderer.borrow_mut();
    let renderer = &mut *renderer;
    let gfx = current_gfx_graphics();
    let mut gfx = gfx.borrow_mut();
    let output = current_output();
    let output = output.borrow();
    gfx.draw(
        renderer,
        &*output,
        Viewport {
            rect: [0, 0, draw_size.width as i32, draw_size.height as i32],
            draw_size: [draw_size.width, draw_size.height],
            window_size: [size.width, size.height],
        },
        |c, g| {
            if let Some(bg_color) = bg_color {
                graphics::clear(bg_color, g);
            }
            f(c, g);
        });
    let gfx_device = current_gfx_device();
    let mut gfx_device = gfx_device.borrow_mut();
    gfx_device.submit(renderer.as_buffer());
    renderer.reset();
}

/// Renders 2D graphics using OpenGL.
///
/// Panics if called nested within the closure
/// to prevent mutable aliases to the graphics back-end.
#[cfg(feature = "include_opengl")]
pub fn render_2d_opengl<F>(
    bg_color: Option<[f32; 4]>,
    mut f: F
)
    where
        F: FnMut(graphics::Context, &mut opengl_graphics::GlGraphics)
{
    use piston::window::Window;
    use graphics::Viewport;

    let window = current_window();
    let window = window.borrow();
    let size = window.size();
    let draw_size = window.draw_size();
    let gl = current_gl_graphics();
    let mut gl = gl.borrow_mut();
    gl.draw(Viewport {
        rect: [0, 0, draw_size.width as i32, draw_size.height as i32],
        draw_size: [draw_size.width, draw_size.height],
        window_size: [size.width, size.height]
    }, |c, g| {
        use graphics::*;
        if let Some(bg_color) = bg_color {
            graphics::clear(bg_color, g);
        }
        f(c, g);
    });
}

<commit_msg>Use Rc<RefCell<Window>><commit_after>#![deny(missing_docs)]
#![warn(dead_code)]

//! A user friendly game engine written in Rust.

#[cfg(feature = "include_gfx")]
extern crate libc;
#[cfg(feature = "include_gfx")]
extern crate gfx;
#[cfg(feature = "include_gfx")]
extern crate gfx_device_gl;
#[cfg(feature = "include_gfx")]
extern crate gfx_graphics;
#[cfg(feature = "include_opengl")]
extern crate opengl_graphics;
#[cfg(feature = "include_glium")]
extern crate glium_graphics;
#[cfg(feature = "include_sdl2")]
extern crate sdl2;
#[cfg(feature = "include_sdl2")]
extern crate sdl2_window;
#[cfg(feature = "include_glfw")]
extern crate glfw;
#[cfg(feature = "include_glfw")]
extern crate glfw_window;
#[cfg(feature = "include_glutin")]
extern crate glutin;
#[cfg(feature = "include_glutin")]
extern crate glutin_window;
extern crate graphics;
extern crate fps_counter;
extern crate current;
extern crate shader_version;

extern crate piston;

#[cfg(feature = "include_sdl2")]
pub use sdl2_window::Sdl2Window as WindowBackEnd;
#[cfg(feature = "include_glfw")]
pub use glfw_window::GlfwWindow as WindowBackEnd;
#[cfg(feature = "include_glutin")]
pub use glutin_window::GlutinWindow as WindowBackEnd;

#[cfg(feature = "include_gfx")]
use gfx_graphics::Gfx2d;
#[cfg(feature = "include_gfx")]
use gfx_device_gl::{ Device, Resources, CommandBuffer, Output };

#[cfg(feature = "include_opengl")]
use opengl_graphics::GlGraphics;
#[cfg(feature = "include_glium")]
use glium_graphics::{ Glium2d, GliumWindow };
use fps_counter::FPSCounter;

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

use piston::window::WindowSettings;
use current::{ Current, CurrentGuard };

fn start_window<F>(
    window_settings: WindowSettings,
    mut f: F
)
    where
        F: FnMut()
{
    let window: WindowBackEnd = window_settings.into();
    let mut window = Rc::new(RefCell::new(window));
    let mut fps_counter = Rc::new(RefCell::new(FPSCounter::new()));

    let window_guard = CurrentGuard::new(&mut window);
    let fps_counter_guard = CurrentGuard::new(&mut fps_counter);

    f();

    drop(window_guard);
    drop(fps_counter_guard);
}

#[cfg(feature = "include_opengl")]
fn start_opengl<F>(opengl: shader_version::OpenGL, mut f: F)
    where
        F: FnMut()
{
    let mut gl = Rc::new(RefCell::new(GlGraphics::new(opengl)));

    let gl_guard = CurrentGuard::new(&mut gl);

    f();

    drop(gl_guard);
}

#[cfg(not(feature = "include_opengl"))]
fn start_opengl<F>(_opengl: shader_version::OpenGL, mut f: F)
    where
        F: FnMut()
{
    f();
}

#[cfg(feature = "include_glium")]
fn start_glium<F>(opengl: shader_version::OpenGL, mut f: F)
    where
        F: FnMut()
{
    let window = current_window();
    let mut glium_window = Rc::new(RefCell::new(GliumWindow::new(&window).unwrap()));
    let mut glium2d = Rc::new(RefCell::new(Glium2d::new(opengl, &*glium_window.borrow())));

    let glium_window_guard = CurrentGuard::new(&mut glium_window);
    let glium2d_guard = CurrentGuard::new(&mut glium2d);

    f();

    drop(glium2d_guard);
    drop(glium_window_guard);
}

#[cfg(not(feature = "include_glium"))]
fn start_glium<F>(_opengl: shader_version::OpenGL, mut f: F)
    where
        F: FnMut()
{
    f();
}

#[cfg(feature = "include_gfx")]
fn start_gfx<F>(mut f: F)
    where
        F: FnMut()
{
    use piston::window::Window;
    use gfx::render::RenderFactory;

    let window = current_window();

    let (device, mut factory) = gfx_device_gl::create(|s| {
        #[cfg(feature = "include_sdl2")]
        fn get_proc_address(_: &WindowBackEnd, s: &str) ->
            *const libc::types::common::c95::c_void {
            unsafe { std::mem::transmute(sdl2::video::gl_get_proc_address(s)) }
        }

        #[cfg(feature = "include_glfw")]
        fn get_proc_address(window: &mut WindowBackEnd, s: &str) ->
            *const libc::types::common::c95::c_void {
            window.window.get_proc_address(s)
        }

        #[cfg(feature = "include_glutin")]
        fn get_proc_address(window: &WindowBackEnd, s: &str) ->
            *const libc::types::common::c95::c_void {
            window.window.get_proc_address(s)
        }

        get_proc_address(&mut *window.borrow_mut(), s)
    });
    let mut renderer: Rc<RefCell<
        gfx::Renderer<gfx_device_gl::Resources,
        <gfx_device_gl::Device as gfx::Device>::CommandBuffer
    >>> =
        Rc::new(RefCell::new(factory.create_renderer()));
    let mut device = Rc::new(RefCell::new(device));
    let factory = Rc::new(RefCell::new(factory));
    let mut g2d = Rc::new(RefCell::new(Gfx2d::new(&mut *factory.borrow_mut())));
    let size = window.borrow().size();
    let mut output = Rc::new(RefCell::new(factory.borrow_mut().make_fake_output(
        size.width as u16, size.height as u16)));

    let device_guard = CurrentGuard::new(&mut device);
    let g2d_guard = CurrentGuard::new(&mut g2d);
    let renderer_guard = CurrentGuard::new(&mut renderer);
    let output_guard = CurrentGuard::new(&mut output);

    f();

    drop(g2d_guard);
    drop(renderer_guard);
    drop(output_guard);
    drop(device_guard);
}

#[cfg(not(feature = "include_gfx"))]
fn start_gfx<F>(mut f: F)
    where
        F: FnMut()
{
    f();
}

/// Initializes window and sets up current objects.
pub fn start<F>(
    window_settings: WindowSettings,
    mut f: F
)
    where
        F: FnMut()
{
    use shader_version::OpenGL;

    let opengl = window_settings.get_maybe_opengl().unwrap_or(OpenGL::_3_2);
    start_window(window_settings, || {
        start_opengl(opengl, || {
            start_gfx(|| {
                start_glium(opengl, || f());
            })
        })
    });
}

/// The current window
pub fn current_window() -> Rc<RefCell<WindowBackEnd>> {
    unsafe {
        Current::<Rc<RefCell<WindowBackEnd>>>::new().clone()
    }
}
/// The current Gfx device
#[cfg(feature = "include_gfx")]
pub fn current_gfx_device() -> Rc<RefCell<Device>> {
    unsafe {
        Current::<Rc<RefCell<Device>>>::new().clone()
    }
}
/// The current opengl_graphics back-end
#[cfg(feature = "include_opengl")]
pub fn current_gl_graphics() -> Rc<RefCell<GlGraphics>> {
    unsafe {
        Current::<Rc<RefCell<GlGraphics>>>::new().clone()
    }
}
/// The current gfx_graphics back-end
#[cfg(feature = "include_gfx")]
pub fn current_gfx_graphics() -> Rc<RefCell<Gfx2d<Resources>>> {
    unsafe {
        Current::<Rc<RefCell<Gfx2d<Resources>>>>::new().clone()
    }
}
/// The current glium window.
#[cfg(feature = "include_glium")]
pub fn current_glium_window() -> Rc<RefCell<GliumWindow>> {
    unsafe {
        Current::<Rc<RefCell<GliumWindow>>>::new().clone()
    }
}
/// The current glium 2d.
#[cfg(feature = "include_glium")]
pub fn current_glium_2d() -> Rc<RefCell<Glium2d>> {
    unsafe {
        Current::<Rc<RefCell<Glium2d>>>::new().clone()
    }
}
/// The current Gfx renderer
#[cfg(feature = "include_gfx")]
pub fn current_renderer() -> Rc<RefCell<gfx::Renderer<Resources, CommandBuffer>>> {
    unsafe {
        Current::<Rc<RefCell<gfx::Renderer<Resources, CommandBuffer>>>>::new().clone()
    }
}
/// The current Gfx frame
#[cfg(feature = "include_gfx")]
pub fn current_output() -> Rc<RefCell<Output>> {
    unsafe {
        Current::<Rc<RefCell<Output>>>::new().clone()
    }
}
/// The current FPS counter
pub fn current_fps_counter() -> Rc<RefCell<FPSCounter>> {
    unsafe {
        Current::<Rc<RefCell<FPSCounter>>>::new().clone()
    }
}

/// Returns an event iterator for the event loop
pub fn events() -> piston::event::WindowEvents<WindowBackEnd, piston::event::Event> {
    use piston::event::Events;

    current_window().events()
}

/// Updates the FPS counter and gets the frames per second.
pub fn fps_tick() -> usize {
    let fps_counter = current_fps_counter();
    let mut fps_counter = fps_counter.borrow_mut();
    fps_counter.tick()
}

/// Sets title of the current window.
pub fn set_title(text: String) {
    use piston::window::AdvancedWindow;

    let window = current_window();
    let mut window = window.borrow_mut();
    window.set_title(text);
}

/// Returns true if the current window should be closed.
pub fn should_close() -> bool {
    use piston::window::Window;

    let window = current_window();
    let window = window.borrow();
    window.should_close()
}

/// Renders 2D graphics using Gfx.
#[cfg(feature = "include_gfx")]
pub fn render_2d_gfx<F>(
    bg_color: Option<[f32; 4]>,
    mut f: F
)
    where
        F: FnMut(graphics::Context,
            &mut gfx_graphics::GfxGraphics<Resources, CommandBuffer, Output>)
{
    use gfx::Device;
    use piston::window::Window;
    use graphics::Viewport;

    let window = current_window();
    let window = window.borrow();
    let size = window.size();
    let draw_size = window.draw_size();
    let renderer = current_renderer();
    let mut renderer = renderer.borrow_mut();
    let renderer = &mut *renderer;
    let gfx = current_gfx_graphics();
    let mut gfx = gfx.borrow_mut();
    let output = current_output();
    let output = output.borrow();
    gfx.draw(
        renderer,
        &*output,
        Viewport {
            rect: [0, 0, draw_size.width as i32, draw_size.height as i32],
            draw_size: [draw_size.width, draw_size.height],
            window_size: [size.width, size.height],
        },
        |c, g| {
            if let Some(bg_color) = bg_color {
                graphics::clear(bg_color, g);
            }
            f(c, g);
        });
    let gfx_device = current_gfx_device();
    let mut gfx_device = gfx_device.borrow_mut();
    gfx_device.submit(renderer.as_buffer());
    renderer.reset();
}

/// Renders 2D graphics using OpenGL.
///
/// Panics if called nested within the closure
/// to prevent mutable aliases to the graphics back-end.
#[cfg(feature = "include_opengl")]
pub fn render_2d_opengl<F>(
    bg_color: Option<[f32; 4]>,
    mut f: F
)
    where
        F: FnMut(graphics::Context, &mut opengl_graphics::GlGraphics)
{
    use piston::window::Window;
    use graphics::Viewport;

    let window = current_window();
    let window = window.borrow();
    let size = window.size();
    let draw_size = window.draw_size();
    let gl = current_gl_graphics();
    let mut gl = gl.borrow_mut();
    gl.draw(Viewport {
        rect: [0, 0, draw_size.width as i32, draw_size.height as i32],
        draw_size: [draw_size.width, draw_size.height],
        window_size: [size.width, size.height]
    }, |c, g| {
        use graphics::*;
        if let Some(bg_color) = bg_color {
            graphics::clear(bg_color, g);
        }
        f(c, g);
    });
}

<|endoftext|>


<commit_before>extern crate nalgebra;
extern crate num;

pub use self::steerable::Steerable;
pub use self::steering_behavior::SteeringBehavior;
pub use self::limiter::Limiter;
pub use self::steering_acceleration::SteeringAcceleration;

mod steerable;
mod steering_behavior;
mod limiter;
mod steering_acceleration;
<commit_msg>steering accelerator calculator trait added to root module<commit_after>extern crate nalgebra;
extern crate num;

pub use self::steerable::Steerable;
pub use self::steering_behavior::SteeringBehavior;
pub use self::limiter::Limiter;
pub use self::steering_acceleration::SteeringAcceleration;
pub use self::steering_acceleration::SteeringAccelerationCalculator;

mod steerable;
mod steering_behavior;
mod limiter;
mod steering_acceleration;
<|endoftext|>


<commit_before>#![feature(conservative_impl_trait)]
#![feature(const_fn)]
#![feature(proc_macro)]

extern crate gl;
pub extern crate glfw;
extern crate image;
pub extern crate luminance;
pub extern crate luminance_gl;
extern crate nalgebra;
#[cfg(feature = "hot-resource")]
extern crate notify;
extern crate num;
extern crate openal;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[cfg(feature = "hot-resource")]
extern crate time;
extern crate vorbis;
extern crate wavefront_obj;

#[macro_use]
pub mod report;

#[macro_use]
pub mod resource;
#[macro_use]
pub mod scene;

pub mod anim;
pub mod app;
pub mod bootstrap;
pub mod camera;
pub mod compositor;
pub mod color;
pub mod device;
pub mod extra;
pub mod gui;
pub mod id;
pub mod linear;
pub mod model;
pub mod object;
pub mod projection;
pub mod renderer;
pub mod shader;
pub mod spline;
pub mod texture;
pub mod transform;

pub use anim::Cont;
pub use app::App;
pub use bootstrap::{LuminanceBackend, Keyboard, Mouse, MouseMove, Scroll, WindowDim, bootstrap};
pub use camera::{Camera, Freefly};
pub use color::Color;
pub use compositor::{Compositor, Screen};
pub use device::Device;
pub use id::Id;
pub use linear::{Matrix4};
pub use model::{Model, ModelError, Part};
pub use object::Object;
pub use projection::{Projectable, perspective};
pub use renderer::Renderer;
pub use resource::{Load, LoadError, Reload};
pub use shader::{Program, ShaderError, new_program};
pub use scene::Scene;
pub use spline::{Interpolate, Interpolation, Key, Sampler, Spline, SplineIterator, Time};
pub use texture::{TextureImage, load_rgba_texture, save_rgba_texture};
pub use transform::{Axis, Orientation, Position, Translation, Transformable, X_AXIS, Y_AXIS, Z_AXIS,
                   Scale, translation_matrix};
<commit_msg>Added ColorAlpha to the pub interface.<commit_after>#![feature(conservative_impl_trait)]
#![feature(const_fn)]
#![feature(proc_macro)]

extern crate gl;
pub extern crate glfw;
extern crate image;
pub extern crate luminance;
pub extern crate luminance_gl;
extern crate nalgebra;
#[cfg(feature = "hot-resource")]
extern crate notify;
extern crate num;
extern crate openal;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[cfg(feature = "hot-resource")]
extern crate time;
extern crate vorbis;
extern crate wavefront_obj;

#[macro_use]
pub mod report;

#[macro_use]
pub mod resource;
#[macro_use]
pub mod scene;

pub mod anim;
pub mod app;
pub mod bootstrap;
pub mod camera;
pub mod compositor;
pub mod color;
pub mod device;
pub mod extra;
pub mod gui;
pub mod id;
pub mod linear;
pub mod model;
pub mod object;
pub mod projection;
pub mod renderer;
pub mod shader;
pub mod spline;
pub mod texture;
pub mod transform;

pub use anim::Cont;
pub use app::App;
pub use bootstrap::{LuminanceBackend, Keyboard, Mouse, MouseMove, Scroll, WindowDim, bootstrap};
pub use camera::{Camera, Freefly};
pub use color::{Color, ColorAlpha};
pub use compositor::{Compositor, Screen};
pub use device::Device;
pub use id::Id;
pub use linear::{Matrix4};
pub use model::{Model, ModelError, Part};
pub use object::Object;
pub use projection::{Projectable, perspective};
pub use renderer::Renderer;
pub use resource::{Load, LoadError, Reload};
pub use shader::{Program, ShaderError, new_program};
pub use scene::Scene;
pub use spline::{Interpolate, Interpolation, Key, Sampler, Spline, SplineIterator, Time};
pub use texture::{TextureImage, load_rgba_texture, save_rgba_texture};
pub use transform::{Axis, Orientation, Position, Translation, Transformable, X_AXIS, Y_AXIS, Z_AXIS,
                   Scale, translation_matrix};
<|endoftext|>


<commit_before>extern crate petgraph;

// XXX: Self-loops?

use petgraph::{Graph, Directed};
use petgraph::graph::{NodeIndex, IndexType};
use std::collections::HashSet;
use std::hash::Hash;

#[repr(u8)]
#[derive(Debug)]
pub enum TriadType {
    T003 = 0,
    T012,
    T102,
    T021D,

    T021U,
    T021C,
    T111D,
    T111U,

    T030T,
    T030C,
    T201,
    T120D,

    T120U,
    T120C,
    T210,
    T300
}

impl TriadType {
    #[inline(always)]
    fn from_u8(i: u8) -> TriadType {
        use std::mem;
        assert!(i < 16);
        unsafe { mem::transmute(i) }
    }
}

fn tricode<N, E, I: IndexType>(graph: &Graph<N, E, Directed, I>, v: NodeIndex<I>, u: NodeIndex<I>, w: NodeIndex<I>) -> usize {
    let mut tricode = 0;
    if let Some(_) = graph.find_edge(v, u) { tricode |= 1 << 0; }
    if let Some(_) = graph.find_edge(u, v) { tricode |= 1 << 1; }
    if let Some(_) = graph.find_edge(v, w) { tricode |= 1 << 2; }
    if let Some(_) = graph.find_edge(w, v) { tricode |= 1 << 3; }
    if let Some(_) = graph.find_edge(u, w) { tricode |= 1 << 4; }
    if let Some(_) = graph.find_edge(w, u) { tricode |= 1 << 5; }
    return tricode;
}

const TRITYPES: [u8;64] = [0, 1, 1, 2, 1, 3, 5, 7, 1, 5, 4, 6, 2, 7, 6, 10,
                           1, 5, 3, 7, 4, 8, 8, 12, 5, 9, 8, 13, 6, 13, 11, 14,
                           1, 4, 5, 6, 5, 8, 9, 13, 3, 8, 8, 11, 7, 12, 13, 14,
                           2, 6, 7, 10, 6, 11, 13, 14, 7, 13, 12, 14, 10, 14, 14, 15];

#[derive(Debug)]
pub struct TriadicCensus {
    census: [u64; 16],
}

impl TriadicCensus {
    #[inline(always)]
    fn new() -> TriadicCensus {
        TriadicCensus{census: [0;16]}
    }

    #[inline(always)]
    fn add(&mut self, triad_type: TriadType, cnt: u64) {
        self.census[triad_type as usize] += cnt;
    }

    #[inline(always)]
    fn set(&mut self, triad_type: TriadType, cnt: u64) {
        self.census[triad_type as usize] = cnt;
    }

    #[inline(always)]
    pub fn get(&self, triad_type: TriadType) -> u64 {
        self.census[triad_type as usize]
    }

    #[inline(always)]
    pub fn as_slice<'a>(&'a self) -> &'a[u64] {
        &self.census[..]
    }

    pub fn from_graph<N, E, I: IndexType+Hash>(graph: &Graph<N, E, Directed, I>) -> TriadicCensus {
        let n = graph.node_count();

        let mut census = TriadicCensus::new();

        for i in 0..n {
            let v = NodeIndex::new(i);

            let mut neighbors_v = HashSet::new();
            for u in graph.neighbors_undirected(v) {
                if v < u {
                    neighbors_v.insert(u);
                }
            }

            for u in neighbors_v {
                let mut s = HashSet::new();
                for nu in graph.neighbors_undirected(u) { s.insert(nu); }
                for nv in graph.neighbors_undirected(v) { s.insert(nv); }
                let _ = s.remove(&u);
                let _ = s.remove(&v);

                let tri_type =
                    if graph.find_edge(v, u).is_some() && graph.find_edge(u, v).is_some() {
                        TriadType::T102
                    } else {
                        TriadType::T012
                    };

                let cnt = n as i64 - s.len() as i64 - 2;
                assert!(cnt >= 0);
                census.add(tri_type, cnt as u64);
                for w in s {
                    if u < w || (v < w && w < u && !(graph.find_edge(v, w).is_some() || graph.find_edge(w, v).is_some())) {
                       let tri_type = TriadType::from_u8(TRITYPES[tricode(graph, v, u, w)]);
                       census.add(tri_type, 1);
                    }
                }
            }
        }

        let mut sum = 0;
        for &cnt in &census.as_slice()[1..] {
            sum += cnt;
        }
        let n = n as u64;
        // Integer division below is guaranteed to produce an integral result
        census.set(TriadType::T003, (n * (n - 1) * (n - 2)) / 6 - sum);
        return census;
    }
}

#[test]
fn test_simple() {
    let mut g: Graph<(),()> = Graph::new();

    let n1 = g.add_node(());
    let n2 = g.add_node(());
    let n3 = g.add_node(());

    let c = TriadicCensus::from_graph(&g);
    assert_eq!(&[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], c.as_slice());

    g.add_edge(n1, n3, ());
    let c = TriadicCensus::from_graph(&g);
    assert_eq!(&[0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0], c.as_slice());

    g.add_edge(n3, n1, ());
    let c = TriadicCensus::from_graph(&g);
    assert_eq!(&[0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0], c.as_slice());

    g.add_edge(n2, n3, ());
    let c = TriadicCensus::from_graph(&g);
    assert_eq!(&[0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0], c.as_slice());
}
<commit_msg>Add TriadicCensus::distance() function<commit_after>extern crate petgraph;

// XXX: Self-loops?

use petgraph::{Graph, Directed};
use petgraph::graph::{NodeIndex, IndexType};
use std::collections::HashSet;
use std::hash::Hash;

#[repr(u8)]
#[derive(Debug)]
pub enum TriadType {
    T003 = 0,
    T012,
    T102,
    T021D,

    T021U,
    T021C,
    T111D,
    T111U,

    T030T,
    T030C,
    T201,
    T120D,

    T120U,
    T120C,
    T210,
    T300
}

impl TriadType {
    #[inline(always)]
    fn from_u8(i: u8) -> TriadType {
        use std::mem;
        assert!(i < 16);
        unsafe { mem::transmute(i) }
    }
}

fn tricode<N, E, I: IndexType>(graph: &Graph<N, E, Directed, I>, v: NodeIndex<I>, u: NodeIndex<I>, w: NodeIndex<I>) -> usize {
    let mut tricode = 0;
    if let Some(_) = graph.find_edge(v, u) { tricode |= 1 << 0; }
    if let Some(_) = graph.find_edge(u, v) { tricode |= 1 << 1; }
    if let Some(_) = graph.find_edge(v, w) { tricode |= 1 << 2; }
    if let Some(_) = graph.find_edge(w, v) { tricode |= 1 << 3; }
    if let Some(_) = graph.find_edge(u, w) { tricode |= 1 << 4; }
    if let Some(_) = graph.find_edge(w, u) { tricode |= 1 << 5; }
    return tricode;
}

const TRITYPES: [u8;64] = [0, 1, 1, 2, 1, 3, 5, 7, 1, 5, 4, 6, 2, 7, 6, 10,
                           1, 5, 3, 7, 4, 8, 8, 12, 5, 9, 8, 13, 6, 13, 11, 14,
                           1, 4, 5, 6, 5, 8, 9, 13, 3, 8, 8, 11, 7, 12, 13, 14,
                           2, 6, 7, 10, 6, 11, 13, 14, 7, 13, 12, 14, 10, 14, 14, 15];

#[derive(Debug)]
pub struct TriadicCensus {
    census: [u64; 16],
}

impl TriadicCensus {
    /// Calculates the `distance` between two TriadicCensus structs, treated as
    /// points in a 16-dimensional space.
    pub fn distance(a: &TriadicCensus, b: &TriadicCensus) -> f64 {
        let mut sum = 0.0f64;
        for i in 0..16 {
            let va = a.census[i];
            let vb = b.census[i];
            let diff = (if va > vb { va - vb } else { vb - va }) as f64;
            sum += diff * diff;
        }
        sum.sqrt()
    }

    #[inline(always)]
    fn new() -> TriadicCensus {
        TriadicCensus{census: [0;16]}
    }

    #[inline(always)]
    fn add(&mut self, triad_type: TriadType, cnt: u64) {
        self.census[triad_type as usize] += cnt;
    }

    #[inline(always)]
    fn set(&mut self, triad_type: TriadType, cnt: u64) {
        self.census[triad_type as usize] = cnt;
    }

    #[inline(always)]
    pub fn get(&self, triad_type: TriadType) -> u64 {
        self.census[triad_type as usize]
    }

    #[inline(always)]
    pub fn as_slice<'a>(&'a self) -> &'a[u64] {
        &self.census[..]
    }

    pub fn from_graph<N, E, I: IndexType+Hash>(graph: &Graph<N, E, Directed, I>) -> TriadicCensus {
        let n = graph.node_count();

        let mut census = TriadicCensus::new();

        for i in 0..n {
            let v = NodeIndex::new(i);

            let mut neighbors_v = HashSet::new();
            for u in graph.neighbors_undirected(v) {
                if v < u {
                    neighbors_v.insert(u);
                }
            }

            for u in neighbors_v {
                let mut s = HashSet::new();
                for nu in graph.neighbors_undirected(u) { s.insert(nu); }
                for nv in graph.neighbors_undirected(v) { s.insert(nv); }
                let _ = s.remove(&u);
                let _ = s.remove(&v);

                let tri_type =
                    if graph.find_edge(v, u).is_some() && graph.find_edge(u, v).is_some() {
                        TriadType::T102
                    } else {
                        TriadType::T012
                    };

                let cnt = n as i64 - s.len() as i64 - 2;
                assert!(cnt >= 0);
                census.add(tri_type, cnt as u64);
                for w in s {
                    if u < w || (v < w && w < u && !(graph.find_edge(v, w).is_some() || graph.find_edge(w, v).is_some())) {
                       let tri_type = TriadType::from_u8(TRITYPES[tricode(graph, v, u, w)]);
                       census.add(tri_type, 1);
                    }
                }
            }
        }

        let mut sum = 0;
        for &cnt in &census.as_slice()[1..] {
            sum += cnt;
        }
        let n = n as u64;
        // Integer division below is guaranteed to produce an integral result
        census.set(TriadType::T003, (n * (n - 1) * (n - 2)) / 6 - sum);
        return census;
    }
}

#[test]
fn test_simple() {
    let mut g: Graph<(),()> = Graph::new();

    let n1 = g.add_node(());
    let n2 = g.add_node(());
    let n3 = g.add_node(());

    let c1 = TriadicCensus::from_graph(&g);
    assert_eq!(&[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], c1.as_slice());

    g.add_edge(n1, n3, ());
    let c2 = TriadicCensus::from_graph(&g);
    assert_eq!(&[0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0], c2.as_slice());

    let d = TriadicCensus::distance(&c1, &c2); // should be sqrt(2)
    assert!(d > 1.414 && d < 1.415);

    g.add_edge(n3, n1, ());
    let c3 = TriadicCensus::from_graph(&g);
    assert_eq!(&[0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0], c3.as_slice());

    g.add_edge(n2, n3, ());
    let c4 = TriadicCensus::from_graph(&g);
    assert_eq!(&[0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0], c4.as_slice());
}
<|endoftext|>


<commit_before>//! The `ipnetwork` crate provides a set of APIs to work with IP CIDRs in
//! Rust. Implementation for IPv4 is more or less stable, IPv6 implementation
//! is still WIP.
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]
#![crate_type = "lib"]
#![doc(html_root_url = "https://docs.rs/ipnetwork/0.15.1")]

use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use std::{fmt, net::IpAddr, str::FromStr};

mod common;
mod ipv4;
mod ipv6;

pub use crate::common::IpNetworkError;
pub use crate::ipv4::{ipv4_mask_to_prefix, Ipv4Network};
pub use crate::ipv6::{ipv6_mask_to_prefix, Ipv6Network};

/// Represents a generic network range. This type can have two variants:
/// the v4 and the v6 case.
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum IpNetwork {
    V4(Ipv4Network),
    V6(Ipv6Network),
}

impl<'de> Deserialize<'de> for IpNetwork {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let s = <String>::deserialize(deserializer)?;
        IpNetwork::from_str(&s).map_err(de::Error::custom)
    }
}

impl Serialize for IpNetwork {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&self.to_string())
    }
}

/// Represents a generic network size. For IPv4, the max size is a u32 and for IPv6, it is a u128
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum NetworkSize {
    V4(u32),
    V6(u128),
}

impl IpNetwork {
    /// Constructs a new `IpNetwork` from a given `IpAddr` and a prefix denoting the
    /// network size. If the prefix is larger than 32 (for IPv4) or 128 (for IPv6), this
    /// will raise an `IpNetworkError::InvalidPrefix` error. Support for IPv6 is not
    /// complete yet.
    pub fn new(ip: IpAddr, prefix: u8) -> Result<IpNetwork, IpNetworkError> {
        match ip {
            IpAddr::V4(a) => Ok(IpNetwork::V4(Ipv4Network::new(a, prefix)?)),
            IpAddr::V6(a) => Ok(IpNetwork::V6(Ipv6Network::new(a, prefix)?)),
        }
    }

    /// Constructs a new `IpNetwork` from a network address and a network mask.
    ///
    /// If the netmask is not valid this will return an `IpNetworkError::InvalidPrefix`.
    pub fn with_netmask(netaddr: IpAddr, netmask: IpAddr) -> Result<Self, IpNetworkError> {
        let prefix = ip_mask_to_prefix(netmask)?;
        Self::new(netaddr, prefix)
    }

    /// Returns the IP part of a given `IpNetwork`
    pub fn ip(&self) -> IpAddr {
        match *self {
            IpNetwork::V4(ref a) => IpAddr::V4(a.ip()),
            IpNetwork::V6(ref a) => IpAddr::V6(a.ip()),
        }
    }

    /// Returns the prefix of the given `IpNetwork`
    ///
    /// # Example
    /// ```
    /// use ipnetwork::IpNetwork;
    ///
    /// assert_eq!(IpNetwork::V4("10.9.0.1".parse().unwrap()).prefix(), 32u8);
    /// assert_eq!(IpNetwork::V4("10.9.0.32/16".parse().unwrap()).prefix(), 16u8);
    ///
    /// assert_eq!(IpNetwork::V6("ff01::0".parse().unwrap()).prefix(), 128u8);
    /// assert_eq!(IpNetwork::V6("ff01::0/32".parse().unwrap()).prefix(), 32u8);
    /// ```
    pub fn prefix(&self) -> u8 {
        match *self {
            IpNetwork::V4(ref a) => a.prefix(),
            IpNetwork::V6(ref a) => a.prefix(),
        }
    }

    /// Returns the address of the network denoted by this `IpNetwork`.
    /// This means the lowest possible IP address inside of the network.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::net::{Ipv4Addr, Ipv6Addr};
    /// use ipnetwork::IpNetwork;
    ///
    /// let net: IpNetwork = "10.1.9.32/16".parse().unwrap();
    /// assert_eq!(net.network(), Ipv4Addr::new(10, 1, 0, 0));
    /// let net: IpNetwork = "2001:db8::/96".parse().unwrap();
    /// assert_eq!(net.network(), Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0));
    /// ```
    pub fn network(&self) -> IpAddr {
        match *self {
            IpNetwork::V4(ref a) => IpAddr::V4(a.network()),
            IpNetwork::V6(ref a) => IpAddr::V6(a.network()),
        }
    }

    /// Returns the broadcasting address of this `IpNetwork`.
    /// This means the highest possible IP address inside of the network.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::net::Ipv4Addr;
    /// use ipnetwork::{IpNetwork, Ipv4Network};
    ///
    /// let net: Ipv4Network = "10.9.0.32/16".parse().unwrap();
    /// assert_eq!(net.broadcast(), Ipv4Addr::new(10, 9, 255, 255));
    /// ```
    pub fn broadcast(&self) -> IpAddr {
        match *self {
            IpNetwork::V4(ref a) => IpAddr::V4(a.broadcast()),
            IpNetwork::V6(ref a) => IpAddr::V6(a.broadcast()),
        }
    }

    /// Returns the mask for this `IpNetwork`.
    /// That means the `prefix` most significant bits will be 1 and the rest 0
    ///
    /// # Example
    ///
    /// ```
    /// use ipnetwork::IpNetwork;
    /// use std::net::{Ipv4Addr, Ipv6Addr};
    ///
    /// let v4_net: IpNetwork = "10.9.0.1".parse().unwrap();
    /// assert_eq!(v4_net.mask(), Ipv4Addr::new(255, 255, 255, 255));
    /// let v4_net: IpNetwork = "10.9.0.32/16".parse().unwrap();
    /// assert_eq!(v4_net.mask(), Ipv4Addr::new(255, 255, 0, 0));
    ///
    /// let v6_net: IpNetwork = "ff01::0".parse().unwrap();
    /// assert_eq!(v6_net.mask(), Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff));
    /// let v6_net: IpNetwork = "ff01::0/32".parse().unwrap();
    /// assert_eq!(v6_net.mask(), Ipv6Addr::new(0xffff, 0xffff, 0, 0, 0, 0, 0, 0));
    /// ```
    pub fn mask(&self) -> IpAddr {
        match *self {
            IpNetwork::V4(ref a) => IpAddr::V4(a.mask()),
            IpNetwork::V6(ref a) => IpAddr::V6(a.mask()),
        }
    }

    /// Returns true if the IP in this `IpNetwork` is a valid IPv4 address,
    /// false if it's a valid IPv6 address.
    ///
    /// # Example
    ///
    ///```
    /// use ipnetwork::IpNetwork;
    ///
    /// let v4: IpNetwork = IpNetwork::V4("10.9.0.32/16".parse().unwrap());
    /// assert_eq!(v4.is_ipv4(), true);
    /// assert_eq!(v4.is_ipv6(), false);
    ///```
    pub fn is_ipv4(&self) -> bool {
        match *self {
            IpNetwork::V4(_) => true,
            IpNetwork::V6(_) => false,
        }
    }

    /// Returns true if the IP in this `IpNetwork` is a valid IPv6 address,
    /// false if it's a valid IPv4 address.
    ///
    /// # Example
    ///
    ///```
    /// use ipnetwork::IpNetwork;
    ///
    /// let v6: IpNetwork = IpNetwork::V6("ff01::0/32".parse().unwrap());
    /// assert_eq!(v6.is_ipv6(), true);
    /// assert_eq!(v6.is_ipv4(), false);
    ///```
    pub fn is_ipv6(&self) -> bool {
        match *self {
            IpNetwork::V4(_) => false,
            IpNetwork::V6(_) => true,
        }
    }

    // TODO(abhishek) when TryFrom is stable, implement it for IpNetwork to
    // variant conversions. Then use that to implement a generic is_subnet_of
    // is_supernet_of, overlaps

    /// Checks if a given `IpAddr` is in this `IpNetwork`
    ///
    /// # Examples
    ///
    /// ```
    /// use std::net::IpAddr;
    /// use ipnetwork::IpNetwork;
    ///
    /// let net: IpNetwork = "127.0.0.0/24".parse().unwrap();
    /// let ip1: IpAddr = "127.0.0.1".parse().unwrap();
    /// let ip2: IpAddr = "172.0.0.1".parse().unwrap();
    /// let ip4: IpAddr = "::1".parse().unwrap();
    /// assert!(net.contains(ip1));
    /// assert!(!net.contains(ip2));
    /// assert!(!net.contains(ip4));
    /// ```
    pub fn contains(&self, ip: IpAddr) -> bool {
        match (*self, ip) {
            (IpNetwork::V4(net), IpAddr::V4(ip)) => net.contains(ip),
            (IpNetwork::V6(net), IpAddr::V6(ip)) => net.contains(ip),
            _ => false,
        }
    }

    /// Returns the number of possible host addresses in this `IpAddr`
    ///
    /// # Examples
    ///
    /// ```
    /// use ipnetwork::{IpNetwork, NetworkSize};
    ///
    ///
    /// let net: IpNetwork = "127.0.0.0/24".parse().unwrap();
    /// assert_eq!(net.size(), NetworkSize::V4(256))
    /// ```
    pub fn size(&self) -> NetworkSize {
        match *self {
            IpNetwork::V4(ref ip) => NetworkSize::V4(ip.size()),
            IpNetwork::V6(ref ip) => NetworkSize::V6(ip.size()),
        }
    }
}

/// Tries to parse the given string into a `IpNetwork`. Will first try to parse
/// it as an `Ipv4Network` and if that fails as an `Ipv6Network`. If both
/// fails it will return an `InvalidAddr` error.
///
/// # Examples
///
/// ```
/// use std::net::Ipv4Addr;
/// use ipnetwork::{IpNetwork, Ipv4Network};
///
/// let expected = IpNetwork::V4(Ipv4Network::new(Ipv4Addr::new(10, 1, 9, 32), 16).unwrap());
/// let from_cidr: IpNetwork = "10.1.9.32/16".parse().unwrap();
/// assert_eq!(expected, from_cidr);
/// ```
impl FromStr for IpNetwork {
    type Err = IpNetworkError;
    fn from_str(s: &str) -> Result<IpNetwork, IpNetworkError> {
        if let Ok(net) = Ipv4Network::from_str(s) {
            Ok(IpNetwork::V4(net))
        } else if let Ok(net) = Ipv6Network::from_str(s) {
            Ok(IpNetwork::V6(net))
        } else {
            Err(IpNetworkError::InvalidAddr(s.to_string()))
        }
    }
}

impl From<Ipv4Network> for IpNetwork {
    fn from(v4: Ipv4Network) -> IpNetwork {
        IpNetwork::V4(v4)
    }
}

impl From<Ipv6Network> for IpNetwork {
    fn from(v6: Ipv6Network) -> IpNetwork {
        IpNetwork::V6(v6)
    }
}

impl From<IpAddr> for IpNetwork {
    fn from(addr: IpAddr) -> IpNetwork {
        match addr {
            IpAddr::V4(a) => IpNetwork::V4(Ipv4Network::from(a)),
            IpAddr::V6(a) => IpNetwork::V6(Ipv6Network::from(a)),
        }
    }
}

impl fmt::Display for IpNetwork {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            IpNetwork::V4(net) => net.fmt(f),
            IpNetwork::V6(net) => net.fmt(f),
        }
    }
}

/// Converts a `IpAddr` network mask into a prefix.
/// If the mask is invalid this will return an `IpNetworkError::InvalidPrefix`.
pub fn ip_mask_to_prefix(mask: IpAddr) -> Result<u8, IpNetworkError> {
    match mask {
        IpAddr::V4(mask) => ipv4_mask_to_prefix(mask),
        IpAddr::V6(mask) => ipv6_mask_to_prefix(mask),
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn deserialize_from_serde_json_value() {
        use super::*;
        let network = IpNetwork::from_str("0.0.0.0/0").unwrap();
        let val: serde_json::value::Value =
            serde_json::from_str(&serde_json::to_string(&network).unwrap()).unwrap();
        let _deser: IpNetwork = serde_json::from_value(val)
            .expect("Fails to deserialize from json_value::value::Value");
    }
}
<commit_msg>Iterators for the IpNetwork<commit_after>//! The `ipnetwork` crate provides a set of APIs to work with IP CIDRs in
//! Rust. Implementation for IPv4 is more or less stable, IPv6 implementation
//! is still WIP.
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]
#![crate_type = "lib"]
#![doc(html_root_url = "https://docs.rs/ipnetwork/0.15.1")]

use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use std::{fmt, net::IpAddr, str::FromStr};

mod common;
mod ipv4;
mod ipv6;

pub use crate::common::IpNetworkError;
pub use crate::ipv4::{ipv4_mask_to_prefix, Ipv4Network};
pub use crate::ipv6::{ipv6_mask_to_prefix, Ipv6Network};
use crate::ipv4::Ipv4NetworkIterator;
use crate::ipv6::Ipv6NetworkIterator;

/// Represents a generic network range. This type can have two variants:
/// the v4 and the v6 case.
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum IpNetwork {
    V4(Ipv4Network),
    V6(Ipv6Network),
}

impl<'de> Deserialize<'de> for IpNetwork {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let s = <String>::deserialize(deserializer)?;
        IpNetwork::from_str(&s).map_err(de::Error::custom)
    }
}

impl Serialize for IpNetwork {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&self.to_string())
    }
}

/// Represents a generic network size. For IPv4, the max size is a u32 and for IPv6, it is a u128
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum NetworkSize {
    V4(u32),
    V6(u128),
}

impl IpNetwork {
    /// Constructs a new `IpNetwork` from a given `IpAddr` and a prefix denoting the
    /// network size. If the prefix is larger than 32 (for IPv4) or 128 (for IPv6), this
    /// will raise an `IpNetworkError::InvalidPrefix` error. Support for IPv6 is not
    /// complete yet.
    pub fn new(ip: IpAddr, prefix: u8) -> Result<IpNetwork, IpNetworkError> {
        match ip {
            IpAddr::V4(a) => Ok(IpNetwork::V4(Ipv4Network::new(a, prefix)?)),
            IpAddr::V6(a) => Ok(IpNetwork::V6(Ipv6Network::new(a, prefix)?)),
        }
    }

    /// Constructs a new `IpNetwork` from a network address and a network mask.
    ///
    /// If the netmask is not valid this will return an `IpNetworkError::InvalidPrefix`.
    pub fn with_netmask(netaddr: IpAddr, netmask: IpAddr) -> Result<Self, IpNetworkError> {
        let prefix = ip_mask_to_prefix(netmask)?;
        Self::new(netaddr, prefix)
    }

    /// Returns the IP part of a given `IpNetwork`
    pub fn ip(&self) -> IpAddr {
        match *self {
            IpNetwork::V4(ref a) => IpAddr::V4(a.ip()),
            IpNetwork::V6(ref a) => IpAddr::V6(a.ip()),
        }
    }

    /// Returns the prefix of the given `IpNetwork`
    ///
    /// # Example
    /// ```
    /// use ipnetwork::IpNetwork;
    ///
    /// assert_eq!(IpNetwork::V4("10.9.0.1".parse().unwrap()).prefix(), 32u8);
    /// assert_eq!(IpNetwork::V4("10.9.0.32/16".parse().unwrap()).prefix(), 16u8);
    ///
    /// assert_eq!(IpNetwork::V6("ff01::0".parse().unwrap()).prefix(), 128u8);
    /// assert_eq!(IpNetwork::V6("ff01::0/32".parse().unwrap()).prefix(), 32u8);
    /// ```
    pub fn prefix(&self) -> u8 {
        match *self {
            IpNetwork::V4(ref a) => a.prefix(),
            IpNetwork::V6(ref a) => a.prefix(),
        }
    }

    /// Returns the address of the network denoted by this `IpNetwork`.
    /// This means the lowest possible IP address inside of the network.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::net::{Ipv4Addr, Ipv6Addr};
    /// use ipnetwork::IpNetwork;
    ///
    /// let net: IpNetwork = "10.1.9.32/16".parse().unwrap();
    /// assert_eq!(net.network(), Ipv4Addr::new(10, 1, 0, 0));
    /// let net: IpNetwork = "2001:db8::/96".parse().unwrap();
    /// assert_eq!(net.network(), Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0));
    /// ```
    pub fn network(&self) -> IpAddr {
        match *self {
            IpNetwork::V4(ref a) => IpAddr::V4(a.network()),
            IpNetwork::V6(ref a) => IpAddr::V6(a.network()),
        }
    }

    /// Returns the broadcasting address of this `IpNetwork`.
    /// This means the highest possible IP address inside of the network.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::net::Ipv4Addr;
    /// use ipnetwork::{IpNetwork, Ipv4Network};
    ///
    /// let net: Ipv4Network = "10.9.0.32/16".parse().unwrap();
    /// assert_eq!(net.broadcast(), Ipv4Addr::new(10, 9, 255, 255));
    /// ```
    pub fn broadcast(&self) -> IpAddr {
        match *self {
            IpNetwork::V4(ref a) => IpAddr::V4(a.broadcast()),
            IpNetwork::V6(ref a) => IpAddr::V6(a.broadcast()),
        }
    }

    /// Returns the mask for this `IpNetwork`.
    /// That means the `prefix` most significant bits will be 1 and the rest 0
    ///
    /// # Example
    ///
    /// ```
    /// use ipnetwork::IpNetwork;
    /// use std::net::{Ipv4Addr, Ipv6Addr};
    ///
    /// let v4_net: IpNetwork = "10.9.0.1".parse().unwrap();
    /// assert_eq!(v4_net.mask(), Ipv4Addr::new(255, 255, 255, 255));
    /// let v4_net: IpNetwork = "10.9.0.32/16".parse().unwrap();
    /// assert_eq!(v4_net.mask(), Ipv4Addr::new(255, 255, 0, 0));
    ///
    /// let v6_net: IpNetwork = "ff01::0".parse().unwrap();
    /// assert_eq!(v6_net.mask(), Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff));
    /// let v6_net: IpNetwork = "ff01::0/32".parse().unwrap();
    /// assert_eq!(v6_net.mask(), Ipv6Addr::new(0xffff, 0xffff, 0, 0, 0, 0, 0, 0));
    /// ```
    pub fn mask(&self) -> IpAddr {
        match *self {
            IpNetwork::V4(ref a) => IpAddr::V4(a.mask()),
            IpNetwork::V6(ref a) => IpAddr::V6(a.mask()),
        }
    }

    /// Returns true if the IP in this `IpNetwork` is a valid IPv4 address,
    /// false if it's a valid IPv6 address.
    ///
    /// # Example
    ///
    ///```
    /// use ipnetwork::IpNetwork;
    ///
    /// let v4: IpNetwork = IpNetwork::V4("10.9.0.32/16".parse().unwrap());
    /// assert_eq!(v4.is_ipv4(), true);
    /// assert_eq!(v4.is_ipv6(), false);
    ///```
    pub fn is_ipv4(&self) -> bool {
        match *self {
            IpNetwork::V4(_) => true,
            IpNetwork::V6(_) => false,
        }
    }

    /// Returns true if the IP in this `IpNetwork` is a valid IPv6 address,
    /// false if it's a valid IPv4 address.
    ///
    /// # Example
    ///
    ///```
    /// use ipnetwork::IpNetwork;
    ///
    /// let v6: IpNetwork = IpNetwork::V6("ff01::0/32".parse().unwrap());
    /// assert_eq!(v6.is_ipv6(), true);
    /// assert_eq!(v6.is_ipv4(), false);
    ///```
    pub fn is_ipv6(&self) -> bool {
        match *self {
            IpNetwork::V4(_) => false,
            IpNetwork::V6(_) => true,
        }
    }

    // TODO(abhishek) when TryFrom is stable, implement it for IpNetwork to
    // variant conversions. Then use that to implement a generic is_subnet_of
    // is_supernet_of, overlaps

    /// Checks if a given `IpAddr` is in this `IpNetwork`
    ///
    /// # Examples
    ///
    /// ```
    /// use std::net::IpAddr;
    /// use ipnetwork::IpNetwork;
    ///
    /// let net: IpNetwork = "127.0.0.0/24".parse().unwrap();
    /// let ip1: IpAddr = "127.0.0.1".parse().unwrap();
    /// let ip2: IpAddr = "172.0.0.1".parse().unwrap();
    /// let ip4: IpAddr = "::1".parse().unwrap();
    /// assert!(net.contains(ip1));
    /// assert!(!net.contains(ip2));
    /// assert!(!net.contains(ip4));
    /// ```
    pub fn contains(&self, ip: IpAddr) -> bool {
        match (*self, ip) {
            (IpNetwork::V4(net), IpAddr::V4(ip)) => net.contains(ip),
            (IpNetwork::V6(net), IpAddr::V6(ip)) => net.contains(ip),
            _ => false,
        }
    }

    /// Returns the number of possible host addresses in this `IpAddr`
    ///
    /// # Examples
    ///
    /// ```
    /// use ipnetwork::{IpNetwork, NetworkSize};
    ///
    ///
    /// let net: IpNetwork = "127.0.0.0/24".parse().unwrap();
    /// assert_eq!(net.size(), NetworkSize::V4(256))
    /// ```
    pub fn size(&self) -> NetworkSize {
        match *self {
            IpNetwork::V4(ref ip) => NetworkSize::V4(ip.size()),
            IpNetwork::V6(ref ip) => NetworkSize::V6(ip.size()),
        }
    }

    /// Returns an iterator over the addresses contained in the network.
    ///
    /// This lists all the addresses in the network range, in ascending order.
    pub fn iter(&self) -> IpNetworkIterator {
        let inner = match self {
            IpNetwork::V4(ip) => IpNetworkIteratorInner::V4(ip.iter()),
            IpNetwork::V6(ip) => IpNetworkIteratorInner::V6(ip.iter()),
        };
        IpNetworkIterator { inner }
    }
}

/// Tries to parse the given string into a `IpNetwork`. Will first try to parse
/// it as an `Ipv4Network` and if that fails as an `Ipv6Network`. If both
/// fails it will return an `InvalidAddr` error.
///
/// # Examples
///
/// ```
/// use std::net::Ipv4Addr;
/// use ipnetwork::{IpNetwork, Ipv4Network};
///
/// let expected = IpNetwork::V4(Ipv4Network::new(Ipv4Addr::new(10, 1, 9, 32), 16).unwrap());
/// let from_cidr: IpNetwork = "10.1.9.32/16".parse().unwrap();
/// assert_eq!(expected, from_cidr);
/// ```
impl FromStr for IpNetwork {
    type Err = IpNetworkError;
    fn from_str(s: &str) -> Result<IpNetwork, IpNetworkError> {
        if let Ok(net) = Ipv4Network::from_str(s) {
            Ok(IpNetwork::V4(net))
        } else if let Ok(net) = Ipv6Network::from_str(s) {
            Ok(IpNetwork::V6(net))
        } else {
            Err(IpNetworkError::InvalidAddr(s.to_string()))
        }
    }
}

impl From<Ipv4Network> for IpNetwork {
    fn from(v4: Ipv4Network) -> IpNetwork {
        IpNetwork::V4(v4)
    }
}

impl From<Ipv6Network> for IpNetwork {
    fn from(v6: Ipv6Network) -> IpNetwork {
        IpNetwork::V6(v6)
    }
}

impl From<IpAddr> for IpNetwork {
    fn from(addr: IpAddr) -> IpNetwork {
        match addr {
            IpAddr::V4(a) => IpNetwork::V4(Ipv4Network::from(a)),
            IpAddr::V6(a) => IpNetwork::V6(Ipv6Network::from(a)),
        }
    }
}

impl fmt::Display for IpNetwork {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            IpNetwork::V4(net) => net.fmt(f),
            IpNetwork::V6(net) => net.fmt(f),
        }
    }
}

#[derive(Clone, Debug)]
enum IpNetworkIteratorInner {
    V4(Ipv4NetworkIterator),
    V6(Ipv6NetworkIterator),
}

pub struct IpNetworkIterator {
    inner: IpNetworkIteratorInner,
}

impl Iterator for IpNetworkIterator {
    type Item = IpAddr;
    fn next(&mut self) -> Option<IpAddr> {
        match &mut self.inner {
            IpNetworkIteratorInner::V4(iter) => iter.next().map(IpAddr::V4),
            IpNetworkIteratorInner::V6(iter) => iter.next().map(IpAddr::V6),
        }
    }
}

impl IntoIterator for &'_ IpNetwork {
    type IntoIter = IpNetworkIterator;
    type Item = IpAddr;
    fn into_iter(self) -> IpNetworkIterator {
        self.iter()
    }
}

/// Converts a `IpAddr` network mask into a prefix.
/// If the mask is invalid this will return an `IpNetworkError::InvalidPrefix`.
pub fn ip_mask_to_prefix(mask: IpAddr) -> Result<u8, IpNetworkError> {
    match mask {
        IpAddr::V4(mask) => ipv4_mask_to_prefix(mask),
        IpAddr::V6(mask) => ipv6_mask_to_prefix(mask),
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn deserialize_from_serde_json_value() {
        use super::*;
        let network = IpNetwork::from_str("0.0.0.0/0").unwrap();
        let val: serde_json::value::Value =
            serde_json::from_str(&serde_json::to_string(&network).unwrap()).unwrap();
        let _deser: IpNetwork = serde_json::from_value(val)
            .expect("Fails to deserialize from json_value::value::Value");
    }
}
<|endoftext|>


<commit_before>//! MC Named Binary Tag type.

#![feature(core, test)]

extern crate byteorder;
extern crate flate2;
extern crate test;

/* Re-export the core API from submodules. */
pub use blob::NbtBlob;
pub use error::NbtError;
pub use value::NbtValue;

mod blob;
mod error;
mod value;
#[cfg(test)] mod tests;
<commit_msg>Only load the `test` feature & crate when testing.<commit_after>//! MC Named Binary Tag type.

#![feature(core)]
#![cfg_attr(test, feature(test))]

extern crate byteorder;
extern crate flate2;
#[cfg(test)] extern crate test;

/* Re-export the core API from submodules. */
pub use blob::NbtBlob;
pub use error::NbtError;
pub use value::NbtValue;

mod blob;
mod error;
mod value;
#[cfg(test)] mod tests;
<|endoftext|>


<commit_before>#![cfg_attr(feature = "nightly", feature(plugin))]
#![cfg_attr(feature = "nightly", plugin(clippy))]

#[derive(Clone, Debug)]
pub enum Type {
    Int8,
    Int16,
    Int32,
    Int64,
    ISize,
    UInt8,
    UInt16,
    UInt32,
    UInt64,
    USize,
    Float32,
    Float64,
    Char,
    Bool,
    Array(Box<Type>, usize),
    Compound(Vec<Field>, usize)
}

impl Type {
    /// Returns the total size of a type value in bytes.
    pub fn size(&self) -> usize {
        match *self {
            Type::Int8 | Type::UInt8 | Type::Bool => 1,
            Type::Int16 | Type::UInt16 => 2,
            Type::Int32 | Type::UInt32 | Type::Float32 => 4,
            Type::Int64 | Type::UInt64 | Type::Float64 => 8,
            Type::Char => ::std::mem::size_of::<char>(),
            Type::USize => ::std::mem::size_of::<usize>(),
            Type::ISize => ::std::mem::size_of::<isize>(),
            Type::Array(ref ty, num) => ty.size() * num,
            Type::Compound(_, size) => size,
        }
    }

    /// Returns true if the underlying type is a scalar.
    pub fn is_scalar(&self) -> bool {
        !self.is_array() && !self.is_compound()
    }

    /// Returns true if the underlying type is a fixed-size array.
    pub fn is_array(&self) -> bool {
        if let Type::Array(_, _) = *self { true } else { false }
    }

    /// Returns true if the underlying type is compound.
    pub fn is_compound(&self) -> bool {
        if let Type::Compound(_, _) = *self { true } else { false }
    }
}

#[derive(Clone, Debug)]
pub struct Field {
    pub ty: Type,
    pub name: String,
    pub offset: usize,
}

impl Field {
    pub fn new<S, U>(ty: &Type, name: S, offset: U) -> Field
    where S: Into<String>, U: Into<usize> {
        Field {
            ty: ty.clone(),
            name: name.into(),
            offset: offset.into()
        }
    }
}

pub trait TypeInfo : Copy {
    fn type_info() -> Type;
}

macro_rules! impl_scalar {
    ($t:ty, $i:ident) => (
        impl $crate::TypeInfo for $t {
            #[inline(always)]
            fn type_info() -> $crate::Type {
                $crate::Type::$i
            }
        }
    )
}

// implement TypeInfo for built-in scalar types
impl_scalar!(i8, Int8);
impl_scalar!(i16, Int16);
impl_scalar!(i32, Int32);
impl_scalar!(i64, Int64);
impl_scalar!(isize, ISize);
impl_scalar!(u8, UInt8);
impl_scalar!(u16, UInt16);
impl_scalar!(u32, UInt32);
impl_scalar!(u64, UInt64);
impl_scalar!(usize, USize);
impl_scalar!(f32, Float32);
impl_scalar!(f64, Float64);
impl_scalar!(char, Char);
impl_scalar!(bool, Bool);

macro_rules! impl_array {
    ($($n:expr),*$(,)*) => {
        $(
            impl<T: $crate::TypeInfo> $crate::TypeInfo for [T; $n] {
                #[inline(always)]
                fn type_info() -> $crate::Type {
                    $crate::Type::Array(
                        Box::new(<T as $crate::TypeInfo>::type_info()),
                        $n
                    )
                }
            }
        )*
    };
}

// implement TypeInfo for fixed-size arrays of lengths 0..63
impl_array!(
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
);

#[macro_export]
macro_rules! def {
    // private struct, private fields
    ($($(#[$attr:meta])* struct $s:ident { $($i:ident: $t:ty),+$(,)* })*) => (
        $(
            #[allow(dead_code)]
            #[derive(Clone, Copy)]
            $(#[$attr])*
            struct $s { $($i: $t),* }
            def!(@impl $s { $($i: $t),+ } );
        )*
    );

    // public struct, private fields
    ($($(#[$attr:meta])* pub struct $s:ident { $($i:ident: $t:ty),+$(,)* })*) => (
        $(
            #[allow(dead_code)]
            #[derive(Clone, Copy)]
            $(#[$attr])*
            pub struct $s { $($i: $t),* }
            def!(@impl $s { $($i: $t),+ } );
        )*
    );

    // public struct, public fields
    ($($(#[$attr:meta])* pub struct $s:ident { $(pub $i:ident: $t:ty),+$(,)* })*) => (
        $(
            #[allow(dead_code)]
            #[derive(Clone, Copy)]
            $(#[$attr])*
            pub struct $s { pub $($i: $t),* }
            def!(@impl $s { $($i: $t),+ } );
        )*
    );

    // implement TypeInfo trait
    (@impl $s:ident { $($i:ident: $t:ty),+ }) => (
        impl $crate::TypeInfo for $s {
            fn type_info() -> $crate::Type {
                let base = 0usize as *const $s;
                $crate::Type::Compound(vec![$(
                    $crate::Field::new(
                        &<$t as $crate::TypeInfo>::type_info(),
                        stringify!($i),
                        unsafe { &((*base).$i) as *const $t as usize}
                    )
                ),*], ::std::mem::size_of::<$s>())
            }
        }
    );
}

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

    def! {
        #[derive(Debug)]
        pub struct Foo {
            pub a: bool,
            pub b: i32,
        }

        pub struct Bar {
            pub foo: [Foo; 2],
            pub s: f64
        }
    }

    #[test]
    fn test_smoke() {
        println!("{:#?}", Bar::type_info());
    }
}
<commit_msg>Docstrings<commit_after>#![cfg_attr(feature = "nightly", feature(plugin))]
#![cfg_attr(feature = "nightly", plugin(clippy))]

/// POD (*plain old data*) type: scalar, fixed-size array or compound (struct).
/// May be arbitrarily nested.
#[derive(Clone, Debug)]
pub enum Type {
    /// 1-byte signed integer
    Int8,
    /// 2-byte signed integer
    Int16,
    /// 4-byte signed integer
    Int32,
    /// 8-byte signed integer
    Int64,
    /// pointer-sized signed integer
    ISize,
    /// 1-byte unsigned integer
    UInt8,
    /// 2-byte unsigned integer
    UInt16,
    /// 3-byte unsigned integer
    UInt32,
    /// 4-byte unsigned integer
    UInt64,
    /// pointer-sized unsigned integer
    USize,
    /// 4-byte floating-point number
    Float32,
    /// 8-byte floating-point number
    Float64,
    /// character type
    Char,
    /// 1-byte boolean type
    Bool,
    /// fixed-size array with POD elements
    Array(Box<Type>, usize),
    /// compound type whose fields are POD
    Compound(Vec<Field>, usize),
}

impl Type {
    /// Returns the total size of a type value in bytes.
    pub fn size(&self) -> usize {
        match *self {
            Type::Int8 | Type::UInt8 | Type::Bool => 1,
            Type::Int16 | Type::UInt16 => 2,
            Type::Int32 | Type::UInt32 | Type::Float32 => 4,
            Type::Int64 | Type::UInt64 | Type::Float64 => 8,
            Type::Char => ::std::mem::size_of::<char>(),
            Type::USize => ::std::mem::size_of::<usize>(),
            Type::ISize => ::std::mem::size_of::<isize>(),
            Type::Array(ref ty, num) => ty.size() * num,
            Type::Compound(_, size) => size,
        }
    }

    /// Returns true if the underlying type is a scalar.
    pub fn is_scalar(&self) -> bool {
        !self.is_array() && !self.is_compound()
    }

    /// Returns true if the underlying type is a fixed-size array.
    pub fn is_array(&self) -> bool {
        if let Type::Array(_, _) = *self { true } else { false }
    }

    /// Returns true if the underlying type is compound.
    pub fn is_compound(&self) -> bool {
        if let Type::Compound(_, _) = *self { true } else { false }
    }
}

/// Field of a compound type: type, name and offset from the beginning of the struct.
#[derive(Clone, Debug)]
pub struct Field {
    /// field value type
    pub ty: Type,
    /// field name
    pub name: String,
    /// offset to the beginning of the struct
    pub offset: usize,
}

impl Field {
    pub fn new<S, U>(ty: &Type, name: S, offset: U) -> Field
    where S: Into<String>, U: Into<usize> {
        Field {
            ty: ty.clone(),
            name: name.into(),
            offset: offset.into()
        }
    }
}

pub trait TypeInfo: Copy {
    /// Returns the runtime type information for the implementing type.
    fn type_info() -> Type;
}

macro_rules! impl_scalar {
    ($t:ty, $i:ident) => (
        impl $crate::TypeInfo for $t {
            #[inline(always)]
            fn type_info() -> $crate::Type {
                $crate::Type::$i
            }
        }
    )
}

// implement TypeInfo for built-in scalar types
impl_scalar!(i8, Int8);
impl_scalar!(i16, Int16);
impl_scalar!(i32, Int32);
impl_scalar!(i64, Int64);
impl_scalar!(isize, ISize);
impl_scalar!(u8, UInt8);
impl_scalar!(u16, UInt16);
impl_scalar!(u32, UInt32);
impl_scalar!(u64, UInt64);
impl_scalar!(usize, USize);
impl_scalar!(f32, Float32);
impl_scalar!(f64, Float64);
impl_scalar!(char, Char);
impl_scalar!(bool, Bool);

macro_rules! impl_array {
    ($($n:expr),*$(,)*) => {
        $(
            impl<T: $crate::TypeInfo> $crate::TypeInfo for [T; $n] {
                #[inline(always)]
                fn type_info() -> $crate::Type {
                    $crate::Type::Array(
                        Box::new(<T as $crate::TypeInfo>::type_info()),
                        $n
                    )
                }
            }
        )*
    };
}

// implement TypeInfo for fixed-size arrays of lengths 0..63
impl_array!(
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
);

#[macro_export]
macro_rules! def {
    // private struct, private fields
    ($($(#[$attr:meta])* struct $s:ident { $($i:ident: $t:ty),+$(,)* })*) => (
        $(
            #[allow(dead_code)]
            #[derive(Clone, Copy)]
            $(#[$attr])*
            struct $s { $($i: $t),* }
            def!(@impl $s { $($i: $t),+ } );
        )*
    );

    // public struct, private fields
    ($($(#[$attr:meta])* pub struct $s:ident { $($i:ident: $t:ty),+$(,)* })*) => (
        $(
            #[allow(dead_code)]
            #[derive(Clone, Copy)]
            $(#[$attr])*
            pub struct $s { $($i: $t),* }
            def!(@impl $s { $($i: $t),+ } );
        )*
    );

    // public struct, public fields
    ($($(#[$attr:meta])* pub struct $s:ident { $(pub $i:ident: $t:ty),+$(,)* })*) => (
        $(
            #[allow(dead_code)]
            #[derive(Clone, Copy)]
            $(#[$attr])*
            pub struct $s { pub $($i: $t),* }
            def!(@impl $s { $($i: $t),+ } );
        )*
    );

    // implement TypeInfo trait
    (@impl $s:ident { $($i:ident: $t:ty),+ }) => (
        impl $crate::TypeInfo for $s {
            fn type_info() -> $crate::Type {
                let base = 0usize as *const $s;
                $crate::Type::Compound(vec![$(
                    $crate::Field::new(
                        &<$t as $crate::TypeInfo>::type_info(),
                        stringify!($i),
                        unsafe { &((*base).$i) as *const $t as usize}
                    )
                ),*], ::std::mem::size_of::<$s>())
            }
        }
    );
}

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

    def! {
        #[derive(Debug)]
        pub struct Foo {
            pub a: bool,
            pub b: i32,
        }

        pub struct Bar {
            pub foo: [Foo; 2],
            pub s: f64
        }
    }

    #[test]
    fn test_smoke() {
        println!("{:#?}", Bar::type_info());
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.

#[macro_use] extern crate bitflags;
extern crate libc;

use std::io::{self, Error};
use std::os::unix::io::RawFd;

#[allow(non_camel_case_types)]
pub enum ControlOptions {
    /// Indicates an addition to the interest list.
    EPOLL_CTL_ADD = libc::EPOLL_CTL_ADD as isize,
    /// Indicates a modification of flags for an interest already in list.
    EPOLL_CTL_MOD = libc::EPOLL_CTL_MOD as isize,
    /// Indicates a removal of an interest from the list.
    EPOLL_CTL_DEL = libc::EPOLL_CTL_DEL as isize
}

bitflags! {
    pub struct Events: u32 {
        /// Sets the Edge Triggered behavior for the associated file descriptor.
        ///
        /// The default behavior for epoll is Level Triggered.
        const EPOLLET      = libc::EPOLLET as u32;
        /// The associated file is available for read operations.
        const EPOLLIN      = libc::EPOLLIN as u32;
        /// Error condition happened on the associated file descriptor.
        ///
        /// `wait` will always wait for this event; is not necessary to set it in events.
        const EPOLLERR     = libc::EPOLLERR as u32;
        /// Hang up happened on the associated file descriptor.
        ///
        /// `wait` will always wait for this event; it is not necessary to set it in events.
        /// Note that when reading from a channel such as a pipe or a stream socket, this event
        /// merely indicates that the peer closed its end of the channel. Subsequent reads from
        /// the channel will return 0 (end of file) only after all outstanding data in the
        /// channel has been consumed.
        const EPOLLHUP     = libc::EPOLLHUP as u32;
        /// The associated file is available for write operations.
        const EPOLLOUT     = libc::EPOLLOUT as u32;
        /// There is urgent data available for read operations.
        const EPOLLPRI     = libc::EPOLLPRI as u32;
        /// Stream socket peer closed connection, or shut down writing half of connection.
        ///
        /// This flag is especially useful for writing simple code to detect peer shutdown when
        /// using Edge Triggered monitoring.
        const EPOLLRDHUP   = libc::EPOLLRDHUP as u32;
        /// If `EPOLLONESHOT` and `EPOLLET` are clear and the process has the `CAP_BLOCK_SUSPEND`
        /// capability, ensure that the system does not enter "suspend" or "hibernate" while this
        /// event is pending or being processed.
        ///
        /// The event is considered as being "processed" from the time when it is returned by
        /// a call to `wait` until the next call to `wait` on the same `EpollInstance`
        /// descriptor, the closure of that file descriptor, the removal of the event file
        /// descriptor with `EPOLL_CTL_DEL`, or the clearing of `EPOLLWAKEUP` for the event file
        /// descriptor with `EPOLL_CTL_MOD`.
        const EPOLLWAKEUP  = libc::EPOLLWAKEUP as u32;
        /// Sets the one-shot behavior for the associated file descriptor.
        ///
        /// This means that after an event is pulled out with `wait` the associated file
        /// descriptor is internally disabled and no other events will be reported by the epoll
        /// interface.  The user must call `ctl` with `EPOLL_CTL_MOD` to rearm the file
        /// descriptor with a new event mask.
        const EPOLLONESHOT = libc::EPOLLONESHOT as u32;
    }
}

/// 'libc::epoll_event' equivalent.
#[repr(C)]
#[cfg_attr(target_arch = "x86_64", repr(packed))]
#[derive(Clone, Copy)]
pub struct Event {
    pub events: u32,
    pub data: u64
}

impl Event {
    pub fn new(events: Events, data: u64) -> Event {
        Event { events: events.bits(), data: data }
    }
}

/// Creates a new epoll file descriptor.
///
/// If `cloexec` is true, `FD_CLOEXEC` will be set on the returned file descriptor.
///
/// ## Notes
///
/// * `epoll_create1()` is the underlying syscall.
pub fn create(cloexec: bool) -> io::Result<RawFd> {
    let flags = if cloexec { libc::EPOLL_CLOEXEC } else { 0 };
    unsafe { cvt(libc::epoll_create1(flags)) }
}

/// Safe wrapper for `libc::epoll_ctl`
pub fn ctl(epfd: RawFd,
           op: ControlOptions,
           fd: RawFd,
           mut event: Event)
           -> io::Result<()>
{
    let e = &mut event as *mut _ as *mut libc::epoll_event;
    unsafe { cvt(libc::epoll_ctl(epfd, op as i32, fd, e))? };
    Ok(())
}

/// Safe wrapper for `libc::epoll_wait`
///
/// ## Notes
///
/// * If `timeout` is negative, it will block until an event is received.
pub fn wait(epfd: RawFd,
            timeout: i32,
            buf: &mut [Event])
            -> io::Result<usize>
{
    let timeout = if timeout < -1 { -1 } else { timeout };
    let num_events = unsafe {
        cvt(libc::epoll_wait(epfd,
                                  buf.as_mut_ptr() as *mut libc::epoll_event,
                                  buf.len() as i32,
                                  timeout))? as usize
    };
    Ok(num_events)
}

/// Safe wrapper for `libc::close`
pub fn close(epfd: RawFd) -> io::Result<()> {
    cvt(unsafe { libc::close(epfd) })?;
    Ok(())
}

fn cvt(result: libc::c_int) -> io::Result<libc::c_int> {
    if result < 0 { Err(Error::last_os_error()) } else { Ok(result) }
}
<commit_msg>Updates ControlOptions to i32.<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.

#[macro_use] extern crate bitflags;
extern crate libc;

use std::io::{self, Error};
use std::os::unix::io::RawFd;

#[repr(i32)]
#[allow(non_camel_case_types)]
pub enum ControlOptions {
    /// Indicates an addition to the interest list.
    EPOLL_CTL_ADD = libc::EPOLL_CTL_ADD,
    /// Indicates a modification of flags for an interest already in list.
    EPOLL_CTL_MOD = libc::EPOLL_CTL_MOD,
    /// Indicates a removal of an interest from the list.
    EPOLL_CTL_DEL = libc::EPOLL_CTL_DEL,
}

bitflags! {
    pub struct Events: u32 {
        /// Sets the Edge Triggered behavior for the associated file descriptor.
        ///
        /// The default behavior for epoll is Level Triggered.
        const EPOLLET      = libc::EPOLLET as u32;
        /// The associated file is available for read operations.
        const EPOLLIN      = libc::EPOLLIN as u32;
        /// Error condition happened on the associated file descriptor.
        ///
        /// `wait` will always wait for this event; is not necessary to set it in events.
        const EPOLLERR     = libc::EPOLLERR as u32;
        /// Hang up happened on the associated file descriptor.
        ///
        /// `wait` will always wait for this event; it is not necessary to set it in events.
        /// Note that when reading from a channel such as a pipe or a stream socket, this event
        /// merely indicates that the peer closed its end of the channel. Subsequent reads from
        /// the channel will return 0 (end of file) only after all outstanding data in the
        /// channel has been consumed.
        const EPOLLHUP     = libc::EPOLLHUP as u32;
        /// The associated file is available for write operations.
        const EPOLLOUT     = libc::EPOLLOUT as u32;
        /// There is urgent data available for read operations.
        const EPOLLPRI     = libc::EPOLLPRI as u32;
        /// Stream socket peer closed connection, or shut down writing half of connection.
        ///
        /// This flag is especially useful for writing simple code to detect peer shutdown when
        /// using Edge Triggered monitoring.
        const EPOLLRDHUP   = libc::EPOLLRDHUP as u32;
        /// If `EPOLLONESHOT` and `EPOLLET` are clear and the process has the `CAP_BLOCK_SUSPEND`
        /// capability, ensure that the system does not enter "suspend" or "hibernate" while this
        /// event is pending or being processed.
        ///
        /// The event is considered as being "processed" from the time when it is returned by
        /// a call to `wait` until the next call to `wait` on the same `EpollInstance`
        /// descriptor, the closure of that file descriptor, the removal of the event file
        /// descriptor with `EPOLL_CTL_DEL`, or the clearing of `EPOLLWAKEUP` for the event file
        /// descriptor with `EPOLL_CTL_MOD`.
        const EPOLLWAKEUP  = libc::EPOLLWAKEUP as u32;
        /// Sets the one-shot behavior for the associated file descriptor.
        ///
        /// This means that after an event is pulled out with `wait` the associated file
        /// descriptor is internally disabled and no other events will be reported by the epoll
        /// interface.  The user must call `ctl` with `EPOLL_CTL_MOD` to rearm the file
        /// descriptor with a new event mask.
        const EPOLLONESHOT = libc::EPOLLONESHOT as u32;
    }
}

/// 'libc::epoll_event' equivalent.
#[repr(C)]
#[cfg_attr(target_arch = "x86_64", repr(packed))]
#[derive(Clone, Copy)]
pub struct Event {
    pub events: u32,
    pub data: u64
}

impl Event {
    pub fn new(events: Events, data: u64) -> Event {
        Event { events: events.bits(), data: data }
    }
}

/// Creates a new epoll file descriptor.
///
/// If `cloexec` is true, `FD_CLOEXEC` will be set on the returned file descriptor.
///
/// ## Notes
///
/// * `epoll_create1()` is the underlying syscall.
pub fn create(cloexec: bool) -> io::Result<RawFd> {
    let flags = if cloexec { libc::EPOLL_CLOEXEC } else { 0 };
    unsafe { cvt(libc::epoll_create1(flags)) }
}

/// Safe wrapper for `libc::epoll_ctl`
pub fn ctl(epfd: RawFd,
           op: ControlOptions,
           fd: RawFd,
           mut event: Event)
           -> io::Result<()>
{
    let e = &mut event as *mut _ as *mut libc::epoll_event;
    unsafe { cvt(libc::epoll_ctl(epfd, op as i32, fd, e))? };
    Ok(())
}

/// Safe wrapper for `libc::epoll_wait`
///
/// ## Notes
///
/// * If `timeout` is negative, it will block until an event is received.
pub fn wait(epfd: RawFd,
            timeout: i32,
            buf: &mut [Event])
            -> io::Result<usize>
{
    let timeout = if timeout < -1 { -1 } else { timeout };
    let num_events = unsafe {
        cvt(libc::epoll_wait(epfd,
                                  buf.as_mut_ptr() as *mut libc::epoll_event,
                                  buf.len() as i32,
                                  timeout))? as usize
    };
    Ok(num_events)
}

/// Safe wrapper for `libc::close`
pub fn close(epfd: RawFd) -> io::Result<()> {
    cvt(unsafe { libc::close(epfd) })?;
    Ok(())
}

fn cvt(result: libc::c_int) -> io::Result<libc::c_int> {
    if result < 0 { Err(Error::last_os_error()) } else { Ok(result) }
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]

//! A Gfx texture representation that works nicely with Piston libraries.

extern crate gfx;
extern crate texture;
extern crate image;

pub use texture::*;

use std::path::Path;
use image::{
    DynamicImage,
    RgbaImage,
};
use gfx::CombinedError;
use gfx::format::{Srgba8, R8_G8_B8_A8};

/// Flip settings.
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Flip {
    /// Does not flip.
    None,
    /// Flips image vertically.
    Vertical,
}

/// Represents a texture.
pub struct Texture<R> where R: gfx::Resources {
    /// Pixel storage for texture.
    pub surface: gfx::handle::Texture<R, R8_G8_B8_A8>,
    /// View used by shader.
    pub view: gfx::handle::ShaderResourceView<R, [f32; 4]>
}

impl<R: gfx::Resources> Texture<R> {
    /// Returns empty texture.
    pub fn empty<F>(factory: &mut F) -> Result<Self, CombinedError>
        where F: gfx::Factory<R>
    {
        CreateTexture::create(factory, Format::Rgba8, &[0u8; 4], [1, 1],
                              &TextureSettings::new())
    }

    /// Creates a texture from path.
    pub fn from_path<F, P>(
        factory: &mut F,
        path: P,
        flip: Flip,
        settings: &TextureSettings,
    ) -> Result<Self, String>
        where F: gfx::Factory<R>,
              P: AsRef<Path>
    {
        let img = try!(image::open(path).map_err(|e| e.to_string()));

        let img = match img {
            DynamicImage::ImageRgba8(img) => img,
            img => img.to_rgba()
        };

        let img = if flip == Flip::Vertical {
            image::imageops::flip_vertical(&img)
        } else {
            img
        };

        Texture::from_image(factory, &img, settings).map_err(
            |e| format!("{:?}", e))
    }

    /// Creates a texture from image.
    pub fn from_image<F>(
        factory: &mut F,
        img: &RgbaImage,
        settings: &TextureSettings
    ) -> Result<Self, CombinedError>
        where F: gfx::Factory<R>
    {
        let (width, height) = img.dimensions();
        CreateTexture::create(factory, Format::Rgba8,
                              img, [width, height], settings)
    }

    /// Creates texture from memory alpha.
    pub fn from_memory_alpha<F>(
        factory: &mut F,
        buffer: &[u8],
        width: u32,
        height: u32,
        settings: &TextureSettings
    ) -> Result<Self, CombinedError>
        where F: gfx::Factory<R>
    {
        if width == 0 || height == 0 {
            return Texture::empty(factory);
        }

        let size = [width, height];
        let buffer = texture::ops::alpha_to_rgba8(buffer, size);
        CreateTexture::create(factory, Format::Rgba8, &buffer, size, settings)
    }

    /// Updates the texture with an image.
    pub fn update<C>(
        &mut self,
        encoder: &mut gfx::Encoder<R, C>,
        img: &RgbaImage
    ) -> Result<(), gfx::UpdateError<[u16; 3]>>
        where C: gfx::CommandBuffer<R>
    {
        let (width, height) = img.dimensions();
        UpdateTexture::update(self, encoder, Format::Rgba8,
                              img, [width, height])
    }
}

impl<F, R> CreateTexture<F> for Texture<R>
    where F: gfx::Factory<R>,
          R: gfx::Resources
{
    type Error = CombinedError;

    fn create<S: Into<[u32; 2]>>(
        factory: &mut F,
        _format: Format,
        memory: &[u8],
        size: S,
        _settings: &TextureSettings
    ) -> Result<Self, Self::Error> {
        let size = size.into();
        let (width, height) = (size[0] as u16, size[1] as u16);
        let tex_kind = gfx::tex::Kind::D2(width, height,
            gfx::tex::AaMode::Single);

        let (surface, view) = try!(factory.create_texture_const_u8::<Srgba8>(
            tex_kind, &[memory]));
        Ok(Texture { surface: surface, view: view })
    }
}

impl<R, C> UpdateTexture<gfx::Encoder<R, C>> for Texture<R>
    where R: gfx::Resources,
          C: gfx::CommandBuffer<R>
{
    type Error = gfx::UpdateError<[u16; 3]>;

    fn update<S: Into<[u32; 2]>>(
        &mut self,
        encoder: &mut gfx::Encoder<R, C>,
        format: Format,
        memory: &[u8],
        size: S,
    ) -> Result<(), Self::Error> {

        // TODO: This should be passed via the args.
        let offset = [0, 0];

        let size = size.into();
        let tex = &self.surface;
        let face = None;
        let img_info = gfx::tex::ImageInfoCommon {
            xoffset: offset[0],
            yoffset: offset[1],
            zoffset: 0,
            width: size[0] as u16,
            height: size[1] as u16,
            depth: 0,
            format: (),
            mipmap: 0,
        };
        let data = gfx::cast_slice(memory);

        match format {
            Format::Rgba8 => {
                use gfx::format::Rgba8;
                encoder.update_texture::<_, Rgba8>(tex, face, img_info, data).map_err(Into::into)
            },
        }
    }
}

impl<R> ImageSize for Texture<R> where R: gfx::Resources {
    #[inline(always)]
    fn get_size(&self) -> (u32, u32) {
        let (w, h, _, _) = self.surface.get_info().kind.get_dimensions();
        (w as u32, h as u32)
    }
}
<commit_msg>Update to the addition of an offset argument to the UpdateTexture::update method, introduced in PistonDevelopers/texture#40.<commit_after>#![deny(missing_docs)]

//! A Gfx texture representation that works nicely with Piston libraries.

extern crate gfx;
extern crate texture;
extern crate image;

pub use texture::*;

use std::path::Path;
use image::{
    DynamicImage,
    RgbaImage,
};
use gfx::CombinedError;
use gfx::format::{Srgba8, R8_G8_B8_A8};

/// Flip settings.
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Flip {
    /// Does not flip.
    None,
    /// Flips image vertically.
    Vertical,
}

/// Represents a texture.
pub struct Texture<R> where R: gfx::Resources {
    /// Pixel storage for texture.
    pub surface: gfx::handle::Texture<R, R8_G8_B8_A8>,
    /// View used by shader.
    pub view: gfx::handle::ShaderResourceView<R, [f32; 4]>
}

impl<R: gfx::Resources> Texture<R> {
    /// Returns empty texture.
    pub fn empty<F>(factory: &mut F) -> Result<Self, CombinedError>
        where F: gfx::Factory<R>
    {
        CreateTexture::create(factory, Format::Rgba8, &[0u8; 4], [1, 1],
                              &TextureSettings::new())
    }

    /// Creates a texture from path.
    pub fn from_path<F, P>(
        factory: &mut F,
        path: P,
        flip: Flip,
        settings: &TextureSettings,
    ) -> Result<Self, String>
        where F: gfx::Factory<R>,
              P: AsRef<Path>
    {
        let img = try!(image::open(path).map_err(|e| e.to_string()));

        let img = match img {
            DynamicImage::ImageRgba8(img) => img,
            img => img.to_rgba()
        };

        let img = if flip == Flip::Vertical {
            image::imageops::flip_vertical(&img)
        } else {
            img
        };

        Texture::from_image(factory, &img, settings).map_err(
            |e| format!("{:?}", e))
    }

    /// Creates a texture from image.
    pub fn from_image<F>(
        factory: &mut F,
        img: &RgbaImage,
        settings: &TextureSettings
    ) -> Result<Self, CombinedError>
        where F: gfx::Factory<R>
    {
        let (width, height) = img.dimensions();
        CreateTexture::create(factory, Format::Rgba8,
                              img, [width, height], settings)
    }

    /// Creates texture from memory alpha.
    pub fn from_memory_alpha<F>(
        factory: &mut F,
        buffer: &[u8],
        width: u32,
        height: u32,
        settings: &TextureSettings
    ) -> Result<Self, CombinedError>
        where F: gfx::Factory<R>
    {
        if width == 0 || height == 0 {
            return Texture::empty(factory);
        }

        let size = [width, height];
        let buffer = texture::ops::alpha_to_rgba8(buffer, size);
        CreateTexture::create(factory, Format::Rgba8, &buffer, size, settings)
    }

    /// Updates the texture with an image.
    pub fn update<C>(
        &mut self,
        encoder: &mut gfx::Encoder<R, C>,
        img: &RgbaImage
    ) -> Result<(), gfx::UpdateError<[u16; 3]>>
        where C: gfx::CommandBuffer<R>
    {
        let (width, height) = img.dimensions();
        let offset = [0, 0];
        let size = [width, height];
        UpdateTexture::update(self, encoder, Format::Rgba8, img, offset, size)
    }
}

impl<F, R> CreateTexture<F> for Texture<R>
    where F: gfx::Factory<R>,
          R: gfx::Resources
{
    type Error = CombinedError;

    fn create<S: Into<[u32; 2]>>(
        factory: &mut F,
        _format: Format,
        memory: &[u8],
        size: S,
        _settings: &TextureSettings
    ) -> Result<Self, Self::Error> {
        let size = size.into();
        let (width, height) = (size[0] as u16, size[1] as u16);
        let tex_kind = gfx::tex::Kind::D2(width, height,
            gfx::tex::AaMode::Single);

        let (surface, view) = try!(factory.create_texture_const_u8::<Srgba8>(
            tex_kind, &[memory]));
        Ok(Texture { surface: surface, view: view })
    }
}

impl<R, C> UpdateTexture<gfx::Encoder<R, C>> for Texture<R>
    where R: gfx::Resources,
          C: gfx::CommandBuffer<R>
{
    type Error = gfx::UpdateError<[u16; 3]>;

    fn update<O, S>(
        &mut self,
        encoder: &mut gfx::Encoder<R, C>,
        format: Format,
        memory: &[u8],
        offset: O,
        size: S,
    ) -> Result<(), Self::Error>
        where O: Into<[u32; 2]>,
              S: Into<[u32; 2]>,
    {
        let offset = offset.into();
        let size = size.into();
        let tex = &self.surface;
        let face = None;
        let img_info = gfx::tex::ImageInfoCommon {
            xoffset: offset[0] as u16,
            yoffset: offset[1] as u16,
            zoffset: 0,
            width: size[0] as u16,
            height: size[1] as u16,
            depth: 0,
            format: (),
            mipmap: 0,
        };
        let data = gfx::cast_slice(memory);

        match format {
            Format::Rgba8 => {
                use gfx::format::Rgba8;
                encoder.update_texture::<_, Rgba8>(tex, face, img_info, data).map_err(Into::into)
            },
        }
    }
}

impl<R> ImageSize for Texture<R> where R: gfx::Resources {
    #[inline(always)]
    fn get_size(&self) -> (u32, u32) {
        let (w, h, _, _) = self.surface.get_info().kind.get_dimensions();
        (w as u32, h as u32)
    }
}
<|endoftext|>