Commit 6a53cb7a authored by David Cuddeback's avatar David Cuddeback
Browse files

adds some basic protocol serialization

parent 2817664c
use std::error;
use std::fmt;
use std::result;
use serial;
pub type Result<T> = result::Result<T,Error>;
#[derive(Debug,Clone,Copy,PartialEq,Eq)]
pub enum ErrorKind {
Protocol,
ShortRead,
Corrupt,
Io,
Timeout,
Nack,
Cancel,
}
#[derive(Debug,Clone,Copy,PartialEq,Eq)]
pub struct Error {
kind: ErrorKind,
}
impl Error {
pub fn new(kind: ErrorKind) -> Self {
Error {
kind: kind,
}
}
pub fn kind(&self) -> ErrorKind {
self.kind
}
pub fn description(&self) -> &str {
match self.kind {
ErrorKind::Protocol => "protocol error",
ErrorKind::ShortRead => "data is too short",
ErrorKind::Corrupt => "data is corrupt",
ErrorKind::Io => "I/O error",
ErrorKind::Timeout => "operation timed out",
ErrorKind::Nack => "request not acknowledged",
ErrorKind::Cancel => "request canceled",
}
}
}
impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
fmt.write_str(self.description())
}
}
impl error::Error for Error {
fn description(&self) -> &str {
Error::description(self)
}
}
impl From<serial::Error> for Error {
fn from(_: serial::Error) -> Self {
Error::new(ErrorKind::Io)
}
}
#[derive(Debug,Default,Clone,Copy,PartialEq,Eq)]
pub struct NodeId(pub u8);
impl NodeId {
pub fn value(&self) -> u8 {
let NodeId(value) = *self;
value
}
}
#![feature(associated_consts,reflect_marker,raw)]
pub mod core;
pub mod protocol;
macro_rules! def_any {
($name:ident : $bound:ident) => {
pub struct $name {
type_id: ::std::any::TypeId,
object: Box<$bound>,
}
impl $name {
pub fn new<T: $bound>(object: T) -> Self {
$name {
type_id: ::std::any::TypeId::of::<T>(),
object: Box::new(object),
}
}
pub fn is<T: $bound>(&self) -> bool {
::std::any::TypeId::of::<T>() == self.type_id
}
pub fn downcast_ref<T: $bound>(&self) -> Option<&T> {
if self.is::<T>() {
unsafe {
let fat_ptr: ::std::raw::TraitObject = ::std::mem::transmute(::std::ops::Deref::deref(self));
Some(&*(fat_ptr.data as *const T))
}
}
else {
None
}
}
pub fn downcast<T: $bound>(self) -> Result<Box<T>, Self> {
if self.is::<T>() {
unsafe {
let raw = Box::into_raw(self.object);
let fat_ptr: ::std::raw::TraitObject = ::std::mem::transmute(raw);
Ok(Box::from_raw(fat_ptr.data as *mut T))
}
}
else {
Err(self)
}
}
}
impl ::std::fmt::Debug for $name {
fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
::std::fmt::Debug::fmt(&self.object, fmt)
}
}
impl ::std::ops::Deref for $name {
type Target = $bound;
fn deref(&self) -> &$bound {
::std::ops::Deref::deref(&self.object)
}
}
impl ::std::ops::DerefMut for $name {
fn deref_mut(&mut self) -> &mut $bound {
::std::ops::DerefMut::deref_mut(&mut self.object)
}
}
impl ::std::borrow::Borrow<$bound> for $name {
fn borrow(&self) -> &$bound {
::std::borrow::Borrow::borrow(&self.object)
}
}
impl ::std::borrow::BorrowMut<$bound> for $name {
fn borrow_mut(&mut self) -> &mut $bound {
::std::borrow::BorrowMut::borrow_mut(&mut self.object)
}
}
}
}
#[derive(Debug,Hash,PartialEq,Eq)]
#[repr(u8)]
pub enum PreambleId {
Frame = 0x01,
Ack = 0x06,
Nack = 0x15,
Cancel = 0x18,
}
impl PreambleId {
pub fn from_u8(value: u8) -> Option<PreambleId> {
match value {
0x01 => Some(PreambleId::Frame),
0x06 => Some(PreambleId::Ack),
0x15 => Some(PreambleId::Nack),
0x18 => Some(PreambleId::Cancel),
_ => None,
}
}
}
#[derive(Debug,Hash,PartialEq,Eq)]
#[repr(u8)]
pub enum MessageTypeId {
Request = 0x00,
Response = 0x01,
}
impl MessageTypeId {
pub fn from_u8(value: u8) -> Option<MessageTypeId> {
match value {
0x00 => Some(MessageTypeId::Request),
0x01 => Some(MessageTypeId::Response),
_ => None,
}
}
}
#[derive(Debug,Hash,PartialEq,Eq)]
#[repr(u8)]
pub enum FunctionId {
SendData = 0x13,
}
impl FunctionId {
pub fn from_u8(value: u8) -> Option<FunctionId> {
match value {
0x13 => Some(FunctionId::SendData),
_ => None,
}
}
}
pub type CommandClassId = u8;
pub type CommandId = u8;
use protocol::bits::{CommandClassId, CommandId};
use protocol::command::Command;
pub const COMMAND_CLASS_ID: CommandClassId = 0x20;
#[derive(Debug,Clone,Copy,PartialEq,Eq)]
pub struct SetValue {
value: u8,
}
impl SetValue {
pub fn new(value: u8) -> Self {
SetValue { value: value }
}
pub fn value(&self) -> u8 {
self.value
}
}
impl Command for SetValue {
const COMMAND_CLASS_ID: CommandClassId = COMMAND_CLASS_ID;
const COMMAND_ID: CommandId = 0x01;
}
#[derive(Debug,Clone,Copy,PartialEq,Eq)]
pub struct GetValue { }
impl GetValue {
pub fn new() -> Self {
GetValue { }
}
}
impl Command for GetValue {
const COMMAND_CLASS_ID: CommandClassId = COMMAND_CLASS_ID;
const COMMAND_ID: CommandId = 0x02;
}
#[derive(Debug,Clone,PartialEq,Eq)]
pub struct Report {
value: u8,
}
impl Report {
pub fn new(value: u8) -> Self {
Report { value: value }
}
}
pub mod serialization {
use std::any::TypeId;
use core;
use protocol::bits::{CommandClassId, CommandId};
use protocol::command::{Serialize, Command, AnyCommand};
pub struct SetValueSerializer;
impl Serialize for SetValueSerializer {
fn type_id(&self) -> TypeId {
TypeId::of::<super::SetValue>()
}
fn key(&self) -> (CommandClassId, CommandId) {
(super::SetValue::COMMAND_CLASS_ID, super::SetValue::COMMAND_ID)
}
fn serialize(&self, command: &Command, buffer: &mut Vec<u8>) -> core::Result<()> {
let set_value = command.downcast_ref::<super::SetValue>().unwrap();
buffer.push(set_value.value());
Ok(())
}
fn deserialize(&self, buffer: &[u8]) -> core::Result<AnyCommand> {
if buffer.len() == 1 {
Ok(AnyCommand::new(super::SetValue::new(buffer[0])))
}
else {
Err(core::Error::new(core::ErrorKind::ShortRead))
}
}
}
pub struct GetValueSerializer;
impl Serialize for GetValueSerializer {
fn type_id(&self) -> TypeId {
TypeId::of::<super::GetValue>()
}
fn key(&self) -> (CommandClassId, CommandId) {
(super::GetValue::COMMAND_CLASS_ID, super::GetValue::COMMAND_ID)
}
fn serialize(&self, command: &Command, _buffer: &mut Vec<u8>) -> core::Result<()> {
command.downcast_ref::<super::GetValue>().unwrap();
Ok(())
}
fn deserialize(&self, _buffer: &[u8]) -> core::Result<AnyCommand> {
Ok(AnyCommand::new(super::GetValue::new()))
}
}
}
use std::any::TypeId;
use std::collections::HashMap;
use std::fmt::Debug;
use std::marker::Reflect;
use std::mem;
use std::raw::TraitObject;
use core;
use protocol::bits::{CommandClassId,CommandId};
pub mod basic;
pub trait Command: Send + Sync + Debug + Reflect + 'static {
const COMMAND_CLASS_ID: CommandClassId;
const COMMAND_ID: CommandId;
fn command_class_id(&self) -> CommandClassId {
Self::COMMAND_CLASS_ID
}
fn command_id(&self) -> CommandId {
Self::COMMAND_ID
}
fn type_id(&self) -> TypeId {
TypeId::of::<Self>()
}
}
impl Command {
pub fn downcast_ref<C: Command>(&self) -> Option<&C> {
if TypeId::of::<C>() == self.type_id() {
unsafe {
let fat_ptr: TraitObject = mem::transmute(self);
Some(&*(fat_ptr.data as *const C))
}
}
else {
None
}
}
}
def_any!(AnyCommand: Command);
pub trait Serialize: Send + 'static {
fn type_id(&self) -> TypeId;
fn key(&self) -> (CommandClassId, CommandId);
fn serialize(&self, command: &Command, buffer: &mut Vec<u8>) -> core::Result<()>;
fn deserialize(&self, buffer: &[u8]) -> core::Result<AnyCommand>;
}
pub struct CommandSerializer {
types: HashMap<(CommandClassId,CommandId), TypeId>,
serializers: HashMap<TypeId, Box<Serialize>>,
}
impl CommandSerializer {
pub fn new() -> Self {
let mut serializer = CommandSerializer {
types: HashMap::<(CommandClassId,CommandId), TypeId>::new(),
serializers: HashMap::<TypeId, Box<Serialize>>::new(),
};
serializer.register(basic::serialization::SetValueSerializer);
serializer.register(basic::serialization::GetValueSerializer);
serializer
}
pub fn serialize(&self, command: &Command, buffer: &mut Vec<u8>) -> core::Result<()> {
buffer.push(command.command_class_id());
buffer.push(command.command_id());
match self.serializers.get(&command.type_id()) {
Some(serializer) => serializer.serialize(command, buffer),
None => Err(core::Error::new(core::ErrorKind::Protocol)),
}
}
pub fn deserialize(&self, buffer: &[u8]) -> core::Result<AnyCommand> {
if buffer.len() < 2 {
return Err(core::Error::new(core::ErrorKind::ShortRead));
}
let command_class_id = buffer[0];
let command_id = buffer[1];
match self.types.get(&(command_class_id, command_id)) {
Some(type_id) => {
match self.serializers.get(type_id) {
Some(serializer) => serializer.deserialize(&buffer[2..]),
None => Err(core::Error::new(core::ErrorKind::Protocol)),
}
},
None => Err(core::Error::new(core::ErrorKind::Protocol)),
}
}
fn register<S: Serialize>(&mut self, serializer: S) {
self.types.insert(serializer.key(), serializer.type_id());
self.serializers.insert(serializer.type_id(), Box::new(serializer));
}
}
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
}