<commit_before>//! Xml Attributes module
//!
//! Provides an iterator over attributes key/value pairs
use std::borrow::Cow;
use std::ops::Range;
use std::io::BufRead;
use errors::{Error, Result};
use escape::{escape, unescape};
use reader::{is_whitespace, Reader};

use memchr;

/// Iterator over attributes key/value pairs
#[derive(Clone)]
pub struct Attributes<'a> {
    /// slice of `Element` corresponding to attributes
    bytes: &'a [u8],
    /// current position of the iterator
    position: usize,
    /// shall the next iterator early exit because there were an error last time
    exit: bool,
    /// if true, checks for duplicate names
    with_checks: bool,
    /// if `with_checks`, contains the ranges corresponding to the
    /// attribute names already parsed in this `Element`
    consumed: Vec<Range<usize>>,
}

impl<'a> Attributes<'a> {
    /// creates a new attribute iterator from a buffer
    pub fn new(buf: &'a [u8], pos: usize) -> Attributes<'a> {
        Attributes {
            bytes: buf,
            position: pos,
            exit: false,
            with_checks: true,
            consumed: Vec::new(),
        }
    }

    /// check if attributes are distincts
    pub fn with_checks(&mut self, val: bool) -> &mut Attributes<'a> {
        self.with_checks = val;
        self
    }

    /// sets `self.exit = true` to terminate the iterator
    fn error(&mut self, err: Error) -> Result<Attribute<'a>> {
        self.exit = true;
        Err(err.into())
    }
}

/// A struct representing a key/value for a xml attribute
///
/// Parses either `key="value"` or `key='value'`.
/// Field `value` stores raw bytes, possibly containing escape-sequences.
#[derive(Debug, Clone, PartialEq)]
pub struct Attribute<'a> {
    /// the key to uniquely define the attribute
    pub key: &'a [u8],
    /// the raw value of attribute
    pub value: Cow<'a, [u8]>,
}

impl<'a> Attribute<'a> {
    /// unescapes the value
    pub fn unescaped_value(&self) -> Result<Cow<[u8]>> {
        unescape(&*self.value).map_err(Error::EscapeError)
    }

    /// unescapes then decode the value
    ///
    /// for performance reasons (could avoid allocating a `String`),
    /// it might be wiser to manually use
    /// 1. Attributes::unescaped_value()
    /// 2. Reader::decode(...)
    pub fn unescape_and_decode_value<B: BufRead>(&self, reader: &Reader<B>) -> Result<String> {
        self.unescaped_value()
            .map(|e| reader.decode(&*e).into_owned())
    }
}

impl<'a> From<(&'a [u8], &'a [u8])> for Attribute<'a> {
    /// Creates new attribute from raw bytes.
    /// Does not apply any transformation to both key and value.
    ///
    /// # Example
    /// ```
    /// use quick_xml::events::attributes::Attribute;
    ///
    /// let features = Attribute::from(("features".as_bytes(), "Bells & whistles".as_bytes()));
    /// assert_eq!(features.value, "Bells & whistles".as_bytes());
    /// ```
    fn from(val: (&'a [u8], &'a [u8])) -> Attribute<'a> {
        Attribute {
            key: val.0,
            value: Cow::from(val.1),
        }
    }
}

impl<'a> From<(&'a str, &'a str)> for Attribute<'a> {
    /// Creates new attribute from text representation.
    /// Key is stored as-is, but the value will be escaped.
    ///
    /// # Example
    /// ```
    /// use quick_xml::events::attributes::Attribute;
    ///
    /// let features = Attribute::from(("features", "Bells & whistles"));
    /// assert_eq!(features.value, "Bells & whistles".as_bytes());
    /// ```
    fn from(val: (&'a str, &'a str)) -> Attribute<'a> {
        Attribute {
            key: val.0.as_bytes(),
            value: escape(val.1.as_bytes()),
        }
    }
}

impl<'a> Iterator for Attributes<'a> {
    type Item = Result<Attribute<'a>>;
    fn next(&mut self) -> Option<Self::Item> {
        if self.exit {
            return None;
        }

        let len = self.bytes.len();
        let p = self.position;
        if len <= p {
            return None;
        }

        // search first space
        let mut start_key = match self.bytes[p..len - 1]
            .iter()
            .position(|&b| is_whitespace(b))
        {
            Some(i) => p + i + 1,
            None => {
                self.position = len;
                return None;
            }
        };

        // now search first non space
        start_key += match self.bytes[start_key..len - 1]
            .iter()
            .position(|&b| !is_whitespace(b))
        {
            Some(i) => i,
            None => {
                self.position = len;
                return None;
            }
        };

        // key end with either whitespace or =
        let end_key = match self.bytes[start_key + 1..len - 1]
            .iter()
            .position(|&b| b == b'=' || is_whitespace(b))
        {
            Some(i) => start_key + 1 + i,
            None => {
                self.position = len;
                return None;
            }
        };

        if self.with_checks {
            if let Some(i) = self.bytes[start_key..end_key]
                .iter()
                .position(|&b| b == b'\'' || b == b'"')
            {
                return Some(self.error(Error::NameWithQuote(start_key + i)));
            }
            if let Some(r) = self.consumed
                .iter()
                .cloned()
                .find(|ref r| &self.bytes[(**r).clone()] == &self.bytes[start_key..end_key])
            {
                return Some(self.error(Error::DuplicatedAttribute(start_key, r.start)));
            }
            self.consumed.push(start_key..end_key);
        }

        // values starts after =
        let start_val = match memchr::memchr(b'=', &self.bytes[end_key..len - 1]) {
            Some(i) => end_key + 1 + i,
            None => {
                self.position = len;
                return None;
            }
        };

        if self.with_checks {
            if let Some(i) = self.bytes[end_key..start_val - 1]
                .iter()
                .position(|&b| !is_whitespace(b))
            {
                return Some(self.error(Error::NoEqAfterName(end_key + i)));
            }
        }

        // value starts with a quote
        let (quote, start_val) = match self.bytes[start_val..len - 1]
            .iter()
            .enumerate()
            .filter(|&(_, &b)| !is_whitespace(b))
            .next()
        {
            Some((i, b @ &b'\'')) | Some((i, b @ &b'"')) => (*b, start_val + i + 1),
            Some((i, _)) => {
                return Some(self.error(Error::UnquotedValue(start_val + i)));
            }
            None => {
                self.position = len;
                return None;
            }
        };

        // value ends with the same quote
        let end_val = match memchr::memchr(quote, &self.bytes[start_val..]) {
            Some(i) => start_val + i,
            None => {
                self.position = len;
                return None;
            }
        };

        self.position = end_val + 1;

        Some(Ok(Attribute {
            key: &self.bytes[start_key..end_key],
            value: Cow::from(&self.bytes[start_val..end_val]),
        }))
    }
}
<commit_msg>allow attributes to use html styles<commit_after>//! Xml Attributes module
//!
//! Provides an iterator over attributes key/value pairs
use std::borrow::Cow;
use std::ops::Range;
use std::io::BufRead;
use errors::{Error, Result};
use escape::{escape, unescape};
use reader::{is_whitespace, Reader};

/// Iterator over attributes key/value pairs
#[derive(Clone)]
pub struct Attributes<'a> {
    /// slice of `Element` corresponding to attributes
    bytes: &'a [u8],
    /// current position of the iterator
    position: usize,
    /// if true, checks for duplicate names
    with_checks: bool,
    /// allows attribute without quote or `=`
    html: bool,
    /// if `with_checks`, contains the ranges corresponding to the
    /// attribute names already parsed in this `Element`
    consumed: Vec<Range<usize>>,
}

impl<'a> Attributes<'a> {
    /// creates a new attribute iterator from a buffer
    pub fn new(buf: &'a [u8], pos: usize) -> Attributes<'a> {
        Attributes {
            bytes: buf,
            position: pos,
            html: false,
            with_checks: true,
            consumed: Vec::new(),
        }
    }

    /// creates a new attribute iterator from a buffer, allowing html attribute syntax
    pub fn html(buf: &'a [u8], pos: usize) -> Attributes<'a> {
        Attributes {
            bytes: buf,
            position: pos,
            html: true,
            with_checks: true,
            consumed: Vec::new(),
        }
    }

    /// check if attributes are distincts
    pub fn with_checks(&mut self, val: bool) -> &mut Attributes<'a> {
        self.with_checks = val;
        self
    }

    /// allow attributes without quote or `=`
    pub fn html_style(&mut self, val: bool) -> &mut Attributes<'a> {
        self.html = val;
        self
    }

    /// sets `self.exit = true` to terminate the iterator
    fn error(&mut self, err: Error, len: usize) -> Result<Attribute<'a>> {
        self.position = len;
        Err(err.into())
    }
}

/// A struct representing a key/value for a xml attribute
///
/// Parses either `key="value"` or `key='value'`.
/// Field `value` stores raw bytes, possibly containing escape-sequences.
#[derive(Debug, Clone, PartialEq)]
pub struct Attribute<'a> {
    /// the key to uniquely define the attribute
    pub key: &'a [u8],
    /// the raw value of attribute
    pub value: Cow<'a, [u8]>,
}

impl<'a> Attribute<'a> {
    /// unescapes the value
    pub fn unescaped_value(&self) -> Result<Cow<[u8]>> {
        unescape(&*self.value).map_err(Error::EscapeError)
    }

    /// unescapes then decode the value
    ///
    /// for performance reasons (could avoid allocating a `String`),
    /// it might be wiser to manually use
    /// 1. Attributes::unescaped_value()
    /// 2. Reader::decode(...)
    pub fn unescape_and_decode_value<B: BufRead>(&self, reader: &Reader<B>) -> Result<String> {
        self.unescaped_value()
            .map(|e| reader.decode(&*e).into_owned())
    }
}

impl<'a> From<(&'a [u8], &'a [u8])> for Attribute<'a> {
    /// Creates new attribute from raw bytes.
    /// Does not apply any transformation to both key and value.
    ///
    /// # Example
    /// ```
    /// use quick_xml::events::attributes::Attribute;
    ///
    /// let features = Attribute::from(("features".as_bytes(), "Bells & whistles".as_bytes()));
    /// assert_eq!(features.value, "Bells & whistles".as_bytes());
    /// ```
    fn from(val: (&'a [u8], &'a [u8])) -> Attribute<'a> {
        Attribute {
            key: val.0,
            value: Cow::from(val.1),
        }
    }
}

impl<'a> From<(&'a str, &'a str)> for Attribute<'a> {
    /// Creates new attribute from text representation.
    /// Key is stored as-is, but the value will be escaped.
    ///
    /// # Example
    /// ```
    /// use quick_xml::events::attributes::Attribute;
    ///
    /// let features = Attribute::from(("features", "Bells & whistles"));
    /// assert_eq!(features.value, "Bells & whistles".as_bytes());
    /// ```
    fn from(val: (&'a str, &'a str)) -> Attribute<'a> {
        Attribute {
            key: val.0.as_bytes(),
            value: escape(val.1.as_bytes()),
        }
    }
}

impl<'a> Iterator for Attributes<'a> {
    type Item = Result<Attribute<'a>>;
    fn next(&mut self) -> Option<Self::Item> {

        let len = self.bytes.len();

        // helper macro for last attribute
        macro_rules! attr {
            ($key: expr) => {
                {
                    self.position = len;
                    if self.html {
                        attr!($key, 0..0)
                    } else {
                        return None;
                    };
                }
            };
            ($key:expr, $val: expr) => {
                return Some(Ok(Attribute {
                    key: &self.bytes[$key],
                    value: Cow::Borrowed(&self.bytes[$val]),
                }));
            };
        }

        if len <= self.position {
            return None;
        }

        let mut bytes = self.bytes.iter().enumerate().skip(self.position);

        // key starts after the whitespace
        let start_key = match bytes.by_ref()
            .skip_while(|&(_, &b)| !is_whitespace(b))
            .find(|&(_, &b)| !is_whitespace(b)) {
            Some((i, _)) => i,
            None => attr!(self.position..len),
        };

        // key ends with either whitespace or =
        let end_key = match bytes.by_ref().find(|&(_, &b)| b == b'=' || is_whitespace(b)) {
            Some((i, &b'=')) => i,
            Some((i, &b'\'')) | Some((i, &b'"')) if self.with_checks => {
                return Some(self.error(Error::NameWithQuote(i), len));
            }
            Some((i, _)) => {
                // consume until `=` or return if html
                match bytes.by_ref().find(|&(_, &b)| !is_whitespace(b)) {
                    Some((_, &b'=')) => i,
                    Some((j, _)) => {
                        if self.html {
                            self.position = j - 1;
                            attr!(start_key..i, 0..0);
                        }
                        return Some(self.error(Error::NoEqAfterName(j), len));
                    }
                    None if self.html => {
                        self.position = len;
                        attr!(start_key..len, 0..0);
                    }
                    None => return Some(self.error(Error::NoEqAfterName(len), len)),
                }
            }
            None => attr!(start_key..len),
        };

        if self.with_checks {
            if let Some(start) = self.consumed
                .iter()
                .filter(|r| r.len() == end_key - start_key)
                .find(|r| &self.bytes[(*r).clone()] == &self.bytes[start_key..end_key])
                .map(|ref r| r.start)
            {
                return Some(self.error(Error::DuplicatedAttribute(start_key, start), len));
            }
            self.consumed.push(start_key..end_key);
        }

        // value has quote if not html
        match bytes.by_ref().find(|&(_, &b)| !is_whitespace(b)) {
            Some((i, quote @ &b'\'')) | Some((i, quote @ &b'"')) => {
                match bytes.by_ref().find(|&(_, &b)| b == *quote) {
                    Some((j, _)) => {
                        self.position = j + 1;
                        attr!(start_key..end_key, i + 1..j)
                    }
                    None => Some(self.error(Error::UnquotedValue(i), len)),
                }
            },
            Some((i, _)) if self.html => {
                let j = bytes.by_ref().find(|&(_, &b)| is_whitespace(b)).map_or(len, |(j, _)| j);
                self.position = j;
                attr!(start_key..end_key, i..j)
            }
            Some((i, _)) => Some(self.error(Error::UnquotedValue(i), len)),
            None => attr!(start_key..end_key),
        }
    }
}

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

    #[test]
    fn regular() {
        let event = b"name a='a' b = 'b'";
        let mut attributes = Attributes::new(event, 0);
        attributes.with_checks(true);
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"a");
        assert_eq!(&*a.value, b"a");
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"b");
        assert_eq!(&*a.value, b"b");
        assert!(attributes.next().is_none());
    }

    #[test]
    fn mixed_quote() {
        let event = b"name a='a' b = \"b\" c='cc\"cc'";
        let mut attributes = Attributes::new(event, 0);
        attributes.with_checks(true);
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"a");
        assert_eq!(&*a.value, b"a");
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"b");
        assert_eq!(&*a.value, b"b");
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"c");
        assert_eq!(&*a.value, b"cc\"cc");
        assert!(attributes.next().is_none());
    }

    #[test]
    fn html_fail() {
        let event = b"name a='a' b=b c";
        let mut attributes = Attributes::new(event, 0);
        attributes.with_checks(true);
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"a");
        assert_eq!(&*a.value, b"a");
        assert!(attributes.next().unwrap().is_err());
    }

    #[test]
    fn html_ok() {
        let event = b"name a='a' e b=b c d ee=ee";
        let mut attributes = Attributes::new(event, 0);
        attributes.with_checks(true).html_style(true);
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"a");
        assert_eq!(&*a.value, b"a");
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"e");
        assert_eq!(&*a.value, b"");
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"b");
        assert_eq!(&*a.value, b"b");
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"c");
        assert_eq!(&*a.value, b"");
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"d");
        assert_eq!(&*a.value, b"");
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"ee");
        assert_eq!(&*a.value, b"ee");
        assert!(attributes.next().is_none());
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Types which pin data to its location in memory
//!
//! It is sometimes useful to have objects that are guaranteed to not move,
//! in the sense that their placement in memory in consistent, and can thus be relied upon.
//!
//! A prime example of such a scenario would be building self-referencial structs,
//! since moving an object with pointers to itself will invalidate them,
//! which could cause undefined behavior.
//!
//! In order to prevent objects from moving, they must be *pinned*,
//! by wrapping the data in special pointer types, such as [`PinMut`] and [`PinBox`].
//! These restrict access to the underlying data to only be immutable by implementing [`Deref`],
//! unless the type implements the [`Unpin`] trait,
//! which indicates that it doesn't need these restrictions and can be safely mutated,
//! by implementing [`DerefMut`].
//!
//! This is done because, while modifying an object can be done in-place,
//! it might also relocate a buffer when its at full capacity,
//! or it might replace one object with another without logically "moving" them with [`swap`].
//!
//! [`PinMut`]: struct.PinMut.html
//! [`PinBox`]: struct.PinBox.html
//! [`Unpin`]: ../../core/marker/trait.Unpin.html
//! [`DerefMut`]: ../../core/ops/trait.DerefMut.html
//! [`Deref`]: ../../core/ops/trait.Deref.html
//! [`swap`]: ../../core/mem/fn.swap.html
//!
//! # Examples
//!
//! ```rust
//! #![feature(pin)]
//!
//! use std::pin::PinBox;
//! use std::marker::Pinned;
//! use std::ptr::NonNull;
//!
//! // This is a self referencial struct since the slice field points to the data field.
//! // We cannot inform the compiler about that with a normal reference,
//! // since this pattern cannot be described with the usual borrowing rules.
//! // Instead we use a raw pointer, though one which is known to not be null,
//! // since we know it's pointing at the string.
//! struct Unmovable {
//!     data: String,
//!     slice: NonNull<String>,
//!     _pin: Pinned,
//! }
//!
//! impl Unmovable {
//!     // To ensure the data doesn't move when the function returns,
//!     // we place it in the heap where it will stay for the lifetime of the object,
//!     // and the only way to access it would be through a pointer to it.
//!     fn new(data: String) -> PinBox<Self> {
//!         let res = Unmovable {
//!             data,
//!             // we only create the pointer once the data is in place
//!             // otherwise it will have already moved before we even started
//!             slice: NonNull::dangling(),
//!             _pin: Pinned,
//!         };
//!         let mut boxed = PinBox::new(res);
//!
//!         let slice = NonNull::from(&boxed.data);
//!         // we know this is safe because modifying a field doesn't move the whole struct
//!         unsafe { PinBox::get_mut(&mut boxed).slice = slice };
//!         boxed
//!     }
//! }
//!
//! let unmoved = Unmovable::new("hello".to_string());
//! // The pointer should point to the correct location,
//! // so long as the struct hasn't moved.
//! // Meanwhile, we are free to move the pointer around.
//! let mut still_unmoved = unmoved;
//! assert_eq!(still_unmoved.slice, NonNull::from(&still_unmoved.data));
//!
//! // Now the only way to access to data (safely) is immutably,
//! // so this will fail to compile:
//! // still_unmoved.data.push_str(" world");
//!
//! ```

#![unstable(feature = "pin", issue = "49150")]

pub use core::pin::*;

use core::convert::From;
use core::fmt;
use core::future::{Future, FutureObj, LocalFutureObj, UnsafeFutureObj};
use core::marker::{Unpin, Unsize};
use core::ops::{CoerceUnsized, Deref, DerefMut};
use core::task::{Context, Poll};

use boxed::Box;

/// A pinned, heap allocated reference.
///
/// This type is similar to [`Box`], except that it pins its value,
/// which prevents it from moving out of the reference, unless it implements [`Unpin`].
///
/// See the [module documentation] for furthur explaination on pinning.
///
/// [`Box`]: ../boxed/struct.Box.html
/// [`Unpin`]: ../../core/marker/trait.Unpin.html
/// [module documentation]: index.html
#[unstable(feature = "pin", issue = "49150")]
#[fundamental]
#[repr(transparent)]
pub struct PinBox<T: ?Sized> {
    inner: Box<T>,
}

#[unstable(feature = "pin", issue = "49150")]
impl<T> PinBox<T> {
    /// Allocate memory on the heap, move the data into it and pin it.
    #[unstable(feature = "pin", issue = "49150")]
    pub fn new(data: T) -> PinBox<T> {
        PinBox { inner: Box::new(data) }
    }
}

#[unstable(feature = "pin", issue = "49150")]
impl<T: ?Sized> PinBox<T> {
    /// Get a pinned reference to the data in this PinBox.
    #[inline]
    pub fn as_pin_mut<'a>(&'a mut self) -> PinMut<'a, T> {
        unsafe { PinMut::new_unchecked(&mut *self.inner) }
    }

    /// Constructs a `PinBox` from a raw pointer.
    ///
    /// After calling this function, the raw pointer is owned by the
    /// resulting `PinBox`. Specifically, the `PinBox` destructor will call
    /// the destructor of `T` and free the allocated memory. Since the
    /// way `PinBox` allocates and releases memory is unspecified, the
    /// only valid pointer to pass to this function is the one taken
    /// from another `PinBox` via the [`PinBox::into_raw`] function.
    ///
    /// This function is unsafe because improper use may lead to
    /// memory problems. For example, a double-free may occur if the
    /// function is called twice on the same raw pointer.
    ///
    /// [`PinBox::into_raw`]: struct.PinBox.html#method.into_raw
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(pin)]
    /// use std::pin::PinBox;
    /// let x = PinBox::new(5);
    /// let ptr = PinBox::into_raw(x);
    /// let x = unsafe { PinBox::from_raw(ptr) };
    /// ```
    #[inline]
    pub unsafe fn from_raw(raw: *mut T) -> Self {
        PinBox { inner: Box::from_raw(raw) }
    }

    /// Consumes the `PinBox`, returning the wrapped raw pointer.
    ///
    /// After calling this function, the caller is responsible for the
    /// memory previously managed by the `PinBox`. In particular, the
    /// caller should properly destroy `T` and release the memory. The
    /// proper way to do so is to convert the raw pointer back into a
    /// `PinBox` with the [`PinBox::from_raw`] function.
    ///
    /// Note: this is an associated function, which means that you have
    /// to call it as `PinBox::into_raw(b)` instead of `b.into_raw()`. This
    /// is so that there is no conflict with a method on the inner type.
    ///
    /// [`PinBox::from_raw`]: struct.PinBox.html#method.from_raw
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(pin)]
    /// use std::pin::PinBox;
    /// let x = PinBox::new(5);
    /// let ptr = PinBox::into_raw(x);
    /// ```
    #[inline]
    pub fn into_raw(b: PinBox<T>) -> *mut T {
        Box::into_raw(b.inner)
    }

    /// Get a mutable reference to the data inside this PinBox.
    ///
    /// This function is unsafe. Users must guarantee that the data is never
    /// moved out of this reference.
    #[inline]
    pub unsafe fn get_mut<'a>(this: &'a mut PinBox<T>) -> &'a mut T {
        &mut *this.inner
    }

    /// Convert this PinBox into an unpinned Box.
    ///
    /// This function is unsafe. Users must guarantee that the data is never
    /// moved out of the box.
    #[inline]
    pub unsafe fn unpin(this: PinBox<T>) -> Box<T> {
        this.inner
    }
}

#[unstable(feature = "pin", issue = "49150")]
impl<T: ?Sized> From<Box<T>> for PinBox<T> {
    fn from(boxed: Box<T>) -> PinBox<T> {
        PinBox { inner: boxed }
    }
}

#[unstable(feature = "pin", issue = "49150")]
impl<T: ?Sized> Deref for PinBox<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &*self.inner
    }
}

#[unstable(feature = "pin", issue = "49150")]
impl<T: Unpin + ?Sized> DerefMut for PinBox<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut *self.inner
    }
}

#[unstable(feature = "pin", issue = "49150")]
impl<T: fmt::Display + ?Sized> fmt::Display for PinBox<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&*self.inner, f)
    }
}

#[unstable(feature = "pin", issue = "49150")]
impl<T: fmt::Debug + ?Sized> fmt::Debug for PinBox<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&*self.inner, f)
    }
}

#[unstable(feature = "pin", issue = "49150")]
impl<T: ?Sized> fmt::Pointer for PinBox<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // It's not possible to extract the inner Uniq directly from the Box,
        // instead we cast it to a *const which aliases the Unique
        let ptr: *const T = &*self.inner;
        fmt::Pointer::fmt(&ptr, f)
    }
}

#[unstable(feature = "pin", issue = "49150")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<PinBox<U>> for PinBox<T> {}

#[unstable(feature = "pin", issue = "49150")]
impl<T: ?Sized> Unpin for PinBox<T> {}

#[unstable(feature = "futures_api", issue = "50547")]
impl<F: ?Sized + Future> Future for PinBox<F> {
    type Output = F::Output;

    fn poll(mut self: PinMut<Self>, cx: &mut Context) -> Poll<Self::Output> {
        self.as_pin_mut().poll(cx)
    }
}

#[unstable(feature = "futures_api", issue = "50547")]
unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for PinBox<F>
    where F: Future<Output = T> + 'a
{
    fn into_raw(self) -> *mut () {
        PinBox::into_raw(self) as *mut ()
    }

    unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll<T> {
        let ptr = ptr as *mut F;
        let pin: PinMut<F> = PinMut::new_unchecked(&mut *ptr);
        pin.poll(cx)
    }

    unsafe fn drop(ptr: *mut ()) {
        drop(PinBox::from_raw(ptr as *mut F))
    }
}

#[unstable(feature = "futures_api", issue = "50547")]
impl<'a, F: Future<Output = ()> + Send + 'a> From<PinBox<F>> for FutureObj<'a, ()> {
    fn from(boxed: PinBox<F>) -> Self {
        FutureObj::new(boxed)
    }
}

#[unstable(feature = "futures_api", issue = "50547")]
impl<'a, F: Future<Output = ()> + 'a> From<PinBox<F>> for LocalFutureObj<'a, ()> {
    fn from(boxed: PinBox<F>) -> Self {
        LocalFutureObj::new(boxed)
    }
}
<commit_msg>deemphasize immutability and improve swap explanation in pin module<commit_after>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Types which pin data to its location in memory
//!
//! It is sometimes useful to have objects that are guaranteed to not move,
//! in the sense that their placement in memory does not change, and can thus be relied upon.
//!
//! A prime example of such a scenario would be building self-referencial structs,
//! since moving an object with pointers to itself will invalidate them,
//! which could cause undefined behavior.
//!
//! In order to prevent objects from moving, they must be *pinned*,
//! by wrapping the data in special pointer types, such as [`PinMut`] and [`PinBox`].
//! On top of ensuring the data cannot be taked by value by being pointers,
//! these types restrict access to the underlying data such that it cannot be moved out of them,
//! unless the type implements the [`Unpin`] trait,
//! which indicates that it can be used safely without these restrictions.
//!
//! A type may be moved out of a reference to it using a function like [`swap`],
//! which replaces the contents of the references, and thus changes their place in memory.
//!
//! [`PinMut`]: struct.PinMut.html
//! [`PinBox`]: struct.PinBox.html
//! [`Unpin`]: ../../core/marker/trait.Unpin.html
//! [`swap`]: ../../core/mem/fn.swap.html
//!
//! # Examples
//!
//! ```rust
//! #![feature(pin)]
//!
//! use std::pin::PinBox;
//! use std::marker::Pinned;
//! use std::ptr::NonNull;
//!
//! // This is a self referencial struct since the slice field points to the data field.
//! // We cannot inform the compiler about that with a normal reference,
//! // since this pattern cannot be described with the usual borrowing rules.
//! // Instead we use a raw pointer, though one which is known to not be null,
//! // since we know it's pointing at the string.
//! struct Unmovable {
//!     data: String,
//!     slice: NonNull<String>,
//!     _pin: Pinned,
//! }
//!
//! impl Unmovable {
//!     // To ensure the data doesn't move when the function returns,
//!     // we place it in the heap where it will stay for the lifetime of the object,
//!     // and the only way to access it would be through a pointer to it.
//!     fn new(data: String) -> PinBox<Self> {
//!         let res = Unmovable {
//!             data,
//!             // we only create the pointer once the data is in place
//!             // otherwise it will have already moved before we even started
//!             slice: NonNull::dangling(),
//!             _pin: Pinned,
//!         };
//!         let mut boxed = PinBox::new(res);
//!
//!         let slice = NonNull::from(&boxed.data);
//!         // we know this is safe because modifying a field doesn't move the whole struct
//!         unsafe { PinBox::get_mut(&mut boxed).slice = slice };
//!         boxed
//!     }
//! }
//!
//! let unmoved = Unmovable::new("hello".to_string());
//! // The pointer should point to the correct location,
//! // so long as the struct hasn't moved.
//! // Meanwhile, we are free to move the pointer around.
//! let mut still_unmoved = unmoved;
//! assert_eq!(still_unmoved.slice, NonNull::from(&still_unmoved.data));
//!
//! // Since our type doesn't implement Unpin, this will fail to compile:
//! // let new_unmoved = Unmovable::new("world".to_string());
//! // std::mem::swap(&mut *still_unmoved, &mut *new_unmoved);
//! ```

#![unstable(feature = "pin", issue = "49150")]

pub use core::pin::*;

use core::convert::From;
use core::fmt;
use core::future::{Future, FutureObj, LocalFutureObj, UnsafeFutureObj};
use core::marker::{Unpin, Unsize};
use core::ops::{CoerceUnsized, Deref, DerefMut};
use core::task::{Context, Poll};

use boxed::Box;

/// A pinned, heap allocated reference.
///
/// This type is similar to [`Box`], except that it pins its value,
/// which prevents it from moving out of the reference, unless it implements [`Unpin`].
///
/// See the [module documentation] for furthur explaination on pinning.
///
/// [`Box`]: ../boxed/struct.Box.html
/// [`Unpin`]: ../../core/marker/trait.Unpin.html
/// [module documentation]: index.html
#[unstable(feature = "pin", issue = "49150")]
#[fundamental]
#[repr(transparent)]
pub struct PinBox<T: ?Sized> {
    inner: Box<T>,
}

#[unstable(feature = "pin", issue = "49150")]
impl<T> PinBox<T> {
    /// Allocate memory on the heap, move the data into it and pin it.
    #[unstable(feature = "pin", issue = "49150")]
    pub fn new(data: T) -> PinBox<T> {
        PinBox { inner: Box::new(data) }
    }
}

#[unstable(feature = "pin", issue = "49150")]
impl<T: ?Sized> PinBox<T> {
    /// Get a pinned reference to the data in this PinBox.
    #[inline]
    pub fn as_pin_mut<'a>(&'a mut self) -> PinMut<'a, T> {
        unsafe { PinMut::new_unchecked(&mut *self.inner) }
    }

    /// Constructs a `PinBox` from a raw pointer.
    ///
    /// After calling this function, the raw pointer is owned by the
    /// resulting `PinBox`. Specifically, the `PinBox` destructor will call
    /// the destructor of `T` and free the allocated memory. Since the
    /// way `PinBox` allocates and releases memory is unspecified, the
    /// only valid pointer to pass to this function is the one taken
    /// from another `PinBox` via the [`PinBox::into_raw`] function.
    ///
    /// This function is unsafe because improper use may lead to
    /// memory problems. For example, a double-free may occur if the
    /// function is called twice on the same raw pointer.
    ///
    /// [`PinBox::into_raw`]: struct.PinBox.html#method.into_raw
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(pin)]
    /// use std::pin::PinBox;
    /// let x = PinBox::new(5);
    /// let ptr = PinBox::into_raw(x);
    /// let x = unsafe { PinBox::from_raw(ptr) };
    /// ```
    #[inline]
    pub unsafe fn from_raw(raw: *mut T) -> Self {
        PinBox { inner: Box::from_raw(raw) }
    }

    /// Consumes the `PinBox`, returning the wrapped raw pointer.
    ///
    /// After calling this function, the caller is responsible for the
    /// memory previously managed by the `PinBox`. In particular, the
    /// caller should properly destroy `T` and release the memory. The
    /// proper way to do so is to convert the raw pointer back into a
    /// `PinBox` with the [`PinBox::from_raw`] function.
    ///
    /// Note: this is an associated function, which means that you have
    /// to call it as `PinBox::into_raw(b)` instead of `b.into_raw()`. This
    /// is so that there is no conflict with a method on the inner type.
    ///
    /// [`PinBox::from_raw`]: struct.PinBox.html#method.from_raw
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(pin)]
    /// use std::pin::PinBox;
    /// let x = PinBox::new(5);
    /// let ptr = PinBox::into_raw(x);
    /// ```
    #[inline]
    pub fn into_raw(b: PinBox<T>) -> *mut T {
        Box::into_raw(b.inner)
    }

    /// Get a mutable reference to the data inside this PinBox.
    ///
    /// This function is unsafe. Users must guarantee that the data is never
    /// moved out of this reference.
    #[inline]
    pub unsafe fn get_mut<'a>(this: &'a mut PinBox<T>) -> &'a mut T {
        &mut *this.inner
    }

    /// Convert this PinBox into an unpinned Box.
    ///
    /// This function is unsafe. Users must guarantee that the data is never
    /// moved out of the box.
    #[inline]
    pub unsafe fn unpin(this: PinBox<T>) -> Box<T> {
        this.inner
    }
}

#[unstable(feature = "pin", issue = "49150")]
impl<T: ?Sized> From<Box<T>> for PinBox<T> {
    fn from(boxed: Box<T>) -> PinBox<T> {
        PinBox { inner: boxed }
    }
}

#[unstable(feature = "pin", issue = "49150")]
impl<T: ?Sized> Deref for PinBox<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &*self.inner
    }
}

#[unstable(feature = "pin", issue = "49150")]
impl<T: Unpin + ?Sized> DerefMut for PinBox<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut *self.inner
    }
}

#[unstable(feature = "pin", issue = "49150")]
impl<T: fmt::Display + ?Sized> fmt::Display for PinBox<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&*self.inner, f)
    }
}

#[unstable(feature = "pin", issue = "49150")]
impl<T: fmt::Debug + ?Sized> fmt::Debug for PinBox<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&*self.inner, f)
    }
}

#[unstable(feature = "pin", issue = "49150")]
impl<T: ?Sized> fmt::Pointer for PinBox<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // It's not possible to extract the inner Uniq directly from the Box,
        // instead we cast it to a *const which aliases the Unique
        let ptr: *const T = &*self.inner;
        fmt::Pointer::fmt(&ptr, f)
    }
}

#[unstable(feature = "pin", issue = "49150")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<PinBox<U>> for PinBox<T> {}

#[unstable(feature = "pin", issue = "49150")]
impl<T: ?Sized> Unpin for PinBox<T> {}

#[unstable(feature = "futures_api", issue = "50547")]
impl<F: ?Sized + Future> Future for PinBox<F> {
    type Output = F::Output;

    fn poll(mut self: PinMut<Self>, cx: &mut Context) -> Poll<Self::Output> {
        self.as_pin_mut().poll(cx)
    }
}

#[unstable(feature = "futures_api", issue = "50547")]
unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for PinBox<F>
    where F: Future<Output = T> + 'a
{
    fn into_raw(self) -> *mut () {
        PinBox::into_raw(self) as *mut ()
    }

    unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll<T> {
        let ptr = ptr as *mut F;
        let pin: PinMut<F> = PinMut::new_unchecked(&mut *ptr);
        pin.poll(cx)
    }

    unsafe fn drop(ptr: *mut ()) {
        drop(PinBox::from_raw(ptr as *mut F))
    }
}

#[unstable(feature = "futures_api", issue = "50547")]
impl<'a, F: Future<Output = ()> + Send + 'a> From<PinBox<F>> for FutureObj<'a, ()> {
    fn from(boxed: PinBox<F>) -> Self {
        FutureObj::new(boxed)
    }
}

#[unstable(feature = "futures_api", issue = "50547")]
impl<'a, F: Future<Output = ()> + 'a> From<PinBox<F>> for LocalFutureObj<'a, ()> {
    fn from(boxed: PinBox<F>) -> Self {
        LocalFutureObj::new(boxed)
    }
}
<|endoftext|>


<commit_before>/**
 * The concurrency primitives you know and love.
 *
 * Maybe once we have a "core exports x only to std" mechanism, these can be
 * in std.
 */

export semaphore, new_semaphore;

// FIXME (#3119) This shouldn't be a thing exported from core.
import arc::exclusive;

// Each waiting task receives on one of these. FIXME #3125 make these oneshot.
type wait_end = pipes::port<()>;
type signal_end = pipes::chan<()>;
// A doubly-ended queue of waiting tasks.
type waitqueue = { head: pipes::port<signal_end>,
                   tail: pipes::chan<signal_end> };

fn new_waiter() -> (signal_end, wait_end) { pipes::stream() }

/// A counting semaphore.
enum semaphore = exclusive<{
    mut count: int,
    waiters:   waitqueue,
}>;

/// Create a new semaphore with the specified count.
fn new_semaphore(count: int) -> semaphore {
    let (tail, head) = pipes::stream();
    semaphore(exclusive({ mut count: count,
                          waiters: { head: head, tail: tail } }))
}

impl semaphore for &semaphore {
    /// Creates a new handle to the semaphore.
    fn clone() -> semaphore {
        semaphore((**self).clone())
    }

    /**
     * Acquires a resource represented by the semaphore. Blocks if necessary
     * until resource(s) become available.
     */
    fn wait() {
        let mut waiter_nobe = none;
        unsafe {
            do (**self).with |state| {
                state.count -= 1;
                if state.count < 0 {
                    let (signal_end,wait_end) = new_waiter();
                    waiter_nobe = some(wait_end);
                    // Enqueue ourself.
                    state.waiters.tail.send(signal_end);
                }
            }
        }
        for 1000.times { task::yield(); }
        // Need to wait outside the exclusive.
        if waiter_nobe.is_some() {
            let _ = option::unwrap(waiter_nobe).recv();
        }
    }

    /**
     * Release a held resource represented by the semaphore. Wakes a blocked
     * contending task, if any exist.
     */
    fn signal() {
        unsafe {
            do (**self).with |state| {
                state.count += 1;
                // The peek is mandatory to make sure recv doesn't block.
                if state.count >= 0 && state.waiters.head.peek() {
                    // Pop off the waitqueue and send a wakeup signal. If the
                    // waiter was killed, its port will have closed, and send
                    // will fail. Keep trying until we get a live task.
                    state.waiters.head.recv().send(());
                    // to-do: use this version when it's ready, kill-friendly.
                    // while !state.waiters.head.recv().try_send(()) { }
                }
            }
        }
    }

    /// Runs a function with ownership of one of the semaphore's resources.
    fn access<U>(blk: fn() -> U) -> U {
        self.wait();
        let _x = sem_release(self);
        blk()
    }
}

// FIXME(#3136) should go inside of access()
struct sem_release {
    sem: &semaphore;
    new(sem: &semaphore) { self.sem = sem; }
    drop { self.sem.signal(); }
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_sem_as_mutex() {
        let s = ~new_semaphore(1);
        let s2 = ~s.clone();
        do task::spawn {
            do s2.access {
                for 10.times { task::yield(); }
            }
        }
        do s.access {
            for 10.times { task::yield(); }
        }
    }
    #[test]
    fn test_sem_as_cvar() {
        /* Child waits and parent signals */
        let (c,p) = pipes::stream();
        let s = ~new_semaphore(0);
        let s2 = ~s.clone();
        do task::spawn {
            s2.wait();
            c.send(());
        }
        for 10.times { task::yield(); }
        s.signal();
        let _ = p.recv();

        /* Parent waits and child signals */
        let (c,p) = pipes::stream();
        let s = ~new_semaphore(0);
        let s2 = ~s.clone();
        do task::spawn {
            for 10.times { task::yield(); }
            s2.signal();
            let _ = p.recv();
        }
        s.wait();
        c.send(());
    }
    #[test]
    fn test_sem_mutual_exclusion() {
        let (c,p) = pipes::stream();
        let s = ~new_semaphore(1);
        let s2 = ~s.clone();
        let sharedstate = ~0;
        let ptr = ptr::addr_of(*sharedstate);
        do task::spawn {
            let sharedstate = unsafe { unsafe::reinterpret_cast(ptr) };
            access_shared(sharedstate, s2, 10);
            c.send(());
        }
        access_shared(sharedstate, s, 10);
        let _ = p.recv();

        assert *sharedstate == 20;

        fn access_shared(sharedstate: &mut int, sem: &semaphore, n: uint) {
            for n.times {
                do sem.access {
                    let oldval = *sharedstate;
                    task::yield();
                    *sharedstate = oldval + 1;
                }
            }
        }
    }
    #[test]
    fn test_sem_runtime_friendly_blocking() {
        do task::spawn_sched(task::manual_threads(1)) {
            let s = ~new_semaphore(1);
            let s2 = ~s.clone();
            let (c,p) = pipes::stream();
            let child_data = ~mut some((s2,c));
            do s.access {
                let (s2,c) = option::swap_unwrap(child_data);
                do task::spawn {
                    c.send(());
                    do s2.access { }
                    c.send(());
                }
                let _ = p.recv(); // wait for child to come alive
                for 5.times { task::yield(); } // let the child contend
            }
            let _ = p.recv(); // wait for child to be done
        }
    }
}
<commit_msg>Touch up semaphores; add another test<commit_after>/**
 * The concurrency primitives you know and love.
 *
 * Maybe once we have a "core exports x only to std" mechanism, these can be
 * in std.
 */

export semaphore, new_semaphore;

// FIXME (#3119) This shouldn't be a thing exported from core.
import arc::exclusive;

// Each waiting task receives on one of these. FIXME #3125 make these oneshot.
type wait_end = pipes::port<()>;
type signal_end = pipes::chan<()>;
// A doubly-ended queue of waiting tasks.
type waitqueue = { head: pipes::port<signal_end>,
                   tail: pipes::chan<signal_end> };

fn waitqueue() -> waitqueue {
    let (tail, head) = pipes::stream();
    { head: head, tail: tail }
}

/// A counting, blocking, bounded-waiting semaphore.
enum semaphore = exclusive<semaphore_inner>;
type semaphore_inner = {
    mut count: int,
    waiters:   waitqueue,
    //blocked:   waitqueue,
};

/// Create a new semaphore with the specified count.
fn new_semaphore(count: int) -> semaphore {
    semaphore(exclusive({ mut count: count,
                          waiters: waitqueue(), /* blocked: waitqueue() */ }))
}

impl semaphore for &semaphore {
    /// Creates a new handle to the semaphore.
    fn clone() -> semaphore {
        semaphore((**self).clone())
    }

    /**
     * Acquires a resource represented by the semaphore. Blocks if necessary
     * until resource(s) become available.
     */
    fn acquire() {
        let mut waiter_nobe = none;
        unsafe {
            do (**self).with |state| {
                state.count -= 1;
                if state.count < 0 {
                    let (signal_end,wait_end) = pipes::stream();
                    waiter_nobe = some(wait_end);
                    // Enqueue ourself.
                    state.waiters.tail.send(signal_end);
                }
            }
        }
        // Uncomment if you wish to test for sem races. Not valgrind-friendly.
        /* for 1000.times { task::yield(); } */
        // Need to wait outside the exclusive.
        if waiter_nobe.is_some() {
            let _ = option::unwrap(waiter_nobe).recv();
        }
    }

    /**
     * Release a held resource represented by the semaphore. Wakes a blocked
     * contending task, if any exist.
     */
    fn release() {
        unsafe {
            do (**self).with |state| {
                state.count += 1;
                // The peek is mandatory to make sure recv doesn't block.
                if state.count >= 0 && state.waiters.head.peek() {
                    // Pop off the waitqueue and send a wakeup signal. If the
                    // waiter was killed, its port will have closed, and send
                    // will fail. Keep trying until we get a live task.
                    state.waiters.head.recv().send(());
                    // to-do: use this version when it's ready, kill-friendly.
                    // while !state.waiters.head.recv().try_send(()) { }
                }
            }
        }
    }

    /// Runs a function with ownership of one of the semaphore's resources.
    fn access<U>(blk: fn() -> U) -> U {
        self.acquire();
        let _x = sem_release(self);
        blk()
    }
}

// FIXME(#3136) should go inside of access()
struct sem_release {
    sem: &semaphore;
    new(sem: &semaphore) { self.sem = sem; }
    drop { self.sem.release(); }
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_sem_as_mutex() {
        let s = ~new_semaphore(1);
        let s2 = ~s.clone();
        do task::spawn {
            do s2.access {
                for 10.times { task::yield(); }
            }
        }
        do s.access {
            for 10.times { task::yield(); }
        }
    }
    #[test]
    fn test_sem_as_cvar() {
        /* Child waits and parent signals */
        let (c,p) = pipes::stream();
        let s = ~new_semaphore(0);
        let s2 = ~s.clone();
        do task::spawn {
            s2.acquire();
            c.send(());
        }
        for 10.times { task::yield(); }
        s.release();
        let _ = p.recv();

        /* Parent waits and child signals */
        let (c,p) = pipes::stream();
        let s = ~new_semaphore(0);
        let s2 = ~s.clone();
        do task::spawn {
            for 10.times { task::yield(); }
            s2.release();
            let _ = p.recv();
        }
        s.acquire();
        c.send(());
    }
    #[test]
    fn test_sem_mutual_exclusion() {
        // Unsafely achieve shared state, and do the textbook
        // "load tmp <- ptr; inc tmp; store ptr <- tmp" dance.
        let (c,p) = pipes::stream();
        let s = ~new_semaphore(1);
        let s2 = ~s.clone();
        let sharedstate = ~0;
        let ptr = ptr::addr_of(*sharedstate);
        do task::spawn {
            let sharedstate = unsafe { unsafe::reinterpret_cast(ptr) };
            access_shared(sharedstate, s2, 10);
            c.send(());
        }
        access_shared(sharedstate, s, 10);
        let _ = p.recv();

        assert *sharedstate == 20;

        fn access_shared(sharedstate: &mut int, sem: &semaphore, n: uint) {
            for n.times {
                do sem.access {
                    let oldval = *sharedstate;
                    task::yield();
                    *sharedstate = oldval + 1;
                }
            }
        }
    }
    #[test]
    fn test_sem_multi_resource() {
        // Parent and child both get in the critical section at the same
        // time, and shake hands.
        let s = ~new_semaphore(2);
        let s2 = ~s.clone();
        let (c1,p1) = pipes::stream();
        let (c2,p2) = pipes::stream();
        do task::spawn {
            do s2.access {
                let _ = p2.recv();
                c1.send(());
            }
        }
        do s.access {
            c2.send(());
            let _ = p1.recv();
        }
    }
    #[test]
    fn test_sem_runtime_friendly_blocking() {
        // Force the runtime to schedule two threads on the same sched_loop.
        // When one blocks, it should schedule the other one.
        do task::spawn_sched(task::manual_threads(1)) {
            let s = ~new_semaphore(1);
            let s2 = ~s.clone();
            let (c,p) = pipes::stream();
            let child_data = ~mut some((s2,c));
            do s.access {
                let (s2,c) = option::swap_unwrap(child_data);
                do task::spawn {
                    c.send(());
                    do s2.access { }
                    c.send(());
                }
                let _ = p.recv(); // wait for child to come alive
                for 5.times { task::yield(); } // let the child contend
            }
            let _ = p.recv(); // wait for child to be done
        }
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
#![allow(unused_variables)]

// Dependencies
mod vjoyinterface;
extern crate std;
extern crate libc;

// Control constants - what magic numbers do we need to play with each virtual device input?
// USB HID joystick constants. We assume our emulator is configured to map virtual joystick to N64 joystick
const HID_JOYSTICK_X: libc::c_uint = 0x30;
const HID_JOYSTICK_Y: libc::c_uint = 0x31;

// Number of digital inputs on a standard N64 controller
const NUM_N64_BUTTONS: u8 = 14;

#[derive(Debug)]
pub enum VirtualN64ControllerButton {
    A,
    B,
    Z,
    L,
    R,
    Start,
    Cup,
    Cdown,
    Cleft,
    Cright,
    Dup,
    Ddown,
    Dleft,
    Dright
}

// Default emulator button bindings. vJoy button indices are one-based
impl VirtualN64ControllerButton {
    fn get_vjoy_button_index(&self) -> libc::c_uchar {
        match *self {
            VirtualN64ControllerButton::A => 0x01,
            VirtualN64ControllerButton::B => 0x02,
            VirtualN64ControllerButton::Z => 0x03,
            VirtualN64ControllerButton::L => 0x04,
            VirtualN64ControllerButton::R => 0x05,
            VirtualN64ControllerButton::Start => 0x06,
            VirtualN64ControllerButton::Cup => 0x07,
            VirtualN64ControllerButton::Cdown => 0x08,
            VirtualN64ControllerButton::Cleft => 0x09,
            VirtualN64ControllerButton::Cright => 0x10,
            VirtualN64ControllerButton::Dup => 0x11,
            VirtualN64ControllerButton::Ddown => 0x12,
            VirtualN64ControllerButton::Dleft => 0x13,
            VirtualN64ControllerButton::Dright => 0x14
        }
    }
}

// Info about our virtual joystick
// Post-initialization, this should all be read-only
struct VirtualN64ControllerProps {
    vjoy_device_number: libc::c_uint,

    x_min: libc::c_long,
    x_max: libc::c_long,
    y_min: libc::c_long,
    y_max: libc::c_long,
}

// Last-set values
struct VirtualN64ControllerState {
    x: libc::c_long,
    y: libc::c_long,
    a: libc::c_int,
    b: libc::c_int,
    z: libc::c_int,
    l: libc::c_int,
    r: libc::c_int,
    start: libc::c_int,
    cup: libc::c_int,
    cdown: libc::c_int,
    cleft: libc::c_int,
    cright: libc::c_int,
    dup: libc::c_int,
    ddown: libc::c_int,
    dleft: libc::c_int,
    dright: libc::c_int,
}

pub struct VirtualN64Controller {
    props: VirtualN64ControllerProps,
    state: VirtualN64ControllerState,
}

impl Default for VirtualN64Controller {
    fn default() -> VirtualN64Controller {
        VirtualN64Controller {
            props: VirtualN64ControllerProps {
                vjoy_device_number: 0,
                x_min: 0,
                x_max: 0,
                y_min: 0,
                y_max: 0
            },
            state: VirtualN64ControllerState {
                x: 0,
                y: 0,
                a: 0,
                b: 0,
                z: 0,
                l: 0,
                r: 0,
                start: 0,
                cup: 0,
                cdown: 0,
                cleft: 0,
                cright: 0,
                dup: 0,
                ddown: 0,
                dleft: 0,
                dright: 0
            }
        }
    }
}

impl VirtualN64Controller {
    // Initialize a virtual N64 controller
    // After calling this successfully, controller is a valid handle for other functions
    pub fn new(vjoy_device_number: u8) -> Result<VirtualN64Controller, String> {
        let vjoy_device_number_native = vjoy_device_number as libc::c_uint;

        match get_vjoy_is_enabled() {
            Ok(val) => {
                if val == false {
                    return Err(format!("vJoy isn't enabled. Have you installed vJoy?"));
                }
            },
            Err(err) => return Err(format!("Unable to check if vJoy is enabled. Have you installed vJoy?"))
        }

        match verify_vjoystick_as_n64(vjoy_device_number_native) {
            Ok(()) => (),
            Err(err) => return Err(format!("Virtual joystick {} can't act as an N64 controller: {}.\
                                            You may need to reconfigure your vJoy device",
                                           vjoy_device_number, err))
            }

        match claim_vjoystick(vjoy_device_number_native) {
            Err(msg) => return Err(format!("{}", msg)),
            _ => ()
        }

        match reset_vjoystick(vjoy_device_number_native) {
            Err(msg) => return Err(format!("{}", msg)),
            _ => ()
        }

        match make_vn64c(vjoy_device_number_native) {
            Err(msg) => Err(format!("{}", msg)),
            Ok(controller) => Ok(controller)
        }
    }

    // Set the virtual joystick, assuming that direction is in degrees and strength is a number 0-1 inclusive
    //@todo don't trust controller argument
    //@todo validate arguments (direction: 0-359, strength: 0-1)
    pub fn set_joystick(&mut self, direction: u16, strength: f32) -> Result<(), &'static str> {
        // Convert direction from degrees to radians
        let direction_rad: f32 = (direction as f32) * std::f32::consts::PI / 180.0;

        let x_strength = direction_rad.cos() * strength;
        let y_strength = direction_rad.sin() * strength;

        let x_mid: libc::c_long = ((self.props.x_max - self.props.x_min)/2) as libc::c_long;
        let y_mid: libc::c_long = ((self.props.y_max - self.props.y_min)/2) as libc::c_long;

        let x = x_mid + (x_strength * (x_mid as f32)) as libc::c_long;
        let y = y_mid + (y_strength * (y_mid as f32)) as libc::c_long;

        match set_vjoystick_axis(self.props.vjoy_device_number, HID_JOYSTICK_X, x) {
            Ok(_) => (),
            Err(_) => return Err("Unable to set X axis")
        }
        self.state.x = x;

        match set_vjoystick_axis(self.props.vjoy_device_number, HID_JOYSTICK_Y, y) {
            Ok(_) => (),
            Err(_) => return Err("Unable to set Y axis")
        }
        self.state.y = y;

        Ok(())
    }

    pub fn set_button(&mut self, button: VirtualN64ControllerButton, value: bool) -> Result<(), &'static str> {
        let valc = value as libc::c_int;

        match set_vjoystick_button(self.props.vjoy_device_number, button.get_vjoy_button_index(), valc) {
            Ok(_) => (),
            Err(_) => return Err("Unable to set virtual joystick button")
        }

        match button {
            VirtualN64ControllerButton::A => self.state.a = valc,
            VirtualN64ControllerButton::B => self.state.b = valc,
            VirtualN64ControllerButton::Z => self.state.z = valc,
            VirtualN64ControllerButton::L => self.state.l = valc,
            VirtualN64ControllerButton::R => self.state.r = valc,
            VirtualN64ControllerButton::Start => self.state.start = valc,
            VirtualN64ControllerButton::Cup => self.state.cup = valc,
            VirtualN64ControllerButton::Cdown => self.state.cdown = valc,
            VirtualN64ControllerButton::Cleft => self.state.cleft = valc,
            VirtualN64ControllerButton::Cright => self.state.cright = valc,
            VirtualN64ControllerButton::Dup => self.state.dup = valc,
            VirtualN64ControllerButton::Ddown => self.state.ddown = valc,
            VirtualN64ControllerButton::Dleft => self.state.dleft = valc,
            VirtualN64ControllerButton::Dright => self.state.dright = valc
        }

        Ok(())
    }
}

// vJoy device utility functions
fn get_vjoy_is_enabled() -> Result<bool, ()> {
    unsafe {
        let vjoy_enabled = vjoyinterface::vJoyEnabled();
        if vjoy_enabled == 0 {
            Ok(false)
        } else {
            Ok(true)
        }
    }
}

fn get_vjoystick_axis_exists(index: libc::c_uint, axis: libc::c_uint) -> Result<bool, ()> {
    unsafe {
        let axis_exists = vjoyinterface::GetVJDAxisExist(index, axis);
        if axis_exists == 0 {
            Ok(false)
        } else {
            Ok(true)
        }
    }
}

fn get_vjoystick_axis_min(index: libc::c_uint, axis: libc::c_uint) -> Result<libc::c_long, &'static str> {
    unsafe {
        let mut min: libc::c_long = 0;
        let min_raw_pointer = &mut min as *mut libc::c_long;
        let min_result = vjoyinterface::GetVJDAxisMin(index, axis, min_raw_pointer);
        if min_result == 0 {
            Err("Unable to get axis minimum")
        } else {
            Ok(min)
        }
    }
}

fn get_vjoystick_axis_max(index: libc::c_uint, axis: libc::c_uint) -> Result<libc::c_long, &'static str> {
    unsafe {
        let mut max: libc::c_long = 0;
        let max_raw_pointer = &mut max as *mut libc::c_long;
        let max_result = vjoyinterface::GetVJDAxisMax(index, axis, max_raw_pointer);
        if max_result == 0 {
            Err("Unable to get axis maximum: does the axis exist?")
        } else {
            Ok(max)
        }
    }
}

fn get_vjoystick_button_count(index: libc::c_uint) -> Result<u8, ()> {
    unsafe {
        let num_buttons = vjoyinterface::GetVJDButtonNumber(index);

        Ok(num_buttons as u8)
    }
}

fn get_vjoystick_status(index: libc::c_uint) -> vjoyinterface::Enum_VjdStat {
    unsafe {
        let joystick_status = vjoyinterface::GetVJDStatus(index);

        joystick_status
    }
}

fn claim_vjoystick(index: libc::c_uint) -> Result<(), &'static str> {
    unsafe {
        let joystick_status = get_vjoystick_status(index);
        if joystick_status == vjoyinterface::VJD_STAT_FREE {
            // Try to claim it
            let acquire_vjd_result = vjoyinterface::AcquireVJD(index);
            if acquire_vjd_result == 0 {
                return Err("Virtual joystick is available, but unable to acquire it");
            } else {
                return Ok(());
            }
        } else if joystick_status == vjoyinterface::VJD_STAT_OWN {
            // We've already claimed it
            return Ok(());
        }
    }

    Err("Virtual joystick is owned by someone else, missing, or in unknown state")
}

fn reset_vjoystick(index: libc::c_uint) -> Result<(), &'static str> {
    unsafe {
        let reset_result = vjoyinterface::ResetVJD(index);
        if reset_result == 0 {
            return Err("vJoy reset function returned failure");
        }
    }

    Ok(())
}

fn set_vjoystick_axis(index: libc::c_uint, axis: libc::c_uint, value: libc::c_long) -> Result<(), ()> {
    unsafe {
        let set_x_result = vjoyinterface::SetAxis(value, index, axis);
        if set_x_result == 0 {
            return Err(());
        }
    }

    Ok(())
}

fn set_vjoystick_button(index: libc::c_uint, button: libc::c_uchar, value: libc::c_int) -> Result<(), ()> {
    unsafe {
        let set_result = vjoyinterface::SetBtn(value, index, button);
        if set_result == 0 {
            return Err(());
        }
    }

    Ok(())
}

// Verify that a vJoy device has the controls we need to treat it like an N64 controller
// If this fails, the vJoy device should be configured manually using vJoy's supplied configuration tool
fn verify_vjoystick_as_n64(index: libc::c_uint) -> Result<(), String> {
    match get_vjoystick_axis_exists(index, HID_JOYSTICK_X) {
        Ok(exists) => {
            if exists == false {
                return Err(format!("No X axis"));
            }
        },
        Err(()) => return Err(format!("Unable to check for X axis"))
    }

    match get_vjoystick_axis_exists(index, HID_JOYSTICK_Y) {
        Ok(exists) => {
            if exists == false {
                return Err(format!("No Y axis"));
            }
        },
        Err(()) => return Err(format!("Unable to check for Y axis"))
    }

    match get_vjoystick_button_count(index) {
        Ok(buttons) => {
            if buttons < NUM_N64_BUTTONS {
                return Err(format!("Less than {} buttons", NUM_N64_BUTTONS));
            }
        },
        Err(()) => return Err(format!("Unable to get button count"))
    }

    Ok(())
}

// Make a virtual N64 controller given a vJoy device number
fn make_vn64c(vjoy_device_number: libc::c_uint) -> Result<(VirtualN64Controller), &'static str> {
    let mut controller = VirtualN64Controller { ..Default::default() };

    controller.props.vjoy_device_number = vjoy_device_number;

    // Get and capture vjoystick min and max
    match get_vjoystick_axis_min(vjoy_device_number, HID_JOYSTICK_X) {
        Ok(min) => controller.props.x_min = min,
        Err(msg) => return Err(msg)
    };
    match get_vjoystick_axis_max(vjoy_device_number, HID_JOYSTICK_X) {
        Ok(max) => controller.props.x_max = max,
        Err(msg) => return Err(msg)
    };
    match get_vjoystick_axis_min(vjoy_device_number, HID_JOYSTICK_Y) {
        Ok(min) => controller.props.y_min = min,
        Err(msg) => return Err(msg)
    };
    match get_vjoystick_axis_min(vjoy_device_number, HID_JOYSTICK_Y) {
        Ok(max) => controller.props.y_max = max,
        Err(msg) => return Err(msg)
    };

    // Set joystick values to neutral
    controller.state.x = (controller.props.x_max - controller.props.x_min) / 2;
    controller.state.y = (controller.props.y_max - controller.props.y_min) / 2;

    Ok(controller)
}<commit_msg>Rustify libvn64c<commit_after>#![allow(dead_code)]
#![allow(unused_variables)]

// Dependencies
mod vjoyinterface;
extern crate std;
extern crate libc;

// Control constants - what magic numbers do we need to play with each virtual device input?
// USB HID joystick constants. We assume our emulator is configured to map virtual joystick to N64 joystick
const HID_JOYSTICK_X: libc::c_uint = 0x30;
const HID_JOYSTICK_Y: libc::c_uint = 0x31;

// Number of digital inputs on a standard N64 controller
const NUM_N64_BUTTONS: u8 = 14;

#[derive(Debug)]
pub enum VirtualN64ControllerButton {
    A,
    B,
    Z,
    L,
    R,
    Start,
    Cup,
    Cdown,
    Cleft,
    Cright,
    Dup,
    Ddown,
    Dleft,
    Dright
}

// Default emulator button bindings. vJoy button indices are one-based
impl VirtualN64ControllerButton {
    fn get_vjoy_button_index(&self) -> libc::c_uchar {
        match *self {
            VirtualN64ControllerButton::A => 0x01,
            VirtualN64ControllerButton::B => 0x02,
            VirtualN64ControllerButton::Z => 0x03,
            VirtualN64ControllerButton::L => 0x04,
            VirtualN64ControllerButton::R => 0x05,
            VirtualN64ControllerButton::Start => 0x06,
            VirtualN64ControllerButton::Cup => 0x07,
            VirtualN64ControllerButton::Cdown => 0x08,
            VirtualN64ControllerButton::Cleft => 0x09,
            VirtualN64ControllerButton::Cright => 0x10,
            VirtualN64ControllerButton::Dup => 0x11,
            VirtualN64ControllerButton::Ddown => 0x12,
            VirtualN64ControllerButton::Dleft => 0x13,
            VirtualN64ControllerButton::Dright => 0x14
        }
    }
}

// Info about our virtual joystick
// Post-initialization, this should all be read-only
struct VirtualN64ControllerProps {
    vjoy_device_number: libc::c_uint,

    x_min: libc::c_long,
    x_max: libc::c_long,
    y_min: libc::c_long,
    y_max: libc::c_long,
}

// Last-set values
struct VirtualN64ControllerState {
    x: libc::c_long,
    y: libc::c_long,
    a: libc::c_int,
    b: libc::c_int,
    z: libc::c_int,
    l: libc::c_int,
    r: libc::c_int,
    start: libc::c_int,
    cup: libc::c_int,
    cdown: libc::c_int,
    cleft: libc::c_int,
    cright: libc::c_int,
    dup: libc::c_int,
    ddown: libc::c_int,
    dleft: libc::c_int,
    dright: libc::c_int,
}

pub struct VirtualN64Controller {
    props: VirtualN64ControllerProps,
    state: VirtualN64ControllerState,
}

impl Default for VirtualN64Controller {
    fn default() -> VirtualN64Controller {
        VirtualN64Controller {
            props: VirtualN64ControllerProps {
                vjoy_device_number: 0,
                x_min: 0,
                x_max: 0,
                y_min: 0,
                y_max: 0
            },
            state: VirtualN64ControllerState {
                x: 0,
                y: 0,
                a: 0,
                b: 0,
                z: 0,
                l: 0,
                r: 0,
                start: 0,
                cup: 0,
                cdown: 0,
                cleft: 0,
                cright: 0,
                dup: 0,
                ddown: 0,
                dleft: 0,
                dright: 0
            }
        }
    }
}

impl VirtualN64Controller {
    // Make a virtual N64 controller given a vJoy device number
    fn from_vjoy_device_number(vjoy_device_number: libc::c_uint) -> Result<(VirtualN64Controller), &'static str> {
        let mut controller = VirtualN64Controller { ..Default::default() };

        controller.props.vjoy_device_number = vjoy_device_number;

        // Get and capture vjoystick min and max
        match get_vjoystick_axis_min(vjoy_device_number, HID_JOYSTICK_X) {
            Ok(min) => controller.props.x_min = min,
            Err(msg) => return Err(msg)
        }
        match get_vjoystick_axis_max(vjoy_device_number, HID_JOYSTICK_X) {
            Ok(max) => controller.props.x_max = max,
            Err(msg) => return Err(msg)
        }
        match get_vjoystick_axis_min(vjoy_device_number, HID_JOYSTICK_Y) {
            Ok(min) => controller.props.y_min = min,
            Err(msg) => return Err(msg)
        }
        match get_vjoystick_axis_min(vjoy_device_number, HID_JOYSTICK_Y) {
            Ok(max) => controller.props.y_max = max,
            Err(msg) => return Err(msg)
        }

        // Set joystick values to neutral
        controller.state.x = (controller.props.x_max - controller.props.x_min) / 2;
        controller.state.y = (controller.props.y_max - controller.props.y_min) / 2;

        Ok(controller)
    }

    // Verify that a vJoy device can act as a virtual N64 controller, and if so, return a virtual N64 controller
    pub fn new(vjoy_device_number: u8) -> Result<VirtualN64Controller, String> {
        let vjoy_device_number_native = vjoy_device_number as libc::c_uint;

        match get_vjoy_is_enabled() {
            Ok(val) => {
                if val == false {
                    return Err(format!("vJoy isn't enabled. Have you installed vJoy?"));
                }
            },
            Err(err) => return Err(format!("Unable to check if vJoy is enabled. Have you installed vJoy?"))
        }

        match verify_vjoystick_as_n64(vjoy_device_number_native) {
            Ok(()) => (),
            Err(err) => return Err(format!("Virtual joystick {} can't act as an N64 controller: {}.\
                                            You may need to reconfigure your vJoy device",
                                           vjoy_device_number, err))
            }

        match claim_vjoystick(vjoy_device_number_native) {
            Err(msg) => return Err(format!("{}", msg)),
            _ => ()
        }

        match reset_vjoystick(vjoy_device_number_native) {
            Err(msg) => return Err(format!("{}", msg)),
            _ => ()
        }

        match VirtualN64Controller::from_vjoy_device_number(vjoy_device_number_native) {
            Err(msg) => Err(format!("{}", msg)),
            Ok(controller) => Ok(controller)
        }
    }

    // Set the virtual joystick, assuming that direction is in degrees and strength is a number 0-1 inclusive
    pub fn set_joystick(&mut self, direction: u16, strength: f32) -> Result<(), &'static str> {
        if direction > 359 {
            return Err("Direction must be between 0 and 359");
        }
        if strength < 0.0 || strength > 1.0 {
            return Err("Strength must be between 0 and 1");
        }

        // Convert direction from degrees to radians
        let direction_rad: f32 = (direction as f32) * std::f32::consts::PI / 180.0;

        let x_strength = direction_rad.cos() * strength;
        let y_strength = direction_rad.sin() * strength;

        let x_mid: libc::c_long = ((self.props.x_max - self.props.x_min)/2) as libc::c_long;
        let y_mid: libc::c_long = ((self.props.y_max - self.props.y_min)/2) as libc::c_long;

        let x = x_mid + (x_strength * (x_mid as f32)) as libc::c_long;
        let y = y_mid + (y_strength * (y_mid as f32)) as libc::c_long;

        match set_vjoystick_axis(self.props.vjoy_device_number, HID_JOYSTICK_X, x) {
            Ok(_) => (),
            Err(_) => return Err("Unable to set X axis")
        }
        self.state.x = x;

        match set_vjoystick_axis(self.props.vjoy_device_number, HID_JOYSTICK_Y, y) {
            Ok(_) => (),
            Err(_) => return Err("Unable to set Y axis")
        }
        self.state.y = y;

        Ok(())
    }

    pub fn set_button(&mut self, button: VirtualN64ControllerButton, value: bool) -> Result<(), &'static str> {
        let valc = value as libc::c_int;

        match set_vjoystick_button(self.props.vjoy_device_number, button.get_vjoy_button_index(), valc) {
            Ok(_) => (),
            Err(_) => return Err("Unable to set virtual joystick button")
        }

        match button {
            VirtualN64ControllerButton::A => self.state.a = valc,
            VirtualN64ControllerButton::B => self.state.b = valc,
            VirtualN64ControllerButton::Z => self.state.z = valc,
            VirtualN64ControllerButton::L => self.state.l = valc,
            VirtualN64ControllerButton::R => self.state.r = valc,
            VirtualN64ControllerButton::Start => self.state.start = valc,
            VirtualN64ControllerButton::Cup => self.state.cup = valc,
            VirtualN64ControllerButton::Cdown => self.state.cdown = valc,
            VirtualN64ControllerButton::Cleft => self.state.cleft = valc,
            VirtualN64ControllerButton::Cright => self.state.cright = valc,
            VirtualN64ControllerButton::Dup => self.state.dup = valc,
            VirtualN64ControllerButton::Ddown => self.state.ddown = valc,
            VirtualN64ControllerButton::Dleft => self.state.dleft = valc,
            VirtualN64ControllerButton::Dright => self.state.dright = valc
        }

        Ok(())
    }
}

// vJoy wrapper functions
fn get_vjoy_is_enabled() -> Result<bool, ()> {
    unsafe {
        let vjoy_enabled = vjoyinterface::vJoyEnabled();
        if vjoy_enabled == 0 {
            Ok(false)
        } else {
            Ok(true)
        }
    }
}

fn get_vjoystick_axis_exists(index: libc::c_uint, axis: libc::c_uint) -> Result<bool, ()> {
    unsafe {
        let axis_exists = vjoyinterface::GetVJDAxisExist(index, axis);
        if axis_exists == 0 {
            Ok(false)
        } else {
            Ok(true)
        }
    }
}

fn get_vjoystick_axis_min(index: libc::c_uint, axis: libc::c_uint) -> Result<libc::c_long, &'static str> {
    unsafe {
        let mut min: libc::c_long = 0;
        let min_raw_pointer = &mut min as *mut libc::c_long;
        let min_result = vjoyinterface::GetVJDAxisMin(index, axis, min_raw_pointer);
        if min_result == 0 {
            Err("Unable to get axis minimum")
        } else {
            Ok(min)
        }
    }
}

fn get_vjoystick_axis_max(index: libc::c_uint, axis: libc::c_uint) -> Result<libc::c_long, &'static str> {
    unsafe {
        let mut max: libc::c_long = 0;
        let max_raw_pointer = &mut max as *mut libc::c_long;
        let max_result = vjoyinterface::GetVJDAxisMax(index, axis, max_raw_pointer);
        if max_result == 0 {
            Err("Unable to get axis maximum: does the axis exist?")
        } else {
            Ok(max)
        }
    }
}

fn get_vjoystick_button_count(index: libc::c_uint) -> Result<u8, ()> {
    unsafe {
        let num_buttons = vjoyinterface::GetVJDButtonNumber(index);

        Ok(num_buttons as u8)
    }
}

fn get_vjoystick_status(index: libc::c_uint) -> vjoyinterface::Enum_VjdStat {
    unsafe {
        let joystick_status = vjoyinterface::GetVJDStatus(index);

        joystick_status
    }
}

fn claim_vjoystick(index: libc::c_uint) -> Result<(), &'static str> {
    unsafe {
        let joystick_status = get_vjoystick_status(index);
        if joystick_status == vjoyinterface::VJD_STAT_FREE {
            // Try to claim it
            let acquire_vjd_result = vjoyinterface::AcquireVJD(index);
            if acquire_vjd_result == 0 {
                return Err("Virtual joystick is available, but unable to acquire it");
            } else {
                return Ok(());
            }
        } else if joystick_status == vjoyinterface::VJD_STAT_OWN {
            // We've already claimed it
            return Ok(());
        }
    }

    Err("Virtual joystick is owned by someone else, missing, or in unknown state")
}

fn reset_vjoystick(index: libc::c_uint) -> Result<(), &'static str> {
    unsafe {
        let reset_result = vjoyinterface::ResetVJD(index);
        if reset_result == 0 {
            return Err("vJoy reset function returned failure");
        }
    }

    Ok(())
}

fn set_vjoystick_axis(index: libc::c_uint, axis: libc::c_uint, value: libc::c_long) -> Result<(), ()> {
    unsafe {
        let set_x_result = vjoyinterface::SetAxis(value, index, axis);
        if set_x_result == 0 {
            return Err(());
        }
    }

    Ok(())
}

fn set_vjoystick_button(index: libc::c_uint, button: libc::c_uchar, value: libc::c_int) -> Result<(), ()> {
    unsafe {
        let set_result = vjoyinterface::SetBtn(value, index, button);
        if set_result == 0 {
            return Err(());
        }
    }

    Ok(())
}

// Verify that a vJoy device has the controls we need to treat it like an N64 controller
// If this fails, the vJoy device should be configured manually using vJoy's supplied configuration tool
fn verify_vjoystick_as_n64(index: libc::c_uint) -> Result<(), String> {
    match get_vjoystick_axis_exists(index, HID_JOYSTICK_X) {
        Ok(exists) => {
            if exists == false {
                return Err(format!("No X axis"));
            }
        },
        Err(()) => return Err(format!("Unable to check for X axis"))
    }

    match get_vjoystick_axis_exists(index, HID_JOYSTICK_Y) {
        Ok(exists) => {
            if exists == false {
                return Err(format!("No Y axis"));
            }
        },
        Err(()) => return Err(format!("Unable to check for Y axis"))
    }

    match get_vjoystick_button_count(index) {
        Ok(buttons) => {
            if buttons < NUM_N64_BUTTONS {
                return Err(format!("Less than {} buttons", NUM_N64_BUTTONS));
            }
        },
        Err(()) => return Err(format!("Unable to get button count"))
    }

    Ok(())
}<|endoftext|>


<commit_before>// Copyright (c) 2017-2021 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use core::convert::Infallible;
use std::time::Duration;

use embedded_hal::digital::blocking::{
    InputPin as InputPinHal, StatefulOutputPin as StatefulOutputPinHal,
    ToggleableOutputPin as ToggleableOutputPinHal,
};
use embedded_hal::pwm::blocking::Pwm as PwmHal;

use super::{InputPin, IoPin, OutputPin, Pin};
use crate::gpio::Mode;

/// Unproven `InputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::InputPin for Pin {
    type Error = Infallible;

    fn is_high(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_high(self)
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_low(self)
    }
}

/// Unproven `InputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::InputPin for InputPin {
    type Error = Infallible;

    fn is_high(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_high(self)
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_low(self)
    }
}

/// Unproven `InputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::InputPin for IoPin {
    type Error = Infallible;

    fn is_high(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_high(self)
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_low(self)
    }
}

/// Unproven `InputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::InputPin for OutputPin {
    type Error = Infallible;

    fn is_high(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_high(self)
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_low(self)
    }
}

/// Unproven `StatefulOutputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::StatefulOutputPin for IoPin {
    fn is_set_high(&self) -> Result<bool, Self::Error> {
        StatefulOutputPinHal::is_set_high(self)
    }

    fn is_set_low(&self) -> Result<bool, Self::Error> {
        StatefulOutputPinHal::is_set_low(self)
    }
}

/// Unproven `StatefulOutputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::StatefulOutputPin for OutputPin {
    fn is_set_high(&self) -> Result<bool, Self::Error> {
        StatefulOutputPinHal::is_set_high(self)
    }

    fn is_set_low(&self) -> Result<bool, Self::Error> {
        StatefulOutputPinHal::is_set_low(self)
    }
}

/// Unproven `ToggleableOutputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::ToggleableOutputPin for IoPin {
    type Error = Infallible;

    fn toggle(&mut self) -> Result<(), Self::Error> {
        ToggleableOutputPinHal::toggle(self)
    }
}

/// Unproven `ToggleableOutputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::ToggleableOutputPin for OutputPin {
    type Error = Infallible;

    fn toggle(&mut self) -> Result<(), Self::Error> {
        ToggleableOutputPinHal::toggle(self)
    }
}

/// Unproven `Pwm` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::Pwm for OutputPin {
    type Duty = f64;
    type Channel = ();
    type Time = Duration;

    /// Disables a PWM `channel`.
    fn disable(&mut self, channel: Self::Channel) {
        let _ = PwmHal::disable(self, &channel);
    }

    /// Enables a PWM `channel`.
    fn enable(&mut self, channel: Self::Channel) {
        let _ = PwmHal::enable(self, &channel);
    }

    /// Returns the current PWM period.
    fn get_period(&self) -> Self::Time {
        PwmHal::get_period(self).unwrap_or_default()
    }

    /// Returns the current duty cycle.
    fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
        PwmHal::get_duty(self, &channel).unwrap_or_default()
    }

    /// Returns the maximum duty cycle value.
    fn get_max_duty(&self) -> Self::Duty {
        PwmHal::get_max_duty(self).unwrap_or(1.0)
    }

    /// Sets a new duty cycle.
    fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
        let _ = PwmHal::set_duty(self, &channel, duty);
    }

    /// Sets a new PWM period.
    fn set_period<P>(&mut self, period: P)
    where
        P: Into<Self::Time>,
    {
        let _ = PwmHal::set_period(self, period);
    }
}

/// Unproven `Pwm` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::Pwm for IoPin {
    type Duty = f64;
    type Channel = ();
    type Time = Duration;

    /// Disables a PWM `channel`.
    fn disable(&mut self, channel: Self::Channel) {
        let _ = PwmHal::disable(self, &channel);
    }

    /// Enables a PWM `channel`.
    fn enable(&mut self, channel: Self::Channel) {
        let _ = PwmHal::enable(self, &channel);
    }

    /// Returns the current PWM period.
    fn get_period(&self) -> Self::Time {
        PwmHal::get_period(self).unwrap_or_default()
    }

    /// Returns the current duty cycle.
    fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
        PwmHal::get_duty(self, &channel).unwrap_or_default()
    }

    /// Returns the maximum duty cycle value.
    fn get_max_duty(&self) -> Self::Duty {
        PwmHal::get_max_duty(self).unwrap_or(1.0)
    }

    /// Sets a new duty cycle.
    fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
        let _ = PwmHal::set_duty(self, &channel, duty);
    }

    /// Sets a new PWM period.
    fn set_period<P>(&mut self, period: P)
    where
        P: Into<Self::Time>,
    {
        let _ = PwmHal::set_period(self, period);
    }
}

/// Unproven `IoPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::IoPin<IoPin, IoPin> for IoPin {
    type Error = Infallible;

    /// Tries to convert this pin to input mode.
    ///
    /// If the pin is already in input mode, this method should succeed.
    fn into_input_pin(mut self) -> Result<IoPin, Self::Error> {
        if self.mode() == Mode::Input {
            Ok(self)
        } else {
            self.set_mode(Mode::Input);
            Ok(self)
        }
    }

    /// Tries to convert this pin to output mode with the given initial state.
    ///
    /// If the pin is already in the requested state, this method should
    /// succeed.
    fn into_output_pin(
        mut self,
        state: embedded_hal_0::digital::v2::PinState,
    ) -> Result<IoPin, Self::Error> {
        if self.mode() == Mode::Output {
            match state {
                embedded_hal_0::digital::v2::PinState::Low => self.set_low(),
                embedded_hal_0::digital::v2::PinState::High => self.set_high(),
            }
            Ok(self)
        } else {
            self.set_mode(Mode::Output);
            match state {
                embedded_hal_0::digital::v2::PinState::Low => self.set_low(),
                embedded_hal_0::digital::v2::PinState::High => self.set_high(),
            }
            Ok(self)
        }
    }
}
<commit_msg>Refactor code<commit_after>// Copyright (c) 2017-2021 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use core::convert::Infallible;
use std::time::Duration;

use embedded_hal::digital::blocking::{
    InputPin as InputPinHal, StatefulOutputPin as StatefulOutputPinHal,
    ToggleableOutputPin as ToggleableOutputPinHal,
};
use embedded_hal::pwm::blocking::Pwm as PwmHal;

use super::{InputPin, IoPin, OutputPin, Pin};
use crate::gpio::Mode;

/// Unproven `InputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::InputPin for Pin {
    type Error = Infallible;

    fn is_high(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_high(self)
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_low(self)
    }
}

/// Unproven `InputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::InputPin for InputPin {
    type Error = Infallible;

    fn is_high(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_high(self)
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_low(self)
    }
}

/// Unproven `InputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::InputPin for IoPin {
    type Error = Infallible;

    fn is_high(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_high(self)
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_low(self)
    }
}

/// Unproven `InputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::InputPin for OutputPin {
    type Error = Infallible;

    fn is_high(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_high(self)
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_low(self)
    }
}

/// Unproven `StatefulOutputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::StatefulOutputPin for IoPin {
    fn is_set_high(&self) -> Result<bool, Self::Error> {
        StatefulOutputPinHal::is_set_high(self)
    }

    fn is_set_low(&self) -> Result<bool, Self::Error> {
        StatefulOutputPinHal::is_set_low(self)
    }
}

/// Unproven `StatefulOutputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::StatefulOutputPin for OutputPin {
    fn is_set_high(&self) -> Result<bool, Self::Error> {
        StatefulOutputPinHal::is_set_high(self)
    }

    fn is_set_low(&self) -> Result<bool, Self::Error> {
        StatefulOutputPinHal::is_set_low(self)
    }
}

/// Unproven `ToggleableOutputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::ToggleableOutputPin for IoPin {
    type Error = Infallible;

    fn toggle(&mut self) -> Result<(), Self::Error> {
        ToggleableOutputPinHal::toggle(self)
    }
}

/// Unproven `ToggleableOutputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::ToggleableOutputPin for OutputPin {
    type Error = Infallible;

    fn toggle(&mut self) -> Result<(), Self::Error> {
        ToggleableOutputPinHal::toggle(self)
    }
}

/// Unproven `Pwm` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::Pwm for OutputPin {
    type Duty = f64;
    type Channel = ();
    type Time = Duration;

    /// Disables a PWM `channel`.
    fn disable(&mut self, channel: Self::Channel) {
        let _ = PwmHal::disable(self, &channel);
    }

    /// Enables a PWM `channel`.
    fn enable(&mut self, channel: Self::Channel) {
        let _ = PwmHal::enable(self, &channel);
    }

    /// Returns the current PWM period.
    fn get_period(&self) -> Self::Time {
        PwmHal::get_period(self).unwrap_or_default()
    }

    /// Returns the current duty cycle.
    fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
        PwmHal::get_duty(self, &channel).unwrap_or_default()
    }

    /// Returns the maximum duty cycle value.
    fn get_max_duty(&self) -> Self::Duty {
        PwmHal::get_max_duty(self).unwrap_or(1.0)
    }

    /// Sets a new duty cycle.
    fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
        let _ = PwmHal::set_duty(self, &channel, duty);
    }

    /// Sets a new PWM period.
    fn set_period<P>(&mut self, period: P)
    where
        P: Into<Self::Time>,
    {
        let _ = PwmHal::set_period(self, period);
    }
}

/// Unproven `Pwm` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::Pwm for IoPin {
    type Duty = f64;
    type Channel = ();
    type Time = Duration;

    /// Disables a PWM `channel`.
    fn disable(&mut self, channel: Self::Channel) {
        let _ = PwmHal::disable(self, &channel);
    }

    /// Enables a PWM `channel`.
    fn enable(&mut self, channel: Self::Channel) {
        let _ = PwmHal::enable(self, &channel);
    }

    /// Returns the current PWM period.
    fn get_period(&self) -> Self::Time {
        PwmHal::get_period(self).unwrap_or_default()
    }

    /// Returns the current duty cycle.
    fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
        PwmHal::get_duty(self, &channel).unwrap_or_default()
    }

    /// Returns the maximum duty cycle value.
    fn get_max_duty(&self) -> Self::Duty {
        PwmHal::get_max_duty(self).unwrap_or(1.0)
    }

    /// Sets a new duty cycle.
    fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
        let _ = PwmHal::set_duty(self, &channel, duty);
    }

    /// Sets a new PWM period.
    fn set_period<P>(&mut self, period: P)
    where
        P: Into<Self::Time>,
    {
        let _ = PwmHal::set_period(self, period);
    }
}

/// Unproven `IoPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::IoPin<IoPin, IoPin> for IoPin {
    type Error = Infallible;

    /// Tries to convert this pin to input mode.
    ///
    /// If the pin is already in input mode, this method should succeed.
    fn into_input_pin(mut self) -> Result<IoPin, Self::Error> {
        if self.mode() != Mode::Input {
            self.set_mode(Mode::Input);
        }

        Ok(self)
    }

    /// Tries to convert this pin to output mode with the given initial state.
    ///
    /// If the pin is already in the requested state, this method should
    /// succeed.
    fn into_output_pin(
        mut self,
        state: embedded_hal_0::digital::v2::PinState,
    ) -> Result<IoPin, Self::Error> {
        match state {
            embedded_hal_0::digital::v2::PinState::Low => self.set_low(),
            embedded_hal_0::digital::v2::PinState::High => self.set_high(),
        }

        if self.mode() != Mode::Output {
            self.set_mode(Mode::Output);
        }

        Ok(self)
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017-2019 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use embedded_hal::digital;

use super::{InputPin, IoPin, Level, OutputPin, Pin};

impl digital::InputPin for Pin {
    fn is_high(&self) -> bool {
        Pin::read(self) == Level::High
    }

    fn is_low(&self) -> bool {
        Pin::read(self) == Level::Low
    }
}

impl digital::InputPin for InputPin {
    fn is_high(&self) -> bool {
        InputPin::is_high(self)
    }

    fn is_low(&self) -> bool {
        InputPin::is_low(self)
    }
}

impl digital::InputPin for IoPin {
    fn is_high(&self) -> bool {
        IoPin::is_high(self)
    }

    fn is_low(&self) -> bool {
        IoPin::is_low(self)
    }
}

impl digital::InputPin for OutputPin {
    fn is_high(&self) -> bool {
        OutputPin::is_set_high(self)
    }

    fn is_low(&self) -> bool {
        OutputPin::is_set_low(self)
    }
}

impl digital::StatefulOutputPin for IoPin {
    fn is_set_high(&self) -> bool {
        IoPin::is_high(self)
    }

    fn is_set_low(&self) -> bool {
        IoPin::is_low(self)
    }
}

impl digital::StatefulOutputPin for OutputPin {
    fn is_set_high(&self) -> bool {
        OutputPin::is_set_high(self)
    }

    fn is_set_low(&self) -> bool {
        OutputPin::is_set_low(self)
    }
}
<commit_msg>Implement embedded-hal ToggleableOutputPin trait<commit_after>// Copyright (c) 2017-2019 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use embedded_hal::digital;

use super::{InputPin, IoPin, Level, OutputPin, Pin};

impl digital::InputPin for Pin {
    fn is_high(&self) -> bool {
        Pin::read(self) == Level::High
    }

    fn is_low(&self) -> bool {
        Pin::read(self) == Level::Low
    }
}

impl digital::InputPin for InputPin {
    fn is_high(&self) -> bool {
        InputPin::is_high(self)
    }

    fn is_low(&self) -> bool {
        InputPin::is_low(self)
    }
}

impl digital::InputPin for IoPin {
    fn is_high(&self) -> bool {
        IoPin::is_high(self)
    }

    fn is_low(&self) -> bool {
        IoPin::is_low(self)
    }
}

impl digital::InputPin for OutputPin {
    fn is_high(&self) -> bool {
        OutputPin::is_set_high(self)
    }

    fn is_low(&self) -> bool {
        OutputPin::is_set_low(self)
    }
}

impl digital::StatefulOutputPin for IoPin {
    fn is_set_high(&self) -> bool {
        IoPin::is_high(self)
    }

    fn is_set_low(&self) -> bool {
        IoPin::is_low(self)
    }
}

impl digital::StatefulOutputPin for OutputPin {
    fn is_set_high(&self) -> bool {
        OutputPin::is_set_high(self)
    }

    fn is_set_low(&self) -> bool {
        OutputPin::is_set_low(self)
    }
}

impl digital::ToggleableOutputPin for IoPin {
    fn toggle(&mut self) {
        IoPin::toggle(self);
    }
}

impl digital::ToggleableOutputPin for OutputPin {
    fn toggle(&mut self) {
        OutputPin::toggle(self);
    }
}
<|endoftext|>