Skip to main content

lite_strtab/types/
string_index.rs

1//! Backing integer types for [`crate::StringId`].
2//!
3//! [`crate::StringId`] is the semantic handle used by the API, while
4//! [`StringIndex`] defines which integer types can store its raw value.
5//! Smaller types reduce memory per ID; larger types increase maximum string
6//! count.
7//!
8//! Default [`u16`] supports up to 65_536 strings per table.
9
10use core::fmt::{Debug, Display};
11
12/// Contract for integer types used by [`crate::StringId`].
13///
14/// [`Self::try_from_usize`] is used at build and validation boundaries where
15/// counts are computed as [`usize`]. [`Self::to_usize`] is used on lookup paths
16/// for infallible indexing.
17///
18/// This trait is sealed and only implemented for unsigned integers that fit in
19/// [`usize`] on the current target.
20pub trait StringIndex:
21    private::Sealed + Copy + Eq + Ord + Debug + Display + Send + Sync + 'static
22{
23    /// Human-readable type name.
24    const TYPE_NAME: &'static str;
25
26    /// Converts a string index into this type.
27    fn try_from_usize(value: usize) -> Option<Self>;
28
29    /// Converts this index to [`usize`].
30    fn to_usize(self) -> usize;
31}
32
33/// Macro pattern:
34/// - `$($ty:ty),+` - One or more comma-separated types
35/// - `$(,)?` - Optional trailing comma
36/// - `$( ... )+` wrapper repeats the inner block for each type
37macro_rules! impl_string_index {
38    ($($ty:ty),+ $(,)?) => {
39        $(
40            impl StringIndex for $ty {
41                const TYPE_NAME: &'static str = stringify!($ty);
42
43                #[inline]
44                fn try_from_usize(value: usize) -> Option<Self> {
45                    <Self as core::convert::TryFrom<usize>>::try_from(value).ok()
46                }
47
48                #[inline]
49                fn to_usize(self) -> usize {
50                    self as usize
51                }
52            }
53        )+
54    };
55}
56
57#[cfg(target_pointer_width = "64")]
58impl_string_index!(u8, u16, u32, u64, usize);
59
60#[cfg(target_pointer_width = "32")]
61impl_string_index!(u8, u16, u32, usize);
62
63#[cfg(target_pointer_width = "16")]
64impl_string_index!(u8, u16, usize);
65
66// Supported pointer widths for this crate.
67#[cfg(not(any(
68    target_pointer_width = "16",
69    target_pointer_width = "32",
70    target_pointer_width = "64"
71)))]
72compile_error!("lite-strtab requires a 16-bit, 32-bit, or 64-bit target");
73
74// Seal the trait so only this crate can define valid implementations.
75mod private {
76    pub trait Sealed {}
77
78    macro_rules! impl_sealed {
79        ($($ty:ty),+ $(,)?) => {
80            $(
81                impl Sealed for $ty {}
82            )+
83        };
84    }
85
86    #[cfg(target_pointer_width = "64")]
87    impl_sealed!(u8, u16, u32, u64, usize);
88
89    #[cfg(target_pointer_width = "32")]
90    impl_sealed!(u8, u16, u32, usize);
91
92    #[cfg(target_pointer_width = "16")]
93    impl_sealed!(u8, u16, usize);
94}