Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,21 @@ criterion = { version = "0.4", features = ["html_reports"] }
env_logger = "0.10"
serde = { version = "1.0", features = ["derive"] }
diesel = { version = "2", features = ["sqlite", "postgres", "mysql"] }

[dependencies]
log = { version = "0.4", optional = true }
serde = { version = "1", optional = true }
diesel = { version = "2", optional = true }
no-panic = "0.1"
no-panic = { version = "0.1", optional = true }

[features]
default = ["std"]
std = []
logs = ["log"]
serde-traits = ["serde"]
diesel-traits = ["diesel"]
no-panic = ["dep:no-panic"]

[package.metadata.docs.rs]
rustdoc-args = ["--cfg", "docs_rs_workaraound"]
features = ["logs", "serde-traits", "std", "diesel-traits"]

[profile.dev]
opt-level = 3
features = ["logs", "serde-traits", "std", "diesel-traits", "no-panic"]
81 changes: 32 additions & 49 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
*For experimentation with `const generics` try [`staticvec`](https://github.com/slightlyoutofphase/staticvec/)*
*For experimentation with nightly only `const generics` features try [`staticvec`](https://github.com/slightlyoutofphase/staticvec/)*

# ArrayString

Expand All @@ -8,9 +8,11 @@ Can't outgrow initial capacity (defined at compile time), always occupies `capac

*Maximum Capacity is 255*

*Doesn't allocate memory on the heap and never panics in release (all panic branches are stripped at compile time - except `Index`/`IndexMut` traits, since they are supposed to)*
*Doesn't allocate memory on the heap and should never panic in release (except in `Index`/`IndexMut` traits, since they are supposed to)*

* [Documentation](https://docs.rs/arraystring/0.3.0/arraystring)
*The no panic garantee can be ensured at compilation time with the `no-panic` feature, just be aware that a compiler update might break this garantee, therefore making the crate uncompilable, open an issue if you notice.*

* [Documentation](https://docs.rs/arraystring/latest/arraystring)

## Why

Expand All @@ -22,9 +24,9 @@ Stack based strings are generally faster to create, clone and append to than hea

But that becomes less true as you increase the array size, `CacheString` occuppies a full cache line, 255 bytes is the maximum we accept - `MaxString` and it's probably already slower than heap based strings of that size (like in `std::string::String`)

There are other stack based strings out there, they generally can have "unlimited" capacity (heap allocate), but the stack based size is defined by the library implementor, we go through a different route by implementing a string based in a generic array.
There are other stack based strings out there, they generally can have "unlimited" capacity using small string optimizations, but the stack based size is defined by the library implementor. We go through a different route by implementing a string based in a generic array.

Array based strings always occupies the full space in memory, so they may use more memory (although in the stack) than dynamic strings.
Be aware that array based strings always occupy the full space in memory, so they may use more memory (although in the stack) than dynamic strings.

## Features

Expand All @@ -39,6 +41,10 @@ Array based strings always occupies the full space in memory, so they may use mo

Opperates like `String`, but truncates it if it's bigger than capacity

- `no-panic` checks at compile time that the panic function is not linked by the library

Only works when all optimizations are enabled, and may break in future compiler updates. Please open an issue if you notice.

- `logs` enables internal logging

You will probably only need this if you are debugging this library
Expand Down Expand Up @@ -68,50 +74,27 @@ fn main() -> Result<(), Error> {
}
```

## Comparisons

*These benchmarks ran while I streamed video and used my computer (with* **non-disclosed specs**) *as usual, so don't take the actual times too seriously, just focus on the comparison*

```my_custom_benchmark
small-string (23 bytes) clone 4.837 ns
small-string (23 bytes) try_from_str 13.552 ns
small-string (23 bytes) from_str_truncate 11.360 ns
small-string (23 bytes) from_str_unchecked 11.291 ns
small-string (23 bytes) try_push_str 1.162 ns
small-string (23 bytes) push_str 3.490 ns
small-string (23 bytes) push_str_unchecked 1.098 ns
-------------------------------------------------------------
cache-string (63 bytes) clone 10.170 ns
cache-string (63 bytes) try_from_str 25.579 ns
cache-string (63 bytes) from_str_truncate 16.977 ns
cache-string (63 bytes) from_str_unchecked 17.201 ns
cache-string (63 bytes) try_push_str 1.160 ns
cache-string (63 bytes) push_str 3.486 ns
cache-string (63 bytes) push_str_unchecked 1.115 ns
-------------------------------------------------------------
max-string (255 bytes) clone 147.410 ns
max-string (255 bytes) try_from_str 157.340 ns
max-string (255 bytes) from_str_truncate 158.000 ns
max-string (255 bytes) from_str_unchecked 158.420 ns
max-string (255 bytes) try_push_str 1.167 ns
max-string (255 bytes) push_str 4.337 ns
max-string (255 bytes) push_str_unchecked 1.103 ns
-------------------------------------------------------------
string (19 bytes) clone 33.295 ns
string (19 bytes) from 32.512 ns
string (19 bytes) push str 28.128 ns
-------------------------------------------------------------
arrayvec string (23 bytes) clone 7.725 ns
arrayvec string (23 bytes) from 14.794 ns
arrayvec string (23 bytes) push str 1.363 ns
-------------------------------------------------------------
inlinable-string (30 bytes) clone 16.751 ns
inlinable-string (30 bytes) from_str 29.310 ns
inlinable-string (30 bytes) push_str 2.865 ns
-------------------------------------------------------------
smallstring crate (20 bytes) clone 60.988 ns
smallstring crate (20 bytes) from_str 50.233 ns
```
# Miri

Tests can be run through Miri to ensure Undefined Behavior isn't triggered by them. It excludes diesel's integration `sqlite` tests as it's impossible to link to C libraries from Miri. And logs won't be persisted in doc tests as `env_logger` isn't supported by Miri either.

To run the tests with it do (requires nightly installed):

`cargo +nightly miri test --release --all-features`

# No Panic

There is a feature to enable the `no_panic` dependency, that will be enforced in every function. To be sure every panicking branch is removed. This depends on compiler optimizations and compilation may break on updates, or in different environments. We generally don't recommend using it, but it's useful in environments with high restrictions.

This feature will only be enforced in `release` builds (it checks for `not(debug_assertions)`)

But it's mostly used to test the library.

To run the tests with it do:

`cargo test --lib --tests --release --features=no-panic`

Both serde and diesel integrations can panic. Index trait implementations too.

## Licenses

Expand Down
Loading