///|
/// ISO 8583 version digit.
pub(all) enum MtiVersion {
Iso1987
Iso1993
Iso2003
NationalVersion
PrivateVersion
ReservedVersion(Int)
} derive(Eq, Debug)
///|
/// Message class digit.
pub(all) enum MessageClass {
Authorization
Financial
FileAction
Reversal
Reconciliation
Administrative
FeeCollection
NetworkManagement
ReservedClass(Int)
} derive(Eq, Debug)
///|
/// Message function digit.
pub(all) enum MessageFunction {
Request
RequestResponse
Advice
AdviceResponse
Notification
NotificationAcknowledgement
Instruction
InstructionAcknowledgement
ReservedFunction(Int)
} derive(Eq, Debug)
///|
/// Message origin digit.
pub(all) enum MessageOrigin {
Acquirer
AcquirerRepeat
Issuer
IssuerRepeat
OtherOrigin(Int)
} derive(Eq, Debug)
///|
/// Parsed four-digit message type indicator.
pub(all) struct Mti {
text : String
version : MtiVersion
message_class : MessageClass
function : MessageFunction
origin : MessageOrigin
} derive(Eq, Debug)
///|
/// Parse an MTI into named components.
pub fn parse_mti(text : String) -> Result[Mti, IsoError] {
if !valid_mti_text(text) {
return Err(InvalidMti(text))
}
let version_digit = text[0].to_int() - 48
let class_digit = text[1].to_int() - 48
let function_digit = text[2].to_int() - 48
let origin_digit = text[3].to_int() - 48
let version = match version_digit {
0 => Iso1987
1 => Iso1993
2 => Iso2003
8 => NationalVersion
9 => PrivateVersion
other => ReservedVersion(other)
}
let message_class = match class_digit {
1 => Authorization
2 => Financial
3 => FileAction
4 => Reversal
5 => Reconciliation
6 => Administrative
7 => FeeCollection
8 => NetworkManagement
other => ReservedClass(other)
}
let function = match function_digit {
0 => Request
1 => RequestResponse
2 => Advice
3 => AdviceResponse
4 => Notification
5 => NotificationAcknowledgement
6 => Instruction
7 => InstructionAcknowledgement
other => ReservedFunction(other)
}
let origin = match origin_digit {
0 => Acquirer
1 => AcquirerRepeat
2 => Issuer
3 => IssuerRepeat
other => OtherOrigin(other)
}
Ok({ text, version, message_class, function, origin, })
}
///|
/// Human-readable version label.
pub fn MtiVersion::label(self : MtiVersion) -> String {
match self {
Iso1987 => "ISO 8583:1987"
Iso1993 => "ISO 8583:1993"
Iso2003 => "ISO 8583:2003"
NationalVersion => "national"
PrivateVersion => "private"
ReservedVersion(value) => "reserved version \{value}"
}
}
///|
/// Human-readable message class label.
pub fn MessageClass::label(self : MessageClass) -> String {
match self {
Authorization => "authorization"
Financial => "financial"
FileAction => "file action"
Reversal => "reversal"
Reconciliation => "reconciliation"
Administrative => "administrative"
FeeCollection => "fee collection"
NetworkManagement => "network management"
ReservedClass(value) => "reserved class \{value}"
}
}
///|
/// Human-readable function label.
pub fn MessageFunction::label(self : MessageFunction) -> String {
match self {
Request => "request"
RequestResponse => "request response"
Advice => "advice"
AdviceResponse => "advice response"
Notification => "notification"
NotificationAcknowledgement => "notification acknowledgement"
Instruction => "instruction"
InstructionAcknowledgement => "instruction acknowledgement"
ReservedFunction(value) => "reserved function \{value}"
}
}
///|
/// Human-readable origin label.
pub fn MessageOrigin::label(self : MessageOrigin) -> String {
match self {
Acquirer => "acquirer"
AcquirerRepeat => "acquirer repeat"
Issuer => "issuer"
IssuerRepeat => "issuer repeat"
OtherOrigin(value) => "other origin \{value}"
}
}
///|
/// True when this MTI is a request-like message.
pub fn Mti::is_request(self : Mti) -> Bool {
self.function == Request ||
self.function == Advice ||
self.function == Notification ||
self.function == Instruction
}
///|
/// True when this MTI is a response or acknowledgement.
pub fn Mti::is_response(self : Mti) -> Bool {
self.function == RequestResponse ||
self.function == AdviceResponse ||
self.function == NotificationAcknowledgement ||
self.function == InstructionAcknowledgement
}
///|
/// True for authorization and financial traffic.
pub fn Mti::is_transaction(self : Mti) -> Bool {
self.message_class == Authorization || self.message_class == Financial
}
///|
/// Derive the ordinary response MTI by incrementing the function digit.
pub fn response_mti(text : String) -> Result[String, IsoError] {
let parsed = match parse_mti(text) {
Ok(value) => value
Err(error) => return Err(error)
}
let function_digit = text[2].to_int() - 48
if function_digit % 2 != 0 || function_digit >= 7 {
return Err(InvalidMti(text))
}
let out = StringBuilder()
out.write_string(text[0:2].to_owned())
out.write_char((48 + function_digit + 1).unsafe_to_char())
out.write_string(text[3:4].to_owned())
ignore(parsed)
Ok(out.to_string())
}
///|
/// Convert a request/advice to its acquirer-repeat form.
pub fn repeat_mti(text : String) -> Result[String, IsoError] {
let parsed = match parse_mti(text) {
Ok(value) => value
Err(error) => return Err(error)
}
let origin = match parsed.origin {
Acquirer => 1
Issuer => 3
AcquirerRepeat => 1
IssuerRepeat => 3
OtherOrigin(_) => return Err(InvalidMti(text))
}
let out = StringBuilder()
out.write_string(text[0:3].to_owned())
out.write_char((48 + origin).unsafe_to_char())
Ok(out.to_string())
}
///|
/// Derive a reversal request MTI while retaining version and origin.
pub fn reversal_mti(text : String) -> Result[String, IsoError] {
let parsed = match parse_mti(text) {
Ok(value) => value
Err(error) => return Err(error)
}
if parsed.message_class != Authorization && parsed.message_class != Financial {
return Err(InvalidMti(text))
}
let out = StringBuilder()
out.write_string(text[0:1].to_owned())
out.write_char('4')
out.write_string(text[2:4].to_owned())
Ok(out.to_string())
}
///|
/// Compact description used in diagnostics.
pub fn Mti::describe(self : Mti) -> String {
"\{self.text} \{self.version.label()} \{self.message_class.label()} \{self.function.label()} from \{self.origin.label()}"
}