typewit

Trait HasTypeWitness

Source
pub trait HasTypeWitness<W: TypeWitnessTypeArg<Arg = Self>> {
    const WITNESS: W;
}
Expand description

Gets a type witness for Self.

A type witness is an enum whose variants only have TypeEq fields. Each variant requires the enum’s type parameter to be a specific type.

This trait is a helper to write W: MakeTypeWitness<Arg = T> with the T and W type parameters flipped, most useful in supertrait bounds.

This trait can’t be implemented outside of typewit.

§Example

This example shows how one can make a const fn that converts both &str and &[u8] to &str

(this example requires Rust 1.64.0)

use typewit::{HasTypeWitness, TypeWitnessTypeArg, MakeTypeWitness, TypeEq};
 
fn main() {
    assert_eq!(str_try_from("hello"), Ok("hello"));
     
    assert_eq!(str_try_from(&[b'w', b'o', b'r', b'l', b'd']), Ok("world"));
     
    assert_eq!(str_try_from(b"foo bar" as &[_]), Ok("foo bar"));
}
 
pub const fn str_try_from<'a, T, const L: usize>(
    input: T
) -> Result<&'a str, std::str::Utf8Error>
where
    T: StrTryFrom<'a, L>
{
    // `T::WITNESS` expands to 
    // `<T as HasTypeWitness<StrTryFromWitness<'a, L, T>>::WITNESS`
    match T::WITNESS {
        StrTryFromWitness::Str(te) => {
            // `te` (a `TypeEq<T, &'a str>`) allows coercing between `T` and `&'a str`.
            let string: &str = te.to_right(input);
            Ok(string)
        }
        StrTryFromWitness::Bytes(te) => {
            let bytes: &[u8] = te.to_right(input);
            std::str::from_utf8(bytes)
        }
        StrTryFromWitness::Array(te) => {
            let slice: &[u8] = te.to_right(input);
            str_try_from(slice)
        }
    }
}
 
 
// trait alias pattern
pub trait StrTryFrom<'a, const L: usize>: 
    Copy + HasTypeWitness<StrTryFromWitness<'a, L, Self>> 
{}
 
impl<'a, T, const L: usize> StrTryFrom<'a, L> for T
where
    T: Copy + HasTypeWitness<StrTryFromWitness<'a, L, T>>
{}
 
// This macro declares a type witness enum
typewit::simple_type_witness! {
    // Declares `enum StrTryFromWitness<'a, const L: usize, __Wit>` 
    // (the `__Wit` type parameter is implicitly added after all generics)
    // `#[non_exhausitve]` allows adding more supported types.
    #[non_exhaustive]
    pub enum StrTryFromWitness<'a, const L: usize> {
        // This variant requires `__Wit == &'a str`
        // 
        // The `<'a, 0>` here changes this macro from generating
        // `impl<'a, const L: usize> MakeTypeWitness for StrTryFromWitness<'a, L, &'a [u8]>`
        // to 
        // `impl<'a> MakeTypeWitness for StrTryFromWitness<'a, 0, &'a [u8]>`
        // which allows the compiler to infer generic arguments when
        // using the latter `MakeTypeWitness` impl`
        Str<'a, 0> = &'a str,
    
        // This variant requires `__Wit == &'a [u8]`
        Bytes<'a, 0> = &'a [u8],
    
        // This variant requires `__Wit == &'a [u8; L]`
        Array = &'a [u8; L],
    }
}

Required Associated Constants§

Source

const WITNESS: W

A constant of the type witness

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§

Source§

impl<T, W> HasTypeWitness<W> for T
where T: ?Sized, W: MakeTypeWitness<Arg = T>,

Source§

const WITNESS: W = W::MAKE