tuple_types/
lib.rs

1//! Library for getting the types of Tuple Elements.
2#![no_std]
3#![deny(unsafe_code, clippy::unwrap_used)]
4
5extern crate alloc;
6
7use core::any::{TypeId, type_name};
8use alloc::vec::Vec;
9
10/// Represents a Type, with it's [TypeId] and Name.
11#[derive(Debug, Clone, Copy, Eq, PartialEq)]
12pub struct Type{
13    pub id: TypeId,
14    pub name: &'static str
15}
16
17impl Type{
18    pub fn of<T: 'static>() -> Self{
19        Self{
20            id: TypeId::of::<T>(),
21            name: type_name::<T>()
22        }
23    }
24
25    pub fn of_val<T: 'static>(_: &T) -> Self{
26        Self{
27            id: TypeId::of::<T>(),
28            name: type_name::<T>()
29        }
30    }
31}
32
33/// Extension Trait that adds the [TupleExt::types],  [TupleExt::type_ids] and [TupleExt::type_names] functions along with methods with the prefix `self_`.
34pub trait TupleExt{
35    /// Returns the types that make up the tuple with [TupleExt] is implemented on.
36    fn types() -> Vec<crate::Type>;
37    /// Returns the [TypeId]s of the type with [TupleExt] is implemented on.
38    fn type_ids() -> Vec<core::any::TypeId>;
39    // Return the names of the types with [TupleExt] is implemented on as a Vector or `&'static str`s.
40    fn type_names() -> Vec<&'static str>;
41
42    /// Method version of [TupleExt::types].
43    fn self_types(&self) -> Vec<Type> { Self::types() }
44    /// Method version of [TupleExt::type_ids].
45    fn self_type_ids(&self) -> Vec<TypeId> { Self::type_ids() }
46    /// Method version of [TupleExt::type_names].
47    fn self_type_names(&self) -> Vec<&'static str> { Self::type_names() }
48}
49
50/// Internal Macro for implementing [TupleExt] on tuples.
51#[doc(hidden)]
52macro_rules! impl_tuple_ext{
53    [$($t:ident), *] => {
54        impl<$($t: 'static), *> TupleExt for ($($t),*,) {
55            fn types() -> Vec<crate::Type> { alloc::vec![$(crate::Type::of::<$t>()), *] }
56            fn type_ids() -> Vec<core::any::TypeId> { alloc::vec![$(core::any::TypeId::of::<$t>()), *] }
57            fn type_names() -> Vec<&'static str> { alloc::vec![$(core::any::type_name::<$t>()), *] }
58        }
59    }
60}
61
62impl TupleExt for () {
63    fn types() -> Vec<crate::Type> { alloc::vec![] }
64    fn type_ids() -> Vec<core::any::TypeId> { alloc::vec![] }
65    fn type_names() -> Vec<&'static str> { alloc::vec![] }
66}
67
68impl_tuple_ext![T1];
69impl_tuple_ext![T1, T2];
70impl_tuple_ext![T1, T2, T3];
71impl_tuple_ext![T1, T2, T3, T4];
72impl_tuple_ext![T1, T2, T3, T4, T5];
73impl_tuple_ext![T1, T2, T3, T4, T5, T6];
74impl_tuple_ext![T1, T2, T3, T4, T5, T6, T7];
75
76#[cfg(test)]
77#[allow(dead_code)]
78mod tests {
79    use alloc::string::ToString as _;
80
81    use super::*;
82
83    #[test]
84    fn test_type_of() {
85        assert_eq!(Type::of::<i32>().name, "i32");
86        assert_eq!(Type::of_val(&"hello".to_string()).name, "alloc::string::String");
87    }
88
89    #[test]
90    fn test_tuple_ext() {
91        let tuple = (1, 2.0, 3, 4, "test", 6, -8);
92        assert_eq!(tuple.self_types().len(), 7);
93        assert_eq!(tuple.self_type_ids().len(), 7);
94        assert_eq!(tuple.self_type_names().len(), 7);
95    }
96
97    #[test]
98    fn test_tuple_ext_different_types() {
99        let tuple = (1, "hello", 3.14, true);
100        let types = tuple.self_types();
101        let type_names: Vec<&str> = types.iter().map(|t| t.name).collect();
102        let type_ids: Vec<TypeId> = types.iter().map(|t| t.id).collect();
103
104        assert_eq!(types.len(), 4);
105        assert_eq!(type_names, alloc::vec!["i32", "&str", "f64", "bool"]);
106        assert_eq!(type_ids.len(), 4);
107    }
108
109    #[test]
110    fn test_type_of_struct() {
111        #[derive(Debug)]
112        struct Person {
113            name: alloc::string::String,
114            age: u8,
115        }
116
117        let person: Person = Person {
118            name: "Proton".to_string(),
119            age: 14,
120        };
121
122        assert!(Type::of_val(&person).name.ends_with("test_type_of_struct::Person"));
123    }
124}
125