MapInPlace

Struct MapInPlace 

Source
pub struct MapInPlace<'a> { /* private fields */ }
Expand description

A mutable reference to a str that allows for in-place pushes and pops while maintaining valid UTF-8 at all times.

Semantically, this creates 2 buffers, a “mapped” buffer, and an “unmapped” buffer.

The mapped buffer starts off empty, and the unmapped buffer starts off with the full contents of the &mut str given in MapInPlace::new.

The mapped buffer can be pushed to, and this will append to the end of it. The unmapped buffer can be popped from, and this will pop from the start of it.

The size of the mapped buffer, plus the size of the unmapped buffer, can never be bigger than the original string size, and you will get errors when you go to push if this is the case.

However, it’s free to be smaller, in which case there will be some area in the middle with unspecified contents. It will still be valid UTF-8 though, to ensure safety.

Implementations§

Source§

impl<'a> MapInPlace<'a>

Source

pub fn new(s: &'a mut str) -> Self

Creates a new MapInPlace, used to do in-place string conversions without allocating a new buffer.

let mut string = String::from("Hello, World!");
let mut map = in_place_string_map::MapInPlace::new(&mut string);
Source

pub fn mapped(&self) -> &str

Returns the mapped portion of the string.

let mut string = String::from("Hello, World!");
let mut map = in_place_string_map::MapInPlace::new(&mut string);

assert_eq!(map.mapped(), "");

map.pop_chars(6);

map.push_str("Yellow");

assert_eq!(map.mapped(), "Yellow");
Source

pub fn into_mapped(self) -> &'a mut str

Consumes this MapInPlace and returns the mapped slice of the original string with the original lifetime.

This is useful for when you want the lifetime of the returned string to outlive the instance of MapInPlace.

fn push_yellow(s: &mut str) -> &mut str {
    let mut map = in_place_string_map::MapInPlace::new(s);
    map.pop_chars(6);
    map.push_str("Yellow");
    map.into_mapped()
}

let mut string = String::from("Hello, World!");
let result = push_yellow(&mut string);
assert_eq!(result, "Yellow");

You cannot simply use MapInPlace::mapped because that will return a reference that can’t outlive the original MapInPlace

fn push_yellow(s: &mut str) -> &str {
    let mut map = in_place_string_map::MapInPlace::new(s);
    map.pop_chars(6);
    map.push_str("Yellow");

    // cannot return value referencing local variable `map`
    map.mapped()
}

let mut string = String::from("Hello, World!");
let result = push_yellow(&mut string);
assert_eq!(result, "Yellow");
Source

pub fn unmapped(&self) -> &str

Returns the not yet mapped portion of the string.

let mut string = String::from("Hello, World!");
let mut map = in_place_string_map::MapInPlace::new(&mut string);

assert_eq!(map.unmapped(), "Hello, World!");

map.pop_chars(5);

assert_eq!(map.unmapped(), ", World!");
Source

pub fn into_unmapped(self) -> &'a mut str

Consumes this MapInPlace and returns the unmapped slice of the original string with the original lifetime.

This is useful for when you want the lifetime of the returned string to outlive the instance of MapInPlace.

fn pop_five(s: &mut str) -> &mut str {
    let mut map = in_place_string_map::MapInPlace::new(s);
    map.pop_chars(5);
    map.into_unmapped()
}

let mut string = String::from("Hello, World!");
let result = pop_five(&mut string);
assert_eq!(result, ", World!");

You cannot simply use MapInPlace::mapped because that will return a reference that can’t outlive the original MapInPlace

fn pop_five(s: &mut str) -> &str {
    let mut map = in_place_string_map::MapInPlace::new(s);
    map.pop_chars(5);

    // cannot return value referencing local variable `map`
    map.unmapped()
}

let mut string = String::from("Hello, World!");
let result = pop_five(&mut string);
assert_eq!(result, ", World!");
Source

pub fn push(&mut self, ch: char) -> Result<(), NoCapacityError>

Pushes a character onto the end of the mapped portion.

let mut string = String::from("Hello!");
let mut map = in_place_string_map::MapInPlace::new(&mut string);
map.pop_chars(6);

assert_eq!(map.mapped(), "");
map.push('£').unwrap();
map.push('1').unwrap();
map.push('.').unwrap();
map.push('2').unwrap();
map.push('5').unwrap();

assert_eq!(map.mapped(), "£1.25");

map.push('5').unwrap_err();

assert_eq!(map.mapped(), "£1.25");
§Errors
Source

pub fn push_str(&mut self, s: &str) -> Result<(), NoCapacityError>

Pushes a string onto the end of the mapped portion. If the string is too long, an error is returned, and no changes will be made to the input.

let mut string = String::from("Hello!");
let mut map = in_place_string_map::MapInPlace::new(&mut string);
map.pop_chars(6);

assert_eq!(map.mapped(), "");

map.push_str("This string is *far* too long!").unwrap_err();

assert_eq!(map.mapped(), "");

map.push_str("Short").unwrap();

assert_eq!(map.mapped(), "Short");

map.push_str(".").unwrap();

assert_eq!(map.mapped(), "Short.");
§Errors
Source

pub fn pop(&mut self) -> Option<char>

Pops a character from the start of the unmapped portion

Will return None if there are no more characters left to pop.

let mut string = String::from("Hi!");
let mut map = in_place_string_map::MapInPlace::new(&mut string);

assert_eq!(map.pop(), Some('H'));
assert_eq!(map.unmapped(), "i!");

assert_eq!(map.pop(), Some('i'));
assert_eq!(map.unmapped(), "!");

assert_eq!(map.pop(), Some('!'));
assert_eq!(map.unmapped(), "");

assert_eq!(map.pop(), None);
assert_eq!(map.unmapped(), "");
Source

pub fn pop_chars(&mut self, n: usize) -> Option<&str>

Pops n characters from the start of the unmapped portion.

Note how this pops in terms of characters, not bytes.

If n is 0 then will always return None

If this fails because there are not enough characters then will return None, and no changes will have been made to self.

let mut string = String::from("A £3.00 sandwich");
let mut map = in_place_string_map::MapInPlace::new(&mut string);

assert_eq!(map.pop_chars(0), None);
assert_eq!(map.pop_chars(2), Some("A "));
assert_eq!(map.pop_chars(5), Some("£3.00"));

// Nothing is done if you try to pop too many characters
assert_eq!(map.pop_chars(10), None);

assert_eq!(map.pop_chars(9), Some(" sandwich"));

Trait Implementations§

Source§

impl<'a> Debug for MapInPlace<'a>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'a> Freeze for MapInPlace<'a>

§

impl<'a> RefUnwindSafe for MapInPlace<'a>

§

impl<'a> Send for MapInPlace<'a>

§

impl<'a> Sync for MapInPlace<'a>

§

impl<'a> Unpin for MapInPlace<'a>

§

impl<'a> !UnwindSafe for MapInPlace<'a>

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.