Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Misc #37

Merged
merged 10 commits into from
Dec 31, 2024
Merged

Misc #37

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
2 changes: 2 additions & 0 deletions .config/nextest.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[profile.default]
leak-timeout = "500ms"
15 changes: 12 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,21 @@ Notable changes only.

## Unreleased

### Added
### Added

- add new unique (non-shared) strings and byte vectors
- add `as_borrowed`
- add inline `const` constructors

### Changed

- refactor the backend to support unique
- refactor the backend to support unique references
- remove low-level `Raw` type
- improve deserialization for strings, bytes and paths, see [#38](https://github.com/polazarus/hipstr/pull/38) and follow-up work

### Removed

- dependency to `serde_bytes`

## [0.6.0] - 2024-10-08

Expand All @@ -19,7 +27,7 @@ Notable changes only.
- implement `core::error:Error` for custom errors, rather than
`std::error::Error` and bump msrv

### Fixed
### Fixe

- fix doc issue [#28](https://github.com/polazarus/hipstr/issues/28)
- fix MIRI check due to provenance loss
Expand Down Expand Up @@ -137,6 +145,7 @@ Most of those addition are breaking because they shadows `str`'s methods.
Initial release

<!-- [unreleased]: https://github.com/polazarus/hipstr/compare/0.6.1...HEAD -->

[0.6.0]: https://github.com/polazarus/hipstr/compare/0.5.1...0.6.0
[0.5.1]: https://github.com/polazarus/hipstr/compare/0.5.0...0.5.1
[0.5.0]: https://github.com/polazarus/hipstr/compare/0.4.0...0.5.0
Expand Down
24 changes: 14 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "hipstr"
version = "0.6.0"
version = "0.6.1"
authors = ["Polazarus <[email protected]>"]
description = """Yet another string for Rust: zero-cost borrow and slicing,
inline representation for small strings, (atomic) reference counting"""
Expand All @@ -10,23 +10,24 @@ categories = ["memory-management", "data-structures"]
license = "MIT OR Apache-2.0"
edition = "2021"
readme = "README.md"
rust-version = "1.81.0"
rust-version = "1.83.0"

[package.metadata.docs.rs]
all-features = true

[features]
default = ["std"]
std = ["serde/std", "serde_bytes/std"]
std = ["serde/std"]
unstable = []
serde = ["dep:serde", "dep:serde_bytes"]
serde = ["dep:serde"]
bstr = ["dep:bstr"]

[dev-dependencies]
fastrand = "2.0.0"
serde_test = "1.0.176"
serde = { version = "1.0.100", default-features = false, features = ["derive", "alloc"] }
serde_json = { version = "1.0.45", default-features = false, features = ["alloc"] }
divan = "0.1.15"

[dependencies]
sptr = "0.3.2"
Expand All @@ -43,18 +44,21 @@ optional = true
default-features = false
features = ["alloc"]

[dependencies.serde_bytes]
version = "0.11.3"
optional = true
default-features = false
features = ["alloc"]

[target.'cfg(loom)'.dependencies]
loom = "0.7"

[target.'cfg(not(loom))'.dev-dependencies]
arcstr = "1.2.0"
ecow = "0.2.3"
kstring = "2.0.2"

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = [
'cfg(coverage_nightly)',
'cfg(docsrs)',
'cfg(loom)',
] }

[[bench]]
name = "main"
harness = false
38 changes: 20 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,24 +129,26 @@ Note: this crate leverages the "exposed provenance" semantics.

`#[non_exhaustive]`

| Name | Thread-safe cheap-clone | Local cheap-clone | Inline | Cheap slice | Bytes | Borrow `'static` | Borrow any `'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) | ❌ | ❌ | 🟢 | ❌ | ❌ | ❌ | ❌ | |
| [`kstring`](https://docs.rs/kstring/latest/kstring/) | 🟢 | ❌ | 🟢 | ❌ | ❌ | 🟢 | ❌ | |
| [`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...
| Name | TS cheap-clone | Local cheap-clone | Inline | Cheap slice | Bytes | Borrow `'static` | Borrow any `'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 `(A)rc<str>` instead of `(A)rc<String>` (remove a 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) | - | - | ✓ | - | - | - | - | |
| [`kstring`](https://docs.rs/kstring/latest/kstring/) | ✓ | ✓ | ✓ | - | - | ✓ | ✓\* | safe mode, use boxed strings; \* with second type |
| [`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 😉

Expand Down
76 changes: 76 additions & 0 deletions benches/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
use arcstr::ArcStr;
use divan::Bencher;
use ecow::EcoString;
use hipstr::{HipStr, UniqueHipStr};
use kstring::KString;

fn main() {
divan::main();
}

const S: &[u8] = &[42; 42];
const S2: &str = unsafe { std::str::from_utf8_unchecked(S) };

#[divan::bench_group(sample_count = 10_000)]
mod from_slice {
use super::*;

#[divan::bench(args = [0, 1, 16, 23, 32, 42])]
fn bench_hipstr_from_slice(n: usize) -> HipStr<'static> {
HipStr::from(&S2[0..n])
}

#[divan::bench(args = [0, 1, 16, 23, 32, 42])]
fn bench_unique_hipstr_from_slice(n: usize) -> UniqueHipStr<'static> {
UniqueHipStr::from(&S2[0..n])
}

#[divan::bench(args = [0, 1, 16, 23, 32, 42])]
fn bench_arcstr_from_slice(n: usize) -> ArcStr {
ArcStr::from(&S2[0..n])
}

#[divan::bench(args = [0, 1, 16, 23, 32, 42])]
fn bench_ecow_from_slice(n: usize) -> EcoString {
EcoString::from(&S2[0..n])
}

#[divan::bench(args = [0, 1, 16, 23, 32, 42])]
fn bench_kstring_from_slice(n: usize) -> KString {
KString::from_ref(&S2[0..n])
}
}

#[divan::bench_group(sample_count = 10_000)]
mod from_string {
use super::*;

#[divan::bench(args = [0, 1, 16, 23, 32, 42])]
fn bench_hipstr_from_string(b: Bencher, n: usize) {
b.with_inputs(|| String::from(&S2[0..n]))
.bench_local_values(|s| HipStr::from(s));
}
#[divan::bench(args = [0, 1, 16, 23, 32, 42])]
fn bench_uhipstr_from_string(b: Bencher, n: usize) {
b.with_inputs(|| String::from(&S2[0..n]))
.bench_local_values(|s| UniqueHipStr::from(s));
}

#[divan::bench(args = [0, 1, 16, 23, 32, 42])]
fn bench_arcstr_from_string(b: Bencher, n: usize) {
b.with_inputs(|| String::from(&S2[0..n]))
.bench_local_values(|s| ArcStr::from(s));
}

#[divan::bench(args = [0, 1, 16, 23, 32, 42])]
fn bench_ecow_from_string(b: Bencher, n: usize) {
b.with_inputs(|| String::from(&S2[0..n]))
.bench_local_values(|s| EcoString::from(s));
}

#[divan::bench(args = [0, 1, 16, 23, 32, 42])]
fn bench_kstring_from_string(b: Bencher, n: usize) {
b.with_inputs(|| String::from(&S2[0..n]))
.bench_local_values(|s| KString::from_string(s));
}
}
Loading
Loading