2 releases
Uses new Rust 2024
| 0.1.1 | Sep 28, 2025 |
|---|---|
| 0.1.0 | Sep 28, 2025 |
#1160 in Rust patterns
72 downloads per month
8KB
80 lines
ownables
A small, safe, and generic Rust library for temporarily taking ownership of a value from a container.
Overview
This library provides a mechanism for safely moving a value out of a container, operating on it, and ensuring it's returned. It uses the robust RAII pattern (Resource Acquisition Is Initialization) via a TakenGuard.
Think of it like checking out a book from a library: you take it, use it, and the system ensures it's returned to the shelf when you're done, even if you get distracted. This prevents your data structures from being left in an invalid or "taken" state, especially in the event of a panic.
Key Features
- Panic Safe: Ensures the value is returned to its container, even if your code panics.
- Ergonomic: The
TakenGuardautomatically handles returning the value on scope exit. No manualput_backcalls are needed. - Generic: The
Ownabletrait allows you to apply this take-and-return pattern to your own custom data structures. - Zero-Cost Abstraction: All checks and operations are handled at compile time with no runtime overhead.
Getting Started
Add ownables to your Cargo.toml:
[dependencies]
ownables = "0.1.0" # Replace with the latest version
Core Concepts
The library is built around two main components:
- Ownable Trait: An interface that defines a container from which an item can be taken and returned. You can implement this for your own types.
- TakenGuard: A smart pointer (like MutexGuard) that holds the taken value. When the TakenGuard is dropped (i.e., goes out of scope), its Drop implementation automatically places the value back into the original container.
Example Usage
Here's a basic example of taking a number from an OwnableCell, modifying it, and letting the guard return it automatically.
use ownables::{Ownable, OwnableCell};
// 1. Create a cell holding a value.
let mut source = OwnableCell::Available(100);
assert!(source.is_available());
// 2. The `take()` method moves the value out of `source` and into a guard.
// At this point, `source` is internally set to `OwnableCell::Taken`.
{
let mut guard = source.take();
// The guard dereferences to an `Option`. We can safely access and mutate the value.
if let Some(value) = guard.as_mut() {
*value += 50;
println!("Value inside guard: {}", value); // Prints: Value inside guard: 150
}
} // <-- The `guard` goes out of scope here. Its Drop impl is called automatically.
// 3. The value has been returned to the source container.
assert!(source.is_available());
assert_eq!(*source.read().unwrap(), 150);
println!("Final value in source: {}", source.read().unwrap()); // Prints: Final value in source: 150
License
This project is licensed under either of:
- Apache License, Version 2.0, (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contribution
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.