Skip to content

Data structures

The runtime shape of a bxp-cli run, read out of the types themselves — field names, field types and public methods are what the compiler sees, so this diagram cannot fall behind the code.

classDiagram
    class Config {
        +brokers: StringArrayHashMap~BrokerConfig~
        +deinit()
    }

    class BrokerConfig {
        +description: string
        +data_dir: string
        +maps: MapRegistry
        +input_schema: StringArrayHashMap~string~
        +file_pattern_in: string
        +file_pattern_out: string
        +xlsx_sheet: ?XlsxSheet
        +zip_input: ?ZipInput
        +date_filter_from_filename: bool
        +combined_output: bool
        +pre_passes: StringArrayHashMap~PrePass~
        +row_rules: ?[]RowRule
        +row_rules_debug_missing: bool
        +output_schema: ArrayList~OutputColumn~
        +csv_header_line: u32
        +csv_delimiter_in: u8
        +csv_delimiter_out: u8
        +csv_decimal_separator_in: u8
        +csv_decimal_separator_out: u8
        +csv_text_quote_in: u8
        +csv_text_quote_out: u8
        +csv_input_encoding: Encoding
        +csv_output_encoding: Encoding
        +file_type_in: FileType
        +file_type_out: FileType
        +validate()
        +validateCollect()
        +validateExprsCollect()
    }

    class PrePass {
        +when: string
        +key: string
        +values: StringHashMap~string~
    }

    class RowRule {
        +when: string
        +rows: []StringHashMap~string~
    }

    class OutputColumn {
        +header: string
        +variable: string
    }

    class XlsxSheet {
        +name: string
        +header_row: u32
        +output_suffix: string
    }

    class ZipInput {
        +entry_pattern: string
        +dir_mode: ZipDirMode
        +path_separator: string
    }

    class SheetSpec {
        +name: string
        +header_row: u32
        +output_suffix: string
    }

    class Value {
        +string: string
        +decimal: Decimal
        +boolean: bool
        +toString()
        +toNumber()
        +toBool()
    }

    class Context {
        +fields: []string
        +col_index: StringHashMap~usize~
        +maps: ?MapRegistry
        +map_names: ?StringHashMap~void~
        +lookup_table: ?StringHashMap~string~
        +single_prepass_name: ?string
        +pre_pass_names: ?StringHashMap~void~
        +alloc: Allocator
        +io: Io
        +decimal_sep_in: u8
        +quote_out: u8
        +input_encoding: Encoding
        +error_detail: ?string
        +error_offset: ?u32
        +error_len: ?u32
        +trace_writer: ?Io.Writer
        +filename: string
        +sheet_name: string
        +record_num: u64
    }

    class Diagnostics {
        +items: ArrayList~Diagnostic~
        +alloc: Allocator
        +init()
        +deinit()
        +append()
        +count()
        +countBySeverity()
    }

    class Diagnostic {
        +path: string
        +line: ?u32
        +col: ?u32
        +end_line: ?u32
        +end_col: ?u32
        +expr_off: ?u32
        +expr_len: ?u32
        +severity: Severity
        +code: string
        +message: string
        +suggest: ?string
    }

    class SectionStats {
        +warnings: u32
        +has_fatal: bool
        +time_ns: u64
        +files: u32
        +rows_in: u64
        +rows_out: u64
        +merge()
    }

    Config "1" *-- "many" BrokerConfig
    BrokerConfig "1" *-- "0..*" PrePass
    BrokerConfig "1" *-- "0..*" RowRule
    BrokerConfig "1" *-- "many" OutputColumn
    BrokerConfig "1" *-- "0..1" XlsxSheet
    BrokerConfig "1" *-- "0..1" ZipInput
    XlsxSheet ..> SheetSpec : runtime form for xlsx.zig
    Context --> Value : eval returns
    Diagnostics "1" *-- "many" Diagnostic

Type aliases

Names the code uses for a bare std container. They carry no fields of their own, so they are spelled out here rather than drawn as classes.

Alias Expands to
MapRegistry StringHashMap~StringArrayHashMap~string~~

Config — The whole loaded bxp-cli.json: a template registry plus the arena every string in it points into. deinit() frees the lot; nothing below it owns its own memory.

BrokerConfig — One template. Everything the engine needs to turn one family of input files into one family of output files — where to read, how to parse, what to compute, where to write. The field-by-field reference with defaults and validation rules is the generated config schema.

SheetSpec — The runtime form of XlsxSheet: the same three values, handed to the converter once the config layer is out of the picture.

Value — The result of evaluating one expression — a tagged union, not a string. decimal is the fixed-point i128 core, so 75,00 and 75.00 compare equal without a float ever appearing.

Context — Everything one expression can see while it is being evaluated: the current row, the column index, the resolved named maps, the active pre_pass lookup, and the out-parameters an error or a trace writes back through. Built once per row, not per expression.

Diagnostics — The structured finding collector behind config validation. bxp-cli passes a null sink and pays nothing; bxp-mcp and the GUI bridge collect into it and turn each entry into an $err_<N> / $warn_<N> / $info_<N> sibling.

SectionStatsbxp-cli's per-section accumulator — one per template plus a top-level total. warnings ticks the exit code from 0 to 2 even when the run completes; has_fatal pushes it to 1. The row and file counters exist for the --debug=json run summary and are ignored by the human one.

MapRegistry — Each template's resolved named-map view: the top-level maps registry merged with the template's own block, template-local winning on a name collision, built once at config-load time. Its values are expr.NamedMaps, which preserve JSON key order — which is why REPLACE applies a map's pairs in declaration order, while REMAP uses the same map for an O(1) whole-value lookup.