<commit_before>use std::collections::HashMap;

#[derive(Debug, PartialEq)]
pub enum CacheError {
    CapacityExceeded,
    KeyNotFound,
    KeyTooLong,
    ValueTooLong,
}

pub type CacheResult<T> = Result<T, CacheError>;

#[derive(PartialEq, Eq, Hash, Debug, Clone)]
pub struct Key {
    item: Vec<u8>,
}

impl Key {
    fn new(item: Vec<u8>) -> Key {
        Key { item: item }
    }

    fn arr(arr: &[u8]) -> Key {
        let mut v = Vec::new();
        v.extend(arr);
        Key::new(v)
    }

    fn len(&self) -> usize {
        self.item.len()
    }
}

#[derive(PartialEq, Eq, Debug, Clone)]
pub struct Value {
    item: Vec<u8>,
}

impl Value {
    fn new(item: Vec<u8>) -> Value {
        Value { item: item }
    }

    fn arr(arr: &[u8]) -> Value {
        let mut v = Vec::new();
        v.extend(arr);
        Value::new(v)
    }

    fn len(&self) -> usize {
        self.item.len()
    }
}

pub struct Cache {
    capacity: u64,
    key_maxlen: u64,
    value_maxlen: u64,
    storage: HashMap<Key, Value>,
}

impl Cache {
    fn new(capacity: u64, key_maxlen: u64, value_maxlen: u64) -> Cache {
        Cache {
            capacity: capacity,
            key_maxlen: key_maxlen,
            value_maxlen: value_maxlen,
            storage: HashMap::new(),
        }
    }

    fn with_defaults(capacity: u64) -> Cache {
        Cache::new(
            capacity,
            1024, // key_maxlen = 1kb
            1048576 // value_maxlen = 1mb
            )
    }

    fn check_key_len(&self, key: &Key) -> bool {
        key.len() as u64 <= self.key_maxlen
    }

    fn check_value_len(&self, value: &Value) -> bool {
        value.len() as u64 <= self.value_maxlen
    }

    fn contains_key(&self, key: &Key) -> CacheResult<bool> {
        // Check key size
        if (!self.check_key_len(key)) {
            return Err(CacheError::KeyTooLong);
        }

        Ok(self.storage.contains_key(key))
    }

    fn get(&self, key: &Key) -> CacheResult<&Value> {
        // Check key size
        if (!self.check_key_len(key)) {
            return Err(CacheError::KeyTooLong);
        }

        match self.storage.get(key) {
            Some(value) => Ok(value),
            None => Err(CacheError::KeyNotFound),
        }
    }

    fn set(&mut self, key: Key, value: Value) -> CacheResult<()> {
        // Check key & value sizes
        if (!self.check_key_len(&key)) {
            return Err(CacheError::KeyTooLong);
        }
        if (!self.check_value_len(&value)) {
            return Err(CacheError::ValueTooLong);
        }

        // Check capacity if adding new key
        if (!self.storage.contains_key(&key)) {
            if (self.storage.len() as u64 == self.capacity) {
                return Err(CacheError::CapacityExceeded);
            }
        }

        self.storage.insert(key, value);
        Ok(())
    }
}

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

    // helper func since assert_eq!(rv.unwrap(), err) does not work
    fn assert_rv_eq<T>(rv: CacheResult<T>, err: CacheError) {
        // First of all it's supposed to be an error
        assert!(rv.is_err());

        // Now check if the error constructor is the right one
        match rv {
            Ok(_) => (),
            Err(e) => { assert_eq!(e, err); }
        };
    }

    #[test]
    fn test_set_one_key() {
        let mut cache = Cache::with_defaults(1);

        let key = Key::arr(&[1, 2, 3]);
        let value = Value::arr(&[4, 5, 6]);

        // First set it
        cache.set(key.clone(), value.clone());

        // Then test for it
        let rv = cache.contains_key(&key);
        assert_eq!(rv.unwrap(), true);

        // Test for a key that was not set
        let rv = cache.contains_key(&Key::arr(&[9, 8]));
        assert_eq!(rv.unwrap(), false);

        // Now fetch it
        let value_found = cache.get(&key).unwrap();

        assert_eq!(value, *value_found);
    }

    #[test]
    fn test_key_not_found() {
        let mut cache = Cache::with_defaults(1);

        // Retrieve a different key to the one set
        cache.set(Key::arr(&[1]), Value::arr(&[9]));
        let rv = cache.get(&Key::arr(&[2]));

        assert_rv_eq(rv, CacheError::KeyNotFound);
    }

    #[test]
    fn test_store_beyond_capacity() {
        let mut cache = Cache::with_defaults(1);

        // we've now reached capacity
        let rv = cache.set(Key::arr(&[1]), Value::arr(&[9]));
        assert!(rv.is_ok());

        // overwriting is ok
        let rv = cache.set(Key::arr(&[1]), Value::arr(&[9]));
        assert!(rv.is_ok());

        // but we cannot store a new key
        let rv = cache.set(Key::arr(&[2]), Value::arr(&[9]));
        assert_rv_eq(rv, CacheError::CapacityExceeded);
    }

    #[test]
    fn test_exceed_item_size_limits() {
        let mut cache = Cache::new(1, 1, 1);

        // set: use a key that is too long
        let rv = cache.set(Key::arr(&[1, 2]), Value::arr(&[9]));
        assert_rv_eq(rv, CacheError::KeyTooLong);

        // set: use a value that is too long
        let rv = cache.set(Key::arr(&[1]), Value::arr(&[9, 8]));
        assert_rv_eq(rv, CacheError::ValueTooLong);

        // get: use a key that is too long
        let rv = cache.get(&Key::arr(&[1, 2]));
        assert_rv_eq(rv, CacheError::KeyTooLong);

        // contains_key: use a key that is too long
        let rv = cache.contains_key(&Key::arr(&[1, 2]));
        assert_rv_eq(rv, CacheError::KeyTooLong);
    }
}
<commit_msg>introduce key! and value! macros for defining literals<commit_after>use std::collections::HashMap;

#[derive(Debug, PartialEq)]
pub enum CacheError {
    CapacityExceeded,
    KeyNotFound,
    KeyTooLong,
    ValueTooLong,
}

pub type CacheResult<T> = Result<T, CacheError>;

#[derive(PartialEq, Eq, Hash, Debug, Clone)]
pub struct Key {
    item: Vec<u8>,
}

impl Key {
    fn new(item: Vec<u8>) -> Key {
        Key { item: item }
    }

    fn len(&self) -> usize {
        self.item.len()
    }
}

// key!(1, 2, 3) => Key { item: Vec<u8> = [1, 2, 3] }
macro_rules! key {
    ( $( $x:expr ),* ) => {
        {
            let mut vec = Vec::new();
            $(
                vec.push($x);
            )*
            Key::new(vec)
        }
    };
}

#[derive(PartialEq, Eq, Debug, Clone)]
pub struct Value {
    item: Vec<u8>,
}

impl Value {
    fn new(item: Vec<u8>) -> Value {
        Value { item: item }
    }

    fn len(&self) -> usize {
        self.item.len()
    }
}

// value!(1, 2, 3) => Value { item: Vec<u8> = [1, 2, 3] }
macro_rules! value {
    ( $( $x:expr ),* ) => {
        {
            let mut vec = Vec::new();
            $(
                vec.push($x);
            )*
            Value::new(vec)
        }
    };
}

pub struct Cache {
    capacity: u64,
    key_maxlen: u64,
    value_maxlen: u64,
    storage: HashMap<Key, Value>,
}

impl Cache {
    fn new(capacity: u64, key_maxlen: u64, value_maxlen: u64) -> Cache {
        Cache {
            capacity: capacity,
            key_maxlen: key_maxlen,
            value_maxlen: value_maxlen,
            storage: HashMap::new(),
        }
    }

    fn with_defaults(capacity: u64) -> Cache {
        Cache::new(
            capacity,
            1024, // key_maxlen = 1kb
            1048576 // value_maxlen = 1mb
            )
    }

    fn check_key_len(&self, key: &Key) -> bool {
        key.len() as u64 <= self.key_maxlen
    }

    fn check_value_len(&self, value: &Value) -> bool {
        value.len() as u64 <= self.value_maxlen
    }

    fn contains_key(&self, key: &Key) -> CacheResult<bool> {
        // Check key size
        if (!self.check_key_len(key)) {
            return Err(CacheError::KeyTooLong);
        }

        Ok(self.storage.contains_key(key))
    }

    fn get(&self, key: &Key) -> CacheResult<&Value> {
        // Check key size
        if (!self.check_key_len(key)) {
            return Err(CacheError::KeyTooLong);
        }

        match self.storage.get(key) {
            Some(value) => Ok(value),
            None => Err(CacheError::KeyNotFound),
        }
    }

    fn set(&mut self, key: Key, value: Value) -> CacheResult<()> {
        // Check key & value sizes
        if (!self.check_key_len(&key)) {
            return Err(CacheError::KeyTooLong);
        }
        if (!self.check_value_len(&value)) {
            return Err(CacheError::ValueTooLong);
        }

        // Check capacity if adding new key
        if (!self.storage.contains_key(&key)) {
            if (self.storage.len() as u64 == self.capacity) {
                return Err(CacheError::CapacityExceeded);
            }
        }

        self.storage.insert(key, value);
        Ok(())
    }
}

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

    // helper func since assert_eq!(rv.unwrap(), err) does not work
    fn assert_rv_eq<T>(rv: CacheResult<T>, err: CacheError) {
        // First of all it's supposed to be an error
        assert!(rv.is_err());

        // Now check if the error constructor is the right one
        match rv {
            Ok(_) => (),
            Err(e) => { assert_eq!(e, err); }
        };
    }

    #[test]
    fn test_set_one_key() {
        let mut cache = Cache::with_defaults(1);

        let key = key!(1, 2, 3);
        let value = value!(4, 5, 6);

        // First set it
        cache.set(key.clone(), value.clone());

        // Then test for it
        let rv = cache.contains_key(&key);
        assert_eq!(rv.unwrap(), true);

        // Test for a key that was not set
        let rv = cache.contains_key(&key!(9, 8));
        assert_eq!(rv.unwrap(), false);

        // Now fetch it
        let value_found = cache.get(&key).unwrap();

        assert_eq!(value, *value_found);
    }

    #[test]
    fn test_key_not_found() {
        let mut cache = Cache::with_defaults(1);

        // Retrieve a different key to the one set
        cache.set(key!(1), value!(9));
        let rv = cache.get(&key!(2));

        assert_rv_eq(rv, CacheError::KeyNotFound);
    }

    #[test]
    fn test_store_beyond_capacity() {
        let mut cache = Cache::with_defaults(1);

        // we've now reached capacity
        let rv = cache.set(key!(1), value!(9));
        assert!(rv.is_ok());

        // overwriting is ok
        let rv = cache.set(key!(1), value!(9));
        assert!(rv.is_ok());

        // but we cannot store a new key
        let rv = cache.set(key!(2), value!(9));
        assert_rv_eq(rv, CacheError::CapacityExceeded);
    }

    #[test]
    fn test_exceed_item_size_limits() {
        let mut cache = Cache::new(1, 1, 1);

        // set: use a key that is too long
        let rv = cache.set(key!(1, 2), value!(9));
        assert_rv_eq(rv, CacheError::KeyTooLong);

        // set: use a value that is too long
        let rv = cache.set(key!(1), value!(9, 8));
        assert_rv_eq(rv, CacheError::ValueTooLong);

        // get: use a key that is too long
        let rv = cache.get(&key!(1, 2));
        assert_rv_eq(rv, CacheError::KeyTooLong);

        // contains_key: use a key that is too long
        let rv = cache.contains_key(&key!(1, 2));
        assert_rv_eq(rv, CacheError::KeyTooLong);
    }
}
<|endoftext|>


<commit_before>//! A TCP RelayServer that intercepts messages between servers inside an
//! integration test. Right now it just allows us to simulate nodes going offline
//! but we could extend it to expose information about which messages have been sent
//! for testing asserts.
//!
//! #Examples
//!
//! ```
//! let relay_server = RelayServer::new_with_addresses(NUM_ADDRESSES);
//! let addrs = relay_server.get_bound_addresses();
//! for addr in addrs {
//!     // start up a new Raft server (can pass in all bound addrs as the addrs for the other
//!     // servers)
//!     # let raft_server_addr = "127.0.0.1:0";
//!     relay_server.relay_address(addr, raft_server_addr);
//! }
//! // relay server is now set up and forwarding messages between raft servers.
//! ```
//!

use std::collections::HashMap;
use std::collections::hash_map::Keys;
use std::net::{SocketAddr, TcpListener, TcpStream, Shutdown};
use std::thread;
use std::sync::{Arc, Mutex};
use std::io::{Read, Write};

pub struct RelayServer {
    addrs: Arc<Mutex<HashMap<SocketAddr, SocketInfo>>>
}

struct SocketInfo {
    to_addr: Option<SocketAddr>,
    online: bool
}

impl RelayServer {
    pub fn new() -> RelayServer {
        RelayServer {addrs: Arc::new(Mutex::new(HashMap::new()))}
    }

    pub fn new_with_random_addresses(num_addresses: u64) -> RelayServer {
        let mut server = RelayServer::new();
        server.bind_random_addresses(num_addresses);
        server
    }

    /// Binds to num_addresses addresses. Ports are assigned by the OS.
    /// Does not initially route their messages anywhere
    ///
    /// #Panics
    /// Panics if it is unable to acquire enough bound TCP ports.
    /// Or if one of the server's background threads have panicked.
    pub fn bind_random_addresses(&mut self, num_addresses: u64) {
        let mut addrs = self.addrs.lock().unwrap();
        for i in 0..num_addresses {
            let listener = TcpListener::bind("127.0.0.0:0").unwrap();
            let socket_info = SocketInfo {to_addr: None, online: false};
            addrs.insert(listener.local_addr().unwrap(), socket_info);

            let addrs_clone = self.addrs.clone();
            // spawn a background thread to listen on this port
            thread::spawn (move || RelayServer::relay_messages(listener, addrs_clone));
        }
    }

    /// Returns a vector containing the bound socket addrs
    pub fn get_bound_addresses(&self) -> Vec<SocketAddr> {
        let addrs = self.addrs.lock().unwrap();
        addrs.keys()
             .cloned()
             .take(addrs.len())
             .collect::<Vec<SocketAddr>>()
    }

    /// Sets up a new mapping from from_address to to_address.
    /// Initially the mapping is online. Use set_address_active to change this
    ///
    /// #Panics
    /// Panics if the from_address is not an existing mapping
    /// Also panics if any of the server's background threads have panicked.
    pub fn relay_address(&mut self, from_address: SocketAddr, to_address: SocketAddr) {
        let mut addrs = self.addrs.lock().unwrap();
        let socket_info: &mut SocketInfo = addrs.get_mut(&from_address).unwrap();

        socket_info.to_addr = Some(to_address);
        socket_info.online = true;
    }

    /// Toggles a mapping online or offline.
    ///
    /// #Panics
    /// Panics if the from_address is not an existing mapping
    /// Also panics if any of the server's background threads have panicked.
    pub fn set_address_active(&mut self, from_address: SocketAddr, online: bool) {
        let mut addrs = self.addrs.lock().unwrap();
        addrs.get_mut(&from_address).unwrap().online = true;
    }

    /// Runs in a background thread, and relays messages according to the hash map.
    fn relay_messages(listener: TcpListener, addrs: Arc<Mutex<HashMap<SocketAddr, SocketInfo>>>) {
        let local_addr = listener.local_addr().unwrap();
        for stream in listener.incoming() {
            match stream {
                Ok (mut stream) => {
                    let addrs = addrs.lock().unwrap();
                    match addrs.get(&local_addr) {
                        Some(info) => {
                            if info.online {
                                RelayServer::relay_stream_to_addr(stream, info.to_addr.unwrap());
                            }
                        },
                        None => {}
                    }
                },
                Err (e) => {
                    // conection errors are dropped
                }
            }
        }
    }

    /// Relays the given stream to the to_addr and sends the result back to the stream.
    fn relay_stream_to_addr(mut stream: TcpStream, to_addr: SocketAddr) {
        // Open a connection to to_addr
        let mut outgoing = TcpStream::connect(to_addr).unwrap();

        let mut outgoing_clone = outgoing.try_clone().unwrap();
        let mut stream_clone = stream.try_clone().unwrap();
        thread::spawn (move || RelayServer::relay_stream_to_stream(outgoing_clone, stream_clone));

        RelayServer::relay_stream_to_stream(stream, outgoing);
    }

    /// Relays messages from from_stream to to_stream until
    /// EOF is reached on from_stream. At this point we send
    /// an EOF on to_stream
    ///
    /// #Panics
    /// Panics if the from_stream cannot be read from or the to_stream can
    /// not be written to
    fn relay_stream_to_stream(mut from_stream: TcpStream, mut to_stream: TcpStream) {
        let mut buf: Vec<u8> = Vec::new();

        loop {
            let bytes_read = from_stream.read(&mut buf[..]).unwrap();
            if bytes_read == 0 {
                to_stream.shutdown(Shutdown::Write);
            }
            to_stream.write(&buf[0..bytes_read]);
            to_stream.flush();
        }
    }
}
<commit_msg>test: Relay server background threads exit<commit_after>//! A TCP RelayServer that intercepts messages between servers inside an
//! integration test. Right now it just allows us to simulate nodes going offline
//! but we could extend it to expose information about which messages have been sent
//! for testing asserts.
//!
//! #Examples
//!
//! ```
//! let relay_server = RelayServer::new_with_addresses(NUM_ADDRESSES);
//! let addrs = relay_server.get_bound_addresses();
//! for addr in addrs {
//!     // start up a new Raft server (can pass in all bound addrs as the addrs for the other
//!     // servers)
//!     # let raft_server_addr = "127.0.0.1:0";
//!     relay_server.relay_address(addr, raft_server_addr);
//! }
//! // relay server is now set up and forwarding messages between raft servers.
//! ```
//!

use std::collections::HashMap;
use std::collections::hash_map::Keys;
use std::net::{SocketAddr, TcpListener, TcpStream, Shutdown};
use std::thread;
use std::sync::{Arc, Mutex};
use std::io::{Read, Write};

pub struct RelayServer {
    addrs: Arc<Mutex<HashMap<SocketAddr, SocketInfo>>>
}

struct SocketInfo {
    to_addr: Option<SocketAddr>,
    online: bool
}

impl RelayServer {
    pub fn new() -> RelayServer {
        RelayServer {addrs: Arc::new(Mutex::new(HashMap::new()))}
    }

    pub fn new_with_random_addresses(num_addresses: u64) -> RelayServer {
        let mut server = RelayServer::new();
        server.bind_random_addresses(num_addresses);
        server
    }

    /// Binds to num_addresses addresses. Ports are assigned by the OS.
    /// Does not initially route their messages anywhere
    ///
    /// #Panics
    /// Panics if it is unable to acquire enough bound TCP ports.
    /// Or if one of the server's background threads have panicked.
    pub fn bind_random_addresses(&mut self, num_addresses: u64) {
        let mut addrs = self.addrs.lock().unwrap();
        for i in 0..num_addresses {
            let listener = TcpListener::bind("127.0.0.0:0").unwrap();
            let socket_info = SocketInfo {to_addr: None, online: false};
            addrs.insert(listener.local_addr().unwrap(), socket_info);

            let addrs_clone = self.addrs.clone();
            // spawn a background thread to listen on this port
            thread::spawn (move || RelayServer::relay_messages(listener, addrs_clone));
        }
    }

    /// Returns a vector containing the bound socket addrs
    pub fn get_bound_addresses(&self) -> Vec<SocketAddr> {
        let addrs = self.addrs.lock().unwrap();
        addrs.keys()
             .cloned()
             .take(addrs.len())
             .collect::<Vec<SocketAddr>>()
    }

    /// Sets up a new mapping from from_address to to_address.
    /// Initially the mapping is online. Use set_address_active to change this
    ///
    /// #Panics
    /// Panics if the from_address is not an existing mapping
    /// Also panics if any of the server's background threads have panicked.
    pub fn relay_address(&mut self, from_address: SocketAddr, to_address: SocketAddr) {
        let mut addrs = self.addrs.lock().unwrap();
        let socket_info: &mut SocketInfo = addrs.get_mut(&from_address).unwrap();

        socket_info.to_addr = Some(to_address);
        socket_info.online = true;
    }

    /// Toggles a mapping online or offline.
    ///
    /// #Panics
    /// Panics if the from_address is not an existing mapping
    /// Also panics if any of the server's background threads have panicked.
    pub fn set_address_active(&mut self, from_address: SocketAddr, online: bool) {
        let mut addrs = self.addrs.lock().unwrap();
        addrs.get_mut(&from_address).unwrap().online = true;
    }

    /// Runs in a background thread, and relays messages according to the hash map.
    fn relay_messages(listener: TcpListener, addrs: Arc<Mutex<HashMap<SocketAddr, SocketInfo>>>) {
        let local_addr = listener.local_addr().unwrap();
        for stream in listener.incoming() {
            match stream {
                Ok (mut stream) => {
                    let addrs = addrs.lock().unwrap();
                    match addrs.get(&local_addr) {
                        Some(info) => {
                            if info.online {
                                RelayServer::relay_stream_to_addr(stream, info.to_addr.unwrap());
                            }
                        },
                        None => {}
                    }
                },
                Err (e) => {
                    // conection errors are dropped
                }
            }
        }
    }

    /// Relays the given stream to the to_addr and sends the result back to the stream.
    fn relay_stream_to_addr(mut stream: TcpStream, to_addr: SocketAddr) {
        // Open a connection to to_addr
        let mut outgoing = TcpStream::connect(to_addr).unwrap();

        let mut outgoing_clone = outgoing.try_clone().unwrap();
        let mut stream_clone = stream.try_clone().unwrap();
        thread::spawn (move || RelayServer::relay_stream_to_stream(outgoing_clone, stream_clone));

        RelayServer::relay_stream_to_stream(stream, outgoing);
    }

    /// Relays messages from from_stream to to_stream until
    /// EOF is reached on from_stream. At this point we send
    /// an EOF on to_stream
    ///
    /// #Panics
    /// Panics if the from_stream cannot be read from or the to_stream can
    /// not be written to
    fn relay_stream_to_stream(mut from_stream: TcpStream, mut to_stream: TcpStream) {
        let mut buf: Vec<u8> = Vec::new();

        loop {
            let bytes_read = from_stream.read(&mut buf[..]).unwrap();
            if bytes_read == 0 {
                to_stream.shutdown(Shutdown::Write);
                break;
            }
            to_stream.write(&buf[0..bytes_read]);
            to_stream.flush();
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Add Markdown (md) support<commit_after><|endoftext|>


<commit_before>#[macro_export]
macro_rules! gc_ref_type {
    (pub struct $ref_type:ident / $storage_type:ident <'a> {
        $($field_name:ident / $field_setter_name:ident : $field_type: ty),*
    }) => {
        struct $storage_type <'a> {
            $($field_name: <$field_type as $crate::HeapInline<'a>>::Storage,)*
        }

        unsafe impl<'a> $crate::Mark<'a> for $storage_type<'a> {
            unsafe fn mark(ptr: *mut $storage_type<'a>) {
                if !$crate::Heap::get_mark_bit(ptr) {
                    $crate::Heap::set_mark_bit(ptr);
                    $(
                        $crate::Mark::mark(
                            &mut (*ptr).$field_name
                                as *mut <$field_type as $crate::HeapInline<'a>>::Storage);
                    )*
                }
            }
        }

        unsafe impl<'a> $crate::Mark<'a> for *mut $storage_type<'a> {
            unsafe fn mark(field_ptr: *mut *mut $storage_type<'a>) {
                let ptr = *field_ptr;
                if !ptr.is_null() {
                    Mark::mark(ptr);
                }
            }
        }

        #[allow(raw_pointer_derive)]
        #[derive(Clone, Debug, PartialEq)]
        pub struct $ref_type<'a>($crate::PinnedRef<'a, $storage_type<'a>>);

        impl<'a> $ref_type<'a> {
            $(
                pub fn $field_name(&self) -> $field_type {
                    let ptr = self.0.ptr;
                    unsafe {
                        <$field_type as $crate::HeapInline<'a>>::from_heap(
                            &*self.0.heap,
                            &(*ptr).$field_name)
                    }
                }

                pub fn $field_setter_name(&self, v: $field_type) {
                    let ptr = self.0.ptr;
                    unsafe {
                        (*ptr).$field_name =
                            <$field_type as $crate::HeapInline<'a>>::to_heap(v);
                    }
                }
            )*
        }

        unsafe impl<'a> $crate::HeapInline<'a> for $ref_type<'a> {
            type Storage = *mut $storage_type<'a>;

            fn to_heap(self) -> Self::Storage {
                self.0.ptr
            }

            unsafe fn from_heap(heap: &$crate::Heap<'a>, v: &Self::Storage) -> Self {
                $ref_type($crate::PinnedRef::new(heap, *v))
            }
        }

        impl<'a> $crate::GCRef for $ref_type<'a> {
            #[cfg(test)]
            fn address(&self) -> usize {
                unsafe { ::std::mem::transmute(self.0.ptr) }
            }
        }
    }
}

#[macro_export]
macro_rules! gc_inline_enum {
    {
        AS_ITEM $x:item
    } => {
        $x
    };

    {
        PARSE_VARIANTS $helper_name:ident
        {}
        $( $etc:tt )*
    } => {
        gc_inline_enum! {
            $helper_name DONE
            $($etc)*
        }
    };

    {
        PARSE_VARIANTS $helper_name:ident
        { $variant_name:ident }
        $( $etc:tt )*
    } => {
        gc_inline_enum! {
            $helper_name VARIANT $variant_name NO_FIELDS
            {}
            $($etc)*
        }
    };

    {
        PARSE_VARIANTS $helper_name:ident
        { $variant_name:ident , $($more_variants:tt)* }
        $( $etc:tt )*
    } => {
        gc_inline_enum! {
            $helper_name VARIANT $variant_name NO_FIELDS
            { $($more_variants)* }
            $($etc)*
        }
    };

    {
        PARSE_VARIANTS $helper_name:ident
        { $variant_name:ident ( $($field_types:tt)* ) }
        $( $etc:tt )*
    } => {
        gc_inline_enum! {
            $helper_name VARIANT $variant_name ( $($field_types)* )
            { }
            $($etc)*
        }
    };

    {
        PARSE_VARIANTS $helper_name:ident
        { $variant_name:ident ( $($field_types:tt)* ), $($more_variants:tt)* }
        $( $etc:tt )*
    } => {
        gc_inline_enum! {
            $helper_name VARIANT $variant_name ( $($field_types)* )
            { $($more_variants)* }
            $($etc)*
        }
    };

    {
        DECLARE_STORAGE_TYPE DONE { $($accumulated_output:tt)* } $storage_type:ident
    } => {
        gc_inline_enum! {
            AS_ITEM
            enum $storage_type<'a> {
                $($accumulated_output)*
            }
        }
    };

    {
        DECLARE_STORAGE_TYPE VARIANT $variant_name:ident NO_FIELDS
        $more_variants:tt
        { $($accumulated_output:tt)* }
        $storage_type:ident
    } => {
        gc_inline_enum! {
            PARSE_VARIANTS DECLARE_STORAGE_TYPE $more_variants {
                $($accumulated_output)*
                $variant_name,
            }
            $storage_type
        }
    };

    {
        DECLARE_STORAGE_TYPE VARIANT $variant_name:ident ( $($field_type:ty),* )
        $more_variants:tt
        { $($accumulated_output:tt)* }
        $storage_type:ident
    } => {
        gc_inline_enum! {
            PARSE_VARIANTS DECLARE_STORAGE_TYPE $more_variants {
                $($accumulated_output)*
                $variant_name($(<$field_type as $crate::HeapInline<'a>>::Storage),*),
            }
            $storage_type
        }
    };

    {
        IMPL_MARK DONE { $($accumulated_output:tt)* } $storage_type:ident
    } => {
        gc_inline_enum! {
            AS_ITEM
            unsafe impl<'a> $crate::Mark<'a> for $storage_type<'a> {
                unsafe fn mark(ptr: *mut $storage_type<'a>) {
                    match *ptr {
                        $($accumulated_output)*
                    }
                }
            }
        }
    };

    {
        IMPL_MARK VARIANT $name:ident NO_FIELDS
        $more_variants:tt
        { $($accumulated_output:tt)* }
        $storage_type:ident
    } => {
        gc_inline_enum! {
            PARSE_VARIANTS IMPL_MARK $more_variants {
                $($accumulated_output)*
                $storage_type::$name => (),
            }
            $storage_type
        }
    };

    {
        IMPL_MARK VARIANT $name:ident ( $($field_type:ty),* )
        $($etc:tt)*
    } => {
        gc_inline_enum! {
            TYPES_TO_IDENTS ( $($field_type),*, ) () (a b c d e f g h i j k l m n o p q r s t u v w x y z)
            (IMPL_MARK CONTINUE_VARIANT $name $($etc)*)
        }
    };

    {
        IMPL_MARK CONTINUE_VARIANT $name:ident
        $more_variants:tt
        { $($accumulated_output:tt)* }
        $storage_type:ident
        ( $(($binding:ident : $field_type:ty))* )
    } => {
        gc_inline_enum! {
            PARSE_VARIANTS IMPL_MARK $more_variants {
                $($accumulated_output)*
                $storage_type::$name ( $(ref mut $binding),* ) => {
                    $( $crate::Mark::mark($binding as *mut <$field_type as HeapInline<'a>>::Storage); )*
                }
            }
            $storage_type
        }
    };

    { TYPES_TO_IDENTS () ($(($binding:ident : $btype:ty))*) $_leftovers:tt ($($ctn:tt)*) } => {
        gc_inline_enum! { $($ctn)* ($(($binding : $btype))*) }
    };
    {
        TYPES_TO_IDENTS
        ($t:ty, $($ts:ty),*)
        ($(($binding:ident : $btype:ty))*)
        ($id:ident $($ids:tt)*)
        ($($ctn:tt)*)
    } => {
        gc_inline_enum! {
            TYPES_TO_IDENTS
            ($($ts),*)
            ($(($binding : $btype))* ($id : $t))
            ($($ids)*)
            ($($ctn)*)
        }
    };

    {
        pub enum $stack_type:ident / $storage_type:ident <'a>
            $variants:tt
    } => {

        gc_inline_enum! {
            PARSE_VARIANTS DECLARE_STORAGE_TYPE $variants {}
            $storage_type
        }

        gc_inline_enum! {
            AS_ITEM
            #[derive(Debug, Clone, PartialEq)]
            pub enum $stack_type<'a>
                $variants
        }

        gc_inline_enum! {
            PARSE_VARIANTS IMPL_MARK $variants {}
            $storage_type
        }
                /*
        pub enum $storage_type<'a> {
            gc_inline_enum!(FOR_EACH_VARIANT VARIANT_STORAGE $variants {})
        }

        unsafe impl<'a> $crate::Mark<'a> for $storage_type<'a> {
            unsafe fn mark(ptr: *mut $storage_type<'a>) {
                match *ptr {
                    gc_inline_enum!(FOR_EACH_VARIANT MARK $variants {}),
                }
            }
        }

        unsafe impl<'a> $crate::HeapInline<'a> for $stack_type<'a> {
            type Storage = $storage_type<'a>;

            fn to_heap(self) -> $storage<'a> {
                match self {
                    $(
                        $stack_type::$variant_name
                            gc_inline_enum!(VARIANT_PATTERN $($variant)*)
                            =>
                            $storage_type::$variant_name
                            gc_inline_enum!(VARIANT_TO_HEAP $($variant)*)
                    ),*
                }
            }

            unsafe fn from_heap(heap: &$crate::Heap<'a>, v: &$storage_type<'a>)
                -> $stack_type<'a>
            {
                match v {
                    $(
                        &$storage_type::$variant_name
                            gc_inline_enum!(VARIANT_PATTERN_BY_REF $($variant)*)
                            =>
                            $stack_type::$variant_name
                            gc_inline_enum!(VARIANT_FROM_HEAP $($variant)*)
                    ),*
                    &ValueStorage::Int(n) => Value::Int(n),
                    &ValueStorage::Str(ref rcstr) => Value::Str(rcstr.clone()),
                    &ValueStorage::Pair(ref ptr) => Value::Pair(HeapInline::<'a>::from_heap(heap, ptr))
                }
            }
        }
*/
    }
}

/*
    (VARIANT_STORAGE $variant_name:ident NO_FIELDS $ignore:tt) => (
        $variant_name
    );
    (VARIANT_STORAGE $variant_name:ident ($($field_type:ty),*) $ignore:tt) => (
        $variant_name ($($field_type),*)
    );

    (MARK $variant_name:ident NO_FIELDS $ignore:tt) => (
        $variant_name => ()
    );
    (MARK $variant_name:ident ($(field_type: ty),*) (
        $ignore:ident / $storage_type:ident
    )) => (
        $storage_type::$variant_name
            ( gc_inline_enum!(FOR_EACH_TYPE_EMIT_REF_BINDING $($field_type)*) )
            => {
                $($crate::Mark::mark();)*
            }
    );

    (STACK_VARIANT $variant_name:ident NO_FIELDS $ignore:tt) => {
        $variant_name
    };
    (STACK_VARIANT $variant_name:ident ($($field_type: ty),*) $ignore:tt) => {
        $variant_name($($field_type),*)
    };
*/
<commit_msg>Delete a bunch of stale comments. Whitespace.<commit_after>#[macro_export]
macro_rules! gc_ref_type {
    (pub struct $ref_type:ident / $storage_type:ident <'a> {
        $($field_name:ident / $field_setter_name:ident : $field_type: ty),*
    }) => {
        struct $storage_type <'a> {
            $($field_name: <$field_type as $crate::HeapInline<'a>>::Storage,)*
        }

        unsafe impl<'a> $crate::Mark<'a> for $storage_type<'a> {
            unsafe fn mark(ptr: *mut $storage_type<'a>) {
                if !$crate::Heap::get_mark_bit(ptr) {
                    $crate::Heap::set_mark_bit(ptr);
                    $(
                        $crate::Mark::mark(
                            &mut (*ptr).$field_name
                                as *mut <$field_type as $crate::HeapInline<'a>>::Storage);
                    )*
                }
            }
        }

        unsafe impl<'a> $crate::Mark<'a> for *mut $storage_type<'a> {
            unsafe fn mark(field_ptr: *mut *mut $storage_type<'a>) {
                let ptr = *field_ptr;
                if !ptr.is_null() {
                    Mark::mark(ptr);
                }
            }
        }

        #[allow(raw_pointer_derive)]
        #[derive(Clone, Debug, PartialEq)]
        pub struct $ref_type<'a>($crate::PinnedRef<'a, $storage_type<'a>>);

        impl<'a> $ref_type<'a> {
            $(
                pub fn $field_name(&self) -> $field_type {
                    let ptr = self.0.ptr;
                    unsafe {
                        <$field_type as $crate::HeapInline<'a>>::from_heap(
                            &*self.0.heap,
                            &(*ptr).$field_name)
                    }
                }

                pub fn $field_setter_name(&self, v: $field_type) {
                    let ptr = self.0.ptr;
                    unsafe {
                        (*ptr).$field_name =
                            <$field_type as $crate::HeapInline<'a>>::to_heap(v);
                    }
                }
            )*
        }

        unsafe impl<'a> $crate::HeapInline<'a> for $ref_type<'a> {
            type Storage = *mut $storage_type<'a>;

            fn to_heap(self) -> Self::Storage {
                self.0.ptr
            }

            unsafe fn from_heap(heap: &$crate::Heap<'a>, v: &Self::Storage) -> Self {
                $ref_type($crate::PinnedRef::new(heap, *v))
            }
        }

        impl<'a> $crate::GCRef for $ref_type<'a> {
            #[cfg(test)]
            fn address(&self) -> usize {
                unsafe { ::std::mem::transmute(self.0.ptr) }
            }
        }
    }
}

#[macro_export]
macro_rules! gc_inline_enum {
    { AS_ITEM $x:item } => { $x };

    {
        PARSE_VARIANTS $helper_name:ident
        {}
        $( $etc:tt )*
    } => {
        gc_inline_enum! {
            $helper_name DONE
            $($etc)*
        }
    };

    {
        PARSE_VARIANTS $helper_name:ident
        { $variant_name:ident }
        $( $etc:tt )*
    } => {
        gc_inline_enum! {
            $helper_name VARIANT $variant_name NO_FIELDS
            {}
            $($etc)*
        }
    };

    {
        PARSE_VARIANTS $helper_name:ident
        { $variant_name:ident , $($more_variants:tt)* }
        $( $etc:tt )*
    } => {
        gc_inline_enum! {
            $helper_name VARIANT $variant_name NO_FIELDS
            { $($more_variants)* }
            $($etc)*
        }
    };

    {
        PARSE_VARIANTS $helper_name:ident
        { $variant_name:ident ( $($field_types:tt)* ) }
        $( $etc:tt )*
    } => {
        gc_inline_enum! {
            $helper_name VARIANT $variant_name ( $($field_types)* )
            { }
            $($etc)*
        }
    };

    {
        PARSE_VARIANTS $helper_name:ident
        { $variant_name:ident ( $($field_types:tt)* ), $($more_variants:tt)* }
        $( $etc:tt )*
    } => {
        gc_inline_enum! {
            $helper_name VARIANT $variant_name ( $($field_types)* )
            { $($more_variants)* }
            $($etc)*
        }
    };

    {
        DECLARE_STORAGE_TYPE DONE { $($accumulated_output:tt)* } $storage_type:ident
    } => {
        gc_inline_enum! {
            AS_ITEM
            enum $storage_type<'a> {
                $($accumulated_output)*
            }
        }
    };

    {
        DECLARE_STORAGE_TYPE VARIANT $variant_name:ident NO_FIELDS
        $more_variants:tt
        { $($accumulated_output:tt)* }
        $storage_type:ident
    } => {
        gc_inline_enum! {
            PARSE_VARIANTS DECLARE_STORAGE_TYPE $more_variants {
                $($accumulated_output)*
                $variant_name,
            }
            $storage_type
        }
    };

    {
        DECLARE_STORAGE_TYPE VARIANT $variant_name:ident ( $($field_type:ty),* )
        $more_variants:tt
        { $($accumulated_output:tt)* }
        $storage_type:ident
    } => {
        gc_inline_enum! {
            PARSE_VARIANTS DECLARE_STORAGE_TYPE $more_variants {
                $($accumulated_output)*
                $variant_name($(<$field_type as $crate::HeapInline<'a>>::Storage),*),
            }
            $storage_type
        }
    };

    {
        IMPL_MARK DONE { $($accumulated_output:tt)* } $storage_type:ident
    } => {
        gc_inline_enum! {
            AS_ITEM
            unsafe impl<'a> $crate::Mark<'a> for $storage_type<'a> {
                unsafe fn mark(ptr: *mut $storage_type<'a>) {
                    match *ptr {
                        $($accumulated_output)*
                    }
                }
            }
        }
    };

    {
        IMPL_MARK VARIANT $name:ident NO_FIELDS
        $more_variants:tt
        { $($accumulated_output:tt)* }
        $storage_type:ident
    } => {
        gc_inline_enum! {
            PARSE_VARIANTS IMPL_MARK $more_variants {
                $($accumulated_output)*
                $storage_type::$name => (),
            }
            $storage_type
        }
    };

    {
        IMPL_MARK VARIANT $name:ident ( $($field_type:ty),* )
        $($etc:tt)*
    } => {
        gc_inline_enum! {
            TYPES_TO_IDENTS ( $($field_type),*, ) () (a b c d e f g h i j k l m n o p q r s t u v w x y z)
            (IMPL_MARK CONTINUE_VARIANT $name $($etc)*)
        }
    };

    {
        IMPL_MARK CONTINUE_VARIANT $name:ident
        $more_variants:tt
        { $($accumulated_output:tt)* }
        $storage_type:ident
        ( $(($binding:ident : $field_type:ty))* )
    } => {
        gc_inline_enum! {
            PARSE_VARIANTS IMPL_MARK $more_variants {
                $($accumulated_output)*
                $storage_type::$name ( $(ref mut $binding),* ) => {
                    $( $crate::Mark::mark($binding as *mut <$field_type as HeapInline<'a>>::Storage); )*
                }
            }
            $storage_type
        }
    };

    { TYPES_TO_IDENTS () ($(($binding:ident : $btype:ty))*) $_leftovers:tt ($($ctn:tt)*) } => {
        gc_inline_enum! { $($ctn)* ($(($binding : $btype))*) }
    };
    {
        TYPES_TO_IDENTS
        ($t:ty, $($ts:ty),*)
        ($(($binding:ident : $btype:ty))*)
        ($id:ident $($ids:tt)*)
        ($($ctn:tt)*)
    } => {
        gc_inline_enum! {
            TYPES_TO_IDENTS
            ($($ts),*)
            ($(($binding : $btype))* ($id : $t))
            ($($ids)*)
            ($($ctn)*)
        }
    };

    {
        pub enum $stack_type:ident / $storage_type:ident <'a>
            $variants:tt
    } => {
        gc_inline_enum! {
            PARSE_VARIANTS DECLARE_STORAGE_TYPE $variants {}
            $storage_type
        }

        gc_inline_enum! {
            AS_ITEM
            #[derive(Debug, Clone, PartialEq)]
            pub enum $stack_type<'a>
                $variants
        }

        gc_inline_enum! {
            PARSE_VARIANTS IMPL_MARK $variants {}
            $storage_type
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-2014 The CGMath Developers. For a full listing of the authors,
// refer to the Cargo.toml file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Utility macros for code generation

#![macro_use]

#[cfg(feature = "simd")]
macro_rules! default_fn {
    { $($tt:tt)* } => { default fn $( $tt )* };
}

#[cfg(not(feature = "simd"))]
macro_rules! default_fn {
    { $($tt:tt)* } => { fn $( $tt )* };
}

/// Generates a binary operator implementation for the permutations of by-ref and by-val
macro_rules! impl_operator {
    // When it is an unary operator
    (<$S:ident: $Constraint:ident> $Op:ident for $Lhs:ty {
        fn $op:ident($x:ident) -> $Output:ty { $body:expr }
    }) => {
        impl<$S: $Constraint> $Op for $Lhs {
            type Output = $Output;
            #[inline]
            default_fn!($op(self) -> $Output {
                let $x = self; $body
            });
        }

        impl<'a, $S: $Constraint> $Op for &'a $Lhs {
            type Output = $Output;
            #[inline]
            default_fn!($op(self) -> $Output {
                let $x = self; $body
            });
        }
    };
    // When the right operand is a scalar
    (<$S:ident: $Constraint:ident> $Op:ident<$Rhs:ident> for $Lhs:ty {
        fn $op:ident($lhs:ident, $rhs:ident) -> $Output:ty { $body:expr }
    }) => {
        impl<$S: $Constraint> $Op<$Rhs> for $Lhs {
            type Output = $Output;
            #[inline]
            default_fn!($op(self, other: $Rhs) -> $Output {
                let ($lhs, $rhs) = (self, other); $body
            });
        }

        impl<'a, $S: $Constraint> $Op<$Rhs> for &'a $Lhs {
            type Output = $Output;
            #[inline]
            default_fn!($op(self, other: $Rhs) -> $Output {
                let ($lhs, $rhs) = (self, other); $body
            });
        }
    };
    // When the right operand is a compound type
    (<$S:ident: $Constraint:ident> $Op:ident<$Rhs:ty> for $Lhs:ty {
        fn $op:ident($lhs:ident, $rhs:ident) -> $Output:ty { $body:expr }
    }) => {
        impl<$S: $Constraint> $Op<$Rhs> for $Lhs {
            type Output = $Output;
            #[inline]
            default_fn!( $op(self, other: $Rhs) -> $Output {
                let ($lhs, $rhs) = (self, other); $body
            });
        }

        impl<'a, $S: $Constraint> $Op<&'a $Rhs> for $Lhs {
            type Output = $Output;
            #[inline]
            default_fn!( $op(self, other: &'a $Rhs) -> $Output {
                let ($lhs, $rhs) = (self, other); $body
            });
        }

        impl<'a, $S: $Constraint> $Op<$Rhs> for &'a $Lhs {
            type Output = $Output;
            #[inline]
            default_fn!( $op(self, other: $Rhs) -> $Output {
                let ($lhs, $rhs) = (self, other); $body
            });
        }

        impl<'a, 'b, $S: $Constraint> $Op<&'a $Rhs> for &'b $Lhs {
            type Output = $Output;
            #[inline]
            default_fn!( $op(self, other: &'a $Rhs) -> $Output {
                let ($lhs, $rhs) = (self, other); $body
            });
        }
    };
    // When the left operand is a scalar
    ($Op:ident<$Rhs:ident<$S:ident>> for $Lhs:ty {
        fn $op:ident($lhs:ident, $rhs:ident) -> $Output:ty { $body:expr }
    }) => {
        impl $Op<$Rhs<$S>> for $Lhs {
            type Output = $Output;
            #[inline]
            default_fn!( $op(self, other: $Rhs<$S>) -> $Output {
                let ($lhs, $rhs) = (self, other); $body
            });
        }

        impl<'a> $Op<&'a $Rhs<$S>> for $Lhs {
            type Output = $Output;
            #[inline]
            default_fn!( $op(self, other: &'a $Rhs<$S>) -> $Output {
                let ($lhs, $rhs) = (self, other); $body
            });
        }
    };
}

macro_rules! impl_assignment_operator {
    (<$S:ident: $Constraint:ident> $Op:ident<$Rhs:ty> for $Lhs:ty {
        fn $op:ident(&mut $lhs:ident, $rhs:ident) $body:block
    }) => {
        impl<$S: $Constraint + $Op<$S>> $Op<$Rhs> for $Lhs {
            #[inline]
            default_fn!( $op(&mut $lhs, $rhs: $Rhs) $body );
        }
    };
}

macro_rules! fold_array {
    ($method:ident, $x:expr) => ($x);
    ($method:ident, $x:expr, $($y:expr),+) => ($x.$method(fold_array!($method, $($y),+)))
}

/// Generate array conversion implementations for a compound array type
macro_rules! impl_fixed_array_conversions {
    ($ArrayN:ident <$S:ident> { $($field:ident : $index:expr),+ }, $n:expr) => {
        impl<$S> Into<[$S; $n]> for $ArrayN<$S> {
            #[inline]
            fn into(self) -> [$S; $n] {
                match self { $ArrayN { $($field),+ } => [$($field),+] }
            }
        }

        impl<$S> AsRef<[$S; $n]> for $ArrayN<$S> {
            #[inline]
            fn as_ref(&self) -> &[$S; $n] {
                unsafe { mem::transmute(self) }
            }
        }

        impl<$S> AsMut<[$S; $n]> for $ArrayN<$S> {
            #[inline]
            fn as_mut(&mut self) -> &mut [$S; $n] {
                unsafe { mem::transmute(self) }
            }
        }

        impl<$S: Clone> From<[$S; $n]> for $ArrayN<$S> {
            #[inline]
            fn from(v: [$S; $n]) -> $ArrayN<$S> {
                // We need to use a clone here because we can't pattern match on arrays yet
                $ArrayN { $($field: v[$index].clone()),+ }
            }
        }

        impl<'a, $S> From<&'a [$S; $n]> for &'a $ArrayN<$S> {
            #[inline]
            fn from(v: &'a [$S; $n]) -> &'a $ArrayN<$S> {
                unsafe { mem::transmute(v) }
            }
        }

        impl<'a, $S> From<&'a mut [$S; $n]> for &'a mut $ArrayN<$S> {
            #[inline]
            fn from(v: &'a mut [$S; $n]) -> &'a mut $ArrayN<$S> {
                unsafe { mem::transmute(v) }
            }
        }
    }
}

/// Generate homogeneous tuple conversion implementations for a compound array type
macro_rules! impl_tuple_conversions {
    ($ArrayN:ident <$S:ident> { $($field:ident),+ }, $Tuple:ty) => {
        impl<$S> Into<$Tuple> for $ArrayN<$S> {
            #[inline]
            fn into(self) -> $Tuple {
                match self { $ArrayN { $($field),+ } => ($($field),+,) }
            }
        }

        impl<$S> AsRef<$Tuple> for $ArrayN<$S> {
            #[inline]
            fn as_ref(&self) -> &$Tuple {
                unsafe { mem::transmute(self) }
            }
        }

        impl<$S> AsMut<$Tuple> for $ArrayN<$S> {
            #[inline]
            fn as_mut(&mut self) -> &mut $Tuple {
                unsafe { mem::transmute(self) }
            }
        }

        impl<$S> From<$Tuple> for $ArrayN<$S> {
            #[inline]
            fn from(v: $Tuple) -> $ArrayN<$S> {
                match v { ($($field),+,) => $ArrayN { $($field: $field),+ } }
            }
        }

        impl<'a, $S> From<&'a $Tuple> for &'a $ArrayN<$S> {
            #[inline]
            fn from(v: &'a $Tuple) -> &'a $ArrayN<$S> {
                unsafe { mem::transmute(v) }
            }
        }

        impl<'a, $S> From<&'a mut $Tuple> for &'a mut $ArrayN<$S> {
            #[inline]
            fn from(v: &'a mut $Tuple) -> &'a mut $ArrayN<$S> {
                unsafe { mem::transmute(v) }
            }
        }
    }
}

/// Generates index operators for a compound type
macro_rules! impl_index_operators {
    ($VectorN:ident<$S:ident>, $n:expr, $Output:ty, $I:ty) => {
        impl<$S> Index<$I> for $VectorN<$S> {
            type Output = $Output;

            #[inline]
            fn index<'a>(&'a self, i: $I) -> &'a $Output {
                let v: &[$S; $n] = self.as_ref();
                &v[i]
            }
        }

        impl<$S> IndexMut<$I> for $VectorN<$S> {
            #[inline]
            fn index_mut<'a>(&'a mut self, i: $I) -> &'a mut $Output {
                let v: &mut [$S; $n] = self.as_mut();
                &mut v[i]
            }
        }
    };
}

/// Generates a binary operator implementation for the permutations of by-ref and by-val, for simd
#[cfg(feature = "simd")]
macro_rules! impl_operator_simd {
    // When it is an unary operator
    ([$Simd:ident]; $Op:ident for $Lhs:ty {
        fn $op:ident($x:ident) -> $Output:ty { $body:expr }
    }) => {
        impl $Op for $Lhs {
            #[inline]
            fn $op(self) -> $Output {
                let $x: $Simd = self.into();
                $body
            }
        }
    };
    // When the right operand is a scalar
    (@rs [$Simd:ident]; $Op:ident<$Rhs:ty> for $Lhs:ty {
        fn $op:ident($lhs:ident, $rhs:ident) -> $Output:ty { $body:expr }
    }) => {
        impl $Op<$Rhs> for $Lhs {
            #[inline]
            fn $op(self, other: $Rhs) -> $Output {
                let ($lhs, $rhs): ($Simd, $Simd) = (self.into(), $Simd::splat(other));
                $body
            }
        }

        impl<'a> $Op<$Rhs> for &'a $Lhs {
            #[inline]
            fn $op(self, other: $Rhs) -> $Output {
                let ($lhs, $rhs): ($Simd, $Simd) = ((*self).into(), $Simd::splat(other));
                $body
            }
        }
    };

    // When the right operand is a compound type
    ([$Simd:ident]; $Op:ident<$Rhs:ty> for $Lhs:ty {
        fn $op:ident($lhs:ident, $rhs:ident) -> $Output:ty { $body:expr }
    }) => {
        impl $Op<$Rhs> for $Lhs {
            #[inline]
            fn $op(self, other: $Rhs) -> $Output {
                let ($lhs, $rhs): ($Simd, $Simd) = (self.into(), other.into());
                $body
            }
        }

        impl<'a> $Op<&'a $Rhs> for $Lhs {
            #[inline]
            fn $op(self, other: &'a $Rhs) -> $Output {
                let ($lhs, $rhs): ($Simd, $Simd) = (self.into(), (*other).into());
                $body
            }
        }

        impl<'a> $Op<$Rhs> for &'a $Lhs {
            #[inline]
            fn $op(self, other: $Rhs) -> $Output {
                let ($lhs, $rhs): ($Simd, $Simd) = ((*self).into(), other.into());
                $body
            }
        }

        impl<'a, 'b> $Op<&'a $Rhs> for &'b $Lhs {
            #[inline]
            fn $op(self, other: &'a $Rhs) -> $Output {
                let ($lhs, $rhs): ($Simd, $Simd) = ((*self).into(), (*other).into());
                $body
            }
        }
    };

    // When the left operand is a scalar
    (@ls [$Simd:ident]; $Op:ident<$Rhs:ty> for $Lhs:ident {
        fn $op:ident($lhs:ident, $rhs:ident) -> $Output:ty { $body:expr }
    }) => {
        impl $Op<$Rhs> for $Lhs {
            #[inline]
            fn $op(self, other: $Rhs) -> $Output {
                let ($lhs, $rhs): ($Simd, $Simd) = ($Simd::splat(self), other.into());
                $body
            }
        }

        impl<'a> $Op<&'a $Rhs> for $Lhs {
            #[inline]
            fn $op(self, other: &'a $Rhs) -> $Output {
                let ($lhs, $rhs): ($Simd, $Simd) = ($Simd::splat(self), (*other).into());
                $body
            }
        }
    };
}

/// Generate `mint` types conversion implementations
#[cfg(feature = "mint")]
macro_rules! impl_mint_conversions {
    ($ArrayN:ident { $($field:ident),+ }, $Mint:ident) => {
        impl<S: Clone> Into<mint::$Mint<S>> for $ArrayN<S> {
            #[inline]
            fn into(self) -> mint::$Mint<S> {
                mint::$Mint::from([$(self.$field),+])
            }
        }

        impl<S> From<mint::$Mint<S>> for $ArrayN<S> {
            #[inline]
            fn from(v: mint::$Mint<S>) -> Self {
                $ArrayN { $( $field: v.$field, )+ }
            }
        }
    }
}

include!(concat!(env!("OUT_DIR"), "/swizzle_operator_macro.rs"));
<commit_msg>Implement From instead of Into for array/tuple/mint conversions (#528)<commit_after>// Copyright 2013-2014 The CGMath Developers. For a full listing of the authors,
// refer to the Cargo.toml file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Utility macros for code generation

#![macro_use]

#[cfg(feature = "simd")]
macro_rules! default_fn {
    { $($tt:tt)* } => { default fn $( $tt )* };
}

#[cfg(not(feature = "simd"))]
macro_rules! default_fn {
    { $($tt:tt)* } => { fn $( $tt )* };
}

/// Generates a binary operator implementation for the permutations of by-ref and by-val
macro_rules! impl_operator {
    // When it is an unary operator
    (<$S:ident: $Constraint:ident> $Op:ident for $Lhs:ty {
        fn $op:ident($x:ident) -> $Output:ty { $body:expr }
    }) => {
        impl<$S: $Constraint> $Op for $Lhs {
            type Output = $Output;
            #[inline]
            default_fn!($op(self) -> $Output {
                let $x = self; $body
            });
        }

        impl<'a, $S: $Constraint> $Op for &'a $Lhs {
            type Output = $Output;
            #[inline]
            default_fn!($op(self) -> $Output {
                let $x = self; $body
            });
        }
    };
    // When the right operand is a scalar
    (<$S:ident: $Constraint:ident> $Op:ident<$Rhs:ident> for $Lhs:ty {
        fn $op:ident($lhs:ident, $rhs:ident) -> $Output:ty { $body:expr }
    }) => {
        impl<$S: $Constraint> $Op<$Rhs> for $Lhs {
            type Output = $Output;
            #[inline]
            default_fn!($op(self, other: $Rhs) -> $Output {
                let ($lhs, $rhs) = (self, other); $body
            });
        }

        impl<'a, $S: $Constraint> $Op<$Rhs> for &'a $Lhs {
            type Output = $Output;
            #[inline]
            default_fn!($op(self, other: $Rhs) -> $Output {
                let ($lhs, $rhs) = (self, other); $body
            });
        }
    };
    // When the right operand is a compound type
    (<$S:ident: $Constraint:ident> $Op:ident<$Rhs:ty> for $Lhs:ty {
        fn $op:ident($lhs:ident, $rhs:ident) -> $Output:ty { $body:expr }
    }) => {
        impl<$S: $Constraint> $Op<$Rhs> for $Lhs {
            type Output = $Output;
            #[inline]
            default_fn!( $op(self, other: $Rhs) -> $Output {
                let ($lhs, $rhs) = (self, other); $body
            });
        }

        impl<'a, $S: $Constraint> $Op<&'a $Rhs> for $Lhs {
            type Output = $Output;
            #[inline]
            default_fn!( $op(self, other: &'a $Rhs) -> $Output {
                let ($lhs, $rhs) = (self, other); $body
            });
        }

        impl<'a, $S: $Constraint> $Op<$Rhs> for &'a $Lhs {
            type Output = $Output;
            #[inline]
            default_fn!( $op(self, other: $Rhs) -> $Output {
                let ($lhs, $rhs) = (self, other); $body
            });
        }

        impl<'a, 'b, $S: $Constraint> $Op<&'a $Rhs> for &'b $Lhs {
            type Output = $Output;
            #[inline]
            default_fn!( $op(self, other: &'a $Rhs) -> $Output {
                let ($lhs, $rhs) = (self, other); $body
            });
        }
    };
    // When the left operand is a scalar
    ($Op:ident<$Rhs:ident<$S:ident>> for $Lhs:ty {
        fn $op:ident($lhs:ident, $rhs:ident) -> $Output:ty { $body:expr }
    }) => {
        impl $Op<$Rhs<$S>> for $Lhs {
            type Output = $Output;
            #[inline]
            default_fn!( $op(self, other: $Rhs<$S>) -> $Output {
                let ($lhs, $rhs) = (self, other); $body
            });
        }

        impl<'a> $Op<&'a $Rhs<$S>> for $Lhs {
            type Output = $Output;
            #[inline]
            default_fn!( $op(self, other: &'a $Rhs<$S>) -> $Output {
                let ($lhs, $rhs) = (self, other); $body
            });
        }
    };
}

macro_rules! impl_assignment_operator {
    (<$S:ident: $Constraint:ident> $Op:ident<$Rhs:ty> for $Lhs:ty {
        fn $op:ident(&mut $lhs:ident, $rhs:ident) $body:block
    }) => {
        impl<$S: $Constraint + $Op<$S>> $Op<$Rhs> for $Lhs {
            #[inline]
            default_fn!( $op(&mut $lhs, $rhs: $Rhs) $body );
        }
    };
}

macro_rules! fold_array {
    ($method:ident, $x:expr) => ($x);
    ($method:ident, $x:expr, $($y:expr),+) => ($x.$method(fold_array!($method, $($y),+)))
}

/// Generate array conversion implementations for a compound array type
macro_rules! impl_fixed_array_conversions {
    ($ArrayN:ident <$S:ident> { $($field:ident : $index:expr),+ }, $n:expr) => {
        impl<$S> From<$ArrayN<$S>> for [$S; $n] {
            #[inline]
            fn from(v: $ArrayN<$S>) -> Self {
                match v { $ArrayN { $($field),+ } => [$($field),+] }
            }
        }

        impl<$S> AsRef<[$S; $n]> for $ArrayN<$S> {
            #[inline]
            fn as_ref(&self) -> &[$S; $n] {
                unsafe { mem::transmute(self) }
            }
        }

        impl<$S> AsMut<[$S; $n]> for $ArrayN<$S> {
            #[inline]
            fn as_mut(&mut self) -> &mut [$S; $n] {
                unsafe { mem::transmute(self) }
            }
        }

        impl<$S: Clone> From<[$S; $n]> for $ArrayN<$S> {
            #[inline]
            fn from(v: [$S; $n]) -> $ArrayN<$S> {
                // We need to use a clone here because we can't pattern match on arrays yet
                $ArrayN { $($field: v[$index].clone()),+ }
            }
        }

        impl<'a, $S> From<&'a [$S; $n]> for &'a $ArrayN<$S> {
            #[inline]
            fn from(v: &'a [$S; $n]) -> &'a $ArrayN<$S> {
                unsafe { mem::transmute(v) }
            }
        }

        impl<'a, $S> From<&'a mut [$S; $n]> for &'a mut $ArrayN<$S> {
            #[inline]
            fn from(v: &'a mut [$S; $n]) -> &'a mut $ArrayN<$S> {
                unsafe { mem::transmute(v) }
            }
        }
    }
}

/// Generate homogeneous tuple conversion implementations for a compound array type
macro_rules! impl_tuple_conversions {
    ($ArrayN:ident <$S:ident> { $($field:ident),+ }, $Tuple:ty) => {
        impl<$S> From<$ArrayN<$S>> for $Tuple {
            #[inline]
            fn from(v: $ArrayN<$S>) -> Self {
                match v { $ArrayN { $($field),+ } => ($($field),+,) }
            }
        }

        impl<$S> AsRef<$Tuple> for $ArrayN<$S> {
            #[inline]
            fn as_ref(&self) -> &$Tuple {
                unsafe { mem::transmute(self) }
            }
        }

        impl<$S> AsMut<$Tuple> for $ArrayN<$S> {
            #[inline]
            fn as_mut(&mut self) -> &mut $Tuple {
                unsafe { mem::transmute(self) }
            }
        }

        impl<$S> From<$Tuple> for $ArrayN<$S> {
            #[inline]
            fn from(v: $Tuple) -> $ArrayN<$S> {
                match v { ($($field),+,) => $ArrayN { $($field: $field),+ } }
            }
        }

        impl<'a, $S> From<&'a $Tuple> for &'a $ArrayN<$S> {
            #[inline]
            fn from(v: &'a $Tuple) -> &'a $ArrayN<$S> {
                unsafe { mem::transmute(v) }
            }
        }

        impl<'a, $S> From<&'a mut $Tuple> for &'a mut $ArrayN<$S> {
            #[inline]
            fn from(v: &'a mut $Tuple) -> &'a mut $ArrayN<$S> {
                unsafe { mem::transmute(v) }
            }
        }
    }
}

/// Generates index operators for a compound type
macro_rules! impl_index_operators {
    ($VectorN:ident<$S:ident>, $n:expr, $Output:ty, $I:ty) => {
        impl<$S> Index<$I> for $VectorN<$S> {
            type Output = $Output;

            #[inline]
            fn index<'a>(&'a self, i: $I) -> &'a $Output {
                let v: &[$S; $n] = self.as_ref();
                &v[i]
            }
        }

        impl<$S> IndexMut<$I> for $VectorN<$S> {
            #[inline]
            fn index_mut<'a>(&'a mut self, i: $I) -> &'a mut $Output {
                let v: &mut [$S; $n] = self.as_mut();
                &mut v[i]
            }
        }
    };
}

/// Generates a binary operator implementation for the permutations of by-ref and by-val, for simd
#[cfg(feature = "simd")]
macro_rules! impl_operator_simd {
    // When it is an unary operator
    ([$Simd:ident]; $Op:ident for $Lhs:ty {
        fn $op:ident($x:ident) -> $Output:ty { $body:expr }
    }) => {
        impl $Op for $Lhs {
            #[inline]
            fn $op(self) -> $Output {
                let $x: $Simd = self.into();
                $body
            }
        }
    };
    // When the right operand is a scalar
    (@rs [$Simd:ident]; $Op:ident<$Rhs:ty> for $Lhs:ty {
        fn $op:ident($lhs:ident, $rhs:ident) -> $Output:ty { $body:expr }
    }) => {
        impl $Op<$Rhs> for $Lhs {
            #[inline]
            fn $op(self, other: $Rhs) -> $Output {
                let ($lhs, $rhs): ($Simd, $Simd) = (self.into(), $Simd::splat(other));
                $body
            }
        }

        impl<'a> $Op<$Rhs> for &'a $Lhs {
            #[inline]
            fn $op(self, other: $Rhs) -> $Output {
                let ($lhs, $rhs): ($Simd, $Simd) = ((*self).into(), $Simd::splat(other));
                $body
            }
        }
    };

    // When the right operand is a compound type
    ([$Simd:ident]; $Op:ident<$Rhs:ty> for $Lhs:ty {
        fn $op:ident($lhs:ident, $rhs:ident) -> $Output:ty { $body:expr }
    }) => {
        impl $Op<$Rhs> for $Lhs {
            #[inline]
            fn $op(self, other: $Rhs) -> $Output {
                let ($lhs, $rhs): ($Simd, $Simd) = (self.into(), other.into());
                $body
            }
        }

        impl<'a> $Op<&'a $Rhs> for $Lhs {
            #[inline]
            fn $op(self, other: &'a $Rhs) -> $Output {
                let ($lhs, $rhs): ($Simd, $Simd) = (self.into(), (*other).into());
                $body
            }
        }

        impl<'a> $Op<$Rhs> for &'a $Lhs {
            #[inline]
            fn $op(self, other: $Rhs) -> $Output {
                let ($lhs, $rhs): ($Simd, $Simd) = ((*self).into(), other.into());
                $body
            }
        }

        impl<'a, 'b> $Op<&'a $Rhs> for &'b $Lhs {
            #[inline]
            fn $op(self, other: &'a $Rhs) -> $Output {
                let ($lhs, $rhs): ($Simd, $Simd) = ((*self).into(), (*other).into());
                $body
            }
        }
    };

    // When the left operand is a scalar
    (@ls [$Simd:ident]; $Op:ident<$Rhs:ty> for $Lhs:ident {
        fn $op:ident($lhs:ident, $rhs:ident) -> $Output:ty { $body:expr }
    }) => {
        impl $Op<$Rhs> for $Lhs {
            #[inline]
            fn $op(self, other: $Rhs) -> $Output {
                let ($lhs, $rhs): ($Simd, $Simd) = ($Simd::splat(self), other.into());
                $body
            }
        }

        impl<'a> $Op<&'a $Rhs> for $Lhs {
            #[inline]
            fn $op(self, other: &'a $Rhs) -> $Output {
                let ($lhs, $rhs): ($Simd, $Simd) = ($Simd::splat(self), (*other).into());
                $body
            }
        }
    };
}

/// Generate `mint` types conversion implementations
#[cfg(feature = "mint")]
macro_rules! impl_mint_conversions {
    ($ArrayN:ident { $($field:ident),+ }, $Mint:ident) => {
        impl<S: Clone> From<$ArrayN<S>> for mint::$Mint<S> {
            #[inline]
            fn from(v: $ArrayN<S>) -> Self {
                mint::$Mint::from([$(v.$field),+])
            }
        }

        impl<S> From<mint::$Mint<S>> for $ArrayN<S> {
            #[inline]
            fn from(v: mint::$Mint<S>) -> Self {
                $ArrayN { $( $field: v.$field, )+ }
            }
        }
    }
}

include!(concat!(env!("OUT_DIR"), "/swizzle_operator_macro.rs"));
<|endoftext|>


<commit_before>#[macro_export]
macro_rules! as_item { ($i:item) => {$i} }

#[macro_export]
macro_rules! request_fns {
    ($fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty) => (
        pub fn $fn_name(&self, $($arg: $in_),*) -> Result<$out> {
            let reply = try!((self.0).rpc(&request_variant!($fn_name $($arg),*)));
            let Reply::$fn_name(reply) = reply;
            Ok(reply)
        }
    );
    ($( $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty)*) => ( $(
        pub fn $fn_name(&self, $($arg: $in_),*) -> Result<$out> {
            let reply = try!((self.0).rpc(&request_variant!($fn_name $($arg),*)));
            if let Reply::$fn_name(reply) = reply {
                Ok(reply)
            } else {
                Err(Error::InternalError)
            }
        }
    )*);
}

#[macro_export]
macro_rules! define_request {
    ($(@($($finished:tt)*))* --) => (as_item!(
            #[allow(non_camel_case_types)]
            #[derive(Debug, Serialize, Deserialize)]
            enum Request { $($($finished)*),* }
    ););
    ($(@$finished:tt)* -- $name:ident() $($req:tt)*) =>
        (define_request!($(@$finished)* @($name) -- $($req)*););
    ($(@$finished:tt)* -- $name:ident $args: tt $($req:tt)*) =>
        (define_request!($(@$finished)* @($name $args) -- $($req)*););
    ($($started:tt)*) => (define_request!(-- $($started)*););
}

#[macro_export]
macro_rules! request_variant {
    ($x:ident) => (Request::$x);
    ($x:ident $($y:ident),+) => (Request::$x($($y),+));
}

#[macro_export]
macro_rules! rpc_service { ($server:ident:
    $( $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty;)*) => {
        #[allow(dead_code)]
        pub mod $server {
            use std::net::ToSocketAddrs;
            use std::io;
            use std::sync::Arc;
            use $crate::protocol::{
                self,
                ServeHandle,
                serve_async,
            };

            #[doc="An RPC error that occurred during serving an RPC request."]
            #[derive(Debug)]
            pub enum Error {
                #[doc="An IO error occurred."]
                Io(io::Error),

                #[doc="An unexpected internal error. Typically a bug in the server impl."]
                InternalError,
            }

            impl ::std::convert::From<protocol::Error> for Error {
                fn from(err: protocol::Error) -> Error {
                    match err {
                        protocol::Error::Io(err) => Error::Io(err),
                        _ => Error::InternalError,
                    }
                }
            }

            impl ::std::convert::From<io::Error> for Error {
                fn from(err: io::Error) -> Error {
                    Error::Io(err)
                }
            }

            #[doc="The result of an RPC call; either the successful result or the error."]
            pub type Result<T> = ::std::result::Result<T, Error>;

            #[doc="The provided RPC service."]
            pub trait Service: Send + Sync {
                $(
                    fn $fn_name(&self, $($arg:$in_),*) -> $out;
                )*
            }

            define_request!($($fn_name($($in_),*))*);

            #[allow(non_camel_case_types)]
            #[derive(Debug, Serialize, Deserialize)]
            enum Reply {
                $(
                    $fn_name($out),
                )*
            }

            #[doc="The client stub that makes RPC calls to the server."]
            pub struct Client(protocol::Client<Request, Reply>);

            impl Client {
                #[doc="Create a new client that connects to the given address."]
                pub fn new<A>(addr: A) -> Result<Self>
                    where A: ToSocketAddrs,
                {
                    let inner = try!(protocol::Client::new(addr));
                    Ok(Client(inner))
                }

                request_fns!($($fn_name($($arg: $in_),*) -> $out)*);
            }

            struct Server<S: 'static + Service>(S);

            impl<S> protocol::Serve<Request, Reply> for Server<S>
                where S: 'static + Service
            {
                fn serve(&self, request: Request) -> Reply {
                    match request {
                        $(
                            request_variant!($fn_name $($arg),*) =>
                                Reply::$fn_name((self.0).$fn_name($($arg),*)),
                         )*
                    }
                }
            }

            #[doc="Start a running service."]
            pub fn serve<A, S>(addr: A, service: S) -> Result<ServeHandle>
                where A: ToSocketAddrs,
                      S: 'static + Service
            {
                let server = Arc::new(Server(service));
                Ok(try!(serve_async(addr, server)))
            }
        }
    }
}

#[cfg(test)]
mod test {

    rpc_service!(my_server:
        hello(foo: super::Foo) -> super::Foo;

        add(x: i32, y: i32) -> i32;
    );

    use self::my_server::*;

    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    pub struct Foo {
        message: String
    }

    impl Service for () {
        fn hello(&self, s: Foo) -> Foo {
            Foo{message: format!("Hello, {}", &s.message)}
        }

        fn add(&self, x: i32, y: i32) -> i32 {
            x + y
        }
    }

    #[test]
    fn simple_test() {
        println!("Starting");
        let addr = "127.0.0.1:9000";
        let shutdown = my_server::serve(addr, ()).unwrap();
        let client = Client::new(addr).unwrap();
        assert_eq!(3, client.add(1, 2).unwrap());
        let foo = Foo{message: "Adam".into()};
        let want = Foo{message: format!("Hello, {}", &foo.message)};
        assert_eq!(want, client.hello(Foo{message: "Adam".into()}).unwrap());
        drop(client);
        shutdown.shutdown();
    }

    // This is a test of a service with a fn that takes no args
    rpc_service! {foo:
        hello() -> String;
    }
}
<commit_msg>A few comments on macros<commit_after>#[macro_export]
macro_rules! as_item { ($i:item) => {$i} }

// Required because if-let can't be used with irrefutable patterns, so it needs to be special
// cased.
#[macro_export]
macro_rules! request_fns {
    ($fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty) => (
        pub fn $fn_name(&self, $($arg: $in_),*) -> Result<$out> {
            let reply = try!((self.0).rpc(&request_variant!($fn_name $($arg),*)));
            let Reply::$fn_name(reply) = reply;
            Ok(reply)
        }
    );
    ($( $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty)*) => ( $(
        pub fn $fn_name(&self, $($arg: $in_),*) -> Result<$out> {
            let reply = try!((self.0).rpc(&request_variant!($fn_name $($arg),*)));
            if let Reply::$fn_name(reply) = reply {
                Ok(reply)
            } else {
                Err(Error::InternalError)
            }
        }
    )*);
}

// Required because enum variants with no fields can't be suffixed by parens
#[macro_export]
macro_rules! define_request {
    ($(@($($finished:tt)*))* --) => (as_item!(
            #[allow(non_camel_case_types)]
            #[derive(Debug, Serialize, Deserialize)]
            enum Request { $($($finished)*),* }
    ););
    ($(@$finished:tt)* -- $name:ident() $($req:tt)*) =>
        (define_request!($(@$finished)* @($name) -- $($req)*););
    ($(@$finished:tt)* -- $name:ident $args: tt $($req:tt)*) =>
        (define_request!($(@$finished)* @($name $args) -- $($req)*););
    ($($started:tt)*) => (define_request!(-- $($started)*););
}

// Required because enum variants with no fields can't be suffixed by parens
#[macro_export]
macro_rules! request_variant {
    ($x:ident) => (Request::$x);
    ($x:ident $($y:ident),+) => (Request::$x($($y),+));
}

// The main macro that creates RPC services.
#[macro_export]
macro_rules! rpc_service { ($server:ident:
    $( $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty;)*) => {
        #[allow(dead_code)]
        pub mod $server {
            use std::net::ToSocketAddrs;
            use std::io;
            use std::sync::Arc;
            use $crate::protocol::{
                self,
                ServeHandle,
                serve_async,
            };

            #[doc="An RPC error that occurred during serving an RPC request."]
            #[derive(Debug)]
            pub enum Error {
                #[doc="An IO error occurred."]
                Io(io::Error),

                #[doc="An unexpected internal error. Typically a bug in the server impl."]
                InternalError,
            }

            impl ::std::convert::From<protocol::Error> for Error {
                fn from(err: protocol::Error) -> Error {
                    match err {
                        protocol::Error::Io(err) => Error::Io(err),
                        _ => Error::InternalError,
                    }
                }
            }

            impl ::std::convert::From<io::Error> for Error {
                fn from(err: io::Error) -> Error {
                    Error::Io(err)
                }
            }

            #[doc="The result of an RPC call; either the successful result or the error."]
            pub type Result<T> = ::std::result::Result<T, Error>;

            #[doc="The provided RPC service."]
            pub trait Service: Send + Sync {
                $(
                    fn $fn_name(&self, $($arg:$in_),*) -> $out;
                )*
            }

            define_request!($($fn_name($($in_),*))*);

            #[allow(non_camel_case_types)]
            #[derive(Debug, Serialize, Deserialize)]
            enum Reply {
                $(
                    $fn_name($out),
                )*
            }

            #[doc="The client stub that makes RPC calls to the server."]
            pub struct Client(protocol::Client<Request, Reply>);

            impl Client {
                #[doc="Create a new client that connects to the given address."]
                pub fn new<A>(addr: A) -> Result<Self>
                    where A: ToSocketAddrs,
                {
                    let inner = try!(protocol::Client::new(addr));
                    Ok(Client(inner))
                }

                request_fns!($($fn_name($($arg: $in_),*) -> $out)*);
            }

            struct Server<S: 'static + Service>(S);

            impl<S> protocol::Serve<Request, Reply> for Server<S>
                where S: 'static + Service
            {
                fn serve(&self, request: Request) -> Reply {
                    match request {
                        $(
                            request_variant!($fn_name $($arg),*) =>
                                Reply::$fn_name((self.0).$fn_name($($arg),*)),
                         )*
                    }
                }
            }

            #[doc="Start a running service."]
            pub fn serve<A, S>(addr: A, service: S) -> Result<ServeHandle>
                where A: ToSocketAddrs,
                      S: 'static + Service
            {
                let server = Arc::new(Server(service));
                Ok(try!(serve_async(addr, server)))
            }
        }
    }
}

#[cfg(test)]
mod test {

    rpc_service!(my_server:
        hello(foo: super::Foo) -> super::Foo;

        add(x: i32, y: i32) -> i32;
    );

    use self::my_server::*;

    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    pub struct Foo {
        message: String
    }

    impl Service for () {
        fn hello(&self, s: Foo) -> Foo {
            Foo{message: format!("Hello, {}", &s.message)}
        }

        fn add(&self, x: i32, y: i32) -> i32 {
            x + y
        }
    }

    #[test]
    fn simple_test() {
        println!("Starting");
        let addr = "127.0.0.1:9000";
        let shutdown = my_server::serve(addr, ()).unwrap();
        let client = Client::new(addr).unwrap();
        assert_eq!(3, client.add(1, 2).unwrap());
        let foo = Foo{message: "Adam".into()};
        let want = Foo{message: format!("Hello, {}", &foo.message)};
        assert_eq!(want, client.hello(Foo{message: "Adam".into()}).unwrap());
        drop(client);
        shutdown.shutdown();
    }

    // This is a test of a service with a fn that takes no args
    rpc_service! {foo:
        hello() -> String;
    }
}
<|endoftext|>


<commit_before><commit_msg>Remove &mut self requirement in TimerSubsystem::delay()<commit_after><|endoftext|>


<commit_before>// Portions of this file are Copyright 2014 The Rust Project Developers.
// See http://rust-lang.org/COPYRIGHT.

use libc;
use {Errno, Result};
use std::mem;
use std::ptr;

pub use libc::{
    SIGHUP,
    SIGINT,
    SIGQUIT,
    SIGILL,
    SIGABRT,
    SIGFPE,
    SIGKILL,
    SIGSEGV,
    SIGPIPE,
    SIGALRM,
    SIGTERM,
    SIGTRAP,
    SIGIOT,
    SIGBUS,
    SIGSYS,
    SIGURG,
    SIGSTOP,
    SIGTSTP,
    SIGCONT,
    SIGCHLD,
    SIGTTIN,
    SIGTTOU,
    SIGIO,
    SIGXCPU,
    SIGXFSZ,
    SIGVTALRM,
    SIGPROF,
    SIGWINCH,
    SIGUSR1,
    SIGUSR2,
};

// This doesn't always exist, but when it does, it's 7
pub const SIGEMT: libc::c_int = 7;

pub const NSIG: libc::c_int = 32;

bitflags!{
    flags SaFlag: libc::c_int {
        const SA_NOCLDSTOP = libc::SA_NOCLDSTOP,
        const SA_NOCLDWAIT = libc::SA_NOCLDWAIT,
        const SA_NODEFER   = libc::SA_NODEFER,
        const SA_ONSTACK   = libc::SA_ONSTACK,
        const SA_RESETHAND = libc::SA_RESETHAND,
        const SA_RESTART   = libc::SA_RESTART,
        const SA_SIGINFO   = libc::SA_SIGINFO,
    }
}

bitflags!{
    flags SigFlag: libc::c_int {
        const SIG_BLOCK   = libc::SIG_BLOCK,
        const SIG_UNBLOCK = libc::SIG_UNBLOCK,
        const SIG_SETMASK = libc::SIG_SETMASK,
    }
}

mod ffi {
    use libc;
    extern {
        pub fn sigwait(set: *const libc::sigset_t, sig: *mut libc::c_int) -> libc::c_int;
    }
}

#[derive(Clone, Copy)]
pub struct SigSet {
    sigset: libc::sigset_t
}

pub type SigNum = libc::c_int;

impl SigSet {
    pub fn all() -> SigSet {
        let mut sigset: libc::sigset_t = unsafe { mem::uninitialized() };
        let _ = unsafe { libc::sigfillset(&mut sigset as *mut libc::sigset_t) };

        SigSet { sigset: sigset }
    }

    pub fn empty() -> SigSet {
        let mut sigset: libc::sigset_t = unsafe { mem::uninitialized() };
        let _ = unsafe { libc::sigemptyset(&mut sigset as *mut libc::sigset_t) };

        SigSet { sigset: sigset }
    }

    pub fn add(&mut self, signum: SigNum) -> Result<()> {
        let res = unsafe { libc::sigaddset(&mut self.sigset as *mut libc::sigset_t, signum) };

        Errno::result(res).map(drop)
    }

    pub fn remove(&mut self, signum: SigNum) -> Result<()> {
        let res = unsafe { libc::sigdelset(&mut self.sigset as *mut libc::sigset_t, signum) };

        Errno::result(res).map(drop)
    }

    pub fn contains(&self, signum: SigNum) -> Result<bool> {
        let res = unsafe { libc::sigismember(&self.sigset as *const libc::sigset_t, signum) };

        match try!(Errno::result(res)) {
            1 => Ok(true),
            0 => Ok(false),
            _ => unreachable!("unexpected value from sigismember"),
        }
    }

    /// Gets the currently blocked (masked) set of signals for the calling thread.
    pub fn thread_get_mask() -> Result<SigSet> {
        let mut oldmask: SigSet = unsafe { mem::uninitialized() };
        try!(pthread_sigmask(SigFlag::empty(), None, Some(&mut oldmask)));
        Ok(oldmask)
    }

    /// Sets the set of signals as the signal mask for the calling thread.
    pub fn thread_set_mask(&self) -> Result<()> {
        pthread_sigmask(SIG_SETMASK, Some(self), None)
    }

    /// Adds the set of signals to the signal mask for the calling thread.
    pub fn thread_block(&self) -> Result<()> {
        pthread_sigmask(SIG_BLOCK, Some(self), None)
    }

    /// Removes the set of signals from the signal mask for the calling thread.
    pub fn thread_unblock(&self) -> Result<()> {
        pthread_sigmask(SIG_UNBLOCK, Some(self), None)
    }

    /// Sets the set of signals as the signal mask, and returns the old mask.
    pub fn thread_swap_mask(&self, how: SigFlag) -> Result<SigSet> {
        let mut oldmask: SigSet = unsafe { mem::uninitialized() };
        try!(pthread_sigmask(how, Some(self), Some(&mut oldmask)));
        Ok(oldmask)
    }

    /// Suspends execution of the calling thread until one of the signals in the
    /// signal mask becomes pending, and returns the accepted signal.
    pub fn wait(&self) -> Result<SigNum> {
        let mut signum: SigNum = unsafe { mem::uninitialized() };
        let res = unsafe { ffi::sigwait(&self.sigset as *const libc::sigset_t, &mut signum) };

        Errno::result(res).map(|_| signum)
    }
}

impl AsRef<libc::sigset_t> for SigSet {
    fn as_ref(&self) -> &libc::sigset_t {
        &self.sigset
    }
}

#[allow(unknown_lints)]
#[allow(raw_pointer_derive)]
#[derive(Clone, Copy, PartialEq)]
pub enum SigHandler {
    SigDfl,
    SigIgn,
    Handler(extern fn(SigNum)),
    SigAction(extern fn(SigNum, *mut libc::siginfo_t, *mut libc::c_void))
}

pub struct SigAction {
    sigaction: libc::sigaction
}

impl SigAction {
    /// This function will set or unset the flag `SA_SIGINFO` depending on the
    /// type of the `handler` argument.
    pub fn new(handler: SigHandler, flags: SaFlag, mask: SigSet) -> SigAction {
        let mut s = unsafe { mem::uninitialized::<libc::sigaction>() };
        s.sa_sigaction = match handler {
            SigHandler::SigDfl => unsafe { mem::transmute(libc::SIG_DFL) },
            SigHandler::SigIgn => unsafe { mem::transmute(libc::SIG_IGN) },
            SigHandler::Handler(f) => unsafe { mem::transmute(f) },
            SigHandler::SigAction(f) => unsafe { mem::transmute(f) },
        };
        s.sa_flags = match handler {
            SigHandler::SigAction(_) => (flags | SA_SIGINFO).bits(),
            _ => (flags - SA_SIGINFO).bits(),
        };
        s.sa_mask = mask.sigset;

        SigAction { sigaction: s }
    }
}

pub unsafe fn sigaction(signum: SigNum, sigaction: &SigAction) -> Result<SigAction> {
    let mut oldact = mem::uninitialized::<libc::sigaction>();

    let res =
        libc::sigaction(signum, &sigaction.sigaction as *const libc::sigaction, &mut oldact as *mut libc::sigaction);

    Errno::result(res).map(|_| SigAction { sigaction: oldact })
}

/// Manages the signal mask (set of blocked signals) for the calling thread.
///
/// If the `set` parameter is `Some(..)`, then the signal mask will be updated with the signal set.
/// The `how` flag decides the type of update. If `set` is `None`, `how` will be ignored,
/// and no modification will take place.
///
/// If the 'oldset' parameter is `Some(..)` then the current signal mask will be written into it.
///
/// If both `set` and `oldset` is `Some(..)`, the current signal mask will be written into oldset,
/// and then it will be updated with `set`.
///
/// If both `set` and `oldset` is None, this function is a no-op.
///
/// For more information, visit the [pthread_sigmask](http://man7.org/linux/man-pages/man3/pthread_sigmask.3.html),
/// or [sigprocmask](http://man7.org/linux/man-pages/man2/sigprocmask.2.html) man pages.
pub fn pthread_sigmask(how: SigFlag,
                       set: Option<&SigSet>,
                       oldset: Option<&mut SigSet>) -> Result<()> {
    if set.is_none() && oldset.is_none() {
        return Ok(())
    }

    let res = unsafe {
        // if set or oldset is None, pass in null pointers instead
        libc::pthread_sigmask(how.bits(),
                             set.map_or_else(|| ptr::null::<libc::sigset_t>(),
                                             |s| &s.sigset as *const libc::sigset_t),
                             oldset.map_or_else(|| ptr::null_mut::<libc::sigset_t>(),
                                                |os| &mut os.sigset as *mut libc::sigset_t))
    };

    Errno::result(res).map(drop)
}

pub fn kill(pid: libc::pid_t, signum: SigNum) -> Result<()> {
    let res = unsafe { libc::kill(pid, signum) };

    Errno::result(res).map(drop)
}

pub fn raise(signum: SigNum) -> Result<()> {
    let res = unsafe { libc::raise(signum) };

    Errno::result(res).map(drop)
}

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

    #[test]
    fn test_contains() {
        let mut mask = SigSet::empty();
        mask.add(SIGUSR1).unwrap();

        assert_eq!(mask.contains(SIGUSR1), Ok(true));
        assert_eq!(mask.contains(SIGUSR2), Ok(false));

        let all = SigSet::all();
        assert_eq!(all.contains(SIGUSR1), Ok(true));
        assert_eq!(all.contains(SIGUSR2), Ok(true));
    }

    #[test]
    fn test_thread_signal_block() {
        let mut mask = SigSet::empty();
        mask.add(SIGUSR1).unwrap();

        assert!(mask.thread_block().is_ok());
    }

    #[test]
    fn test_thread_signal_swap() {
        let mut mask = SigSet::empty();
        mask.add(SIGUSR1).unwrap();
        mask.thread_block().unwrap();

        assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1).unwrap());

        let mask2 = SigSet::empty();
        mask.add(SIGUSR2).unwrap();

        let oldmask = mask2.thread_swap_mask(SIG_SETMASK).unwrap();

        assert!(oldmask.contains(SIGUSR1).unwrap());
        assert!(!oldmask.contains(SIGUSR2).unwrap());
    }

    // TODO(#251): Re-enable after figuring out flakiness.
    #[cfg(not(any(target_os = "macos", target_os = "ios")))]
    #[test]
    fn test_sigwait() {
        let mut mask = SigSet::empty();
        mask.add(SIGUSR1).unwrap();
        mask.add(SIGUSR2).unwrap();
        mask.thread_block().unwrap();

        raise(SIGUSR1).unwrap();
        assert_eq!(mask.wait().unwrap(), SIGUSR1);
    }
}
<commit_msg>Use sigwait function from libc instead of own ffi function.<commit_after>// Portions of this file are Copyright 2014 The Rust Project Developers.
// See http://rust-lang.org/COPYRIGHT.

use libc;
use {Errno, Result};
use std::mem;
use std::ptr;

pub use libc::{
    SIGHUP,
    SIGINT,
    SIGQUIT,
    SIGILL,
    SIGABRT,
    SIGFPE,
    SIGKILL,
    SIGSEGV,
    SIGPIPE,
    SIGALRM,
    SIGTERM,
    SIGTRAP,
    SIGIOT,
    SIGBUS,
    SIGSYS,
    SIGURG,
    SIGSTOP,
    SIGTSTP,
    SIGCONT,
    SIGCHLD,
    SIGTTIN,
    SIGTTOU,
    SIGIO,
    SIGXCPU,
    SIGXFSZ,
    SIGVTALRM,
    SIGPROF,
    SIGWINCH,
    SIGUSR1,
    SIGUSR2,
};

// This doesn't always exist, but when it does, it's 7
pub const SIGEMT: libc::c_int = 7;

pub const NSIG: libc::c_int = 32;

bitflags!{
    flags SaFlag: libc::c_int {
        const SA_NOCLDSTOP = libc::SA_NOCLDSTOP,
        const SA_NOCLDWAIT = libc::SA_NOCLDWAIT,
        const SA_NODEFER   = libc::SA_NODEFER,
        const SA_ONSTACK   = libc::SA_ONSTACK,
        const SA_RESETHAND = libc::SA_RESETHAND,
        const SA_RESTART   = libc::SA_RESTART,
        const SA_SIGINFO   = libc::SA_SIGINFO,
    }
}

bitflags!{
    flags SigFlag: libc::c_int {
        const SIG_BLOCK   = libc::SIG_BLOCK,
        const SIG_UNBLOCK = libc::SIG_UNBLOCK,
        const SIG_SETMASK = libc::SIG_SETMASK,
    }
}

#[derive(Clone, Copy)]
pub struct SigSet {
    sigset: libc::sigset_t
}

pub type SigNum = libc::c_int;

impl SigSet {
    pub fn all() -> SigSet {
        let mut sigset: libc::sigset_t = unsafe { mem::uninitialized() };
        let _ = unsafe { libc::sigfillset(&mut sigset as *mut libc::sigset_t) };

        SigSet { sigset: sigset }
    }

    pub fn empty() -> SigSet {
        let mut sigset: libc::sigset_t = unsafe { mem::uninitialized() };
        let _ = unsafe { libc::sigemptyset(&mut sigset as *mut libc::sigset_t) };

        SigSet { sigset: sigset }
    }

    pub fn add(&mut self, signum: SigNum) -> Result<()> {
        let res = unsafe { libc::sigaddset(&mut self.sigset as *mut libc::sigset_t, signum) };

        Errno::result(res).map(drop)
    }

    pub fn remove(&mut self, signum: SigNum) -> Result<()> {
        let res = unsafe { libc::sigdelset(&mut self.sigset as *mut libc::sigset_t, signum) };

        Errno::result(res).map(drop)
    }

    pub fn contains(&self, signum: SigNum) -> Result<bool> {
        let res = unsafe { libc::sigismember(&self.sigset as *const libc::sigset_t, signum) };

        match try!(Errno::result(res)) {
            1 => Ok(true),
            0 => Ok(false),
            _ => unreachable!("unexpected value from sigismember"),
        }
    }

    /// Gets the currently blocked (masked) set of signals for the calling thread.
    pub fn thread_get_mask() -> Result<SigSet> {
        let mut oldmask: SigSet = unsafe { mem::uninitialized() };
        try!(pthread_sigmask(SigFlag::empty(), None, Some(&mut oldmask)));
        Ok(oldmask)
    }

    /// Sets the set of signals as the signal mask for the calling thread.
    pub fn thread_set_mask(&self) -> Result<()> {
        pthread_sigmask(SIG_SETMASK, Some(self), None)
    }

    /// Adds the set of signals to the signal mask for the calling thread.
    pub fn thread_block(&self) -> Result<()> {
        pthread_sigmask(SIG_BLOCK, Some(self), None)
    }

    /// Removes the set of signals from the signal mask for the calling thread.
    pub fn thread_unblock(&self) -> Result<()> {
        pthread_sigmask(SIG_UNBLOCK, Some(self), None)
    }

    /// Sets the set of signals as the signal mask, and returns the old mask.
    pub fn thread_swap_mask(&self, how: SigFlag) -> Result<SigSet> {
        let mut oldmask: SigSet = unsafe { mem::uninitialized() };
        try!(pthread_sigmask(how, Some(self), Some(&mut oldmask)));
        Ok(oldmask)
    }

    /// Suspends execution of the calling thread until one of the signals in the
    /// signal mask becomes pending, and returns the accepted signal.
    pub fn wait(&self) -> Result<SigNum> {
        let mut signum: SigNum = unsafe { mem::uninitialized() };
        let res = unsafe { libc::sigwait(&self.sigset as *const libc::sigset_t, &mut signum) };

        Errno::result(res).map(|_| signum)
    }
}

impl AsRef<libc::sigset_t> for SigSet {
    fn as_ref(&self) -> &libc::sigset_t {
        &self.sigset
    }
}

#[allow(unknown_lints)]
#[allow(raw_pointer_derive)]
#[derive(Clone, Copy, PartialEq)]
pub enum SigHandler {
    SigDfl,
    SigIgn,
    Handler(extern fn(SigNum)),
    SigAction(extern fn(SigNum, *mut libc::siginfo_t, *mut libc::c_void))
}

pub struct SigAction {
    sigaction: libc::sigaction
}

impl SigAction {
    /// This function will set or unset the flag `SA_SIGINFO` depending on the
    /// type of the `handler` argument.
    pub fn new(handler: SigHandler, flags: SaFlag, mask: SigSet) -> SigAction {
        let mut s = unsafe { mem::uninitialized::<libc::sigaction>() };
        s.sa_sigaction = match handler {
            SigHandler::SigDfl => unsafe { mem::transmute(libc::SIG_DFL) },
            SigHandler::SigIgn => unsafe { mem::transmute(libc::SIG_IGN) },
            SigHandler::Handler(f) => unsafe { mem::transmute(f) },
            SigHandler::SigAction(f) => unsafe { mem::transmute(f) },
        };
        s.sa_flags = match handler {
            SigHandler::SigAction(_) => (flags | SA_SIGINFO).bits(),
            _ => (flags - SA_SIGINFO).bits(),
        };
        s.sa_mask = mask.sigset;

        SigAction { sigaction: s }
    }
}

pub unsafe fn sigaction(signum: SigNum, sigaction: &SigAction) -> Result<SigAction> {
    let mut oldact = mem::uninitialized::<libc::sigaction>();

    let res =
        libc::sigaction(signum, &sigaction.sigaction as *const libc::sigaction, &mut oldact as *mut libc::sigaction);

    Errno::result(res).map(|_| SigAction { sigaction: oldact })
}

/// Manages the signal mask (set of blocked signals) for the calling thread.
///
/// If the `set` parameter is `Some(..)`, then the signal mask will be updated with the signal set.
/// The `how` flag decides the type of update. If `set` is `None`, `how` will be ignored,
/// and no modification will take place.
///
/// If the 'oldset' parameter is `Some(..)` then the current signal mask will be written into it.
///
/// If both `set` and `oldset` is `Some(..)`, the current signal mask will be written into oldset,
/// and then it will be updated with `set`.
///
/// If both `set` and `oldset` is None, this function is a no-op.
///
/// For more information, visit the [pthread_sigmask](http://man7.org/linux/man-pages/man3/pthread_sigmask.3.html),
/// or [sigprocmask](http://man7.org/linux/man-pages/man2/sigprocmask.2.html) man pages.
pub fn pthread_sigmask(how: SigFlag,
                       set: Option<&SigSet>,
                       oldset: Option<&mut SigSet>) -> Result<()> {
    if set.is_none() && oldset.is_none() {
        return Ok(())
    }

    let res = unsafe {
        // if set or oldset is None, pass in null pointers instead
        libc::pthread_sigmask(how.bits(),
                             set.map_or_else(|| ptr::null::<libc::sigset_t>(),
                                             |s| &s.sigset as *const libc::sigset_t),
                             oldset.map_or_else(|| ptr::null_mut::<libc::sigset_t>(),
                                                |os| &mut os.sigset as *mut libc::sigset_t))
    };

    Errno::result(res).map(drop)
}

pub fn kill(pid: libc::pid_t, signum: SigNum) -> Result<()> {
    let res = unsafe { libc::kill(pid, signum) };

    Errno::result(res).map(drop)
}

pub fn raise(signum: SigNum) -> Result<()> {
    let res = unsafe { libc::raise(signum) };

    Errno::result(res).map(drop)
}

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

    #[test]
    fn test_contains() {
        let mut mask = SigSet::empty();
        mask.add(SIGUSR1).unwrap();

        assert_eq!(mask.contains(SIGUSR1), Ok(true));
        assert_eq!(mask.contains(SIGUSR2), Ok(false));

        let all = SigSet::all();
        assert_eq!(all.contains(SIGUSR1), Ok(true));
        assert_eq!(all.contains(SIGUSR2), Ok(true));
    }

    #[test]
    fn test_thread_signal_block() {
        let mut mask = SigSet::empty();
        mask.add(SIGUSR1).unwrap();

        assert!(mask.thread_block().is_ok());
    }

    #[test]
    fn test_thread_signal_swap() {
        let mut mask = SigSet::empty();
        mask.add(SIGUSR1).unwrap();
        mask.thread_block().unwrap();

        assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1).unwrap());

        let mask2 = SigSet::empty();
        mask.add(SIGUSR2).unwrap();

        let oldmask = mask2.thread_swap_mask(SIG_SETMASK).unwrap();

        assert!(oldmask.contains(SIGUSR1).unwrap());
        assert!(!oldmask.contains(SIGUSR2).unwrap());
    }

    // TODO(#251): Re-enable after figuring out flakiness.
    #[cfg(not(any(target_os = "macos", target_os = "ios")))]
    #[test]
    fn test_sigwait() {
        let mut mask = SigSet::empty();
        mask.add(SIGUSR1).unwrap();
        mask.add(SIGUSR2).unwrap();
        mask.thread_block().unwrap();

        raise(SIGUSR1).unwrap();
        assert_eq!(mask.wait().unwrap(), SIGUSR1);
    }
}
<|endoftext|>