-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #43 from cr8t/feature/version-request-response
message: version request and response types
- Loading branch information
Showing
8 changed files
with
844 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,251 @@ | ||
use crate::{ | ||
Error, Message, MessageCode, MessageData, MessageType, RequestCode, RequestType, Result, | ||
}; | ||
|
||
/// Represents a `Version` request message. | ||
#[repr(C)] | ||
#[derive(Clone, Copy, Debug, Eq, PartialEq)] | ||
pub struct VersionRequest; | ||
|
||
impl VersionRequest { | ||
/// Creates a new [VersionRequest]. | ||
pub const fn new() -> Self { | ||
Self | ||
} | ||
|
||
/// Gets the [MessageType] for the [VersionRequest]. | ||
pub const fn message_type(&self) -> MessageType { | ||
MessageType::Request(self.request_type()) | ||
} | ||
|
||
/// Gets the [RequestType] for the [VersionRequest]. | ||
pub const fn request_type(&self) -> RequestType { | ||
RequestType::Status | ||
} | ||
|
||
/// Gets the [MessageCode] for the [VersionRequest]. | ||
pub const fn message_code(&self) -> MessageCode { | ||
MessageCode::Request(self.request_code()) | ||
} | ||
|
||
/// Gets the [RequestCode] for the [VersionRequest]. | ||
pub const fn request_code(&self) -> RequestCode { | ||
RequestCode::Version | ||
} | ||
} | ||
|
||
impl Default for VersionRequest { | ||
fn default() -> Self { | ||
Self::new() | ||
} | ||
} | ||
|
||
impl From<VersionRequest> for Message { | ||
fn from(val: VersionRequest) -> Self { | ||
Message::new().with_data(val.into()) | ||
} | ||
} | ||
|
||
impl From<&VersionRequest> for Message { | ||
fn from(val: &VersionRequest) -> Self { | ||
(*val).into() | ||
} | ||
} | ||
|
||
impl From<VersionRequest> for MessageData { | ||
fn from(val: VersionRequest) -> Self { | ||
Self::new() | ||
.with_message_type(val.message_type()) | ||
.with_message_code(val.message_code()) | ||
} | ||
} | ||
|
||
impl From<&VersionRequest> for MessageData { | ||
fn from(val: &VersionRequest) -> Self { | ||
(*val).into() | ||
} | ||
} | ||
|
||
impl TryFrom<&Message> for VersionRequest { | ||
type Error = Error; | ||
|
||
fn try_from(val: &Message) -> Result<Self> { | ||
val.data().try_into() | ||
} | ||
} | ||
|
||
impl TryFrom<Message> for VersionRequest { | ||
type Error = Error; | ||
|
||
fn try_from(val: Message) -> Result<Self> { | ||
(&val).try_into() | ||
} | ||
} | ||
|
||
impl TryFrom<&MessageData> for VersionRequest { | ||
type Error = Error; | ||
|
||
fn try_from(val: &MessageData) -> Result<Self> { | ||
let (exp_type, exp_code) = ( | ||
MessageType::Request(RequestType::Status), | ||
MessageCode::Request(RequestCode::Version), | ||
); | ||
|
||
match (val.message_type(), val.message_code()) { | ||
(msg_type, msg_code) if msg_type == exp_type && msg_code == exp_code => Ok(Self), | ||
(msg_type, msg_code) => Err(Error::InvalidMessage(( | ||
(msg_type.into(), msg_code.into()), | ||
(exp_type.into(), exp_code.into()), | ||
))), | ||
} | ||
} | ||
} | ||
|
||
impl TryFrom<MessageData> for VersionRequest { | ||
type Error = Error; | ||
|
||
fn try_from(val: MessageData) -> Result<Self> { | ||
(&val).try_into() | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
use crate::{EventCode, EventType}; | ||
|
||
#[test] | ||
fn test_version_request() -> Result<()> { | ||
let exp_type = MessageType::Request(RequestType::Status); | ||
let exp_code = MessageCode::Request(RequestCode::Version); | ||
|
||
let msg_data = MessageData::new() | ||
.with_message_type(exp_type) | ||
.with_message_code(exp_code); | ||
let msg = Message::new().with_data(msg_data); | ||
|
||
let exp_req = VersionRequest::new(); | ||
|
||
assert_eq!(exp_req.message_type(), exp_type); | ||
assert_eq!(exp_type.request_type(), Ok(exp_req.request_type())); | ||
|
||
assert_eq!(exp_req.message_code(), exp_code); | ||
assert_eq!(exp_code.request_code(), Ok(exp_req.request_code())); | ||
|
||
assert_eq!(Message::from(exp_req), msg); | ||
assert_eq!(VersionRequest::try_from(&msg), Ok(exp_req)); | ||
|
||
Ok(()) | ||
} | ||
|
||
#[test] | ||
fn test_version_request_invalid() -> Result<()> { | ||
let invalid_types = [MessageType::Reserved] | ||
.into_iter() | ||
.chain((0x80..=0x8f).map(|m| MessageType::Event(EventType::from_u8(m)))) | ||
.chain( | ||
[ | ||
RequestType::Operation, | ||
RequestType::SetFeature, | ||
RequestType::Reserved, | ||
] | ||
.map(MessageType::Request), | ||
) | ||
.collect::<Vec<MessageType>>(); | ||
|
||
let invalid_codes = [ | ||
RequestCode::Uid, | ||
RequestCode::ProgramSignature, | ||
RequestCode::SerialNumber, | ||
RequestCode::ModelName, | ||
RequestCode::Status, | ||
RequestCode::Stack, | ||
RequestCode::Idle, | ||
RequestCode::Inhibit, | ||
RequestCode::Collect, | ||
RequestCode::Key, | ||
RequestCode::EventResendInterval, | ||
RequestCode::Reset, | ||
RequestCode::Reject, | ||
RequestCode::Hold, | ||
RequestCode::AcceptorCollect, | ||
RequestCode::DenominationDisable, | ||
RequestCode::DirectionDisable, | ||
RequestCode::CurrencyAssign, | ||
RequestCode::CashBoxSize, | ||
RequestCode::NearFull, | ||
RequestCode::BarCode, | ||
RequestCode::Insert, | ||
RequestCode::ConditionalVend, | ||
RequestCode::Pause, | ||
RequestCode::NoteDataInfo, | ||
RequestCode::RecyclerCollect, | ||
RequestCode::Reserved, | ||
] | ||
.map(MessageCode::Request) | ||
.into_iter() | ||
.chain( | ||
[ | ||
EventCode::PowerUp, | ||
EventCode::PowerUpAcceptor, | ||
EventCode::PowerUpStacker, | ||
EventCode::Inhibit, | ||
EventCode::ProgramSignature, | ||
EventCode::Rejected, | ||
EventCode::Collected, | ||
EventCode::Clear, | ||
EventCode::OperationError, | ||
EventCode::Failure, | ||
EventCode::NoteStay, | ||
EventCode::PowerUpAcceptorAccepting, | ||
EventCode::PowerUpStackerAccepting, | ||
EventCode::Escrow, | ||
EventCode::VendValid, | ||
EventCode::AcceptorRejected, | ||
EventCode::Returned, | ||
EventCode::AcceptorCollected, | ||
EventCode::Insert, | ||
EventCode::ConditionalVend, | ||
EventCode::Pause, | ||
EventCode::Resume, | ||
EventCode::AcceptorClear, | ||
EventCode::AcceptorOperationError, | ||
EventCode::AcceptorFailure, | ||
EventCode::AcceptorNoteStay, | ||
EventCode::FunctionAbeyance, | ||
EventCode::Reserved, | ||
] | ||
.map(MessageCode::Event), | ||
) | ||
.collect::<Vec<MessageCode>>(); | ||
|
||
let exp_req = VersionRequest::new(); | ||
let exp_type = exp_req.message_type(); | ||
let exp_code = exp_req.message_code(); | ||
|
||
for &msg_type in invalid_types.iter() { | ||
for &msg_code in invalid_codes.iter() { | ||
let inval_data = MessageData::new() | ||
.with_message_type(msg_type) | ||
.with_message_code(msg_code); | ||
|
||
let inval_type = MessageData::new() | ||
.with_message_type(msg_type) | ||
.with_message_code(exp_code); | ||
|
||
let inval_code = MessageData::new() | ||
.with_message_type(exp_type) | ||
.with_message_code(msg_code); | ||
|
||
for stack_data in [inval_data, inval_type, inval_code] { | ||
assert!(VersionRequest::try_from(&stack_data).is_err()); | ||
assert!( | ||
VersionRequest::try_from(Message::new().with_data(stack_data)).is_err() | ||
); | ||
} | ||
} | ||
} | ||
|
||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.