diff --git a/zvt/src/commands.rs b/zvt/src/commands.rs new file mode 100644 index 0000000..fd04ed3 --- /dev/null +++ b/zvt/src/commands.rs @@ -0,0 +1,119 @@ +use crate::packets; +use crate::ZvtEnum; + + +/// Enum that wraps all ZVT command structs from packets.rs +#[derive(Debug, PartialEq, ZvtEnum)] +pub enum Command { + /// PT to ECR - Chapter 3.4 + /// class = 0x04, instr = 0x01 + SetTimeAndDate(packets::SetTimeAndDate), + /// PT to ECR - Chapter 2.2.6 + /// class = 0x04, instr = 0x0f + StatusInformation(packets::StatusInformation), + /// PT to ECR - Chapter 3.7 + /// class = 0x04, instr = 0xff + IntermediateStatusInformation(packets::IntermediateStatusInformation), + /// ECR to PT - Chapter 2.58 + /// class = 0x05, instr = 0x01 + StatusEnquiry(packets::StatusEnquiry), + /// ECR to PT - Chapter 2.1 + /// class = 0x06, instr = 0x00 + Registration(packets::Registration), + /// ECR to PT - Chapter 2.2 + /// class = 0x06, instr = 0x01 + Authorization(packets::Authorization), + /// PT to ECR - Chapter 2.1 + /// class = 0x06, instr = 0x0f + CompletionData(packets::CompletionData), + /// PT to ECR + /// class = 0x06, instr = 0x0f + ReceiptPrintoutCompletion(packets::ReceiptPrintoutCompletion), + /// ECR to PT - Chapter 2.46 + /// class = 0x06, instr = 0x18 + ResetTerminal(packets::ResetTerminal), + /// ECR to PT - Chapter 2.47 + /// class = 0x06, instr = 0x1a + PrintSystemConfiguration(packets::PrintSystemConfiguration), + /// ECR to PT - Chapter 2.48 + /// class = 0x06, instr = 0x1b + SetTerminalId(packets::SetTerminalId), + /// PT to ECR - Chapter 2.2.9 + /// class = 0x06, instr = 0x1e + Abort(packets::Abort), + /// PT to ECR - Chapter 2.2.9 + /// class = 0x06, instr = 0x1e + ReservationAbort(packets::ReservationAbort), + /// PT to ECR - Chapter 2.10.1 + /// class = 0x06, instr = 0x1e + PartialReversalAbort(packets::PartialReversalAbort), + /// ECR to PT - Chapter 2.8 + /// class = 0x06, instr = 0x22 + Reservation(packets::Reservation), + /// ECR to PT - Chapter 2.10 + /// class = 0x06, instr = 0x23 + PartialReversal(packets::PartialReversal), + /// ECR to PT + /// class = 0x06, instr = 0x25 + PreAuthReversal(packets::PreAuthReversal), + /// ECR to PT - Chapter 2.16 + /// class = 0x06, instr = 0x50 + EndOfDay(packets::EndOfDay), + /// ECR to PT - Chapter 2.18 + /// class = 0x06, instr = 0x70 + Diagnosis(packets::Diagnosis), + /// ECR to PT - Chapter 2.19 + /// class = 0x06, instr = 0x93 + Initialization(packets::Initialization), + /// ECR to PT - Chapter 2.22 + /// class = 0x06, instr = 0xc0 + ReadCard(packets::ReadCard), + /// PT to ECR - Chapter 3.5 + /// class = 0x06, instr = 0xd1 + PrintLine(packets::PrintLine), + /// PT to ECR + /// class = 0x06, instr = 0xd3 + PrintTextBlock(packets::PrintTextBlock), + /// ECR to PT - Chapter 2.38 + /// class = 0x08, instr = 0x30 + SelectLanguage(packets::SelectLanguage), + + /// class = 0x80, instr = 0x00 + Ack(packets::Ack), + /// class = 0x84, instr = * + #[zvt_instr_any] + Nack(packets::Nack), +} + +impl std::fmt::Display for Command { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Command::SetTimeAndDate(_) => write!(f, "SetTimeAndDate (04 01)"), + Command::StatusInformation(_) => write!(f, "StatusInformation (04 0F)"), + Command::IntermediateStatusInformation(_) => write!(f, "IntermediateStatusInformation (04 FF)"), + Command::StatusEnquiry(_) => write!(f, "StatusEnquiry (05 01)"), + Command::Registration(_) => write!(f, "Registration (06 00)"), + Command::Authorization(_) => write!(f, "Authorization (06 01)"), + Command::CompletionData(_) => write!(f, "CompletionData (06 0F)"), + Command::ReceiptPrintoutCompletion(_) => write!(f, "ReceiptPrintoutCompletion (06 0F)"), + Command::ResetTerminal(_) => write!(f, "ResetTerminal (06 18)"), + Command::PrintSystemConfiguration(_) => write!(f, "PrintSystemConfiguration (06 1A)"), + Command::SetTerminalId(_) => write!(f, "SetTerminalId (06 1B)"), + Command::Abort(_) => write!(f, "Abort (06 1E)"), + Command::ReservationAbort(_) => write!(f, "ReservationAbort (06 1E)"), + Command::PartialReversalAbort(_) => write!(f, "PartialReversalAbort (06 1E)"), + Command::Reservation(_) => write!(f, "Reservation (06 22)"), + Command::PartialReversal(_) => write!(f, "PartialReversal (06 23)"), + Command::PreAuthReversal(_) => write!(f, "PreAuthReversal (06 25)"), + Command::EndOfDay(_) => write!(f, "EndOfDay (06 50)"), + Command::Diagnosis(_) => write!(f, "Diagnosis (06 70)"), + Command::Initialization(_) => write!(f, "Initialization (06 93)"), + Command::ReadCard(_) => write!(f, "ReadCard (06 C0)"), + Command::PrintLine(_) => write!(f, "PrintLine (06 D1)"), + Command::PrintTextBlock(_) => write!(f, "PrintTextBlock (06 D3)"), + Command::SelectLanguage(_) => write!(f, "SelectLanguage (08 30)"), + Command::Ack(_) => write!(f, "Ack (80 00)"), + Command::Nack(_) => write!(f, "Nack (84 XX)"), + } + } +} diff --git a/zvt/src/lib.rs b/zvt/src/lib.rs index 7b50638..e8b3017 100644 --- a/zvt/src/lib.rs +++ b/zvt/src/lib.rs @@ -2,6 +2,7 @@ pub mod constants; pub mod feig; pub mod io; pub mod packets; +pub mod commands; pub mod sequences; // Reexport everything so we can just use this crate for importing the internals. diff --git a/zvt_derive/src/lib.rs b/zvt_derive/src/lib.rs index eb3c2d7..872b744 100644 --- a/zvt_derive/src/lib.rs +++ b/zvt_derive/src/lib.rs @@ -433,7 +433,7 @@ pub fn parser(input: proc_macro::TokenStream) -> proc_macro::TokenStream { derive(&ast) } -#[proc_macro_derive(ZvtEnum)] +#[proc_macro_derive(ZvtEnum, attributes(zvt_instr_any))] pub fn zvt_enum(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let ast: syn::DeriveInput = syn::parse(input).unwrap(); let Data::Enum(ref s) = ast.data else { @@ -449,11 +449,22 @@ pub fn zvt_enum(input: proc_macro::TokenStream) -> proc_macro::TokenStream { } let name = &variant.ident; let ty = &field.unnamed[0].ty; - variants.push(quote!{ - (<#ty as zvt_builder::ZvtCommand>::CLASS, <#ty as zvt_builder::ZvtCommand>::INSTR) => { - return Ok(Self::#name(<#ty as zvt_builder::ZvtSerializer>::zvt_deserialize(&bytes)?.0)); - } - }); + let has_zvt_instr_any = variant.attrs.iter().any(|attr| attr.path().is_ident("zvt_instr_any")); + if has_zvt_instr_any { + // For variants with #[zvt_instr_any], match any INSTR with the fixed CLASS + variants.push(quote!{ + (<#ty as zvt_builder::ZvtCommand>::CLASS, _) => { + return Ok(Self::#name(<#ty as zvt_builder::ZvtSerializer>::zvt_deserialize(&bytes)?.0)); + } + }); + } else { + // For regular variants, match both CLASS and INSTR exactly + variants.push(quote!{ + (<#ty as zvt_builder::ZvtCommand>::CLASS, <#ty as zvt_builder::ZvtCommand>::INSTR) => { + return Ok(Self::#name(<#ty as zvt_builder::ZvtSerializer>::zvt_deserialize(&bytes)?.0)); + } + }); + } } let name = ast.ident; quote! {