gpt4 book ai didi

Rust 通用值内存存储实现

转载 作者:行者123 更新时间:2023-12-05 01:23:35 26 4
gpt4 key购买 nike

我正在为一个对象存储开发一个 API,我正在努力寻找一种在 Rust 中实现它的方法。有点令人沮丧,因为我很清楚如何在 C++ 中完成此操作,所以也许该设计从根本上不适合 Rust,但我希望这里的人们可以提供一些有用的见解。

我希望能够做到以下几点:

// This is clone & copy
struct Id<Identifiable> {
// What I think would be needed to get this entire system
// to work, but it is not fixed like this so alternate
// ideas are welcome.
raw_id: usize,
_marker: PhantomData<Identifiable>,
}

struct Store {
// ... don't know how to implement this
}

trait Object {
// ... some behavior
}

struct ObjectA {}
impl Object for ObjectA {}

struct ObjectB {}
impl Object for ObjectB {}

impl Store {
pub fn create_object_a(&mut self) -> Id<ObjectA> { todo!() }
pub fn create_object_b(&mut self) -> Id<ObjectB> { todo!() }

pub fn get<'a, Obj: Object>(&self, id: Id<Obj>) -> &'a Obj { todo!() }
}

这将按如下方式使用:

let store = Store::new();
let handle_a = store.create_object_a();
let handle_b = store.create_object_b();

let obj_a = store.get(handle_a); // obj_a is of type &ObjectA
let obj_b = store.get(handle_b); // obj_b is of type &ObjectB

由于可以放入商店的具体类型是静态已知的(如果它们是通过 create_something() 方法构建的,它们只能在商店中),我觉得类型系统中应该有足够的信息来能够做到这一点。我非常想避免的一件事是 Vec<Box<dyn Any>>。 ,因为这引入了额外的间接性。

我意识到这在安全的 Rust 中可能是不可能的,尽管我觉得使用不安全的 Rust 应该是可能的。我的想法是它有点类似于 Bevy ECS 实现存储组件的方式(相同类型的组件连续存储在内存中,我也希望在这里看到这个属性),尽管我正在努力理解它是如何工作的.

希望有人对如何实现这个有想法,或者有一个更适合 Rust 的替代设计。谢谢!

最佳答案

您可以在 Obj 上创建一个通用特征,指定如何从存储中检索 Obj 的竞技场 (Vecs),并将其应用于 ObjectA ObjectB。然后 Store::get() 使用此实现来检索值。

// Your store type:
struct Store {
a_store: Vec<ObjectA>,
b_store: Vec<ObjectB>,
}

// Trait family that specifies how to obtain slice of T's from Store
trait StoreGet<T> {
fn raw_storage(&self) -> &[T];
}

// Implementation of the trait applied to ObjectA and ObjectB on Store:
impl StoreGet<ObjectA> for Store {
fn raw_storage(&self) -> &[ObjectA] {
&self.a_store
}
}
impl StoreGet<ObjectB> for Store {
fn raw_storage(&self) -> &[ObjectB] {
&self.b_store
}
}

有了它,Store 将按如下方式实现:

impl Store {
pub fn create_object_a(&mut self) -> Id<ObjectA> {
let raw_id = self.a_store.len();
self.a_store.push(ObjectA {});
Id {
raw_id,
_marker: PhantomData,
}
}
pub fn create_object_b(&mut self) -> Id<ObjectB> {
// ... essentially the same as create_object_a ...
}

pub fn get<Obj>(&self, id: Id<Obj>) -> &Obj
where
Obj: Object,
Self: StoreGet<Obj>,
{
let slice = self.raw_storage();
&slice[id.raw_id]
}
}

Playground

我建议查看 an arena crate而不是实现自己的竞技场(虽然如果你自己实现它并不是悲剧 - 重用通常是个好主意)。

关于Rust 通用值内存存储实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72241916/

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