// lint me harder
// not that hard:
//! Provides safe trivial transmutes in generic context, emulating
//! specialization on stable Rust. These functions are designed for being
//! optimized out by the compiler, so are probably zero-cost in most cases.
//!
//! ```rust
//! fn specialized_function<T: 'static>(x: T) -> String {
//! // We have an efficient algorithm for `i32` and worse algorithm for any other type.
//! // With `cismute` we can do:
//! match cismute::owned::<T, i32>(x) {
//! Ok(x) => format!("got an i32: {x}"),
//! Err(x) => format!("got something else"),
//! }
//! }
//!
//! assert_eq!(specialized_function(42_i32), "got an i32: 42");
//! assert_eq!(specialized_function(":)"), "got something else");
//! ```
//!
//! [`cismute::owned`](owned()) works only for `'static` types. If your type
//! is a reference, you should use [`cismute::reference`](reference()) or
//! [`cismute::mutable`](mutable()).
//!
//! ```rust
//! fn specialized_function<T: 'static>(x: &T) -> String {
//! // We have an efficient algorithm for `i32` and worse algorithm for any other type.
//! // With `cismute` we can do:
//! match cismute::reference::<T, i32>(x) {
//! Ok(x) => format!("got an i32: {x}"),
//! Err(x) => format!("got something else"),
//! }
//! }
//!
//! assert_eq!(specialized_function(&42_i32), "got an i32: 42");
//! assert_eq!(specialized_function(&":)"), "got something else");
//! ```
//!
//! There's also a more generic function [`cismute::value`](value()) which can
//! do all three. Writing all type arguments can be cumbersome, so you can also
//! pass the type pair as an argument via [`cismute::value_with`](value_with()):
//!
//! ```rust
//! use cismute::Pair;
//!
//! fn specialized_function<T: 'static>(x: &T) -> String {
//! match cismute::value_with(Pair::<(T, i32)>, x) {
//! Ok(x) => format!("got an i32: {x}"),
//! Err(x) => format!("got something else"),
//! }
//! }
//!
//! assert_eq!(specialized_function(&42_i32), "got an i32: 42");
//! assert_eq!(specialized_function(&":)"), "got something else");
//! ```
//!
//! There are also [`switch!()`] macro and [`switch()`] function
//! to match one value with multiple types.
use ;
use Branches;
union
// Required because transmute doesn't work in generic contexts
unsafe
/// Pair of two types for passing to [`cismute::value_with`](value_with()).
///
/// <!-- I'm sorry, but rustdoc does something weird with reexports -->
/// <div style="display: none">
pub use PhantomData as Pair;
/// A reference that can be safely transmuted if underlying type is the same.
///
/// # Safety
/// For any `RefT: Cismutable<'a, T, RefU>` transmutation from `RefT` to
/// `RefU` must be safe if `T` and `U` are the same type.
pub unsafe
unsafe
unsafe
unsafe
use Phantom;
/// Transmutes an owned value of type `T` to type `U` if they are the same type.
/// Returns the passed value back if failed.
///
/// See module-level docs for usage example.
/// Transmutes reference to type `T` to `&U` if they are the same type.
/// Returns the passed value back if failed.
///
/// See module-level docs for usage example.
/// Transmutes a mutable reference to type `T` to `&mut U` if they are the same
/// type. Returns the passed value back if failed.
///
/// See module-level docs for usage example.
/// Cismutes `T` or a (possibly mutable) reference to `T` to `U` with the same
/// ownership, i.e. owned value is cismuted like with
/// [`cismute::owned`](owned()), reference is cismuted to reference and mutable
/// reference is cismuted to mutable reference, if they are the same type.
/// Returns the passed value back if failed.
///
/// See module-level docs for usage example.
/// Cismutes `T` or a (possibly mutable) reference to `T` to the type specified
/// by the first argument while preserving ownership, i.e. owned value is
/// cismuted like with [`cismute::owned`](owned()), reference is cismuted to
/// reference and mutable reference is cismuted to mutable reference.
/// Returns the passed value back if failed.
///
/// **Note**: first argument specifies types `T` and `U`, not the reference
/// types.
///
/// See module-level docs for usage example.
/// Try to match `T` with several (up to 32) other types. This function requires
/// the `switch` feature, as it increases build time considerably.
///
/// ```rust
/// # use std::fmt::Debug;
/// fn specialized_function<T: Debug + 'static>(val: T) -> String {
/// cismute::switch(
/// val,
/// (
/// |x: i32| format!("got an i32: {x}"),
/// |x: char| format!("got a char: {x}"),
/// ),
/// )
/// .unwrap_or_else(|x| format!("got something else: {x:?}"))
/// }
///
/// assert_eq!(specialized_function(42_i32), "got an i32: 42");
/// assert_eq!(specialized_function('!'), "got a char: !");
/// assert_eq!(specialized_function([1, 2]), "got something else: [1, 2]");
/// ```
///
/// Switching on references requires specifying the source type. This is a
/// limitation of Rust type system.
///
/// ```rust
/// # use std::fmt::Debug;
/// use std::marker::PhantomData as X;
///
/// fn specialized_function<T: Debug + 'static>(val: &mut T) -> String {
/// cismute::switch(
/// val,
/// cismute::from(
/// X::<T>,
/// (
/// |x: &mut i32| format!("got an i32: {x}"),
/// |x: &mut char| format!("got a char: {x}"),
/// ),
/// ),
/// )
/// .unwrap_or_else(|x| format!("got something else: {x:?}"))
/// }
///
/// assert_eq!(specialized_function(&mut 42_i32), "got an i32: 42");
/// assert_eq!(specialized_function(&mut '!'), "got a char: !");
/// assert_eq!(
/// specialized_function(&mut [1, 2]),
/// "got something else: [1, 2]"
/// );
/// ```
/// Helper function for [`switch()`].
/// Try to match a value with any number of types. This macro _does not_ require
/// the `switch` feature.
///
/// ```rust
/// # use std::fmt::Debug;
/// fn specialized_function<T: Debug + 'static>(val: T) -> String {
/// cismute::switch!(val; T => {
/// x: i32 => format!("got an i32: {x}"),
/// x: char => format!("got a char: {x}"),
/// }).unwrap_or_else(|x| format!("got something else: {x:?}"))
/// }
///
/// assert_eq!(specialized_function(42_i32), "got an i32: 42");
/// assert_eq!(specialized_function('!'), "got a char: !");
/// assert_eq!(specialized_function([1, 2]), "got something else: [1, 2]");
/// ```
///
/// It can also be used with (possibly mutable) references:
///
/// ```rust
/// # use std::fmt::Debug;
/// fn specialized_function<T: Debug + 'static>(val: &mut T) -> String {
/// cismute::switch!(val; T => {
/// x: i32 => format!("got an i32: {x}"),
/// x: char => format!("got a char: {x}"),
/// }).unwrap_or_else(|x| format!("got something else: {x:?}"))
/// }
///
/// assert_eq!(specialized_function(&mut 42_i32), "got an i32: 42");
/// assert_eq!(specialized_function(&mut '!'), "got a char: !");
/// assert_eq!(specialized_function(&mut [1, 2]), "got something else: [1, 2]");
/// ````