1#![deny(missing_docs)]
3
4extern crate async_codec;
5extern crate async_codec_util;
6extern crate atm_io_utils;
7extern crate futures_core;
8extern crate futures_io;
9
10
11#[cfg(test)]
12#[macro_use(quickcheck)]
13extern crate quickcheck;
14#[cfg(test)]
15extern crate async_ringbuffer;
16
17macro_rules! gen_byte_module {
18 ($num:ty, $name:tt) => (
19 use async_codec::{AsyncDecode, AsyncEncode, AsyncEncodeLen, PollEnc, PollDec};
20 use futures_core::Never;
21 use futures_core::Async::{Ready, Pending};
22 use futures_core::task::Context;
23 use futures_io::{AsyncRead, AsyncWrite, Error as FutIoErr, ErrorKind};
24
25 #[doc = "Create a decoder for a `"]
26 #[doc = $name]
27 #[doc = "`."]
28 pub fn decode_byte() -> DecodeByte {
29 DecodeByte
30 }
31
32 #[doc = "Decode a `"]
33 #[doc = $name]
34 #[doc = "`."]
35 pub struct DecodeByte;
36
37 impl AsyncDecode for DecodeByte {
38 type Item = $num;
39 type Error = Never;
40
41 fn poll_decode<R: AsyncRead>(
42 self,
43 cx: &mut Context,
44 reader: &mut R
45 ) -> PollDec<Self::Item, Self,Self::Error> {
46 let mut byte = [0];
47
48 match reader.poll_read(cx, &mut byte) {
49 Ok(Ready(0)) => PollDec::Errored(FutIoErr::new(ErrorKind::UnexpectedEof, $name).into()),
50 Ok(Ready(_)) => PollDec::Done(byte[0] as $num, 1),
51 Ok(Pending) => PollDec::Pending(self),
52 Err(err) => PollDec::Errored(err.into())
53 }
54 }
55 }
56
57 #[doc = "Create an encoder for a `"]
58 #[doc = $name]
59 #[doc = "`."]
60 pub fn encode_byte(num: $num) -> EncodeByte {
61 EncodeByte {num: [num as u8]}
62 }
63
64 #[doc = "Encode a `"]
65 #[doc = $name]
66 #[doc = "`."]
67 pub struct EncodeByte {
68 num: [u8; 1]
69 }
70
71 impl AsyncEncode for EncodeByte {
72 fn poll_encode<W: AsyncWrite>(
73 self,
74 cx: &mut Context,
75 writer: &mut W
76 ) -> PollEnc<Self> {
77 match writer.poll_write(cx, &self.num[..]) {
78 Ok(Ready(0)) => PollEnc::Errored(FutIoErr::new(ErrorKind::WriteZero, $name).into()),
79 Ok(Ready(_)) => PollEnc::Done(1),
80 Ok(Pending) => PollEnc::Pending(self),
81 Err(err) => PollEnc::Errored(err)
82 }
83 }
84 }
85
86 impl AsyncEncodeLen for EncodeByte {
87 fn remaining_bytes(&self) -> usize {
88 1
89 }
90 }
91 )
92}
93
94macro_rules! gen_module {
95 ($num:ty, $name:tt, $bytes:expr, $from_be:path, $from_le:path) => (
96 use std::mem::transmute;
97
98 use async_codec::{AsyncDecode, AsyncEncode, AsyncEncodeLen, PollEnc, PollDec};
99 use futures_core::Never;
100 use futures_core::Async::{Ready, Pending};
101 use futures_core::task::Context;
102 use futures_io::{AsyncRead, AsyncWrite, Error as FutIoErr, ErrorKind};
103
104 #[doc = "Create a decoder for a `"]
105 #[doc = $name]
106 #[doc = "` in native byte order."]
107 pub fn decode_native() -> DecodeNative {
108 DecodeNative {
109 bytes: [0; $bytes],
110 offset: 0,
111 }
112 }
113
114 #[doc = "Decode a `"]
115 #[doc = $name]
116 #[doc = "` in native byte order."]
117 pub struct DecodeNative {
118 bytes: [u8; $bytes],
119 offset: u8,
120 }
121
122 impl AsyncDecode for DecodeNative {
123 type Item = $num;
124 type Error = Never;
125
126 fn poll_decode<R: AsyncRead>(
127 mut self,
128 cx: &mut Context,
129 reader: &mut R
130 ) -> PollDec<Self::Item, Self, Self::Error> {
131 match reader.poll_read(cx, &mut self.bytes[self.offset as usize..]) {
132 Ok(Ready(0)) => PollDec::Errored(FutIoErr::new(ErrorKind::UnexpectedEof, $name).into()),
133 Ok(Ready(read)) => {
134 self.offset += read as u8;
135
136 if self.offset < $bytes {
137 PollDec::Progress(self, read)
138 } else {
139 PollDec::Done(unsafe { transmute::<[u8; $bytes], $num>(self.bytes) }, read)
140 }
141 }
142 Ok(Pending) => PollDec::Pending(self),
143 Err(err) => PollDec::Errored(err.into())
144 }
145 }
146 }
147
148 #[doc = "Create a decoder for a `"]
149 #[doc = $name]
150 #[doc = "` in big-endian byte order."]
151 pub fn decode_be() -> DecodeBE {
152 DecodeBE(decode_native())
153 }
154
155 #[doc = "Decode a `"]
156 #[doc = $name]
157 #[doc = "` in big-endian byte order."]
158 pub struct DecodeBE(DecodeNative);
159
160 impl AsyncDecode for DecodeBE {
161 type Item = $num;
162 type Error = Never;
163
164 fn poll_decode<R: AsyncRead>(
165 self,
166 cx: &mut Context,
167 reader: &mut R
168 ) -> PollDec<Self::Item, Self, Self::Error> {
169 match self.0.poll_decode(cx, reader) {
170 PollDec::Done(item, read) => PollDec::Done($from_be(item), read),
171 PollDec::Progress(inner, read) => {
172 PollDec::Progress(DecodeBE(inner), read)
173 }
174 PollDec::Pending(inner) => {
175 PollDec::Pending(DecodeBE(inner))
176 }
177 PollDec::Errored(err) => PollDec::Errored(err),
178 }
179 }
180 }
181
182 #[doc = "Create a decoder for a `"]
183 #[doc = $name]
184 #[doc = "` in little-endian byte order."]
185 pub fn decode_le() -> DecodeLE {
186 DecodeLE(decode_native())
187 }
188
189 #[doc = "Decode a `"]
190 #[doc = $name]
191 #[doc = "` in little-endian byte order."]
192 pub struct DecodeLE(DecodeNative);
193
194 impl AsyncDecode for DecodeLE {
195 type Item = $num;
196 type Error = Never;
197
198 fn poll_decode<R: AsyncRead>(
199 self,
200 cx: &mut Context,
201 reader: &mut R
202 ) -> PollDec<Self::Item, Self, Self::Error> {
203 match self.0.poll_decode(cx, reader) {
204 PollDec::Done(item, read) => PollDec::Done($from_le(item), read),
205 PollDec::Progress(inner, read) => {
206 PollDec::Progress(DecodeLE(inner), read)
207 }
208 PollDec::Pending(inner) => {
209 PollDec::Pending(DecodeLE(inner))
210 }
211 PollDec::Errored(err) => PollDec::Errored(err),
212 }
213 }
214 }
215
216 #[doc = "Create an encoder for a `"]
217 #[doc = $name]
218 #[doc = "` in native byte order."]
219 pub fn encode_native(num: $num) -> EncodeNative {
220 EncodeNative {
221 bytes: unsafe { transmute::<$num, [u8; $bytes]>(num) },
222 offset: 0,
223 }
224 }
225
226 #[doc = "Encode a `"]
227 #[doc = $name]
228 #[doc = "` in native byte order."]
229 pub struct EncodeNative {
230 bytes: [u8; $bytes],
231 offset: u8,
232 }
233
234 impl AsyncEncode for EncodeNative {
235 fn poll_encode<W: AsyncWrite>(
236 mut self,
237 cx: &mut Context,
238 writer: &mut W
239 ) -> PollEnc<Self> {
240 match writer.poll_write(cx, &mut self.bytes[self.offset as usize..]) {
241 Ok(Ready(0)) => PollEnc::Errored(FutIoErr::new(ErrorKind::WriteZero, $name).into()),
242 Ok(Ready(written)) => {
243 self.offset += written as u8;
244 if self.offset < $bytes {
245 PollEnc::Progress(self, written)
246 } else {
247 PollEnc::Done(written)
248 }
249 },
250 Ok(Pending) => PollEnc::Pending(self),
251 Err(err) => PollEnc::Errored(err)
252 }
253 }
254 }
255
256 impl AsyncEncodeLen for EncodeNative {
257 fn remaining_bytes(&self) -> usize {
258 ($bytes - self.offset) as usize
259 }
260 }
261
262 #[doc = "Create an encoder for a `"]
263 #[doc = $name]
264 #[doc = "` in big-endian byte order."]
265 pub fn encode_be(num: $num) -> EncodeBE {
266 EncodeBE(encode_native(num.to_be()))
267 }
268
269 #[doc = "Encode a `"]
270 #[doc = $name]
271 #[doc = "` in big-endian byte order."]
272 pub struct EncodeBE(EncodeNative);
273
274 impl AsyncEncode for EncodeBE {
275 fn poll_encode<W: AsyncWrite>(
276 self,
277 cx: &mut Context,
278 writer: &mut W
279 ) -> PollEnc<Self> {
280 match self.0.poll_encode(cx, writer) {
281 PollEnc::Done(written) => PollEnc::Done(written),
282 PollEnc::Progress(inner, written) => {
283 PollEnc::Progress(EncodeBE(inner), written)
284 }
285 PollEnc::Pending(inner) => {
286 PollEnc::Pending(EncodeBE(inner))
287 }
288 PollEnc::Errored(err) => PollEnc::Errored(err),
289 }
290 }
291 }
292
293 impl AsyncEncodeLen for EncodeBE {
294 fn remaining_bytes(&self) -> usize {
295 self.0.remaining_bytes()
296 }
297 }
298
299 #[doc = "Create an encoder for a `"]
300 #[doc = $name]
301 #[doc = "` in little-endian byte order."]
302 pub fn encode_le(num: $num) -> EncodeLE {
303 EncodeLE(encode_native(num.to_le()))
304 }
305
306 #[doc = "Encode a `"]
307 #[doc = $name]
308 #[doc = "` in little-endian byte order."]
309 pub struct EncodeLE(EncodeNative);
310
311 impl AsyncEncode for EncodeLE {
312 fn poll_encode<W: AsyncWrite>(
313 self,
314 cx: &mut Context,
315 writer: &mut W
316 ) -> PollEnc<Self> {
317 match self.0.poll_encode(cx, writer) {
318 PollEnc::Done(written) => PollEnc::Done(written),
319 PollEnc::Progress(inner, written) => {
320 PollEnc::Progress(EncodeLE(inner), written)
321 }
322 PollEnc::Pending(inner) => {
323 PollEnc::Pending(EncodeLE(inner))
324 }
325 PollEnc::Errored(err) => PollEnc::Errored(err),
326 }
327 }
328 }
329
330 impl AsyncEncodeLen for EncodeLE {
331 fn remaining_bytes(&self) -> usize {
332 self.0.remaining_bytes()
333 }
334 }
335 )
336}
337
338mod mod_u8 {
339 gen_byte_module!{u8, "u8"}
340}
341pub use self::mod_u8::decode_byte as decode_u8;
342pub use self::mod_u8::DecodeByte as DecodeU8;
343pub use self::mod_u8::encode_byte as encode_u8;
344pub use self::mod_u8::EncodeByte as EncodeU8;
345
346mod mod_i8 {
347 gen_byte_module!{i8, "i8"}
348}
349pub use self::mod_i8::decode_byte as decode_i8;
350pub use self::mod_i8::DecodeByte as DecodeI8;
351pub use self::mod_i8::encode_byte as encode_i8;
352pub use self::mod_i8::EncodeByte as EncodeI8;
353
354mod mod_u16 {
355 gen_module!{u16, "u16", 2, u16::from_be, u16::from_le}
356}
357pub use self::mod_u16::decode_native as decode_u16_native;
358pub use self::mod_u16::DecodeNative as DecodeU16Native;
359pub use self::mod_u16::decode_be as decode_u16_be;
360pub use self::mod_u16::DecodeBE as DecodeU16BE;
361pub use self::mod_u16::decode_le as decode_u16_le;
362pub use self::mod_u16::DecodeLE as DecodeU16LE;
363pub use self::mod_u16::encode_native as encode_u16_native;
364pub use self::mod_u16::EncodeNative as EncodeU16Native;
365pub use self::mod_u16::encode_be as encode_u16_be;
366pub use self::mod_u16::EncodeBE as EncodeU16BE;
367pub use self::mod_u16::encode_le as encode_u16_le;
368pub use self::mod_u16::EncodeLE as EncodeU16LE;
369
370mod mod_u32 {
371 gen_module!{u32, "u32", 4, u32::from_be, u32::from_le}
372}
373pub use self::mod_u32::decode_native as decode_u32_native;
374pub use self::mod_u32::DecodeNative as DecodeU32Native;
375pub use self::mod_u32::decode_be as decode_u32_be;
376pub use self::mod_u32::DecodeBE as DecodeU32BE;
377pub use self::mod_u32::decode_le as decode_u32_le;
378pub use self::mod_u32::DecodeLE as DecodeU32LE;
379pub use self::mod_u32::encode_native as encode_u32_native;
380pub use self::mod_u32::EncodeNative as EncodeU32Native;
381pub use self::mod_u32::encode_be as encode_u32_be;
382pub use self::mod_u32::EncodeBE as EncodeU32BE;
383pub use self::mod_u32::encode_le as encode_u32_le;
384pub use self::mod_u32::EncodeLE as EncodeU32LE;
385
386mod mod_u64 {
387 gen_module!{u64, "u64", 8, u64::from_be, u64::from_le}
388}
389pub use self::mod_u64::decode_native as decode_u64_native;
390pub use self::mod_u64::DecodeNative as DecodeU64Native;
391pub use self::mod_u64::decode_be as decode_u64_be;
392pub use self::mod_u64::DecodeBE as DecodeU64BE;
393pub use self::mod_u64::decode_le as decode_u64_le;
394pub use self::mod_u64::DecodeLE as DecodeU64LE;
395pub use self::mod_u64::encode_native as encode_u64_native;
396pub use self::mod_u64::EncodeNative as EncodeU64Native;
397pub use self::mod_u64::encode_be as encode_u64_be;
398pub use self::mod_u64::EncodeBE as EncodeU64BE;
399pub use self::mod_u64::encode_le as encode_u64_le;
400pub use self::mod_u64::EncodeLE as EncodeU64LE;
401
402mod mod_i16 {
403 gen_module!{i16, "i16", 2, i16::from_be, i16::from_le}
404}
405pub use self::mod_i16::decode_native as decode_i16_native;
406pub use self::mod_i16::DecodeNative as DecodeI16Native;
407pub use self::mod_i16::decode_be as decode_i16_be;
408pub use self::mod_i16::DecodeBE as DecodeI16BE;
409pub use self::mod_i16::decode_le as decode_i16_le;
410pub use self::mod_i16::DecodeLE as DecodeI16LE;
411pub use self::mod_i16::encode_native as encode_i16_native;
412pub use self::mod_i16::EncodeNative as EncodeI16Native;
413pub use self::mod_i16::encode_be as encode_i16_be;
414pub use self::mod_i16::EncodeBE as EncodeI16BE;
415pub use self::mod_i16::encode_le as encode_i16_le;
416pub use self::mod_i16::EncodeLE as EncodeI16LE;
417
418mod mod_i32 {
419 gen_module!{i32, "i32", 4, i32::from_be, i32::from_le}
420}
421pub use self::mod_i32::decode_native as decode_i32_native;
422pub use self::mod_i32::DecodeNative as DecodeI32Native;
423pub use self::mod_i32::decode_be as decode_i32_be;
424pub use self::mod_i32::DecodeBE as DecodeI32BE;
425pub use self::mod_i32::decode_le as decode_i32_le;
426pub use self::mod_i32::DecodeLE as DecodeI32LE;
427pub use self::mod_i32::encode_native as encode_i32_native;
428pub use self::mod_i32::EncodeNative as EncodeI32Native;
429pub use self::mod_i32::encode_be as encode_i32_be;
430pub use self::mod_i32::EncodeBE as EncodeI32BE;
431pub use self::mod_i32::encode_le as encode_i32_le;
432pub use self::mod_i32::EncodeLE as EncodeI32LE;
433
434mod mod_i64 {
435 gen_module!{i64, "i64", 8, i64::from_be, i64::from_le}
436}
437pub use self::mod_i64::decode_native as decode_i64_native;
438pub use self::mod_i64::DecodeNative as DecodeI64Native;
439pub use self::mod_i64::decode_be as decode_i64_be;
440pub use self::mod_i64::DecodeBE as DecodeI64BE;
441pub use self::mod_i64::decode_le as decode_i64_le;
442pub use self::mod_i64::DecodeLE as DecodeI64LE;
443pub use self::mod_i64::encode_native as encode_i64_native;
444pub use self::mod_i64::EncodeNative as EncodeI64Native;
445pub use self::mod_i64::encode_be as encode_i64_be;
446pub use self::mod_i64::EncodeBE as EncodeI64BE;
447pub use self::mod_i64::encode_le as encode_i64_le;
448pub use self::mod_i64::EncodeLE as EncodeI64LE;
449
450#[cfg(test)]
451mod tests {
452 use atm_io_utils::partial::*;
453 use async_codec_util::testing::test_codec_len;
454 use async_ringbuffer::ring_buffer;
455
456 use super::*;
457
458 macro_rules! gen_byte_test {
459 ($num:ty, $decode_byte:expr, $encode_byte:expr) => (
460 quickcheck! {
461 fn test(buf_size: usize, read_ops: Vec<PartialOp>, write_ops: Vec<PartialOp>, num: $num) -> bool {
462 let mut read_ops = read_ops;
463 let mut write_ops = write_ops;
464 let (w, r) = ring_buffer(buf_size + 1);
465 let w = PartialWrite::new(w, write_ops.drain(..));
466 let r = PartialRead::new(r, read_ops.drain(..));
467
468 let test_outcome = test_codec_len(r, w, $decode_byte(), $encode_byte(num));
469 test_outcome.1 && test_outcome.0 == num
470 }
471 }
472 );
473 }
474
475 macro_rules! gen_test {
476 ($num: ty, $decode_native:expr, $encode_native:expr, $decode_be:expr, $encode_be:expr, $decode_le:expr, $encode_le:expr) => (
477 quickcheck! {
478 fn native(buf_size: usize, read_ops: Vec<PartialOp>, write_ops: Vec<PartialOp>, num: $num) -> bool {
479 let mut read_ops = read_ops;
480 let mut write_ops = write_ops;
481 let (w, r) = ring_buffer(buf_size + 1);
482 let w = PartialWrite::new(w, write_ops.drain(..));
483 let r = PartialRead::new(r, read_ops.drain(..));
484
485 let test_outcome = test_codec_len(r, w, $decode_native(), $encode_native(num));
486 test_outcome.1 && (test_outcome.0 == num)
487 }
488 }
489
490 quickcheck! {
491 fn be(buf_size: usize, read_ops: Vec<PartialOp>, write_ops: Vec<PartialOp>, num: $num) -> bool {
492 let mut read_ops = read_ops;
493 let mut write_ops = write_ops;
494 let (w, r) = ring_buffer(buf_size + 1);
495 let w = PartialWrite::new(w, write_ops.drain(..));
496 let r = PartialRead::new(r, read_ops.drain(..));
497
498 let test_outcome = test_codec_len(r, w, $decode_be(), $encode_be(num));
499 test_outcome.1 && test_outcome.0 == num
500 }
501 }
502
503 quickcheck! {
504 fn le(buf_size: usize, read_ops: Vec<PartialOp>, write_ops: Vec<PartialOp>, num: $num) -> bool {
505 let mut read_ops = read_ops;
506 let mut write_ops = write_ops;
507 let (w, r) = ring_buffer(buf_size + 1);
508 let w = PartialWrite::new(w, write_ops.drain(..));
509 let r = PartialRead::new(r, read_ops.drain(..));
510
511 let test_outcome = test_codec_len(r, w, $decode_le(), $encode_le(num));
512 test_outcome.1 && test_outcome.0 == num
513 }
514 }
515 )
516 }
517
518 mod test_u8 {
519 use super::*;
520 gen_byte_test!{u8, decode_u8, encode_u8}
521 }
522
523 mod test_i8 {
524 use super::*;
525 gen_byte_test!{i8, decode_i8, encode_i8}
526 }
527
528 mod test_u16 {
529 use super::*;
530 gen_test!{u16, decode_u16_native, encode_u16_native, decode_u16_be, encode_u16_be, decode_u16_le, encode_u16_le}
531 }
532
533 mod test_u32 {
534 use super::*;
535 gen_test!{u32, decode_u32_native, encode_u32_native, decode_u32_be, encode_u32_be, decode_u32_le, encode_u32_le}
536 }
537
538 mod test_u64 {
539 use super::*;
540 gen_test!{u64, decode_u64_native, encode_u64_native, decode_u64_be, encode_u64_be, decode_u64_le, encode_u64_le}
541 }
542
543 mod test_i16 {
544 use super::*;
545 gen_test!{i16, decode_i16_native, encode_i16_native, decode_i16_be, encode_i16_be, decode_i16_le, encode_i16_le}
546 }
547
548 mod test_i32 {
549 use super::*;
550 gen_test!{i32, decode_i32_native, encode_i32_native, decode_i32_be, encode_i32_be, decode_i32_le, encode_i32_le}
551 }
552
553 mod test_i64 {
554 use super::*;
555 gen_test!{i64, decode_i64_native, encode_i64_native, decode_i64_be, encode_i64_be, decode_i64_le, encode_i64_le}
556 }
557}