pub const MAX_INLINE_STRING: usize = 23;
pub const MAX_INLINE_BYTES: usize = 23;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct DxInlineString {
data: [u8; 24],
}
impl DxInlineString {
pub const HEAP_MARKER: u8 = 255;
#[inline(always)]
pub const fn new() -> Self {
Self { data: [0; 24] }
}
#[inline]
pub fn from_str(s: &str) -> Option<Self> {
Self::from_bytes(s.as_bytes())
}
#[inline]
pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
if bytes.len() > MAX_INLINE_BYTES {
return None;
}
let mut result = Self::new();
result.data[..bytes.len()].copy_from_slice(bytes);
result.data[23] = bytes.len() as u8;
Some(result)
}
#[inline]
pub fn from_heap(ptr: u64, len: u32) -> Self {
let mut result = Self::new();
result.data[0..8].copy_from_slice(&ptr.to_le_bytes());
result.data[8..12].copy_from_slice(&len.to_le_bytes());
result.data[23] = Self::HEAP_MARKER;
result
}
#[inline(always)]
pub const fn is_inline(&self) -> bool {
self.data[23] != Self::HEAP_MARKER
}
#[inline(always)]
pub const fn is_heap(&self) -> bool {
self.data[23] == Self::HEAP_MARKER
}
#[inline(always)]
pub const fn inline_len(&self) -> usize {
debug_assert!(self.is_inline());
self.data[23] as usize
}
#[inline(always)]
pub fn heap_ptr(&self) -> u64 {
debug_assert!(self.is_heap());
u64::from_le_bytes([
self.data[0],
self.data[1],
self.data[2],
self.data[3],
self.data[4],
self.data[5],
self.data[6],
self.data[7],
])
}
#[inline(always)]
pub fn heap_len(&self) -> u32 {
debug_assert!(self.is_heap());
u32::from_le_bytes([self.data[8], self.data[9], self.data[10], self.data[11]])
}
#[inline(always)]
pub fn as_inline_str(&self) -> Option<&str> {
if !self.is_inline() {
return None;
}
let len = self.inline_len();
unsafe { Some(core::str::from_utf8_unchecked(&self.data[..len])) }
}
#[inline(always)]
pub fn as_inline_bytes(&self) -> Option<&[u8]> {
if !self.is_inline() {
return None;
}
let len = self.inline_len();
Some(&self.data[..len])
}
#[inline]
pub fn as_str_with_heap<'a>(&'a self, heap: &'a [u8]) -> Option<&'a str> {
if self.is_inline() {
self.as_inline_str()
} else {
let ptr = self.heap_ptr() as usize;
let len = self.heap_len() as usize;
if ptr + len > heap.len() {
return None;
}
core::str::from_utf8(&heap[ptr..ptr + len]).ok()
}
}
#[inline]
pub fn eq_str(&self, other: &str) -> bool {
if let Some(s) = self.as_inline_str() {
s == other
} else {
false }
}
#[inline]
pub fn eq_inline(&self, other: &Self) -> bool {
if !self.is_inline() || !other.is_inline() {
return false;
}
self.data == other.data
}
}
impl Default for DxInlineString {
fn default() -> Self {
Self::new()
}
}
impl core::fmt::Debug for DxInlineString {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if self.is_inline() {
if let Some(s) = self.as_inline_str() {
write!(f, "DxInlineString::Inline({:?})", s)
} else {
write!(f, "DxInlineString::Inline(<invalid utf8>)")
}
} else {
write!(f, "DxInlineString::Heap(ptr={}, len={})", self.heap_ptr(), self.heap_len())
}
}
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct DxInlineBytes {
data: [u8; 24],
}
impl DxInlineBytes {
pub const HEAP_MARKER: u8 = 255;
#[inline(always)]
pub const fn new() -> Self {
Self { data: [0; 24] }
}
#[inline]
pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
if bytes.len() > MAX_INLINE_BYTES {
return None;
}
let mut result = Self::new();
result.data[..bytes.len()].copy_from_slice(bytes);
result.data[23] = bytes.len() as u8;
Some(result)
}
#[inline]
pub fn from_heap(ptr: u64, len: u32) -> Self {
let mut result = Self::new();
result.data[0..8].copy_from_slice(&ptr.to_le_bytes());
result.data[8..12].copy_from_slice(&len.to_le_bytes());
result.data[23] = Self::HEAP_MARKER;
result
}
#[inline(always)]
pub const fn is_inline(&self) -> bool {
self.data[23] != Self::HEAP_MARKER
}
#[inline(always)]
pub fn as_inline(&self) -> Option<&[u8]> {
if !self.is_inline() {
return None;
}
let len = self.data[23] as usize;
Some(&self.data[..len])
}
#[inline]
pub fn as_bytes_with_heap<'a>(&'a self, heap: &'a [u8]) -> Option<&'a [u8]> {
if self.is_inline() {
self.as_inline()
} else {
let ptr = u64::from_le_bytes([
self.data[0],
self.data[1],
self.data[2],
self.data[3],
self.data[4],
self.data[5],
self.data[6],
self.data[7],
]) as usize;
let len = u32::from_le_bytes([self.data[8], self.data[9], self.data[10], self.data[11]])
as usize;
if ptr + len > heap.len() {
return None;
}
Some(&heap[ptr..ptr + len])
}
}
}
impl Default for DxInlineBytes {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Default, Clone, Copy)]
pub struct InlineStats {
pub inline_count: usize,
pub heap_count: usize,
pub bytes_saved: usize,
}
impl InlineStats {
pub fn inline_percentage(&self) -> f64 {
let total = self.inline_count + self.heap_count;
if total == 0 {
return 100.0;
}
(self.inline_count as f64 / total as f64) * 100.0
}
}
pub fn collect_inline_stats(strings: &[&str]) -> InlineStats {
let mut stats = InlineStats::default();
for s in strings {
if s.len() <= MAX_INLINE_STRING {
stats.inline_count += 1;
stats.bytes_saved += 12usize.saturating_sub(s.len());
} else {
stats.heap_count += 1;
}
}
stats
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_inline_string_short() {
let s = DxInlineString::from_str("Hello").unwrap();
assert!(s.is_inline());
assert_eq!(s.as_inline_str(), Some("Hello"));
assert_eq!(s.inline_len(), 5);
}
#[test]
fn test_inline_string_max() {
let long = "12345678901234567890123"; let s = DxInlineString::from_str(long).unwrap();
assert!(s.is_inline());
assert_eq!(s.as_inline_str(), Some(long));
}
#[test]
fn test_inline_string_too_long() {
let too_long = "123456789012345678901234"; let s = DxInlineString::from_str(too_long);
assert!(s.is_none());
}
#[test]
fn test_inline_string_empty() {
let s = DxInlineString::from_str("").unwrap();
assert!(s.is_inline());
assert_eq!(s.as_inline_str(), Some(""));
assert_eq!(s.inline_len(), 0);
}
#[test]
fn test_heap_string() {
let s = DxInlineString::from_heap(1000, 50);
assert!(s.is_heap());
assert_eq!(s.heap_ptr(), 1000);
assert_eq!(s.heap_len(), 50);
}
#[test]
fn test_string_comparison() {
let s1 = DxInlineString::from_str("Test").unwrap();
let s2 = DxInlineString::from_str("Test").unwrap();
let s3 = DxInlineString::from_str("Other").unwrap();
assert!(s1.eq_str("Test"));
assert!(!s1.eq_str("Other"));
assert!(s1.eq_inline(&s2));
assert!(!s1.eq_inline(&s3));
}
#[test]
fn test_with_heap() {
let heap = b"This is the heap data for testing longer strings.";
let inline = DxInlineString::from_str("Short").unwrap();
assert_eq!(inline.as_str_with_heap(heap), Some("Short"));
let heap_ref = DxInlineString::from_heap(0, 10);
assert_eq!(heap_ref.as_str_with_heap(heap), Some("This is th"));
}
#[test]
fn test_inline_bytes() {
let bytes = DxInlineBytes::from_bytes(&[1, 2, 3, 4, 5]).unwrap();
assert!(bytes.is_inline());
assert_eq!(bytes.as_inline(), Some([1, 2, 3, 4, 5].as_slice()));
}
#[test]
fn test_inline_stats() {
let strings = vec![
"Hello",
"World",
"This is a much longer string that won't fit",
];
let stats = collect_inline_stats(&strings);
assert_eq!(stats.inline_count, 2);
assert_eq!(stats.heap_count, 1);
assert!(stats.inline_percentage() > 60.0);
}
#[test]
fn test_size() {
assert_eq!(core::mem::size_of::<DxInlineString>(), 24);
assert_eq!(core::mem::size_of::<DxInlineBytes>(), 24);
}
}