water 0.8.23-alpha

Provides thread-safe distributed message sending facility supporting synchronous and asynchronous I/O across process and machine boundaries. It also uses nets which allow message broadcasts to all, groups, or specific endpoints which eliminates the need for tons of individual channels to interconnect threads. It also provides inter-process communication using a more restricted raw message type. It is hoped that this library can replace the current channel functionality.
use RawMessage;

use std::mem::size_of;
use std::intrinsics::TypeId;

/// A message that can be cloned but not copied, and can be shared with other threads.
///
/// This message _can_ be cloned and _can_ be recieved by multiple endpoints, but only
/// on the local net. This message can not cross process boundaries and is sharable only
/// with threads under the same process as the sender.
pub struct CloneMessage {
    /// The hash represents the type.
    pub hash:           u64,
    /// The payload contains the raw type bytes.
    pub payload:        RawMessage,
}

/// Provides ability to be cloned and satisfies clone contraints.
impl Clone for CloneMessage {
    /// Will produce a clone but will keep the same payload instance.
    fn clone(&self) -> CloneMessage {
        CloneMessage {
            hash:       self.hash,
            payload:    self.payload.clone(),
        }
    }
}


impl CloneMessage {
    /// Create a new clone message from a specific type.
    pub fn new<T: Send + Clone + 'static>(t: T) -> CloneMessage {
        let tyid = TypeId::of::<T>();
        let hash = tyid.hash();

        // Write the structure into a raw message, and
        // consume it in the process making it unsable.
        let mut rmsg = RawMessage::new(size_of::<T>());
        rmsg.writestruct(0, t);

        CloneMessage {
            hash:       hash,
            payload:    rmsg
        }        
    }

    /// Check if the clone message contains the type specified. `is_type::<MyType>()`
    pub fn is_type<T: Send + 'static>(&self) -> bool {
        let tyid = TypeId::of::<T>();
        let hash = tyid.hash();

        if hash != self.hash {
            return false;
        }

        return true;
    }

    /// Returns an instance of the type by consuming the clone message. The
    /// clone message is consumed to prevent another copy from being produced.
    /// To produce a copy you should call `clone` on the type returned.
    ///
    /// _There is no contraint on `T` to have the traits `Send` and `Clone` because
    /// the hash is checked to ensure it is the same type that was sent._
    pub fn get_payload<T: 'static>(self) -> T {
        let rawmsg = self.payload;

        let tyid = TypeId::of::<T>();
        let hash = tyid.hash();

        if hash != self.hash {
            panic!("clone message was not correct type");
        }

        let t: T = unsafe { rawmsg.readstructunsafe(0) };
        t
    }

}