diffusion/
lib.rs

1#![warn(missing_docs,
2        missing_debug_implementations, missing_copy_implementations,
3        trivial_casts, trivial_numeric_casts,
4        unstable_features,
5        unused_import_braces, unused_qualifications)]
6
7//! # Diffusion
8//! Diffusion is a static library that provides several transport with a unified interface for
9//! messages based sub-pub style communication.
10
11mod file;
12mod multicast;
13
14use std::convert::From;
15use std::{error, fmt};
16
17/// represents errors that can be encountered during the usage of of reader and writer.
18#[derive(Copy, Clone, Debug, PartialEq, Eq)]
19pub enum Error {
20    /// indicates corruption when initializing the reader. This can only happens in a file.
21    CorruptSegmentHeader,
22    /// indicates corruption when reading a message. This can only happens in a file.
23    CorruptMsgHeader,
24    /// indicates possibily a curruption. `usize` means the number of bytes it need in addition to
25    /// what is already in there. This can only happens in a file.
26    InsufficientLength(usize),
27    /// indicates there is an IO error happening during reading or writing. This can happen in all
28    /// transport types.
29    IoError(std::io::ErrorKind),
30}
31
32impl fmt::Display for Error {
33    fn fmt(&self, f: &mut fmt::Formatter) -> std::result::Result<(), fmt::Error> {
34        write!(f, "{:?}", self)
35    }
36}
37
38impl error::Error for Error {
39    fn description(&self) -> &str {
40        match *self {
41            Error::CorruptSegmentHeader => "corrupted segment header",
42            Error::CorruptMsgHeader => "corruped message header",
43            Error::InsufficientLength(..) => "insufficient length",
44            Error::IoError(..) => "I/O error",
45        }
46    }
47
48    fn cause(&self) -> Option<&dyn error::Error> {
49        None
50    }
51}
52
53impl From<std::io::Error> for Error {
54    fn from(err: std::io::Error) -> Error {
55        Error::IoError(err.kind())
56    }
57}
58
59/// is an alias for crate level result derived from the crate level `Error`.
60pub type Result<T> = std::result::Result<T, Error>;
61
62/// is the general trait for all readers.
63pub trait Reader {
64    /// returns a message if there is one. And returns any error if it cannot return the message.
65    /// It returns a `Ok(None)` if file reader has reached to the end of the file, or there is no
66    /// new message currently, in which case user should retry.
67    fn read(&mut self) -> Result<Option<Vec<u8>>>;
68}
69
70/// is the general trait for all writers.
71pub trait Writer {
72    /// returns `Ok(())` if write is successful.
73    fn write(&mut self, buf: &[u8]) -> Result<()>;
74}
75
76pub use file::{FileReader, FileWriter};
77pub use multicast::{MulticastReader, MulticastWriter};
78
79#[cfg(test)]
80mod tests {
81    use ::std;
82    use super::*;
83
84    #[test]
85    fn reader_return_err_on_corrupted_header() {
86        let empty = std::io::empty();
87        assert_eq!(Error::CorruptSegmentHeader, FileReader::new(empty).err().unwrap());
88        let wrong_header = &b"DFSM"[..];
89        assert_eq!(Error::CorruptSegmentHeader, FileReader::new(wrong_header).err().unwrap());
90    }
91
92    #[test]
93    fn reader_read_one_message() {
94        let data = &b"DFSN\x05\0\0\0hello"[..];
95        assert_eq!(b"hello"[..], FileReader::new(data).unwrap().read().unwrap().unwrap()[..]);
96    }
97
98    #[test]
99    fn reader_return_err_on_truncated_data() {
100        let truncated_data = &b"DFSN\x05\0\0\0hell"[..];
101        assert_eq!(Err(Error::InsufficientLength(1)), FileReader::new(truncated_data).unwrap().read());
102    }
103
104    #[test]
105    fn reader_return_err_on_corrupted_message_header() {
106        let data_with_corrupted_header = &b"DFSN\x05\0\0"[..];
107        assert_eq!(Err(Error::CorruptMsgHeader), FileReader::new(data_with_corrupted_header).unwrap().read());
108    }
109
110    #[test]
111    fn writer_return_err_when_writing_header_with_short_length() {
112        let mut buffer = [0u8;3];
113        assert_eq!(Error::CorruptSegmentHeader, FileWriter::new(&mut buffer[..]).err().unwrap());
114    }
115
116    #[test]
117    fn writer_write_one_message() {
118        let message: &[u8] = b"hello";
119        let mut writer: Vec<u8> = vec![];
120        assert!(FileWriter::new(&mut writer).unwrap().write(message).is_ok());
121        assert_eq!(b"DFSN\x05\0\0\0hello".as_ref(), &writer[..]);
122    }
123}