Rust中缓存资源的惯用方式

4

我刚接触 Rust,并且正在使用 Piston 引擎制作游戏。

我想要用精灵表格渲染一系列实体,但是很多实体可能会共享一个精灵表格,因此我希望只加载和存储每个文件的一个副本。

伪代码中,我的方法基本上是这样的:

fn get_spritesheet(hashmap_cache, file):
    if file not in hashmap_cache:
        hashmap_cache[file] = load_image_file(file)

    return hashmap_cache[file]

也许可以这样表达:

然后可能会有类似这样的内容:

//These 'sprite' fileds point to the same image in memory
let player1 = Entity { sprite: get_spritesheet(cache, "player.png") };
let player2 = Entity { sprite: get_spritesheet(cache, "player.png") }; 

然而,我在使用Rust的所有权系统时遇到了很多障碍(可能是因为我不理解它)。
据我所知,我希望cache/hashmap“拥有”图像资源。具体来说,返回引用(如get_spritesheet函数中)似乎很奇怪。此外,一个结构体是否可以不拥有其所有成员?我认为可以,但我对如何实现感到困惑。

如何高效地从HashMap中查找和插入数据? - Shepmaster
2个回答

6
这是 std::collections::hash_map::Entry 的作用:
提供了对地图中单个条目的视图,该条目可以是空闲的或已被占用的。
match hashmap_cache.entry(key) {
    Entry::Vacant(entry) => *entry.insert(value),
    Entry::Occupied(entry) => *entry.get(),
}

如果条目为空,则将值插入缓存中,否则从缓存中获取该值。 Playground

0

我发现返回一个borrow只会出错,因为我将两个借用的引用传递给了函数,它不知道返回哪个引用。添加生命周期参数使其工作。我的函数现在看起来像这样:

pub fn load_spritesheet<'a>(
    spritesheets: &'a mut HashMap<String, Texture>,
    file: &String,
) -> Option<&'a Texture> {
    if !spritesheets.contains_key(file) {
        if let Some(texture) = load_texture(
            &vec!["dynamic_entities", "spritesheets"],
            file.as_str(),
            &TextureSettings::new(),
        ) {
            spritesheets.insert(file.clone(), texture);
        }
    }
    spritesheets.get(file)
}

关于结构体中的引用,我只实现了一个getter方法,每帧调用一次load_spritesheet。不是很理想,但目前还可以。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接