14 releases
Uses new Rust 2024
new 0.1.14 | May 11, 2025 |
---|---|
0.1.13 | May 11, 2025 |
#752 in Encoding
378 downloads per month
22KB
332 lines
Cowboy 🤠
A thread-safe wrapper for shared data with a focus on ergonomics.
Designed for quick prototyping, when you don't really want to think about lifetimes and just want to get something working as fast as possible.
What is it?
Cowboy<T>
is just a wrapper for Arc<RwLock<T>>
that's designed to be as low-boilerplate as possible. It has more concise method names, and lots of trait implementations that make it work in more situations. (It implements Eq
, Hash
, Ord
, and so on as long as the underlying type supports it).
Features
- Thread-safe shared data with interior mutability.
- Simple API: just use
.r()
to read and.w()
to write. - Implements common traits like
Clone
,PartialEq
,Hash
, etc. - Unsafe methods for those who want to break the rules.
SHERIFF
for global cowboy storage.- Zero-boilerplate serialization and deserialization.
Quick Start
I think we can all agree that you shouldn't use Cowboy
or SHERIFF
in production code, but I'm hopeful it can be useful for when you're prototyping and want the borrow checker to get out of your way. Here's how they work:
Basic usage
use cowboy::*;
// use `.cowboy()` on any value to get a Cowboy version of it.
let counter = 0.cowboy();
println!("Counter: {counter}");
// Cloning a cowboy gives you a pointer to the same underlying data
let counter_2 = counter.clone();
// Modify the value
*counter.w() += 1;
// Both counter and counter_2 were modified
assert_eq!(counter, counter_2);
Global storage with SHERIFF
use cowboy::*;
let counter = 0.cowboy();
// You can register cowboys with the SHERIFF using any key type
SHERIFF.register("counter", counter.clone());
SHERIFF.register(42, counter.clone());
// Access from anywhere
let counter_1 = SHERIFF.get::<_, i32>("counter");
let counter_2 = SHERIFF.get::<_, i32>(42); // Note: not &42
*counter.w() += 1;
*counter_1.w() += 2;
*counter_2.w() += 3;
// All counters should have the same value since they're all
// clones of the same original counter
assert_eq!(counter_1, counter_2);
println!("Counter: {counter}");
Zero-boilerplate saving and loading
use cowboy::*;
let counter = 0.cowboy();
counter.save("counter.json");
let new_counter = Cowboy::<i64>::load("counter.json");
println!("Counter: {counter}");
Examples
Check out the examples directory for more usage patterns:
basic.rs
: Simple usageshared_data.rs
: Sharing data between threadsunsafe_methods.rs
: Demonstrating the unsafe methods
License
MIT
Dependencies
~1.2–7MB
~29K SLoC