| Crates.io | rustmorphism |
| lib.rs | rustmorphism |
| version | 0.1.0 |
| created_at | 2025-04-15 12:18:51.44197+00 |
| updated_at | 2025-04-15 12:18:51.44197+00 |
| description | A Rust macro for creating functions with multiple implementations that are deterministically selected at compile-time |
| homepage | |
| repository | https://github.com/EduContin/rustmorphism |
| max_upload_size | |
| id | 1634361 |
| size | 15,731 |
Compile-time polymorphism for Rust functions: deterministic, zero-cost, and ergonomic.
rustmorphism is a procedural macro crate that lets you define multiple implementations for a function, with one being deterministically selected at compile time. This enables A/B testing, feature comparison, and binary size optimization—all with zero runtime overhead.
Rust does not natively support function-level compile-time polymorphism. rustmorphism fills this gap, making it easy to:
Add this to your Cargo.toml:
[dependencies]
rustmorphism = "0.1.0"
use rustmorphism::polymorphic_fn;
polymorphic_fn! {
pub fn choose(x: i32) -> i32 {
{ x + 1 }, // Implementation 1
{ x * 2 }, // Implementation 2
{ x * x } // Implementation 3
}
}
fn main() {
println!("Result: {}", choose(5));
}
use rustmorphism::polymorphic_fn;
polymorphic_fn! {
pub fn calculate(x: i32) -> i32 {
{ x + 1 }, // Implementation 1
{ x * 2 }, // Implementation 2
{ x * x } // Implementation 3
}
}
fn main() {
let result = calculate(5);
println!("Result: {}", result); // Will print result from one of the implementations
}
use rustmorphism::polymorphic_fn;
fn small_impl(data: &[u8]) -> u64 {
data.iter().map(|&b| b as u64).sum()
}
fn large_impl(data: &[u8]) -> u64 {
static LARGE_DATA: [u8; 1_000_000] = [0; 1_000_000];
data.iter().zip(LARGE_DATA.iter())
.map(|(&a, &b)| (a as u64) * (b as u64 + 1))
.sum()
}
polymorphic_fn! {
pub fn process_data(data: &[u8]) -> u64 {
{ small_impl(data) },
{ large_impl(data) }
}
}
use rustmorphism::polymorphic_fn;
polymorphic_fn! {
pub fn sort_algorithm<T: Ord + Copy>(data: &mut [T]) {
{
// Implementation 1: Quick sort
data.sort_unstable();
},
{
// Implementation 2: Insertion sort
for i in 1..data.len() {
let mut j = i;
while j > 0 && data[j-1] > data[j] {
data.swap(j-1, j);
j -= 1;
}
}
}
}
}
The polymorphic_fn! macro uses compile-time hashing to select one implementation from the provided alternatives. The selection is based on:
This ensures the selection is consistent for a given build, but can change between builds, allowing for different implementations to be tested over time.
You can influence which implementation is selected by:
cargo clean).cargo:rerun-if-changed=nonexistent-file to ensure the build script runs every time.FORCE_REBUILD environment variable before building.Q: Is there any runtime overhead?
A: No. Only the selected implementation is compiled into the binary.
Q: Can I use this for benchmarking or fuzzing?
A: Yes! This is a great way to compare different algorithms or code paths.
Q: How do I ensure a specific implementation is chosen?
A: The selection is deterministic but based on build metadata. For full control, you can patch the macro or use environment variables as entropy.
Contributions, issues, and feature requests are welcome!
Feel free to check the issues page or submit a pull request.
This project is licensed under the MIT License. See the LICENSE file for details.