cgp_field/types/
char.rs

1use core::fmt::Display;
2use core::marker::PhantomData;
3
4/**
5    The `Char` type, a.k.a. `ι`, is used to represent _type-level_ list of
6    `char`s, which are equivalent to type-level strings.
7
8    `Char` is a specialized version of [`Cons`](crate::types::Cons), with the
9    `Head` type being fixed to a _const-generic_ value of type `char`.
10    Similar to `Cons`, `Char` is also parameterized by a `Tail` type, which is
11    expected to be either the next `Char`, or [`Nil`](crate::types::Nil) to
12    represent the end of the string.
13
14    Instead of reusing `Cons`, we combine the use of `Cons` within `Char` so
15    that its representation is more compact when shown in compiler error messages.
16    Similar to `Cons`, `Char` is also shown as `ι` to further improve its
17    readability.
18
19    We represent type-level strings as list of `Char`s, because it is currently
20    not possible to use types like `String` or `&str` as const-generic parameters.
21    On the other hand, a single `char` can be used as a const-generic parameter,
22    and so we can workaround the limitation by combining a type-level list of
23    `char`s to represent a type-level string.
24
25    `Char` is most often not used directly, but rather through the `symbol!` macro,
26    which accepts a string literal and converts it into a list of `Char`s.
27
28    ## Example
29
30    Given the following symbol definition:
31
32    ```rust,ignore
33    type Hello = symbol!("hello");
34    ```
35
36    The following type would be generated:
37
38    ```rust,ignore
39    type Hello = Char<'h', Char<'e', Char<'l', Char<'l', Char<'o', Nil>>>>>;
40    ```
41
42    which would be shown with the shortened representation as:
43
44    ```rust,ignore
45    type Hello = ι<'h', ι<'e', ι<'l', ι<'l', ι<'o', ε>>>>>;
46    ```
47*/
48#[derive(Eq, PartialEq, Clone, Copy, Default)]
49pub struct ι<const CHAR: char, Tail>(pub PhantomData<Tail>);
50
51pub use ι as Char;
52
53use crate::StaticFormat;
54
55impl<const CHAR: char, Tail> Display for Char<CHAR, Tail>
56where
57    Self: StaticFormat,
58{
59    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
60        <Self as StaticFormat>::fmt(f)
61    }
62}
63
64impl<const CHAR: char, Tail> StaticFormat for Char<CHAR, Tail>
65where
66    Tail: StaticFormat,
67{
68    fn fmt(f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
69        write!(f, "{CHAR}")?;
70        Tail::fmt(f)
71    }
72}