use crate::std;
use std::fmt;
use crate::{
banknote::*, cash::CurrencyDenomination, impl_from_for_omnibus_reply, impl_message_ops,
impl_omnibus_reply_ops, len::OMNIBUS_REPLY, status::*, AdvancedBookmarkModeReply,
ClearAuditDataRequestAck, ClearAuditDataRequestResults, ExtendedNoteInhibitsReplyAlt,
ExtendedNoteReply, MessageOps, MessageType, NoteRetrievedEvent, NoteRetrievedReply,
QueryApplicationIdReply, QueryApplicationPartNumberReply, QueryBootPartNumberReply,
QueryDeviceCapabilitiesReply, QueryValueTableReply, QueryVariantIdReply, QueryVariantNameReply,
QueryVariantPartNumberReply, SetEscrowTimeoutReply, StandardDenomination,
};
pub mod index {
use crate::index::DATA;
pub const DEVICE_STATE: usize = DATA;
pub const DEVICE_STATUS: usize = DATA + 1;
pub const EXCEPTION_STATUS: usize = DATA + 2;
pub const MISC_DEVICE_STATE: usize = DATA + 3;
pub const MODEL_NUMBER: usize = DATA + 4;
pub const CODE_REVISION: usize = DATA + 5;
}
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct OmnibusReply {
buf: [u8; OMNIBUS_REPLY],
}
impl OmnibusReply {
pub fn new() -> Self {
let mut message = Self {
buf: [0u8; OMNIBUS_REPLY],
};
message.init();
message.set_message_type(MessageType::OmnibusReply);
message
}
}
impl_from_for_omnibus_reply!(AdvancedBookmarkModeReply);
impl_from_for_omnibus_reply!(ClearAuditDataRequestAck);
impl_from_for_omnibus_reply!(ClearAuditDataRequestResults);
impl_from_for_omnibus_reply!(ExtendedNoteReply);
impl_from_for_omnibus_reply!(ExtendedNoteInhibitsReplyAlt);
impl_from_for_omnibus_reply!(NoteRetrievedReply);
impl_from_for_omnibus_reply!(NoteRetrievedEvent);
impl_from_for_omnibus_reply!(QueryValueTableReply);
impl_from_for_omnibus_reply!(SetEscrowTimeoutReply);
impl_from_for_omnibus_reply!(QueryBootPartNumberReply);
impl_from_for_omnibus_reply!(QueryApplicationPartNumberReply);
impl_from_for_omnibus_reply!(QueryVariantNameReply);
impl_from_for_omnibus_reply!(QueryVariantPartNumberReply);
impl_from_for_omnibus_reply!(QueryDeviceCapabilitiesReply);
impl_from_for_omnibus_reply!(QueryApplicationIdReply);
impl_from_for_omnibus_reply!(QueryVariantIdReply);
impl fmt::Display for OmnibusReply {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"AckNak: {}, DeviceType: {}, MessageType: {}, DeviceState: {}, DeviceStatus: {}, ExceptionStatus: {}, MiscDeviceState: {}, ModelNumber: {}, CodeRevision: {}",
self.acknak(),
self.device_type(),
self.message_type(),
self.device_state(),
self.device_status(),
self.exception_status(),
self.misc_device_state(),
self.model_number(),
self.code_revision(),
)
}
}
pub trait OmnibusReplyOps: MessageOps {
fn device_state(&self) -> DeviceState {
self.buf()[index::DEVICE_STATE].into()
}
fn set_device_state(&mut self, device_state: DeviceState) {
self.buf_mut()[index::DEVICE_STATE] = device_state.into();
}
fn idling(&self) -> Idling {
self.device_state().idling().into()
}
fn set_idling(&mut self, idling: Idling) {
let mut state = self.device_state();
state.set_idling(idling.into());
self.set_device_state(state);
}
fn accepting(&self) -> Accepting {
self.device_state().accepting().into()
}
fn set_accepting(&mut self, accepting: Accepting) {
let mut state = self.device_state();
state.set_accepting(accepting.into());
self.set_device_state(state);
}
fn escrowed_state(&self) -> EscrowedState {
self.device_state().escrowed_state().into()
}
fn set_escrowed_state(&mut self, escrowed_state: EscrowedState) {
let mut state = self.device_state();
state.set_escrowed_state(escrowed_state.into());
self.set_device_state(state);
}
fn stacking(&self) -> Stacking {
self.device_state().stacking().into()
}
fn set_stacking(&mut self, stacking: Stacking) {
let mut state = self.device_state();
state.set_stacking(stacking.into());
self.set_device_state(state);
}
fn stacked_event(&self) -> StackedEvent {
self.device_state().stacked_event().into()
}
fn set_stacked_event(&mut self, stacked_event: StackedEvent) {
let mut state = self.device_state();
state.set_stacked_event(stacked_event.into());
self.set_device_state(state);
}
fn returning(&self) -> Returning {
self.device_state().returning().into()
}
fn set_returning(&mut self, returning: Returning) {
let mut state = self.device_state();
state.set_returning(returning.into());
self.set_device_state(state);
}
fn returned_event(&self) -> ReturnedEvent {
self.device_state().returned_event().into()
}
fn set_returned_event(&mut self, returned_event: ReturnedEvent) {
let mut state = self.device_state();
state.set_returned_event(returned_event.into());
self.set_device_state(state);
}
fn device_status(&self) -> DeviceStatus {
self.buf()[index::DEVICE_STATUS].into()
}
fn set_device_status(&mut self, device_status: DeviceStatus) {
self.buf_mut()[index::DEVICE_STATUS] = device_status.into();
}
fn cheated(&self) -> Cheated {
self.device_status().cheated().into()
}
fn set_cheated(&mut self, cheated: Cheated) {
let mut status = self.device_status();
status.set_cheated(cheated.into());
self.set_device_status(status);
}
fn rejected(&self) -> Rejected {
self.device_status().rejected().into()
}
fn set_rejected(&mut self, rejected: Rejected) {
let mut status = self.device_status();
status.set_rejected(rejected.into());
self.set_device_status(status);
}
fn jammed(&self) -> Jammed {
self.device_status().jammed().into()
}
fn set_jammed(&mut self, jammed: Jammed) {
let mut status = self.device_status();
status.set_jammed(jammed.into());
self.set_device_status(status);
}
fn stacker_full(&self) -> StackerFull {
self.device_status().stacker_full().into()
}
fn set_stacker_full(&mut self, stacker_full: StackerFull) {
let mut status = self.device_status();
status.set_stacker_full(stacker_full.into());
self.set_device_status(status);
}
fn cassette_attached(&self) -> CassetteAttached {
self.device_status().cassette_attached().into()
}
fn set_cassette_attached(&mut self, cassette_attached: CassetteAttached) {
let mut status = self.device_status();
status.set_cassette_attached(cassette_attached.into());
self.set_device_status(status);
}
fn cash_box_status(&self) -> CashBoxStatus {
let status = self.device_status();
if status.stacker_full() {
CashBoxStatus::Full
} else if status.cassette_attached() {
CashBoxStatus::Attached
} else {
CashBoxStatus::Removed
}
}
fn paused(&self) -> Paused {
self.device_status().paused().into()
}
fn set_paused(&mut self, paused: Paused) {
let mut status = self.device_status();
status.set_paused(paused.into());
self.set_device_status(status);
}
fn calibration(&self) -> Calibration {
self.device_status().calibration().into()
}
fn set_calibration(&mut self, calibration: Calibration) {
let mut status = self.device_status();
status.set_calibration(calibration.into());
self.set_device_status(status);
}
fn exception_status(&self) -> ExceptionStatus {
self.buf()[index::EXCEPTION_STATUS].into()
}
fn set_exception_status(&mut self, exception_status: ExceptionStatus) {
self.buf_mut()[index::EXCEPTION_STATUS] = exception_status.into();
}
fn power_up(&self) -> PowerUpStatus {
self.exception_status().power_up().into()
}
fn set_power_up(&mut self, power_up: PowerUpStatus) {
let mut ex = self.exception_status();
ex.set_power_up(power_up.into());
self.set_exception_status(ex);
}
fn invalid_command(&self) -> InvalidCommand {
self.exception_status().invalid_command().into()
}
fn set_invalid_command(&mut self, invalid_command: InvalidCommand) {
let mut ex = self.exception_status();
ex.set_invalid_command(invalid_command.into());
self.set_exception_status(ex);
}
fn failure(&self) -> Failure {
self.exception_status().failure().into()
}
fn set_failure(&mut self, failure: Failure) {
let mut ex = self.exception_status();
ex.set_failure(failure.into());
self.set_exception_status(ex);
}
fn note_value(&self) -> StandardDenomination {
self.exception_status().note_value().into()
}
fn set_note_value(&mut self, note_value: StandardDenomination) {
let mut ex = self.exception_status();
ex.set_note_value(note_value.into());
self.set_exception_status(ex);
}
fn transport_open(&self) -> TransportOpen {
self.exception_status().transport_open().into()
}
fn set_transport_open(&mut self, transport_open: TransportOpen) {
let mut ex = self.exception_status();
ex.set_transport_open(transport_open.into());
self.set_exception_status(ex);
}
fn misc_device_state(&self) -> MiscDeviceState {
self.buf()[index::MISC_DEVICE_STATE].into()
}
fn set_misc_device_state(&mut self, misc_device_state: MiscDeviceState) {
self.buf_mut()[index::MISC_DEVICE_STATE] = misc_device_state.into();
}
fn stalled(&self) -> Stalled {
self.misc_device_state().stalled().into()
}
fn set_stalled(&mut self, stalled: Stalled) {
let mut misc = self.misc_device_state();
misc.set_stalled(stalled.into());
self.set_misc_device_state(misc);
}
fn flash_download(&self) -> FlashDownload {
self.misc_device_state().flash_download().into()
}
fn set_flash_download(&mut self, flash_download: FlashDownload) {
let mut misc = self.misc_device_state();
misc.set_flash_download(flash_download.into());
self.set_misc_device_state(misc);
}
fn pre_stack(&self) -> PreStack {
self.misc_device_state().pre_stack().into()
}
fn set_pre_stack(&mut self, pre_stack: PreStack) {
let mut misc = self.misc_device_state();
misc.set_pre_stack(pre_stack.into());
self.set_misc_device_state(misc);
}
fn raw_barcode(&self) -> RawBarcode {
self.misc_device_state().raw_barcode().into()
}
fn set_raw_barcode(&mut self, raw_barcode: RawBarcode) {
let mut misc = self.misc_device_state();
misc.set_raw_barcode(raw_barcode.into());
self.set_misc_device_state(misc);
}
fn device_capabilities(&self) -> DeviceCapabilities {
self.misc_device_state().device_capabilities().into()
}
fn set_device_capabilities(&mut self, device_capabilities: DeviceCapabilities) {
let mut misc = self.misc_device_state();
misc.set_device_capabilities(device_capabilities.into());
self.set_misc_device_state(misc);
}
fn disabled(&self) -> Disabled {
self.misc_device_state().disabled().into()
}
fn set_disabled(&mut self, disabled: Disabled) {
let mut misc = self.misc_device_state();
misc.set_disabled(disabled.into());
self.set_misc_device_state(misc);
}
fn model_number(&self) -> ModelNumber {
self.buf()[index::MODEL_NUMBER].into()
}
fn set_model_number(&mut self, model_number: ModelNumber) {
self.buf_mut()[index::MODEL_NUMBER] = model_number.into();
}
fn code_revision(&self) -> CodeRevision {
self.buf()[index::CODE_REVISION].into()
}
fn set_code_revision(&mut self, code_revision: CodeRevision) {
self.buf_mut()[index::CODE_REVISION] = code_revision.into()
}
}
impl_message_ops!(OmnibusReply);
impl_omnibus_reply_ops!(OmnibusReply);
impl From<&OmnibusReply> for Banknote {
fn from(reply: &OmnibusReply) -> Self {
use crate::bau_currency;
let note_value = bau_currency().denomination_value_base(reply.note_value());
Self::default().with_value(note_value.into())
}
}
impl From<&dyn OmnibusReplyOps> for DocumentStatus {
fn from(reply: &dyn OmnibusReplyOps) -> Self {
Self::default().with_standard_denomination(reply.note_value())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Result;
#[test]
#[rustfmt::skip]
fn test_omnibus_reply_from_buf() -> Result<()> {
let msg_bytes = [
0x02, 0x0b, 0x20,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x2b,
];
let mut msg = OmnibusReply::new();
msg.from_buf(msg_bytes.as_ref())?;
assert_eq!(msg.message_type(), MessageType::OmnibusReply);
assert_eq!(msg.device_state(), DeviceState::from(0));
assert_eq!(msg.device_status(), DeviceStatus::from(0));
assert_eq!(msg.exception_status(), ExceptionStatus::from(0));
assert_eq!(msg.misc_device_state(), MiscDeviceState::from(0));
assert_eq!(msg.model_number(), ModelNumber::from(0));
assert_eq!(msg.code_revision(), CodeRevision::from(0));
Ok(())
}
}