1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
use std::io;
use std::fmt;

use std::convert::From;

/// A type for results generated by the `rpos_drv::net` module
///
/// The `Err` type is hard-wired to [`rpos_drv::net::Error`](struct.Error.html)
pub type Result<T> = std::result::Result<T, Error>;

/// Categories of errors that can occur when operating with `rpos_drv::net` module
/// This list is intended to grow over time and it is not recommended to exhaustively match against it.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ErrorKind {
    /// The execution of operation failed
    OperationFail,

    /// The execution of operation is timed out
    OperationTimeout,

    /// The device doesn't support this operation
    OperationNotSupport,

    /// The decoding data is invalid according to current protocol
    ProtocolError,

    /// The buffer is too small for message encoding
    BufferTooSmall,

    /// An I/O error occurred
    Io(io::ErrorKind),
}

/// And error type for `rpos_drv::net` module
#[derive(Debug)]
pub struct Error {
    /// The kind of error
    pub kind: ErrorKind,

    /// A description to the error suitable for end-users
    pub description: String,
}

impl Error {
    /// Instantiates a new error
    pub fn new<T: Into<String>>(kind: ErrorKind, description: T) -> Self {
        Error {
            kind,
            description: description.into(),
        }
    }

    /// Returns the corresponding `ErrorKind` for this error
    pub fn kind(&self) -> ErrorKind {
        self.kind
    }
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> std::result::Result<(), fmt::Error> {
        fmt.write_str(&self.description)
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        &self.description
    }
}

impl From<io::Error> for Error {
    fn from(io_error: io::Error) -> Error {
        Error::new(
            ErrorKind::Io(io_error.kind()),
            format!("{}", io_error)
        )
    }
}

impl From<Error> for io::Error {
    fn from(error: Error) -> io::Error {
        let kind = match error.kind {
            ErrorKind::Io(kind) => kind,
            _ => io::ErrorKind::Other
        };

        io::Error::new(kind, error.description)
    }
}

/// A message send via channels
#[derive(Debug, Clone, PartialEq)]
pub struct Message {
    /// The command
    pub cmd: u8,

    /// Payload data
    pub data: Vec<u8>
}

impl Message {
    pub fn new(cmd: u8) -> Message {
        return Message::with_data(cmd, &[]);
    }

    pub fn with_data(cmd: u8, data: &[u8]) -> Message {
        let mut msg = Message {
            cmd: cmd,
            data: Vec::with_capacity(data.len())
        };

        msg.data.extend_from_slice(&data);

        return msg;
    }
}

/// Protocol decoder
pub trait ProtocolDecoder {
    /// Decode bytes and return consumed bytes and message
    fn decode(&mut self, buf: &[u8]) -> Result<(usize, Option<Message>)>;

    /// Reset the decoder status
    fn reset_decoder(&mut self);
}

/// Protocol encoder
pub trait ProtocolEncoder {
    /// Encode message into byte array
    fn encode(&mut self, msg: &Message, bytes: &mut [u8]) -> Result<usize>;

    /// Estimate encoded message size (must be greater than or equal to the actual encoded size)
    fn estimate_encoded_size(&mut self, msg: &Message) -> Result<usize>;

    /// Write message to `std::io::Write` targets
    fn write_to(&mut self, msg: &Message, dest: &mut impl io::Write) -> Result<usize>;

    /// Reset encoder
    fn reset_encoder(&mut self);
}