Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/qnighy/omniswap
a crate to swap values between possibly-overlapping references
https://github.com/qnighy/omniswap
rust
Last synced: 3 days ago
JSON representation
a crate to swap values between possibly-overlapping references
- Host: GitHub
- URL: https://github.com/qnighy/omniswap
- Owner: qnighy
- License: mit
- Created: 2022-08-20T09:27:40.000Z (about 2 years ago)
- Default Branch: master
- Last Pushed: 2022-08-22T22:28:01.000Z (about 2 years ago)
- Last Synced: 2024-10-30T00:27:01.417Z (13 days ago)
- Topics: rust
- Language: Rust
- Homepage:
- Size: 12.7 KB
- Stars: 23
- Watchers: 2
- Forks: 2
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# omniswap: a crate to swap values between possibly-overlapping references
## Motivating Example
You cannot simply use `std::mem::swap` to replace values within an array:
```rust
let mut a = [1, 2, 3];
// You cannot prove their disjointness!
std::mem::swap(&mut a[0], &mut a[2]);
```You get the following message:
```text
error[E0499]: cannot borrow `a[_]` as mutable more than once at a time
--> src/main.rs:4:31
|
4 | std::mem::swap(&mut a[0], &mut a[2]);
| -------------- --------- ^^^^^^^^^ second mutable borrow occurs here
| | |
| | first mutable borrow occurs here
| first borrow later used by call
|
= help: consider using `.split_at_mut(position)` or similar method to obtain two mutable non-overlapping sub-slices
```You can use the dedicated `<[T]>::swap` instead:
```rust
let mut a = [1, 2, 3];
a.swap(0, 2);
```But how about two-dimensional arrays?
```rust
let mut a = [[1, 2], [3, 4]];
// You cannot prove their disjointness!
std::mem::swap(&mut a[0][0], &mut a[1][1]);
```This is not as simple as the first one.
## Solution
This crate solves the problem by providing a generic framework for
**sentinel-based swapping**.The idea is simple: it leaves a dummy value behind to safely
move values around:```rust
let mut a = [[1, 2], [3, 4]];
let tmp = std::mem::replace(&mut a[0][0], 0);
let tmp = std::mem::replace(&mut a[1][1], tmp);
a[0][0] = tmp;
# assert_eq!(a, [[4, 2], [3, 1]]);
```However, in Rust, the best sentinel value differs between types.
The macro `swap!` automatically chooses the best sentinel and
provides the same interface as `std::mem::swap`:```rust
let mut a = [[1, 2], [3, 4]];
omniswap::swap!(&mut a[0][0], &mut a[1][1]);
# assert_eq!(a, [[4, 2], [3, 1]]);
```## Usage
Simply use `swap!` where you want to use `std::mem::swap`:
```rust
let mut x = 42;
let mut y = 84;
omniswap::swap!(&mut x, &mut y);
```See `swap!` for detailed usages.
## Other APIs
The crate provides the following variants:
- `rotate!` -- swaps more than two values at once
The crate also exposes `take!` and `Replace`.
These are primitives used in `swap!` and `rotate!`.