Skip to main content

SmallBytes

Union SmallBytes 

Source
pub union SmallBytes {
    /* private fields */
}
Expand description

A 24-byte owned byte string with inline small-string optimization.

Strings of up to 23 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

Source

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);
Source

pub fn from_slice(bytes: &[u8]) -> Self

Construct from a byte slice — inline if bytes.len() <= 23, else heap.

§Examples

Twenty-three is the boundary, and it is exact:

use kevy_bytes::SmallBytes;
assert_eq!(SmallBytes::from_slice(&[b'x'; 23]).heap_bytes(), 0);
assert_eq!(SmallBytes::from_slice(&[b'x'; 24]).heap_bytes(), 24);
Source

pub fn from_vec(vec: Vec<u8>) -> Self

Take ownership of a Vec<u8> — inline if vec.len() <= 23, 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);
Source

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);
Source

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");
Source

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.

This is the allocation, not the live length, and those differ: Self::from_vec adopts its argument’s buffer as it stands, so a Vec grown by extend_from_slice arrives with the doubling ladder’s slack still on it. Reporting len charged 360 bytes for a 640-byte allocation on the eleventh APPEND to one key — and maxmemory is what this number feeds, so the server could sit at 1.8x its bound without evicting.

§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);
// `from_slice` allocates exactly, so here the two agree.
assert_eq!(SmallBytes::from_slice(&[b'x'; 1000]).heap_bytes(), 1000);

// A buffer with slack does not, and the slack is real memory.
let mut v = Vec::with_capacity(4096);
v.extend_from_slice(&[b'x'; 1000]);
assert_eq!(SmallBytes::from_vec(v).heap_bytes(), 4096);
Source

pub fn heap_bytes_for(bytes: &[u8]) -> usize

Heap bytes a SmallBytes built from bytes would own.

The same rule as Self::heap_bytes, answerable without building the value — for accounting a key by its slice before it is stored. Exists so the inline threshold is not copied out of this crate: it was, as the literal 22, and any change to the boundary would have silently mis-charged every key with nothing failing.

§Examples
use kevy_bytes::SmallBytes;
assert_eq!(SmallBytes::heap_bytes_for(b"user:1"), 0);
assert_eq!(SmallBytes::heap_bytes_for(&[b'x'; 1000]), 1000);
Source

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"");
Source

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");
Source

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

Source§

fn as_ref(&self) -> &[u8]

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl Borrow<[u8]> for SmallBytes

Source§

fn borrow(&self) -> &[u8]

Immutably borrows from an owned value. Read more
Source§

impl Clone for SmallBytes

Source§

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)

Performs copy-assignment from source. Read more
Source§

impl Debug for SmallBytes

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for SmallBytes

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl Drop for SmallBytes

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more
Source§

impl Eq for SmallBytes

Source§

impl From<&[u8]> for SmallBytes

Source§

fn from(bytes: &[u8]) -> Self

Converts to this type from the input type.
Source§

impl From<Vec<u8>> for SmallBytes

Source§

fn from(vec: Vec<u8>) -> Self

Converts to this type from the input type.
Source§

impl Hash for SmallBytes

Source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
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.

Source§

fn kevy_hash(&self) -> u64

Compute the final mixed 64-bit hash of self in one call.
Source§

impl Ord for SmallBytes

Source§

fn cmp(&self, other: &Self) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 (const: unstable) · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 (const: unstable) · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 (const: unstable) · Source§

fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized,

Restrict a value to a certain interval. Read more
Source§

fn clamp_to<R>(self, range: R) -> Self
where Self: Sized, R: ClampBounds<Self>,

🔬This is a nightly-only experimental API. (clamp_to)
Restrict a value to a certain range. Read more
Source§

impl PartialEq for SmallBytes

Source§

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.

1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl PartialOrd for SmallBytes

Source§

fn partial_cmp(&self, other: &Self) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 (const: unstable) · Source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 (const: unstable) · Source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 (const: unstable) · Source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 (const: unstable) · Source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Source§

impl Send for SmallBytes

Source§

impl Sync for SmallBytes

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.