Module bytes_utils::string

source ·
Expand description

String-like wrappers around Bytes and BytesMut.

The Bytes and BytesMut provide a buffer of bytes with ability to create owned slices into the same shared memory allocation. This allows cheap manipulation of data.

Strings are mostly just byte buffers with extra APIs to manipulate them. The standard String type is built as a wrapper around Vec. We build similar wrappers around the Bytes and BytesMut, gaining the ability to create owned shared slices for textual data as well.

Users are expected to use the Str and StrMut types. Note that these are type aliases around the StrInner type. The latter is means to implement both in one go and contains all the documentation, but is not meant to be used directly.

Splitting

The str type from standard library (which the types here dereference to) allows for slicing and splitting in many convenient ways. They, however, return borrowed string slices (&str), which might pose some problems.

The Str, and to certain extent, the StrMut type additionally allow cheap splitting and slicing that produce owned Str and StrMut respectively. They are slightly more expensive than the slicing than the ones returning &str, but only by incrementing internal reference counts. They do not clone the actual string data, like .to_owned() on the standard library methods would. These methods are available in addition to the standard ones.

There are three ways how this can be done:

  • By dedicated methods, like lines_bytes (in general, the name of the standard method suffixed with _bytes).
  • By using the BytesIter iterator manually.
  • By using the standard-library methods, producing &str and translating it back to Str with slice or StrInner::slice_ref.

Examples

let mut builder = StrMut::new();
builder += "Hello";
builder.push(' ');
builder.push_str("World");
assert_eq!("Hello World", builder);

let s1 = builder.split_built().freeze();
// This is a cheap copy, in the form of incrementing a reference count.
let s2 = s1.clone();
assert_eq!("Hello World", s1);
assert_eq!("Hello World", s2);
// Slicing is cheap as well, even though the returned things are Str and therefore owned too.
assert_eq!("ello", s1.slice(1..5));
// We have taken the data out of the builder, but the rest of its capacity can be used for
// further things.
assert_eq!("", builder);

// Creating from strings and similar works
let a = Str::from("Hello");
assert_eq!("Hello", a);

let e = Str::new();
assert_eq!("", e);

// And from static str in O(1)
let b = Str::from_static("World");
assert_eq!("World", b);

// And from Bytes too.
let b = Str::try_from(Bytes::from_static(b"World")).expect("Must be utf8");
assert_eq!("World", b);
// Invalid utf8 is refused.
Str::try_from(Bytes::from_static(&[0, 0, 255])).unwrap_err();

Structs

Enums

Traits

Type Aliases