1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
//! Convert strings to types to make it available as generic parameters.
//!
//! # Example
//!
//! ```
//! use stringz::{TypedString, string};
//!
//! fn test_hello<T: TypedString>() {
//!     assert_eq!(T::value(), "hello");
//! }
//!
//! test_hello::<string!("hello")>();
//! ```
//!
//! # Explanation
//!
//! The [`string`] macro converts `"hello"` to the following tuple type:
//!
//! ```text
//! (Character<'h'>, Character<'e'>, Character<'l'>, Character<'l'>, Character<'o'>)
//! ```
//!
//! Note: The above form is only for ease of understanding, the actual [`Tuple`] type of
//! [tuplez](https://docs.rs/tuplez) is used.
//! 
//! All generated types are zero-sized types:
//! 
//! ```
//! use stringz::string;
//! assert_eq!(std::mem::size_of::<string!("no matter how long it is")>(), 0);
//! ```

/// Convert a string to a type, the input must be a string literal.
///
/// # Example
///
/// ```
/// use stringz::{TypedString, string};
///
/// fn test_hello<T: TypedString>() {
///     assert_eq!(T::value(), "hello");
/// }
///
/// test_hello::<string!("hello")>();
/// ```
pub use stringz_macros::string;

/// Convert a string to a type, the input must be an identifier.
///
/// # Example
///
/// ```
/// use stringz::{TypedString, ident};
///
/// fn test_hello<T: TypedString>() {
///     assert_eq!(T::value(), "hello");
/// }
///
/// test_hello::<ident!(hello)>();
/// ```
pub use stringz_macros::ident;

use tuplez::{Tuple, Unit};

extern crate self as stringz;

/// Single `char` type value representation.
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Character<const C: char>;

/// Get original string from typed string.
pub trait TypedString {
    /// The original string.
    fn value() -> String;
}

impl<const C: char> TypedString for Tuple<Character<C>, Unit> {
    fn value() -> String {
        C.to_string()
    }
}

impl<const C: char, Other> TypedString for Tuple<Character<C>, Other>
where
    Other: TypedString,
{
    fn value() -> String {
        format!("{}{}", C, Other::value())
    }
}