mooniso8583

    ISO 8583-1987 message packing, decoding and validation for MoonBit

    iso8583
    payment
    pos
    bitmap
    bcd
    Download zip
    Version
    0.1.0
    License
    Apache-2.0
    Last updated
    1 hour ago
    Downloads
    2

    #MoonISO8583

    MoonISO8583 是一个使用 MoonBit 编写的 ISO 8583-1987 报文编解码与业务校验库,面向收单联调、POS/ATM 终端模拟、支付网关适配和交易回放。项目重点处理真正容易出错的部分:位图、固定字段与 LLVAR/LLLVAR、ASCII/BCD 差异、请求响应关联、冲正 DE90、EMV DE55 BER-TLV,以及日志中的卡号和密钥数据保护。

    ISO 8583 在不同机构之间通常会形成各自的字段配置。MoonISO8583 提供一套可运行的 1987 基准规格,同时把字段定义、报文模板和传输格式分开,接入方可以替换字段规格,不需要重写位图和编解码器。

    #主要能力

    • MTI 解析,支持请求、响应、重发和冲正 MTI 派生。
    • 64 位主位图与 128 位主/次位图,支持二进制和 ASCII Hex 表示。
    • 固定长度、LLVAR、LLLVAR 字段,支持 ASCII 长度头、BCD 长度头、ASCII/BCD/Binary 内容。
    • ISO 8583-1987 的 DE2–DE128 基准字段规格,可自行创建 FieldSpecPackager
    • ASCII MTI + Binary Bitmap、ASCII MTI + ASCII Hex Bitmap、BCD MTI + Binary Bitmap 三种线格式。
    • Processing Code、金额、ISO 4217 常用币种、PAN/Luhn、Track 2、DE54、DE55、DE90 等领域模型。
    • 0100/01100200/02100400/04100420/04300800/0810 报文模板。
    • 请求/响应关联检查,STAN、金额、终端号、币种、RRN、DE90 等关键字段不一致时给出稳定错误。
    • 2 字节大端长度头和 4 位 ASCII 长度头,增量处理半包、粘包和连续多包。
    • 安全诊断:PAN 保留前六后四,Track 1/2、PIN Data、MAC、密钥数据不输出原文,DE55 只显示长度和 Tag。
    • 可预测的 IsoError 错误码与 ValidationIssue 校验结果,便于网关映射日志和监控指标。

    #处理流程

    IsoMessage │ 字段规格校验 / 业务模板校验 / 领域一致性校验 ▼ MTI + Bitmap + Data Elements │ WireProfile: ASCII / BCD / Binary ▼ ISO 8583 payload │ FrameHeader: uint16-be 或 ASCII4 ▼ TCP frame

    解码按相反方向进行。传输层只负责长度帧,不绑定 Socket、异步运行时或服务端框架。

    #快速开始

    #1. 构造并编码金融请求

    let packager = @iso.iso1987_packager()
    let request = @iso.message("0200").unwrap()
    request.set_field(2, "6222021234567890").unwrap()
    request.set_field(3, "000000").unwrap()
    request.set_field(4, "000000001500").unwrap()
    request.set_field(7, "0916123456").unwrap()
    request.set_field(11, "123456").unwrap()
    request.set_field(22, "051").unwrap()
    request.set_field(41, "TERM0001").unwrap()
    request.set_field(49, "156").unwrap()

    let issues = @iso.validate_message_template(
    request,
    @iso.financial_request_template(),
    )
    assert_eq(issues.length(), 0)

    let payload = @iso.pack_message(
    packager,
    @iso.ascii_binary_profile(),
    request,
    ).unwrap()

    调用方包的 moon.pkg

    import { "Han-Wentao/mooniso8583" @iso, }

    #2. 解码并生成响应

    let received = @iso.unpack_message(
    packager,
    @iso.ascii_binary_profile(),
    payload,
    ).unwrap()

    let response = @iso.response_skeleton(received, "00").unwrap()
    response.set_field(38, "A12345").unwrap()
    assert_true(@iso.response_correlates(received, response))

    response_skeleton 只复制关联所需字段,不会把 DE52 PIN Data 带入响应。

    #3. 增量处理 TCP 数据

    let decoder = @iso.stream_decoder(
    @iso.BinaryBigEndian16,
    8192,
    ).unwrap()

    let frames = decoder.feed(socket_chunk).unwrap()
    for frame in frames {
    let message = @iso.unpack_message(
    packager,
    @iso.ascii_binary_profile(),
    frame,
    ).unwrap()
    // 处理一条完整报文
    }

    连接关闭时调用 decoder.finish(),可以区分正常结束和残留半包。

    #三个可运行场景

    #授权请求与响应

    终端构造 0100,先检查必填字段,再完成位图和字段编码;模拟发卡方解码后生成 0110,校验 MTI、STAN、金额、终端号和币种是否与请求对应。输出使用安全诊断,不泄露完整 PAN 或 DE55 值。

    moon run examples/authorization

    #消费冲正

    网关保留原始 0200,超时后用新的 STAN 和传输时间生成 0400。库自动从原交易构造 42 位 DE90,并检查 Processing Code、金额、终端、币种和原交易标识。DE52 不会复制到冲正报文。

    moon run examples/reversal

    #网络管理 Sign-on

    接入程序生成 0800 + DE70=001,添加 2 字节大端长度头,模拟半包/粘包环境下的收包;对端返回 0810 + DE39=00,请求与响应按 STAN 和 DE70 关联。

    moon run examples/network_management

    #字段规格和线格式

    iso1987_packager() 使用 ASCII 内容和常见 ISO 8583-1987 长度。iso1987_bcd_packager() 将适合的数字字段改为 BCD 表示。实际机构规范有差异,尤其是 DE48、DE60–DE63、DE100 以后字段;接入时应按接口文档建立独立 Packager,不要直接假设基准规格等于某家网络规范。

    内置线格式:

    APIMTIBitmap典型用途
    ascii_binary_profile()4 字节 ASCII8/16 字节二进制常见 TCP 私有网络
    ascii_hex_profile()4 字节 ASCII16/32 字节 ASCII Hex文本网关、联调日志
    bcd_binary_profile()2 字节 BCD8/16 字节二进制带宽敏感或历史终端协议

    #业务模板与领域校验

    报文模板只规定通用的必填、可选和禁用字段;机构私有要求应在上层追加。模板校验与字段编码校验分开,因此可以明确区分“字段格式错误”和“这类交易不允许出现该字段”。

    常用入口:

    • validate_message_fields:检查长度、字符集、padding 和字段规格。
    • validate_message_template:检查必填、禁用字段和 PAN 来源。
    • validate_common_domains:检查日期、时间、STAN、RRN、响应码、DE2/DE35、DE14/DE35 一致性。
    • validate_response_correlation:关联请求与响应。
    • validate_reversal_correlation:确认 DE90 指向正确原交易。

    #DE55 BER-TLV

    DE55 支持 1–4 字节 BER Tag、短长度和 1–4 字节长定长、constructed TLV、递归查询和重新编码。解析器拒绝 indefinite length、非最短长度、非法高 Tag 编码、截断值和超过 16 层的嵌套。

    let nodes = @iso.parse_de55(
    "9F260811223344556677889F270180",
    ).unwrap()
    let cryptogram = @iso.find_tlv(nodes, "9F26").unwrap()
    assert_eq(cryptogram.value.length(), 8)

    这里处理的是 BER-TLV 结构,不解释 EMV Tag 的业务含义,也不实现 EMV Kernel 或脱机认证。

    #日志安全

    不要直接打印 IsoMessage。使用:

    println(@iso.safe_message_dump(message, packager))

    默认策略:

    字段日志行为
    DE2前六后四,其余替换为 *
    DE35 / DE45隐藏有效期、服务码和全部轨道数据
    DE52完全隐藏 PIN Data
    DE53 / DE96隐藏安全控制和密钥管理数据
    DE55仅显示字节数和 Tag 列表
    DE64 / DE128完全隐藏 MAC

    安全诊断降低误打日志的风险,但不能代替 PCI DSS 流程、密钥隔离、HSM 或访问控制。

    #错误处理

    编解码 API 返回 Result[..., IsoError]IsoError::code() 提供稳定代码,IsoError::message() 提供可读原因。批量校验返回 Array[ValidationIssue],一次可以报告多个缺失或冲突字段。

    例如,截断 LLVAR、位图长度错误、BCD nibble 非法、DE55 非最短长度、DE90 日期错误和超长 TCP frame 都有独立错误类型。

    #与常见实现的定位区别

    项目/类型主要定位MoonISO8583 的取舍
    jPOSJava 支付平台,覆盖 Channel、MUX、交易管理等完整基础设施不做交换平台,只提供 MoonBit 原生编解码、校验和传输帧
    j8583Java ISO 8583 报文库提供 MoonBit 类型和多后端构建,增加严格 BER-TLV、DE90 关联与安全诊断
    pyiso8583Python 配置驱动编解码保留可配置字段模型,同时面向静态编译和 Wasm/JS/Native 目标
    手写字符串拼接快速但难以处理次位图、变长头和截断错误字段规格、位图和错误偏移统一处理,并用 round-trip 测试覆盖

    MoonISO8583 目前不是 jPOS 替代品。它适合嵌入网关、模拟器和测试工具,网络连接池、持久化队列、路由、HSM、密钥生命周期由宿主系统负责。

    #明确不做

    • 不实现 PIN Block 的生成、翻译或校验。
    • 不实现 MAC/签名算法和密钥存储,只把相关字段当作受保护的二进制数据。
    • 不实现 HSM、EMV Kernel、3-D Secure、银行卡清算规则或争议处理。
    • 不提供 TCP 服务端、连接池、超时重试和交易数据库。
    • 不承诺内置 1987 profile 与任何特定银行或卡组织私有规范完全一致。
    • 暂不实现 ISO 8583:1993/2003 的完整字段语义。

    这些边界让库保持可审计。密码学和在线交易状态机应由专门组件承担。

    #测试和验收

    moon fmt moon check --target wasm-gc --deny-warn moon check --target wasm --deny-warn moon check --target js --deny-warn moon test --target wasm-gc moon test --target js moon run examples/authorization moon run examples/reversal moon run examples/network_management python tools/count_effective_moonbit.py --check-core 3000

    GitHub CI 额外运行 Native check/test。当前仓库有 81 个测试,覆盖位图、BCD、字段编解码、报文 round-trip、PAN/Track 2、DE54、DE55、DE90、模板、请求响应关联、流式半包/粘包和安全日志。

    源码统计使用保守口径:排除测试、示例、生成目录、空行、整行注释,并将大型字段规格表 profile_1987.mbt 单独列出。2026 年 9 月 16 日的统计结果:

    分类文件物理行有效行
    核心算法(不含规格表)2052884396
    ISO 8583-1987 字段规格表1302282
    测试181042886
    三个示例3105102

    核心算法单独超过 3000 行,字段规格表没有用于满足该门槛。可随时运行统计脚本复核。

    #工程状态

    • 版本:0.1.0
    • 许可证:Apache-2.0
    • 默认目标:Wasm GC
    • CI:Wasm GC、Wasm、JavaScript、Native
    • 提交历史:按功能切片提交,包含 20 个以上可独立审查的实现、测试、示例和工程提交

    #原创与参考

    项目为原创 MoonBit 实现,没有移植其他 ISO 8583 库的源码。ISO 8583 字段编号和行业术语属于协议知识;实现结构、错误体系、编解码器、业务模板、流式帧、诊断策略和测试均在本项目中编写。对标项目只用于界定功能边界,不构成源码移植。

    #许可证

    Apache License 2.0,见 LICENSE

    AccountType

    pub(all) enum AccountType {
    DefaultAccount
    Savings
    Checking
    Credit
    Universal
    Investment
    ElectronicPurse
    UnknownAccountType(String)
    } derive(Eq,
    Debug
    )

    Common account-type meaning.

    AccountType::label

    fn AccountType::label(self : AccountType) -> String

    Human-readable account-type label.

    AdditionalAmount

    pub(all) struct AdditionalAmount {
    account_type : String
    amount_type : String
    currency : String
    sign : UInt16
    amount : String
    } derive(Eq,
    Debug
    )

    One twenty-character component of DE54 Additional Amounts.

    AdditionalAmount::display

    fn AdditionalAmount::display(self : AdditionalAmount) -> Result[String, IsoError]

    Render the component with currency metadata and decimal scale.

    AdditionalAmount::kind

    Decode the amount type code into a useful label.

    AdditionalAmount::signed_minor_units

    fn AdditionalAmount::signed_minor_units(self : AdditionalAmount) -> Int64

    Signed minor units from the component.

    AdditionalAmount::to_string

    fn AdditionalAmount::to_string(self : AdditionalAmount) -> String

    Render one DE54 component.

    AdditionalAmountType

    pub(all) enum AdditionalAmountType {
    LedgerBalance
    AvailableBalance
    CashAmount
    PurchaseAmount
    CreditLimit
    UnknownAdditionalAmount(String)
    } derive(Eq,
    Debug
    )

    Named meaning for common DE54 amount type codes.

    BerTlv

    pub(all) struct BerTlv {
    tag : String
    value : Bytes
    constructed : Bool
    children : Array[BerTlv]
    } derive(
    Debug
    )

    One BER-TLV node as used by EMV data in ISO 8583 field 55.

    Bitmap

    pub(all) struct Bitmap {
    bytes : Bytes
    } derive(Eq,
    Debug
    )

    ISO 8583 primary or primary+secondary bitmap.

    Bitmap::byte_length

    fn Bitmap::byte_length(self : Bitmap) -> Int

    Number of bytes occupied by this bitmap.

    Bitmap::field_count

    fn Bitmap::field_count(self : Bitmap) -> Int

    Return the number of populated data elements.

    Bitmap::fields

    fn Bitmap::fields(self : Bitmap) -> Array[Int]

    Return populated data-element numbers, excluding bit 1.

    Bitmap::has

    fn Bitmap::has(self : Bitmap, field : Int) -> Bool

    True when the data element is present.

    Bitmap::has_secondary

    fn Bitmap::has_secondary(self : Bitmap) -> Bool

    Whether a secondary bitmap follows the primary bitmap.

    Bitmap::matches_message

    fn Bitmap::matches_message(self : Bitmap, message : IsoMessage) -> Bool

    Compare a bitmap against the fields stored in a message.

    Bitmap::to_ascii_bytes

    fn Bitmap::to_ascii_bytes(self : Bitmap) -> Bytes

    Encode a bitmap as uppercase ASCII hexadecimal bytes.

    Bitmap::to_bytes

    fn Bitmap::to_bytes(self : Bitmap) -> Bytes

    Raw bitmap bytes suitable for binary bitmap profiles.

    Bitmap::to_hex

    fn Bitmap::to_hex(self : Bitmap) -> String

    Uppercase hexadecimal bitmap text.

    BitmapEncoding

    pub(all) enum BitmapEncoding {
    BinaryBitmap
    AsciiHexBitmap
    } derive(Eq,
    Debug
    )

    Bitmap representation selected by a wire profile.

    CardExpiration

    pub(all) struct CardExpiration {
    year : Int
    month : Int
    } derive(Eq,
    Debug
    )

    Parsed DE14 card expiration (YYMM).

    CardExpiration::expired_at

    fn CardExpiration::expired_at(self : CardExpiration, year : Int, month : Int) -> Bool

    True after the supplied two-digit calendar month has passed.

    ContentEncoding

    pub(all) enum ContentEncoding {
    AsciiContent
    BcdContent
    BinaryContent
    } derive(Eq,
    Debug
    )

    How field content is represented on the wire.

    CurrencyCode

    pub(all) struct CurrencyCode {
    numeric : String
    alpha : String?
    minor_units : Int?
    } derive(Eq,
    Debug
    )

    ISO 4217 numeric code represented by DE49/50/51.

    DataKind

    pub(all) enum DataKind {
    Numeric
    Alpha
    Alphanumeric
    AlphanumericSpecial
    Track2Data
    BinaryHex
    AnyText
    } derive(Eq,
    Debug
    )

    Validation class applied before a field is packed.

    DecodeResult

    pub(all) struct DecodeResult {
    message : IsoMessage
    consumed : Int
    bitmap_bytes : Int
    } derive(
    Debug
    )

    Result of decoding with byte-consumption information.

    DecodedField

    pub(all) struct DecodedField {
    value : String
    consumed : Int
    logical_length : Int
    prefix_length : Int
    } derive(Eq,
    Debug
    )

    Decoded data element with byte-consumption accounting.

    EncodedField

    pub(all) struct EncodedField {
    bytes : Bytes
    logical_length : Int
    prefix_length : Int
    content_length : Int
    } derive(Eq,
    Debug
    )

    Encoded data element with length accounting.

    FieldEntry

    pub(all) struct FieldEntry {
    number : Int
    value : String
    } derive(Eq,
    Debug
    )

    A field stored in a message. Values are unencoded canonical text.

    FieldPresence

    pub(all) enum FieldPresence {
    RequiredField
    OptionalField
    ForbiddenField
    } derive(Eq,
    Debug
    )

    Whether a data element is required, optional, or forbidden by a message template.

    FieldSensitivity

    pub(all) enum FieldSensitivity {
    PublicField
    MaskedAccountData
    RedactedTrackData
    RedactedSecret
    SummarizedChipData
    } derive(Eq,
    Debug
    )

    Sensitivity class used by safe message diagnostics.

    FieldSpec

    pub(all) struct FieldSpec {
    number : Int
    name : String
    length_kind : LengthKind
    max_length : Int
    min_length : Int
    length_encoding : LengthEncoding
    content_encoding : ContentEncoding
    data_kind : DataKind
    pad_direction : PadDirection
    pad_char : UInt16
    } derive(Eq,
    Debug
    )

    One data-element definition in a packager profile.

    FrameHeader

    pub(all) enum FrameHeader {
    BinaryBigEndian16
    AsciiDecimal4
    } derive(Eq,
    Debug
    )

    Length-prefix format used by common ISO 8583 TCP integrations.

    IsoError

    pub(all) enum IsoError {
    InvalidMti(String)
    InvalidFieldNumber(Int)
    DuplicateField(Int)
    MissingField(Int)
    UnknownField(Int)
    InvalidLength(Int, Int, Int)
    InvalidCharacter(Int, Int, String)
    InvalidNumeric(Int, String)
    InvalidHex(String)
    InvalidBcd(Int, Int)
    InvalidBitmapLength(Int)
    BitmapFieldOneReserved
    Truncated(String, Int, Int)
    LengthPrefixOverflow(Int, Int)
    FieldTooLong(Int, Int, Int)
    FieldTooShort(Int, Int, Int)
    InvalidSpec(Int, String)
    InvalidTrack2(String)
    InvalidProcessingCode(String)
    InvalidAmount(String)
    InvalidDateTime(String)
    InvalidPan(String)
    InvalidCurrency(String)
    InvalidTlv(String)
    InvalidOriginalData(String)
    InvalidStreamFrame(String)
    TrailingBytes(Int)
    TemplateViolation(String)
    } derive(Eq,
    Debug
    )

    Stable errors returned by codecs, packagers and domain parsers.

    IsoError::code

    fn IsoError::code(self : IsoError) -> String

    IsoError::message

    fn IsoError::message(self : IsoError) -> String

    IsoMessage

    pub(all) struct IsoMessage {
    mti : String
    fields : Array[FieldEntry]
    } derive(
    Debug
    )

    Mutable message model used by pack and validation operations.

    IsoMessage::bitmap

    fn IsoMessage::bitmap(self : IsoMessage) -> Result[Bitmap, IsoError]

    Build the wire bitmap for a message.

    IsoMessage::copy

    fn IsoMessage::copy(self : IsoMessage) -> IsoMessage

    Clone a message so callers can edit independently.

    IsoMessage::field

    fn IsoMessage::field(self : IsoMessage, number : Int) -> String?

    Retrieve a field value.

    IsoMessage::field_count

    fn IsoMessage::field_count(self : IsoMessage) -> Int

    Number of populated data elements.

    IsoMessage::field_numbers

    fn IsoMessage::field_numbers(self : IsoMessage) -> Array[Int]

    Return field numbers in wire order.

    IsoMessage::has_field

    fn IsoMessage::has_field(self : IsoMessage, number : Int) -> Bool

    Test whether a field is present.

    IsoMessage::remove_field

    fn IsoMessage::remove_field(self : IsoMessage, number : Int) -> Bool

    Remove a field and report whether it existed.

    IsoMessage::set_field

    fn IsoMessage::set_field(self : IsoMessage, number : Int, value : String) -> Result[Unit, IsoError]

    Insert or replace a field while keeping entries sorted.

    IsoMessage::set_mti

    fn IsoMessage::set_mti(self : IsoMessage, mti : String) -> Result[Unit, IsoError]

    Change the message MTI after validating it.

    LengthEncoding

    pub(all) enum LengthEncoding {
    AsciiLength
    BcdLength
    } derive(Eq,
    Debug
    )

    How a variable-length prefix is represented.

    LengthKind

    pub(all) enum LengthKind {
    Fixed
    Llvar
    Lllvar
    } derive(Eq,
    Debug
    )

    How a data element obtains its encoded length.

    LocalTransactionDate

    pub(all) struct LocalTransactionDate {
    month : Int
    day : Int
    } derive(Eq,
    Debug
    )

    Parsed DE13 local date (MMDD).

    LocalTransactionTime

    pub(all) struct LocalTransactionTime {
    hour : Int
    minute : Int
    second : Int
    } derive(Eq,
    Debug
    )

    Parsed DE12 local time (hhmmss).

    MessageClass

    pub(all) enum MessageClass {
    Authorization
    Financial
    FileAction
    Reversal
    Reconciliation
    Administrative
    FeeCollection
    NetworkManagement
    ReservedClass(Int)
    } derive(Eq,
    Debug
    )

    Message class digit.

    MessageClass::label

    fn MessageClass::label(self : MessageClass) -> String

    Human-readable message class label.

    MessageFunction

    pub(all) enum MessageFunction {
    Request
    RequestResponse
    Advice
    AdviceResponse
    Notification
    NotificationAcknowledgement
    Instruction
    InstructionAcknowledgement
    ReservedFunction(Int)
    } derive(Eq,
    Debug
    )

    Message function digit.

    MessageFunction::label

    fn MessageFunction::label(self : MessageFunction) -> String

    Human-readable function label.

    MessageOrigin

    pub(all) enum MessageOrigin {
    Acquirer
    AcquirerRepeat
    Issuer
    IssuerRepeat
    OtherOrigin(Int)
    } derive(Eq,
    Debug
    )

    Message origin digit.

    MessageOrigin::label

    fn MessageOrigin::label(self : MessageOrigin) -> String

    Human-readable origin label.

    MessageTemplate

    pub(all) struct MessageTemplate {
    name : String
    mtis : Array[String]
    rules : Array[TemplateFieldRule]
    require_pan_source : Bool
    } derive(
    Debug
    )

    A practical ISO 8583 message template for one or more exact MTIs.

    MessageTemplate::accepts_mti

    fn MessageTemplate::accepts_mti(self : MessageTemplate, mti : String) -> Bool

    True when an exact MTI belongs to this template.

    MessageTemplate::forbidden_fields

    fn MessageTemplate::forbidden_fields(self : MessageTemplate) -> Array[Int]

    Return all explicitly forbidden field numbers.

    MessageTemplate::required_fields

    fn MessageTemplate::required_fields(self : MessageTemplate) -> Array[Int]

    Return all required field numbers for documentation and diagnostics.

    MessageTemplate::rule

    fn MessageTemplate::rule(self : MessageTemplate, field : Int) -> TemplateFieldRule?

    Find a rule for one data element.

    MinorAmount

    pub(all) struct MinorAmount {
    minor_units : Int64
    digits : String
    scale : Int
    } derive(Eq,
    Debug
    )

    Parsed unsigned minor-unit amount.

    MinorAmount::display

    fn MinorAmount::display(self : MinorAmount) -> String

    Format a decimal display without floating-point arithmetic.

    Mti

    pub(all) struct Mti {
    text : String
    version : MtiVersion
    message_class : MessageClass
    function : MessageFunction
    origin : MessageOrigin
    } derive(Eq,
    Debug
    )

    Parsed four-digit message type indicator.

    Mti::describe

    fn Mti::describe(self : Mti) -> String

    Compact description used in diagnostics.

    Mti::is_request

    fn Mti::is_request(self : Mti) -> Bool

    True when this MTI is a request-like message.

    Mti::is_response

    fn Mti::is_response(self : Mti) -> Bool

    True when this MTI is a response or acknowledgement.

    Mti::is_transaction

    fn Mti::is_transaction(self : Mti) -> Bool

    True for authorization and financial traffic.

    MtiEncoding

    pub(all) enum MtiEncoding {
    AsciiMti
    BcdMti
    } derive(Eq,
    Debug
    )

    MTI representation selected by a wire profile.

    MtiVersion

    pub(all) enum MtiVersion {
    Iso1987
    Iso1993
    Iso2003
    NationalVersion
    PrivateVersion
    ReservedVersion(Int)
    } derive(Eq,
    Debug
    )

    ISO 8583 version digit.

    MtiVersion::label

    fn MtiVersion::label(self : MtiVersion) -> String

    Human-readable version label.

    NetworkManagementOperation

    pub(all) enum NetworkManagementOperation {
    SignOn
    SignOff
    EchoTest
    Cutover
    KeyChange
    UnknownNetworkOperation(String)
    } derive(Eq,
    Debug
    )

    Common network management operations carried in DE70.

    OriginalDataElements

    pub(all) struct OriginalDataElements {
    original_mti : String
    original_stan : String
    original_transmission_datetime : String
    acquiring_institution_id : String
    forwarding_institution_id : String
    } derive(Eq,
    Debug
    )

    Structured representation of DE90 Original Data Elements.

    OriginalDataElements::matches

    fn OriginalDataElements::matches(self : OriginalDataElements, message : IsoMessage) -> Bool

    Check that DE90 refers to the supplied original message.

    OriginalDataElements::to_string

    fn OriginalDataElements::to_string(self : OriginalDataElements) -> String

    Render the 42-digit wire representation.

    Packager

    pub(all) struct Packager {
    name : String
    specs : Array[FieldSpec]
    } derive(
    Debug
    )

    Ordered collection of field definitions.

    Packager::contains

    fn Packager::contains(self : Packager, number : Int) -> Bool

    True if the packager defines the field.

    Packager::field_numbers

    fn Packager::field_numbers(self : Packager) -> Array[Int]

    Return all defined field numbers.

    Packager::spec

    fn Packager::spec(self : Packager, number : Int) -> FieldSpec?

    Find a field definition.

    PadDirection

    pub(all) enum PadDirection {
    NoPadding
    PadLeft
    PadRight
    } derive(Eq,
    Debug
    )

    Direction used when a fixed field needs padding.

    PanInfo

    pub(all) struct PanInfo {
    digits : String
    length : Int
    issuer_prefix : String
    masked : String
    } derive(Eq,
    Debug
    )

    PAN validation and Track 2 payment data helpers.

    ProcessingCode

    pub(all) struct ProcessingCode {
    transaction_type : String
    from_account : String
    to_account : String
    } derive(Eq,
    Debug
    )

    Parsed six-digit processing code (DE3).

    ProcessingCode::destination_account

    fn ProcessingCode::destination_account(self : ProcessingCode) -> AccountType

    Map the destination-account component.

    ProcessingCode::source_account

    fn ProcessingCode::source_account(self : ProcessingCode) -> AccountType

    Map the source-account component.

    ProcessingCode::transaction

    fn ProcessingCode::transaction(self : ProcessingCode) -> TransactionType

    Map a DE3 transaction type to a named meaning.

    ProfileVariant

    pub(all) enum ProfileVariant {
    Ascii
    BcdNumeric
    } derive(Eq,
    Debug
    )

    Profile families used by the built-in ISO 8583 definitions.

    ResponseCodeInfo

    pub(all) struct ResponseCodeInfo {
    code : String
    approved : Bool
    category : String
    meaning : String
    } derive(Eq,
    Debug
    )

    Parsed response-code metadata.

    RetrievalReference

    pub(all) struct RetrievalReference {
    text : String
    } derive(Eq,
    Debug
    )

    Parsed retrieval reference number.

    SafeFieldDiagnostic

    pub(all) struct SafeFieldDiagnostic {
    field : Int
    name : String
    logical_length : Int
    sensitivity : FieldSensitivity
    display : String
    } derive(Eq,
    Debug
    )

    One field in a diagnostic view that never contains raw secrets.

    Stan

    pub(all) struct Stan {
    text : String
    number : Int
    } derive(Eq,
    Debug
    )

    Parsed systems trace audit number.

    Stan::next

    fn Stan::next(self : Stan) -> Stan

    Return the next STAN with six-digit wraparound.

    StreamDecoder

    pub(all) struct StreamDecoder {
    header : FrameHeader
    max_frame : Int
    buffer : Array[Byte]
    } derive(
    Debug
    )

    Incremental decoder for length-prefixed byte streams.

    StreamDecoder::buffered_bytes

    fn StreamDecoder::buffered_bytes(self : StreamDecoder) -> Int

    Number of undecoded bytes currently retained.

    StreamDecoder::feed

    fn StreamDecoder::feed(self : StreamDecoder, chunk : Bytes) -> Result[Array[Bytes], IsoError]

    Feed an arbitrary stream chunk and return every complete payload.

    StreamDecoder::finish

    fn StreamDecoder::finish(self : StreamDecoder) -> Result[Unit, IsoError]

    Assert that the stream ended on a complete frame boundary.

    StreamDecoder::reset

    fn StreamDecoder::reset(self : StreamDecoder) -> Unit

    Drop a partial frame after a connection reset.

    TemplateFieldRule

    pub(all) struct TemplateFieldRule {
    field : Int
    presence : FieldPresence
    purpose : String
    } derive(Eq,
    Debug
    )

    One field-level rule attached to a business message template.

    Track2

    pub(all) struct Track2 {
    pan : String
    expiration : String
    service_code : String
    discretionary : String
    separator : UInt16
    } derive(Eq,
    Debug
    )

    Parsed Track 2 data.

    Track2::masked

    fn Track2::masked(self : Track2) -> String

    Render a masked Track 2 value for diagnostics.

    Track2::to_string

    fn Track2::to_string(self : Track2) -> String

    Render Track 2 with a canonical '=' separator.

    Track2::with_separator

    fn Track2::with_separator(self : Track2, separator : UInt16) -> Result[Track2, IsoError]

    Replace the separator and preserve the other Track 2 components.

    TransactionType

    pub(all) enum TransactionType {
    GoodsAndServices
    CashWithdrawal
    DebitAdjustment
    CreditAdjustment
    BalanceInquiry
    AccountTransfer
    Payment
    Deposit
    UnknownTransactionType(String)
    } derive(Eq,
    Debug
    )

    Common transaction-type meaning.

    TransactionType::label

    fn TransactionType::label(self : TransactionType) -> String

    Human-readable transaction-type label.

    TransmissionDateTime

    pub(all) struct TransmissionDateTime {
    month : Int
    day : Int
    hour : Int
    minute : Int
    second : Int
    } derive(Eq,
    Debug
    )

    Parsed DE7 transmission date and time (MMDDhhmmss).

    ValidationIssue

    pub(all) struct ValidationIssue {
    code : String
    field : Int
    message : String
    severity : String
    } derive(Eq,
    Debug
    )

    A validation finding that can be rendered in stable logs.

    WireProfile

    pub(all) struct WireProfile {
    name : String
    mti_encoding : MtiEncoding
    bitmap_encoding : BitmapEncoding
    reject_trailing : Bool
    } derive(Eq,
    Debug
    )

    Complete message wire-format choices.

    WireProfile::allow_trailing

    fn WireProfile::allow_trailing(self : WireProfile) -> WireProfile

    Return a copy that allows bytes after one decoded message.

    account_type

    fn account_type(value : String) -> AccountType

    Decode one two-digit account type.

    additional_amount

    fn additional_amount(account_type_code : String, amount_type_code : String, currency : String, debit : Bool, minor_units : Int64) -> Result[AdditionalAmount, IsoError]

    Build one DE54 component from validated pieces.

    ascii_alnum

    fn ascii_alnum(c : UInt16) -> Bool

    True for an ASCII alphanumeric character.

    ascii_alpha

    fn ascii_alpha(c : UInt16) -> Bool

    True for an ASCII alphabetic character.

    ascii_binary_profile

    fn ascii_binary_profile() -> WireProfile

    Common binary-bitmap ASCII-MTI profile.

    ascii_digit

    fn ascii_digit(c : UInt16) -> Bool

    True for an ASCII decimal character.

    ascii_hex_profile

    fn ascii_hex_profile() -> WireProfile

    Common all-display profile using ASCII hexadecimal bitmap text.

    ascii_to_text

    fn ascii_to_text(field : Int, data : Bytes) -> Result[String, IsoError]

    Convert bytes to an ASCII string, rejecting bytes above 0x7f.

    attach_original_data

    fn attach_original_data(target : IsoMessage, original : IsoMessage) -> Result[Unit, IsoError]

    Attach a rendered DE90 to a reversal or advice message.

    authorization_request_template

    fn authorization_request_template() -> MessageTemplate

    Authorization request template (0100).

    authorization_response_template

    fn authorization_response_template() -> MessageTemplate

    Authorization response template (0110).

    bcd_binary_profile

    fn bcd_binary_profile() -> WireProfile

    Compact profile with a two-byte BCD MTI.

    bcd_pack_digits

    fn bcd_pack_digits(field : Int, digits : String, pad_left : Bool, pad_nibble : Int) -> Result[Bytes, IsoError]

    Pack decimal digits into BCD. Odd values are padded on the requested side.

    bcd_pack_length

    fn bcd_pack_length(value : Int, digits : Int) -> Result[Bytes, IsoError]

    Pack an LLVAR or LLLVAR length into BCD bytes.

    bcd_pack_signed

    fn bcd_pack_signed(field : Int, text : String) -> Result[Bytes, IsoError]

    Pack signed decimal text using a trailing C/D sign nibble.

    bcd_unpack_digits

    fn bcd_unpack_digits(field : Int, data : Bytes, digit_count : Int, pad_left : Bool, pad_nibble : Int) -> Result[String, IsoError]

    Unpack BCD bytes into decimal digits.

    bcd_unpack_length

    fn bcd_unpack_length(data : Bytes, start : Int, digits : Int) -> Result[(Int, Int), IsoError]

    Decode a BCD length prefix and return value plus consumed bytes.

    bcd_unpack_signed

    fn bcd_unpack_signed(field : Int, data : Bytes, digits : Int) -> Result[String, IsoError]

    Decode signed BCD text using a trailing C/D sign nibble.

    binary_hex

    fn binary_hex(number : Int, name : String, maximum_bytes : Int, variable : Bool) -> FieldSpec

    Create a binary field represented as hexadecimal text in the API.

    bitmap_decode_ascii

    fn bitmap_decode_ascii(data : Bytes, start : Int) -> Result[(Bitmap, Int), IsoError]

    Read an ASCII-hex bitmap at an offset and report consumed bytes.

    bitmap_decode_binary

    fn bitmap_decode_binary(data : Bytes, start : Int) -> Result[(Bitmap, Int), IsoError]

    Read a binary bitmap at an offset and report consumed bytes.

    bitmap_empty

    fn bitmap_empty() -> Bitmap

    Create an empty primary bitmap.

    bitmap_from_bytes

    fn bitmap_from_bytes(data : Bytes) -> Result[Bitmap, IsoError]

    Create a bitmap from validated raw bytes.

    bitmap_from_fields

    fn bitmap_from_fields(fields : Array[Int]) -> Result[Bitmap, IsoError]

    Build a bitmap from data-element numbers.

    bitmap_from_hex

    fn bitmap_from_hex(text : String) -> Result[Bitmap, IsoError]

    Parse a hexadecimal primary or extended bitmap.

    bytes_equal

    fn bytes_equal(left : Bytes, right : Bytes) -> Bool

    Constant-time-ish equality for byte strings of equal public length.

    canonical_field_value

    fn canonical_field_value(spec : FieldSpec, value : String) -> Result[String, IsoError]

    Validate and canonicalize a value, applying fixed-field padding.

    concat_bytes

    fn concat_bytes(left : Bytes, right : Bytes) -> Bytes

    Concatenate two byte sequences.

    constructed_tlv

    fn constructed_tlv(tag : String, children : Array[BerTlv]) -> Result[BerTlv, IsoError]

    Construct a BER constructed node and derive its encoded value.

    count_tlv_nodes

    fn count_tlv_nodes(nodes : Array[BerTlv]) -> Int

    Count all primitive and constructed nodes recursively.

    decimal_width

    fn decimal_width(value : Int, width : Int) -> Result[String, IsoError]

    Render a non-negative integer as zero-padded decimal text.

    decode_ber_tlv

    fn decode_ber_tlv(data : Bytes) -> Result[Array[BerTlv], IsoError]

    Decode a complete byte string containing one or more BER-TLV nodes.

    decode_field

    fn decode_field(spec : FieldSpec, data : Bytes, start : Int) -> Result[DecodedField, IsoError]

    Decode one data element from an offset.

    decode_field_hex

    fn decode_field_hex(spec : FieldSpec, wire : String) -> Result[DecodedField, IsoError]

    Decode a field from hexadecimal fixture text.

    decode_selected_fields

    fn decode_selected_fields(packager : Packager, bitmap : Bitmap, data : Bytes, start : Int) -> Result[(Array[FieldEntry], Int), IsoError]

    Decode a sequence of fields selected by a bitmap.

    describe_transaction_amount

    fn describe_transaction_amount(amount : String, currency : String) -> Result[String, IsoError]

    Combine DE4 and DE49 into an inspectable amount description.

    diagnostic_contains_raw_value

    fn diagnostic_contains_raw_value(diagnostic : String, field : Int, raw_value : String) -> Bool

    Defensive check used by tests and host applications before emitting a dump.

    encode_ber_tlv

    fn encode_ber_tlv(nodes : Array[BerTlv]) -> Result[Bytes, IsoError]

    Encode a complete BER-TLV sequence.

    encode_field

    fn encode_field(spec : FieldSpec, value : String) -> Result[EncodedField, IsoError]

    Encode one data element including its optional length prefix.

    encode_field_hex

    fn encode_field_hex(spec : FieldSpec, value : String) -> Result[String, IsoError]

    Encode a field directly to uppercase hexadecimal for fixtures.

    encode_frame

    fn encode_frame(header : FrameHeader, payload : Bytes) -> Result[Bytes, IsoError]

    Prefix one payload with the selected length format.

    encode_selected_fields

    fn encode_selected_fields(packager : Packager, message : IsoMessage) -> Result[Bytes, IsoError]

    Encode message fields in ascending data-element order.

    encoded_content_length

    fn encoded_content_length(spec : FieldSpec, logical_length : Int) -> Int

    Compute bytes occupied by content of the given logical length.

    field_logical_length

    fn field_logical_length(spec : FieldSpec, value : String) -> Int

    Logical field length used by a length prefix.

    field_max_logical_length

    fn field_max_logical_length(spec : FieldSpec) -> Int

    Maximum logical length for the field.

    field_min_logical_length

    fn field_min_logical_length(spec : FieldSpec) -> Int

    Minimum logical length for the field.

    field_sensitivity

    fn field_sensitivity(field : Int) -> FieldSensitivity

    Classify common payment data elements for safe logging.

    fields_are_valid

    fn fields_are_valid(message : IsoMessage, packager : Packager) -> Bool

    True when no error-level field validation findings exist.

    financial_request_template

    fn financial_request_template() -> MessageTemplate

    Financial request template (0200).

    financial_response_template

    fn financial_response_template() -> MessageTemplate

    Financial response template (0210).

    find_additional_amount

    fn find_additional_amount(values : Array[AdditionalAmount], amount_type : String) -> AdditionalAmount?

    Find the first component with the requested amount type.

    find_all_tlv

    fn find_all_tlv(nodes : Array[BerTlv], tag : String) -> Array[BerTlv]

    Return every matching node in depth-first wire order.

    find_tlv

    fn find_tlv(nodes : Array[BerTlv], tag : String) -> BerTlv?

    Return the first node with a canonical hexadecimal tag, depth-first.

    fixed_ascii

    fn fixed_ascii(number : Int, name : String, length : Int, kind : DataKind) -> FieldSpec

    Create a fixed ASCII field definition.

    fixed_bcd_numeric

    fn fixed_bcd_numeric(number : Int, name : String, digits : Int) -> FieldSpec

    Construct a fixed BCD numeric field definition.

    fixed_numeric

    fn fixed_numeric(number : Int, name : String, length : Int) -> FieldSpec

    Create a fixed numeric field left padded with zeroes.

    flatten_primitive_tlv

    fn flatten_primitive_tlv(nodes : Array[BerTlv]) -> Array[(String, String)]

    Return hexadecimal values for all primitive nodes in wire order.

    format_additional_amounts

    fn format_additional_amounts(values : Array[AdditionalAmount]) -> String

    Render multiple DE54 components in wire order.

    format_de55

    fn format_de55(nodes : Array[BerTlv]) -> Result[String, IsoError]

    Encode a TLV tree as uppercase DE55 hexadecimal text.

    format_minor_amount

    fn format_minor_amount(value : Int64, width : Int) -> Result[String, IsoError]

    Format a non-negative minor-unit amount as fixed-width digits.

    frame_header_width

    fn frame_header_width(header : FrameHeader) -> Int

    Header width in bytes.

    hex_decode

    fn hex_decode(text : String) -> Result[Bytes, IsoError]

    Decode even-length hexadecimal text.

    hex_encode

    fn hex_encode(data : Bytes) -> String

    Encode bytes as uppercase hexadecimal.

    iso1987_bcd_packager

    fn iso1987_bcd_packager() -> Result[Packager, IsoError]

    Use BCD length headers and BCD content for numeric fields.

    iso1987_field

    fn iso1987_field(number : Int) -> FieldSpec?

    Return the standard field specification for a common 1987 data element.

    iso1987_packager

    fn iso1987_packager() -> Packager

    Make a built-in ISO 8583-1987 ASCII profile.

    iso1987_specs

    fn iso1987_specs() -> Array[FieldSpec]

    Collect all standard field definitions in ascending order.

    iso1987_variable_field_count

    fn iso1987_variable_field_count() -> Int

    Count how many standard fields are variable length.

    left_pad

    fn left_pad(text : String, width : Int, fill : UInt16) -> String

    Left pad text to a fixed width.

    lllvar_ascii

    fn lllvar_ascii(number : Int, name : String, maximum : Int, kind : DataKind) -> FieldSpec

    Create an ASCII LLLVAR field.

    lllvar_bcd_binary

    fn lllvar_bcd_binary(number : Int, name : String, maximum_bytes : Int) -> FieldSpec

    Construct a binary LLLVAR field with BCD length prefix.

    llvar_ascii

    fn llvar_ascii(number : Int, name : String, maximum : Int, kind : DataKind) -> FieldSpec

    Create an ASCII LLVAR field.

    llvar_bcd_numeric

    fn llvar_bcd_numeric(number : Int, name : String, digits : Int) -> FieldSpec

    Construct a BCD-content LLVAR numeric field.

    mask_pan

    fn mask_pan(value : String) -> String

    Produce a log-safe PAN mask while preserving the first six and last four digits.

    message

    fn message(mti : String) -> Result[IsoMessage, IsoError]

    Create an empty ISO 8583 message.

    message_layout

    fn message_layout(packager : Packager, profile : WireProfile, message : IsoMessage) -> Result[Array[String], IsoError]

    Explain byte-level layout without exposing sensitive values.

    message_matches_template

    fn message_matches_template(message : IsoMessage, template : MessageTemplate) -> Bool

    True when the message satisfies the selected template.

    network_management_request_template

    fn network_management_request_template() -> MessageTemplate

    Network management request template (0800).

    network_management_response_template

    fn network_management_response_template() -> MessageTemplate

    Network management response template (0810).

    original_data

    fn original_data(original_mti : String, original_stan : String, original_transmission_datetime : String, acquiring_institution_id : String, forwarding_institution_id : String) -> Result[OriginalDataElements, IsoError]

    Build DE90 from individual original-message identifiers.

    original_data_from_message

    fn original_data_from_message(message : IsoMessage) -> Result[OriginalDataElements, IsoError]

    Build DE90 from fields available in an original message.

    pack_framed_message

    fn pack_framed_message(packager : Packager, profile : WireProfile, header : FrameHeader, message : IsoMessage) -> Result[Bytes, IsoError]

    Pack an ISO message and add a transport length header.

    pack_message

    fn pack_message(packager : Packager, profile : WireProfile, message : IsoMessage) -> Result[Bytes, IsoError]

    Pack a complete ISO 8583 message.

    pack_message_hex

    fn pack_message_hex(packager : Packager, profile : WireProfile, message : IsoMessage) -> Result[String, IsoError]

    Pack directly to a hexadecimal diagnostic fixture.

    packager

    fn packager(name : String, specs : Array[FieldSpec]) -> Result[Packager, IsoError]

    Create a packager after validating field definitions.

    pan_equal

    fn pan_equal(left : String, right : String) -> Bool

    Compare two PANs without exposing their digits to callers.

    pan_issuer_prefix

    fn pan_issuer_prefix(value : String) -> Result[String, IsoError]

    Extract the issuer identification number prefix from a valid PAN.

    pan_luhn_valid

    fn pan_luhn_valid(value : String) -> Bool

    Check the Luhn checksum of a numeric PAN.

    parse_additional_amount_component

    fn parse_additional_amount_component(value : String) -> Result[AdditionalAmount, IsoError]

    Parse one fixed-width DE54 component.

    parse_additional_amounts

    fn parse_additional_amounts(value : String) -> Result[Array[AdditionalAmount], IsoError]

    Parse concatenated DE54 amount components.

    parse_card_expiration

    fn parse_card_expiration(value : String) -> Result[CardExpiration, IsoError]

    Parse DE14 card expiration date.

    parse_currency

    fn parse_currency(value : String) -> Result[CurrencyCode, IsoError]

    Parse a three-digit currency code with selected common metadata.

    parse_de55

    fn parse_de55(value : String) -> Result[Array[BerTlv], IsoError]

    Parse hexadecimal DE55 text into a BER-TLV tree.

    parse_decimal_bytes

    fn parse_decimal_bytes(data : Bytes, start : Int, width : Int) -> Result[Int, IsoError]

    Parse a decimal ASCII range without allocating an intermediate slice.

    parse_local_transaction_date

    fn parse_local_transaction_date(value : String) -> Result[LocalTransactionDate, IsoError]

    Parse DE13 local transaction date.

    parse_local_transaction_time

    fn parse_local_transaction_time(value : String) -> Result[LocalTransactionTime, IsoError]

    Parse DE12 local transaction time.

    parse_minor_amount

    fn parse_minor_amount(field : Int, value : String, width : Int, scale : Int) -> Result[MinorAmount, IsoError]

    Parse a fixed-width numeric amount in minor currency units.

    parse_mti

    fn parse_mti(text : String) -> Result[Mti, IsoError]

    Parse an MTI into named components.

    parse_network_management_code

    fn parse_network_management_code(value : String) -> Result[NetworkManagementOperation, IsoError]

    Parse common DE70 operation codes.

    parse_original_data

    fn parse_original_data(value : String) -> Result[OriginalDataElements, IsoError]

    Parse the fixed 42-digit DE90 layout.

    parse_pan

    fn parse_pan(value : String) -> Result[PanInfo, IsoError]

    Validate a PAN with length and Luhn constraints.

    parse_processing_code

    fn parse_processing_code(value : String) -> Result[ProcessingCode, IsoError]

    Parse DE3 into three two-digit components.

    parse_response_code

    fn parse_response_code(value : String) -> Result[ResponseCodeInfo, IsoError]

    Interpret widely used ISO 8583 response codes without imposing one network dialect.

    parse_retrieval_reference

    fn parse_retrieval_reference(value : String) -> Result[RetrievalReference, IsoError]

    Parse a 12-character retrieval reference number.

    parse_stan

    fn parse_stan(value : String) -> Result[Stan, IsoError]

    Parse a six-digit STAN while preserving leading zeroes.

    parse_track2

    fn parse_track2(value : String) -> Result[Track2, IsoError]

    Parse PAN, expiry, service code and discretionary data from Track 2.

    parse_transmission_datetime

    fn parse_transmission_datetime(value : String) -> Result[TransmissionDateTime, IsoError]

    Parse DE7 with calendar and clock range checks.

    primitive_tlv

    fn primitive_tlv(tag : String, value : Bytes) -> Result[BerTlv, IsoError]

    Construct a primitive TLV after validating the tag form.

    primitive_tlv_hex

    fn primitive_tlv_hex(tag : String, value : String) -> Result[BerTlv, IsoError]

    Construct a primitive TLV from hexadecimal value text.

    processing_code

    fn processing_code(transaction_type : String, from_account : String, to_account : String) -> Result[String, IsoError]

    Build DE3 from validated two-digit components.

    repeat_mti

    fn repeat_mti(text : String) -> Result[String, IsoError]

    Convert a request/advice to its acquirer-repeat form.

    require_iso1987_field

    fn require_iso1987_field(number : Int) -> Result[FieldSpec, IsoError]

    Return a built-in field spec or a stable unknown-field error.

    response_correlates

    fn response_correlates(request : IsoMessage, response : IsoMessage) -> Bool

    True when request and response pass all correlation checks.

    response_mti

    fn response_mti(text : String) -> Result[String, IsoError]

    Derive the ordinary response MTI by incrementing the function digit.

    response_skeleton

    fn response_skeleton(request : IsoMessage, response_code : String) -> Result[IsoMessage, IsoError]

    Build a minimal response skeleton with correlation fields and response code.

    reversal_mti

    fn reversal_mti(text : String) -> Result[String, IsoError]

    Derive a reversal request MTI while retaining version and origin.

    reversal_request_template

    fn reversal_request_template() -> MessageTemplate

    Reversal request/advice template (0400 or 0420).

    reversal_response_template

    fn reversal_response_template() -> MessageTemplate

    Reversal response template (0410 or 0430).

    reversal_skeleton

    fn reversal_skeleton(original : IsoMessage, reversal_stan : String, reversal_transmission_datetime : String) -> Result[IsoMessage, IsoError]

    Build a reversal request skeleton with a new STAN and transmission time.

    right_pad

    fn right_pad(text : String, width : Int, fill : UInt16) -> String

    Right pad text to a fixed width.

    safe_field_diagnostics

    fn safe_field_diagnostics(message : IsoMessage, packager : Packager) -> Array[SafeFieldDiagnostic]

    Build structured, log-safe diagnostics in field order.

    safe_field_display

    fn safe_field_display(field : Int, value : String) -> String

    Render one field value according to its sensitivity class.

    safe_layout_dump

    fn safe_layout_dump(message : IsoMessage, packager : Packager, profile : WireProfile) -> Result[String, IsoError]

    Explain the wire layout alongside safe field displays.

    safe_message_dump

    fn safe_message_dump(message : IsoMessage, packager : Packager) -> String

    Render a deterministic multi-line message dump suitable for application logs.

    sensitive_fields

    fn sensitive_fields(message : IsoMessage) -> Array[Int]

    Return only field numbers whose values require masking or redaction.

    stream_decoder

    fn stream_decoder(header : FrameHeader, max_frame : Int) -> Result[StreamDecoder, IsoError]

    Create an incremental decoder with an explicit payload limit.

    template_for_mti

    fn template_for_mti(mti : String) -> MessageTemplate?

    Look up the built-in template for a supported exact MTI.

    text_to_ascii

    fn text_to_ascii(field : Int, text : String) -> Result[Bytes, IsoError]

    Convert ASCII text into bytes, rejecting non-ASCII characters.

    track2_from_bcd

    fn track2_from_bcd(data : Bytes) -> Result[Track2, IsoError]

    Decode Track 2 BCD nibbles, accepting either D or '=' in the API.

    track2_to_bcd

    fn track2_to_bcd(value : Track2) -> Result[Bytes, IsoError]

    Pack Track 2 into BCD nibbles using D as separator and F as pad.

    trim_left_char

    fn trim_left_char(text : String, fill : UInt16) -> String

    Remove leading padding down to a minimum of one character.

    trim_right_char

    fn trim_right_char(text : String, fill : UInt16) -> String

    Remove trailing padding.

    unpack_framed_message

    fn unpack_framed_message(packager : Packager, profile : WireProfile, header : FrameHeader, frame : Bytes) -> Result[IsoMessage, IsoError]

    Decode exactly one framed message and reject extra frames or partial data.

    unpack_message

    fn unpack_message(packager : Packager, profile : WireProfile, data : Bytes) -> Result[IsoMessage, IsoError]

    Decode exactly one complete message.

    unpack_message_hex

    fn unpack_message_hex(packager : Packager, profile : WireProfile, fixture : String) -> Result[IsoMessage, IsoError]

    Unpack a hexadecimal diagnostic fixture.

    unpack_message_with_result

    fn unpack_message_with_result(packager : Packager, profile : WireProfile, data : Bytes) -> Result[DecodeResult, IsoError]

    Decode a complete message and retain consumption metadata.

    validate_alpha_text

    fn validate_alpha_text(field : Int, value : String) -> Result[Unit, IsoError]

    Alphabetic-only field validation, including space.

    validate_alphanumeric_text

    fn validate_alphanumeric_text(field : Int, value : String, allow_special : Bool) -> Result[Unit, IsoError]

    Alphanumeric validation with optional ISO 8583 special characters.

    validate_binary_hex_text

    fn validate_binary_hex_text(field : Int, value : String) -> Result[Unit, IsoError]

    Hexadecimal API representation for binary fields.

    validate_common_domains

    fn validate_common_domains(message : IsoMessage) -> Array[ValidationIssue]

    Validate common field domains and cross-field consistency.

    validate_data_kind

    fn validate_data_kind(field : Int, kind : DataKind, value : String) -> Result[Unit, IsoError]

    Validate content according to a data-element character class.

    validate_digits

    fn validate_digits(field : Int, text : String) -> Result[Unit, IsoError]

    Validate a string containing decimal digits only.

    validate_known_message_template

    fn validate_known_message_template(message : IsoMessage) -> Result[Array[ValidationIssue], IsoError]

    Validate a message with its built-in template.

    validate_message_fields

    fn validate_message_fields(message : IsoMessage, packager : Packager) -> Array[ValidationIssue]

    Validate a message against every referenced field specification.

    validate_message_template

    fn validate_message_template(message : IsoMessage, template : MessageTemplate) -> Array[ValidationIssue]

    Validate required, forbidden, and composite business rules.

    validate_numeric_text

    fn validate_numeric_text(field : Int, value : String) -> Result[Unit, IsoError]

    Decimal-only field validation.

    validate_printable_text

    fn validate_printable_text(field : Int, value : String) -> Result[Unit, IsoError]

    Printable seven-bit ASCII validation.

    validate_response_correlation

    fn validate_response_correlation(request : IsoMessage, response : IsoMessage) -> Array[ValidationIssue]

    Validate that a response belongs to a particular request.

    validate_reversal_correlation

    fn validate_reversal_correlation(original : IsoMessage, reversal : IsoMessage) -> Array[ValidationIssue]

    Validate that a reversal points to and preserves key data from its original transaction.

    validate_terminal_id

    fn validate_terminal_id(value : String) -> Result[Unit, IsoError]

    Validate an eight-character terminal identifier.

    validate_track2_text

    fn validate_track2_text(field : Int, value : String) -> Result[Unit, IsoError]

    Track 2 accepts digits, one separator, and common pad markers.

    validate_transmission_datetime

    fn validate_transmission_datetime(value : String) -> Result[Unit, IsoError]

    Validate MMDDhhmmss without assigning a year or timezone.