【发布时间】:2020-10-16 00:58:37
【问题描述】:
我对 Rust 还很陌生,正在尝试实现某种数据库。用户应该通过给出表名、列名向量和列类型向量(通过枚举实现)来创建表。填写表格应通过指定 csv 文件来完成。但是,这需要在编译时指定表行的结构,如基本示例所示:
#[derive(Debug, Deserialize, Eq, PartialEq)]
struct Row {
key: u32,
name: String,
comment: String
}
use std::error::Error;
use csv::ReaderBuilder;
use serde::Deserialize;
use std::fs;
fn read_from_file(path: &str) -> Result<(), Box<dyn Error>> {
let data = fs::read_to_string(path).expect("Unable to read file");
let mut rdr = ReaderBuilder::new()
.has_headers(false)
.delimiter(b'|')
.from_reader(data.as_bytes());
let mut iter = rdr.deserialize();
if let Some(result) = iter.next() {
let record:Row = result?;
println!("{:?}", record);
Ok(())
} else {
Err(From::from("expected at least one record but got none"))
}
}
是否有可能使用通用表信息而不是“行”结构来转换反序列化的结果?是否可以根据列类型的组合大小简单地分配内存并解析其中的记录?我会在 C 中做这样的事情......
【问题讨论】:
-
serde_json 有一个通用的
Value类型,它提供运行时动态构建和 JSON 映射。 stackoverflow.com/questions/59047280/… 有更多解释。这可能是第一个研究方向。 -
您的
result具有StringRecord类型,或多或少可以作为字符串数组处理。 -
@Jmb 没错,我可以将每一行存储为字符串向量,并在每次访问时转换为实际类型。但是,这似乎不是很有效。
-
所以你的问题不是关于 CSV 读取,而是更多关于“当类型仅在运行时知道时,如何存储不同类型的值?”然后,您想使用
enum和每种可能类型的变体。 -
由于您是从 CSV 文件中读取数据,因此您的所有值都是
String类型。插入时可能会发生特定类型的转换。您可以利用From特征来实现这一点。例如,如果您的表 A 需要为u32类型的值,那么您可以执行impl From<String> for u32(这可能已经实现......不确定)。在插入期间,您可以执行let value_to_be_inserted_in_table_A: u32 = string_value.into();您可以在此处阅读更多关于From和Into特征sjoshid.blog/2020/06/07/from-and-to-traits-in-rust
标签: rust deserialization