#fixed-length #fields #record #enums #begin #fixedlength #record-like

fixedlength-format-parser

构建具有固定长度、类似记录字段的文件解析器

2个版本

0.1.1 2023年12月1日
0.1.0 2023年12月1日

#1417 in 过程宏


用于 nr-cif

MIT 许可证

13KB
175

固定长度格式解析器

快速编写固定长度格式平面文件的解析器。

目标

此项目提供了一组宏,可以快速构建具有标识符开头且格式为固定长度的记录格式的解析器。

示例

考虑以下文件

AA20231201
PNDarth     Vader               123 Death Star Way            AB12 3CD
ZZ001

模式

这可以看作是以下指定格式的文件

记录类型

  • 标题 ("AA")
  • 个人 ("PN")
  • 尾随 ("ZZ")

注意:记录类型可以由任意数量的字符表示,但必须始终位于记录的开始处,并且必须始终具有相同的长度。

标题:

字段 长度 描述
类型 "AA" 2 标题类型
日期 YYYYMMDD 8 文件的生成日期。

个人:

字段 长度 描述
类型 "PN" 2 个人类型
名字 字符串 10 个人的名字
姓氏 字符串 20 个人的姓氏
地址行 字符串 30 地址行
邮政编码 字符串 8 英国格式的邮政编码

尾随:

字段 长度 描述
类型 "ZZ" 2 尾随类型
记录数量 数量 3 文件中的记录数量。

示例解析器

use fixedlength_format_parser::FixedLengthFormatParser;

#[derive(FixedLengthFormatParser)]
pub enum PersonRecord {
    #[record_type = "AA"]
    Header {
        #[field_starts = 2]
        #[field_length = 8]
        // You could also specify the end instead of the length. End is exclusive.
        // #[field_ends = 10]
        date: String,
    },

    #[record_type = "PN"]
    Person {
        #[field_starts = 2]
        #[field_length = 10]
        forename: String,

        // `field_starts` is optional. If unspecified, it starts at 0 then increments by the length for each field.
        #[field_length = 20]
        surname: String,

        #[field_length = 30]
        address_line: String,

        #[field_length = 8]
        postcode: String,
    },

    #[record_type = "ZZ"]
    Trailer {
        // Any type is allowed, as long as it implements [`std::str::FromStr`].
        #[field_starts = 2]
        #[field_length = 3]
        num_records: usize,
    },
}

// You can now invoke the parser for each record:
fn parse_record(record: &str) -> PersonRecord {
    record.parse::<PersonRecord>().expect("the record should be valid")
}

依赖项

~295–750KB
~18K SLoC