beef

Travis shield Crates.io version shield Crates.io license shield

Faster, more compact implementation of Cow.

Changelog - Documentation - Cargo - Repository

```rust use beef::Cow;

let borrowed: Cow = Cow::borrowed("Hello"); let owned: Cow = Cow::owned(String::from("World"));

assert_eq!( format!("{} {}!", borrowed, owned), "Hello World!", ); ```

There are two versions of Cow exposed by this crate:

Both versions are leaner than the std::borrow::Cow:

```rust use std::mem::size_of;

const WORD: usize = size_of::();

asserteq!(sizeof::>(), 4 * WORD); asserteq!(sizeof::>(), 3 * WORD); asserteq!(sizeof::>(), 2 * WORD); ```

How does it work?

The standard library Cow is an enum with two variants:

rust pub enum Cow<'a, B> where B: 'a + ToOwned + ?Sized, { Borrowed(&'a B), Owned(<B as ToOwned>::Owned), }

For the most common pairs of values - &str and String, or &[u8] and Vec<u8> - this means that the entire enum is 4 words wide:

```text Padding | v +-----------+-----------+-----------+-----------+ Borrowed: | Tag | Pointer | Length | XXXXXXXXX | +-----------+-----------+-----------+-----------+

      +-----------+-----------+-----------+-----------+

Owned: | Tag | Pointer | Length | Capacity | +-----------+-----------+-----------+-----------+ ```

Instead of being an enum with a tag, beef::Cow uses capacity to determine whether the value it's holding is owned (capacity is greater than 0), or borrowed (capacity is 0).

beef::lean::Cow goes even further and puts length and capacity on a single 64 word.

```text +-----------+-----------+-----------+ beef::Cow | Pointer | Length | Capacity? | +-----------+-----------+-----------+

             +-----------+-----------+

beef::lean::Cow | Pointer | Cap | Len | +-----------+-----------+ ```

Any owned Vec or String that has 0 capacity is effectively treated as a borrowed value. Since having no capacity means there is no actual allocation behind the pointer this is safe.

Benchmarks

cargo +nightly bench

Microbenchmarking obtaining a &str reference is rather flaky and you can have widely different results. In general the following seems to hold true:

running 9 tests test beef_as_ref ... bench: 57 ns/iter (+/- 15) test beef_create ... bench: 135 ns/iter (+/- 5) test beef_create_mixed ... bench: 659 ns/iter (+/- 52) test lean_beef_as_ref ... bench: 50 ns/iter (+/- 2) test lean_beef_create ... bench: 77 ns/iter (+/- 3) test lean_beef_create_mixed ... bench: 594 ns/iter (+/- 52) test std_as_ref ... bench: 70 ns/iter (+/- 6) test std_create ... bench: 142 ns/iter (+/- 7) test std_create_mixed ... bench: 663 ns/iter (+/- 32)

License

This crate is distributed under the terms of both the MIT license and the Apache License (Version 2.0). Choose whichever one works best for you.

See LICENSE-APACHE and LICENSE-MIT for details.