hipstr 0.3.2

Yet another string for Rust: zero-cost borrow and slicing, inline representation for small strings, (atomic) reference counting
Documentation
# `hipstr`


[![Rust](https://github.com/polazarus/hipstr/actions/workflows/basic.yml/badge.svg)](https://github.com/polazarus/hipstr/actions/workflows/basic.yml)
[![Clippy](https://github.com/polazarus/hipstr/actions/workflows/clippy.yml/badge.svg)](https://github.com/polazarus/hipstr/actions/workflows/clippy.yml)
[![Miri](https://github.com/polazarus/hipstr/actions/workflows/miri.yml/badge.svg)](https://github.com/polazarus/hipstr/actions/workflows/miri.yml)
[![codecov](https://codecov.io/gh/polazarus/hipstr/branch/main/graph/badge.svg?token=Z7YUHB4YUD)](https://codecov.io/gh/polazarus/hipstr)
[![Docs](https://img.shields.io/docsrs/hipstr)](https://docs.rs/hipstr)
![MIT OR Apache-2.0](https://img.shields.io/crates/l/hipstr)

Yet another string for Rust ๐Ÿฆ€

* no copy **borrow** via `borrowed` (a `const` constructor) or `from_static`
* no alloc **small strings** (_23 bytes_ on 64-bit platform)
* no copy **owned slices**
* **zero dependency**

And **bytes** too!

## โšก Examples


```rust
use hipstr::HipStr;

let simple_greetings = HipStr::from_static("Hello world");
let _clone = simple_greetings.clone(); // no copy

let user = "John";
let greetings = HipStr::from(format!("Hello {}", user));
let _user = greetings.slice(6..): // no copy
```

## โœ๏ธ Features


* `serde`: provides serialization/deserialization support with `serde` crate
* `unstable`: exposes internal `Backend` trait that may change at any moment

## โ˜ฃ๏ธ Safety of `hipstr`


This crate uses `unsafe` extensively. ๐Ÿคท

It exploits the 1-bit alignment niche in pointers existing on most platforms
(I think all Rustc supported platforms) to distinguish the inline representation
from the other representations.

To make things safer, Rust is tested thoroughly on multiple platforms, normally
and with [Miri] (the MIR interpreter).

## ๐Ÿงช Testing


### โ˜” Coverage


This crate has **near full line coverage**:

```bash
cargo llvm-cov --all-features --html
# or

cargo tarpaulin --all-features --out html --engine llvm
```

Check out the current coverage on [Codecov]:

![Coverage grid](https://codecov.io/gh/polazarus/hipstr/branch/main/graphs/tree.svg?token=Z7YUHB4YUD)

### ๐Ÿ–ฅ๏ธ Cross-platform testing


You can easily run the test on various platforms with [`cross`]:

```bash
cross test --target mips-unknown-linux-gnu          # 32-bit BE
cross test --target mips64-unknown-linux-gnuabi64   # 64-bit BE
cross test --target i686-unknown-linux-gnu          # 32-bit LE
cross test --target x86_64-unknown-linux-gnu        # 64-bit LE
```

### ๐Ÿ” [Miri]


This crate runs successfully with Miri:

```bash
MIRIFLAGS=-Zmiri-symbolic-alignment-check cargo +nightly miri test

for SEED in $(seq 0 10); do
  echo "Trying seed: $SEED"
  MIRIFLAGS="-Zmiri-seed=$SEED" cargo +nightly miri test || { echo "Failing seed: $SEED"; break; };
done
```

To check with different word size and endianness:

```bash
# Big endian, 64-bit

cargo +nightly miri test --target mips64-unknown-linux-gnuabi64
# Little endian, 32-bit

cargo +nightly miri test --target i686-unknown-linux-gnu
```

[Codecov]: https://app.codecov.io/gh/polazarus/hipstr
[`cross`]: https://github.com/cross-rs/cross
[Miri]: https://github.com/rust-lang/miri

## ๐Ÿ“ฆ Similar crates


`#[non_exhaustive]`

| Name | Thread-safe cheap-clone | Local cheap-clone | Inline | Cheap slice  | Bytes | Cow<'a>  | Comment |
| ---- | ----------- | ----- | ------ | ------ | ----- | ---- | :------ |
| `hipstr` | ๐ŸŸข | ๐ŸŸข | ๐ŸŸข | ๐ŸŸข | ๐ŸŸข | ๐ŸŸข | obviously!
| [`arcstr`]https://github.com/thomcc/arcstr | ๐ŸŸข* | โŒ | โŒ | โŒ** | โŒ | โŒ | *use a custom thin `Arc`, **heavy slice (with dedicated substring type) |
| [`flexstr`]https://github.com/nu11ptr/flexstr | ๐ŸŸข* | ๐ŸŸข | ๐ŸŸข | โŒ |  โŒ | โŒ | *use an `Arc<str>` instead of an `Arc<String>` (remove one level of  indirection but use fat pointers) |
| [`imstr`]https://github.com/xfbs/imstr | ๐ŸŸข | ๐ŸŸข | โŒ | ๐ŸŸข | โŒ | โŒ | |
| [`faststr`]https://github.com/volo-rs/faststr | ๐ŸŸข | โŒ | ๐ŸŸข | ๐ŸŸข | โŒ | โŒ | zero-doc with complex API |
| [`fast-str`]https://github.com/xxXyh1908/rust-fast-str | ๐ŸŸข | โŒ | ๐ŸŸข | ๐ŸŸข | โŒ | โŒ | inline repr is opt-in |
| [`ecow`]https://github.com/typst/ecow | ๐ŸŸข* | โŒ | ๐ŸŸข | โŒ | ๐ŸŸข** | โŒ | *on two words only ๐Ÿคค, **even any `T`
| [`cowstr`]https://git.pipapo.org/cehteh/cowstr.git | ๐ŸŸข | โŒ | โŒ | โŒ* | โŒ | โŒ** | *heavy slice, **contrary to its name |
| [`compact_str`]https://github.com/parkmycar/compact_str | โŒ | โŒ | ๐ŸŸข | โŒ | ๐ŸŸข* | โŒ | *opt-in via `smallvec` |
| [`inline_string`]https://github.com/fitzgen/inlinable_string | โŒ | โŒ | ๐ŸŸข   | โŒ | โŒ | โŒ | |
| [`smartstring`]https://github.com/bodil/smartstring | โŒ | โŒ | ๐ŸŸข   | โŒ | โŒ | โŒ | |
| [`smallstr`]https://github.com/murarth/smallstr | โŒ | โŒ | ๐ŸŸข   | โŒ | โŒ | โŒ | |
| [`smol_str`]https://github.com/rust-analyzer/smol_str | โŒ | โŒ | ๐ŸŸข* | โŒ | โŒ | โŒ | *but only inline string, here for reference |

skipping specialized string types like [`tinystr`](https://github.com/unicode-org/icu4x) (ASCII-only, bounded), or bstr, or bytestring, or...

In short, `HipStr`, one string type to rule them all ๐Ÿ˜‰

[![How standards proliferate](https://imgs.xkcd.com/comics/standards.png)](https://xkcd.com/927/)

## ๐ŸŽ๏ธ Performances


While speed is not the main motivator for `hipstr`, it seems to be doing OK on that front.

On my i7-8550U, under Arch Linux over Windows 11/WSL 2 (yeah I know ๐Ÿ˜…), the creation of a `HipStr` from a slice is competitive with other crates and the `std`:

![string-comparison/chart.svg](string-comparison/chart.svg)

## ๐Ÿ“– Author and licenses


For now, just me PoLazarus ๐Ÿ‘ป \
Help welcome! ๐Ÿšจ

MIT + Apache