zwave 0.0.1

Control Z-Wave networks with Rust.
use std::any::TypeId;
use std::fmt::Debug;
use std::marker::Reflect;
use std::mem;
use std::raw::TraitObject;

use core::NodeId;
use protocol::bits::{PreambleId, MessageTypeId, FunctionId};
use protocol::command::{Command, AnyCommand};

pub use self::serialization::MessageSerializer;

#[doc(hidden)]
pub mod serialization;

pub trait Message: Send + Sync + Debug + Reflect + 'static {
    #[doc(hidden)]
    const PREAMBLE_ID: PreambleId;

    #[doc(hidden)]
    fn preamble_id(&self) -> PreambleId {
        Self::PREAMBLE_ID
    }

    #[doc(hidden)]
    fn type_id(&self) -> TypeId {
        TypeId::of::<Self>()
    }
}

impl Message {
    pub fn is<M: Message>(&self) -> bool {
        TypeId::of::<M>() == self.type_id()
    }

    pub fn downcast_ref<M: Message>(&self) -> Option<&M> {
        if TypeId::of::<M>() == self.type_id() {
            unsafe {
                let fat_ptr: TraitObject = mem::transmute(self);

                Some(&*(fat_ptr.data as *const M))
            }
        }
        else {
            None
        }
    }
}

pub trait Frame: Send + Sync + Debug + Reflect + 'static {
    #[doc(hidden)]
    const MESSAGE_TYPE_ID: MessageTypeId;

    #[doc(hidden)]
    const FUNCTION_ID: FunctionId;

    #[doc(hidden)]
    fn message_type_id(&self) -> MessageTypeId {
        Self::MESSAGE_TYPE_ID
    }

    #[doc(hidden)]
    fn function_id(&self) -> FunctionId {
        Self::FUNCTION_ID
    }

    #[doc(hidden)]
    fn type_id(&self) -> TypeId {
        TypeId::of::<Self>()
    }
}

impl<F: Frame> Message for F {
    const PREAMBLE_ID: PreambleId = PreambleId::Frame;
}

def_any!(AnyMessage: Message);

#[derive(Debug)]
pub struct Ack { }

impl Ack {
    pub fn new() -> Self {
        Ack { }
    }
}

impl Message for Ack {
    const PREAMBLE_ID: PreambleId = PreambleId::Ack;
}

#[derive(Debug)]
pub struct Nack { }

impl Nack {
    pub fn new() -> Self {
        Nack { }
    }
}

impl Message for Nack {
    const PREAMBLE_ID: PreambleId = PreambleId::Nack;
}

#[derive(Debug)]
pub struct Cancel { }

impl Cancel {
    pub fn new() -> Self {
        Cancel { }
    }
}

impl Message for Cancel {
    const PREAMBLE_ID: PreambleId = PreambleId::Cancel;
}

#[derive(Debug)]
pub struct SendData {
    destination: NodeId,
    command: AnyCommand,
    callback_id: u8,
    packet_options: u8,
}

impl SendData {
    pub fn new<C: Command>(destination: NodeId, command: C, callback_id: u8) -> Self {
        SendData::with_options(destination, command, callback_id, 0x05)
    }

    pub fn with_options<C: Command>(destination: NodeId, command: C, callback_id: u8, packet_options: u8) -> Self {
        SendData {
            destination: destination,
            command: AnyCommand::new(command),
            callback_id: callback_id,
            packet_options: packet_options,
        }
    }

    pub fn destination(&self) -> NodeId {
        self.destination
    }

    pub fn command(&self) -> &AnyCommand {
        &self.command
    }

    pub fn callback_id(&self) -> u8 {
        self.callback_id
    }

    pub fn packet_options(&self) -> u8 {
        self.packet_options
    }
}

impl Frame for SendData {
    const MESSAGE_TYPE_ID: MessageTypeId = MessageTypeId::Request;
    const FUNCTION_ID: FunctionId = FunctionId::SendData;
}


#[derive(Debug)]
pub struct MessageTransmitted {
    flags: u8,
}

impl MessageTransmitted {
    pub fn new(flags: u8) -> Self {
        MessageTransmitted {
            flags: flags,
        }
    }

    pub fn flags(&self) -> u8 {
        self.flags
    }
}

impl Frame for MessageTransmitted {
    const MESSAGE_TYPE_ID: MessageTypeId = MessageTypeId::Response;
    const FUNCTION_ID: FunctionId = FunctionId::SendData;
}

#[derive(Debug)]
pub struct MessageReceived {
    callback_id: u8,
    flags: u8,
}

impl MessageReceived {
    pub fn new(callback_id: u8, flags: u8) -> Self {
        MessageReceived {
            callback_id: callback_id,
            flags: flags,
        }
    }

    pub fn callback_id(&self) -> u8 {
        self.callback_id
    }

    pub fn flags(&self) -> u8 {
        self.flags
    }
}

impl Frame for MessageReceived {
    const MESSAGE_TYPE_ID: MessageTypeId = MessageTypeId::Request;
    const FUNCTION_ID: FunctionId = FunctionId::SendData;
}