<commit_before>// TODO Copyright Header

//! A very basic libstd front
//!
//! This is where all the stuff relating to processes is, including context switching, interrupts,
//! and processes/threads. Because of order of initialization and their use in interrupt handling
//! acpi and apic are in here as well.

#![crate_name="basicstd"]
#![crate_type="rlib"]
#![doc(html_logo_url = "https://avatars.io/gravatar/d0ad9c6f37bb5aceac2d7ac95ba82607?size=large",
       html_favicon_url="https://avatars.io/gravatar/d0ad9c6f37bb5aceac2d7ac95ba82607?size=small")]
#![feature(unsafe_destructor, int_uint, box_syntax)]
#![feature(optin_builtin_traits)]
#![feature(core)]
#![feature(alloc)]
#![feature(unicode)]
#![feature(collections)]
#![feature(rand)]
#![feature(hash)]
#![no_std]

#[macro_reexport(assert, assert_eq, debug_assert, write, writeln)]
#[macro_use] extern crate core;
#[macro_reexport(vec)]
#[macro_use] extern crate "collections" as core_collections;
extern crate "rand" as rrand;
extern crate alloc;
extern crate unicode;

pub use alloc::{boxed, rc};
pub use core::{any, borrow, cell, clone, cmp, default, error};
pub use core::{f32, f64, finally, hash, i16, i32, i64, i8, int, intrinsics};
pub use core::{isize, iter, marker, mem, num, ops, option, ptr, raw};
pub use core::{result, simd, u16, u32, u64, u8, uint, usize};
pub use core_collections::{str, string, slice, vec};
pub use unicode::char;

#[path = "../rust/src/libstd/macros.rs"]
#[macro_use] mod macros;

#[path = "../rust/src/libstd/ascii.rs"]
pub mod ascii;
#[path = "../rust/src/libstd/fmt.rs"]
pub mod fmt;
#[path = "../rust/src/libstd/collections/mod.rs"]
pub mod collections;

pub mod rand {
    pub use rrand::*;
    /// This is just a front. We will use what we have, which is a IsaacRng.
    #[derive(Clone)]
    #[allow(missing_copy_implementations)]
    pub struct ThreadRng(IsaacRng);
    impl Rng for ThreadRng {
        fn next_u32(&mut self) -> u32 { self.0.next_u32() }
    }
    static mut base_seed : [u32; 256] = [0; 256];
    /// Get an rng
    pub fn thread_rng() -> ThreadRng {
        use ::slice::*;
        let mut rng = IsaacRng::new_unseeded();
        rng.reseed(unsafe { &base_seed });
        let bs : &'static mut [u32] = unsafe { &mut base_seed };
        let len = bs.len();
        bs[rng.gen_range(0, len)] = rng.gen();
        ThreadRng(rng)
    }
}

pub mod thread {
    #[allow(missing_copy_implementations)]
    pub struct Thread;
    impl Thread {
        pub fn panicking() -> bool {
            false
        }
    }
}
pub mod sync;

pub mod rt {
    pub use alloc::heap;

    pub fn begin_unwind(msg: &str, fl: &(&'static str, usize)) -> ! {
        ::core::panicking::panic_fmt(format_args!("{}", msg), fl)
    }
    pub fn begin_unwind_fmt(msg: ::fmt::Arguments, file_line: &(&'static str, usize)) -> ! {
        ::core::panicking::panic_fmt(msg, file_line)
    }
}

pub mod prelude {
    pub mod v1 {
        pub use marker::{Copy, Send, Sized, Sync};
        pub use ops::{Drop, Fn, FnMut, FnOnce};
        pub use mem::drop;
        pub use boxed::Box;
        pub use char::CharExt;
        pub use clone::Clone;
        pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
        pub use iter::DoubleEndedIterator;
        pub use iter::ExactSizeIterator;
        pub use iter::{Iterator, IteratorExt, Extend};
        pub use option::Option::{self, Some, None};
        pub use ptr::{PtrExt, MutPtrExt};
        pub use result::Result::{self, Ok, Err};
        pub use slice::AsSlice;
        pub use slice::{SliceExt, SliceConcatExt};
        pub use str::{Str, StrExt};
        pub use string::{String, ToString};
        pub use vec::Vec;
        pub use iter::range;
    }
}

#[doc(hidden)]
mod std {
    pub use super::*;
}
<commit_msg>removed reenix doccomment I missed<commit_after>// TODO Copyright Header

//! A very basic libstd front
//!
//! This is almost totally independent of the runtime of rust, relying only
//! on the presence of allocation defined within liballoc.

#![crate_name="basicstd"]
#![crate_type="rlib"]
#![doc(html_logo_url = "https://avatars.io/gravatar/d0ad9c6f37bb5aceac2d7ac95ba82607?size=large",
       html_favicon_url="https://avatars.io/gravatar/d0ad9c6f37bb5aceac2d7ac95ba82607?size=small")]
#![feature(unsafe_destructor, int_uint, box_syntax)]
#![feature(optin_builtin_traits)]
#![feature(core)]
#![feature(alloc)]
#![feature(unicode)]
#![feature(collections)]
#![feature(rand)]
#![feature(hash)]
#![no_std]

#[macro_reexport(assert, assert_eq, debug_assert, write, writeln)]
#[macro_use] extern crate core;
#[macro_reexport(vec)]
#[macro_use] extern crate "collections" as core_collections;
extern crate "rand" as rrand;
extern crate alloc;
extern crate unicode;

pub use alloc::{boxed, rc};
pub use core::{any, borrow, cell, clone, cmp, default, error};
pub use core::{f32, f64, finally, hash, i16, i32, i64, i8, int, intrinsics};
pub use core::{isize, iter, marker, mem, num, ops, option, ptr, raw};
pub use core::{result, simd, u16, u32, u64, u8, uint, usize};
pub use core_collections::{str, string, slice, vec};
pub use unicode::char;

#[path = "../rust/src/libstd/macros.rs"]
#[macro_use] mod macros;

#[path = "../rust/src/libstd/ascii.rs"]
pub mod ascii;
#[path = "../rust/src/libstd/fmt.rs"]
pub mod fmt;
#[path = "../rust/src/libstd/collections/mod.rs"]
pub mod collections;

pub mod rand {
    pub use rrand::*;
    /// This is just a front. We will use what we have, which is a IsaacRng.
    #[derive(Clone)]
    #[allow(missing_copy_implementations)]
    pub struct ThreadRng(IsaacRng);
    impl Rng for ThreadRng {
        fn next_u32(&mut self) -> u32 { self.0.next_u32() }
    }
    static mut base_seed : [u32; 256] = [0; 256];
    /// Get an rng
    pub fn thread_rng() -> ThreadRng {
        use ::slice::*;
        let mut rng = IsaacRng::new_unseeded();
        rng.reseed(unsafe { &base_seed });
        let bs : &'static mut [u32] = unsafe { &mut base_seed };
        let len = bs.len();
        bs[rng.gen_range(0, len)] = rng.gen();
        ThreadRng(rng)
    }
}

pub mod thread {
    #[allow(missing_copy_implementations)]
    pub struct Thread;
    impl Thread {
        pub fn panicking() -> bool {
            false
        }
    }
}
pub mod sync;

pub mod rt {
    pub use alloc::heap;

    pub fn begin_unwind(msg: &str, fl: &(&'static str, usize)) -> ! {
        ::core::panicking::panic_fmt(format_args!("{}", msg), fl)
    }
    pub fn begin_unwind_fmt(msg: ::fmt::Arguments, file_line: &(&'static str, usize)) -> ! {
        ::core::panicking::panic_fmt(msg, file_line)
    }
}

pub mod prelude {
    pub mod v1 {
        pub use marker::{Copy, Send, Sized, Sync};
        pub use ops::{Drop, Fn, FnMut, FnOnce};
        pub use mem::drop;
        pub use boxed::Box;
        pub use char::CharExt;
        pub use clone::Clone;
        pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
        pub use iter::DoubleEndedIterator;
        pub use iter::ExactSizeIterator;
        pub use iter::{Iterator, IteratorExt, Extend};
        pub use option::Option::{self, Some, None};
        pub use ptr::{PtrExt, MutPtrExt};
        pub use result::Result::{self, Ok, Err};
        pub use slice::AsSlice;
        pub use slice::{SliceExt, SliceConcatExt};
        pub use str::{Str, StrExt};
        pub use string::{String, ToString};
        pub use vec::Vec;
        pub use iter::range;
    }
}

#[doc(hidden)]
mod std {
    pub use super::*;
}
<|endoftext|>


<commit_before>extern crate num;
extern crate glium;

pub mod vector;
pub mod matrix;

pub use vector::{
    Vec2,
    Vec3,
    Vec4,
};

pub use matrix::{
    Mat4,
};
<commit_msg>reexports<commit_after>extern crate num;
extern crate glium;

mod vector;
mod matrix;

pub use vector::{
    Vec2,
    Vec3,
    Vec4,
};

pub use matrix::{
    Mat4,
};

pub use vector::{
    Vector,
    Dot,
    Cross,
    Normalize,
    Length,
};

pub use matrix::{
    Translate,
    Rotate,
    Transpose,
    Inverse,
    Scale,
    LookAt,
    Projection,
    Matrix,
};
<|endoftext|>


<commit_before><commit_msg>remove lib.rs<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2016 glium_sdl2 developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! An SDL2 backend for [Glium](https://github.com/tomaka/glium) - a high-level
//! OpenGL wrapper for the Rust language.
//!
//! # Example
//! ```no_run
//! # #[macro_use] extern crate glium;
//! # extern crate glium_sdl2;
//! # extern crate sdl2;
//! # fn main() {
//! use glium_sdl2::DisplayBuild;
//!
//! let sdl_context = sdl2::init().unwrap();
//! let video_subsystem = sdl_context.video().unwrap();
//!
//! let display = video_subsystem.window("My window", 800, 600)
//!     .resizable()
//!     .build_glium()
//!     .unwrap();
//!
//! let mut running = true;
//! let mut event_pump = sdl_context.event_pump().unwrap();
//!
//! while running {
//!     let mut target = display.draw();
//!     // do drawing here...
//!     target.finish().unwrap();
//!
//!     // Event loop: includes all windows
//!
//!     for event in event_pump.poll_iter() {
//!         use sdl2::event::Event;
//!
//!         match event {
//!             Event::Quit { .. } => {
//!                 running = false;
//!             },
//!             _ => ()
//!         }
//!     }
//! }
//! # }
//! ```

extern crate glium;
extern crate sdl2;

use std::mem;
use std::cell::UnsafeCell;
use std::ops::Deref;
use std::rc::Rc;
use std::os::raw::c_void;
use std::error::Error;

use glium::SwapBuffersError;
use glium::debug;
use glium::backend::{Backend, Context, Facade};
use sdl2::VideoSubsystem;
use sdl2::video::{Window, WindowRef, WindowBuildError};

pub type Display = SDL2Facade;

#[derive(Debug)]
pub enum GliumSdl2Error {
    WindowBuildError(WindowBuildError),
    ContextCreationError(String)
}

impl From<String> for GliumSdl2Error {
    fn from(s : String) -> GliumSdl2Error {
        return GliumSdl2Error::ContextCreationError(s);
    }
}

impl From<WindowBuildError> for GliumSdl2Error {
    fn from(err : WindowBuildError) -> GliumSdl2Error {
        return GliumSdl2Error::WindowBuildError(err);
    }
}

impl std::error::Error for GliumSdl2Error {
    fn description(&self) -> &str {
        return match *self {
            GliumSdl2Error::WindowBuildError(ref err) => err.description(),
            GliumSdl2Error::ContextCreationError(ref s) => s
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        match *self {
            GliumSdl2Error::WindowBuildError(ref err) => err.cause(),
            GliumSdl2Error::ContextCreationError(_) => None
        }
    }
}

impl std::fmt::Display for GliumSdl2Error {
    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        formatter.write_str(self.to_string().as_str())
    }
}

/// Facade implementation for an SDL2 window.
#[derive(Clone)]
pub struct SDL2Facade {
    // contains everything related to the current context and its state
    context: Rc<Context>,

    backend: Rc<SDL2WindowBackend>,
}

impl Facade for SDL2Facade {
    fn get_context(&self) -> &Rc<Context> { &self.context }
}

impl Deref for SDL2Facade {
    type Target = Context;

    fn deref(&self) -> &Context { &self.context }
}

impl SDL2Facade {
    pub fn window(&self) -> &WindowRef {
        self.backend.window()
    }

    pub fn window_mut(&mut self) -> &mut WindowRef {
        self.backend.window_mut()
    }

    /// Start drawing on the backbuffer.
    ///
    /// This function returns a `Frame`, which can be used to draw on it.
    /// When the `Frame` is destroyed, the buffers are swapped.
    ///
    /// Note that destroying a `Frame` is immediate, even if vsync is enabled.
    pub fn draw(&self) -> glium::Frame {
        glium::Frame::new(self.context.clone(), self.backend.get_framebuffer_dimensions())
    }
}

/// An object that can build a facade object.
///
/// This trait is different from `glium::DisplayBuild` because Rust doesn't allow trait
/// implementations on types from external crates, unless the trait is in the same crate as the impl.
/// To clarify, both `glium::DisplayBuild` and `sdl2::video::WindowBuilder` are in different crates
/// than `glium_sdl2`.
pub trait DisplayBuild {
    /// The object that this `DisplayBuild` builds.
    type Facade: glium::backend::Facade;

    /// The type of error that initialization can return.
    type Err;

    /// Build a context and a facade to draw on it.
    ///
    /// Performs a compatibility check to make sure that all core elements of glium
    /// are supported by the implementation.
    fn build_glium(self) -> Result<Self::Facade, Self::Err> where Self: Sized {
        self.build_glium_debug(Default::default())
    }

    /// Build a context and a facade to draw on it.
    ///
    /// Performs a compatibility check to make sure that all core elements of glium
    /// are supported by the implementation.
    fn build_glium_debug(self, debug::DebugCallbackBehavior) -> Result<Self::Facade, Self::Err>;

    /// Build a context and a facade to draw on it
    ///
    /// This function does the same as `build_glium`, except that the resulting context
    /// will assume that the current OpenGL context will never change.
    unsafe fn build_glium_unchecked(self) -> Result<Self::Facade, Self::Err> where Self: Sized {
        self.build_glium_unchecked_debug(Default::default())
    }

    /// Build a context and a facade to draw on it
    ///
    /// This function does the same as `build_glium`, except that the resulting context
    /// will assume that the current OpenGL context will never change.
    unsafe fn build_glium_unchecked_debug(self, debug::DebugCallbackBehavior)
                                          -> Result<Self::Facade, Self::Err>;

    // TODO
    // Changes the settings of an existing facade.
    // fn rebuild_glium(self, &Self::Facade) -> Result<(), Self::Err>;
}

impl<'a> DisplayBuild for &'a mut sdl2::video::WindowBuilder {
    type Facade = SDL2Facade;
    type Err = glium::GliumCreationError<GliumSdl2Error>;

    fn build_glium_debug(self, debug: debug::DebugCallbackBehavior) -> Result<SDL2Facade, glium::GliumCreationError<GliumSdl2Error>> {
        let backend = Rc::new(try!(SDL2WindowBackend::new(self)));
        let context = try!(unsafe { Context::new(backend.clone(), true, debug) });

        let display = SDL2Facade {
            context: context,
            backend: backend
        };

        Ok(display)
    }

    unsafe fn build_glium_unchecked_debug(self, debug: debug::DebugCallbackBehavior) -> Result<SDL2Facade, glium::GliumCreationError<GliumSdl2Error>> {
        let backend = Rc::new(try!(SDL2WindowBackend::new(self)));
        let context = try!(Context::new(backend.clone(), false, debug));

        let display = SDL2Facade {
            context: context,
            backend: backend
        };

        Ok(display)
    }
}

pub struct SDL2WindowBackend {
    window: UnsafeCell<sdl2::video::Window>,
    context: sdl2::video::GLContext
}

impl SDL2WindowBackend {
    fn subsystem(&self) -> &VideoSubsystem {
        let ptr = self.window.get();
        let window: &Window = unsafe { mem::transmute(ptr) };
        window.subsystem()
    }

    fn window(&self) -> &WindowRef {
        let ptr = self.window.get();
        let window: &Window = unsafe { mem::transmute(ptr) };
        window
    }

    fn window_mut(&self) -> &mut WindowRef {
        let ptr = self.window.get();
        let window: &mut Window = unsafe { mem::transmute(ptr) };
        window
    }

    pub fn new(window_builder: &mut sdl2::video::WindowBuilder) -> Result<SDL2WindowBackend, GliumSdl2Error> {
        let window = try!(window_builder.opengl().build());
        let context = try!(window.gl_create_context());

        Ok(SDL2WindowBackend {
            window: UnsafeCell::new(window),
            context: context
        })
    }
}

unsafe impl Backend for SDL2WindowBackend {
    fn swap_buffers(&self) -> Result<(), SwapBuffersError> {
        self.window().gl_swap_window();

        // AFAIK, SDL or `SDL_GL_SwapWindow` doesn't have any way to detect context loss.
        // TODO: Find out if context loss is an issue in SDL2 (especially for the Android port).

        Ok(())
    }

    unsafe fn get_proc_address(&self, symbol: &str) -> *const c_void {
        // Assumes the appropriate context for the window has been set before this call.

        self.subsystem().gl_get_proc_address(symbol) as *const c_void
    }

    fn get_framebuffer_dimensions(&self) -> (u32, u32) {
        let (width, height) = self.window().drawable_size();
        (width as u32, height as u32)
    }

    fn is_current(&self) -> bool {
        self.context.is_current()
    }

    unsafe fn make_current(&self) {
        self.window().gl_make_current(&self.context).unwrap()
    }
}
<commit_msg>fix warning message for unused import<commit_after>// Copyright (c) 2016 glium_sdl2 developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! An SDL2 backend for [Glium](https://github.com/tomaka/glium) - a high-level
//! OpenGL wrapper for the Rust language.
//!
//! # Example
//! ```no_run
//! # #[macro_use] extern crate glium;
//! # extern crate glium_sdl2;
//! # extern crate sdl2;
//! # fn main() {
//! use glium_sdl2::DisplayBuild;
//!
//! let sdl_context = sdl2::init().unwrap();
//! let video_subsystem = sdl_context.video().unwrap();
//!
//! let display = video_subsystem.window("My window", 800, 600)
//!     .resizable()
//!     .build_glium()
//!     .unwrap();
//!
//! let mut running = true;
//! let mut event_pump = sdl_context.event_pump().unwrap();
//!
//! while running {
//!     let mut target = display.draw();
//!     // do drawing here...
//!     target.finish().unwrap();
//!
//!     // Event loop: includes all windows
//!
//!     for event in event_pump.poll_iter() {
//!         use sdl2::event::Event;
//!
//!         match event {
//!             Event::Quit { .. } => {
//!                 running = false;
//!             },
//!             _ => ()
//!         }
//!     }
//! }
//! # }
//! ```

extern crate glium;
extern crate sdl2;

use std::mem;
use std::cell::UnsafeCell;
use std::ops::Deref;
use std::rc::Rc;
use std::os::raw::c_void;

use glium::SwapBuffersError;
use glium::debug;
use glium::backend::{Backend, Context, Facade};
use sdl2::VideoSubsystem;
use sdl2::video::{Window, WindowRef, WindowBuildError};

pub type Display = SDL2Facade;

#[derive(Debug)]
pub enum GliumSdl2Error {
    WindowBuildError(WindowBuildError),
    ContextCreationError(String)
}

impl From<String> for GliumSdl2Error {
    fn from(s : String) -> GliumSdl2Error {
        return GliumSdl2Error::ContextCreationError(s);
    }
}

impl From<WindowBuildError> for GliumSdl2Error {
    fn from(err : WindowBuildError) -> GliumSdl2Error {
        return GliumSdl2Error::WindowBuildError(err);
    }
}

impl std::error::Error for GliumSdl2Error {
    fn description(&self) -> &str {
        return match *self {
            GliumSdl2Error::WindowBuildError(ref err) => err.description(),
            GliumSdl2Error::ContextCreationError(ref s) => s
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        match *self {
            GliumSdl2Error::WindowBuildError(ref err) => err.cause(),
            GliumSdl2Error::ContextCreationError(_) => None
        }
    }
}

impl std::fmt::Display for GliumSdl2Error {
    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        formatter.write_str(self.to_string().as_str())
    }
}

/// Facade implementation for an SDL2 window.
#[derive(Clone)]
pub struct SDL2Facade {
    // contains everything related to the current context and its state
    context: Rc<Context>,

    backend: Rc<SDL2WindowBackend>,
}

impl Facade for SDL2Facade {
    fn get_context(&self) -> &Rc<Context> { &self.context }
}

impl Deref for SDL2Facade {
    type Target = Context;

    fn deref(&self) -> &Context { &self.context }
}

impl SDL2Facade {
    pub fn window(&self) -> &WindowRef {
        self.backend.window()
    }

    pub fn window_mut(&mut self) -> &mut WindowRef {
        self.backend.window_mut()
    }

    /// Start drawing on the backbuffer.
    ///
    /// This function returns a `Frame`, which can be used to draw on it.
    /// When the `Frame` is destroyed, the buffers are swapped.
    ///
    /// Note that destroying a `Frame` is immediate, even if vsync is enabled.
    pub fn draw(&self) -> glium::Frame {
        glium::Frame::new(self.context.clone(), self.backend.get_framebuffer_dimensions())
    }
}

/// An object that can build a facade object.
///
/// This trait is different from `glium::DisplayBuild` because Rust doesn't allow trait
/// implementations on types from external crates, unless the trait is in the same crate as the impl.
/// To clarify, both `glium::DisplayBuild` and `sdl2::video::WindowBuilder` are in different crates
/// than `glium_sdl2`.
pub trait DisplayBuild {
    /// The object that this `DisplayBuild` builds.
    type Facade: glium::backend::Facade;

    /// The type of error that initialization can return.
    type Err;

    /// Build a context and a facade to draw on it.
    ///
    /// Performs a compatibility check to make sure that all core elements of glium
    /// are supported by the implementation.
    fn build_glium(self) -> Result<Self::Facade, Self::Err> where Self: Sized {
        self.build_glium_debug(Default::default())
    }

    /// Build a context and a facade to draw on it.
    ///
    /// Performs a compatibility check to make sure that all core elements of glium
    /// are supported by the implementation.
    fn build_glium_debug(self, debug::DebugCallbackBehavior) -> Result<Self::Facade, Self::Err>;

    /// Build a context and a facade to draw on it
    ///
    /// This function does the same as `build_glium`, except that the resulting context
    /// will assume that the current OpenGL context will never change.
    unsafe fn build_glium_unchecked(self) -> Result<Self::Facade, Self::Err> where Self: Sized {
        self.build_glium_unchecked_debug(Default::default())
    }

    /// Build a context and a facade to draw on it
    ///
    /// This function does the same as `build_glium`, except that the resulting context
    /// will assume that the current OpenGL context will never change.
    unsafe fn build_glium_unchecked_debug(self, debug::DebugCallbackBehavior)
                                          -> Result<Self::Facade, Self::Err>;

    // TODO
    // Changes the settings of an existing facade.
    // fn rebuild_glium(self, &Self::Facade) -> Result<(), Self::Err>;
}

impl<'a> DisplayBuild for &'a mut sdl2::video::WindowBuilder {
    type Facade = SDL2Facade;
    type Err = glium::GliumCreationError<GliumSdl2Error>;

    fn build_glium_debug(self, debug: debug::DebugCallbackBehavior) -> Result<SDL2Facade, glium::GliumCreationError<GliumSdl2Error>> {
        let backend = Rc::new(try!(SDL2WindowBackend::new(self)));
        let context = try!(unsafe { Context::new(backend.clone(), true, debug) });

        let display = SDL2Facade {
            context: context,
            backend: backend
        };

        Ok(display)
    }

    unsafe fn build_glium_unchecked_debug(self, debug: debug::DebugCallbackBehavior) -> Result<SDL2Facade, glium::GliumCreationError<GliumSdl2Error>> {
        let backend = Rc::new(try!(SDL2WindowBackend::new(self)));
        let context = try!(Context::new(backend.clone(), false, debug));

        let display = SDL2Facade {
            context: context,
            backend: backend
        };

        Ok(display)
    }
}

pub struct SDL2WindowBackend {
    window: UnsafeCell<sdl2::video::Window>,
    context: sdl2::video::GLContext
}

impl SDL2WindowBackend {
    fn subsystem(&self) -> &VideoSubsystem {
        let ptr = self.window.get();
        let window: &Window = unsafe { mem::transmute(ptr) };
        window.subsystem()
    }

    fn window(&self) -> &WindowRef {
        let ptr = self.window.get();
        let window: &Window = unsafe { mem::transmute(ptr) };
        window
    }

    fn window_mut(&self) -> &mut WindowRef {
        let ptr = self.window.get();
        let window: &mut Window = unsafe { mem::transmute(ptr) };
        window
    }

    pub fn new(window_builder: &mut sdl2::video::WindowBuilder) -> Result<SDL2WindowBackend, GliumSdl2Error> {
        let window = try!(window_builder.opengl().build());
        let context = try!(window.gl_create_context());

        Ok(SDL2WindowBackend {
            window: UnsafeCell::new(window),
            context: context
        })
    }
}

unsafe impl Backend for SDL2WindowBackend {
    fn swap_buffers(&self) -> Result<(), SwapBuffersError> {
        self.window().gl_swap_window();

        // AFAIK, SDL or `SDL_GL_SwapWindow` doesn't have any way to detect context loss.
        // TODO: Find out if context loss is an issue in SDL2 (especially for the Android port).

        Ok(())
    }

    unsafe fn get_proc_address(&self, symbol: &str) -> *const c_void {
        // Assumes the appropriate context for the window has been set before this call.

        self.subsystem().gl_get_proc_address(symbol) as *const c_void
    }

    fn get_framebuffer_dimensions(&self) -> (u32, u32) {
        let (width, height) = self.window().drawable_size();
        (width as u32, height as u32)
    }

    fn is_current(&self) -> bool {
        self.context.is_current()
    }

    unsafe fn make_current(&self) {
        self.window().gl_make_current(&self.context).unwrap()
    }
}
<|endoftext|>


<commit_before>extern crate base64;
extern crate envy;
extern crate futures;
extern crate hyper;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate log4rs;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate tokio_core;

pub mod config;
pub mod http;
pub mod logging;

mod ctapi;

#[no_mangle]
#[allow(non_snake_case)]
pub extern "system" fn CT_init(ctn: u16, pn: u16) -> i8 {
    logging::init();

    debug!("CT_init(ctn: {}, pn: {})", ctn, pn);

    ctapi::init(config::ctn_or(ctn), config::pn_or(pn))
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern "system" fn CT_data(
    ctn: u16,
    dad: *mut u8,
    sad: *mut u8,
    lenc: u16,
    command: *const u8,
    lenr: *mut u16,
    response: *mut u8,
) -> i8 {
    logging::init();

    debug!("CT_data(ctn: {})", ctn);

    ctapi::data(config::ctn_or(ctn), dad, sad, lenc, command, lenr, response)
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern "system" fn CT_close(ctn: u16) -> i8 {
    logging::init();

    debug!("CT_close(ctn: {})", ctn);

    ctapi::close(config::ctn_or(ctn))
}
<commit_msg>convert StatusCode into i8 for pub functions<commit_after>extern crate base64;
extern crate envy;
extern crate futures;
extern crate hyper;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate log4rs;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate tokio_core;

mod config;
mod ctapi;
mod http;
mod logging;

#[no_mangle]
#[allow(non_snake_case)]
pub extern "system" fn CT_init(ctn: u16, pn: u16) -> i8 {
    logging::init();

    debug!("CT_init(ctn: {}, pn: {})", ctn, pn);
    let status = ctapi::init(config::ctn_or(ctn), config::pn_or(pn));

    debug!("Returning {}", status);
    status.to_i8()
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern "system" fn CT_data(
    ctn: u16,
    dad: *mut u8,
    sad: *mut u8,
    lenc: u16,
    command: *const u8,
    lenr: *mut u16,
    response: *mut u8,
) -> i8 {
    logging::init();

    debug!("CT_data(ctn: {})", ctn);
    let status = ctapi::data(config::ctn_or(ctn), dad, sad, lenc, command, lenr, response);

    debug!("Returning {}", status);
    status.to_i8()
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern "system" fn CT_close(ctn: u16) -> i8 {
    logging::init();

    debug!("CT_close(ctn: {})", ctn);
    let status = ctapi::close(config::ctn_or(ctn));

    debug!("Returning {}", status);
    status.to_i8()
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::fmt;

#[derive(Clone, PartialEq, Eq)]
pub enum Token {
    Output,
    Input,
    Loop(Vec<Token>),
    Move(i32),
    Add(i32, i32),
    Set(i32, i32),
    MulCopy(i32, i32, i32),
    Scan(i32),
    LoadOut(i32, i32),
    LoadOutSet(i32),
    If(i32, Vec<Token>),
}
use Token::*;

impl fmt::Debug for Token {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Output => write!(f, "Output"),
            Input => write!(f, "Input"),
            Move(offset) => write!(f, "Move(offset={})", offset),
            Add(offset, value) => write!(f, "Add(offset={}, value={})", offset, value),
            Set(offset, value) => write!(f, "Set(offset={}, value={})", offset, value),
            MulCopy(src, dest, mul) => {
                write!(f, "MulCopy(src={}, dest={}, mul={})", src, dest, mul)
            }
            Scan(offset) => write!(f, "Scan(offset={})", offset),
            LoadOut(offset, add) => write!(f, "LoadOut(offset={}, add={})", offset, add),
            LoadOutSet(value) => write!(f, "LoadOutSet(value={})", value),
            Loop(ref content) => write!(f, "Loop(content={:?})", content),
            If(offset, ref content) => write!(f, "If(offset={}, content={:?})", offset, content),
        }
    }
}

pub fn parse(code: &str) -> Vec<Token> {
    _parse(&mut code.chars())
}

fn _parse(chars: &mut std::str::Chars) -> Vec<Token> {
    let mut tokens = Vec::new();
    while let Some(i) = chars.next() {
        match i {
            '+' => tokens.push(Add(0, 1)),
            '-' => tokens.push(Add(0, -1)),
            '>' => tokens.push(Move(1)),
            '<' => tokens.push(Move(-1)),
            '[' => tokens.push(Loop(_parse(chars))),
            ']' => {
                break;
            }
            ',' => tokens.push(Input),
            '.' => {
                tokens.push(LoadOut(0, 0));
                tokens.push(Output);
            }
            _ => (),
        };
    }

    tokens
}

fn _optimize(tokens: &Vec<Token>) -> (Vec<Token>, BTreeMap<i32, i32>, BTreeMap<i32, i32>, i32) {
    let mut newtokens: Vec<Token> = Vec::with_capacity(tokens.len());
    let mut shift = 0;
    let mut do_output = false;
    // With HashMap, the order sometimes switches
    // in recursion, and the optimizer never exits.
    let mut adds: BTreeMap<i32, i32> = BTreeMap::new();
    let mut sets: BTreeMap<i32, i32> = BTreeMap::new();

    for token in tokens.iter() {
        match *token {
            Set(..) | Add(..) | Move(_) | LoadOut(..) | LoadOutSet(_) | Output => {}
            _ => {
                if do_output {
                    newtokens.push(Output);
                    do_output = false;
                }

                for (offset, value) in sets.iter() {
                    newtokens.push(Set(*offset, *value));
                }
                for (offset, value) in adds.iter() {
                    newtokens.push(Add(*offset, *value));
                }
                sets.clear();
                adds.clear();
            }
        }

        if shift != 0 {
            match *token {
                Loop(_) | Input | Scan(_) => {
                    newtokens.push(Move(shift));
                    shift = 0;
                }
                _ => {}
            }
        }

        match *token {
            Set(mut offset, val) => {
                offset += shift;
                // Add before Set does nothing; remove it
                adds.remove(&offset);
                sets.insert(offset, val);
            }
            Add(mut offset, mut val) => {
                offset += shift;
                if sets.contains_key(&offset) {
                    val = sets.get(&offset).unwrap() + val;
                    sets.insert(offset, val);
                } else {
                    val = adds.get(&offset).unwrap_or(&0) + val;
                    adds.insert(offset, val);
                }
            }
            MulCopy(src, dest, mul) => newtokens.push(MulCopy(src + shift, dest + shift, mul)),
            // XXX Deal with shift in if, if those are ever generated
            // TODO Optimize inside of If?
            If(offset, ref contents) => newtokens.push(If(offset + shift, contents.clone())),
            Move(offset) => shift += offset,
            Output => do_output = true,
            LoadOut(mut offset, add) => {
                offset += shift;
                if sets.contains_key(&offset) {
                    newtokens.push(LoadOutSet(sets.get(&offset).unwrap() + add));
                } else {
                    newtokens.push(LoadOut(offset, adds.get(&offset).unwrap_or(&0) + add));
                }
            }
            Loop(ref contents) => newtokens.push(_optimize_loop(contents)),
            LoadOutSet(value) => newtokens.push(LoadOutSet(value)),
            Input => newtokens.push(Input),
            Scan(offset) => newtokens.push(Scan(offset + shift)),
        }
    }

    if do_output {
        newtokens.push(Output);
    }

    (newtokens, sets, adds, shift)
}

fn _optimize_loop(tokens: &Vec<Token>) -> Token {
    let (mut newtokens, sets, adds, shift) = _optimize(tokens);

    if shift != 0 && sets.is_empty() && adds.is_empty() && newtokens.is_empty() {
        Scan(shift)
    }
    else {
        for (offset, value) in sets.iter() {
            newtokens.push(Set(*offset, *value));
        }
        for (offset, value) in adds.iter() {
            newtokens.push(Add(*offset, *value));
        }
        if shift != 0 {
            newtokens.push(Move(shift));
        }

        Loop(newtokens)
    }
}

pub fn optimize(tokens: Vec<Token>) -> Vec<Token> {
    let mut oldtokens = tokens;
    // Ignore sets/adds/shifts at end of file
    let mut newtokens = _optimize(&oldtokens).0;
    while newtokens != oldtokens {
        oldtokens = newtokens;
        newtokens = _optimize(&oldtokens).0;
    }
    newtokens
}
<commit_msg>Basic implementation of "Set" optimization<commit_after>use std::collections::BTreeMap;
use std::fmt;

#[derive(Clone, PartialEq, Eq)]
pub enum Token {
    Output,
    Input,
    Loop(Vec<Token>),
    Move(i32),
    Add(i32, i32),
    Set(i32, i32),
    MulCopy(i32, i32, i32),
    Scan(i32),
    LoadOut(i32, i32),
    LoadOutSet(i32),
    If(i32, Vec<Token>),
}
use Token::*;

impl fmt::Debug for Token {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Output => write!(f, "Output"),
            Input => write!(f, "Input"),
            Move(offset) => write!(f, "Move(offset={})", offset),
            Add(offset, value) => write!(f, "Add(offset={}, value={})", offset, value),
            Set(offset, value) => write!(f, "Set(offset={}, value={})", offset, value),
            MulCopy(src, dest, mul) => {
                write!(f, "MulCopy(src={}, dest={}, mul={})", src, dest, mul)
            }
            Scan(offset) => write!(f, "Scan(offset={})", offset),
            LoadOut(offset, add) => write!(f, "LoadOut(offset={}, add={})", offset, add),
            LoadOutSet(value) => write!(f, "LoadOutSet(value={})", value),
            Loop(ref content) => write!(f, "Loop(content={:?})", content),
            If(offset, ref content) => write!(f, "If(offset={}, content={:?})", offset, content),
        }
    }
}

pub fn parse(code: &str) -> Vec<Token> {
    _parse(&mut code.chars())
}

fn _parse(chars: &mut std::str::Chars) -> Vec<Token> {
    let mut tokens = Vec::new();
    while let Some(i) = chars.next() {
        match i {
            '+' => tokens.push(Add(0, 1)),
            '-' => tokens.push(Add(0, -1)),
            '>' => tokens.push(Move(1)),
            '<' => tokens.push(Move(-1)),
            '[' => tokens.push(Loop(_parse(chars))),
            ']' => {
                break;
            }
            ',' => tokens.push(Input),
            '.' => {
                tokens.push(LoadOut(0, 0));
                tokens.push(Output);
            }
            _ => (),
        };
    }

    tokens
}

fn _optimize(tokens: &Vec<Token>) -> (Vec<Token>, BTreeMap<i32, i32>, BTreeMap<i32, i32>, i32) {
    let mut newtokens: Vec<Token> = Vec::with_capacity(tokens.len());
    let mut shift = 0;
    let mut do_output = false;
    // With HashMap, the order sometimes switches
    // in recursion, and the optimizer never exits.
    let mut adds: BTreeMap<i32, i32> = BTreeMap::new();
    let mut sets: BTreeMap<i32, i32> = BTreeMap::new();

    for token in tokens.iter() {
        match *token {
            Set(..) | Add(..) | Move(_) | LoadOut(..) | LoadOutSet(_) | Output => {}
            _ => {
                if do_output {
                    newtokens.push(Output);
                    do_output = false;
                }

                for (offset, value) in sets.iter() {
                    newtokens.push(Set(*offset, *value));
                }
                for (offset, value) in adds.iter() {
                    newtokens.push(Add(*offset, *value));
                }
                sets.clear();
                adds.clear();
            }
        }

        if shift != 0 {
            match *token {
                Loop(_) | Input | Scan(_) => {
                    newtokens.push(Move(shift));
                    shift = 0;
                }
                _ => {}
            }
        }

        match *token {
            Set(mut offset, val) => {
                offset += shift;
                // Add before Set does nothing; remove it
                adds.remove(&offset);
                sets.insert(offset, val);
            }
            Add(mut offset, mut val) => {
                offset += shift;
                if sets.contains_key(&offset) {
                    val = sets.get(&offset).unwrap() + val;
                    sets.insert(offset, val);
                } else {
                    val = adds.get(&offset).unwrap_or(&0) + val;
                    adds.insert(offset, val);
                }
            }
            MulCopy(src, dest, mul) => newtokens.push(MulCopy(src + shift, dest + shift, mul)),
            // XXX Deal with shift in if, if those are ever generated
            // TODO Optimize inside of If?
            If(offset, ref contents) => newtokens.push(If(offset + shift, contents.clone())),
            Move(offset) => shift += offset,
            Output => do_output = true,
            LoadOut(mut offset, add) => {
                offset += shift;
                if sets.contains_key(&offset) {
                    newtokens.push(LoadOutSet(sets.get(&offset).unwrap() + add));
                } else {
                    newtokens.push(LoadOut(offset, adds.get(&offset).unwrap_or(&0) + add));
                }
            }
            Loop(ref contents) => {
                if let Some(token) =_optimize_loop(contents, &mut sets, &mut adds, &mut shift) {
                    newtokens.push(token);
                }
            },
            LoadOutSet(value) => newtokens.push(LoadOutSet(value)),
            Input => newtokens.push(Input),
            Scan(offset) => newtokens.push(Scan(offset + shift)),
        }
    }

    if do_output {
        newtokens.push(Output);
    }

    (newtokens, sets, adds, shift)
}

fn _optimize_loop(tokens: &Vec<Token>, outer_sets: &mut BTreeMap<i32, i32>, outer_adds: &mut BTreeMap<i32, i32>, outer_shift: &mut i32) -> Option<Token> {
    let (mut newtokens, sets, adds, shift) = _optimize(tokens);

    if shift != 0 && sets.is_empty() && adds.is_empty() && newtokens.is_empty() {
        Some(Scan(shift))
    }
    else if shift == 0 && newtokens.is_empty() && adds.contains_key(&0) && adds.len() == 1 && sets.is_empty() {
        // TODO: Implement when !sets.is_empty()
        outer_sets.insert(0, 0);

        None
    }
    else {
        for (offset, value) in sets.iter() {
            newtokens.push(Set(*offset, *value));
        }
        for (offset, value) in adds.iter() {
            newtokens.push(Add(*offset, *value));
        }
        if shift != 0 {
            newtokens.push(Move(shift));
        }

        Some(Loop(newtokens))
    }
}

pub fn optimize(tokens: Vec<Token>) -> Vec<Token> {
    let mut oldtokens = tokens;
    // Ignore sets/adds/shifts at end of file
    let mut newtokens = _optimize(&oldtokens).0;
    while newtokens != oldtokens {
        oldtokens = newtokens;
        newtokens = _optimize(&oldtokens).0;
    }
    newtokens
}
<|endoftext|>


<commit_before>#![feature(io, core, std_misc)]

extern crate conduit;
extern crate flate2;

use std::ascii::AsciiExt;
use std::collections::hash_map::{HashMap, Entry};
use std::error::Error;
use std::old_io::{Process, Command, IoResult, BufferedReader, util};

use conduit::{Request, Response};
use flate2::reader::GzDecoder;

pub struct Serve(pub Path);

impl Serve {
    fn doit(&self, req: &mut Request) -> IoResult<Response> {
        let mut cmd = Command::new("git");
        cmd.arg("http-backend");

        // Required environment variables
        cmd.env("REQUEST_METHOD",
                format!("{:?}", req.method()).as_slice().to_ascii_uppercase());
        cmd.env("GIT_PROJECT_ROOT", &self.0);
        cmd.env("PATH_INFO", req.path());
        cmd.env("REMOTE_USER", "");
        cmd.env("REMOTE_ADDR", req.remote_ip().to_string());
        cmd.env("QUERY_STRING", req.query_string().unwrap_or(""));
        cmd.env("CONTENT_TYPE", header(req, "Content-Type"));
        cmd.stderr(::std::old_io::process::InheritFd(2));
        let mut p = try!(cmd.spawn());

        // Pass in the body of the request (if any)
        //
        // As part of the CGI interface we're required to take care of gzip'd
        // requests. I'm not totally sure that this sequential copy is the best
        // thing to do or actually correct...
        if header(req, "Content-Encoding") == "gzip" {
            let mut body = GzDecoder::new(req.body());
            try!(util::copy(&mut body, &mut p.stdin.take().unwrap()));
        } else {
            try!(util::copy(&mut req.body(), &mut p.stdin.take().unwrap()));
        }

        // Parse the headers coming out, and the pass through the rest of the
        // process back down the stack.
        //
        // Note that we have to be careful to not drop the process which will wait
        // for the process to exit (and we haven't read stdout)
        let mut rdr = BufferedReader::new(p.stdout.take().unwrap());

        let mut headers = HashMap::new();
        for line in rdr.lines() {
            let line = try!(line);
            if line.as_slice() == "\r\n" { break }

            let mut parts = line.as_slice().splitn(2, ':');
            let key = parts.next().unwrap();
            let value = parts.next().unwrap();
            let value = &value[1 .. value.len() - 2];
            match headers.entry(key.to_string()) {
                Entry::Occupied(e) => e.into_mut(),
                Entry::Vacant(e) => e.insert(Vec::new()),
            }.push(value.to_string());
        }

        let (status_code, status_desc) = {
            let line = headers.remove("Status").unwrap_or(Vec::new());
            let line = line.into_iter().next().unwrap_or(String::new());
            let mut parts = line.as_slice().splitn(1, ' ');
            (parts.next().unwrap_or("").parse().unwrap_or(200),
             match parts.next() {
                 Some("Not Found") => "Not Found",
                 _ => "Ok",
             })
        };

        struct ProcessAndBuffer<R> { _p: Process, buf: BufferedReader<R> }
        impl<R: Reader> Reader for ProcessAndBuffer<R> {
            fn read(&mut self, b: &mut [u8]) -> IoResult<usize> { self.buf.read(b) }
        }
        return Ok(Response {
            status: (status_code, status_desc),
            headers: headers,
            body: Box::new(ProcessAndBuffer { _p: p, buf: rdr }),
        });

        fn header<'a>(req: &'a Request, name: &str) -> &'a str {
            let h = req.headers().find(name).unwrap_or(Vec::new());
            h.as_slice().get(0).map(|s| *s).unwrap_or("")
        }
    }
}

impl conduit::Handler for Serve {
    fn call(&self, req: &mut Request) -> Result<Response, Box<Error+Send>> {
        self.doit(req).map_err(|e| Box::new(e) as Box<Error+Send>)
    }
}
<commit_msg>Update to rust master<commit_after>#![feature(old_io, core, std_misc, old_path)]
#![cfg_attr(test, deny(warnings))]

extern crate conduit;
extern crate flate2;

use std::ascii::AsciiExt;
use std::collections::hash_map::{HashMap, Entry};
use std::error::Error;
use std::old_io::{Process, Command, IoResult, BufferedReader, util};

use conduit::{Request, Response};
use flate2::reader::GzDecoder;

pub struct Serve(pub Path);

impl Serve {
    fn doit(&self, req: &mut Request) -> IoResult<Response> {
        let mut cmd = Command::new("git");
        cmd.arg("http-backend");

        // Required environment variables
        cmd.env("REQUEST_METHOD",
                format!("{:?}", req.method()).as_slice().to_ascii_uppercase());
        cmd.env("GIT_PROJECT_ROOT", &self.0);
        cmd.env("PATH_INFO", req.path());
        cmd.env("REMOTE_USER", "");
        cmd.env("REMOTE_ADDR", req.remote_ip().to_string());
        cmd.env("QUERY_STRING", req.query_string().unwrap_or(""));
        cmd.env("CONTENT_TYPE", header(req, "Content-Type"));
        cmd.stderr(::std::old_io::process::InheritFd(2));
        let mut p = try!(cmd.spawn());

        // Pass in the body of the request (if any)
        //
        // As part of the CGI interface we're required to take care of gzip'd
        // requests. I'm not totally sure that this sequential copy is the best
        // thing to do or actually correct...
        if header(req, "Content-Encoding") == "gzip" {
            let mut body = GzDecoder::new(req.body());
            try!(util::copy(&mut body, &mut p.stdin.take().unwrap()));
        } else {
            try!(util::copy(&mut req.body(), &mut p.stdin.take().unwrap()));
        }

        // Parse the headers coming out, and the pass through the rest of the
        // process back down the stack.
        //
        // Note that we have to be careful to not drop the process which will wait
        // for the process to exit (and we haven't read stdout)
        let mut rdr = BufferedReader::new(p.stdout.take().unwrap());

        let mut headers = HashMap::new();
        for line in rdr.lines() {
            let line = try!(line);
            if line.as_slice() == "\r\n" { break }

            let mut parts = line.as_slice().splitn(2, ':');
            let key = parts.next().unwrap();
            let value = parts.next().unwrap();
            let value = &value[1 .. value.len() - 2];
            match headers.entry(key.to_string()) {
                Entry::Occupied(e) => e.into_mut(),
                Entry::Vacant(e) => e.insert(Vec::new()),
            }.push(value.to_string());
        }

        let (status_code, status_desc) = {
            let line = headers.remove("Status").unwrap_or(Vec::new());
            let line = line.into_iter().next().unwrap_or(String::new());
            let mut parts = line.as_slice().splitn(1, ' ');
            (parts.next().unwrap_or("").parse().unwrap_or(200),
             match parts.next() {
                 Some("Not Found") => "Not Found",
                 _ => "Ok",
             })
        };

        struct ProcessAndBuffer<R> { _p: Process, buf: BufferedReader<R> }
        impl<R: Reader> Reader for ProcessAndBuffer<R> {
            fn read(&mut self, b: &mut [u8]) -> IoResult<usize> { self.buf.read(b) }
        }
        return Ok(Response {
            status: (status_code, status_desc),
            headers: headers,
            body: Box::new(ProcessAndBuffer { _p: p, buf: rdr }),
        });

        fn header<'a>(req: &'a Request, name: &str) -> &'a str {
            let h = req.headers().find(name).unwrap_or(Vec::new());
            h.as_slice().get(0).map(|s| *s).unwrap_or("")
        }
    }
}

impl conduit::Handler for Serve {
    fn call(&self, req: &mut Request) -> Result<Response, Box<Error+Send>> {
        self.doit(req).map_err(|e| Box::new(e) as Box<Error+Send>)
    }
}
<|endoftext|>


<commit_before>//! This crate provides native rust implementations of
//! Image encoders and decoders and basic image manipulation
//! functions.

#![crate_name = "image"]
#![crate_type = "rlib"]

#![warn(missing_docs)]
#![warn(unused_qualifications)]
#![warn(unused_typecasts)]
#![warn(unused_features)] // reduce errors due to using test&rand features
#![deny(missing_copy_implementations)]
#![feature(core)]
#![feature(io)]
#![feature(path)]
#![feature(collections)]
#![feature(std_misc)]
#![feature(hash)]
#![feature(rustc_private)]
#![cfg_attr(test, feature(test))]

extern crate flate;
extern crate num;
#[cfg(test)] extern crate test;

pub use color::ColorType as ColorType;
pub use traits::Primitive;

pub use color::ColorType:: {
    Gray,
    RGB,
    Palette,
    GrayA,
    RGBA,
};
pub use color:: {
    Luma,
    LumaA,
    Rgb,
    Rgba,
};

pub use buffer::Pixel;

pub use image::ImageDecoder as ImageDecoder;
pub use image::ImageError as ImageError;
pub use image::ImageResult as ImageResult;
pub use image::ImageFormat as ImageFormat;
pub use imageops::FilterType as FilterType;

pub use imageops:: {
    Triangle,
    Nearest,
    CatmullRom,
    Gaussian,
    Lanczos3
};

pub use image::ImageFormat:: {
    PNG,
    JPEG,
    GIF,
    WEBP,
    PPM
};

// Image Types
pub use image::SubImage as SubImage;
pub use dynimage::DynamicImage as DynamicImage;
pub use buffer::{
    ImageBuffer,
    RgbImage,
    RgbaImage,
    GrayImage,
    GrayAlphaImage
};

// Traits
pub use image::GenericImage as GenericImage;

// Iterators
pub use image::Pixels as Pixels;
pub use image::MutPixels as MutPixels;

/// Opening and loading images
pub use dynimage:: {
    open,
    load,
    load_from_memory,
    load_from_memory_with_format,
    save_buffer,
};
pub use dynimage::DynamicImage:: {
    ImageRgb8,
    ImageRgba8,
    ImageLuma8,
    ImageLumaA8,
};

pub use animation:: {
    Frame, Frames
};

// Math utils
pub mod math;

// Image Processing Functions
pub mod imageops;

// Image Codecs
pub mod webp;
pub mod ppm;
pub mod png;
pub mod jpeg;
pub mod gif;
pub mod tiff;
pub mod tga;

mod image;
mod utils;
mod dynimage;
mod color;
mod buffer;
mod traits;
mod animation;
<commit_msg>Silence (most) warnings on build<commit_after>//! This crate provides native rust implementations of
//! Image encoders and decoders and basic image manipulation
//! functions.

#![crate_name = "image"]
#![crate_type = "rlib"]

#![warn(missing_docs)]
#![warn(unused_qualifications)]
#![warn(unused_typecasts)]
#![warn(unused_features)] // reduce errors due to using test&rand features
#![deny(missing_copy_implementations)]
#![feature(core)]
#![feature(io)]
#![feature(old_io, old_path)]
#![feature(collections)]
#![feature(std_misc)]
#![feature(rustc_private)]
#![cfg_attr(test, feature(test))]

extern crate flate;
extern crate num;
#[cfg(test)] extern crate test;

pub use color::ColorType as ColorType;
pub use traits::Primitive;

pub use color::ColorType:: {
    Gray,
    RGB,
    Palette,
    GrayA,
    RGBA,
};
pub use color:: {
    Luma,
    LumaA,
    Rgb,
    Rgba,
};

pub use buffer::Pixel;

pub use image::ImageDecoder as ImageDecoder;
pub use image::ImageError as ImageError;
pub use image::ImageResult as ImageResult;
pub use image::ImageFormat as ImageFormat;
pub use imageops::FilterType as FilterType;

pub use imageops:: {
    Triangle,
    Nearest,
    CatmullRom,
    Gaussian,
    Lanczos3
};

pub use image::ImageFormat:: {
    PNG,
    JPEG,
    GIF,
    WEBP,
    PPM
};

// Image Types
pub use image::SubImage as SubImage;
pub use dynimage::DynamicImage as DynamicImage;
pub use buffer::{
    ImageBuffer,
    RgbImage,
    RgbaImage,
    GrayImage,
    GrayAlphaImage
};

// Traits
pub use image::GenericImage as GenericImage;

// Iterators
pub use image::Pixels as Pixels;
pub use image::MutPixels as MutPixels;

/// Opening and loading images
pub use dynimage:: {
    open,
    load,
    load_from_memory,
    load_from_memory_with_format,
    save_buffer,
};
pub use dynimage::DynamicImage:: {
    ImageRgb8,
    ImageRgba8,
    ImageLuma8,
    ImageLumaA8,
};

pub use animation:: {
    Frame, Frames
};

// Math utils
pub mod math;

// Image Processing Functions
pub mod imageops;

// Image Codecs
pub mod webp;
pub mod ppm;
pub mod png;
pub mod jpeg;
pub mod gif;
pub mod tiff;
pub mod tga;

mod image;
mod utils;
mod dynimage;
mod color;
mod buffer;
mod traits;
mod animation;
<|endoftext|>


<commit_before>//! A crate with utilities to determine the number of CPUs available on the
//! current system.
//!
//! Sometimes the CPU will exaggerate the number of CPUs it contains, because it can use
//! [processor tricks] to deliver increased performance when there are more threads. This
//! crate provides methods to get both the logical and physical numbers of cores.
//!
//! This information can be used as a guide to how many tasks can be run in parallel.
//! There are many properties of the system architecture that will affect parallelism,
//! for example memory access speeds (for all the caches and RAM) and the physical
//! architecture of the processor, so the number of CPUs should be used as a rough guide
//! only.
//!
//!
//! ## Examples
//!
//! Fetch the number of logical CPUs.
//!
//! ```
//! let cpus = num_cpus::get();
//! ```
//!
//! See [`rayon::Threadpool`] for an example of where the number of CPUs could be
//! used when setting up parallel jobs (Where the threadpool example uses a fixed
//! number 8, it could use the number of CPUs).
//!
//! [processor tricks]: https://en.wikipedia.org/wiki/Simultaneous_multithreading
//! [`rayon::ThreadPool`]: https://docs.rs/rayon/1.*/rayon/struct.ThreadPool.html
#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]
#![doc(html_root_url = "https://docs.rs/num_cpus/1.13.0")]
#![allow(non_snake_case)]

#[cfg(not(windows))]
extern crate libc;

#[cfg(target_os = "hermit")]
extern crate hermit_abi;

#[cfg(target_os = "linux")]
mod linux;
#[cfg(target_os = "linux")]
use linux::{get_num_cpus, get_num_physical_cpus};

/// Returns the number of available CPUs of the current system.
///
/// This function will get the number of logical cores. Sometimes this is different from the number
/// of physical cores (See [Simultaneous multithreading on Wikipedia][smt]).
///
/// # Examples
///
/// ```
/// let cpus = num_cpus::get();
/// if cpus > 1 {
///     println!("We are on a multicore system with {} CPUs", cpus);
/// } else {
///     println!("We are on a single core system");
/// }
/// ```
///
/// # Note
///
/// This will check [sched affinity] on Linux, showing a lower number of CPUs if the current
/// thread does not have access to all the computer's CPUs.
///
/// This will also check [cgroups], frequently used in containers to constrain CPU usage.
///
/// [smt]: https://en.wikipedia.org/wiki/Simultaneous_multithreading
/// [sched affinity]: http://www.gnu.org/software/libc/manual/html_node/CPU-Affinity.html
/// [cgroups]: https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt
#[inline]
pub fn get() -> usize {
    get_num_cpus()
}

/// Returns the number of physical cores of the current system.
///
/// # Note
///
/// Physical count is supported only on Linux, mac OS and Windows platforms.
/// On other platforms, or if the physical count fails on supported platforms,
/// this function returns the same as [`get()`], which is the number of logical
/// CPUS.
///
/// # Examples
///
/// ```
/// let logical_cpus = num_cpus::get();
/// let physical_cpus = num_cpus::get_physical();
/// if logical_cpus > physical_cpus {
///     println!("We have simultaneous multithreading with about {:.2} \
///               logical cores to 1 physical core.",
///               (logical_cpus as f64) / (physical_cpus as f64));
/// } else if logical_cpus == physical_cpus {
///     println!("Either we don't have simultaneous multithreading, or our \
///               system doesn't support getting the number of physical CPUs.");
/// } else {
///     println!("We have less logical CPUs than physical CPUs, maybe we only have access to \
///               some of the CPUs on our system.");
/// }
/// ```
///
/// [`get()`]: fn.get.html
#[inline]
pub fn get_physical() -> usize {
    get_num_physical_cpus()
}

#[cfg(not(any(target_os = "linux", target_os = "windows", target_os="macos", target_os="openbsd")))]
#[inline]
fn get_num_physical_cpus() -> usize {
    // Not implemented, fall back
    get_num_cpus()
}

#[cfg(target_os = "windows")]
fn get_num_physical_cpus() -> usize {
    match get_num_physical_cpus_windows() {
        Some(num) => num,
        None => get_num_cpus()
    }
}

#[cfg(target_os = "windows")]
fn get_num_physical_cpus_windows() -> Option<usize> {
    // Inspired by https://msdn.microsoft.com/en-us/library/ms683194

    use std::ptr;
    use std::mem;

    #[allow(non_upper_case_globals)]
    const RelationProcessorCore: u32 = 0;

    #[repr(C)]
    #[allow(non_camel_case_types)]
    struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION {
        mask: usize,
        relationship: u32,
        _unused: [u64; 2]
    }

    extern "system" {
        fn GetLogicalProcessorInformation(
            info: *mut SYSTEM_LOGICAL_PROCESSOR_INFORMATION,
            length: &mut u32
        ) -> u32;
    }

    // First we need to determine how much space to reserve.

    // The required size of the buffer, in bytes.
    let mut needed_size = 0;

    unsafe {
        GetLogicalProcessorInformation(ptr::null_mut(), &mut needed_size);
    }

    let struct_size = mem::size_of::<SYSTEM_LOGICAL_PROCESSOR_INFORMATION>() as u32;

    // Could be 0, or some other bogus size.
    if needed_size == 0 || needed_size < struct_size || needed_size % struct_size != 0 {
        return None;
    }

    let count = needed_size / struct_size;

    // Allocate some memory where we will store the processor info.
    let mut buf = Vec::with_capacity(count as usize);

    let result;

    unsafe {
        result = GetLogicalProcessorInformation(buf.as_mut_ptr(), &mut needed_size);
    }

    // Failed for any reason.
    if result == 0 {
        return None;
    }

    let count = needed_size / struct_size;

    unsafe {
        buf.set_len(count as usize);
    }

    let phys_proc_count = buf.iter()
        // Only interested in processor packages (physical processors.)
        .filter(|proc_info| proc_info.relationship == RelationProcessorCore)
        .count();

    if phys_proc_count == 0 {
        None
    } else {
        Some(phys_proc_count)
    }
}

#[cfg(windows)]
fn get_num_cpus() -> usize {
    #[repr(C)]
    struct SYSTEM_INFO {
        wProcessorArchitecture: u16,
        wReserved: u16,
        dwPageSize: u32,
        lpMinimumApplicationAddress: *mut u8,
        lpMaximumApplicationAddress: *mut u8,
        dwActiveProcessorMask: *mut u8,
        dwNumberOfProcessors: u32,
        dwProcessorType: u32,
        dwAllocationGranularity: u32,
        wProcessorLevel: u16,
        wProcessorRevision: u16,
    }

    extern "system" {
        fn GetSystemInfo(lpSystemInfo: *mut SYSTEM_INFO);
    }

    unsafe {
        let mut sysinfo: SYSTEM_INFO = std::mem::zeroed();
        GetSystemInfo(&mut sysinfo);
        sysinfo.dwNumberOfProcessors as usize
    }
}

#[cfg(any(target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "netbsd"))]
fn get_num_cpus() -> usize {
    use std::ptr;

    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);

    unsafe {
        cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint;
    }
    if cpus < 1 {
        let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
        unsafe {
            libc::sysctl(mib.as_mut_ptr(),
                         2,
                         &mut cpus as *mut _ as *mut _,
                         &mut cpus_size as *mut _ as *mut _,
                         ptr::null_mut(),
                         0);
        }
        if cpus < 1 {
            cpus = 1;
        }
    }
    cpus as usize
}

#[cfg(target_os = "openbsd")]
fn get_num_cpus() -> usize {
    use std::ptr;

    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);
    let mut mib = [libc::CTL_HW, libc::HW_NCPUONLINE, 0, 0];
    let rc: libc::c_int;

    unsafe {
        rc = libc::sysctl(mib.as_mut_ptr(),
                          2,
                          &mut cpus as *mut _ as *mut _,
                          &mut cpus_size as *mut _ as *mut _,
                          ptr::null_mut(),
                          0);
    }
    if rc < 0 {
        cpus = 1;
    }
    cpus as usize
}

#[cfg(target_os = "openbsd")]
fn get_num_physical_cpus() -> usize {
    use std::ptr;

    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);
    let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
    let rc: libc::c_int;

    unsafe {
        rc = libc::sysctl(mib.as_mut_ptr(),
                          2,
                          &mut cpus as *mut _ as *mut _,
                          &mut cpus_size as *mut _ as *mut _,
                          ptr::null_mut(),
                          0);
    }
    if rc < 0 {
        cpus = 1;
    }
    cpus as usize
}

#[cfg(target_os = "macos")]
fn get_num_physical_cpus() -> usize {
    use std::ffi::CStr;
    use std::ptr;

    let mut cpus: i32 = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);

    let sysctl_name = CStr::from_bytes_with_nul(b"hw.physicalcpu\0")
        .expect("byte literal is missing NUL");

    unsafe {
        if 0 != libc::sysctlbyname(sysctl_name.as_ptr(),
                                   &mut cpus as *mut _ as *mut _,
                                   &mut cpus_size as *mut _ as *mut _,
                                   ptr::null_mut(),
                                   0) {
            return get_num_cpus();
        }
    }
    cpus as usize
}

#[cfg(any(
    target_os = "nacl",
    target_os = "macos",
    target_os = "ios",
    target_os = "android",
    target_os = "solaris",
    target_os = "illumos",
    target_os = "fuchsia")
)]
fn get_num_cpus() -> usize {
    // On ARM targets, processors could be turned off to save power.
    // Use `_SC_NPROCESSORS_CONF` to get the real number.
    #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
    const CONF_NAME: libc::c_int = libc::_SC_NPROCESSORS_CONF;
    #[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))]
    const CONF_NAME: libc::c_int = libc::_SC_NPROCESSORS_ONLN;

    let cpus = unsafe { libc::sysconf(CONF_NAME) };
    if cpus < 1 {
        1
    } else {
        cpus as usize
    }
}

#[cfg(target_os = "haiku")]
fn get_num_cpus() -> usize {
    use std::mem;

    #[allow(non_camel_case_types)]
    type bigtime_t = i64;
    #[allow(non_camel_case_types)]
    type status_t = i32;

    #[repr(C)]
    pub struct system_info {
        pub boot_time: bigtime_t,
        pub cpu_count: u32,
        pub max_pages: u64,
        pub used_pages: u64,
        pub cached_pages: u64,
        pub block_cache_pages: u64,
        pub ignored_pages: u64,
        pub needed_memory: u64,
        pub free_memory: u64,
        pub max_swap_pages: u64,
        pub free_swap_pages: u64,
        pub page_faults: u32,
        pub max_sems: u32,
        pub used_sems: u32,
        pub max_ports: u32,
        pub used_ports: u32,
        pub max_threads: u32,
        pub used_threads: u32,
        pub max_teams: u32,
        pub used_teams: u32,
        pub kernel_name: [::std::os::raw::c_char; 256usize],
        pub kernel_build_date: [::std::os::raw::c_char; 32usize],
        pub kernel_build_time: [::std::os::raw::c_char; 32usize],
        pub kernel_version: i64,
        pub abi: u32,
    }

    extern {
        fn get_system_info(info: *mut system_info) -> status_t;
    }

    let mut info: system_info = unsafe { mem::zeroed() };
    let status = unsafe { get_system_info(&mut info as *mut _) };
    if status == 0 {
        info.cpu_count as usize
    } else {
        1
    }
}

#[cfg(target_os = "hermit")]
fn get_num_cpus() -> usize {
    unsafe { hermit_abi::get_processor_count() }
}

#[cfg(not(any(
    target_os = "nacl",
    target_os = "macos",
    target_os = "ios",
    target_os = "android",
    target_os = "solaris",
    target_os = "illumos",
    target_os = "fuchsia",
    target_os = "linux",
    target_os = "openbsd",
    target_os = "freebsd",
    target_os = "dragonfly",
    target_os = "netbsd",
    target_os = "haiku",
    target_os = "hermit",
    windows,
)))]
fn get_num_cpus() -> usize {
    1
}

#[cfg(test)]
mod tests {
    fn env_var(name: &'static str) -> Option<usize> {
        ::std::env::var(name).ok().map(|val| val.parse().unwrap())
    }

    #[test]
    fn test_get() {
        let num = super::get();
        if let Some(n) = env_var("NUM_CPUS_TEST_GET") {
            assert_eq!(num, n);
        } else {
            assert!(num > 0);
            assert!(num < 236_451);
        }
    }

    #[test]
    fn test_get_physical() {
        let num = super::get_physical();
        if let Some(n) = env_var("NUM_CPUS_TEST_GET_PHYSICAL") {
            assert_eq!(num, n);
        } else {
            assert!(num > 0);
            assert!(num < 236_451);
        }
    }
}
<commit_msg>Document always returning at least 1 core (#106)<commit_after>//! A crate with utilities to determine the number of CPUs available on the
//! current system.
//!
//! Sometimes the CPU will exaggerate the number of CPUs it contains, because it can use
//! [processor tricks] to deliver increased performance when there are more threads. This
//! crate provides methods to get both the logical and physical numbers of cores.
//!
//! This information can be used as a guide to how many tasks can be run in parallel.
//! There are many properties of the system architecture that will affect parallelism,
//! for example memory access speeds (for all the caches and RAM) and the physical
//! architecture of the processor, so the number of CPUs should be used as a rough guide
//! only.
//!
//!
//! ## Examples
//!
//! Fetch the number of logical CPUs.
//!
//! ```
//! let cpus = num_cpus::get();
//! ```
//!
//! See [`rayon::Threadpool`] for an example of where the number of CPUs could be
//! used when setting up parallel jobs (Where the threadpool example uses a fixed
//! number 8, it could use the number of CPUs).
//!
//! [processor tricks]: https://en.wikipedia.org/wiki/Simultaneous_multithreading
//! [`rayon::ThreadPool`]: https://docs.rs/rayon/1.*/rayon/struct.ThreadPool.html
#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]
#![doc(html_root_url = "https://docs.rs/num_cpus/1.13.0")]
#![allow(non_snake_case)]

#[cfg(not(windows))]
extern crate libc;

#[cfg(target_os = "hermit")]
extern crate hermit_abi;

#[cfg(target_os = "linux")]
mod linux;
#[cfg(target_os = "linux")]
use linux::{get_num_cpus, get_num_physical_cpus};

/// Returns the number of available CPUs of the current system.
///
/// This function will get the number of logical cores. Sometimes this is different from the number
/// of physical cores (See [Simultaneous multithreading on Wikipedia][smt]).
///
/// This will always return at least `1`.
///
/// # Examples
///
/// ```
/// let cpus = num_cpus::get();
/// if cpus > 1 {
///     println!("We are on a multicore system with {} CPUs", cpus);
/// } else {
///     println!("We are on a single core system");
/// }
/// ```
///
/// # Note
///
/// This will check [sched affinity] on Linux, showing a lower number of CPUs if the current
/// thread does not have access to all the computer's CPUs.
///
/// This will also check [cgroups], frequently used in containers to constrain CPU usage.
///
/// [smt]: https://en.wikipedia.org/wiki/Simultaneous_multithreading
/// [sched affinity]: http://www.gnu.org/software/libc/manual/html_node/CPU-Affinity.html
/// [cgroups]: https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt
#[inline]
pub fn get() -> usize {
    get_num_cpus()
}

/// Returns the number of physical cores of the current system.
///
/// This will always return at least `1`.
///
/// # Note
///
/// Physical count is supported only on Linux, mac OS and Windows platforms.
/// On other platforms, or if the physical count fails on supported platforms,
/// this function returns the same as [`get()`], which is the number of logical
/// CPUS.
///
/// # Examples
///
/// ```
/// let logical_cpus = num_cpus::get();
/// let physical_cpus = num_cpus::get_physical();
/// if logical_cpus > physical_cpus {
///     println!("We have simultaneous multithreading with about {:.2} \
///               logical cores to 1 physical core.",
///               (logical_cpus as f64) / (physical_cpus as f64));
/// } else if logical_cpus == physical_cpus {
///     println!("Either we don't have simultaneous multithreading, or our \
///               system doesn't support getting the number of physical CPUs.");
/// } else {
///     println!("We have less logical CPUs than physical CPUs, maybe we only have access to \
///               some of the CPUs on our system.");
/// }
/// ```
///
/// [`get()`]: fn.get.html
#[inline]
pub fn get_physical() -> usize {
    get_num_physical_cpus()
}

#[cfg(not(any(target_os = "linux", target_os = "windows", target_os="macos", target_os="openbsd")))]
#[inline]
fn get_num_physical_cpus() -> usize {
    // Not implemented, fall back
    get_num_cpus()
}

#[cfg(target_os = "windows")]
fn get_num_physical_cpus() -> usize {
    match get_num_physical_cpus_windows() {
        Some(num) => num,
        None => get_num_cpus()
    }
}

#[cfg(target_os = "windows")]
fn get_num_physical_cpus_windows() -> Option<usize> {
    // Inspired by https://msdn.microsoft.com/en-us/library/ms683194

    use std::ptr;
    use std::mem;

    #[allow(non_upper_case_globals)]
    const RelationProcessorCore: u32 = 0;

    #[repr(C)]
    #[allow(non_camel_case_types)]
    struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION {
        mask: usize,
        relationship: u32,
        _unused: [u64; 2]
    }

    extern "system" {
        fn GetLogicalProcessorInformation(
            info: *mut SYSTEM_LOGICAL_PROCESSOR_INFORMATION,
            length: &mut u32
        ) -> u32;
    }

    // First we need to determine how much space to reserve.

    // The required size of the buffer, in bytes.
    let mut needed_size = 0;

    unsafe {
        GetLogicalProcessorInformation(ptr::null_mut(), &mut needed_size);
    }

    let struct_size = mem::size_of::<SYSTEM_LOGICAL_PROCESSOR_INFORMATION>() as u32;

    // Could be 0, or some other bogus size.
    if needed_size == 0 || needed_size < struct_size || needed_size % struct_size != 0 {
        return None;
    }

    let count = needed_size / struct_size;

    // Allocate some memory where we will store the processor info.
    let mut buf = Vec::with_capacity(count as usize);

    let result;

    unsafe {
        result = GetLogicalProcessorInformation(buf.as_mut_ptr(), &mut needed_size);
    }

    // Failed for any reason.
    if result == 0 {
        return None;
    }

    let count = needed_size / struct_size;

    unsafe {
        buf.set_len(count as usize);
    }

    let phys_proc_count = buf.iter()
        // Only interested in processor packages (physical processors.)
        .filter(|proc_info| proc_info.relationship == RelationProcessorCore)
        .count();

    if phys_proc_count == 0 {
        None
    } else {
        Some(phys_proc_count)
    }
}

#[cfg(windows)]
fn get_num_cpus() -> usize {
    #[repr(C)]
    struct SYSTEM_INFO {
        wProcessorArchitecture: u16,
        wReserved: u16,
        dwPageSize: u32,
        lpMinimumApplicationAddress: *mut u8,
        lpMaximumApplicationAddress: *mut u8,
        dwActiveProcessorMask: *mut u8,
        dwNumberOfProcessors: u32,
        dwProcessorType: u32,
        dwAllocationGranularity: u32,
        wProcessorLevel: u16,
        wProcessorRevision: u16,
    }

    extern "system" {
        fn GetSystemInfo(lpSystemInfo: *mut SYSTEM_INFO);
    }

    unsafe {
        let mut sysinfo: SYSTEM_INFO = std::mem::zeroed();
        GetSystemInfo(&mut sysinfo);
        sysinfo.dwNumberOfProcessors as usize
    }
}

#[cfg(any(target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "netbsd"))]
fn get_num_cpus() -> usize {
    use std::ptr;

    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);

    unsafe {
        cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint;
    }
    if cpus < 1 {
        let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
        unsafe {
            libc::sysctl(mib.as_mut_ptr(),
                         2,
                         &mut cpus as *mut _ as *mut _,
                         &mut cpus_size as *mut _ as *mut _,
                         ptr::null_mut(),
                         0);
        }
        if cpus < 1 {
            cpus = 1;
        }
    }
    cpus as usize
}

#[cfg(target_os = "openbsd")]
fn get_num_cpus() -> usize {
    use std::ptr;

    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);
    let mut mib = [libc::CTL_HW, libc::HW_NCPUONLINE, 0, 0];
    let rc: libc::c_int;

    unsafe {
        rc = libc::sysctl(mib.as_mut_ptr(),
                          2,
                          &mut cpus as *mut _ as *mut _,
                          &mut cpus_size as *mut _ as *mut _,
                          ptr::null_mut(),
                          0);
    }
    if rc < 0 {
        cpus = 1;
    }
    cpus as usize
}

#[cfg(target_os = "openbsd")]
fn get_num_physical_cpus() -> usize {
    use std::ptr;

    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);
    let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
    let rc: libc::c_int;

    unsafe {
        rc = libc::sysctl(mib.as_mut_ptr(),
                          2,
                          &mut cpus as *mut _ as *mut _,
                          &mut cpus_size as *mut _ as *mut _,
                          ptr::null_mut(),
                          0);
    }
    if rc < 0 {
        cpus = 1;
    }
    cpus as usize
}

#[cfg(target_os = "macos")]
fn get_num_physical_cpus() -> usize {
    use std::ffi::CStr;
    use std::ptr;

    let mut cpus: i32 = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);

    let sysctl_name = CStr::from_bytes_with_nul(b"hw.physicalcpu\0")
        .expect("byte literal is missing NUL");

    unsafe {
        if 0 != libc::sysctlbyname(sysctl_name.as_ptr(),
                                   &mut cpus as *mut _ as *mut _,
                                   &mut cpus_size as *mut _ as *mut _,
                                   ptr::null_mut(),
                                   0) {
            return get_num_cpus();
        }
    }
    cpus as usize
}

#[cfg(any(
    target_os = "nacl",
    target_os = "macos",
    target_os = "ios",
    target_os = "android",
    target_os = "solaris",
    target_os = "illumos",
    target_os = "fuchsia")
)]
fn get_num_cpus() -> usize {
    // On ARM targets, processors could be turned off to save power.
    // Use `_SC_NPROCESSORS_CONF` to get the real number.
    #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
    const CONF_NAME: libc::c_int = libc::_SC_NPROCESSORS_CONF;
    #[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))]
    const CONF_NAME: libc::c_int = libc::_SC_NPROCESSORS_ONLN;

    let cpus = unsafe { libc::sysconf(CONF_NAME) };
    if cpus < 1 {
        1
    } else {
        cpus as usize
    }
}

#[cfg(target_os = "haiku")]
fn get_num_cpus() -> usize {
    use std::mem;

    #[allow(non_camel_case_types)]
    type bigtime_t = i64;
    #[allow(non_camel_case_types)]
    type status_t = i32;

    #[repr(C)]
    pub struct system_info {
        pub boot_time: bigtime_t,
        pub cpu_count: u32,
        pub max_pages: u64,
        pub used_pages: u64,
        pub cached_pages: u64,
        pub block_cache_pages: u64,
        pub ignored_pages: u64,
        pub needed_memory: u64,
        pub free_memory: u64,
        pub max_swap_pages: u64,
        pub free_swap_pages: u64,
        pub page_faults: u32,
        pub max_sems: u32,
        pub used_sems: u32,
        pub max_ports: u32,
        pub used_ports: u32,
        pub max_threads: u32,
        pub used_threads: u32,
        pub max_teams: u32,
        pub used_teams: u32,
        pub kernel_name: [::std::os::raw::c_char; 256usize],
        pub kernel_build_date: [::std::os::raw::c_char; 32usize],
        pub kernel_build_time: [::std::os::raw::c_char; 32usize],
        pub kernel_version: i64,
        pub abi: u32,
    }

    extern {
        fn get_system_info(info: *mut system_info) -> status_t;
    }

    let mut info: system_info = unsafe { mem::zeroed() };
    let status = unsafe { get_system_info(&mut info as *mut _) };
    if status == 0 {
        info.cpu_count as usize
    } else {
        1
    }
}

#[cfg(target_os = "hermit")]
fn get_num_cpus() -> usize {
    unsafe { hermit_abi::get_processor_count() }
}

#[cfg(not(any(
    target_os = "nacl",
    target_os = "macos",
    target_os = "ios",
    target_os = "android",
    target_os = "solaris",
    target_os = "illumos",
    target_os = "fuchsia",
    target_os = "linux",
    target_os = "openbsd",
    target_os = "freebsd",
    target_os = "dragonfly",
    target_os = "netbsd",
    target_os = "haiku",
    target_os = "hermit",
    windows,
)))]
fn get_num_cpus() -> usize {
    1
}

#[cfg(test)]
mod tests {
    fn env_var(name: &'static str) -> Option<usize> {
        ::std::env::var(name).ok().map(|val| val.parse().unwrap())
    }

    #[test]
    fn test_get() {
        let num = super::get();
        if let Some(n) = env_var("NUM_CPUS_TEST_GET") {
            assert_eq!(num, n);
        } else {
            assert!(num > 0);
            assert!(num < 236_451);
        }
    }

    #[test]
    fn test_get_physical() {
        let num = super::get_physical();
        if let Some(n) = env_var("NUM_CPUS_TEST_GET_PHYSICAL") {
            assert_eq!(num, n);
        } else {
            assert!(num > 0);
            assert!(num < 236_451);
        }
    }
}
<|endoftext|>