jstring/lib.rs
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()) }
}
}