type-protocol 0.1.0

A crate provding a simple syntax representing types.
Documentation
use std::collections::{HashMap, BTreeMap, HashSet, BTreeSet};

use crate::{RustIdent, Typing, UniversalType};

#[doc(hidden)]
#[macro_export]
macro_rules! nz {
    ($i: literal) => {
        match ::core::num::NonZeroUsize::new($i) {
            Some(x) => x,
            None => unreachable!(),
        }
    };
}

macro_rules! impl_common {
    ($ty: ty, $branch: ident) => {
        impl ToTypeProtocol for $ty {
            fn type_protocol() -> Typing<RustIdent> {
                Typing::Common(UniversalType::$branch)
            }
        }
    };
    ($ty: ty, $branch: ident, $len: literal) => {
        impl ToTypeProtocol for $ty {
            fn type_protocol() -> Typing<RustIdent> {
                Typing::Common(UniversalType::$branch(nz!($len)))
            }
        }
    };
}

pub trait ToTypeProtocol {
    fn type_protocol() -> Typing<RustIdent>;
}

impl_common!(bool, Bool);
impl_common!(u8, UInt, 1);
impl_common!(u16, UInt, 2);
impl_common!(u32, UInt, 4);
impl_common!(u64, UInt, 8);
impl_common!(u128, UInt, 16);
impl_common!(i8, Int, 1);
impl_common!(i16, Int, 2);
impl_common!(i32, Int, 4);
impl_common!(i64, Int, 8);
impl_common!(i128, Int, 16);
impl_common!(f32, Float, 4);
impl_common!(f64, Float, 8);
impl_common!(usize, USize);
impl_common!(isize, ISize);
impl_common!(char, Char);
impl_common!(String, String);

impl<T: ToTypeProtocol> ToTypeProtocol for Option<T> {
    fn type_protocol() -> Typing<RustIdent> {
        Typing::Option(T::type_protocol().boxed())
    }
}

impl<T: ToTypeProtocol, const N: usize> ToTypeProtocol for [T; N] {
    fn type_protocol() -> Typing<RustIdent> {
        Typing::Array(N, T::type_protocol().boxed())
    }
}

impl<T: ToTypeProtocol> ToTypeProtocol for Vec<T> {
    fn type_protocol() -> Typing<RustIdent> {
        Typing::Vec(T::type_protocol().boxed())
    }
}

impl<T: ToTypeProtocol> ToTypeProtocol for HashSet<T> {
    fn type_protocol() -> Typing<RustIdent> {
        Typing::Set(T::type_protocol().boxed())
    }
}

impl<T: ToTypeProtocol> ToTypeProtocol for BTreeSet<T> {
    fn type_protocol() -> Typing<RustIdent> {
        Typing::Set(T::type_protocol().boxed())
    }
}

impl<A: ToTypeProtocol, B: ToTypeProtocol> ToTypeProtocol for HashMap<A, B> {
    fn type_protocol() -> Typing<RustIdent> {
        Typing::Map(A::type_protocol().boxed(), B::type_protocol().boxed())
    }
}

impl<A: ToTypeProtocol, B: ToTypeProtocol> ToTypeProtocol for BTreeMap<A, B> {
    fn type_protocol() -> Typing<RustIdent> {
        Typing::Map(A::type_protocol().boxed(), B::type_protocol().boxed())
    }
}