Skip to main content

lite_strtab/types/
offset.rs

1//! Backing integer types for byte offsets in [`crate::StringTable`].
2//!
3//! Offsets index into the contiguous UTF-8 byte buffer and include a final
4//! sentinel equal to the total byte length. The chosen [`Offset`] type
5//! controls offset-table memory use and maximum total byte size.
6//!
7//! Default [`u32`] supports up to 4 GiB of string bytes.
8
9use core::fmt::Debug;
10
11/// Contract for integer types used as byte offsets.
12///
13/// Unlike [`crate::StringIndex`] (which bounds string count), [`Offset`]
14/// bounds total UTF-8 byte size. Builders and validators use
15/// [`Self::try_from_usize`] for checked growth, while lookup code uses
16/// [`Self::to_usize`] for infallible slicing.
17///
18/// This trait is sealed and only implemented for unsigned integers that fit in
19/// [`usize`] on the current target.
20pub trait Offset: private::Sealed + Copy + Eq + Ord + Debug + Send + Sync + 'static {
21    /// Human-readable type name.
22    const TYPE_NAME: &'static str;
23
24    /// Converts a byte length/offset into this type.
25    fn try_from_usize(value: usize) -> Option<Self>;
26
27    /// Converts this offset to [`usize`].
28    fn to_usize(self) -> usize;
29}
30
31macro_rules! impl_offset {
32    ($($ty:ty),+ $(,)?) => {
33        $(
34            impl Offset for $ty {
35                const TYPE_NAME: &'static str = stringify!($ty);
36
37                #[inline]
38                fn try_from_usize(value: usize) -> Option<Self> {
39                    <Self as core::convert::TryFrom<usize>>::try_from(value).ok()
40                }
41
42                #[inline]
43                fn to_usize(self) -> usize {
44                    self as usize
45                }
46            }
47        )+
48    };
49}
50
51#[cfg(target_pointer_width = "64")]
52impl_offset!(u8, u16, u32, u64, usize);
53
54#[cfg(target_pointer_width = "32")]
55impl_offset!(u8, u16, u32, usize);
56
57#[cfg(target_pointer_width = "16")]
58impl_offset!(u8, u16, usize);
59
60// Supported pointer widths for this crate.
61#[cfg(not(any(
62    target_pointer_width = "16",
63    target_pointer_width = "32",
64    target_pointer_width = "64"
65)))]
66compile_error!("lite-strtab requires a 16-bit, 32-bit, or 64-bit target");
67
68// Seal the trait so only this crate can define valid implementations.
69mod private {
70    pub trait Sealed {}
71
72    macro_rules! impl_sealed {
73        ($($ty:ty),+ $(,)?) => {
74            $(
75                impl Sealed for $ty {}
76            )+
77        };
78    }
79
80    #[cfg(target_pointer_width = "64")]
81    impl_sealed!(u8, u16, u32, u64, usize);
82
83    #[cfg(target_pointer_width = "32")]
84    impl_sealed!(u8, u16, u32, usize);
85
86    #[cfg(target_pointer_width = "16")]
87    impl_sealed!(u8, u16, usize);
88}