#DBF codec

    Independent dBASE III (version 0x03, no memo) codec. Public Table, Row, Field and Value types are directly constructible. read and write default to strict UTF-8; pass encoding=Latin1 explicitly for ISO-8859-1. No encoding is guessed from the language-driver byte. Field names are unique, case-sensitive printable ASCII, 1–10 bytes. Character fields support widths 1–255 bytes.

    Numeric/Float values use exact fixed decimal strings, including sign and trailing fractional zeroes. No floating-point conversion, exponent notation, implicit rounding, precision reduction, or width truncation occurs. Fractional digits must fit the field decimals. Dates use real Gregorian YYYYMMDD dates, years 0001–9999. Logical T/Y/F/N is accepted case-insensitively; space and ? mean Missing.

    Character reads remove trailing space/NUL padding; blank character data becomes Text(""). Writing Missing to a character column therefore reads back as Text(""). Blank numeric/date data means Missing; date 00000000 also reads as Missing. These are format-level normalizations, not byte-for-byte preservation. Physical row order and deleted flags are always retained. Reserved header bytes and field addresses are not preserved. The optional EOF marker is accepted; other trailing bytes, truncated records and unsupported field types are rejected.

    open_reader validates the structure, then row_at decodes an individual physical record lazily. rows_range reads a checked interval. Malformed values in other records are detected only when those records are decoded. read validates all records by materializing them. fields() returns a schema copy.

    Limits caps input/output bytes, records, fields and materialized cells. Defaults: 256 MiB, one million records, 2046 fields, ten million cells. Callers can supply larger explicit limits; signed integer overflow guards still apply. The cell cap applies to full read, so row_at can process large tables without materializing all values. write has deterministic update date 2000-01-01; pass update_date to write an explicit Gregorian date in the dBASE header range 1900–2155.

    validate_table uses UTF-8 byte widths; validate_table_encoded checks the chosen encoding. field_index and project use exact case-sensitive names; projection preserves row order and deletion flags, and rejects missing/duplicate columns. DbfError::Invalid(Int,String) reports byte offsets for input failures; table validation and out-of-range APIs use logical row/index positions where no input byte exists.

    DbfError

    pub suberror DbfError {
    Invalid(Int, String)
    } derive(
    Debug
    )

    Encoding

    pub(all) enum Encoding {
    Utf8
    Latin1
    } derive(Eq,
    Debug
    )

    Field

    pub(all) struct Field {
    name : String
    kind : FieldType
    width : Int
    decimals : Int
    } derive(Eq,
    Debug
    )

    FieldType

    pub(all) enum FieldType {
    Character
    Numeric
    Float
    Date
    Logical
    } derive(Eq,
    Debug
    )

    Limits

    pub(all) struct Limits {
    max_bytes : Int
    max_records : Int
    max_fields : Int
    max_cells : Int
    } derive(Eq,
    Debug
    )

    Reader

    pub struct Reader {
    data : Bytes
    schema : Array[Field]
    count : Int
    header : Int
    width : Int
    encoding : Encoding
    }

    Reader::fields

    fn Reader::fields(self : Reader) -> Array[Field]

    Reader::record_count

    fn Reader::record_count(self : Reader) -> Int

    Reader::row_at

    fn Reader::row_at(self : Reader, index : Int) -> Row raise DbfError

    Reader::rows_range

    fn Reader::rows_range(self : Reader, start : Int, count : Int) -> Array[Row] raise DbfError

    Returns a bounded range of physical rows, including deleted records.

    Row

    pub(all) struct Row {
    deleted : Bool
    values : Array[Value]
    } derive(Eq,
    Debug
    )

    Table

    pub(all) struct Table {
    fields : Array[Field]
    rows : Array[Row]
    } derive(Eq,
    Debug
    )

    UpdateDate

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

    Value

    pub(all) enum Value {
    Text(String)
    Number(String)
    DateValue(String)
    LogicalValue(Bool)
    Missing
    } derive(Eq,
    Debug
    )

    default_limits

    fn default_limits() -> Limits

    field_index

    fn field_index(table : Table, name : String) -> Int?

    Exact, case-sensitive field lookup. Missing fields are explicit.

    open_reader

    fn open_reader(data : Bytes, encoding? : Encoding, limits? : Limits) -> Reader raise DbfError

    project

    fn project(table : Table, names : Array[String]) -> Table raise DbfError

    Reorders or selects columns while retaining every physical row and deletion flag.

    read

    fn read(data : Bytes, encoding? : Encoding, limits? : Limits) -> Table raise DbfError

    validate_table

    fn validate_table(table : Table) -> Unit raise DbfError

    validate_table_encoded

    fn validate_table_encoded(table : Table, encoding : Encoding) -> Unit raise DbfError

    Checks values using the intended output encoding, including encoded byte widths.

    write

    fn write(table : Table, encoding? : Encoding, update_date? : UpdateDate, limits? : Limits) -> Bytes raise DbfError