pub union SmallBytes {
/* private fields */
}Expand description
A 24-byte owned byte string with inline small-string optimization.
Strings of up to 22 bytes live entirely inside the value (no allocation, no pointer chase); larger strings spill to a heap buffer. The discriminator is a single byte at offset 23 (the tag, which doubles as the inline length 0..=22 OR equals 0xFF when the heap variant is active).
See the crate root for layout details.
§Examples
Short values live inline; longer ones move to the heap. The API does not
change, but heap_bytes reports which happened, which is what the
keyspace’s memory accounting reads.
use kevy_bytes::SmallBytes;
let short = SmallBytes::from_slice(b"hello");
assert_eq!(short.as_slice(), b"hello");
assert_eq!(short.len(), 5);
assert_eq!(short.heap_bytes(), 0, "a short value allocates nothing");
let long = SmallBytes::from_slice(&[b'x'; 100]);
assert_eq!(long.len(), 100);
assert!(long.heap_bytes() >= 100, "a long value is on the heap");use kevy_bytes::SmallBytes;
assert!(SmallBytes::from_slice(b"").is_empty());Implementations§
Source§impl SmallBytes
impl SmallBytes
Sourcepub const fn new() -> Self
pub const fn new() -> Self
Empty inline SmallBytes (zero allocation).
§Examples
const, so it can seed a static or an array without a run-time
initialiser:
use kevy_bytes::SmallBytes;
static EMPTY: SmallBytes = SmallBytes::new();
assert!(EMPTY.is_empty());
assert_eq!(EMPTY.heap_bytes(), 0);Sourcepub fn from_slice(bytes: &[u8]) -> Self
pub fn from_slice(bytes: &[u8]) -> Self
Construct from a byte slice — inline if bytes.len() <= 22, else heap.
§Examples
Twenty-two is the boundary, and it is exact:
use kevy_bytes::SmallBytes;
assert_eq!(SmallBytes::from_slice(&[b'x'; 22]).heap_bytes(), 0);
assert_eq!(SmallBytes::from_slice(&[b'x'; 23]).heap_bytes(), 23);Sourcepub fn from_vec(vec: Vec<u8>) -> Self
pub fn from_vec(vec: Vec<u8>) -> Self
Take ownership of a Vec<u8> — inline if vec.len() <= 22, else reuse
the vec’s allocation (no copy on the heap path).
§Examples
The heap path keeps the vec’s own buffer, so a value that arrived as
a Vec is stored without a second copy:
use kevy_bytes::SmallBytes;
let v = vec![b'z'; 64];
let addr = v.as_ptr();
let b = SmallBytes::from_vec(v);
assert_eq!(b.as_slice().as_ptr(), addr, "same allocation, not a copy");A short vec goes inline instead, and its allocation is released:
use kevy_bytes::SmallBytes;
assert_eq!(SmallBytes::from_vec(vec![b'a'; 4]).heap_bytes(), 0);Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Number of bytes stored.
§Examples
The same answer either side of the inline boundary — which is the point of the type: where the bytes live is not the caller’s problem.
use kevy_bytes::SmallBytes;
assert_eq!(SmallBytes::from_slice(&[0u8; 22]).len(), 22);
assert_eq!(SmallBytes::from_slice(&[0u8; 23]).len(), 23);Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Whether len() == 0.
§Examples
use kevy_bytes::SmallBytes;
assert!(SmallBytes::from_slice(b"").is_empty());
assert!(!SmallBytes::from_slice(b"\0").is_empty(), "a NUL byte is a byte");Sourcepub fn heap_bytes(&self) -> usize
pub fn heap_bytes(&self) -> usize
Bytes this value holds on the heap (0 when inline). Lets memory-accounting
callers (e.g. maxmemory enforcement) charge only the off-stack footprint
without re-deriving the inline-length threshold.
§Examples
This is what maxmemory charges, so an inline value must cost zero
— it is already inside the entry the keyspace has counted:
use kevy_bytes::SmallBytes;
assert_eq!(SmallBytes::from_slice(b"user:1").heap_bytes(), 0);
assert_eq!(SmallBytes::from_slice(&[b'x'; 1000]).heap_bytes(), 1000);Sourcepub fn as_slice(&self) -> &[u8] ⓘ
pub fn as_slice(&self) -> &[u8] ⓘ
Borrow the bytes (no allocation; same for inline and heap variants).
§Examples
use kevy_bytes::SmallBytes;
let b = SmallBytes::from_slice(b"GET");
assert_eq!(b.as_slice(), b"GET");
assert_eq!(SmallBytes::new().as_slice(), b"");Sourcepub fn to_vec(&self) -> Vec<u8> ⓘ
pub fn to_vec(&self) -> Vec<u8> ⓘ
Copy into a fresh Vec<u8> (clone semantics).
§Examples
use kevy_bytes::SmallBytes;
let b = SmallBytes::from_slice(b"copy me");
assert_eq!(b.to_vec(), b"copy me");
assert_eq!(b.as_slice(), b"copy me", "the original still holds them");Sourcepub fn into_vec(self) -> Vec<u8> ⓘ
pub fn into_vec(self) -> Vec<u8> ⓘ
Consume self and return an owned Vec<u8>. The heap path reuses the
existing allocation; the inline path copies into a new vec.
§Examples
A heap value hands its buffer straight back, so a round trip through
SmallBytes costs no allocation at either end:
use kevy_bytes::SmallBytes;
let v = vec![b'q'; 128];
let addr = v.as_ptr();
assert_eq!(SmallBytes::from_vec(v).into_vec().as_ptr(), addr);use kevy_bytes::SmallBytes;
assert_eq!(SmallBytes::from_slice(b"short").into_vec(), b"short");Trait Implementations§
Source§impl AsRef<[u8]> for SmallBytes
impl AsRef<[u8]> for SmallBytes
Source§impl Borrow<[u8]> for SmallBytes
impl Borrow<[u8]> for SmallBytes
Source§impl Clone for SmallBytes
impl Clone for SmallBytes
Source§fn clone(&self) -> Self
fn clone(&self) -> Self
Specialised clone that bypasses as_slice → from_slice → alloc_heap’s
two layered length checks. Inline variant is a bitwise union copy (no
branch through the slice path); heap variant goes straight to a single
alloc + memcpy keyed on the already-known heap length.
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for SmallBytes
impl Debug for SmallBytes
Source§impl Default for SmallBytes
impl Default for SmallBytes
Source§impl Drop for SmallBytes
impl Drop for SmallBytes
impl Eq for SmallBytes
Source§impl From<&[u8]> for SmallBytes
impl From<&[u8]> for SmallBytes
Source§impl Hash for SmallBytes
impl Hash for SmallBytes
Source§impl KevyHash for SmallBytes
KevyHash agrees with the byte-slice impl, so a KevyMap<SmallBytes, V>
can be queried with &[u8] (via Borrow<[u8]>) and the hash matches.
impl KevyHash for SmallBytes
KevyHash agrees with the byte-slice impl, so a KevyMap<SmallBytes, V>
can be queried with &[u8] (via Borrow<[u8]>) and the hash matches.
Source§impl Ord for SmallBytes
impl Ord for SmallBytes
1.21.0 (const: unstable) · Source§fn max(self, other: Self) -> Selfwhere
Self: Sized,
fn max(self, other: Self) -> Selfwhere
Self: Sized,
1.21.0 (const: unstable) · Source§fn min(self, other: Self) -> Selfwhere
Self: Sized,
fn min(self, other: Self) -> Selfwhere
Self: Sized,
Source§impl PartialEq for SmallBytes
impl PartialEq for SmallBytes
Source§fn eq(&self, other: &Self) -> bool
fn eq(&self, other: &Self) -> bool
Specialised over the slice form (as_slice == as_slice) by branching
on variant once and reading the relevant length / pointer pair
directly. Same-variant cases (inline/inline + heap/heap, which are the
only ones produced by a single allocator) skip a redundant as_slice
dispatch on each side; the mixed case falls back to the slice form.