vorner / arc-swap

Support atomic operations on Arc itself
Apache License 2.0
777 stars 31 forks source link

Feature Request: Returning owned types from Map #92

Open edward-shen opened 1 year ago

edward-shen commented 1 year ago

Hey! Thanks for the work on this -- It's super useful and I appreciate the technical effort.

I'm running into a bit of trouble that I don't think is currently resolvable by the current implementation. In short, I have the following:

struct GlobalConfig {
    config: Arc<ArcSwap<Config>>,
}

struct Config {
    sub_configs: HashMap<String, SubConfig>
}

struct SubConfig {} // implementation is unnecessary

I'm trying to implement the following function:

impl GlobalConfig {
    fn fetch_subconfig(&self, config_name: &str) -> Guard<&SubConfig> {
        // Doesn't work
        self.config.map(move |config| config.get(config_name))
    }
}

where I dynamically load a sub-config based on the provided config name.

The issue is that I don't think the current API offers an easy way to do. Map currently requires a function that returns a reference, while HashMap::get returns an owned type (Option<&T>). This leads to two lifetime issues.

Here's a playground link of my attempt: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=cd5ff805d13d091e47852cf29266fec0

and where I get stuck.

Is there a way to offer this? Would a signature of something like map_owned<'a>(&'a self, f: impl Fn(&'a Self) -> T + 'a) work?

The closest API I can get is where I always return a static reference to a default value (https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=fbf48553ec5d3e85d0cb6aeb1dcf0d5d)

but that's not very useful as I'd optimally work with Result in this projection (e.g. it would return something like Result<&'a T, E>.

vorner commented 1 year ago

Hello

I confirm your observation that this doesn't exist. The idea of Map is that it simply „projects“ into the whole thing and doesn't actually store anything. I'm not entirely sure this can be done or, if it can, if there are some serious drawbacks, currently. But as Map doesn't use anything „special“ from inside, maybe you could sketch it out and we could decide if it fits into the crate in some place.