簡體   English   中英

Rust:從 HashMap 可變值的 downcast_ref 返回 &mut 引用

[英]Rust: return &mut reference from downcast_ref of HashMap mutable value

正如標題所說,我們有一個運行 wasm 插件的應用程序。 每個插件都可以在State中注冊自己的StateRegistry 然后每當執行插件時,它們都會修改各自的State

下面的代碼說明了這一點:

use std::{collections::HashMap, any::Any};

type ContractId = String;
type GenericContractState = Box<dyn Any>;

// This will be WASM code
mod foo_contract {
    use super::StateRegistry;

    pub struct State {
    }

    pub fn update(states: &mut StateRegistry) {
        let state = states.states.get_mut(&"foo_contract".to_string()).unwrap();
        let state = state.downcast_mut::<State>().unwrap();
        // I'd prefer something like:
        // let state = state.lookup::<State>().unwrap()
    }
}

pub struct StateRegistry {
    pub states: HashMap<ContractId, GenericContractState>,
}

impl StateRegistry {
    fn new() -> Self {
        Self { states: HashMap::new() }
    }

    fn register(&mut self, contract_id: ContractId, state: GenericContractState) {
        self.states.insert(contract_id, state);
    }

    /*
    fn lookup<'a, S>(&'a mut self, contract_id: &ContractId) -> Option<StateRefWrapper<'a, S>> {
        match self.states.get_mut(contract_id) {
            Some(state) => {
                let ptr = state.downcast_mut::<S>();
                match ptr {
                    Some(ptr) => Some(StateRefWrapper { _mut: state, ptr }),
                    None => None,
                }
            }
            None => None,
        }
    }
    */
}

/*
struct StateRefWrapper<'a, S> {
    _mut: &'a mut Box<dyn Any>,
    ptr: &'a mut S,
}
*/

fn main() {
    let mut states = StateRegistry::new();
    let foo_state = Box::new(foo_contract::State {});
    states.register("foo_contract".to_string(), foo_state);

    foo_contract::update(&mut states);
}

我要改進的部分是,目前插件開發人員必須使用此代碼在注冊表中查找他們的State

        let state = states.states.get_mut(&"foo_contract".to_string()).unwrap();
        let state = state.downcast_mut::<State>().unwrap();

我想在StateRegistry中創建一個可以像這樣使用的相應方法:

        let state = state.lookup::<State>().unwrap()

我的嘗試(上面評論)是這樣的:

impl StateRegistry {
    // ...

    fn lookup<'a, S>(&'a mut self, contract_id: &ContractId) -> Option<StateRefWrapper<'a, S>> {
        match self.states.get_mut(contract_id) {
            Some(state) => {
                let ptr = state.downcast_mut::<S>();
                match ptr {
                    Some(ptr) => Some(StateRefWrapper { _mut: state, ptr }),
                    None => None,
                }
            }
            None => None,
        }
    }
}

struct StateRefWrapper<'a, S> {
    _mut: &'a mut Box<dyn Any>,
    ptr: &'a mut S,
}

我怎樣才能讓這個lookup() function 工作?

謝謝

您不能以您想要的方式構造您的StateRefWrapper ,因為它將包含兩個具有相同值的可變借用。 但是,您可以只返回一個看起來足夠的&mut S

fn lookup<'a, S: 'static>(&'a mut self, contract_id: &ContractId) -> Option<&'a mut S> {
    self.states
        .get_mut(contract_id)
        .and_then(|state| state.downcast_mut())
}

並像這樣使用它:

pub fn update(states: &mut StateRegistry) {
    let state = states.lookup::<State>(&"foo_contract".to_string()).unwrap();
    // state.modify();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM