MCPcopy Index your code
hub / github.com/alecmocatta/replace_with

github.com/alecmocatta/replace_with @v0.1.8

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.1.8 ↗ · + Follow
21 symbols 50 edges 1 files 0 documented · 0%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

replace_with

Crates.io MIT / Apache 2.0 licensed Build Status

📖 Docs | 💬 Chat

Temporarily take ownership of a value at a mutable location, and replace it with a new value based on the old one.

This crate provides the function replace_with(), which is like std::mem::replace() except it allows the replacement value to be mapped from the original value.

See RFC 1736 for a lot of discussion as to its merits. It was never merged, and the desired ability to temporarily move out of &mut T doesn't exist yet, so this crate is my interim solution.

It's very akin to take_mut, though uses Drop instead of std::panic::catch_unwind() to react to unwinding, which avoids the optimisation barrier of calling the extern "C" __rust_maybe_catch_panic(). As such it's up to ∞x faster. The API also attempts to make slightly more explicit the behavior on panic – replace_with() accepts two closures such that aborting in the "standard case" where the mapping closure (FnOnce(T) -> T) panics (as take_mut::take() does) is avoided. If the second closure (FnOnce() -> T) panics, however, then it does indeed abort. The "abort on first panic" behaviour is available with replace_with_or_abort().

Example

Consider this motivating example:

enum States {
    A(String),
    B(String),
}

impl States {
    fn poll(&mut self) {
        // error[E0507]: cannot move out of borrowed content
        *self = match *self {
            //        ^^^^^ cannot move out of borrowed content
            States::A(a) => States::B(a),
            States::B(a) => States::A(a),
        };
    }
}

Depending on context this can be quite tricky to work around. With this crate, however:

enum States {
    A(String),
    B(String),
}

impl States {
    fn poll(&mut self) {
        replace_with_or_abort(self, |self_| match self_ {
            States::A(a) => States::B(a),
            States::B(a) => States::A(a),
        });
    }
}

Huzzah!

no_std

To use replace_with with no_std you have to disable the std feature, which is active by default, by specifying your dependency to it like this:

# Cargo.toml

replace_with = { version = "0.1", default-features = false }

The nightly feature can be enabled to use core::intrinsics::abort() instead of triggering an abort via std::process::abort() or extern "C" fn abort() { panic!() } abort().

License

Licensed under either of

  • Apache License, Version 2.0, (LICENSE-APACHE.txt or http://www.apache.org/licenses/LICENSE-2.0)
  • MIT license (LICENSE-MIT.txt or http://opensource.org/licenses/MIT)

at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Core symbols most depended-on inside this repo

replace_with
called by 6
src/lib.rs
abort
called by 3
src/lib.rs
on_unwind_inner
called by 3
src/lib.rs
replace_with_and_return
called by 3
src/lib.rs
abort_unwind
called by 2
src/lib.rs
on_unwind
called by 2
src/lib.rs
drop
called by 0
src/lib.rs
on_return_or_unwind
called by 0
src/lib.rs

Shape

Function 17
Class 2
Enum 1
Method 1

Languages

Rust100%

Modules by API surface

src/lib.rs21 symbols

For agents

$ claude mcp add replace_with \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact