Swap out a type's Ord, Hash, Display (or any user-defined trait)
for one block of code, without newtype boilerplate.
Sometimes you want to sort a Vec<i32> descending, hash a String
case-insensitively, or render a number with a custom prefix, but only
for one operation. The orthodox Rust answer is to wrap the value in a
newtype that implements the trait differently. That works, but it
requires a new struct, manual impls, and you lose access to all the
existing impls on the inner type.
This crate offers a lighter alternative. [WithContext<T, Ctx>] is a
wrapper that pairs a value with a context, a small Copy struct of
function pointers that supplies the relevant trait implementation.
Standard library APIs that take Ord / Hash / Display work
unchanged; the context decides the behavior.
Three built-in contexts cover the common cases:
- [
OrdContext<T>] supplies a custom comparator. - [
HashContext<T>] supplies a custom hasher. - [
DisplayContext<T>] supplies a custom formatter.
And three corresponding macros wrap up the lift / call / project dance:
- [
with_ord!] - [
with_hash!] - [
with_display!]
For traits beyond these three, [impl_context_trait!] generates a new
context type for an arbitrary trait of yours.
Why function pointers?
Contexts hold fn pointers, not Box<dyn Fn>. This makes the wrapper
Copy regardless of T, which is what lets BTreeSet,
slice::sort, and HashMap accept it without complaint. It also
means the comparator must be stateless. If you need captured state,
reach for a newtype.
See docs/phase3-context-trait.md for the full design
rationale.
Examples
Sort a slice descending without a newtype:
use ;
let items = vec!;
with_ord!;