gpt4 book ai didi

rust - 在Rust中通过枚举类型实现延迟加载

转载 作者:行者123 更新时间:2023-12-03 11:35:58 27 4
gpt4 key购买 nike

在我的用例中,我有大量的Layer类型,其中包括图像数据和有关图像的一些元数据:

extern crate image;

type Img = image::ImageBuffer<image::Rgba<u8>, Vec<u8>>;

#[derive(Debug, Clone)]
struct Layer {
// some metadata fields
lazy_image: Img,
}

到目前为止,一切都很好。但是,我在实际处理图像数据之前执行了一些层选,所以我想以一种懒惰的方式执行图像加载,以避免必须加载我实际上不需要的所有图像。

这是我的第一次尝试:
extern crate image;

type Img = image::ImageBuffer<image::Rgba<u8>, Vec<u8>>;

#[derive(Debug, Clone)]
enum LazyImage {
Path(String),
Image(Img)
}

#[derive(Debug, Clone)]
struct Layer {
// some metadata fields
lazy_image: LazyImage,
}

impl Layer {
fn get_image(&mut self) -> Img {
match self.lazy_image {
LazyImage::Image(img) => img,
LazyImage::Path(path) => {
let img = image::open(path).expect("Could not open image").to_rgba();
self.lazy_image = LazyImage::Image(img);
img
}
}
}
}

您可能会猜到,由于 get_image中我的match语句的所有权问题,这行不通。编译器建议我借用 self.lazy_image,实际上是在做:
impl Layer {
fn get_image(&mut self) -> Img {
match &self.lazy_image {
LazyImage::Image(img) => img,
LazyImage::Path(path) => {
let img = image::open(path).expect("Could not open image").to_rgba();
self.lazy_image = LazyImage::Image(img);
img
}
}
}
}

但是,现在我遇到类型问题:第一个分支(如果图像已经加载)返回引用 &Img而不是实际的 Img。好的,没问题,让我们引用一下。唯一要注意的是,由于我正在对这些图像进行处理,因此它们必须是可变的:
impl Layer {
fn get_image(&mut self) -> &mut Img {
match &self.lazy_image {
LazyImage::Image(img) => img,
LazyImage::Path(path) => {
let img = image::open(path).expect("Could not open image").to_rgba();
self.lazy_image = LazyImage::Image(img);
&mut img
}
}
}
}

现在它们是相同的类型,但是可变性不同:在第一个分支中(如果图像已经加载),我得到了一个不可变的引用。我已经尝试了一些尝试,但未能成功完成我想要的操作。

如您所知,我对Rust还是有些陌生,而且还有些挣扎。此外,我实际上不确定要实现自己的目标要做什么。

任何帮助,无论是告诉我如何使编译器满意,还是只是告诉我我对这一切都是错的,将不胜感激。

最佳答案

我建议直接在get()类型上实现LazyImage方法,因为感觉加载图像是该类型的内部问题。

由于您很可能不想将图像移出数据结构,因此应返回&mut Img。该引用又需要指向Image枚举变量中存储的值。枚举变体字段只能通过解构来提取,因此我们需要在加载图像后再次进行解构。

一种可能的解决方案是使用两个if let语句进行解构:

impl LazyImage {
fn get(&mut self) -> &mut Img {
if let LazyImage::Path(path) = self {
let img = image::open(path).expect("Could not open image").to_rgba();
*self = LazyImage::Image(img);
}
if let LazyImage::Image(img) = self {
img
} else {
unreachable!()
}
}
}

在第一个 if let之后,保证枚举为 Image。第二种解构也可以使用 match表达式完成。编译器将坚持我们包括 else的情况,因为编译器无法轻易地看到另一个分支是不可访问的。

请注意,我们利用 match ergonomics避免了代码中的某些干扰。

关于rust - 在Rust中通过枚举类型实现延迟加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59683330/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com