a crate to swap values between possibly-overlapping references

Related tags

Command-line rust
Overview

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:

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:

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:

let mut a = [1, 2, 3];
a.swap(0, 2);

But how about two-dimensional arrays?

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:

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:

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:

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!.

You might also like...
🍅 A command-line tool to get and set values in toml files while preserving comments and formatting

tomato Get, set, and delete values in TOML files while preserving comments and formatting. That's it. That's the feature set. I wrote tomato to satisf

Encode and decode dynamically constructed values of arbitrary shapes to/from SCALE bytes

scale-value · This crate provides a Value type, which is a runtime representation that is compatible with scale_info::TypeDef. It somewhat analogous t

A command line tool that resembles a debugger as well as Cheat Engine, to search for values in memory
A command line tool that resembles a debugger as well as Cheat Engine, to search for values in memory

Summary This is a small command-line tool designed to peek around memory of a running Linux process. It also provides filtering mechanisms similar to

Library uses file-based mmap to store key-values

Library uses file-based mmap to store key-values This is a Rust version of MMKV. By default, this lib uses CRC8 to check data integrity. If include fe

Macro to print variable(s) with values nicely (stripped from release builds)

log_macro Macro to print variable(s) with values nicely (stripped from release builds) Install cargo add log_macro Use Add this to top of file: #[mac

Use LLMs to generate strongly-typed values

Magic Instantiate Quickstart use openai_magic_instantiate::*; #[derive(MagicInstantiate)] struct Person { // Descriptions can help the LLM unders

Fast conversion between linear float and 8-bit sRGB

fast-srgb8 Small crate implementing fast conversion between linear float and 8-bit sRGB. Includes API for performing 4 simultaneous conversions, which

 ⚡️ A blazing fast way of maintaining powerful notes with connections between them.
⚡️ A blazing fast way of maintaining powerful notes with connections between them.

Zettl ⚡️ A blazing fast way of maintaining powerful notes with connections between them. Installing Zettl To install Zettl, you will need the Rust too

Facilitates navigating between tmux and nvim with C-hjkl

neovim-tmux-navigator Usage Use C-hjkl to navigate left, down, up, right, respectively. neovim-tmux-navigator will switch between vim splits and tmu

Owner
Masaki Hara
Software Engineer at @wantedly
Masaki Hara
Periodically download a youtube playlist, extract audio, convert to mp3, move to directory (possibly synced using syncthing).

auto-dl Periodically download a youtube playlist, extract audio, convert to mp3, move to directory (possibly synced using syncthing). drop https://git

Paul Adenot 10 Jan 12, 2023
A Supra + Pandoc post-processor for footnote cross-references.

AutoCref AutoCref is a Supra and Pandoc post-processor that turns footnote cross-references in a Word document into automatically updated fields. Abou

null 2 Sep 4, 2022
An adaptation of the Solana token-swap program implementing Curve's StableSwap invariant.

StableSwap Program An adaptation of the Solana token-swap program implementing Curve's StableSwap invariant. Click here to try it out live on the Sola

smaster0517 3 Mar 30, 2022
Neovim Configuration Manager (Swap/Backup/Try Configurations Easily)

ncm-rs Neovim Configuration Manager (Swap/Backup/Try Configurations Easily) I created this package because I wanted to try out Lazyvim (which is why i

instance.id 4 Mar 5, 2023
Microsoft Excel (XLSX) to Unicode Separated Values (USV) Rust crate

xlsx-to-usv Convert Microsoft Excel (XLSX) to Unicode Separated Values (USV). Built with the USV Rust crate. Syntax: stdin | xlsx-to-usv [options] | s

SixArm 3 Mar 31, 2024
Padding/aligning values without heap allocation

zero-copy-pads Padding/aligning values without heap allocation. Cargo Features std (default feature): Disable #![no_std]. Enable features that require

Khải 5 Nov 29, 2021
Eventually consistent values for Rust

Eventuals give you the most up-to-date snapshots of some value. They are like Futures that update over time, continually resolving to an eventually co

Edge & Node 110 Dec 31, 2022
Rust TUI library - Clipping region is a set of min/max x/y values applied to the existing region

TinyBit Clipping region is a set of min/max x/y values applied to the existing region A TUI lib This is not yet production ready T O D O TODO: bugs: T

Togglebit 13 May 3, 2022
Generic extensions for tapping values in Rust.

tap Suffix-Position Pipeline Behavior This crate provides extension methods on all types that allow transparent, temporary, inspection/mutation (tappi

Alexander Payne 213 Dec 30, 2022
Quickly save and retrieve values for shell scripts.

Quickly save and retrieve values for shell scripts.

Alex Andrade 2 Dec 15, 2022