#csv #csv-tsv #codegen #type #data-type #cargo-subcommand #parse-input

app cargo-generate-type

Cargo 子命令,用于从输入数据生成和为输入数据生成 Rust 代码

5 个版本

0.1.4 2024 年 4 月 9 日
0.1.3 2023 年 12 月 27 日
0.1.2 2023 年 2 月 22 日
0.1.1 2023 年 1 月 12 日
0.1.0 2023 年 1 月 8 日

#46Cargo 插件

Download history 1/week @ 2024-05-16

229 每月下载量

MIT/Apache

57KB
991

cargo-generate-type

此二进制文件作为 cargo自定义命令 使用,分析带标题的定界符(CSV、TSV)文件,并生成适当的 Rust 代码以干净地解析数据。生成的代码包装了 csv crate 以执行 CSV 解析。您可以通过运行以下命令来安装此实用程序:

cargo install cargo-generate-type

此工具的输出旨在在处理定界符数据时使您的生活更加轻松——只需将其指向文件(或计划在生产中处理的代表文件)并将生成的代码集成到您的项目中即可。

cargo-generate-type 读取指定的文件;确定每列的适当类型,对于整数,将类型限制为适应范围的所需最小大小;并生成使读取这些数据更加方便的代码

$ head -5 iris.csv
sepal length in cm,sepal width in cm,petal length in cm,petal width in cm,class
5.1,3.5,1.4,0.2,Iris-setosa
4.9,3.0,1.4,0.2,Iris-setosa
4.7,3.2,1.3,0.2,Iris-setosa
4.6,3.1,1.5,0.2,Iris-setosa

$ cargo generate-type iris.csv
Generated "iris.rs"

这会生成一个 Iris 结构体

#[derive(Clone, Debug)]
pub struct Iris {
    pub sepal_length_in_cm: f64,
    pub sepal_width_in_cm: f64,
    pub petal_length_in_cm: f64,
    pub petal_width_in_cm: f64,
    pub class: String,
}

它还生成了一个 impl Iris,该结构体知道如何加载数据、解析数据并处理输入中的错误。

用法

您必须传入定界文件的路径。默认情况下,此文件的名称将成为生成的结构体名称(尽管进行了一些规范化)和输出源文件。例如,"iris.csv" 将生成一个包含在 iris.rs 中的 Iris 结构体。"shareholder_report.csv" 将生成 ShareholderReport。您可以使用 --typename name 参数来指定结构体名称,并使用 --output-file outfile 指定要创建的文件。如果文件已存在,除非您使用 --force 标志,否则不会覆盖。

存在标题行可以让此工具生成适当的列名。如果您的数据缺少标题行,您可以通过传递 --no-header 来实现。这将计算输入文件第一行的列数,并以 column_{索引} 的格式插入列名。然后,您可以从您的 IDE 中选择重命名这些列。

模式检测

运行此工具时,它将处理(部分)您的输入文件,以尝试理解模式,包括所有列的列名和数据类型。

默认情况下,它将处理输入的前 100 行以猜测类型。您可以通过指定非负整数值 n--rows n 来覆盖此操作。如果您使用 --rows 0,它将使用整个输入文件。

列的类型推断大致遵循以下过程:

  • 如果一个列始终为空,它将被视为单元类型(())。
  • 如果一个列曾经有空白值,它将被视为 Option<T> 类型,其中 T 是决定的数据类型。
  • 如果值始终为 "true" 或 "false",则该列将被视为 bool
  • 如果值始终为整数类型,将跟踪看到的值范围,并根据最小值和最大值,该列将属于以下之一:i8i16i32i64u8u16u32u64
  • 如果值始终为数值,则该列将被视为 f64
  • 否则,使用 String

目前,字符串值将被分配,而不是使用指向底层 csv::StringRecord&'a str 引用。这可能会很快被 Cow<'_, str> 替换以减少分配。

错误处理

生成的代码可以以三种不同的方式处理意外的输入,这些方式由 --error handling-type 参数指定

  1. --error ignore 将静默忽略输入中的任何错误,跳过缺失列或具有意外类型的行。
  2. --error panic 将对任何具有无效输入的行引发恐慌。
  3. --error result 将返回一个 Result<T, E>,其中 T 是表示您数据的类型,而 E 则涵盖了底层的 csv 错误 以及意外的输入类型。这是未指定时的默认行为。

字符串处理

默认情况下,文本列将被处理为拥有 String。对于大量输入或基数较低的列,所发生的内存分配可能过多。0.1.3 版本提供了 --strings 参数,可能的值为 owned(默认值)、staticenum

使用 --strings static,将看到的唯一字符串集合进行配置文件分析,生成的代码将为您提供 &'static str 而不是 String,从而减少内存分配(并允许生成的结构体 #[derive(Copy)])。

使用 --strings enum 也做同样的事情,除了定义一个辅助枚举,使用 impl std::str::FromStr 将输入文本解析为该枚举。此枚举以及该类型的结构体也是 Copy

还有一个 --max-strings n 参数(其中 n 的默认值为 20);如果看到的唯一值超过 n,则代码生成失败,以避免为高基数数据生成过多的代码。

使用说明

因为这个二进制文件是作为 Cargo 自定义命令的,所以它被调用为 cargo generate-type。请注意,这是带有 generate-type 子命令的 cargo 程序。Cargo 将此子命令作为参数传递给二进制文件,并将其忽略。因为期望此参数,如果您尝试运行 cargo-generate-type,则必须向其传递一个虚拟参数。

./cargo-generate-type generate-type shareholder_report.csv --error result
#                     ^^^^^^^^^^^^^ or any bogus argument is fine

附加文档

您可以在输入 ".csv" 文件旁边创建一个 ".def" 文件,该文件将生成类型的字段的文档。例如,对于从 "iris.csv" 生成的上述 Iris 数据类型,您可以创建一个类似下面的 "iris.def" 文件

This represents [Fisher's Iris data set](https://en.wikipedia.org/wiki/Iris_flower_data_set)

[sepal length in cm]
The length of the flower's sepal, in centimeters.

[sepal width in cm]
The width of the flower's sepal, in centimeters.

[petal length in cm]
The length of the flower's petal, in centimeters.

[petal width in cm]
The width of the flower's petal, in centimeters.

[class]
The species of flower, one of: Iris-setosa, Iris-virginica, Iris-versicolor.

在生成代码时,将生成以下具有文档的类型

#[derive(Clone, Debug)]
/// This represents [Fisher's Iris data set](https://en.wikipedia.org/wiki/Iris_flower_data_set)
pub struct Iris {
    /// The length of the flower's sepal, in centimeters.
    pub sepal_length_in_cm: f64,
    /// The width of the flower's sepal, in centimeters.
    pub sepal_width_in_cm: f64,
    /// The length of the flower's petal, in centimeters.
    pub petal_length_in_cm: f64,
    /// The width of the flower's petal, in centimeters.
    pub petal_width_in_cm: f64,
    /// The species of flower, one of: Iris-setosa, Iris-virginica, Iris-versicolor.
    pub class: String,
}

输入修剪

某些输入文件可能具有空格填充的内容,尽管它们是分隔的。例如

sepal length in cm,sepal width in cm,petal length in cm,petal width in cm,class
5.1               ,3.5              ,1.4               ,0.2              ,Iris-setosa
4.9               ,3.0              ,1.4               ,0.2              ,Iris-setosa
4.7               ,3.2              ,1.3               ,0.2              ,Iris-setosa
4.6               ,3.1              ,1.5               ,0.2              ,Iris-setosa
5.0               ,3.6              ,1.4               ,0.2              ,Iris-setosa

在这种情况下,由于值不会解析为浮点数,它们将被错误地视为字符串。如果您传递 --trim-input 开关,则将在尝试解析之前修剪值。此开关默认情况下未启用。

依赖关系

~2.4–3.5MB
~51K SLoC