tk_opc/
lib.rs

1extern crate tokio_io;
2extern crate bytes;
3
4use tokio_io::codec::{Decoder, Encoder};
5use bytes::BytesMut;
6
7mod pixel;
8mod sysexclusive;
9
10pub struct OPCCodec;
11
12pub use pixel::Pixels;
13pub use sysexclusive::SystemExclusiveData;
14
15#[derive(Clone,Debug)]
16pub enum OpcMessageData {
17    SetPixelColours(Pixels),
18    SystemExclusive(SystemExclusiveData),
19    Other(u8, Vec<u8>),
20}
21
22impl OpcMessageData {
23    fn len(&self) -> usize {
24        match *self {
25            OpcMessageData::SetPixelColours(ref pixels) => pixels.len_bytes(),
26            OpcMessageData::SystemExclusive(ref sysdata) => sysdata.len_bytes(),
27            OpcMessageData::Other(_, ref data) => data.len(),
28        }
29    }
30}
31
32
33impl std::convert::From<OpcMessageData> for Vec<u8> {
34    fn from(t: OpcMessageData) -> Vec<u8> {
35        match t {
36            OpcMessageData::SetPixelColours(pixels) => pixels.into(),
37            OpcMessageData::SystemExclusive(sysdata) => sysdata.into(),
38            OpcMessageData::Other(_, data) => data,
39        }
40    }
41}
42
43#[derive(Clone,Debug)]
44pub struct OpcMessage {
45    pub channel: u8,
46    pub message: OpcMessageData,
47}
48
49impl OpcMessage {
50    pub fn new(channel: u8, msg: OpcMessageData) -> Self {
51        OpcMessage {
52            channel: channel,
53            message: msg,
54        }
55    }
56
57    pub fn header(&self) -> OpcHeader {
58        let command = match self.message {
59            OpcMessageData::SetPixelColours(_) => 0,
60            OpcMessageData::SystemExclusive(_) => 255,
61            OpcMessageData::Other(cmd, _) => cmd,
62        };
63
64        OpcHeader {
65 channel: self.channel,
66     command: command,
67     length: self.message.len() as u16,
68}   
69    }
70}
71
72const OPC_HEADER_LENGTH: usize = 4;
73
74#[derive(Copy,Clone,Debug)]
75pub struct OpcHeader {
76    pub channel: u8,
77    pub command: u8,
78    pub length: u16,
79}
80
81impl OpcHeader {
82    pub fn new(buf: &[u8]) -> Self {
83        
84        OpcHeader {
85            channel: buf[0],
86            command: buf[1],
87            length: (((buf[2] as u16) << 8) + (buf[3] as u16)),
88        }
89    }
90
91    pub fn read_header<T: std::io::Read>(r: &mut T) -> std::io::Result<Self> {
92        let mut buf = [0u8; 4];
93        r.read_exact(&mut buf)?;
94
95        Ok(OpcHeader {
96            channel: buf[0],
97            command: buf[1],
98            length: (((buf[2] as u16) << 8) + (buf[3] as u16)),
99        })
100    }
101
102    pub fn to_bytes(&self) -> [u8;4] {
103        let len1: u8 = ((self.length >> 8) & 0xff) as u8;
104        let len2: u8 = (self.length & 0xff) as u8;
105
106        [self.channel, self.command, len1, len2]
107    }
108
109    pub fn write_header<T: std::io::Write>(&self, w: &mut T) -> std::io::Result<()> {
110        let buf = self.to_bytes();
111        w.write_all(&buf)?;
112
113        Ok(())
114    }
115}
116
117#[cfg(not(feature="failfast"))]
118fn verify_vec_size(mut d: Vec<u8>) -> Vec<u8> {
119    if d.len() > (std::u16::MAX as usize) {
120        d.truncate(std::u16::MAX as usize);
121    }
122
123    d
124}
125
126#[cfg(feature="failfast")]
127fn verify_vec_size(d: Vec<u8>) -> Vec<u8> {
128    if d.len() > (std::u16::MAX as usize) {
129        panic!("Vector too big for OPC Message")
130    }
131    d
132}
133
134impl Decoder for OPCCodec {
135    type Item = OpcMessage;
136    type Error = std::io::Error;
137
138    fn decode(&mut self, buf: &mut BytesMut) -> std::io::Result<Option<OpcMessage>> {
139        if buf.len() >= OPC_HEADER_LENGTH {
140            let header = OpcHeader::new(buf);
141
142            let packet_size = OPC_HEADER_LENGTH + header.length as usize;
143
144            if buf.len() >= packet_size {
145                //get rid of header, we all ready have it..
146                buf.split_to(OPC_HEADER_LENGTH);
147                // read the data
148                let data = buf.split_to(header.length as usize).to_vec();
149                let data = match header.command {
150                    0 => OpcMessageData::SetPixelColours(data.into()),
151                    255 => OpcMessageData::SystemExclusive(data.into()),
152                    _ => OpcMessageData::Other(header.command, data),
153                };
154                Ok(Some(OpcMessage::new(header.channel, data)))
155            } else {
156                Ok(None)
157            }
158        } else {
159            Ok(None)
160        }
161    }
162
163    fn decode_eof(&mut self, buf: &mut BytesMut) -> std::io::Result<Option<OpcMessage>> {
164        self.decode(buf)
165    }
166}
167
168impl Encoder for OPCCodec {
169    type Item = OpcMessage;
170    type Error = std::io::Error;
171
172
173    fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> {
174
175        let mut header = item.header();
176
177        let data: Vec<u8> = item.message.into();
178        let data = verify_vec_size(data);
179        let datalen = data.len();
180        
181        header.length = datalen as u16;
182        let headerbuf = header.to_bytes();
183
184        dst.extend(&headerbuf);
185        dst.extend(data);
186
187        Ok(())
188
189    }
190}
191
192#[cfg(test)]
193mod tests {
194    use super::*;
195    use bytes;
196
197    #[test]
198    fn vec_of_pixels_deserialized() {
199        let mut pixels_vec: BytesMut = vec![1u8,// channel
200        0, // command
201        0,3, // size
202        1,2,3]
203            .into();
204        let mut codec = OPCCodec;
205
206        let pixelsmsg: OpcMessage = codec.decode(&mut pixels_vec).unwrap().unwrap();
207
208        assert_eq!(pixelsmsg.channel, 1);
209
210        let pixels = match pixelsmsg.message {
211            OpcMessageData::SetPixelColours(pixels) => pixels,
212            _ => panic!("wrong message"),
213        };
214        let pixel = pixels.iter().next().unwrap();
215        assert_eq!(pixel.r(), 1);
216        assert_eq!(pixel.g(), 2);
217        assert_eq!(pixel.b(), 3);
218    }
219
220
221    #[test]
222    fn vec_of_pixels_serialized() {
223        let mut p = Pixels::new(1);
224        {
225            let mut pixel = p.iter_mut().next().unwrap();
226            pixel.set_r(1);
227            pixel.set_g(2);
228            pixel.set_b(3);
229        }
230        let msg = OpcMessage::new(1, OpcMessageData::SetPixelColours(p));
231        let expect_pixels_vec = vec![1u8,// channel
232        0,   // command
233        0,3, // size
234        1,2,3];
235
236        let mut serialized = bytes::Bytes::new().try_mut().unwrap();
237        let mut codec = OPCCodec;
238
239        codec.encode(msg, &mut serialized).unwrap();
240
241        assert_eq!(expect_pixels_vec, serialized.to_vec());
242
243    }
244}