<commit_before>//! Mutex and RwLock types that do not poison themselves.
//!
//! These types expose identical APIs to the standard library `Mutex` and
//! `RwLock` except that they do not return `PoisonError`s.
#![doc(html_root_url="https://sfackler.github.io/rust-antidote/doc/v0.1.0")]
#![warn(missing_docs)]

use std::error::Error;
use std::fmt;
use std::ops::{Deref, DerefMut};
use std::sync;

/// Like `std::sync::Mutex` except that it does not poison itself.
pub struct Mutex<T: ?Sized>(sync::Mutex<T>);

impl<T> Mutex<T> {
    /// Like `std::sync::Mutex::new`.
    #[inline]
    pub fn new(t: T) -> Mutex<T> {
        Mutex(sync::Mutex::new(t))
    }

    /// Like `std::sync::Mutex::into_inner`.
    #[inline]
    pub fn into_inner(self) -> T {
        self.0.into_inner().unwrap_or_else(|e| e.into_inner())
    }
}

impl<T: ?Sized> Mutex<T> {
    /// Like `std::sync::Mutex::lock`.
    #[inline]
    pub fn lock<'a>(&'a self) -> MutexGuard<'a, T> {
        MutexGuard(self.0.lock().unwrap_or_else(|e| e.into_inner()))
    }

    /// Like `std::sync::Mutex::try_lock`.
    #[inline]
    pub fn try_lock<'a>(&'a self) -> TryLockResult<MutexGuard<'a, T>> {
        match self.0.try_lock() {
            Ok(t) => Ok(MutexGuard(t)),
            Err(sync::TryLockError::Poisoned(e)) => Ok(MutexGuard(e.into_inner())),
            Err(sync::TryLockError::WouldBlock) => Err(TryLockError(())),
        }
    }

    /// Like `std::sync::Mutex::get_mut`.
    #[inline]
    pub fn get_mut(&mut self) -> &mut T {
        self.0.get_mut().unwrap_or_else(|e| e.into_inner())
    }
}

/// Like `std::sync::MutexGuard`.
#[must_use]
pub struct MutexGuard<'a, T: ?Sized + 'a>(sync::MutexGuard<'a, T>);

impl<'a, T: ?Sized> Deref for MutexGuard<'a, T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &T {
        self.0.deref()
    }
}

impl<'a, T: ?Sized> DerefMut for MutexGuard<'a, T> {
    #[inline]
    fn deref_mut(&mut self) -> &mut T {
        self.0.deref_mut()
    }
}

/// Like `std::sync::TryLockResult`.
pub type TryLockResult<T> = Result<T, TryLockError>;

/// Like `std::sync::TryLockError`.
#[derive(Debug)]
pub struct TryLockError(());

impl fmt::Display for TryLockError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.write_str(self.description())
    }
}

impl Error for TryLockError {
    fn description(&self) -> &str {
        "try_lock failed because the operation would block"
    }
}

/// Like `std::sync::RwLock` except that it does not poison itself.
pub struct RwLock<T: ?Sized>(sync::RwLock<T>);

impl<T> RwLock<T> {
    /// Like `std::sync::RwLock::new`.
    #[inline]
    pub fn new(t: T) -> RwLock<T> {
        RwLock(sync::RwLock::new(t))
    }

    /// Like `std::sync::RwLock::into_inner`.
    #[inline]
    pub fn into_inner(self) -> T where T: Sized {
        self.0.into_inner().unwrap_or_else(|e| e.into_inner())
    }
}

impl<T: ?Sized> RwLock<T> {
    /// Like `std::sync::RwLock::read`.
    #[inline]
    pub fn read<'a>(&'a self) -> RwLockReadGuard<'a, T> {
        RwLockReadGuard(self.0.read().unwrap_or_else(|e| e.into_inner()))
    }

    /// Like `std::sync::RwLock::try_read`.
    #[inline]
    pub fn try_read<'a>(&'a self) -> TryLockResult<RwLockReadGuard<'a, T>> {
        match self.0.try_read() {
            Ok(t) => Ok(RwLockReadGuard(t)),
            Err(sync::TryLockError::Poisoned(e)) => Ok(RwLockReadGuard(e.into_inner())),
            Err(sync::TryLockError::WouldBlock) => Err(TryLockError(())),
        }
    }

    /// Like `std::sync::RwLock::write`.
    #[inline]
    pub fn write<'a>(&'a self) -> RwLockWriteGuard<'a, T> {
        RwLockWriteGuard(self.0.write().unwrap_or_else(|e| e.into_inner()))
    }

    /// Like `std::sync::RwLock::try_write`.
    #[inline]
    pub fn try_write<'a>(&'a self) -> TryLockResult<RwLockWriteGuard<'a, T>> {
        match self.0.try_write() {
            Ok(t) => Ok(RwLockWriteGuard(t)),
            Err(sync::TryLockError::Poisoned(e)) => Ok(RwLockWriteGuard(e.into_inner())),
            Err(sync::TryLockError::WouldBlock) => Err(TryLockError(())),
        }
    }

    /// Like `std::sync::RwLock::get_mut`.
    #[inline]
    pub fn get_mut(&mut self) -> &mut T {
        self.0.get_mut().unwrap_or_else(|e| e.into_inner())
    }
}

/// Like `std::sync::RwLockReadGuard`.
#[must_use]
pub struct RwLockReadGuard<'a, T: ?Sized + 'a>(sync::RwLockReadGuard<'a, T>);

impl<'a, T: ?Sized> Deref for RwLockReadGuard<'a, T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &T {
        self.0.deref()
    }
}

/// Like `std::sync::RwLockWriteGuard`.
#[must_use]
pub struct RwLockWriteGuard<'a, T: ?Sized + 'a>(sync::RwLockWriteGuard<'a, T>);

impl<'a, T: ?Sized> Deref for RwLockWriteGuard<'a, T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &T {
        self.0.deref()
    }
}

impl<'a, T: ?Sized> DerefMut for RwLockWriteGuard<'a, T> {
    #[inline]
    fn deref_mut(&mut self) -> &mut T {
        self.0.deref_mut()
    }
}
<commit_msg>Implement debug for Mutex and RwLock<commit_after>//! Mutex and RwLock types that do not poison themselves.
//!
//! These types expose identical APIs to the standard library `Mutex` and
//! `RwLock` except that they do not return `PoisonError`s.
#![doc(html_root_url="https://sfackler.github.io/rust-antidote/doc/v0.1.0")]
#![warn(missing_docs)]

use std::error::Error;
use std::fmt;
use std::ops::{Deref, DerefMut};
use std::sync;

/// Like `std::sync::Mutex` except that it does not poison itself.
pub struct Mutex<T: ?Sized>(sync::Mutex<T>);

impl<T: ?Sized + fmt::Debug> fmt::Debug for Mutex<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl<T> Mutex<T> {
    /// Like `std::sync::Mutex::new`.
    #[inline]
    pub fn new(t: T) -> Mutex<T> {
        Mutex(sync::Mutex::new(t))
    }

    /// Like `std::sync::Mutex::into_inner`.
    #[inline]
    pub fn into_inner(self) -> T {
        self.0.into_inner().unwrap_or_else(|e| e.into_inner())
    }
}

impl<T: ?Sized> Mutex<T> {
    /// Like `std::sync::Mutex::lock`.
    #[inline]
    pub fn lock<'a>(&'a self) -> MutexGuard<'a, T> {
        MutexGuard(self.0.lock().unwrap_or_else(|e| e.into_inner()))
    }

    /// Like `std::sync::Mutex::try_lock`.
    #[inline]
    pub fn try_lock<'a>(&'a self) -> TryLockResult<MutexGuard<'a, T>> {
        match self.0.try_lock() {
            Ok(t) => Ok(MutexGuard(t)),
            Err(sync::TryLockError::Poisoned(e)) => Ok(MutexGuard(e.into_inner())),
            Err(sync::TryLockError::WouldBlock) => Err(TryLockError(())),
        }
    }

    /// Like `std::sync::Mutex::get_mut`.
    #[inline]
    pub fn get_mut(&mut self) -> &mut T {
        self.0.get_mut().unwrap_or_else(|e| e.into_inner())
    }
}

/// Like `std::sync::MutexGuard`.
#[must_use]
pub struct MutexGuard<'a, T: ?Sized + 'a>(sync::MutexGuard<'a, T>);

impl<'a, T: ?Sized> Deref for MutexGuard<'a, T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &T {
        self.0.deref()
    }
}

impl<'a, T: ?Sized> DerefMut for MutexGuard<'a, T> {
    #[inline]
    fn deref_mut(&mut self) -> &mut T {
        self.0.deref_mut()
    }
}

/// Like `std::sync::TryLockResult`.
pub type TryLockResult<T> = Result<T, TryLockError>;

/// Like `std::sync::TryLockError`.
#[derive(Debug)]
pub struct TryLockError(());

impl fmt::Display for TryLockError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.write_str(self.description())
    }
}

impl Error for TryLockError {
    fn description(&self) -> &str {
        "try_lock failed because the operation would block"
    }
}

/// Like `std::sync::RwLock` except that it does not poison itself.
pub struct RwLock<T: ?Sized>(sync::RwLock<T>);

impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLock<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl<T> RwLock<T> {
    /// Like `std::sync::RwLock::new`.
    #[inline]
    pub fn new(t: T) -> RwLock<T> {
        RwLock(sync::RwLock::new(t))
    }

    /// Like `std::sync::RwLock::into_inner`.
    #[inline]
    pub fn into_inner(self) -> T where T: Sized {
        self.0.into_inner().unwrap_or_else(|e| e.into_inner())
    }
}

impl<T: ?Sized> RwLock<T> {
    /// Like `std::sync::RwLock::read`.
    #[inline]
    pub fn read<'a>(&'a self) -> RwLockReadGuard<'a, T> {
        RwLockReadGuard(self.0.read().unwrap_or_else(|e| e.into_inner()))
    }

    /// Like `std::sync::RwLock::try_read`.
    #[inline]
    pub fn try_read<'a>(&'a self) -> TryLockResult<RwLockReadGuard<'a, T>> {
        match self.0.try_read() {
            Ok(t) => Ok(RwLockReadGuard(t)),
            Err(sync::TryLockError::Poisoned(e)) => Ok(RwLockReadGuard(e.into_inner())),
            Err(sync::TryLockError::WouldBlock) => Err(TryLockError(())),
        }
    }

    /// Like `std::sync::RwLock::write`.
    #[inline]
    pub fn write<'a>(&'a self) -> RwLockWriteGuard<'a, T> {
        RwLockWriteGuard(self.0.write().unwrap_or_else(|e| e.into_inner()))
    }

    /// Like `std::sync::RwLock::try_write`.
    #[inline]
    pub fn try_write<'a>(&'a self) -> TryLockResult<RwLockWriteGuard<'a, T>> {
        match self.0.try_write() {
            Ok(t) => Ok(RwLockWriteGuard(t)),
            Err(sync::TryLockError::Poisoned(e)) => Ok(RwLockWriteGuard(e.into_inner())),
            Err(sync::TryLockError::WouldBlock) => Err(TryLockError(())),
        }
    }

    /// Like `std::sync::RwLock::get_mut`.
    #[inline]
    pub fn get_mut(&mut self) -> &mut T {
        self.0.get_mut().unwrap_or_else(|e| e.into_inner())
    }
}

/// Like `std::sync::RwLockReadGuard`.
#[must_use]
pub struct RwLockReadGuard<'a, T: ?Sized + 'a>(sync::RwLockReadGuard<'a, T>);

impl<'a, T: ?Sized> Deref for RwLockReadGuard<'a, T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &T {
        self.0.deref()
    }
}

/// Like `std::sync::RwLockWriteGuard`.
#[must_use]
pub struct RwLockWriteGuard<'a, T: ?Sized + 'a>(sync::RwLockWriteGuard<'a, T>);

impl<'a, T: ?Sized> Deref for RwLockWriteGuard<'a, T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &T {
        self.0.deref()
    }
}

impl<'a, T: ?Sized> DerefMut for RwLockWriteGuard<'a, T> {
    #[inline]
    fn deref_mut(&mut self) -> &mut T {
        self.0.deref_mut()
    }
}
<|endoftext|>


<commit_before>extern crate logi_lcd_sys as sys;

pub use sys::{
    LcdButton, LcdType, BitFlags,
    MONO_WIDTH, MONO_HEIGHT, MONO_BYTES_PER_PIXEL,
    COLOR_WIDTH, COLOR_HEIGHT, COLOR_BYTES_PER_PIXEL
};

use std::sync::atomic::{AtomicBool, Ordering, ATOMIC_BOOL_INIT};
use std::fmt::{Display, Formatter};
use std::error::Error;
use std::os::raw::c_int;

static INITIALIZED: AtomicBool = ATOMIC_BOOL_INIT;

pub struct Lcd {
    type_flags: BitFlags<LcdType>,
}

#[derive(Debug)]
pub enum LcdError {
    NotConnected,
    Initialization,
    MonoBackground,
    MonoText,
    ColorBackground,
    ColorTitle,
    ColorText,
    NullCharacter,
}

impl Error for LcdError {
    fn description(&self) -> &str {
        match *self {
            LcdError::NotConnected    => "LCD is not connected",
            LcdError::Initialization  => "A FFI call to LogiLcdInit() has failed",
            LcdError::MonoBackground  => "A FFI call to LogiLcdMonoSetBackground() has failed",
            LcdError::MonoText        => "A FFI call to LogiLcdMonoSetText() has failed",
            LcdError::ColorBackground => "A FFI call to LogiLcdColorSetBackground() has failed",
            LcdError::ColorTitle      => "A FFI call to LogiLcdColorSetTitle() has failed",
            LcdError::ColorText       => "A FFI call to LogiLcdColorSetText() has failed",
            LcdError::NullCharacter   => "Unexpected NULL character",
        }
    }
}

impl Display for LcdError {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        write!(f, "LcdError: {}", self.description())
    }
}

fn str_to_wchar(s: &str) -> Result<Vec<u16>, LcdError> {
    let mut v = s.encode_utf16().collect::<Vec<u16>>();

    if v.iter().any(|&val| val == 0) {
        return Err(LcdError::NullCharacter);
    }

    v.push(0);

    Ok(v)
}

impl Lcd {
    fn init(app_name: &str, type_flags: BitFlags<LcdType>) -> Result<Lcd, LcdError> {
        assert_eq!(INITIALIZED.swap(true, Ordering::SeqCst), false);
        let ws = str_to_wchar(app_name)?;

        let ret = unsafe {
            match sys::LogiLcdInit(ws.as_ptr(), type_flags.bits()) {
                true => {
                    match sys::LogiLcdIsConnected(type_flags.bits()) {
                        true => Ok(Lcd{type_flags: type_flags}),
                        false => Err(LcdError::NotConnected),
                    }
                },
                false => Err(LcdError::Initialization),
            }
        };

        if ret.is_err() {
            INITIALIZED.store(false, Ordering::SeqCst);
        }

        ret
    }

    /// Initialize and connect to a monochrome lcd device.
    ///
    /// ### Parameters:
    /// - app_name: The name of your applet.
    ///
    /// ### Panics
    /// Will panic if another lcd instance exits.
    ///
    pub fn init_mono(app_name: &str) -> Result<Lcd, LcdError>  {
        Self::init(app_name, LcdType::MONO.into())
    }

    /// Initialize and connect to a color lcd device.
    ///
    /// ### Parameters:
    /// - app_name: The name of your applet.
    ///
    /// ### Panics
    /// Will panic if another lcd instance exits.
    ///
    pub fn init_color(app_name: &str) -> Result<Lcd, LcdError>  {
        Self::init(app_name, LcdType::COLOR.into())
    }

    /// Initialize and connect to either a monochrome or color lcd device.
    ///
    /// ### Parameters:
    /// - app_name: The name of your applet.
    ///
    /// ### Panics
    /// Will panic if another lcd instance exits.
    ///
    pub fn init_either(app_name: &str) -> Result<Lcd, LcdError> {
        Self::init(app_name, LcdType::either())
    }

    /// Checks if the device is connected.
    ///
    /// ### Return value:
    /// If a device supporting the lcd type specified is found, it returns `true`. Otherwise `false`
    ///
    pub fn is_connected(&self) -> bool {
        unsafe {
            sys::LogiLcdIsConnected(self.type_flags.bits())
        }
    }

    /// Updates the lcd display.
    ///
    /// ### Notes:
    /// You have to call this function every frame of your main loop, to keep the lcd updated.
    ///
    pub fn update(&mut self) {
        unsafe {
            sys::LogiLcdUpdate();
        }
    }

    /// Checks if the buttons specified by the parameter are being pressed.
    ///
    /// ### Return value:
    /// If the button specified is being pressed it returns `true`. Otherwise `false`
    ///
    /// ### Notes:
    /// The button will be considered pressed only if your applet is the one currently in the foreground.
    ///
    pub fn is_mono_buttons_pressed(&self, buttons: BitFlags<LcdButton>) -> bool {
        assert!(!(self.type_flags | LcdType::MONO).is_empty());

        unsafe {
            sys::LogiLcdIsButtonPressed((buttons & LcdButton::mono()).bits())
        }
    }

    /// Sets the specified image as background for the monochrome lcd device.
    ///
    /// ### Parameters:
    /// - bytemap: The image data is organized as a rectangular area, 160 bytes wide and 43
    /// bytes high. Despite the display being monochrome, 8 bits per pixel are used
    /// here for simple manipulation of individual pixels. The SDK will turn on the
    /// pixel on the screen if the value assigned to that byte is >= 128, it will
    /// remain off if the value is < 128.
    ///
    /// ### Panics
    /// Will panic if bytemaps size is not 160x43bytes long.
    ///
    pub fn set_mono_background(&mut self, bytemap: &[u8]) -> Result<(), LcdError> {
        assert!(!(self.type_flags | LcdType::MONO).is_empty());
        assert_eq!(bytemap.len(), MONO_WIDTH * MONO_HEIGHT);

        unsafe {
            match sys::LogiLcdMonoSetBackground(bytemap.as_ptr()) {
                true => Ok(()),
                false => Err(LcdError::MonoBackground),
            }
        }
    }

    /// Sets the specified text in the requested line on the monochrome lcd device.
    ///
    /// ### Parameters:
    /// - line_number: The line on the screen you want the text to appear. The monochrome lcd display
    ///   has 4 lines, so this parameter can be any number from 0 to 3.
    /// - text: Defines the text you want to display
    ///
    /// ### Panics
    /// Will panic if line_number larger than or equal to 4.
    ///
    pub fn set_mono_text(&mut self, line_number: usize, text: &str) -> Result<(), LcdError> {
        assert!(!(self.type_flags | LcdType::MONO).is_empty());

        let ws = str_to_wchar(text)?;
        assert!(line_number < 4);

        unsafe {
            match sys::LogiLcdMonoSetText(line_number as c_int, ws.as_ptr()) {
                true => Ok(()),
                false => Err(LcdError::MonoText),
            }
        }
    }

    /// Checks if the buttons specified by the parameter are being pressed.
    ///
    /// ### Return value:
    /// If the button specified is being pressed it returns `true`. Otherwise `false`
    ///
    /// ### Notes:
    /// The button will be considered pressed only if your applet is the one currently in the foreground.
    ///
    pub fn is_color_buttons_pressed(&self, buttons: BitFlags<LcdButton>) -> bool {
        assert!(!(self.type_flags | LcdType::COLOR).is_empty());

        unsafe {
            sys::LogiLcdIsButtonPressed((buttons & LcdButton::color()).bits())
        }
    }

    pub fn set_color_background(&mut self, bitmap: &[u8]) -> Result<(), LcdError> {
        assert!(!(self.type_flags | LcdType::COLOR).is_empty());
        assert_eq!(bitmap.len(), COLOR_WIDTH * COLOR_HEIGHT * COLOR_BYTES_PER_PIXEL);

        unsafe {
            match sys::LogiLcdColorSetBackground(bitmap.as_ptr()) {
                true => Ok(()),
                false => Err(LcdError::ColorBackground),
            }
        }
    }

    pub fn set_color_title(&mut self, text: &str, red: u8, green: u8, blue: u8)
        -> Result<(), LcdError>
    {
        assert!(!(self.type_flags | LcdType::COLOR).is_empty());
        let ws = str_to_wchar(text)?;

        unsafe {
            match sys::LogiLcdColorSetTitle(ws.as_ptr(), red as c_int,
                green as c_int, blue as c_int)
            {
                true  => Ok(()),
                false => Err(LcdError::ColorTitle),
            }
        }
    }

    pub fn set_color_text(&mut self, line_number: usize, text: &str,
        red: u8, green: u8, blue: u8) -> Result<(), LcdError>
    {
        assert!(!(self.type_flags | LcdType::COLOR).is_empty());

        let ws = str_to_wchar(text)?;
        assert!(line_number < 8);

        unsafe {
            match sys::LogiLcdColorSetText(line_number as c_int,
                ws.as_ptr(), red as c_int, green as c_int, blue as c_int)
            {
                true => Ok(()),
                false => Err(LcdError::ColorText),
            }
        }
    }
}

impl Drop for Lcd {
    /// Kills the applet and frees memory used by the SDK
    fn drop(&mut self) {
        unsafe {
            sys::LogiLcdShutdown();
        }
        INITIALIZED.store(false, Ordering::SeqCst);
    }
}
<commit_msg>Add crate documentation<commit_after>#![warn(missing_docs)]

//! # logi-lcd
//! logi-lcd provides binding for the [Logitech Gaming LCD/Gamepanel SDK]
//! (http://gaming.logitech.com/en-us/developers).
//!
//! ## Overview
//! The Logitech LCD/GamePanel SDK introduces second screen capability that allows GamePanel-enabled
//! Logitech gaming keyboards to display in-game info, system statistics, and more.
//! The SDK enables integration of GamePanel functionality within your code.
//!
//! ## Lcd Interface
//! The SDK interface is implemented by the [Lcd](struct.Lcd.html) struct. Create a new
//! [Lcd](struct.Lcd.html) at start of program. Update it with the provided methods.
//! The [Lcd](struct.Lcd.html) will automatically disconnect when the [Lcd](struct.Lcd.html)
//! goes out of scope.
//!
//! ## Example
//! ```
//! let mut lcd = logi_lcd::Lcd::init_mono("My Glorious App").unwrap();
//!
//! lcd.set_mono_text(0, "Hello World!").unwrap();
//!
//! lcd.update();
//! ```
//!
//! ## Error Handling
//!
//! ## Do’s and Don’ts
//! These are a few guidelines that may help you implement 'better' support in your application:
//!
//! - For color use a splash screen when the application starts up.
//! - For color have a nice background image to take full advantage of the RGBA LCD.
//! - Don’t just display information on the LCD that is already being displayed on main view of your
//! application. Instead display information he can only see when hitting tab or going to the menu.
//! - Use the LCD to unclutter the main view.
//! - Write support for both the color and monochrome LCDs, as both have an important user base.
//! - Text displayed on the LCD is fixed-width, so you can easily create multiple columns that
//! always align correctly.
//! - If you want to create custom screens, draw your own bitmaps and update the background LCD
//! bitmap up to 60 times/second.
//! - Use the buttons to create multiple pages or add functionality to the LCD.
//!

extern crate logi_lcd_sys as sys;

pub use sys::{
    LcdButton, LcdType, BitFlags,
    MONO_WIDTH, MONO_HEIGHT, MONO_BYTES_PER_PIXEL,
    COLOR_WIDTH, COLOR_HEIGHT, COLOR_BYTES_PER_PIXEL
};

use std::sync::atomic::{AtomicBool, Ordering, ATOMIC_BOOL_INIT};
use std::fmt::{Display, Formatter};
use std::error::Error;
use std::os::raw::c_int;

static INITIALIZED: AtomicBool = ATOMIC_BOOL_INIT;

pub struct Lcd {
    type_flags: BitFlags<LcdType>,
}

#[derive(Debug)]
pub enum LcdError {
    NotConnected,
    Initialization,
    MonoBackground,
    MonoText,
    ColorBackground,
    ColorTitle,
    ColorText,
    NullCharacter,
}

impl Error for LcdError {
    fn description(&self) -> &str {
        match *self {
            LcdError::NotConnected    => "LCD is not connected",
            LcdError::Initialization  => "A FFI call to LogiLcdInit() has failed",
            LcdError::MonoBackground  => "A FFI call to LogiLcdMonoSetBackground() has failed",
            LcdError::MonoText        => "A FFI call to LogiLcdMonoSetText() has failed",
            LcdError::ColorBackground => "A FFI call to LogiLcdColorSetBackground() has failed",
            LcdError::ColorTitle      => "A FFI call to LogiLcdColorSetTitle() has failed",
            LcdError::ColorText       => "A FFI call to LogiLcdColorSetText() has failed",
            LcdError::NullCharacter   => "Unexpected NULL character",
        }
    }
}

impl Display for LcdError {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        write!(f, "LcdError: {}", self.description())
    }
}

fn str_to_wchar(s: &str) -> Result<Vec<u16>, LcdError> {
    let mut v = s.encode_utf16().collect::<Vec<u16>>();

    if v.iter().any(|&val| val == 0) {
        return Err(LcdError::NullCharacter);
    }

    v.push(0);

    Ok(v)
}

impl Lcd {
    fn init(app_name: &str, type_flags: BitFlags<LcdType>) -> Result<Lcd, LcdError> {
        assert_eq!(INITIALIZED.swap(true, Ordering::SeqCst), false);
        let ws = str_to_wchar(app_name)?;

        let ret = unsafe {
            match sys::LogiLcdInit(ws.as_ptr(), type_flags.bits()) {
                true => {
                    match sys::LogiLcdIsConnected(type_flags.bits()) {
                        true => Ok(Lcd{type_flags: type_flags}),
                        false => Err(LcdError::NotConnected),
                    }
                },
                false => Err(LcdError::Initialization),
            }
        };

        if ret.is_err() {
            INITIALIZED.store(false, Ordering::SeqCst);
        }

        ret
    }

    /// Initialize and connect to a monochrome lcd device.
    ///
    /// ### Parameters:
    /// - app_name: The name of your applet.
    ///
    /// ### Panics
    /// Will panic if another lcd instance exits.
    ///
    pub fn init_mono(app_name: &str) -> Result<Lcd, LcdError>  {
        Self::init(app_name, LcdType::MONO.into())
    }

    /// Initialize and connect to a color lcd device.
    ///
    /// ### Parameters:
    /// - app_name: The name of your applet.
    ///
    /// ### Panics
    /// Will panic if another lcd instance exits.
    ///
    pub fn init_color(app_name: &str) -> Result<Lcd, LcdError>  {
        Self::init(app_name, LcdType::COLOR.into())
    }

    /// Initialize and connect to either a monochrome or color lcd device.
    ///
    /// ### Parameters:
    /// - app_name: The name of your applet.
    ///
    /// ### Panics
    /// Will panic if another lcd instance exits.
    ///
    pub fn init_either(app_name: &str) -> Result<Lcd, LcdError> {
        Self::init(app_name, LcdType::either())
    }

    /// Checks if the device is connected.
    ///
    /// ### Return value:
    /// If a device supporting the lcd type specified is found, it returns `true`. Otherwise `false`
    ///
    pub fn is_connected(&self) -> bool {
        unsafe {
            sys::LogiLcdIsConnected(self.type_flags.bits())
        }
    }

    /// Updates the lcd display.
    ///
    /// ### Notes:
    /// You have to call this function every frame of your main loop, to keep the lcd updated.
    ///
    pub fn update(&mut self) {
        unsafe {
            sys::LogiLcdUpdate();
        }
    }

    /// Checks if the buttons specified by the parameter are being pressed.
    ///
    /// ### Return value:
    /// If the button specified is being pressed it returns `true`. Otherwise `false`
    ///
    /// ### Notes:
    /// The button will be considered pressed only if your applet is the one currently in the foreground.
    ///
    pub fn is_mono_buttons_pressed(&self, buttons: BitFlags<LcdButton>) -> bool {
        assert!(!(self.type_flags | LcdType::MONO).is_empty());

        unsafe {
            sys::LogiLcdIsButtonPressed((buttons & LcdButton::mono()).bits())
        }
    }

    /// Sets the specified image as background for the monochrome lcd device.
    ///
    /// ### Parameters:
    /// - bytemap: The image data is organized as a rectangular area, 160 bytes wide and 43
    /// bytes high. Despite the display being monochrome, 8 bits per pixel are used
    /// here for simple manipulation of individual pixels. The SDK will turn on the
    /// pixel on the screen if the value assigned to that byte is >= 128, it will
    /// remain off if the value is < 128.
    ///
    /// ### Panics
    /// Will panic if bytemaps size is not 160x43bytes long.
    ///
    pub fn set_mono_background(&mut self, bytemap: &[u8]) -> Result<(), LcdError> {
        assert!(!(self.type_flags | LcdType::MONO).is_empty());
        assert_eq!(bytemap.len(), MONO_WIDTH * MONO_HEIGHT);

        unsafe {
            match sys::LogiLcdMonoSetBackground(bytemap.as_ptr()) {
                true => Ok(()),
                false => Err(LcdError::MonoBackground),
            }
        }
    }

    /// Sets the specified text in the requested line on the monochrome lcd device.
    ///
    /// ### Parameters:
    /// - line_number: The line on the screen you want the text to appear. The monochrome lcd display
    ///   has 4 lines, so this parameter can be any number from 0 to 3.
    /// - text: Defines the text you want to display
    ///
    /// ### Panics
    /// Will panic if line_number larger than or equal to 4.
    ///
    pub fn set_mono_text(&mut self, line_number: usize, text: &str) -> Result<(), LcdError> {
        assert!(!(self.type_flags | LcdType::MONO).is_empty());

        let ws = str_to_wchar(text)?;
        assert!(line_number < 4);

        unsafe {
            match sys::LogiLcdMonoSetText(line_number as c_int, ws.as_ptr()) {
                true => Ok(()),
                false => Err(LcdError::MonoText),
            }
        }
    }

    /// Checks if the buttons specified by the parameter are being pressed.
    ///
    /// ### Return value:
    /// If the button specified is being pressed it returns `true`. Otherwise `false`
    ///
    /// ### Notes:
    /// The button will be considered pressed only if your applet is the one currently in the foreground.
    ///
    pub fn is_color_buttons_pressed(&self, buttons: BitFlags<LcdButton>) -> bool {
        assert!(!(self.type_flags | LcdType::COLOR).is_empty());

        unsafe {
            sys::LogiLcdIsButtonPressed((buttons & LcdButton::color()).bits())
        }
    }

    pub fn set_color_background(&mut self, bitmap: &[u8]) -> Result<(), LcdError> {
        assert!(!(self.type_flags | LcdType::COLOR).is_empty());
        assert_eq!(bitmap.len(), COLOR_WIDTH * COLOR_HEIGHT * COLOR_BYTES_PER_PIXEL);

        unsafe {
            match sys::LogiLcdColorSetBackground(bitmap.as_ptr()) {
                true => Ok(()),
                false => Err(LcdError::ColorBackground),
            }
        }
    }

    pub fn set_color_title(&mut self, text: &str, red: u8, green: u8, blue: u8)
        -> Result<(), LcdError>
    {
        assert!(!(self.type_flags | LcdType::COLOR).is_empty());
        let ws = str_to_wchar(text)?;

        unsafe {
            match sys::LogiLcdColorSetTitle(ws.as_ptr(), red as c_int,
                green as c_int, blue as c_int)
            {
                true  => Ok(()),
                false => Err(LcdError::ColorTitle),
            }
        }
    }

    pub fn set_color_text(&mut self, line_number: usize, text: &str,
        red: u8, green: u8, blue: u8) -> Result<(), LcdError>
    {
        assert!(!(self.type_flags | LcdType::COLOR).is_empty());

        let ws = str_to_wchar(text)?;
        assert!(line_number < 8);

        unsafe {
            match sys::LogiLcdColorSetText(line_number as c_int,
                ws.as_ptr(), red as c_int, green as c_int, blue as c_int)
            {
                true => Ok(()),
                false => Err(LcdError::ColorText),
            }
        }
    }
}

impl Drop for Lcd {
    /// Kills the applet and frees memory used by the SDK
    fn drop(&mut self) {
        unsafe {
            sys::LogiLcdShutdown();
        }
        INITIALIZED.store(false, Ordering::SeqCst);
    }
}
<|endoftext|>


<commit_before>#![crate_name = "logger"]
#![license = "MIT"]

//! Request logging middleware for Iron

#[deny(warnings)]

extern crate iron;
extern crate time;
extern crate term;
extern crate typemap;

use iron::{AfterMiddleware, BeforeMiddleware, IronResult, Request, Response, Error};
use iron::errors::FileError;
use iron::typemap::Assoc;
use term::{Terminal, WriterWrapper, stdout};

use std::io::IoResult;

use format::{Format, FormatText, Str, Method, URI, Status, ResponseTime,
             ConstantColor, FunctionColor, ConstantAttrs, FunctionAttrs};

pub mod format;

/// `Middleware` for logging request and response info to the terminal.
pub struct Logger {
    format: Option<Format>
}

impl Logger {
    /// Create a pair of `Logger` middlewares with the specified `format`. If a `None` is passed in, uses the default format:
    ///
    /// ```ignore
    /// {method} {uri} -> {status} ({response_time} ms)
    /// ```
    ///
    /// While the returned value can be passed straight to `Chain::link`, consider making the logger `BeforeMiddleware`
    /// the first in your chain and the logger `AfterMiddleware` the last by doing something like this:
    ///
    /// ```ignore
    /// let mut chain = ChainBuilder::new(handler);
    /// let (logger_before, logger_after) = Logger::new(None);
    /// chain.link_before(logger_before);
    /// // link other middlewares here...
    /// chain.link_after(logger_after);
    /// ```
    pub fn new(format: Option<Format>) -> (Logger, Logger) {
        (Logger { format: format.clone() }, Logger { format: format })
    }
}

struct StartTime;
impl Assoc<u64> for StartTime {}

impl BeforeMiddleware for Logger {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        req.extensions.insert::<StartTime, u64>(time::precise_time_ns());
        Ok(())
    }
}

impl AfterMiddleware for Logger {
    fn after(&self, req: &mut Request, res: &mut Response) -> IronResult<()> {
        let entry_time = *req.extensions.find::<StartTime, u64>().unwrap();
        let response_time_ms = (time::precise_time_ns() - entry_time) as f64 / 1000000.0;
        let Format(format) = self.format.clone().unwrap_or_default();

        let render = |text: &FormatText| {
            match *text {
                Str(ref string) => string.clone(),
                Method => format!("{}", req.method),
                URI => format!("{}", req.url),
                Status => format!("{}", res.status),
                ResponseTime => format!("{} ms", response_time_ms)
            }
        };

        let log = |mut t: Box<Terminal<WriterWrapper> + Send>| -> IoResult<()> {
            for unit in format.iter() {
                match unit.color {
                    ConstantColor(Some(color)) => { try!(t.fg(color)); }
                    ConstantColor(None) => (),
                    FunctionColor(f) => match f(req, res) {
                        Some(color) => { try!(t.fg(color)); }
                        None => ()
                    }
                }
                match unit.attrs {
                    ConstantAttrs(ref attrs) => {
                        for &attr in attrs.iter() {
                            try!(t.attr(attr));
                        }
                    }
                    FunctionAttrs(f) => {
                        for &attr in f(req, res).iter() {
                            try!(t.attr(attr));
                        }
                    }
                }
                try!(write!(t, "{}", render(&unit.text)));
                try!(t.reset());
            }
            try!(writeln!(t, ""));
            Ok(())
        };

        match stdout() {
            Some(terminal) => {
                match log(terminal) {
                    Err(e) => return Err(FileError(e).erase()),
                    _ => {}
                }
            }
            None => { return Err(CouldNotOpenTerminal.erase()) }
        };

        Ok(())
    }
}

/// Error returned when logger cannout access stdout.
#[deriving(Show)]
pub struct CouldNotOpenTerminal;

impl Error for CouldNotOpenTerminal {
    fn name(&self) -> &'static str {
        "Could Not Open Terminal"
    }

    fn description(&self) -> Option<&str> {
        Some("Logger could not open stdout as a terminal.")
    }
}

<commit_msg>(fix) Error::erase was removed due to new trait object safety rules.<commit_after>#![crate_name = "logger"]
#![license = "MIT"]

//! Request logging middleware for Iron

#[deny(warnings)]

extern crate iron;
extern crate time;
extern crate term;
extern crate typemap;

use iron::{AfterMiddleware, BeforeMiddleware, IronResult, IronError, Request, Response, Error};
use iron::errors::FileError;
use iron::typemap::Assoc;
use term::{Terminal, WriterWrapper, stdout};

use std::io::IoResult;

use format::{Format, FormatText, Str, Method, URI, Status, ResponseTime,
             ConstantColor, FunctionColor, ConstantAttrs, FunctionAttrs};

pub mod format;

/// `Middleware` for logging request and response info to the terminal.
pub struct Logger {
    format: Option<Format>
}

impl Logger {
    /// Create a pair of `Logger` middlewares with the specified `format`. If a `None` is passed in, uses the default format:
    ///
    /// ```ignore
    /// {method} {uri} -> {status} ({response_time} ms)
    /// ```
    ///
    /// While the returned value can be passed straight to `Chain::link`, consider making the logger `BeforeMiddleware`
    /// the first in your chain and the logger `AfterMiddleware` the last by doing something like this:
    ///
    /// ```ignore
    /// let mut chain = ChainBuilder::new(handler);
    /// let (logger_before, logger_after) = Logger::new(None);
    /// chain.link_before(logger_before);
    /// // link other middlewares here...
    /// chain.link_after(logger_after);
    /// ```
    pub fn new(format: Option<Format>) -> (Logger, Logger) {
        (Logger { format: format.clone() }, Logger { format: format })
    }
}

struct StartTime;
impl Assoc<u64> for StartTime {}

impl BeforeMiddleware for Logger {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        req.extensions.insert::<StartTime, u64>(time::precise_time_ns());
        Ok(())
    }
}

impl AfterMiddleware for Logger {
    fn after(&self, req: &mut Request, res: &mut Response) -> IronResult<()> {
        let entry_time = *req.extensions.find::<StartTime, u64>().unwrap();
        let response_time_ms = (time::precise_time_ns() - entry_time) as f64 / 1000000.0;
        let Format(format) = self.format.clone().unwrap_or_default();

        let render = |text: &FormatText| {
            match *text {
                Str(ref string) => string.clone(),
                Method => format!("{}", req.method),
                URI => format!("{}", req.url),
                Status => format!("{}", res.status),
                ResponseTime => format!("{} ms", response_time_ms)
            }
        };

        let log = |mut t: Box<Terminal<WriterWrapper> + Send>| -> IoResult<()> {
            for unit in format.iter() {
                match unit.color {
                    ConstantColor(Some(color)) => { try!(t.fg(color)); }
                    ConstantColor(None) => (),
                    FunctionColor(f) => match f(req, res) {
                        Some(color) => { try!(t.fg(color)); }
                        None => ()
                    }
                }
                match unit.attrs {
                    ConstantAttrs(ref attrs) => {
                        for &attr in attrs.iter() {
                            try!(t.attr(attr));
                        }
                    }
                    FunctionAttrs(f) => {
                        for &attr in f(req, res).iter() {
                            try!(t.attr(attr));
                        }
                    }
                }
                try!(write!(t, "{}", render(&unit.text)));
                try!(t.reset());
            }
            try!(writeln!(t, ""));
            Ok(())
        };

        match stdout() {
            Some(terminal) => {
                match log(terminal) {
                    Err(e) => return Err(box FileError(e) as IronError),
                    _ => {}
                }
            }
            None => { return Err(box CouldNotOpenTerminal as IronError) }
        };

        Ok(())
    }
}

/// Error returned when logger cannout access stdout.
#[deriving(Show)]
pub struct CouldNotOpenTerminal;

impl Error for CouldNotOpenTerminal {
    fn name(&self) -> &'static str {
        "Could Not Open Terminal"
    }

    fn description(&self) -> Option<&str> {
        Some("Logger could not open stdout as a terminal.")
    }
}

<|endoftext|>


<commit_before>//! An element-tree style XML library
//!
//! # Examples
//!
//! ## Reading
//!
//! ```
//! use treexml::Document;
//!
//! let doc_raw = r#"
//! <?xml version="1.1" encoding="UTF-8"?>
//! <table>
//!     <fruit type="apple">worm</fruit>
//!     <vegetable />
//! </table>
//! "#;
//!
//! let doc = Document::parse(doc_raw.as_bytes()).unwrap();
//! let root = doc.root.unwrap();
//!
//! let fruit = root.find_child(|tag| tag.name == "fruit").unwrap().clone();
//! println!("{} [{:?}] = {}", fruit.name, fruit.attributes, fruit.text.unwrap());
//! ```
//!
//! ## Writing
//!
//! ```
//! use treexml::{Document, Element};
//!
//! let mut root = Element::new("root");
//! let mut child = Element::new("child");
//! child.text = Some("contents".to_owned());
//! root.children.push(child);
//!
//! let doc = Document{
//!     root: Some(root),
//!     .. Document::default()
//! };
//!
//! println!("{}", doc);
//! ```

extern crate xml;

use std::borrow::Cow;
use std::collections::HashMap;
use std::fmt;
use std::io::{Read, Write};
use std::iter::Filter;
use std::slice::{Iter, IterMut};

/// The common error type for all XML tree operations
#[derive(Debug)]
pub enum Error {
    /// Error parsing input data into an XML tree
    ParseError(xml::reader::Error),
    WriteError(xml::writer::Error),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::ParseError(ref e) => e.fmt(f),
            Error::WriteError(ref e) => e.fmt(f),
        }
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::ParseError(ref e) => e.description(),
            Error::WriteError(_) => "Error writing XML element",
        }
    }
}

impl From<xml::reader::Error> for Error {
    fn from(err: xml::reader::Error) -> Error {
        Error::ParseError(err)
    }
}

impl From<xml::writer::Error> for Error {
    fn from(err: xml::writer::Error) -> Error {
        Error::WriteError(err)
    }
}

/// Enumeration of XML versions
///
/// This exists solely because `xml-rs`'s XmlVersion doesn't implement Debug
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum XmlVersion {
    /// XML Version 1.0
    Version10,
    /// XML Version 1.1
    Version11,
}

impl From<xml::common::XmlVersion> for XmlVersion {
    fn from(v: xml::common::XmlVersion) -> XmlVersion {
        match v {
            xml::common::XmlVersion::Version10 => XmlVersion::Version10,
            xml::common::XmlVersion::Version11 => XmlVersion::Version11,
        }
    }
}

impl Into<xml::common::XmlVersion> for XmlVersion {
    fn into(self) -> xml::common::XmlVersion {
        match self {
            XmlVersion::Version10 => xml::common::XmlVersion::Version10,
            XmlVersion::Version11 => xml::common::XmlVersion::Version11,
        }
    }
}

/// An XML element
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Element {
    /// Tag prefix, used for namespacing: `xsl` in `xsl:for-each`
    pub prefix: Option<String>,
    /// Tag name: `for-each` in `xsl:for-each`
    pub name: String,
    /// Tag attributes
    pub attributes: HashMap<String, String>,
    /// A vector of child elements
    pub children: Vec<Element>,
    /// Contents of the element
    pub text: Option<String>,
    /// CDATA contents of the element
    pub cdata: Option<String>,
}

impl Default for Element {
    fn default() -> Self {
        Element{
            prefix: None,
            name: "tag".to_owned(),
            attributes: HashMap::new(),
            children: Vec::new(),
            text: None,
            cdata: None,
        }
    }
}

impl Element {

    /// Create a new `Element` with the tag name `name`
    pub fn new<S>(name: S) -> Element
        where S: Into<String>
    {
        Element{name: name.into(), .. Element::default()}
    }

    /// Parse the contents of an element
    fn parse<R: Read>(&mut self, mut reader: &mut xml::reader::EventReader<R>) -> Result<(), Error> {

        use xml::reader::XmlEvent;

        loop {
            let ev = try!(reader.next());
            match ev {
                XmlEvent::StartElement{name, attributes, ..} => {

                    let mut attr_map = HashMap::new();
                    for attr in attributes {
                        let attr_name = match attr.name.prefix {
                            Some(prefix) => format!("{}:{}", prefix, attr.name.local_name),
                            None => attr.name.local_name,
                        };
                        attr_map.insert(attr_name, attr.value);
                    }

                    let mut child = Element{
                        prefix: name.prefix,
                        name: name.local_name,
                        attributes: attr_map,
                        .. Element::default()
                    };
                    try!(child.parse(&mut reader));
                    self.children.push(child);

                },
                XmlEvent::EndElement{name} => {

                    if name.prefix == self.prefix && name.local_name == self.name {
                        return Ok(());
                    } else {
                        // This should never happen, since the base xml library will panic first
                        panic!("Unexpected closing tag: {}, expected {}", name, self.name);
                    }

                },
                XmlEvent::Characters(s) => {

                    let text = match self.text {
                        Some(ref v) => v.clone(),
                        None => String::new(),
                    };
                    self.text = Some(text + &s)

                },
                XmlEvent::CData(s) => {

                    let cdata = match self.cdata {
                        Some(ref v) => v.clone(),
                        None => String::new(),
                    };
                    self.cdata = Some(cdata + &s);

                },
                XmlEvent::Whitespace(_) => {},
                XmlEvent::Comment(_) => {},
                _ => {},
            }
        }
    }

    /// Write an element and its contents to `writer`
    fn write<W: Write>(&self, writer: &mut xml::writer::EventWriter<W>) -> Result<(), Error> {

        use xml::writer::XmlEvent;
        use xml::name::Name;
        use xml::attribute::Attribute;
        use xml::namespace::Namespace;

        let name = Name::local(&self.name);
        let mut attributes = Vec::with_capacity(self.attributes.len());
        for (k, v) in self.attributes.iter() {
            attributes.push(Attribute{name: Name::local(k), value: v});
        }

        let namespace = Namespace::empty();

        try!(writer.write(XmlEvent::StartElement{
            name: name,
            attributes: Cow::Owned(attributes),
            namespace: Cow::Owned(namespace),
        }));

        if let Some(ref text) = self.text {
            try!(writer.write(XmlEvent::Characters(&text[..])));
        }
        if let Some(ref cdata) = self.cdata {
            try!(writer.write(XmlEvent::CData(&cdata[..])));
        }

        for ref e in &self.children {
            try!(e.write(writer));
        }

        try!(writer.write(XmlEvent::EndElement{name: Some(name)}));

        Ok(())

    }

    /// Find a single child of the current `Element`, given a predicate
    pub fn find_child<P>(&self, predicate: P) -> Option<&Element>
        where P: for<'r> Fn(&'r &Element) -> bool
    {
        self.children.iter().find(predicate)
    }

    /// Find a single child of the current `Element`, given a predicate; returns a mutable borrow
    pub fn find_child_mut<P>(&mut self, predicate: P) -> Option<&mut Element>
        where P: for<'r> FnMut(&'r &mut Element) -> bool
    {
        self.children.iter_mut().find(predicate)
    }

    /// Filters the children of the current `Element`, given a predicate
    pub fn filter_children<P>(&self, predicate: P) -> Filter<Iter<Element>, P>
        where P: for<'r> Fn(&'r &Element) -> bool
    {
        self.children.iter().filter(predicate)
    }

    /// Filters the children of the current `Element`, given a predicate; returns a mutable iterator
    pub fn filter_children_mut<P>(&mut self, predicate: P) -> Filter<IterMut<Element>, P>
        where P: for<'r> FnMut(&'r &mut Element) -> bool
    {
        self.children.iter_mut().filter(predicate)
    }

}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let doc = Document{
            root: Some(self.clone()),
            .. Document::default()
        };
        let mut v = Vec::<u8>::new();
        doc._write(&mut v, false, "  ").unwrap();
        let s = String::from_utf8(v).unwrap();
        f.write_str(&s[..])
    }
}

/// An XML document
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Document {
    /// Version of the XML document
    pub version: XmlVersion,
    /// Encoding of the XML document
    pub encoding: String,
    /// Root tag of the XML document
    pub root: Option<Element>,
}

impl Default for Document {
    fn default() -> Self {
        Document{
            version: XmlVersion::Version10,
            encoding: "UTF-8".to_owned(),
            root: None,
        }
    }
}

impl Document {

    /// Create a new `Document` with default values
    pub fn new() -> Document {
        Document{.. Document::default()}
    }

    /// Parse data from a reader to construct an XML document
    ///
    /// # Failures
    ///
    /// Passes any errors that the `xml-rs` library returns up the stack
    pub fn parse<R: Read>(r: R) -> Result<Document, Error> {

        use xml::reader::{EventReader, XmlEvent};

        let mut reader = EventReader::new(r);
        let mut doc = Document::new();

        loop {
            let ev = try!(reader.next());
            match ev {
                XmlEvent::StartDocument{version, encoding, ..} => {
                    doc.version = XmlVersion::from(version);
                    doc.encoding = encoding;
                },
                XmlEvent::StartElement{name, attributes, ..} => {

                    // Start of the root element

                    let mut attr_map = HashMap::new();
                    for attr in attributes {
                        let attr_name = match attr.name.prefix {
                            Some(prefix) => format!("{}:{}", prefix, attr.name.local_name),
                            None => attr.name.local_name,
                        };
                        attr_map.insert(attr_name, attr.value);
                    }

                    let mut root = Element{
                        prefix: name.prefix,
                        name: name.local_name,
                        attributes: attr_map,
                        .. Element::default()
                    };
                    try!(root.parse(&mut reader));
                    doc.root = Some(root);

                },
                XmlEvent::EndDocument => break,
                _ => {},
            }
        }

        Ok(doc)

    }

    pub fn write<W: Write>(&self, mut w: &mut W) -> Result<(), Error> {
        self._write(&mut w, true, "  ")
    }

    /// Writes a document to `w`
    fn _write<W: Write>(&self, w: &mut W, document_decl: bool, indent_str: &'static str) -> Result<(), Error> {

        use xml::writer::{EmitterConfig, XmlEvent};

        let mut writer = EmitterConfig::new()
            .perform_indent(true)
            .write_document_declaration(document_decl)
            .indent_string(indent_str)
            .create_writer(w);

        if document_decl {
            try!(writer.write(XmlEvent::StartDocument{
                version: self.version.into(),
                encoding: Some(&self.encoding),
                standalone: None,
            }));
        }

        if let Some(ref e) = self.root {
            try!(e.write(&mut writer));
        }

        Ok(())

    }

}

impl fmt::Display for Document {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut v = Vec::<u8>::new();
        self.write(&mut v).unwrap();
        let s = String::from_utf8(v).unwrap();
        f.write_str(&s[..])
    }
}
<commit_msg>import XmlVersion from xml-rs as BaseXmlVersion<commit_after>//! An element-tree style XML library
//!
//! # Examples
//!
//! ## Reading
//!
//! ```
//! use treexml::Document;
//!
//! let doc_raw = r#"
//! <?xml version="1.1" encoding="UTF-8"?>
//! <table>
//!     <fruit type="apple">worm</fruit>
//!     <vegetable />
//! </table>
//! "#;
//!
//! let doc = Document::parse(doc_raw.as_bytes()).unwrap();
//! let root = doc.root.unwrap();
//!
//! let fruit = root.find_child(|tag| tag.name == "fruit").unwrap().clone();
//! println!("{} [{:?}] = {}", fruit.name, fruit.attributes, fruit.text.unwrap());
//! ```
//!
//! ## Writing
//!
//! ```
//! use treexml::{Document, Element};
//!
//! let mut root = Element::new("root");
//! let mut child = Element::new("child");
//! child.text = Some("contents".to_owned());
//! root.children.push(child);
//!
//! let doc = Document{
//!     root: Some(root),
//!     .. Document::default()
//! };
//!
//! println!("{}", doc);
//! ```

extern crate xml;

use std::borrow::Cow;
use std::collections::HashMap;
use std::fmt;
use std::io::{Read, Write};
use std::iter::Filter;
use std::slice::{Iter, IterMut};

use xml::common::XmlVersion as BaseXmlVersion;

/// The common error type for all XML tree operations
#[derive(Debug)]
pub enum Error {
    /// Error parsing input data into an XML tree
    ParseError(xml::reader::Error),
    WriteError(xml::writer::Error),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::ParseError(ref e) => e.fmt(f),
            Error::WriteError(ref e) => e.fmt(f),
        }
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::ParseError(ref e) => e.description(),
            Error::WriteError(_) => "Error writing XML element",
        }
    }
}

impl From<xml::reader::Error> for Error {
    fn from(err: xml::reader::Error) -> Error {
        Error::ParseError(err)
    }
}

impl From<xml::writer::Error> for Error {
    fn from(err: xml::writer::Error) -> Error {
        Error::WriteError(err)
    }
}

/// Enumeration of XML versions
///
/// This exists solely because `xml-rs`'s XmlVersion doesn't implement Debug
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum XmlVersion {
    /// XML Version 1.0
    Version10,
    /// XML Version 1.1
    Version11,
}

impl From<BaseXmlVersion> for XmlVersion {
    fn from(v: BaseXmlVersion) -> XmlVersion {
        match v {
            BaseXmlVersion::Version10 => XmlVersion::Version10,
            BaseXmlVersion::Version11 => XmlVersion::Version11,
        }
    }
}

impl Into<BaseXmlVersion> for XmlVersion {
    fn into(self) -> BaseXmlVersion {
        match self {
            XmlVersion::Version10 => BaseXmlVersion::Version10,
            XmlVersion::Version11 => BaseXmlVersion::Version11,
        }
    }
}

/// An XML element
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Element {
    /// Tag prefix, used for namespacing: `xsl` in `xsl:for-each`
    pub prefix: Option<String>,
    /// Tag name: `for-each` in `xsl:for-each`
    pub name: String,
    /// Tag attributes
    pub attributes: HashMap<String, String>,
    /// A vector of child elements
    pub children: Vec<Element>,
    /// Contents of the element
    pub text: Option<String>,
    /// CDATA contents of the element
    pub cdata: Option<String>,
}

impl Default for Element {
    fn default() -> Self {
        Element{
            prefix: None,
            name: "tag".to_owned(),
            attributes: HashMap::new(),
            children: Vec::new(),
            text: None,
            cdata: None,
        }
    }
}

impl Element {

    /// Create a new `Element` with the tag name `name`
    pub fn new<S>(name: S) -> Element
        where S: Into<String>
    {
        Element{name: name.into(), .. Element::default()}
    }

    /// Parse the contents of an element
    fn parse<R: Read>(&mut self, mut reader: &mut xml::reader::EventReader<R>) -> Result<(), Error> {

        use xml::reader::XmlEvent;

        loop {
            let ev = try!(reader.next());
            match ev {
                XmlEvent::StartElement{name, attributes, ..} => {

                    let mut attr_map = HashMap::new();
                    for attr in attributes {
                        let attr_name = match attr.name.prefix {
                            Some(prefix) => format!("{}:{}", prefix, attr.name.local_name),
                            None => attr.name.local_name,
                        };
                        attr_map.insert(attr_name, attr.value);
                    }

                    let mut child = Element{
                        prefix: name.prefix,
                        name: name.local_name,
                        attributes: attr_map,
                        .. Element::default()
                    };
                    try!(child.parse(&mut reader));
                    self.children.push(child);

                },
                XmlEvent::EndElement{name} => {

                    if name.prefix == self.prefix && name.local_name == self.name {
                        return Ok(());
                    } else {
                        // This should never happen, since the base xml library will panic first
                        panic!("Unexpected closing tag: {}, expected {}", name, self.name);
                    }

                },
                XmlEvent::Characters(s) => {

                    let text = match self.text {
                        Some(ref v) => v.clone(),
                        None => String::new(),
                    };
                    self.text = Some(text + &s)

                },
                XmlEvent::CData(s) => {

                    let cdata = match self.cdata {
                        Some(ref v) => v.clone(),
                        None => String::new(),
                    };
                    self.cdata = Some(cdata + &s);

                },
                XmlEvent::Whitespace(_) => {},
                XmlEvent::Comment(_) => {},
                _ => {},
            }
        }
    }

    /// Write an element and its contents to `writer`
    fn write<W: Write>(&self, writer: &mut xml::writer::EventWriter<W>) -> Result<(), Error> {

        use xml::writer::XmlEvent;
        use xml::name::Name;
        use xml::attribute::Attribute;
        use xml::namespace::Namespace;

        let name = Name::local(&self.name);
        let mut attributes = Vec::with_capacity(self.attributes.len());
        for (k, v) in self.attributes.iter() {
            attributes.push(Attribute{name: Name::local(k), value: v});
        }

        let namespace = Namespace::empty();

        try!(writer.write(XmlEvent::StartElement{
            name: name,
            attributes: Cow::Owned(attributes),
            namespace: Cow::Owned(namespace),
        }));

        if let Some(ref text) = self.text {
            try!(writer.write(XmlEvent::Characters(&text[..])));
        }
        if let Some(ref cdata) = self.cdata {
            try!(writer.write(XmlEvent::CData(&cdata[..])));
        }

        for ref e in &self.children {
            try!(e.write(writer));
        }

        try!(writer.write(XmlEvent::EndElement{name: Some(name)}));

        Ok(())

    }

    /// Find a single child of the current `Element`, given a predicate
    pub fn find_child<P>(&self, predicate: P) -> Option<&Element>
        where P: for<'r> Fn(&'r &Element) -> bool
    {
        self.children.iter().find(predicate)
    }

    /// Find a single child of the current `Element`, given a predicate; returns a mutable borrow
    pub fn find_child_mut<P>(&mut self, predicate: P) -> Option<&mut Element>
        where P: for<'r> FnMut(&'r &mut Element) -> bool
    {
        self.children.iter_mut().find(predicate)
    }

    /// Filters the children of the current `Element`, given a predicate
    pub fn filter_children<P>(&self, predicate: P) -> Filter<Iter<Element>, P>
        where P: for<'r> Fn(&'r &Element) -> bool
    {
        self.children.iter().filter(predicate)
    }

    /// Filters the children of the current `Element`, given a predicate; returns a mutable iterator
    pub fn filter_children_mut<P>(&mut self, predicate: P) -> Filter<IterMut<Element>, P>
        where P: for<'r> FnMut(&'r &mut Element) -> bool
    {
        self.children.iter_mut().filter(predicate)
    }

}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let doc = Document{
            root: Some(self.clone()),
            .. Document::default()
        };
        let mut v = Vec::<u8>::new();
        doc._write(&mut v, false, "  ").unwrap();
        let s = String::from_utf8(v).unwrap();
        f.write_str(&s[..])
    }
}

/// An XML document
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Document {
    /// Version of the XML document
    pub version: XmlVersion,
    /// Encoding of the XML document
    pub encoding: String,
    /// Root tag of the XML document
    pub root: Option<Element>,
}

impl Default for Document {
    fn default() -> Self {
        Document{
            version: XmlVersion::Version10,
            encoding: "UTF-8".to_owned(),
            root: None,
        }
    }
}

impl Document {

    /// Create a new `Document` with default values
    pub fn new() -> Document {
        Document{.. Document::default()}
    }

    /// Parse data from a reader to construct an XML document
    ///
    /// # Failures
    ///
    /// Passes any errors that the `xml-rs` library returns up the stack
    pub fn parse<R: Read>(r: R) -> Result<Document, Error> {

        use xml::reader::{EventReader, XmlEvent};

        let mut reader = EventReader::new(r);
        let mut doc = Document::new();

        loop {
            let ev = try!(reader.next());
            match ev {
                XmlEvent::StartDocument{version, encoding, ..} => {
                    doc.version = XmlVersion::from(version);
                    doc.encoding = encoding;
                },
                XmlEvent::StartElement{name, attributes, ..} => {

                    // Start of the root element

                    let mut attr_map = HashMap::new();
                    for attr in attributes {
                        let attr_name = match attr.name.prefix {
                            Some(prefix) => format!("{}:{}", prefix, attr.name.local_name),
                            None => attr.name.local_name,
                        };
                        attr_map.insert(attr_name, attr.value);
                    }

                    let mut root = Element{
                        prefix: name.prefix,
                        name: name.local_name,
                        attributes: attr_map,
                        .. Element::default()
                    };
                    try!(root.parse(&mut reader));
                    doc.root = Some(root);

                },
                XmlEvent::EndDocument => break,
                _ => {},
            }
        }

        Ok(doc)

    }

    pub fn write<W: Write>(&self, mut w: &mut W) -> Result<(), Error> {
        self._write(&mut w, true, "  ")
    }

    /// Writes a document to `w`
    fn _write<W: Write>(&self, w: &mut W, document_decl: bool, indent_str: &'static str) -> Result<(), Error> {

        use xml::writer::{EmitterConfig, XmlEvent};

        let mut writer = EmitterConfig::new()
            .perform_indent(true)
            .write_document_declaration(document_decl)
            .indent_string(indent_str)
            .create_writer(w);

        if document_decl {
            try!(writer.write(XmlEvent::StartDocument{
                version: self.version.into(),
                encoding: Some(&self.encoding),
                standalone: None,
            }));
        }

        if let Some(ref e) = self.root {
            try!(e.write(&mut writer));
        }

        Ok(())

    }

}

impl fmt::Display for Document {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut v = Vec::<u8>::new();
        self.write(&mut v).unwrap();
        let s = String::from_utf8(v).unwrap();
        f.write_str(&s[..])
    }
}
<|endoftext|>


<commit_before>//! Use the API Documentation below to learn about the various things you can do with this crate.
//!
//! **If this is your first time using this crate, read the Guide on [turtle.rs](http://turtle.rs)
//! to learn how to start.**
//!
//! * The [`Turtle` struct](struct.Turtle.html) - lists of all the various drawing commands that the
//!   turtle supports
//! * The [`Drawing` struct](struct.Drawing.html) - allows you to manipulate the title, size,
//!   background and more of the drawing that you are creating
//! * The [`color` module](color/index.html) - describes the different ways to create colors and
//!   includes a list of the hundreds of predefined color names that you can use to easily set the
//!   pen, fill, and background color of your drawings
//!
//! Note: Call [`turtle::start()`](fn.start.html) if you do not create a turtle with
//! [`Turtle::new()`](struct.Turtle.html#method.new) right at the beginning of your program. Most
//! programs will never need to call this function as it is called for you in
//! [`Turtle::new()`](struct.Turtle.html#method.new).
//!
//! # Random Values
//!
//! See the [`rand` module](rand/index.html) for information about generating random colors, speeds,
//! angles, and more which can be used in your programs to produce some interesting results!
//!
//! # Event Handling
//!
#![cfg_attr(not(feature = "unstable"), doc = "
**The turtle events API is unstable.** Rebuild the documentation with `--features \"unstable\"` to
show the documentation for the types and modules that are part of that. Some links may appear
broken unless you do so. See [Unstable features](#unstable-features) below for more information.
")]
//! The [`Event` enum](event/enum.Event.html) documentation provides information about how you can
//! create an event loop. This allows you to draw things in response to certain events like the
//! mouse moving, keys being pressed, and more.
//!
//! The `Turtle` struct contains a few convenience methods so you can do some common event-related
//! things without creating the entire event loop. For example, use
//! [`wait_for_click()`](struct.Turtle.html#method.wait_for_click) to wait for the user to click
//! anywhere on the screen before proceeding.
//!
//! # Adding turtle to your project
//!
//! To add the turtle crate to your project, add the following to your `Cargo.toml` file with `...`
//! replaced by the version of the turtle crate you want to use:
//!
//! ```toml
//! [dependencies]
//! turtle = "..."
//!
//! # Compile turtle and other dependencies with optimizations
//! [profile.dev.package."*"]
//! opt-level = 3
//! ```
//!
//! This is the recommended way to use the turtle crate because it provides maximum performance
//! with minimum impact on build time. The initial build will take a bit longer since dependencies
//! are being optimized, but each build of your program after that should run relatively quickly.
//!
//! For maximum overall performance, run your build with the `--release` flag.
//!
//! # Unstable features
//!
//! Some parts of this crate are unstable and may be subject to change in the future. If you would
//! like to use unstable functionality, enable the "unstable" feature in your `Cargo.toml` file as
//! shown below:
//!
//! ```toml
//! [dependencies]
//! # Explicitly opt-in to unstable features that may change in the future
//! turtle = { version = "...", features = ["unstable"] }
//! ```
//!
//! If you are developing this crate with a local version of the turtle repository, see the
//! [CONTRIBUTING.md] file for the specific commands you should run to generate the documentation.
//!
//! [CONTRIBUTING.md]: https://github.com/sunjay/turtle/blob/master/CONTRIBUTING.md

// This warning usually signals an error and so it should be treated as such.
#![deny(unused_must_use)]

#![doc(html_logo_url = "https://raw.githubusercontent.com/sunjay/turtle/master/docs/assets/images/turtle-logo-512.png")]
#![cfg_attr(docsrs, feature(doc_cfg))]

#[cfg(all(test, not(feature = "test")))]
compile_error!("Make sure you run tests with `cargo test --features \"test unstable\"`");

mod radians;
mod point;
mod speed;
pub mod color;
pub mod rand;

mod ipc_protocol;
mod renderer_server;
mod renderer_client;
mod async_drawing;
mod async_turtle;
mod sync_runtime;
mod drawing;
mod turtle;

pub use crate::color::Color;
pub use crate::async_drawing::Size;
pub use crate::drawing::Drawing;
pub use crate::point::Point;
pub use crate::speed::Speed;
pub use crate::async_turtle::{Angle, Distance};
pub use crate::turtle::Turtle;
pub use crate::renderer_server::{ExportError, start};

cfg_if::cfg_if! {
    if #[cfg(feature = "unstable")] {
        #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
        pub mod event;
        #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
        pub use crate::event::Event;

    } else {
        mod event;
        use crate::event::Event;
    }
}
<commit_msg>Make color module private and re-export color::extended as extra_colors<commit_after>//! Use the API Documentation below to learn about the various things you can do with this crate.
//!
//! **If this is your first time using this crate, read the Guide on [turtle.rs](http://turtle.rs)
//! to learn how to start.**
//!
//! * The [`Turtle` struct](struct.Turtle.html) - lists of all the various drawing commands that the
//!   turtle supports
//! * The [`Drawing` struct](struct.Drawing.html) - allows you to manipulate the title, size,
//!   background and more of the drawing that you are creating
//! * The [`color` module](color/index.html) - describes the different ways to create colors and
//!   includes a list of the hundreds of predefined color names that you can use to easily set the
//!   pen, fill, and background color of your drawings
//!
//! Note: Call [`turtle::start()`](fn.start.html) if you do not create a turtle with
//! [`Turtle::new()`](struct.Turtle.html#method.new) right at the beginning of your program. Most
//! programs will never need to call this function as it is called for you in
//! [`Turtle::new()`](struct.Turtle.html#method.new).
//!
//! # Random Values
//!
//! See the [`rand` module](rand/index.html) for information about generating random colors, speeds,
//! angles, and more which can be used in your programs to produce some interesting results!
//!
//! # Event Handling
//!
#![cfg_attr(not(feature = "unstable"), doc = "
**The turtle events API is unstable.** Rebuild the documentation with `--features \"unstable\"` to
show the documentation for the types and modules that are part of that. Some links may appear
broken unless you do so. See [Unstable features](#unstable-features) below for more information.
")]
//! The [`Event` enum](event/enum.Event.html) documentation provides information about how you can
//! create an event loop. This allows you to draw things in response to certain events like the
//! mouse moving, keys being pressed, and more.
//!
//! The `Turtle` struct contains a few convenience methods so you can do some common event-related
//! things without creating the entire event loop. For example, use
//! [`wait_for_click()`](struct.Turtle.html#method.wait_for_click) to wait for the user to click
//! anywhere on the screen before proceeding.
//!
//! # Adding turtle to your project
//!
//! To add the turtle crate to your project, add the following to your `Cargo.toml` file with `...`
//! replaced by the version of the turtle crate you want to use:
//!
//! ```toml
//! [dependencies]
//! turtle = "..."
//!
//! # Compile turtle and other dependencies with optimizations
//! [profile.dev.package."*"]
//! opt-level = 3
//! ```
//!
//! This is the recommended way to use the turtle crate because it provides maximum performance
//! with minimum impact on build time. The initial build will take a bit longer since dependencies
//! are being optimized, but each build of your program after that should run relatively quickly.
//!
//! For maximum overall performance, run your build with the `--release` flag.
//!
//! # Unstable features
//!
//! Some parts of this crate are unstable and may be subject to change in the future. If you would
//! like to use unstable functionality, enable the "unstable" feature in your `Cargo.toml` file as
//! shown below:
//!
//! ```toml
//! [dependencies]
//! # Explicitly opt-in to unstable features that may change in the future
//! turtle = { version = "...", features = ["unstable"] }
//! ```
//!
//! If you are developing this crate with a local version of the turtle repository, see the
//! [CONTRIBUTING.md] file for the specific commands you should run to generate the documentation.
//!
//! [CONTRIBUTING.md]: https://github.com/sunjay/turtle/blob/master/CONTRIBUTING.md

// This warning usually signals an error and so it should be treated as such.
#![deny(unused_must_use)]

#![doc(html_logo_url = "https://raw.githubusercontent.com/sunjay/turtle/master/docs/assets/images/turtle-logo-512.png")]
#![cfg_attr(docsrs, feature(doc_cfg))]

#[cfg(all(test, not(feature = "test")))]
compile_error!("Make sure you run tests with `cargo test --features \"test unstable\"`");

mod radians;
mod point;
mod speed;
mod color;
pub mod rand;

mod ipc_protocol;
mod renderer_server;
mod renderer_client;
mod async_drawing;
mod async_turtle;
mod sync_runtime;
mod drawing;
mod turtle;

pub use crate::color::Color;
pub use crate::color::extended as extra_colors;
pub use crate::async_drawing::Size;
pub use crate::drawing::Drawing;
pub use crate::point::Point;
pub use crate::speed::Speed;
pub use crate::async_turtle::{Angle, Distance};
pub use crate::turtle::Turtle;
pub use crate::renderer_server::{ExportError, start};

cfg_if::cfg_if! {
    if #[cfg(feature = "unstable")] {
        #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
        pub mod event;
        #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
        pub use crate::event::Event;

    } else {
        mod event;
        use crate::event::Event;
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

#![crate_type = "lib"]
#![cfg_attr(test, feature(test))]
#![feature(fnbox)]
#![feature(alloc)]
#![feature(slice_patterns)]
#![feature(box_syntax)]
#![feature(iterator_for_each)]
#![feature(conservative_impl_trait)]
#![feature(entry_or_default)]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]
#![cfg_attr(not(feature = "dev"), allow(unknown_lints))]
#![recursion_limit = "100"]
#![feature(ascii_ctype)]
#![allow(module_inception)]
#![allow(should_implement_trait)]
#![allow(large_enum_variant)]
#![allow(needless_pass_by_value)]
#![allow(unreadable_literal)]
#![allow(new_without_default_derive)]
#![allow(verbose_bit_mask)]
#![allow(implicit_hasher)]

extern crate alloc;
extern crate backtrace;
#[macro_use]
extern crate bitflags;
extern crate byteorder;
extern crate chrono;
extern crate crc;
extern crate crossbeam_channel;
#[macro_use]
extern crate fail;
extern crate flat_map;
extern crate fnv;
extern crate fs2;
extern crate futures;
extern crate futures_cpupool;
extern crate grpcio as grpc;
extern crate indexmap;
extern crate kvproto;
#[macro_use]
extern crate lazy_static;
extern crate libc;
#[macro_use]
extern crate log;
extern crate mio;
extern crate murmur3;
#[macro_use]
extern crate prometheus;
extern crate protobuf;
#[macro_use]
extern crate quick_error;
extern crate raft;
extern crate rand;
extern crate regex;
extern crate rocksdb;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate sys_info;
extern crate tempdir;
#[cfg(test)]
extern crate test;
extern crate time;
extern crate tipb;
extern crate tokio_core;
extern crate tokio_timer;
#[cfg(test)]
extern crate toml;
extern crate url;
#[cfg(test)]
extern crate utime;
extern crate uuid;
extern crate zipf;

#[macro_use]
pub mod util;
pub mod config;
pub mod storage;
pub mod raftstore;
pub mod pd;
pub mod server;
pub mod coprocessor;
pub mod import;

pub use storage::Storage;
<commit_msg>src/lib.rs: Bump recursion limit to 200 (#2958)<commit_after>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

#![crate_type = "lib"]
#![cfg_attr(test, feature(test))]
#![feature(fnbox)]
#![feature(alloc)]
#![feature(slice_patterns)]
#![feature(box_syntax)]
#![feature(iterator_for_each)]
#![feature(conservative_impl_trait)]
#![feature(entry_or_default)]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]
#![cfg_attr(not(feature = "dev"), allow(unknown_lints))]
#![recursion_limit = "200"]
#![feature(ascii_ctype)]
#![allow(module_inception)]
#![allow(should_implement_trait)]
#![allow(large_enum_variant)]
#![allow(needless_pass_by_value)]
#![allow(unreadable_literal)]
#![allow(new_without_default_derive)]
#![allow(verbose_bit_mask)]
#![allow(implicit_hasher)]

extern crate alloc;
extern crate backtrace;
#[macro_use]
extern crate bitflags;
extern crate byteorder;
extern crate chrono;
extern crate crc;
extern crate crossbeam_channel;
#[macro_use]
extern crate fail;
extern crate flat_map;
extern crate fnv;
extern crate fs2;
extern crate futures;
extern crate futures_cpupool;
extern crate grpcio as grpc;
extern crate indexmap;
extern crate kvproto;
#[macro_use]
extern crate lazy_static;
extern crate libc;
#[macro_use]
extern crate log;
extern crate mio;
extern crate murmur3;
#[macro_use]
extern crate prometheus;
extern crate protobuf;
#[macro_use]
extern crate quick_error;
extern crate raft;
extern crate rand;
extern crate regex;
extern crate rocksdb;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate sys_info;
extern crate tempdir;
#[cfg(test)]
extern crate test;
extern crate time;
extern crate tipb;
extern crate tokio_core;
extern crate tokio_timer;
#[cfg(test)]
extern crate toml;
extern crate url;
#[cfg(test)]
extern crate utime;
extern crate uuid;
extern crate zipf;

#[macro_use]
pub mod util;
pub mod config;
pub mod storage;
pub mod raftstore;
pub mod pd;
pub mod server;
pub mod coprocessor;
pub mod import;

pub use storage::Storage;
<|endoftext|>


<commit_before>#![feature(libc)]
extern crate libc;

#[allow(dead_code, non_camel_case_types, raw_pointer_derive, non_snake_case, missing_copy_implementations)]
mod ffi;

pub struct VM {
    raw: ffi::HSQUIRRELVM,
}

impl VM {
    pub fn new() -> VM {
        unsafe {
            let mut vm = ffi::sq_open(1024);
            ffi::sq_helper_setup_default_callbacks(vm);
            VM { raw: vm }
        }
    }
}

impl Drop for VM {
    fn drop(&mut self) {
        unsafe {
            ffi::sq_close(self.raw);
        }
    }
}

#[test]
fn starting_squirrel() {
    let vm = VM::new();
}
<commit_msg>Added code for function wrapping, not working.<commit_after>#![feature(libc)]
extern crate libc;

use std::ffi::CString;
use std::mem;
use std::ptr;

#[allow(dead_code, non_camel_case_types, raw_pointer_derive, non_snake_case, missing_copy_implementations)]
mod ffi;

mod wrapper {
    use ::std::mem;
    use ::ffi;

    pub extern "C" fn func0<F, R>(vm: ffi::HSQUIRRELVM) -> ffi::SQInteger where F: Fn() -> R {
        unsafe {
            let mut ptr: ffi::SQUserPointer;
            ffi::sq_getuserdata(vm, -1, mem::transmute(&ptr), mem::transmute(0)); // TODO: last arguments should be NULL, find better way
            let func: F = mem::transmute(ptr);
            //let func: F = ptr as F;
            func();
        }
        0
    }
}

pub struct VM {
    raw: ffi::HSQUIRRELVM,
}

impl VM {
    pub fn new() -> VM {
        unsafe {
            let mut vm = ffi::sq_open(1024);
            ffi::sq_helper_setup_default_callbacks(vm);
            VM { raw: vm }
        }
    }

    pub fn func0<F, R>(&mut self, name: &str, func: F) where F: Fn() -> R {
        self.push_function(name, func, wrapper::func0::<F, R>);
    }

    fn push_function<F>(&mut self, name: &str, func: F, wrapper: extern "C" fn(ffi::HSQUIRRELVM) -> ffi::SQInteger) {
        let c_str = CString::from_slice(name.as_bytes());
        unsafe {
            ffi::sq_pushroottable(self.raw);
            ffi::sq_pushstring(self.raw, c_str.as_ptr(), -1);
            let user_ptr = ffi::sq_newuserdata(self.raw, mem::size_of::<F>() as ffi::SQUnsignedInteger);
            ptr::write(mem::transmute(user_ptr), func);
            ffi::sq_newclosure(self.raw, Some(wrapper), 0);
            ffi::sq_newslot(self.raw, -3, 0);
            ffi::sq_pop(self.raw, 1);
        }
    }
}

impl Drop for VM {
    fn drop(&mut self) {
        unsafe {
            ffi::sq_close(self.raw);
        }
    }
}

#[test]
fn starting_squirrel() {
    let mut vm = VM::new();
    vm.func0("test", || {
        println!("Hello, world!");
    });
}
<|endoftext|>