ref_str
ref_str provides compact borrowed-or-shared string types for no_std Rust.
Install
[]
= "0.1"
With serde support:
[]
= { = "0.1", = ["serde"] }
With serde + std support:
[]
= { = "0.1", = ["serde", "std"] }
With arbitrary support:
[]
= { = "0.1", = ["arbitrary"] }
Overview
LocalRefStr<'a> and RefStr<'a> store either a borrowed &'a str or a shared owned string while keeping the representation compact and clone-friendly. LocalStaticRefStr and StaticRefStr provide dedicated 'static wrappers with the same layout and API shape, but with explicit static-only serde/arbitrary semantics.
All four public types share the same core model:
- Values are always either borrowed or shared.
- Borrowed values keep the original lifetime and avoid allocation.
- Shared values clone cheaply by bumping an
Rc<str>orArc<str>strong count. - The internal representation is compact: a data pointer plus packed length/tag metadata.
Why Four Types
LocalRefStr<'a>is optimized for single-threaded code and usesRc<str>when it needs shared ownership.RefStr<'a>is the thread-safe counterpart and usesArc<str>when it needs shared ownership.LocalStaticRefStrandStaticRefStrmirror those two backends for'staticstrings, so static-only behavior is expressed by a real wrapper type instead of by aliasingRefStr<'static>.- The
'awrappers can deserialize borrowed strings directly, while the static wrappers always materialize shared owned strings when deserializing or generatingArbitraryvalues.
API
| Item | Purpose |
|---|---|
LocalRefStr<'a> |
Compact string backed by Rc<str> when shared |
RefStr<'a> |
Compact string backed by Arc<str> when shared |
LocalStaticRefStr |
Static compact string backed by Rc<str> when shared |
StaticRefStr |
Static compact string backed by Arc<str> when shared |
new(&str) |
Build a borrowed value |
from_str(&str) |
Alias of new |
from_owned_like(impl AsRef<str>) |
Always allocate and build a shared value from string-like input |
from_shared(...) |
Build from Rc<str> or Arc<str> |
from_static(&'static str) |
Build a borrowed static wrapper |
is_borrowed() / is_shared() |
Inspect the current storage mode |
len() / is_empty() |
Inspect string length |
as_str() / as_cow() |
Borrow as &str or convert to Cow<str>; as_cow() clones when shared |
into_cow() |
Convert into borrowed-or-owned Cow<str> |
into_bytes() |
Convert into Vec<u8> |
into_boxed_str() |
Convert into Box<str> |
into_string() |
Convert into String |
into_str_unchecked() |
Extract &str without verifying borrowed state |
Conversion Map
borrowed/shared input
│
┌──────────────┴──────────────┐
▼ ▼
LocalRefStr<'a> <──────► RefStr<'a>
│ │
▼ ▼
LocalStaticRefStr <──────► StaticRefStr
Allocation Notes
as_cow()is allocation-free only for borrowed values. Shared values are converted intoCow::Owned, so the string contents are cloned.into_cow()follows the same rule: borrowed values stay borrowed, while shared values become owned strings.- Conversions between
LocalRefStrandRefStrpreserve borrowed values without allocation. - Conversions between
LocalRefStrandRefStrallocate and copy when the source is already shared, becauseRc<str>andArc<str>use different backends.
Safety Boundaries
from_raw_partsisunsafebecause the caller must provide a valid non-null pointer and a correct length/tag combination.into_str_uncheckedisunsafebecause it is only sound for values that are currently borrowed.LocalStaticRefStrandStaticRefStrnever deserialize into borrowed values; non-'staticinput is always converted into shared owned storage.from_owned_likealways constructs the shared representation, even if the input starts as&str.
Example
extern crate alloc;
use String;
use ;
let local: = Stringfrom.into;
let shared: = Stringfrom.into;
assert_eq!;
assert_eq!;
let back: = shared.into;
assert_eq!;
let static_value = from_static;
assert!;
let forced_shared = from_owned_like;
assert!;
Examples
Borrowed:
use LocalRefStr;
let value = from;
assert!;
assert_eq!;
Shared:
# extern crate alloc;
use Rc;
use LocalRefStr;
let value = from_shared;
assert!;
assert_eq!;
Advanced Raw Pointer APIs
These APIs are intended for FFI or other low-level ownership transfer cases:
into_raw_parts()from_raw_parts()into_raw()increment_strong_count()
All of them are unsafe, because they expose the packed representation or raw shared pointer ownership rules directly.
Raw:
# extern crate alloc;
use Arc;
use RefStr;
let value = from_shared;
let = unsafe ;
let value = unsafe ;
assert_eq!;
Cow:
# extern crate alloc;
use Cow;
use RefStr;
let value: = Borrowed.into;
assert_eq!;
Static:
use LocalStaticRefStr;
let value = from_static;
assert!;
assert_eq!;
Forced shared:
use RefStr;
let value = from_owned_like;
assert!;
assert_eq!;
Notes
- This crate is
no_stdand depends onalloc. - The
stdfeature does not enableserdeby itself; it only forwardsserde/stdwhenserdeis already enabled. - The
arbitraryfeature enablesArbitrarysupport for fuzzing and property testing. RefStr<'a>/LocalRefStr<'a>may deserialize or generate borrowed values, whileStaticRefStr/LocalStaticRefStralways materialize shared owned strings in those paths.from_owned_like,String,Box<str>,Rc<str>, andArc<str>constructors all create shared values.Default::default()creates an empty borrowed value for all four wrappers.
License
Dual licensed under MIT or Apache-2.0.