<commit_before>//!
//! You can make _any_ program run on Android with minimal non-intrusive
//! modification using this library.
//!
//! If you are using Cargo add this line to your `Cargo.toml`.
//!
//!     [dependencies.android_glue] git = "https://github.com/tomaka/android-rs-glue"
//!
//! If you are not using Cargo then make sure the library is findable by `rustc`
//! and then see example program below.
//!
//!
//! A sample application:
//!
//!     // This code will only be included if android is the target.
//!     #[cfg(target_os = "android")]
//!     #[macro_use]
//!     extern crate android_glue;
//!     // This code will only be included if android is the target.
//!     #[cfg(target_os = "android")]
//!     android_start!(main);
//!
//!     use std::sync::mpsc::channel;
//!     use android_glue::{Event, add_sender};
//!
//!     fn main() {
//!         // Create a channel.
//!         let (eventstx, eventsrx) = channel::<Event>();
//!
//!         // Try `dbg logcat *:D | grep RustAndroidGlue` when you run this program.
//!         println!("HELLO WORLD");
//!
//!         // Add the sender half of the channel so we can be sent events.
//!         add_sender(eventstx);
//!
//!         loop {
//!             // Print the event since it implements the Debug trait.
//!             println!("{:?}", eventsrx.recv());
//!         }
//!     }

#![feature(box_syntax, plugin, libc, core, io, collections, std_misc)]

#![unstable]

extern crate libc;

use std::ffi::{CString};
use std::sync::mpsc::{Sender};
use std::sync::Mutex;
use std::thread::Thread;

#[doc(hidden)]
pub mod ffi;

/// This static variable  will store the android_app* on creation, and set it back to 0 at
///  destruction.
/// Apart from this, the static is never written, so there is no risk of race condition.
static mut ANDROID_APP: *mut ffi::android_app = 0 as *mut ffi::android_app;

/// This is the structure that serves as user data in the android_app*
#[doc(hidden)]
struct Context {
    senders:    Mutex<Vec<Sender<Event>>>,
    // Any missed events are stored here.
    missed:     Mutex<Vec<Event>>,
    // The maximum number of missed events.
    missedmax:  usize,
}

/// An event triggered by the Android environment.
#[derive(Debug)]
pub enum Event {
    EventUp,
    EventDown,
    EventMove(i32, i32),
    // The above are more specifically EventMotion, but to prevent a breaking
    // change I did not rename them, but instead made EventKey** --kmcg3413@gmail.com
    EventKeyUp,
    EventKeyDown,
    InitWindow,
    SaveState,
    TermWindow,
    GainedFocus,
    LostFocus,
    InputChanged,
    WindowResized,
    WindowRedrawNeeded,
    ContentRectChanged,
    ConfigChanged,
    LowMemory,
    Start,
    Resume,
    Pause,
    Stop,
    Destroy,
}

impl Copy for Event {}

#[cfg(not(target_os = "android"))]
use this_platform_is_not_supported;

#[macro_export]
macro_rules! android_start(
    ($main: ident) => (
        pub mod __android_start {
            extern crate android_glue;

            // this function is here because we are sure that it will be included by the linker
            // so we call app_dummy in it, in order to be sure that the native glue will be included
            #[start]
            pub fn start(_: isize, _: *const *const u8) -> isize {
                unsafe { android_glue::ffi::app_dummy() };
                1
            }

            #[no_mangle]
            #[inline(never)]
            #[allow(non_snake_case)]
            pub extern "C" fn android_main(app: *mut ()) {
                android_glue::android_main2(app, move|| super::$main());
            }
        }
    )
);

/// This is the function that must be called by `android_main`
#[doc(hidden)]
pub fn android_main2<F>(app: *mut (), main_function: F)
    where F: FnOnce(), F: Send
{
    use std::{mem, ptr};

    write_log("Entering android_main");

    unsafe { ANDROID_APP = std::mem::transmute(app) };
    let app: &mut ffi::android_app = unsafe { std::mem::transmute(app) };

    // creating the context that will be passed to the callback
    let context = Context {
        senders:    Mutex::new(Vec::new()),
        missed:     Mutex::new(Vec::new()),
        missedmax:  1024,
    };
    app.onAppCmd = commands_callback;
    app.onInputEvent = inputs_callback;
    app.userData = unsafe { std::mem::transmute(&context) };

    // Set our stdout and stderr so that panics are directed to the log.
    std::old_io::stdio::set_stdout(box std::old_io::LineBufferedWriter::new(ToLogWriter));
    std::old_io::stdio::set_stderr(box std::old_io::LineBufferedWriter::new(ToLogWriter));

    // executing the main function in parallel
    let g = Thread::spawn(move|| {
        std::old_io::stdio::set_stdout(box std::old_io::LineBufferedWriter::new(ToLogWriter));
        std::old_io::stdio::set_stderr(box std::old_io::LineBufferedWriter::new(ToLogWriter));
        main_function()
    });

    // polling for events forever
    // note that this must be done in the same thread as android_main because ALooper are
    //  thread-local
    unsafe {
        loop {
            let mut events = mem::uninitialized();
            let mut source = mem::uninitialized();

            // passing -1 means that we are blocking
            let ident = ffi::ALooper_pollAll(-1, ptr::null_mut(), &mut events,
                &mut source);

            // processing the event
            if !source.is_null() {
                let source: *mut ffi::android_poll_source = mem::transmute(source);
                ((*source).process)(ANDROID_APP, source);
            }
        }
    }

    // terminating the application
    unsafe { ANDROID_APP = 0 as *mut ffi::android_app };
}

/// Writer that will redirect what is written to it to the logs.
struct ToLogWriter;

impl Writer for ToLogWriter {
    fn write_all(&mut self, buf: &[u8]) -> std::old_io::IoResult<()> {
        let message = CString::from_slice(buf);
        let message = message.as_slice_with_nul().as_ptr();
        let tag = b"RustAndroidGlueStdouterr";
        let tag = CString::from_slice(tag);
        let tag = tag.as_slice_with_nul().as_ptr();
        unsafe { ffi::__android_log_write(3, tag, message) };
        Ok(())
    }
}

/// Send a event to anything that has registered a sender. This is where events
/// messages are sent, and the main application can recieve them from this. There
/// is likely only one sender in our list, but we support more than one.
fn send_event(event: Event) {
    let mut ctx = get_context();
    let senders = ctx.senders.lock().ok().unwrap();

    // Store missed events up to a maximum. This is a little expensive, because
    // we have to double lock, until a sender is added. For applications that
    // never register a sender it would always double lock on any event, but
    // those applications might be short lived and not bothered?
    // -- kmcg3413@gmail.com
    if senders.len() < 1 {
        let mut missed = ctx.missed.lock().unwrap();
        if missed.len() < ctx.missedmax {
            missed.push(event);
        }
    }

    for sender in senders.iter() {
        sender.send(event);
    }
}

/// The callback for input.
///
/// This callback is registered when we startup and is called by our main thread,
/// from the function `android_main2`. We then process the event to gain additional
/// information, and finally send the event, which normally would be recieved by
/// the main application thread IF it has registered a sender.
pub extern fn inputs_callback(_: *mut ffi::android_app, event: *const ffi::AInputEvent)
    -> libc::int32_t
{
    fn get_xy(event: *const ffi::AInputEvent) -> (i32, i32) {
        let x = unsafe { ffi::AMotionEvent_getX(event, 0) };
        let y = unsafe { ffi::AMotionEvent_getY(event, 0) };
        (x as i32, y as i32)
    }

    let etype = unsafe { ffi::AInputEvent_getType(event) };
    let action = unsafe { ffi::AMotionEvent_getAction(event) };
    let action_code = action & ffi::AMOTION_EVENT_ACTION_MASK;

    match etype {
        ffi::AINPUT_EVENT_TYPE_KEY => match action_code {
            ffi::AKEY_EVENT_ACTION_DOWN => { send_event(Event::EventKeyDown); },
            ffi::AKEY_EVENT_ACTION_UP => send_event(Event::EventKeyUp),
            _ => write_log(format!("unknown input-event-type:{} action_code:{}", etype, action_code).as_slice()),
        },
        ffi::AINPUT_EVENT_TYPE_MOTION => match action_code {
            ffi::AMOTION_EVENT_ACTION_UP
                | ffi::AMOTION_EVENT_ACTION_OUTSIDE
                | ffi::AMOTION_EVENT_ACTION_CANCEL
                | ffi::AMOTION_EVENT_ACTION_POINTER_UP =>
            {
                send_event(Event::EventUp);
            },
            ffi::AMOTION_EVENT_ACTION_DOWN
                | ffi::AMOTION_EVENT_ACTION_POINTER_DOWN =>
            {
                let (x, y) = get_xy(event);
                send_event(Event::EventMove(x, y));
                send_event(Event::EventDown);
            },
            _ => {
                let (x, y) = get_xy(event);
                send_event(Event::EventMove(x, y));
            },
        },
        _ => write_log(format!("unknown input-event-type:{} action_code:{}", etype, action_code).as_slice()),
    }
    0
}

/// The callback for commands.
#[doc(hidden)]
pub extern fn commands_callback(_: *mut ffi::android_app, command: libc::int32_t) {
    let context = get_context();

    match command {
        ffi::APP_CMD_INIT_WINDOW => send_event(Event::InitWindow),
        ffi::APP_CMD_SAVE_STATE => send_event(Event::SaveState),
        ffi::APP_CMD_TERM_WINDOW => send_event(Event::TermWindow),
        ffi::APP_CMD_GAINED_FOCUS => send_event(Event::GainedFocus),
        ffi::APP_CMD_LOST_FOCUS => send_event(Event::LostFocus),
        ffi::APP_CMD_INPUT_CHANGED => send_event(Event::InputChanged),
        ffi::APP_CMD_WINDOW_RESIZED => send_event(Event::WindowResized),
        ffi::APP_CMD_WINDOW_REDRAW_NEEDED => send_event(Event::WindowRedrawNeeded),
        ffi::APP_CMD_CONTENT_RECT_CHANGED => send_event(Event::ContentRectChanged),
        ffi::APP_CMD_CONFIG_CHANGED => send_event(Event::ConfigChanged),
        ffi::APP_CMD_LOW_MEMORY => send_event(Event::LowMemory),
        ffi::APP_CMD_START => send_event(Event::Start),
        ffi::APP_CMD_RESUME => send_event(Event::Resume),
        ffi::APP_CMD_PAUSE => send_event(Event::Pause),
        ffi::APP_CMD_STOP => send_event(Event::Stop),
        ffi::APP_CMD_DESTROY => send_event(Event::Destroy),
        _ => write_log(format!("unknown command {}", command).as_slice()),
    }
}

/// Returns the current Context.
fn get_context() -> &'static Context {
    let context = unsafe { (*ANDROID_APP).userData };
    unsafe { std::mem::transmute(context) }
}

/// Adds a sender where events will be sent to.
pub fn add_sender(sender: Sender<Event>) {
    get_context().senders.lock().unwrap().push(sender);
}

/// Adds a sender where events will be sent to, but also sends
/// any missing events to the sender object.
///
/// The missing events happen when the application starts, but before
/// any senders are registered. Since these might be important to certain
/// applications, this function provides that support.
pub fn add_sender_missing(sender: Sender<Event>) {
    let mut ctx = get_context();
    let mut senders = ctx.senders.lock().ok().unwrap();

    if senders.len() == 0 {
        // If the first sender added then, let us send any missing events.
        let mut missed = ctx.missed.lock().unwrap();
        while missed.len() > 0 {
            sender.send(missed.remove(0));
        }
    }

    senders.push(sender);
}

/// Returns a handle to the native window.
pub unsafe fn get_native_window() -> ffi::NativeWindowType {
    if ANDROID_APP.is_null() {
        panic!("The application was not initialized from android_main");
    }

    loop {
        let value = (*ANDROID_APP).window;
        if !value.is_null() {
            return value;
        }

        // spin-locking
        std::old_io::timer::sleep(std::time::Duration::milliseconds(10));
    }
}

///
pub fn write_log(message: &str) {
    let message = CString::from_slice(message.as_bytes());
    let message = message.as_slice_with_nul().as_ptr();
    let tag = b"RustAndroidGlueStdouterr";
    let tag = CString::from_slice(tag);
    let tag = tag.as_slice_with_nul().as_ptr();
    unsafe { ffi::__android_log_write(3, tag, message) };
}

pub enum AssetError {
    AssetMissing,
    EmptyBuffer,
}

pub fn load_asset(filename: &str) -> Result<Vec<u8>, AssetError> {
    struct AssetCloser {
        asset: *const ffi::Asset,
    }

    impl Drop for AssetCloser {
        fn drop(&mut self) {
            unsafe {
                ffi::AAsset_close(self.asset)
            };
        }
    }

    unsafe fn get_asset_manager() -> *const ffi::AAssetManager {
        let app = &*ANDROID_APP;
        let activity = &*app.activity;
        activity.assetManager
    }

    let filename_c_str = CString::from_slice(filename.as_bytes());
    let filename_c_str = filename_c_str.as_slice_with_nul().as_ptr();
    let asset = unsafe {
        ffi::AAssetManager_open(
            get_asset_manager(), filename_c_str, ffi::MODE_STREAMING)
    };
    if asset.is_null() {
        return Err(AssetError::AssetMissing);
    }
    let _asset_closer = AssetCloser{asset: asset};
    let len = unsafe {
        ffi::AAsset_getLength(asset)
    };
    let buff = unsafe {
        ffi::AAsset_getBuffer(asset)
    };
    if buff.is_null() {
        return Err(AssetError::EmptyBuffer);
    }
    let vec = unsafe {
        Vec::from_raw_buf(buff as *const u8, len as usize)
    };
    Ok(vec)
}
<commit_msg>Added atomic target word sized field to track missed event count.<commit_after>//!
//! You can make _any_ program run on Android with minimal non-intrusive
//! modification using this library.
//!
//! If you are using Cargo add this line to your `Cargo.toml`.
//!
//!     [dependencies.android_glue] git = "https://github.com/tomaka/android-rs-glue"
//!
//! If you are not using Cargo then make sure the library is findable by `rustc`
//! and then see example program below.
//!
//!
//! A sample application:
//!
//!     // This code will only be included if android is the target.
//!     #[cfg(target_os = "android")]
//!     #[macro_use]
//!     extern crate android_glue;
//!     // This code will only be included if android is the target.
//!     #[cfg(target_os = "android")]
//!     android_start!(main);
//!
//!     use std::sync::mpsc::channel;
//!     use android_glue::{Event, add_sender};
//!
//!     fn main() {
//!         // Create a channel.
//!         let (eventstx, eventsrx) = channel::<Event>();
//!
//!         // Try `dbg logcat *:D | grep RustAndroidGlue` when you run this program.
//!         println!("HELLO WORLD");
//!
//!         // Add the sender half of the channel so we can be sent events.
//!         add_sender(eventstx);
//!
//!         loop {
//!             // Print the event since it implements the Debug trait.
//!             println!("{:?}", eventsrx.recv());
//!         }
//!     }

#![feature(box_syntax, plugin, libc, core, io, collections, std_misc)]

#![unstable]

extern crate libc;

use std::ffi::{CString};
use std::sync::mpsc::{Sender};
use std::sync::Mutex;
use std::thread::Thread;
use std::sync::atomic::{AtomicUsize, Ordering};

#[doc(hidden)]
pub mod ffi;

/// This static variable  will store the android_app* on creation, and set it back to 0 at
///  destruction.
/// Apart from this, the static is never written, so there is no risk of race condition.
static mut ANDROID_APP: *mut ffi::android_app = 0 as *mut ffi::android_app;

/// This is the structure that serves as user data in the android_app*
#[doc(hidden)]
struct Context {
    senders:    Mutex<Vec<Sender<Event>>>,
    // Any missed events are stored here.
    missed:     Mutex<Vec<Event>>,
    // Better performance to track number of missed items.
    missedcnt:  AtomicUsize,
    // The maximum number of missed events.
    missedmax:  usize,
}

/// An event triggered by the Android environment.
#[derive(Debug)]
pub enum Event {
    EventUp,
    EventDown,
    EventMove(i32, i32),
    // The above are more specifically EventMotion, but to prevent a breaking
    // change I did not rename them, but instead made EventKey** --kmcg3413@gmail.com
    EventKeyUp,
    EventKeyDown,
    InitWindow,
    SaveState,
    TermWindow,
    GainedFocus,
    LostFocus,
    InputChanged,
    WindowResized,
    WindowRedrawNeeded,
    ContentRectChanged,
    ConfigChanged,
    LowMemory,
    Start,
    Resume,
    Pause,
    Stop,
    Destroy,
}

impl Copy for Event {}

#[cfg(not(target_os = "android"))]
use this_platform_is_not_supported;

#[macro_export]
macro_rules! android_start(
    ($main: ident) => (
        pub mod __android_start {
            extern crate android_glue;

            // this function is here because we are sure that it will be included by the linker
            // so we call app_dummy in it, in order to be sure that the native glue will be included
            #[start]
            pub fn start(_: isize, _: *const *const u8) -> isize {
                unsafe { android_glue::ffi::app_dummy() };
                1
            }

            #[no_mangle]
            #[inline(never)]
            #[allow(non_snake_case)]
            pub extern "C" fn android_main(app: *mut ()) {
                android_glue::android_main2(app, move|| super::$main());
            }
        }
    )
);

/// This is the function that must be called by `android_main`
#[doc(hidden)]
pub fn android_main2<F>(app: *mut (), main_function: F)
    where F: FnOnce(), F: Send
{
    use std::{mem, ptr};

    write_log("Entering android_main");

    unsafe { ANDROID_APP = std::mem::transmute(app) };
    let app: &mut ffi::android_app = unsafe { std::mem::transmute(app) };

    // creating the context that will be passed to the callback
    let context = Context {
        senders:    Mutex::new(Vec::new()),
        missed:     Mutex::new(Vec::new()),
        missedcnt:  AtomicUsize::new(0),
        missedmax:  1024,
    };
    app.onAppCmd = commands_callback;
    app.onInputEvent = inputs_callback;
    app.userData = unsafe { std::mem::transmute(&context) };

    // Set our stdout and stderr so that panics are directed to the log.
    std::old_io::stdio::set_stdout(box std::old_io::LineBufferedWriter::new(ToLogWriter));
    std::old_io::stdio::set_stderr(box std::old_io::LineBufferedWriter::new(ToLogWriter));

    // executing the main function in parallel
    let g = Thread::spawn(move|| {
        std::old_io::stdio::set_stdout(box std::old_io::LineBufferedWriter::new(ToLogWriter));
        std::old_io::stdio::set_stderr(box std::old_io::LineBufferedWriter::new(ToLogWriter));
        main_function()
    });

    // polling for events forever
    // note that this must be done in the same thread as android_main because ALooper are
    //  thread-local
    unsafe {
        loop {
            let mut events = mem::uninitialized();
            let mut source = mem::uninitialized();

            // passing -1 means that we are blocking
            let ident = ffi::ALooper_pollAll(-1, ptr::null_mut(), &mut events,
                &mut source);

            // processing the event
            if !source.is_null() {
                let source: *mut ffi::android_poll_source = mem::transmute(source);
                ((*source).process)(ANDROID_APP, source);
            }
        }
    }

    // terminating the application
    unsafe { ANDROID_APP = 0 as *mut ffi::android_app };
}

/// Writer that will redirect what is written to it to the logs.
struct ToLogWriter;

impl Writer for ToLogWriter {
    fn write_all(&mut self, buf: &[u8]) -> std::old_io::IoResult<()> {
        let message = CString::from_slice(buf);
        let message = message.as_slice_with_nul().as_ptr();
        let tag = b"RustAndroidGlueStdouterr";
        let tag = CString::from_slice(tag);
        let tag = tag.as_slice_with_nul().as_ptr();
        unsafe { ffi::__android_log_write(3, tag, message) };
        Ok(())
    }
}

/// Send a event to anything that has registered a sender. This is where events
/// messages are sent, and the main application can recieve them from this. There
/// is likely only one sender in our list, but we support more than one.
fn send_event(event: Event) {
    let mut ctx = get_context();
    let senders = ctx.senders.lock().ok().unwrap();

    // Store missed events up to a maximum.
    if senders.len() < 1 {
        // We use a quick target word sized atomic load to check
        if ctx.missedcnt.load(Ordering::SeqCst) < ctx.missedmax {
            let mut missed = ctx.missed.lock().unwrap();
            missed.push(event);
            ctx.missedcnt.fetch_add(1, Ordering::SeqCst);
        }
    }

    for sender in senders.iter() {
        sender.send(event);
    }
}

/// The callback for input.
///
/// This callback is registered when we startup and is called by our main thread,
/// from the function `android_main2`. We then process the event to gain additional
/// information, and finally send the event, which normally would be recieved by
/// the main application thread IF it has registered a sender.
pub extern fn inputs_callback(_: *mut ffi::android_app, event: *const ffi::AInputEvent)
    -> libc::int32_t
{
    fn get_xy(event: *const ffi::AInputEvent) -> (i32, i32) {
        let x = unsafe { ffi::AMotionEvent_getX(event, 0) };
        let y = unsafe { ffi::AMotionEvent_getY(event, 0) };
        (x as i32, y as i32)
    }

    let etype = unsafe { ffi::AInputEvent_getType(event) };
    let action = unsafe { ffi::AMotionEvent_getAction(event) };
    let action_code = action & ffi::AMOTION_EVENT_ACTION_MASK;

    match etype {
        ffi::AINPUT_EVENT_TYPE_KEY => match action_code {
            ffi::AKEY_EVENT_ACTION_DOWN => { send_event(Event::EventKeyDown); },
            ffi::AKEY_EVENT_ACTION_UP => send_event(Event::EventKeyUp),
            _ => write_log(format!("unknown input-event-type:{} action_code:{}", etype, action_code).as_slice()),
        },
        ffi::AINPUT_EVENT_TYPE_MOTION => match action_code {
            ffi::AMOTION_EVENT_ACTION_UP
                | ffi::AMOTION_EVENT_ACTION_OUTSIDE
                | ffi::AMOTION_EVENT_ACTION_CANCEL
                | ffi::AMOTION_EVENT_ACTION_POINTER_UP =>
            {
                send_event(Event::EventUp);
            },
            ffi::AMOTION_EVENT_ACTION_DOWN
                | ffi::AMOTION_EVENT_ACTION_POINTER_DOWN =>
            {
                let (x, y) = get_xy(event);
                send_event(Event::EventMove(x, y));
                send_event(Event::EventDown);
            },
            _ => {
                let (x, y) = get_xy(event);
                send_event(Event::EventMove(x, y));
            },
        },
        _ => write_log(format!("unknown input-event-type:{} action_code:{}", etype, action_code).as_slice()),
    }
    0
}

/// The callback for commands.
#[doc(hidden)]
pub extern fn commands_callback(_: *mut ffi::android_app, command: libc::int32_t) {
    let context = get_context();

    match command {
        ffi::APP_CMD_INIT_WINDOW => send_event(Event::InitWindow),
        ffi::APP_CMD_SAVE_STATE => send_event(Event::SaveState),
        ffi::APP_CMD_TERM_WINDOW => send_event(Event::TermWindow),
        ffi::APP_CMD_GAINED_FOCUS => send_event(Event::GainedFocus),
        ffi::APP_CMD_LOST_FOCUS => send_event(Event::LostFocus),
        ffi::APP_CMD_INPUT_CHANGED => send_event(Event::InputChanged),
        ffi::APP_CMD_WINDOW_RESIZED => send_event(Event::WindowResized),
        ffi::APP_CMD_WINDOW_REDRAW_NEEDED => send_event(Event::WindowRedrawNeeded),
        ffi::APP_CMD_CONTENT_RECT_CHANGED => send_event(Event::ContentRectChanged),
        ffi::APP_CMD_CONFIG_CHANGED => send_event(Event::ConfigChanged),
        ffi::APP_CMD_LOW_MEMORY => send_event(Event::LowMemory),
        ffi::APP_CMD_START => send_event(Event::Start),
        ffi::APP_CMD_RESUME => send_event(Event::Resume),
        ffi::APP_CMD_PAUSE => send_event(Event::Pause),
        ffi::APP_CMD_STOP => send_event(Event::Stop),
        ffi::APP_CMD_DESTROY => send_event(Event::Destroy),
        _ => write_log(format!("unknown command {}", command).as_slice()),
    }
}

/// Returns the current Context.
fn get_context() -> &'static Context {
    let context = unsafe { (*ANDROID_APP).userData };
    unsafe { std::mem::transmute(context) }
}

/// Adds a sender where events will be sent to.
pub fn add_sender(sender: Sender<Event>) {
    get_context().senders.lock().unwrap().push(sender);
}

/// Adds a sender where events will be sent to, but also sends
/// any missing events to the sender object.
///
/// The missing events happen when the application starts, but before
/// any senders are registered. Since these might be important to certain
/// applications, this function provides that support.
pub fn add_sender_missing(sender: Sender<Event>) {
    let mut ctx = get_context();
    let mut senders = ctx.senders.lock().ok().unwrap();

    if senders.len() == 0 {
        // If the first sender added then, let us send any missing events.
        let mut missed = ctx.missed.lock().unwrap();
        while missed.len() > 0 {
            sender.send(missed.remove(0));
        }
        ctx.missedcnt.store(0, Ordering::Relaxed);
    }

    senders.push(sender);
}

/// Returns a handle to the native window.
pub unsafe fn get_native_window() -> ffi::NativeWindowType {
    if ANDROID_APP.is_null() {
        panic!("The application was not initialized from android_main");
    }

    loop {
        let value = (*ANDROID_APP).window;
        if !value.is_null() {
            return value;
        }

        // spin-locking
        std::old_io::timer::sleep(std::time::Duration::milliseconds(10));
    }
}

///
pub fn write_log(message: &str) {
    let message = CString::from_slice(message.as_bytes());
    let message = message.as_slice_with_nul().as_ptr();
    let tag = b"RustAndroidGlueStdouterr";
    let tag = CString::from_slice(tag);
    let tag = tag.as_slice_with_nul().as_ptr();
    unsafe { ffi::__android_log_write(3, tag, message) };
}

pub enum AssetError {
    AssetMissing,
    EmptyBuffer,
}

pub fn load_asset(filename: &str) -> Result<Vec<u8>, AssetError> {
    struct AssetCloser {
        asset: *const ffi::Asset,
    }

    impl Drop for AssetCloser {
        fn drop(&mut self) {
            unsafe {
                ffi::AAsset_close(self.asset)
            };
        }
    }

    unsafe fn get_asset_manager() -> *const ffi::AAssetManager {
        let app = &*ANDROID_APP;
        let activity = &*app.activity;
        activity.assetManager
    }

    let filename_c_str = CString::from_slice(filename.as_bytes());
    let filename_c_str = filename_c_str.as_slice_with_nul().as_ptr();
    let asset = unsafe {
        ffi::AAssetManager_open(
            get_asset_manager(), filename_c_str, ffi::MODE_STREAMING)
    };
    if asset.is_null() {
        return Err(AssetError::AssetMissing);
    }
    let _asset_closer = AssetCloser{asset: asset};
    let len = unsafe {
        ffi::AAsset_getLength(asset)
    };
    let buff = unsafe {
        ffi::AAsset_getBuffer(asset)
    };
    if buff.is_null() {
        return Err(AssetError::EmptyBuffer);
    }
    let vec = unsafe {
        Vec::from_raw_buf(buff as *const u8, len as usize)
    };
    Ok(vec)
}
<|endoftext|>


<commit_before>use std::fmt::{Display, Formatter, Error};
use std::hash::{Hash, Hasher};
use std::string::String;

use super::binding::{Binding, UniqueBinding};
use super::coerce::AsString;
use super::js_fn::JsFnStruct;
use super::js_obj::JsObjStruct;
use super::js_str::JsStrStruct;
use super::native_fn::NativeFn;
use super::native_var::NativeVar;

#[derive(Clone, Debug)]
pub struct JsVar {
    pub unique: UniqueBinding,
    pub binding: Binding,
    pub t: JsType,
}

impl Hash for JsVar {
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        self.unique.hash(state);
    }
}

impl JsVar {
    pub fn new(t: JsType) -> JsVar {
        let mut var = JsVar {
            unique: UniqueBinding::dummy(),
            binding: Binding::anon(),
            t: t,
        };
        var.unique = UniqueBinding::mangle(&var.binding);
        var
    }

    pub fn bind(binding: &str, t: JsType) -> JsVar {
        let mut var = JsVar {
            unique: UniqueBinding::mangle_str(binding),
            binding: Binding::new(binding.to_owned()),
            t: t,
        };
        var.unique = UniqueBinding::mangle(&var.binding);
        var
    }

    pub fn deanonymize(&mut self, binding: &str) -> bool {
        if self.binding.is_anon() {
            self.unique = UniqueBinding::mangle_str(binding);
            self.binding = Binding::new(binding.to_owned());
            true
        } else {
            false
        }
    }

    pub fn rename(&mut self, binding: &str) -> bool {
        if self.binding.var_name() != binding {
            self.binding = Binding::new(binding.to_owned());
            true
        } else {
            false
        }
    }

    pub fn type_of(&self) -> String {
        self.t.type_of()
    }
}

impl Display for JsVar {
    fn fmt(&self, mut fmt: &mut Formatter) -> Result<(), Error> {
        if !self.binding.is_anon() {
            return write!(fmt, "{}", self.binding);
        }

        write!(fmt, "{}", self.t)
    }
}

impl PartialEq for JsVar {
    fn eq(&self, other: &Self) -> bool {
        self.unique == other.unique
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}

impl Eq for JsVar {}

#[derive(Clone, Debug)]
pub enum JsPtrEnum {
    JsSym(String),
    JsStr(JsStrStruct),
    JsObj(JsObjStruct),
    JsFn(JsFnStruct),
    NativeFn(NativeFn),
    NativeVar(NativeVar),
}

impl Display for JsPtrEnum {
    fn fmt(&self, mut fmt: &mut Formatter) -> Result<(), Error> {
        match self {
            &JsPtrEnum::JsSym(ref s) => write!(fmt, "Symbol({})", s),
            &JsPtrEnum::JsStr(ref s) => write!(fmt, "\"{}\"", s),
            &JsPtrEnum::JsObj(ref o) => write!(fmt, "{}", o),
            &JsPtrEnum::JsFn(ref f) => write!(fmt, "{}", f),
            &JsPtrEnum::NativeFn(_) => write!(fmt, "[native code]"),
            &JsPtrEnum::NativeVar(ref v) => write!(fmt, "{}", v.var),
        }
    }
}

#[derive(Clone, Debug)]
pub enum JsPtrTag {
    JsSym,
    JsStr,
    JsObj,
    JsFn { name: Option<String> },
    NativeFn { name: String },
    NativeVar { type_string: String },
}

impl JsPtrTag {
    pub fn eq_ptr_type(&self, other: &JsPtrEnum) -> bool {
        match (self, other) {
            (&JsPtrTag::JsSym, &JsPtrEnum::JsSym(_)) |
            (&JsPtrTag::JsStr, &JsPtrEnum::JsStr(_)) |
            (&JsPtrTag::JsObj, &JsPtrEnum::JsObj(_)) |
            (&JsPtrTag::JsFn{..},  &JsPtrEnum::JsFn(_)) |
            (&JsPtrTag::NativeFn{..}, &JsPtrEnum::NativeFn(_)) |
            (&JsPtrTag::NativeVar{..}, &JsPtrEnum::NativeVar(_)) => true,
            _ => false
        }
    }

    fn type_of(&self) -> String {
        let s = match *self {
            JsPtrTag::JsSym => "symbol",
            JsPtrTag::JsStr => "string",
            JsPtrTag::JsObj => "object",
            JsPtrTag::JsFn{..} | JsPtrTag::NativeFn{..} => "function",
            JsPtrTag::NativeVar{ ref type_string } => return type_string.to_owned(),
        };

        String::from(s)
    }
}

#[derive(Clone, Debug)]
pub enum JsType {
    JsUndef,
    JsNum(f64),
    JsBool(bool),
    JsPtr(JsPtrTag),
    JsNull, // null is not a ptr since it doesn't actually require heap allocation
}

impl JsType {
    fn type_of(&self) -> String {
        let s = match *self {
            JsType::JsUndef => "undefined",
            JsType::JsNum(_) => "number",
            JsType::JsBool(_) => "boolean",
            JsType::JsNull => "object",
            JsType::JsPtr(ref t) => return t.type_of(),
        };

        String::from(s)
    }
}

impl Display for JsType {
    fn fmt(&self, mut fmt: &mut Formatter) -> Result<(), Error> {
        write!(fmt, "{}", self.as_string())
    }
}

impl PartialEq for JsType {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (&JsType::JsUndef, &JsType::JsUndef) => true,
            (&JsType::JsNum(x), &JsType::JsNum(y)) => x == y,
            (&JsType::JsBool(b1), &JsType::JsBool(b2)) => b1 == b2,
            (&JsType::JsNull, &JsType::JsNull) => true,
            (_, _) => false,
        }
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}

impl Eq for JsType {}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum JsKey {
    JsStr(JsStrStruct),
    JsSym(String),
}

impl Display for JsKey {
    fn fmt(&self, mut fmt: &mut Formatter) -> Result<(), Error> {
        match *self {
            JsKey::JsStr(ref s) => write!(fmt, "{}", s),
            JsKey::JsSym(ref s) => write!(fmt, "Symbol({})", s),
        }
    }
}
<commit_msg>refactor `deanonymize` into `mangle`<commit_after>use std::fmt::{Display, Formatter, Error};
use std::hash::{Hash, Hasher};
use std::string::String;

use super::binding::{Binding, UniqueBinding};
use super::coerce::AsString;
use super::js_fn::JsFnStruct;
use super::js_obj::JsObjStruct;
use super::js_str::JsStrStruct;
use super::native_fn::NativeFn;
use super::native_var::NativeVar;

#[derive(Clone, Debug)]
pub struct JsVar {
    pub unique: UniqueBinding,
    pub binding: Binding,
    pub t: JsType,
}

impl Hash for JsVar {
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        self.unique.hash(state);
    }
}

impl JsVar {
    pub fn new(t: JsType) -> JsVar {
        let mut var = JsVar {
            unique: UniqueBinding::dummy(),
            binding: Binding::anon(),
            t: t,
        };
        var.unique = UniqueBinding::mangle(&var.binding);
        var
    }

    pub fn bind(binding: &str, t: JsType) -> JsVar {
        let mut var = JsVar {
            unique: UniqueBinding::mangle_str(binding),
            binding: Binding::new(binding.to_owned()),
            t: t,
        };
        var.unique = UniqueBinding::mangle(&var.binding);
        var
    }

    pub fn mangle(&mut self, binding: &str) {
        self.unique = UniqueBinding::mangle_str(binding);
        self.binding = Binding::new(binding.to_owned());
    }

    pub fn rename(&mut self, binding: &str) -> bool {
        if self.binding.var_name() != binding {
            self.binding = Binding::new(binding.to_owned());
            true
        } else {
            false
        }
    }

    pub fn type_of(&self) -> String {
        self.t.type_of()
    }
}

impl Display for JsVar {
    fn fmt(&self, mut fmt: &mut Formatter) -> Result<(), Error> {
        if !self.binding.is_anon() {
            return write!(fmt, "{}", self.binding);
        }

        write!(fmt, "{}", self.t)
    }
}

impl PartialEq for JsVar {
    fn eq(&self, other: &Self) -> bool {
        self.unique == other.unique
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}

impl Eq for JsVar {}

#[derive(Clone, Debug)]
pub enum JsPtrEnum {
    JsSym(String),
    JsStr(JsStrStruct),
    JsObj(JsObjStruct),
    JsFn(JsFnStruct),
    NativeFn(NativeFn),
    NativeVar(NativeVar),
}

impl Display for JsPtrEnum {
    fn fmt(&self, mut fmt: &mut Formatter) -> Result<(), Error> {
        match self {
            &JsPtrEnum::JsSym(ref s) => write!(fmt, "Symbol({})", s),
            &JsPtrEnum::JsStr(ref s) => write!(fmt, "\"{}\"", s),
            &JsPtrEnum::JsObj(ref o) => write!(fmt, "{}", o),
            &JsPtrEnum::JsFn(ref f) => write!(fmt, "{}", f),
            &JsPtrEnum::NativeFn(_) => write!(fmt, "[native code]"),
            &JsPtrEnum::NativeVar(ref v) => write!(fmt, "{}", v.var),
        }
    }
}

#[derive(Clone, Debug)]
pub enum JsPtrTag {
    JsSym,
    JsStr,
    JsObj,
    JsFn { name: Option<String> },
    NativeFn { name: String },
    NativeVar { type_string: String },
}

impl JsPtrTag {
    pub fn eq_ptr_type(&self, other: &JsPtrEnum) -> bool {
        match (self, other) {
            (&JsPtrTag::JsSym, &JsPtrEnum::JsSym(_)) |
            (&JsPtrTag::JsStr, &JsPtrEnum::JsStr(_)) |
            (&JsPtrTag::JsObj, &JsPtrEnum::JsObj(_)) |
            (&JsPtrTag::JsFn{..},  &JsPtrEnum::JsFn(_)) |
            (&JsPtrTag::NativeFn{..}, &JsPtrEnum::NativeFn(_)) |
            (&JsPtrTag::NativeVar{..}, &JsPtrEnum::NativeVar(_)) => true,
            _ => false
        }
    }

    fn type_of(&self) -> String {
        let s = match *self {
            JsPtrTag::JsSym => "symbol",
            JsPtrTag::JsStr => "string",
            JsPtrTag::JsObj => "object",
            JsPtrTag::JsFn{..} | JsPtrTag::NativeFn{..} => "function",
            JsPtrTag::NativeVar{ ref type_string } => return type_string.to_owned(),
        };

        String::from(s)
    }
}

#[derive(Clone, Debug)]
pub enum JsType {
    JsUndef,
    JsNum(f64),
    JsBool(bool),
    JsPtr(JsPtrTag),
    JsNull, // null is not a ptr since it doesn't actually require heap allocation
}

impl JsType {
    fn type_of(&self) -> String {
        let s = match *self {
            JsType::JsUndef => "undefined",
            JsType::JsNum(_) => "number",
            JsType::JsBool(_) => "boolean",
            JsType::JsNull => "object",
            JsType::JsPtr(ref t) => return t.type_of(),
        };

        String::from(s)
    }
}

impl Display for JsType {
    fn fmt(&self, mut fmt: &mut Formatter) -> Result<(), Error> {
        write!(fmt, "{}", self.as_string())
    }
}

impl PartialEq for JsType {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (&JsType::JsUndef, &JsType::JsUndef) => true,
            (&JsType::JsNum(x), &JsType::JsNum(y)) => x == y,
            (&JsType::JsBool(b1), &JsType::JsBool(b2)) => b1 == b2,
            (&JsType::JsNull, &JsType::JsNull) => true,
            (_, _) => false,
        }
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}

impl Eq for JsType {}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum JsKey {
    JsStr(JsStrStruct),
    JsSym(String),
}

impl Display for JsKey {
    fn fmt(&self, mut fmt: &mut Formatter) -> Result<(), Error> {
        match *self {
            JsKey::JsStr(ref s) => write!(fmt, "{}", s),
            JsKey::JsSym(ref s) => write!(fmt, "Symbol({})", s),
        }
    }
}
<|endoftext|>


<commit_before>use na::Real;
use pipeline::broad_phase::BroadPhasePairFilter;
use pipeline::world::CollisionObject;

const SELF_COLLISION: u32 = 1 << 31;
const ALL_GROUPS: u32 = (1 << 30) - 1;
const NO_GROUP: u32 = 0;

/// Groups of collision used to filter which object interact with which other one.
///
/// There are at most 30 groups indexed from 0 to 29 (included). This identifies collidable
/// entities by combining three attributes:
///    * A set of group this structure is member of.
///    * A collision group whitelist.
///    * A collision group blacklist.
///
/// For two entities to interact, they must be member of at least one group part of each-other's
/// whitelists, and must not be part of any blacklisted group. The blacklist always has priority on
/// the whitelist.
///
/// ### Example
/// For example if the object A is such that:
///    * It is part of the groups 1, 3, and 6.
///    * It whitelists the groups 6 and 7.
///    * It blacklists the group 1.
/// Let the object B be such that:
///    * It is part of the groups 1, 3, and 7.
///    * It whitelists the groups 3 and 7.
///    * It does not blacklist anything.
/// For example if the object C is such that:
///    * It is part of the groups 6 and 9.
///    * It whitelists the groups 3 and 7.
///    * It does not blacklist anything.
///
/// Then we have:
///    * A and C can interact because A whitelists the group 6 (which C is part of), and,
///    reciprocally, C whitelists the group 3 (which A is part of).
///    * A and B will **not** interact because B is part of the group 1 which is blacklisted by A.
///    * Finally, B and C will **not** interact either because, even if C whitelists the group 3
///    (which B is part of), B does not whitelists the groups 6 nor 9 (which B is part of).
#[derive(Clone, Debug, Copy)]
pub struct CollisionGroups {
    membership: u32,
    whitelist: u32,
    blacklist: u32,
}

impl CollisionGroups {
    /// Creates a new `CollisionGroups` that enables interactions with everything except
    /// self-interaction.
    #[inline]
    pub fn new() -> CollisionGroups {
        CollisionGroups {
            membership: ALL_GROUPS,
            whitelist: ALL_GROUPS,
            blacklist: NO_GROUP,
        }
    }

    /// The maximum allowed group identifier.
    #[inline]
    pub fn max_group_id() -> usize {
        29
    }

    #[inline]
    fn modify_mask(mask: &mut u32, group_id: usize, add: bool) {
        assert!(
            group_id < 30,
            "There are at most 30 groups indexed from 0 to 29 (included)."
        );

        if add {
            *mask = *mask | (1 << group_id)
        } else {
            *mask = *mask & !(1 << group_id)
        }
    }

    #[inline]
    fn set_mask(mask: &mut u32, groups: &[usize]) {
        *mask = 0;
        for g in groups.iter() {
            CollisionGroups::modify_mask(mask, *g, true);
        }
    }

    /// Adds or removes this entity from the given group.
    #[inline]
    pub fn modify_membership(&mut self, group_id: usize, add: bool) {
        CollisionGroups::modify_mask(&mut self.membership, group_id, add);
    }

    /// Adds or removes the given group from this entity whitelist.
    #[inline]
    pub fn modify_whitelist(&mut self, group_id: usize, add: bool) {
        CollisionGroups::modify_mask(&mut self.whitelist, group_id, add);
    }

    /// Adds or removes this entity from the given group.
    #[inline]
    pub fn modify_blacklist(&mut self, group_id: usize, add: bool) {
        CollisionGroups::modify_mask(&mut self.blacklist, group_id, add);
    }

    /// Make this object member of the given groups only.
    #[inline]
    pub fn set_membership(&mut self, groups: &[usize]) {
        CollisionGroups::set_mask(&mut self.membership, groups);
    }

    /// Whitelists the given groups only (others will be un-whitelisted).
    #[inline]
    pub fn set_whitelist(&mut self, groups: &[usize]) {
        CollisionGroups::set_mask(&mut self.whitelist, groups);
    }

    /// Blacklists the given groups only (others will be un-blacklisted).
    #[inline]
    pub fn set_blacklist(&mut self, groups: &[usize]) {
        CollisionGroups::set_mask(&mut self.blacklist, groups);
    }

    /// Copies the membership of another collision groups.
    #[inline]
    pub fn copy_membership(&mut self, other: &CollisionGroups) {
        self.membership = other.membership
    }

    /// Copies the whitelist of another collision groups.
    #[inline]
    pub fn copy_whitelist(&mut self, other: &CollisionGroups) {
        self.whitelist = other.whitelist
    }

    /// Copies the blacklist of another collision groups.
    #[inline]
    pub fn copy_blacklist(&mut self, other: &CollisionGroups) {
        self.blacklist = other.blacklist
    }

    /// Allows the object to interact with itself.
    #[inline]
    pub fn enable_self_interaction(&mut self) {
        self.whitelist = self.whitelist | SELF_COLLISION;
    }

    /// Prevents the object from interacting with itself.
    #[inline]
    pub fn disable_self_interaction(&mut self) {
        self.whitelist = self.whitelist & !SELF_COLLISION;
    }

    #[inline]
    fn is_inside_mask(mask: u32, group_id: usize) -> bool {
        assert!(
            group_id < 30,
            "There are at most 30 groups indexed from 0 to 29 (included)."
        );
        mask & (1 << group_id) != 0
    }

    /// Tests if this entity is part of the given group.
    #[inline]
    pub fn is_member_of(&self, group_id: usize) -> bool {
        CollisionGroups::is_inside_mask(self.membership, group_id)
    }

    /// Tests if the given group is whitelisted.
    #[inline]
    pub fn is_group_whitelisted(&self, group_id: usize) -> bool {
        CollisionGroups::is_inside_mask(self.whitelist, group_id)
    }

    /// Tests if the given group is blacklisted.
    #[inline]
    pub fn is_group_blacklisted(&self, group_id: usize) -> bool {
        CollisionGroups::is_inside_mask(self.blacklist, group_id)
    }

    /// Tests whether interactions with a given group is possible.
    ///
    /// Collision is possible if `group_id` is whitelisted but not blacklisted.
    #[inline]
    pub fn can_interact_with(&self, group_id: usize) -> bool {
        !CollisionGroups::is_inside_mask(self.blacklist, group_id)
            && CollisionGroups::is_inside_mask(self.whitelist, group_id)
    }

    /// Tests whether two collision groups have at least one group in common.
    #[inline]
    pub fn can_interact_with_groups(&self, other: &CollisionGroups) -> bool {
        // FIXME: is there a more bitwise-y way of doing this?
        self.membership & other.blacklist == 0 && other.membership & self.blacklist == 0
            && self.membership & other.whitelist != 0
            && other.membership & self.whitelist != 0
    }

    /// Tests whether self-interaction is enabled.
    #[inline]
    pub fn can_interact_with_self(&self) -> bool {
        self.whitelist & SELF_COLLISION != 0
    }
}

/// A collision filter based collision groups.
pub struct CollisionGroupsPairFilter;

impl CollisionGroupsPairFilter {
    /// Creates a new collision filter based collision groups.
    #[inline]
    pub fn new() -> CollisionGroupsPairFilter {
        CollisionGroupsPairFilter
    }
}

impl<N: Real, T> BroadPhasePairFilter<N, T> for CollisionGroupsPairFilter {
    fn is_pair_valid(
        &self,
        co1: &CollisionObject<N, T>,
        co2: &CollisionObject<N, T>,
    ) -> bool {
        if co1.handle() == co2.handle() {
            co1.collision_groups().can_interact_with_self()
        } else {
            co1.collision_groups()
                .can_interact_with_groups(co2.collision_groups())
        }
    }
}
<commit_msg>rustfmt fixups for src/pipeline/world/collision_groups<commit_after>use na::Real;
use pipeline::broad_phase::BroadPhasePairFilter;
use pipeline::world::CollisionObject;

const SELF_COLLISION: u32 = 1 << 31;
const ALL_GROUPS: u32 = (1 << 30) - 1;
const NO_GROUP: u32 = 0;

/// Groups of collision used to filter which object interact with which other one.
///
/// There are at most 30 groups indexed from 0 to 29 (included). This identifies collidable
/// entities by combining three attributes:
///    * A set of group this structure is member of.
///    * A collision group whitelist.
///    * A collision group blacklist.
///
/// For two entities to interact, they must be member of at least one group part of each-other's
/// whitelists, and must not be part of any blacklisted group. The blacklist always has priority on
/// the whitelist.
///
/// ### Example
/// For example if the object A is such that:
///    * It is part of the groups 1, 3, and 6.
///    * It whitelists the groups 6 and 7.
///    * It blacklists the group 1.
/// Let the object B be such that:
///    * It is part of the groups 1, 3, and 7.
///    * It whitelists the groups 3 and 7.
///    * It does not blacklist anything.
/// For example if the object C is such that:
///    * It is part of the groups 6 and 9.
///    * It whitelists the groups 3 and 7.
///    * It does not blacklist anything.
///
/// Then we have:
///    * A and C can interact because A whitelists the group 6 (which C is part of), and,
///    reciprocally, C whitelists the group 3 (which A is part of).
///    * A and B will **not** interact because B is part of the group 1 which is blacklisted by A.
///    * Finally, B and C will **not** interact either because, even if C whitelists the group 3
///    (which B is part of), B does not whitelists the groups 6 nor 9 (which B is part of).
#[derive(Clone, Debug, Copy)]
pub struct CollisionGroups {
    membership: u32,
    whitelist: u32,
    blacklist: u32,
}

impl CollisionGroups {
    /// Creates a new `CollisionGroups` that enables interactions with everything except
    /// self-interaction.
    #[inline]
    pub fn new() -> CollisionGroups {
        CollisionGroups {
            membership: ALL_GROUPS,
            whitelist: ALL_GROUPS,
            blacklist: NO_GROUP,
        }
    }

    /// The maximum allowed group identifier.
    #[inline]
    pub fn max_group_id() -> usize {
        29
    }

    #[inline]
    fn modify_mask(mask: &mut u32, group_id: usize, add: bool) {
        assert!(
            group_id < 30,
            "There are at most 30 groups indexed from 0 to 29 (included)."
        );

        if add {
            *mask = *mask | (1 << group_id)
        } else {
            *mask = *mask & !(1 << group_id)
        }
    }

    #[inline]
    fn set_mask(mask: &mut u32, groups: &[usize]) {
        *mask = 0;
        for g in groups.iter() {
            CollisionGroups::modify_mask(mask, *g, true);
        }
    }

    /// Adds or removes this entity from the given group.
    #[inline]
    pub fn modify_membership(&mut self, group_id: usize, add: bool) {
        CollisionGroups::modify_mask(&mut self.membership, group_id, add);
    }

    /// Adds or removes the given group from this entity whitelist.
    #[inline]
    pub fn modify_whitelist(&mut self, group_id: usize, add: bool) {
        CollisionGroups::modify_mask(&mut self.whitelist, group_id, add);
    }

    /// Adds or removes this entity from the given group.
    #[inline]
    pub fn modify_blacklist(&mut self, group_id: usize, add: bool) {
        CollisionGroups::modify_mask(&mut self.blacklist, group_id, add);
    }

    /// Make this object member of the given groups only.
    #[inline]
    pub fn set_membership(&mut self, groups: &[usize]) {
        CollisionGroups::set_mask(&mut self.membership, groups);
    }

    /// Whitelists the given groups only (others will be un-whitelisted).
    #[inline]
    pub fn set_whitelist(&mut self, groups: &[usize]) {
        CollisionGroups::set_mask(&mut self.whitelist, groups);
    }

    /// Blacklists the given groups only (others will be un-blacklisted).
    #[inline]
    pub fn set_blacklist(&mut self, groups: &[usize]) {
        CollisionGroups::set_mask(&mut self.blacklist, groups);
    }

    /// Copies the membership of another collision groups.
    #[inline]
    pub fn copy_membership(&mut self, other: &CollisionGroups) {
        self.membership = other.membership
    }

    /// Copies the whitelist of another collision groups.
    #[inline]
    pub fn copy_whitelist(&mut self, other: &CollisionGroups) {
        self.whitelist = other.whitelist
    }

    /// Copies the blacklist of another collision groups.
    #[inline]
    pub fn copy_blacklist(&mut self, other: &CollisionGroups) {
        self.blacklist = other.blacklist
    }

    /// Allows the object to interact with itself.
    #[inline]
    pub fn enable_self_interaction(&mut self) {
        self.whitelist = self.whitelist | SELF_COLLISION;
    }

    /// Prevents the object from interacting with itself.
    #[inline]
    pub fn disable_self_interaction(&mut self) {
        self.whitelist = self.whitelist & !SELF_COLLISION;
    }

    #[inline]
    fn is_inside_mask(mask: u32, group_id: usize) -> bool {
        assert!(
            group_id < 30,
            "There are at most 30 groups indexed from 0 to 29 (included)."
        );
        mask & (1 << group_id) != 0
    }

    /// Tests if this entity is part of the given group.
    #[inline]
    pub fn is_member_of(&self, group_id: usize) -> bool {
        CollisionGroups::is_inside_mask(self.membership, group_id)
    }

    /// Tests if the given group is whitelisted.
    #[inline]
    pub fn is_group_whitelisted(&self, group_id: usize) -> bool {
        CollisionGroups::is_inside_mask(self.whitelist, group_id)
    }

    /// Tests if the given group is blacklisted.
    #[inline]
    pub fn is_group_blacklisted(&self, group_id: usize) -> bool {
        CollisionGroups::is_inside_mask(self.blacklist, group_id)
    }

    /// Tests whether interactions with a given group is possible.
    ///
    /// Collision is possible if `group_id` is whitelisted but not blacklisted.
    #[inline]
    pub fn can_interact_with(&self, group_id: usize) -> bool {
        !CollisionGroups::is_inside_mask(self.blacklist, group_id)
            && CollisionGroups::is_inside_mask(self.whitelist, group_id)
    }

    /// Tests whether two collision groups have at least one group in common.
    #[inline]
    pub fn can_interact_with_groups(&self, other: &CollisionGroups) -> bool {
        // FIXME: is there a more bitwise-y way of doing this?
        self.membership & other.blacklist == 0
            && other.membership & self.blacklist == 0
            && self.membership & other.whitelist != 0
            && other.membership & self.whitelist != 0
    }

    /// Tests whether self-interaction is enabled.
    #[inline]
    pub fn can_interact_with_self(&self) -> bool {
        self.whitelist & SELF_COLLISION != 0
    }
}

/// A collision filter based collision groups.
pub struct CollisionGroupsPairFilter;

impl CollisionGroupsPairFilter {
    /// Creates a new collision filter based collision groups.
    #[inline]
    pub fn new() -> CollisionGroupsPairFilter {
        CollisionGroupsPairFilter
    }
}

impl<N: Real, T> BroadPhasePairFilter<N, T> for CollisionGroupsPairFilter {
    fn is_pair_valid(&self, co1: &CollisionObject<N, T>, co2: &CollisionObject<N, T>) -> bool {
        if co1.handle() == co2.handle() {
            co1.collision_groups().can_interact_with_self()
        } else {
            co1.collision_groups()
                .can_interact_with_groups(co2.collision_groups())
        }
    }
}
<|endoftext|>


<commit_before>// Disable this lint to avoid it wanting to change `0xABCDEF` to `0xAB_CDEF`.
#![allow(unreadable_literal)]

macro_rules! colour {
    ($(#[$attr:meta] $name:ident, $val:expr;)*) => {
        impl Colour {
            $(
                #[$attr]
                pub fn $name() -> Colour {
                    Colour::new($val)
                }
            )*
        }
    }
}

/// A utility struct to help with working with the basic representation of a
/// colour. This is particularly useful when working with a [`Role`]'s colour,
/// as the API works with an integer value instead of an RGB value.
///
/// Instances can be created by using the struct's associated functions. These
/// produce presets equivalent to those found in the official client's colour
/// picker.
///
/// # Examples
///
/// Passing in a role's colour, and then retrieving its green component
/// via [`g`]:
///
/// ```rust
/// # use serenity::model::guild::Role;
/// # use serenity::model::id::RoleId;
/// # use serenity::model::permissions;
/// #
/// # let role = Role {
/// #     colour: Colour::blurple(),
/// #     hoist: false,
/// #     id: RoleId(1),
/// #     managed: false,
/// #     mentionable: false,
/// #     name: "test".to_string(),
/// #     permissions: permissions::PRESET_GENERAL,
/// #     position: 7,
/// # };
/// #
/// use serenity::utils::Colour;
///
/// // assuming a `role` has already been bound
///
/// let green = role.colour.g();
///
/// println!("The green component is: {}", green);
/// ```
///
/// Creating an instance with the [`dark_teal`] presets:
///
/// ```rust
/// use serenity::utils::Colour;
///
/// let colour = Colour::dark_teal();
///
/// assert_eq!(colour.tuple(), (17, 128, 106));
/// ```
///
/// Colours can also be directly compared for equivalence:
///
/// ```rust
/// use serenity::utils::Colour;
///
/// let blitz_blue = Colour::blitz_blue();
/// let fooyoo = Colour::fooyoo();
/// let fooyoo2 = Colour::fooyoo();
/// assert!(blitz_blue != fooyoo);
/// assert_eq!(fooyoo, fooyoo2);
/// assert!(blitz_blue > fooyoo);
/// ```
///
/// [`Role`]: ../model/guild/struct.Role.html
/// [`dark_teal`]: #method.dark_teal
/// [`g`]: #method.g
#[derive(Clone, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
pub struct Colour(pub u32);

impl Colour {
    /// Generates a new Colour with the given integer value set.
    ///
    /// # Examples
    ///
    /// Create a new Colour, and then ensure that its inner value is equivalent
    /// to a specific RGB value, retrieved via [`tuple`]:
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// let colour = Colour::new(6573123);
    ///
    /// assert_eq!(colour.tuple(), (100, 76, 67));
    /// ```
    ///
    /// [`tuple`]: #method.tuple
    #[inline]
    pub fn new(value: u32) -> Colour { Colour(value) }

    /// Generates a new Colour from an RGB value, creating an inner u32
    /// representation.
    ///
    /// # Examples
    ///
    /// Creating a `Colour` via its RGB values will set its inner u32 correctly:
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert!(Colour::from_rgb(255, 0, 0).0 == 0xFF0000);
    /// assert!(Colour::from_rgb(217, 23, 211).0 == 0xD917D3);
    /// ```
    ///
    /// And you can then retrieve those same RGB values via its methods:
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// let colour = Colour::from_rgb(217, 45, 215);
    ///
    /// assert_eq!(colour.r(), 217);
    /// assert_eq!(colour.g(), 45);
    /// assert_eq!(colour.b(), 215);
    /// assert_eq!(colour.tuple(), (217, 45, 215));
    /// ```
    pub fn from_rgb(r: u8, g: u8, b: u8) -> Colour {
        let mut uint = u32::from(r);
        uint = (uint << 8) | (u32::from(g));
        uint = (uint << 8) | (u32::from(b));

        Colour(uint)
    }

    /// Returns the red RGB component of this Colour.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::new(6573123).r(), 100);
    /// ```
    pub fn r(&self) -> u8 { ((self.0 >> 16) & 255) as u8 }

    /// Returns the green RGB component of this Colour.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::new(6573123).g(), 76);
    /// ```
    pub fn g(&self) -> u8 { ((self.0 >> 8) & 255) as u8 }

    /// Returns the blue RGB component of this Colour.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::new(6573123).b(), 67);
    pub fn b(&self) -> u8 { (self.0 & 255) as u8 }

    /// Returns a tuple of the red, green, and blue components of this Colour.
    ///
    /// This is equivalent to creating a tuple with the return values of
    /// [`r`], [`g`], and [`b`].
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::new(6573123).tuple(), (100, 76, 67));
    /// ```
    ///
    /// [`r`]: #method.r
    /// [`g`]: #method.g
    /// [`b`]: #method.b
    pub fn tuple(&self) -> (u8, u8, u8) { (self.r(), self.g(), self.b()) }
}

impl From<i32> for Colour {
    /// Constructs a Colour from a i32.
    ///
    /// This is used for functions that accept `Into<Colour>`.
    ///
    /// This is useful when providing hex values.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::from(0xDEA584).tuple(), (222, 165, 132));
    /// ```
    fn from(value: i32) -> Colour { Colour(value as u32) }
}

impl From<u32> for Colour {
    /// Constructs a Colour from a u32.
    ///
    /// This is used for functions that accept `Into<Colour>`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::from(6573123u32).r(), 100);
    /// ```
    fn from(value: u32) -> Colour { Colour(value) }
}

impl From<u64> for Colour {
    /// Constructs a Colour from a u32.
    ///
    /// This is used for functions that accept `Into<Colour>`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::from(6573123u64).r(), 100);
    /// ```
    fn from(value: u64) -> Colour { Colour(value as u32) }
}

impl From<(u8, u8, u8)> for Colour {
    /// Constructs a Colour from rgb.
    fn from((r, g, b): (u8, u8, u8)) -> Self { Colour::from_rgb(r, g, b) }
}

colour! {
    /// Creates a new `Colour`, setting its RGB value to `(111, 198, 226)`.
    blitz_blue, 0x6FC6E2;
    /// Creates a new `Colour`, setting its RGB value to `(52, 152, 219)`.
    blue, 0x3498DB;
    /// Creates a new `Colour`, setting its RGB value to `(114, 137, 218)`.
    blurple, 0x7289DA;
    /// Creates a new `Colour`, setting its RGB value to `(32, 102, 148)`.
    dark_blue, 0x206694;
    /// Creates a new `Colour`, setting its RGB value to `(194, 124, 14)`.
    dark_gold, 0xC27C0E;
    /// Creates a new `Colour`, setting its RGB value to `(31, 139, 76)`.
    dark_green, 0x1F8B4C;
    /// Creates a new `Colour`, setting its RGB value to `(96, 125, 139)`.
    dark_grey, 0x607D8B;
    /// Creates a new `Colour`, setting its RGB value to `(173, 20, 87)`.
    dark_magenta, 0xAD1457;
    /// Creates a new `Colour`, setting its RGB value to `(168, 67, 0)`.
    dark_orange, 0xA84300;
    /// Creates a new `Colour`, setting its RGB value to `(113, 54, 138)`.
    dark_purple, 0x71368A;
    /// Creates a new `Colour`, setting its RGB value to `(153, 45, 34)`.
    dark_red, 0x992D22;
    /// Creates a new `Colour`, setting its RGB value to `(17, 128, 106)`.
    dark_teal, 0x11806A;
    /// Creates a new `Colour`, setting its RGB value to `(84, 110, 122)`.
    darker_grey, 0x546E7A;
    /// Creates a new `Colour`, setting its RGB value to `(250, 177, 237)`.
    fabled_pink, 0xFAB1ED;
    /// Creates a new `Colour`, setting its RGB value to `(136, 130, 196)`.`
    faded_purple, 0x8882C4;
    /// Creates a new `Colour`, setting its RGB value to `(17, 202, 128)`.
    fooyoo, 0x11CA80;
    /// Creates a new `Colour`, setting its RGB value to `(241, 196, 15)`.
    gold, 0xF1C40F;
    /// Creates a new `Colour`, setting its RGB value to `(186, 218, 85)`.
    kerbal, 0xBADA55;
    /// Creates a new `Colour`, setting its RGB value to `(151, 156, 159)`.
    light_grey, 0x979C9F;
    /// Creates a new `Colour`, setting its RGB value to `(149, 165, 166)`.
    lighter_grey, 0x95A5A6;
    /// Creates a new `Colour`, setting its RGB value to `(233, 30, 99)`.
    magenta, 0xE91E63;
    /// Creates a new `Colour`, setting its RGB value to `(230, 131, 151)`.
    meibe_pink, 0xE68397;
    /// Creates a new `Colour`, setting its RGB value to `(230, 126, 34)`.
    orange, 0xE67E22;
    /// Creates a new `Colour`, setting its RGB value to `(155, 89, 182)`.
    purple, 0x9B59B6;
    /// Creates a new `Colour`, setting its RGB value to `(231, 76, 60)`.
    red, 0xE74C3C;
    /// Creates a new `Colour`, setting its RGB value to `(117, 150, 255)`.
    rohrkatze_blue, 0x7596FF;
    /// Creates a new `Colour`, setting its RGB value to `(246, 219, 216)`.
    rosewater, 0xF6DBD8;
    /// Creates a new `Colour`, setting its RGB value to `(26, 188, 156)`.
    teal, 0x1ABC9C;
}

impl Default for Colour {
    /// Creates a default value for a `Colour`, setting the inner value to `0`.
    fn default() -> Colour { Colour(0) }
}
<commit_msg>Add associated consts in Colour, deprecate methods<commit_after>// Disable this lint to avoid it wanting to change `0xABCDEF` to `0xAB_CDEF`.
#![allow(unreadable_literal)]

macro_rules! colour {
    ($(#[$attr:meta] $constname:ident, $name:ident, $val:expr;)*) => {
        impl Colour {
            $(
                #[$attr]
                pub const $constname: Colour = Colour($val);
            )*

            $(
                #[$attr]
                #[deprecated(note = "Use the constant instead", since = "0.5.5")]
                pub fn $name() -> Colour {
                    Colour::new($val)
                }
            )*
        }
    }
}

/// A utility struct to help with working with the basic representation of a
/// colour. This is particularly useful when working with a [`Role`]'s colour,
/// as the API works with an integer value instead of an RGB value.
///
/// Instances can be created by using the struct's associated functions. These
/// produce presets equivalent to those found in the official client's colour
/// picker.
///
/// # Examples
///
/// Passing in a role's colour, and then retrieving its green component
/// via [`g`]:
///
/// ```rust
/// # use serenity::model::guild::Role;
/// # use serenity::model::id::RoleId;
/// # use serenity::model::permissions;
/// #
/// # let role = Role {
/// #     colour: Colour::BLURPLE,
/// #     hoist: false,
/// #     id: RoleId(1),
/// #     managed: false,
/// #     mentionable: false,
/// #     name: "test".to_string(),
/// #     permissions: permissions::PRESET_GENERAL,
/// #     position: 7,
/// # };
/// #
/// use serenity::utils::Colour;
///
/// // assuming a `role` has already been bound
///
/// let green = role.colour.g();
///
/// println!("The green component is: {}", green);
/// ```
///
/// Creating an instance with the [`DARK_TEAL`] preset:
///
/// ```rust
/// use serenity::utils::Colour;
///
/// let colour = Colour::DARK_TEAL;
///
/// assert_eq!(colour.tuple(), (17, 128, 106));
/// ```
///
/// Colours can also be directly compared for equivalence:
///
/// ```rust
/// use serenity::utils::Colour;
///
/// let blitz_blue = Colour::BLITZ_BLUE;
/// let fooyoo = Colour::FOOYOO;
/// let fooyoo2 = Colour::FOOYOO;
/// assert!(blitz_blue != fooyoo);
/// assert_eq!(fooyoo, fooyoo2);
/// assert!(blitz_blue > fooyoo);
/// ```
///
/// [`Role`]: ../model/guild/struct.Role.html
/// [`DARK_TEAL`]: #associatedconstant.DARK_TEAL
/// [`g`]: #method.g
#[derive(Clone, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
pub struct Colour(pub u32);

impl Colour {
    /// Generates a new Colour with the given integer value set.
    ///
    /// # Examples
    ///
    /// Create a new Colour, and then ensure that its inner value is equivalent
    /// to a specific RGB value, retrieved via [`tuple`]:
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// let colour = Colour::new(6573123);
    ///
    /// assert_eq!(colour.tuple(), (100, 76, 67));
    /// ```
    ///
    /// [`tuple`]: #method.tuple
    #[inline]
    pub fn new(value: u32) -> Colour { Colour(value) }

    /// Generates a new Colour from an RGB value, creating an inner u32
    /// representation.
    ///
    /// # Examples
    ///
    /// Creating a `Colour` via its RGB values will set its inner u32 correctly:
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert!(Colour::from_rgb(255, 0, 0).0 == 0xFF0000);
    /// assert!(Colour::from_rgb(217, 23, 211).0 == 0xD917D3);
    /// ```
    ///
    /// And you can then retrieve those same RGB values via its methods:
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// let colour = Colour::from_rgb(217, 45, 215);
    ///
    /// assert_eq!(colour.r(), 217);
    /// assert_eq!(colour.g(), 45);
    /// assert_eq!(colour.b(), 215);
    /// assert_eq!(colour.tuple(), (217, 45, 215));
    /// ```
    pub fn from_rgb(r: u8, g: u8, b: u8) -> Colour {
        let mut uint = u32::from(r);
        uint = (uint << 8) | (u32::from(g));
        uint = (uint << 8) | (u32::from(b));

        Colour(uint)
    }

    /// Returns the red RGB component of this Colour.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::new(6573123).r(), 100);
    /// ```
    pub fn r(&self) -> u8 { ((self.0 >> 16) & 255) as u8 }

    /// Returns the green RGB component of this Colour.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::new(6573123).g(), 76);
    /// ```
    pub fn g(&self) -> u8 { ((self.0 >> 8) & 255) as u8 }

    /// Returns the blue RGB component of this Colour.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::new(6573123).b(), 67);
    pub fn b(&self) -> u8 { (self.0 & 255) as u8 }

    /// Returns a tuple of the red, green, and blue components of this Colour.
    ///
    /// This is equivalent to creating a tuple with the return values of
    /// [`r`], [`g`], and [`b`].
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::new(6573123).tuple(), (100, 76, 67));
    /// ```
    ///
    /// [`r`]: #method.r
    /// [`g`]: #method.g
    /// [`b`]: #method.b
    pub fn tuple(&self) -> (u8, u8, u8) { (self.r(), self.g(), self.b()) }
}

impl From<i32> for Colour {
    /// Constructs a Colour from a i32.
    ///
    /// This is used for functions that accept `Into<Colour>`.
    ///
    /// This is useful when providing hex values.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::from(0xDEA584).tuple(), (222, 165, 132));
    /// ```
    fn from(value: i32) -> Colour { Colour(value as u32) }
}

impl From<u32> for Colour {
    /// Constructs a Colour from a u32.
    ///
    /// This is used for functions that accept `Into<Colour>`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::from(6573123u32).r(), 100);
    /// ```
    fn from(value: u32) -> Colour { Colour(value) }
}

impl From<u64> for Colour {
    /// Constructs a Colour from a u32.
    ///
    /// This is used for functions that accept `Into<Colour>`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::from(6573123u64).r(), 100);
    /// ```
    fn from(value: u64) -> Colour { Colour(value as u32) }
}

impl From<(u8, u8, u8)> for Colour {
    /// Constructs a Colour from rgb.
    fn from((r, g, b): (u8, u8, u8)) -> Self { Colour::from_rgb(r, g, b) }
}

colour! {
    /// Creates a new `Colour`, setting its RGB value to `(111, 198, 226)`.
    BLITZ_BLUE, blitz_blue, 0x6FC6E2;
    /// Creates a new `Colour`, setting its RGB value to `(52, 152, 219)`.
    BLUE, blue, 0x3498DB;
    /// Creates a new `Colour`, setting its RGB value to `(114, 137, 218)`.
    BLURPLE, blurple, 0x7289DA;
    /// Creates a new `Colour`, setting its RGB value to `(32, 102, 148)`.
    DARK_BLUE, dark_blue, 0x206694;
    /// Creates a new `Colour`, setting its RGB value to `(194, 124, 14)`.
    DARK_GOLD, dark_gold, 0xC27C0E;
    /// Creates a new `Colour`, setting its RGB value to `(31, 139, 76)`.
    DARK_GREEN, dark_green, 0x1F8B4C;
    /// Creates a new `Colour`, setting its RGB value to `(96, 125, 139)`.
    DARK_GREY, dark_grey, 0x607D8B;
    /// Creates a new `Colour`, setting its RGB value to `(173, 20, 87)`.
    DARK_MAGENTA, dark_magenta, 0xAD1457;
    /// Creates a new `Colour`, setting its RGB value to `(168, 67, 0)`.
    DARK_ORANGE, dark_orange, 0xA84300;
    /// Creates a new `Colour`, setting its RGB value to `(113, 54, 138)`.
    DARK_PURPLE, dark_purple, 0x71368A;
    /// Creates a new `Colour`, setting its RGB value to `(153, 45, 34)`.
    DARK_RED, dark_red, 0x992D22;
    /// Creates a new `Colour`, setting its RGB value to `(17, 128, 106)`.
    DARK_TEAL, dark_teal, 0x11806A;
    /// Creates a new `Colour`, setting its RGB value to `(84, 110, 122)`.
    DARKER_GREY, darker_grey, 0x546E7A;
    /// Creates a new `Colour`, setting its RGB value to `(250, 177, 237)`.
    FABLED_PINK, fabled_pink, 0xFAB1ED;
    /// Creates a new `Colour`, setting its RGB value to `(136, 130, 196)`.`
    FADED_PURPLE, faded_purple, 0x8882C4;
    /// Creates a new `Colour`, setting its RGB value to `(17, 202, 128)`.
    FOOYOO, fooyoo, 0x11CA80;
    /// Creates a new `Colour`, setting its RGB value to `(241, 196, 15)`.
    GOLD, gold, 0xF1C40F;
    /// Creates a new `Colour`, setting its RGB value to `(186, 218, 85)`.
    KERBAL, kerbal, 0xBADA55;
    /// Creates a new `Colour`, setting its RGB value to `(151, 156, 159)`.
    LIGHT_GREY, light_grey, 0x979C9F;
    /// Creates a new `Colour`, setting its RGB value to `(149, 165, 166)`.
    LIGHTER_GREY, lighter_grey, 0x95A5A6;
    /// Creates a new `Colour`, setting its RGB value to `(233, 30, 99)`.
    MAGENTA, magenta, 0xE91E63;
    /// Creates a new `Colour`, setting its RGB value to `(230, 131, 151)`.
    MEIBE_PINK, meibe_pink, 0xE68397;
    /// Creates a new `Colour`, setting its RGB value to `(230, 126, 34)`.
    ORANGE, orange, 0xE67E22;
    /// Creates a new `Colour`, setting its RGB value to `(155, 89, 182)`.
    PURPLE, purple, 0x9B59B6;
    /// Creates a new `Colour`, setting its RGB value to `(231, 76, 60)`.
    RED, red, 0xE74C3C;
    /// Creates a new `Colour`, setting its RGB value to `(117, 150, 255)`.
    ROHRKATZE_BLUE, rohrkatze_blue, 0x7596FF;
    /// Creates a new `Colour`, setting its RGB value to `(246, 219, 216)`.
    ROSEWATER, rosewater, 0xF6DBD8;
    /// Creates a new `Colour`, setting its RGB value to `(26, 188, 156)`.
    TEAL, teal, 0x1ABC9C;
}

impl Default for Colour {
    /// Creates a default value for a `Colour`, setting the inner value to `0`.
    fn default() -> Colour { Colour(0) }
}
<|endoftext|>


<commit_before>#[macro_use] extern crate rustler;
#[macro_use] extern crate rustler_codegen;
#[macro_use] extern crate lazy_static;
#[macro_use] extern crate pact_mock_server;
extern crate libc;

use rustler::{NifEnv, NifTerm, NifResult, NifEncoder};
use pact_mock_server::create_mock_server;
use pact_mock_server::MockServerError;
use pact_mock_server::mock_server_mismatches;
use pact_mock_server::mock_server_matched;
use pact_mock_server::write_pact_file;
use pact_mock_server::WritePactFileErr;
use pact_mock_server::shutdown_mock_server_by_port;
mod atoms {
    rustler_atoms! {
        atom ok;
        atom error;
        atom mock_server_failed_to_start;
        atom invalid_pact_json;
        atom io_error;
        atom no_mock_server_running_on_port;
        //atom __true__ = "true";
        //atom __false__ = "false";
    }
}

rustler_export_nifs! {
    "Elixir.PactElixir.RustPactMockServerFacade",
    [
        ("create_mock_server", 2, create_mock_server_call),
        ("mock_server_mismatches", 1, mock_server_mismatches_call),
        ("mock_server_matched", 1, mock_server_matched_call),
        ("write_pact_file", 2, write_pact_file_call),
        ("cleanup_mock_server", 1, cleanup_mock_server_call)
    ],
    None
}

fn create_mock_server_call<'a>(env: NifEnv<'a>, args: &[NifTerm<'a>]) -> NifResult<NifTerm<'a>> {
    let pact_json: &str = try!(args[0].decode());
    let port_arg: i32 = try!(args[1].decode());

    match create_mock_server(pact_json, port_arg) {
        Ok(port) =>
            Ok((atoms::ok(), port).encode(env)),
        Err(MockServerError::MockServerFailedToStart) =>
            Ok((atoms::error(), atoms::mock_server_failed_to_start()).encode(env)),
        Err(MockServerError::InvalidPactJson) =>
            Ok((atoms::error(), atoms::invalid_pact_json()).encode(env))
    }
}

fn mock_server_mismatches_call<'a>(env: NifEnv<'a>, args: &[NifTerm<'a>]) -> NifResult<NifTerm<'a>> {
    let port: i32 = try!(args[0].decode());
    // TODO: This works only because mock_server_mismatches returns a string now:
    // Calling to_string() on json!(mismatches) in pact-reference/rust/pact_mock_server/src/lib.rs:657
    Ok((atoms::ok(), mock_server_mismatches(port)).encode(env))
}

fn mock_server_matched_call<'a>(env: NifEnv<'a>, args: &[NifTerm<'a>]) -> NifResult<NifTerm<'a>> {
    let port: i32 = try!(args[0].decode());

    let matched: bool = mock_server_matched(port);

    Ok((atoms::ok(), matched).encode(env))
}

fn write_pact_file_call<'a>(env: NifEnv<'a>, args: &[NifTerm<'a>]) -> NifResult<NifTerm<'a>> {
    let port: i32 = try!(args[0].decode());
    let dir_path: String = try!(args[1].decode());

    match write_pact_file(port, Some(dir_path)) {
        Ok(_result) =>
            Ok((atoms::ok()).encode(env)),
        /// IO Error occured
        Err(WritePactFileErr::IOError) =>
            Ok((atoms::error(), atoms::io_error()).encode(env)),
        /// No mock server was running on the port
        Err(WritePactFileErr::NoMockServer) =>
            Ok((atoms::error(), atoms::no_mock_server_running_on_port()).encode(env))
    }
}

fn cleanup_mock_server_call<'a>(env: NifEnv<'a>, args: &[NifTerm<'a>]) -> NifResult<NifTerm<'a>> {
    let port: i32 = try!(args[0].decode());

    Ok((atoms::ok(), shutdown_mock_server_by_port(port)).encode(env))
}

<commit_msg>Removed Rust compile warnings<commit_after>#[macro_use] extern crate rustler;

// Disabled for now, but still
// wondering why rustler generated this in the first place
// #[macro_use] extern crate rustler_codegen;

#[macro_use] extern crate lazy_static;
extern crate pact_mock_server;
extern crate libc;

use rustler::{NifEnv, NifTerm, NifResult, NifEncoder};
use pact_mock_server::create_mock_server;
use pact_mock_server::MockServerError;
use pact_mock_server::mock_server_mismatches;
use pact_mock_server::mock_server_matched;
use pact_mock_server::write_pact_file;
use pact_mock_server::WritePactFileErr;
use pact_mock_server::shutdown_mock_server_by_port;
mod atoms {
    rustler_atoms! {
        atom ok;
        atom error;
        atom mock_server_failed_to_start;
        atom invalid_pact_json;
        atom io_error;
        atom no_mock_server_running_on_port;
        //atom __true__ = "true";
        //atom __false__ = "false";
    }
}

rustler_export_nifs! {
    "Elixir.PactElixir.RustPactMockServerFacade",
    [
        ("create_mock_server", 2, create_mock_server_call),
        ("mock_server_mismatches", 1, mock_server_mismatches_call),
        ("mock_server_matched", 1, mock_server_matched_call),
        ("write_pact_file", 2, write_pact_file_call),
        ("cleanup_mock_server", 1, cleanup_mock_server_call)
    ],
    None
}

fn create_mock_server_call<'a>(env: NifEnv<'a>, args: &[NifTerm<'a>]) -> NifResult<NifTerm<'a>> {
    let pact_json: &str = try!(args[0].decode());
    let port_arg: i32 = try!(args[1].decode());

    match create_mock_server(pact_json, port_arg) {
        Ok(port) =>
            Ok((atoms::ok(), port).encode(env)),
        Err(MockServerError::MockServerFailedToStart) =>
            Ok((atoms::error(), atoms::mock_server_failed_to_start()).encode(env)),
        Err(MockServerError::InvalidPactJson) =>
            Ok((atoms::error(), atoms::invalid_pact_json()).encode(env))
    }
}

fn mock_server_mismatches_call<'a>(env: NifEnv<'a>, args: &[NifTerm<'a>]) -> NifResult<NifTerm<'a>> {
    let port: i32 = try!(args[0].decode());
    // TODO: This works only because mock_server_mismatches returns a string now:
    // Calling to_string() on json!(mismatches) in pact-reference/rust/pact_mock_server/src/lib.rs:657
    Ok((atoms::ok(), mock_server_mismatches(port)).encode(env))
}

fn mock_server_matched_call<'a>(env: NifEnv<'a>, args: &[NifTerm<'a>]) -> NifResult<NifTerm<'a>> {
    let port: i32 = try!(args[0].decode());

    let matched: bool = mock_server_matched(port);

    Ok((atoms::ok(), matched).encode(env))
}

fn write_pact_file_call<'a>(env: NifEnv<'a>, args: &[NifTerm<'a>]) -> NifResult<NifTerm<'a>> {
    let port: i32 = try!(args[0].decode());
    let dir_path: String = try!(args[1].decode());

    match write_pact_file(port, Some(dir_path)) {
        Ok(_result) =>
            Ok((atoms::ok()).encode(env)),
        Err(WritePactFileErr::IOError) =>
            Ok((atoms::error(), atoms::io_error()).encode(env)),
        Err(WritePactFileErr::NoMockServer) =>
            Ok((atoms::error(), atoms::no_mock_server_running_on_port()).encode(env))
    }
}

fn cleanup_mock_server_call<'a>(env: NifEnv<'a>, args: &[NifTerm<'a>]) -> NifResult<NifTerm<'a>> {
    let port: i32 = try!(args[0].decode());

    Ok((atoms::ok(), shutdown_mock_server_by_port(port)).encode(env))
}

<|endoftext|>


<commit_before>#![crate_id(name="uutils", vers="1.0.0", author="Michael Gehring")]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Michael Gehring <mg@ebfe.org>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;

extern crate base64;
extern crate basename;
extern crate cat;
extern crate chroot;
extern crate cksum;
extern crate comm;
extern crate cp;
extern crate dirname;
extern crate du;
extern crate echo;
extern crate env;
extern crate factor;
extern crate fmt;
extern crate fold;
extern crate groups;
extern crate head;
extern crate hostid;
extern crate hostname;
extern crate id;
extern crate kill;
extern crate link;
extern crate logname;
extern crate hashsum;
extern crate mkdir;
extern crate mkfifo;
extern crate nl;
extern crate paste;
extern crate printenv;
extern crate pwd;
extern crate rm;
extern crate rmdir;
extern crate seq;
extern crate sleep;
extern crate sum;
extern crate uusync;
extern crate tac;
extern crate tail;
extern crate tee;
extern crate touch;
extern crate tr;
extern crate truncate;
extern crate tty;
extern crate uname;
extern crate unlink;
extern crate uptime;
extern crate users;
extern crate wc;
extern crate whoami;
extern crate yes;

use std::os;
use std::collections::hashmap::HashMap;

static NAME: &'static str = "uutils";
static VERSION: &'static str = "1.0.0";

fn util_map() -> HashMap<&str, fn(Vec<String>) -> int> {
    fn uutrue(_: Vec<String>) -> int { 0 }
    fn uufalse(_: Vec<String>) -> int { 1 }

    let mut map = HashMap::new();
    map.insert("base64", base64::uumain);
    map.insert("basename", basename::uumain);
    map.insert("cat", cat::uumain);
    map.insert("chroot", chroot::uumain);
    map.insert("cksum", cksum::uumain);
    map.insert("comm", comm::uumain);
    map.insert("cp", cp::uumain);
    map.insert("dirname", dirname::uumain);
    map.insert("du", du::uumain);
    map.insert("echo", echo::uumain);
    map.insert("env", env::uumain);
    map.insert("factor", factor::uumain);
    map.insert("false", uufalse);
    map.insert("fmt", fmt::uumain);
    map.insert("fold", fold::uumain);
    map.insert("groups", groups::uumain);
    map.insert("head", head::uumain);
    map.insert("hostid", hostid::uumain);
    map.insert("hostname", hostname::uumain);
    map.insert("id", id::uumain);
    map.insert("kill", kill::uumain);
    map.insert("link", link::uumain);
    map.insert("logname", logname::uumain);
    map.insert("md5sum", hashsum::uumain);
    map.insert("sha1sum", hashsum::uumain);
    map.insert("sha224sum", hashsum::uumain);
    map.insert("sha256sum", hashsum::uumain);
    map.insert("sha384sum", hashsum::uumain);
    map.insert("sha512sum", hashsum::uumain);
    map.insert("mkdir", mkdir::uumain);
    map.insert("mkfifo", mkfifo::uumain);
    map.insert("nl", nl::uumain);
    map.insert("paste", paste::uumain);
    map.insert("printenv", printenv::uumain);
    map.insert("pwd", pwd::uumain);
    map.insert("rm", rm::uumain);
    map.insert("rmdir", rmdir::uumain);
    map.insert("seq", seq::uumain);
    map.insert("sleep", sleep::uumain);
    map.insert("sum", sum::uumain);
    map.insert("sync", uusync::uumain);
    map.insert("tac", tac::uumain);
    map.insert("tail", tail::uumain);
    map.insert("tee", tee::uumain);
    map.insert("touch", touch::uumain);
    map.insert("tr", tr::uumain);
    map.insert("true", uutrue);
    map.insert("truncate", truncate::uumain);
    map.insert("tty", tty::uumain);
    map.insert("uname", uname::uumain);
    map.insert("unlink", unlink::uumain);
    map.insert("uptime", uptime::uumain);
    map.insert("users", users::uumain);
    map.insert("wc", wc::uumain);
    map.insert("whoami", whoami::uumain);
    map.insert("yes", yes::uumain);
    map
}

fn usage(cmap: &HashMap<&str, fn(Vec<String>) -> int>) {
    println!("{} {}", NAME, VERSION);
    println!("");
    println!("Usage:");
    println!("  {} [util [arguments...]", NAME);
    println!("Currently defined functions:");
    let mut utils: Vec<&str> = cmap.keys().map(|&s| s).collect();
    utils.sort();
    for util in utils.iter() {
        println!("\t{}", util);
    }
    println!("");
}

fn main() {
    let umap = util_map();
    let mut args = os::args();

    // try binary name as util name.
    let binary = Path::new(args.get(0).as_slice());
    let binary_as_util = binary.filename_str().unwrap();
    if umap.contains_key(&binary_as_util) {
        let &uumain = umap.get(&binary_as_util);
        os::set_exit_status(uumain(args));
        return
    } else if binary_as_util.starts_with("uutils")
        || binary_as_util.starts_with("busybox") {
            // uutils can be called as either "uutils", "busybox"
            // "uutils-suffix" or "busybox-suffix". Not sure
            // what busybox uses the -suffix pattern for.
    } else {
        println!("{}: applet not found", binary_as_util);
        os::set_exit_status(1);
        return
    }

    // try first arg as util name.
    if args.len() >= 2 {
        args.shift();
        let util = args.get(0).as_slice();
        if umap.contains_key(&util) {
            let &uumain = umap.get(&util);
            os::set_exit_status(uumain(args.clone()));
            return
        } else if args.get(0).as_slice() == "--help" {
            // see if they want help on a specific util
            if args.len() >= 2 {
                let util = args.get(1).as_slice();
                if umap.contains_key(&util) {
                    let &uumain = umap.get(&util);
                    os::set_exit_status(uumain(vec!["--help".to_string()]));
                    return
                } else {
                    println!("{}: applet not found", util);
                    os::set_exit_status(1);
                    return
                }
            }
            usage(&umap);
            os::set_exit_status(0);
            return
        } else {
            println!("{}: applet not found", util);
            os::set_exit_status(1);
            return
        }
    } else {
        // no arguments provided
        usage(&umap);
        os::set_exit_status(0);
        return
    }
}
<commit_msg>Added nohup to uutils<commit_after>#![crate_id(name="uutils", vers="1.0.0", author="Michael Gehring")]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Michael Gehring <mg@ebfe.org>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;

extern crate base64;
extern crate basename;
extern crate cat;
extern crate chroot;
extern crate cksum;
extern crate comm;
extern crate cp;
extern crate dirname;
extern crate du;
extern crate echo;
extern crate env;
extern crate factor;
extern crate fmt;
extern crate fold;
extern crate groups;
extern crate head;
extern crate hostid;
extern crate hostname;
extern crate id;
extern crate kill;
extern crate link;
extern crate logname;
extern crate hashsum;
extern crate mkdir;
extern crate mkfifo;
extern crate nl;
extern crate nohup;
extern crate paste;
extern crate printenv;
extern crate pwd;
extern crate rm;
extern crate rmdir;
extern crate seq;
extern crate sleep;
extern crate sum;
extern crate uusync;
extern crate tac;
extern crate tail;
extern crate tee;
extern crate touch;
extern crate tr;
extern crate truncate;
extern crate tty;
extern crate uname;
extern crate unlink;
extern crate uptime;
extern crate users;
extern crate wc;
extern crate whoami;
extern crate yes;

use std::os;
use std::collections::hashmap::HashMap;

static NAME: &'static str = "uutils";
static VERSION: &'static str = "1.0.0";

fn util_map() -> HashMap<&str, fn(Vec<String>) -> int> {
    fn uutrue(_: Vec<String>) -> int { 0 }
    fn uufalse(_: Vec<String>) -> int { 1 }

    let mut map = HashMap::new();
    map.insert("base64", base64::uumain);
    map.insert("basename", basename::uumain);
    map.insert("cat", cat::uumain);
    map.insert("chroot", chroot::uumain);
    map.insert("cksum", cksum::uumain);
    map.insert("comm", comm::uumain);
    map.insert("cp", cp::uumain);
    map.insert("dirname", dirname::uumain);
    map.insert("du", du::uumain);
    map.insert("echo", echo::uumain);
    map.insert("env", env::uumain);
    map.insert("factor", factor::uumain);
    map.insert("false", uufalse);
    map.insert("fmt", fmt::uumain);
    map.insert("fold", fold::uumain);
    map.insert("groups", groups::uumain);
    map.insert("head", head::uumain);
    map.insert("hostid", hostid::uumain);
    map.insert("hostname", hostname::uumain);
    map.insert("id", id::uumain);
    map.insert("kill", kill::uumain);
    map.insert("link", link::uumain);
    map.insert("logname", logname::uumain);
    map.insert("md5sum", hashsum::uumain);
    map.insert("sha1sum", hashsum::uumain);
    map.insert("sha224sum", hashsum::uumain);
    map.insert("sha256sum", hashsum::uumain);
    map.insert("sha384sum", hashsum::uumain);
    map.insert("sha512sum", hashsum::uumain);
    map.insert("mkdir", mkdir::uumain);
    map.insert("mkfifo", mkfifo::uumain);
    map.insert("nl", nl::uumain);
    map.insert("nohup", nohup::uumain);
    map.insert("paste", paste::uumain);
    map.insert("printenv", printenv::uumain);
    map.insert("pwd", pwd::uumain);
    map.insert("rm", rm::uumain);
    map.insert("rmdir", rmdir::uumain);
    map.insert("seq", seq::uumain);
    map.insert("sleep", sleep::uumain);
    map.insert("sum", sum::uumain);
    map.insert("sync", uusync::uumain);
    map.insert("tac", tac::uumain);
    map.insert("tail", tail::uumain);
    map.insert("tee", tee::uumain);
    map.insert("touch", touch::uumain);
    map.insert("tr", tr::uumain);
    map.insert("true", uutrue);
    map.insert("truncate", truncate::uumain);
    map.insert("tty", tty::uumain);
    map.insert("uname", uname::uumain);
    map.insert("unlink", unlink::uumain);
    map.insert("uptime", uptime::uumain);
    map.insert("users", users::uumain);
    map.insert("wc", wc::uumain);
    map.insert("whoami", whoami::uumain);
    map.insert("yes", yes::uumain);
    map
}

fn usage(cmap: &HashMap<&str, fn(Vec<String>) -> int>) {
    println!("{} {}", NAME, VERSION);
    println!("");
    println!("Usage:");
    println!("  {} [util [arguments...]", NAME);
    println!("Currently defined functions:");
    let mut utils: Vec<&str> = cmap.keys().map(|&s| s).collect();
    utils.sort();
    for util in utils.iter() {
        println!("\t{}", util);
    }
    println!("");
}

fn main() {
    let umap = util_map();
    let mut args = os::args();

    // try binary name as util name.
    let binary = Path::new(args.get(0).as_slice());
    let binary_as_util = binary.filename_str().unwrap();
    if umap.contains_key(&binary_as_util) {
        let &uumain = umap.get(&binary_as_util);
        os::set_exit_status(uumain(args));
        return
    } else if binary_as_util.starts_with("uutils")
        || binary_as_util.starts_with("busybox") {
            // uutils can be called as either "uutils", "busybox"
            // "uutils-suffix" or "busybox-suffix". Not sure
            // what busybox uses the -suffix pattern for.
    } else {
        println!("{}: applet not found", binary_as_util);
        os::set_exit_status(1);
        return
    }

    // try first arg as util name.
    if args.len() >= 2 {
        args.shift();
        let util = args.get(0).as_slice();
        if umap.contains_key(&util) {
            let &uumain = umap.get(&util);
            os::set_exit_status(uumain(args.clone()));
            return
        } else if args.get(0).as_slice() == "--help" {
            // see if they want help on a specific util
            if args.len() >= 2 {
                let util = args.get(1).as_slice();
                if umap.contains_key(&util) {
                    let &uumain = umap.get(&util);
                    os::set_exit_status(uumain(vec!["--help".to_string()]));
                    return
                } else {
                    println!("{}: applet not found", util);
                    os::set_exit_status(1);
                    return
                }
            }
            usage(&umap);
            os::set_exit_status(0);
            return
        } else {
            println!("{}: applet not found", util);
            os::set_exit_status(1);
            return
        }
    } else {
        // no arguments provided
        usage(&umap);
        os::set_exit_status(0);
        return
    }
}
<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!");
}
<commit_msg>happy new year 2017<commit_after>fn main() {
    println!("Happy New Year 2017");
}
<|endoftext|>


<commit_before>//! Workspace module for Xt.
//! Handles workspaces and their associated buffers.

// This file is part of Xt.

// This is the Xt text editor; it edits text.
// Copyright (C) 2016-2018  The Xt Developers

// This program is free software: you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.

// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see
// <http://www.gnu.org/licenses/>.

extern crate slog;

use logging::init_logger;
use server::buffer::Buffer;

/// Workspace struct
#[derive(Debug)]
pub struct Workspace {
    /// Human-readable name for workspace.
    pub hname: String,
    /// Logger instance for workspace.
    /// Derived from root Logger.
    pub logger: slog::Logger,
    /// Vector of Buffer structs.
    pub buffers: Vec<Buffer>,
}

impl Workspace {
    ///
    pub fn new(hname: String) -> Workspace {
        let logger = init_logger().new(o!("workspace" => hname.clone()));
        Workspace {
            hname: hname,
            logger: logger,
            buffers: Vec::new(),
        }
    }
}
<commit_msg>server/workspace: Use <Into<String>><commit_after>//! Workspace module for Xt.
//! Handles workspaces and their associated buffers.

// This file is part of Xt.

// This is the Xt text editor; it edits text.
// Copyright (C) 2016-2018  The Xt Developers

// This program is free software: you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.

// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see
// <http://www.gnu.org/licenses/>.

extern crate slog;

use logging::init_logger;
use server::buffer::Buffer;

/// Workspace struct
#[derive(Debug)]
pub struct Workspace {
    /// Human-readable name for workspace.
    pub hname: String,
    /// Logger instance for workspace.
    /// Derived from root Logger.
    pub logger: slog::Logger,
    /// Vector of Buffer structs.
    pub buffers: Vec<Buffer>,
}

impl Workspace {
    /// Create a new workspace.
    pub fn new<S: Into<String>>(hname: S) -> Workspace {
        let hname = hname.into();
        let logger = init_logger().new(o!("workspace" => hname.clone()));

        Workspace {
            hname: hname,
            logger: logger,
            buffers: Vec::new(),
        }
    }
}
<|endoftext|>