当我在板条箱中使用 Rust 工作区时,Vec 会清除

问题描述 投票:0回答:1

我最近创建了一个工具,它允许我从代码中的任何位置访问结构,只需通过结构名称。 它的工作方式非常简单,分配足够的空间来保存所需的结构,并存储指向每个结构的指针,并通过取消引用来访问它们。

#[derive(Debug, Default, Module)]
pub struct SomeStruct {
    test_u8: u8,
    test_vec: Vec<u8>,
}

#[derive(Debug, Default, Module)]
pub struct OtherStruct {
    pub test_vec: Vec<u8>,
}


fn main() {
    let bundle = ModuleBundleBuilder::default()
        .add_module::<SomeStruct>()
        .add_module::<OtherStruct>()
        .build()
        .unwrap();

    module_manager::init(bundle);

    let other_struct = get_module_mut::<OtherStruct>();
    other_struct.test_vec = Vec::new();
    other_struct.test_vec.push(2);
    other_struct.test_u8 = 2;

    dbg!(&other_struct.test_vec.as_ptr());
    //[app/src/main.rs:25:5] &other_struct.test_vec.as_ptr() = 0x000058ff06362c50
    get_module_mut::<SomeStruct>().test_vec = Vec::new();
    dbg!(&other_struct.test_vec.as_ptr());
    //[app/src/main.rs:27:5] &other_struct.test_vec.as_ptr() = 0x0000000000000001
    dbg!(&other_struct.test_u8);
    //[app/src/main.rs:30:5] &other_struct.test_u8 = 2
}

当我在单个包中使用上面的示例时,它工作得非常好。当我开始使用工作区并在工作区的不同成员中定义任一结构时,就会出现问题。 正如示例中所示,当我有两个结构体,每个结构体都持有一个 Vec 时,当我对其中一个结构体进行变异时,另一个结构体就会被丢弃或清除。

此时,我对如何解决该问题没有任何想法,希望这不是 Rust 本身的限制或错误。该工具位于 crates.io 上,称为模块管理器。

如果有人能给我建议一个解决方案,我会非常高兴。

pointers rust vector low-level
1个回答
0
投票

你正在使用的这个库(

module_manager
)充满了UB和不健全之处。不要使用它。

您可以通过以下简单安全的代码实现您想要的:

use std::any::{Any, TypeId};
use std::cell::{Ref, RefCell, RefMut};
use std::collections::HashMap;

pub struct ModuleBundle {
    map: HashMap<TypeId, RefCell<Box<dyn Any>>>,
}

impl ModuleBundle {
    pub fn new() -> Self {
        Self {
            map: HashMap::new(),
        }
    }

    pub fn add_module<M: Any>(&mut self, module: M) {
        self.map
            .insert(TypeId::of::<M>(), RefCell::new(Box::new(module)));
    }

    pub fn get_module<M: Any>(&self) -> Option<Ref<'_, M>> {
        self.map.get(&TypeId::of::<M>()).map(|module| {
            Ref::map(module.borrow(), |module| {
                module.downcast_ref::<M>().unwrap()
            })
        })
    }

    pub fn get_module_mut<M: Any>(&self) -> Option<RefMut<'_, M>> {
        self.map.get(&TypeId::of::<M>()).map(|module| {
            RefMut::map(module.borrow_mut(), |module| {
                module.downcast_mut::<M>().unwrap()
            })
        })
    }
}

这不允许您按照 Rust 定律的要求两次可变地获取模块。

© www.soinside.com 2019 - 2024. All rights reserved.