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 buf.split_to(OPC_HEADER_LENGTH);
147 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,0, 0,3, 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,0, 0,3, 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}