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
use byteorder::{ReadBytesExt, WriteBytesExt}; use std::io::{Read, Write}; use std::{fmt, io}; use {Endian, PreliminaryTryFrom, WithFixedPayloadLength}; #[repr(u16)] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum ErrorCode { Success = 0x0000, Failure = 0x0001, MessageConstructionError = 0x0002, InvalidOptions = 0x0003, OutOfSequence = 0x0011, PayloadTooBig = 0x0012, UnknownMessage = 0x0020, InvalidLength = 0x0021, NonExistingIndex = 0x0100, InvalidCount = 0x0101, UnsupportedType = 0x0102, UnsupportedValue = 0x0103, TypeValueMismatch = 0x0104, InvalidOperation = 0x0105, ExhaustedResources = 0x0106, InvalidState = 0x0107, InsufficientPermission = 0x0108, ProgrammingMistake = 0x0109, } impl fmt::Display for ErrorCode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:?}", self) } } impl fmt::LowerHex for ErrorCode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:x}", *self as u16) } } impl ErrorCode { pub fn is_success(&self) -> bool { *self == ErrorCode::Success } pub fn is_error(&self) -> bool { !self.is_success() } pub fn success_or_else<F, O>(self, op: O) -> Result<(), F> where O: FnOnce(ErrorCode) -> F, { if self.is_error() { Err(op(self)) } else { Ok(()) } } } impl WithFixedPayloadLength for ErrorCode { const FIXED_PAYLOAD_LENGTH: u16 = u16::FIXED_PAYLOAD_LENGTH; } impl PreliminaryTryFrom<u16> for ErrorCode { type Error = io::Error; fn try_from(value: u16) -> io::Result<Self> { match value { 0x0000 => Ok(ErrorCode::Success), 0x0001 => Ok(ErrorCode::Failure), 0x0002 => Ok(ErrorCode::MessageConstructionError), 0x0003 => Ok(ErrorCode::InvalidOptions), 0x0011 => Ok(ErrorCode::OutOfSequence), 0x0012 => Ok(ErrorCode::PayloadTooBig), 0x0020 => Ok(ErrorCode::UnknownMessage), 0x0021 => Ok(ErrorCode::InvalidLength), 0x0100 => Ok(ErrorCode::NonExistingIndex), 0x0101 => Ok(ErrorCode::InvalidCount), 0x0102 => Ok(ErrorCode::UnsupportedType), 0x0103 => Ok(ErrorCode::UnsupportedValue), 0x0104 => Ok(ErrorCode::TypeValueMismatch), 0x0105 => Ok(ErrorCode::InvalidOperation), 0x0106 => Ok(ErrorCode::ExhaustedResources), 0x0107 => Ok(ErrorCode::InvalidState), 0x0108 => Ok(ErrorCode::InsufficientPermission), 0x0109 => Ok(ErrorCode::ProgrammingMistake), _ => Err(io::Error::new( io::ErrorKind::InvalidData, format!("Invalid ErrorCode enum value {}", value), )), } } } pub(crate) trait ErrorCodeWriterExt: Write { fn write_error_code( &mut self, error_code: &ErrorCode, ) -> io::Result<()> { self.write_u16::<Endian>(*error_code as u16)?; Ok(()) } } impl<B: Write + ?Sized> ErrorCodeWriterExt for B {} pub(crate) trait ErrorCodeReaderExt: Read { fn read_error_code(&mut self) -> io::Result<ErrorCode> { let value = self.read_u16::<Endian>()?; ErrorCode::try_from(value) } } impl<B: Read + ?Sized> ErrorCodeReaderExt for B {} impl<E> Into<::std::result::Result<(), E>> for ErrorCode where E: From<ErrorCode>, { fn into(self) -> ::std::result::Result<(), E> { match self { ErrorCode::Success => Ok(()), _ => Err(E::from(self)), } } } pub trait HasErrorCode { fn error_code(&self) -> ErrorCode; } impl<'a, T: HasErrorCode> HasErrorCode for &'a T { fn error_code(&self) -> ErrorCode { (**self).error_code() } }