#specialization #cast #specialize #generics #object

no-std castaway

Safe, zero-cost downcasting for limited compile-time specialization

7 releases

0.2.3 Jul 4, 2024
0.2.2 Jun 4, 2022
0.2.1 Apr 22, 2022
0.1.2 Dec 9, 2021
0.1.0 Jun 21, 2021

#59 in Rust patterns

Download history 324643/week @ 2024-07-19 334843/week @ 2024-07-26 323740/week @ 2024-08-02 344443/week @ 2024-08-09 352868/week @ 2024-08-16 343329/week @ 2024-08-23 323408/week @ 2024-08-30 364660/week @ 2024-09-06 336440/week @ 2024-09-13 397752/week @ 2024-09-20 376847/week @ 2024-09-27 432360/week @ 2024-10-04 385242/week @ 2024-10-11 400311/week @ 2024-10-18 409470/week @ 2024-10-25 374150/week @ 2024-11-01

1,648,312 downloads per month
Used in 1,258 crates (17 directly)

MIT license

38KB
494 lines

Castaway

Safe, zero-cost downcasting for limited compile-time specialization.

Crates.io Documentation License Minimum supported Rust version Build

Documentation

Please check out the documentation for details how to use Castaway and its limitations. To get you started, here is a really simple, complete example of Castaway in action:

use std::fmt::Display;
use castaway::cast;

/// Like `std::string::ToString`, but with an optimization when `Self` is
/// already a `String`.
///
/// Since the standard library is allowed to use unstable features,
/// `ToString` already has this optimization using the `specialization`
/// feature, but this isn't something normal crates can do.
pub trait FastToString {
    fn fast_to_string(&self) -> String;
}

impl<T: Display> FastToString for T {
    fn fast_to_string(&self) -> String {
        // If `T` is already a string, then take a different code path.
        // After monomorphization, this check will be completely optimized
        // away.
        if let Ok(string) = cast!(self, &String) {
            // Don't invoke the std::fmt machinery, just clone the string.
            string.to_owned()
        } else {
            // Make use of `Display` for any other `T`.
            format!("{}", self)
        }
    }
}

fn main() {
    println!("specialized: {}", String::from("hello").fast_to_string());
    println!("default: {}", "hello".fast_to_string());
}

Minimum supported Rust version

The minimum supported Rust version (or MSRV) for Castaway is stable Rust 1.38 or greater, meaning we only guarantee that Castaway will compile if you use a rustc version of at least 1.38. This version is explicitly tested in CI and may only be bumped in new minor versions. Any changes to the supported minimum version will be called out in the release notes.

What is this?

This is an experimental library that implements zero-cost downcasting of types that works on stable Rust. It began as a thought experiment after I had read this pull request and wondered if it would be possible to alter the behavior of a generic function based on a concrete type without using trait objects. I stumbled on the "zero-cost"-ness of my findings by accident while playing around with different implementations and examining the generated assembly of example programs.

The API is somewhat similar to Any in the standard library, but Castaway is instead focused on ergonomic compile-time downcasting rather than runtime downcasting. Unlike Any, Castaway does support safely casting non-'static references in limited scenarios. If you need to store one or more Box<?> objects implementing some trait with the option of downcasting, you are much better off using Any.

License

This project's source code and documentation is licensed under the MIT license. See the LICENSE file for details.

Dependencies