Skip to main content

AppendStr

Struct AppendStr 

Source
pub struct AppendStr { /* private fields */ }
Expand description

A concurrent append-only String-like container.

Implementations§

Source§

impl AppendStr

Source

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!");
Source

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);
}
Source

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;
            }
        }
    });
});
Source

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);
}
Source

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);
}
Source

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 of index must 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 Default for AppendStr

Source§

fn default() -> AppendStr

Returns the “default value” for a type. Read more
Source§

impl Index<Range<usize>> for AppendStr

Source§

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 of index must 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.

Source§

type Output = str

The returned type after indexing.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.