我正在编写一个解析多个文件的程序。 这些文件可以分为许多不同的类别,我事先不知道是哪一个。 我为文件可以包含的每种类型的数据创建一个类型是有意义的,但是我正在努力将这种数据类型从我的解析器中获取到我的模型/主程序中。

在大多数其他编程语言中,我可能会定义一个函数/方法,它接受一个文件名作为输入,并返回一个通用类型作为输出。 根据我的需要,然后我将转换或测试我的通用返回类型的类型,并获得我重新调整的数据的真实类型。

然而,这在 Rust 中似乎并不奏效。 我可以定义一个函数,它返回一个像这样的特征:

fn parse_file(file: &'str) -> impl ParsedData

其中ParsedData是我所有数据类型的共同特征。 但是我该怎么做呢? 在某些时候,我需要分离隐藏在 ParsedData Trait 后面的不同类型的数据。

解决方案 1:我发现 Any trait 确实可以将 Trait 向下转换为类型。 但普遍的共识似乎是你应该避免这种情况。 我不确定我完全理解为什么人们不喜欢它,但如果没有别的,它似乎需要很多工作/样板代码才能工作。

解决方案 2:也有可能将所有已知数据类型填充到一个大容器类型中,如下所示:

pub struct DataContainer {
    pub data_type_1: Option<DataType1>,
    pub data_type_2: Option<DataType2>,
    pub data_type_3: Option<DataType3>,
    pub data_type_4: Option<DataType4>,
}

fn parse_file(file: &'str) -> DataContainer 

并且只是传递它,直到您需要其中的数据类型。

解决方案 n:似乎有一些不太流行的解决方案


在事先不知道类型的情况下读取一些数据一定是一项非常常见的任务。 难道就没有实际的处理方法吗? 我多次读到 Rust 中向下转换支持不佳的主要原因是因为有其他更好的方法来处理人们遇到向下转换数据需求的几乎/每一种类型的问题。

所以这是我的问题。 如何处理这个问题的一个简单的习惯的方法?

问题定义:

  • 假设您要读取多个文件。 有些将包含用户资料,有些将包含图片(与用户无关),有些将包含烹饪食谱。
  • 在阅读文件之前,您不知道文件包含什么,但它很容易解析并且没有不确定性。
  • 我在上面定义了一个函数parse_file ,但这只是我认为这将是读取这些文件的一个很好的界面,因为它们可能共享许多用于打开文件等的代码。

#1楼 票数:3

你想要的是一个enum

如果您有类型DataType1DataType2DataType3DataType4 ,您可以定义一个枚举,保证只包含其中一种数据类型。

enum DataContainer {
    Type1(DataType1),
    Type2(DataType2),
    Type3(DataType3),
    Type4(DataType4),
}

然后您可以使用match处理每个变体:

let data: DataContainer = parse(something);
match data {
    Type1(x) => do_something_with_type_1(x),
    Type2(x) => do_something_with_type_2(x),
    Type3(x) => do_something_with_type_3(x),
    Type4(x) => do_something_with_type_4(x),
}

#2楼 票数:1

我认为您将特征数据类型泛型混淆了。

trait 告诉 Rust 编译器特定类型具有的功能,并且可以与其他类型共享

所以基本上fn parse_file(file: &'str) -> impl ParsedData返回一个支持特征ParsedData的类型,它被定义为:

trait ParsedData{
   fn some_funtion(&self) -> some_return_type;
}

现在您可以对所有类型的data_types执行类似操作:

impl ParsedData for data_type_x{
    fn some_funtion(&self) -> some_return_type{
        // code
    }
}

现在您现在可以直接在返回的类型上使用some_funtion ,其中返回的类型为data_type (例如: let k = parse_file(&"some_str").some_function(); )。

但是如果它的返回类型是有条件的:

fn parse_file(file: &'str) -> impl ParsedData{
   x
}

然后将其更改为:

fn parse_file(file: &'str) -> Box<ParsedData>{
   Box::new(x)
}

  ask by Peter Ludvigsen translate from so

未解决问题?本站智能推荐:

1回复

如何在Rust中构建灵活的多类型数据系统而不克隆字符串?

我想构建一个系统,在该系统中,不同类型的数据( i32 , String ,...)在修改数据的函数之间流动。 例如,我想要一个add函数来获取“一些”数据并将其添加。 add函数获得类型为Value东西,如果Value是i32 ,它将两个i32值相加,如果它是String ,则返回一个将
1回复

如何让Rust函数接受任何浮动类型作为参数

我正在寻找一个可以接受任何浮点数据的函数,类似于以下形式:fn multiply<F: Float>(floating_point_number: F) -> F { floating_point_number * 2} 但是我在文档中找不到它的语法,或者只有浮点数才有的特征
1回复

Rust:从函数返回一个通用结构,其中(仅)是不同的

我正在寻求有关正确语法或 Rust 方法的帮助。 我的用例:我有一个通用的 struct FileData ,它有一个名为provider的变量。 提供者必须实现AsRef<[u8]>以便数据可能来自静态字节、堆分配的内存、内存映射,以及其他可能的。 我有几种方法来创建FileData
1回复

Rust中的“子类化”特征

我遇到的情况是,我的几个结构应实现多个特征,但所有结构都至少实现一个共同的特征。 当我掌握了这些结构的混合包时,我想将它们全部视为具有共同特征:将它们作为键入该特征的方法参数传递,将它们存储在为此特征键入的集合中,等等。 我还无法弄清楚该怎么做。 这是一些代码,我尝试按照此处建议的方式进
2回复

如何从Rust中的File或stdin执行多态IO?

我正在尝试实现一个“多态” Input枚举,它隐藏我们是从文件还是从标准输入读取。 更具体地说,我试图建立一个枚举,将有一个lines方法将反过来“委托”调用到任何一个File包裹成BufReader或到StdInLock (两者有lines()方法)。 这是枚举: 我有三种方法:
2回复

Rust在专用版本中调用函数的默认实现

我在 Rust 中有一个特性,它为其函数提供了一些默认实现。trait MyTrait { fn do_something(&self); fn say_hello(&self) { println!("Hello I am default"); }}
2回复

如何在Rust中创建对通用特征对象的引用的Vec?[复制]

这个问题在这里已经有了答案: 属于某个特征的对象向量(2 个回答) 如何在 Rust 中使用不同数量的参数动态构建函数调用? (1 个回答)
1回复

如何在Rust中实现通用链表映射函数?

我正在用Rust切割牙齿,我正在尝试实现一般类型的链表。 到目前为止,我的cons和len函数都有效,但map出了点问题,我无法弄清楚。 错误 error[E0308]: mismatched types --> src/main.rs:32:27 |32 | prin