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 91 92
/*! # JavaString The JavaString uses short string optimizations and a lack of a "capacity" field to reduce struct size and heap fragmentation in certain cases. ## Features - Supports String API (very little at the moment but steadily growing) - Smaller size than standard string (16 vs 24 bytes on 64-bit platforms) - String interning for up to 15 bytes on 64-bit architectures (or 7 bytes on 32-bit) ## How it works Here's how it works: 1. We store `len`, the length of the string, and `data`, the pointer to the string itself. 2. We maintain the invariant that `data` is a valid pointer if and only if it points to something that's aligned to 2 bytes. 3. Now, any time we wanna read the string, we first check the lowest significance bit on `data`, and use that to see whether or not to dereference it. 4. Since `data` only uses one bit for its flag, we can use the entire lower order byte for length information when it's interned. We do this with a bitshift right. 5. When interning, we have `std::mem::size_of::<usize>() * 2 - 1` bytes of space. On x64, this is 15 bytes, and on 32-bit architectures, this is 7 bytes. */ #![allow(dead_code)] // #![cfg_attr(not(any(test, docs)), no_std)] extern crate alloc; pub mod raw_string; use core::ops::{Deref, DerefMut}; use raw_string::RawJavaString; /// JavaString uses short string optimizations and a lack of a "capacity" field /// to reduce struct size and heap fragmentation in certain cases. /// /// It allows for mutation, but not for growth without reallocation. pub struct JavaString { data: RawJavaString, } impl JavaString { /// Creates a new empty `JavaString`. /// /// Given that the `JavaString` is empty, this will not allocate any initial /// buffer. /// /// # Examples /// /// Basic usage: /// /// ``` /// # use java_string::*; /// let s = JavaString::new(); /// ``` pub const fn new() -> Self { Self { data: RawJavaString::new(), } } /// Creates a new empty `JavaString`. Included for API compatibility with standard /// `String` implementation. /// /// # Examples /// /// Basic usage: /// /// ``` /// let mut s = String::with_capacity(10); /// ``` pub const fn with_capacity(_len: usize) -> Self { Self::new() } } impl Deref for JavaString { type Target = str; fn deref(&self) -> &str { unsafe { std::str::from_utf8_unchecked(self.data.get_bytes()) } } } impl DerefMut for JavaString { fn deref_mut(&mut self) -> &mut str { unsafe { std::str::from_utf8_unchecked_mut(self.data.get_bytes_mut()) } } }