Trait konst_kernel::type_eq::HasTypeWitness

source ·
pub trait HasTypeWitness<W>
where 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

Object Safety§

This trait is not object safe.

Implementors§

source§

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

source§

const WITNESS: W = W::MAKE