pub struct AppendStr { /* private fields */ }Expand description
A concurrent append-only String-like container.
Implementations§
Source§impl AppendStr
impl AppendStr
Sourcepub fn new() -> Self
pub fn new() -> Self
Creates a new, empty string.
use appendvec::AppendStr;
let mut container = AppendStr::new();
let index = container.push_str_mut("Hello world!");
assert_eq!(&container[index], "Hello world!");Sourcepub fn with_capacity(capacity: usize) -> Self
pub fn with_capacity(capacity: usize) -> Self
Creates a new, empty string, pre-allocating space for at least
capacity bytes.
§Panics
This function panics if the capacity exceeds the maximum allocation size.
use appendvec::AppendStr;
let mut container = AppendStr::with_capacity(42);
for i in 0..42 {
let bytes = [i];
let s = std::str::from_utf8(&bytes).unwrap();
let index = container.push_str_mut(s);
assert_eq!(&container[index], s);
}Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the length in bytes of this collection.
Given that writes can happen concurrently, beware of TOCTOU bugs! The value returned here is only a lower-bound of the collection size.
To know the index of an added item, use the return value of the
push_str() function.
use appendvec::AppendStr;
use std::thread;
let container = AppendStr::with_capacity(42);
thread::scope(|s| {
s.spawn(|| {
for i in 0..42 {
let index = container.push_str(std::str::from_utf8(&[i]).unwrap());
// There is only one writer thread.
assert_eq!(index, i as usize..i as usize + 1);
}
});
s.spawn(|| {
loop {
let l = container.len();
if l != 0 {
// The unique writer thread pushes values in order.
assert_eq!(
&container[l - 1..l],
std::str::from_utf8(&[l as u8 - 1]).unwrap()
);
}
if l == 42 {
break;
}
}
});
});Sourcepub fn push_str(&self, s: &str) -> Range<usize>
pub fn push_str(&self, s: &str) -> Range<usize>
Adds the given string to this collection, and returns the byte range at which it was added.
The string is guaranteed to be pushed contiguously, so that indexing the result allows to retrieve back a contiguous string. If the current bucket doesn’t have enough remaining capacity to accommodate this contiguous string, it will be padded with zero bytes (which are valid UTF-8).
See also push_str_mut(), which is more efficient
if you hold a mutable reference to this collection.
§Panics
This function panics if this collection has reached the maximum allocation size.
use appendvec::AppendStr;
let container = AppendStr::new();
for i in 0..42 {
let blob = vec![123; i];
let s = std::str::from_utf8(blob.as_slice()).unwrap();
let index = container.push_str(s);
assert_eq!(&container[index], s);
}Sourcepub fn push_str_mut(&mut self, s: &str) -> Range<usize>
pub fn push_str_mut(&mut self, s: &str) -> Range<usize>
Adds the given string to this collection, and returns the byte range at which it was added.
Contrary to push_str(), no write lock is held
internally because this function already takes an exclusive mutable
reference to this collection.
§Panics
This function panics if this collection has reached the maximum allocation size.
use appendvec::AppendStr;
let mut container = AppendStr::new();
for i in 0..42 {
let blob = vec![123; i];
let s = std::str::from_utf8(blob.as_slice()).unwrap();
let index = container.push_str_mut(s);
assert_eq!(&container[index], s);
}Sourcepub fn get_bytes(&self, index: Range<usize>) -> &[u8] ⓘ
pub fn get_bytes(&self, index: Range<usize>) -> &[u8] ⓘ
Gets the byte slice at the given index range, without checking that they are valid UTF-8.
Bypassing the UTF-8 check can be useful if you’ll only look at bytes anyway, for example for string comparison.
§Panics
The passed index range:
- must be correctly ordered, i.e.
index.start <= index.end, - must be lower than the size of the collection, i.e. a call to
push_str()(or its variants) that returned a superset ofindexmust have happened before this function call, - must be contained in a single contiguous bucket; this is always the
case when passing a subset of a range returned by a previous call to
push_str().
Otherwise, this function panics.
use appendvec::AppendStr;
let container = AppendStr::new();
for i in 0..42 {
let blob = vec![123; i];
let s = std::str::from_utf8(blob.as_slice()).unwrap();
let index = container.push_str(s);
assert_eq!(container.get_bytes(index), blob.as_slice());
}Trait Implementations§
Source§impl Index<Range<usize>> for AppendStr
impl Index<Range<usize>> for AppendStr
Source§fn index(&self, index: Range<usize>) -> &Self::Output
fn index(&self, index: Range<usize>) -> &Self::Output
§Panics
The passed index range:
- must be correctly ordered, i.e.
index.start <= index.end, - must be lower than the size of the collection, i.e. a call to
push_str()(or its variants) that returned a superset ofindexmust have happened before this function call, - must be contained in a single contiguous bucket; this is always the
case when passing a subset of a range returned by a previous call to
push_str(), - must be fall on UTF-8 boundaries; this is always the case when exactly
passing a range returned by a previous call to
push_str().
Otherwise, this function panics.