Struct indexed::Pool

source ·
pub struct Pool<T: Indexed> { /* private fields */ }
Expand description

A Vec-like, no reallocation collection. Elements in a Pool should not be zero sized type, or the construction will panic.

Implementations

Creates a new pool that drops its elements on destruction.

Panics

Panics if the type of element is ZST.

Examples
#[macro_use] extern crate indexed;
use indexed::{Indexed,Pool};

static mut COUNT: usize = 0;

struct Name { index: usize, text: String }

impl_indexed!{ Name{ index: usize }}

impl Drop for Name { fn drop( &mut self ) { unsafe{ COUNT += 1; }}}

impl From<&'static str> for Name {
    fn from( s: &'static str ) -> Self {
        Name{ index: <Self as Indexed>::null(), text: s.to_string() }
    }
}

{ let pool = pool!( Name[ "foo", "bar", "baz" ]); }

assert_eq!( unsafe{ COUNT }, 3 );

Creates a new pool that does not drop its elements on destruction. It is up to the user to drop the elements manually to avoid memory leaks.

Panics

Panics if the type of element is ZST.

Examples
#[macro_use] extern crate indexed;
use indexed::{Indexed,Pool};

static mut COUNT: usize = 0;

struct Name { index: usize, text: String }

impl_indexed!{ Name{ index: usize }}

impl Drop for Name { fn drop( &mut self ) { unsafe{ COUNT += 1; }}}

impl From<&'static str> for Name {
    fn from( s: &'static str ) -> Self {
        Name{ index: <Self as Indexed>::null(), text: s.to_string() }
    }
}

{
    let mut pool = Pool::<Name>::new_unmanaged();
    pool.push( "foo".into() );
    pool.push( "bar".into() );
    pool.push( "baz".into() );
}
assert_eq!( unsafe{ COUNT }, 0 );

Appends an element to the back of a pool.

Panics

Panics if the number of elements in the vector overflows a usize.

Examples
#[macro_use] extern crate indexed;
use indexed::{Indexed,Pool};

extrusive_indexed!{ Foo{ inner: i32 }}

let mut pool = Pool::new();

pool.push( Foo::from( 0 ));
pool.push( Foo::from( 1 ));
pool.push( Foo::from( 2 ));

assert_eq!( pool.iter().map( |e| e.inner ).collect::<Vec<_>>(), vec![ 0, 1, 2 ]);

Overwrites a new value into a pool at given index without reading or dropping the old value.

Safety

This operation is marked unsafe because it accepts an index as an offset which acts like a raw pointer.

It does not drop the contents of the existing self[index] element. This is safe, but it could leak allocations or resources, so care must be taken not to overwrite an object that should be dropped.

Additionally, it does not drop value. Semantically, value is moved into self[index].

This is appropriate for initializing uninitialized memory.

Examples

Basic usage:

#[macro_use] extern crate indexed;
use indexed::{Indexed,Pool};

extrusive_indexed!{ Foo{ inner: &'static str }}

let mut pool = Pool::<Foo>::new();

pool.reserve( 3 );

unsafe {
    pool.write( 0, "a".into() );
    pool.write( 2, "c".into() );
    pool.write( 1, "b".into() );
    pool.set_len( 3 );
}

assert_eq!( pool.iter().map( |e| e.inner ).collect::<Vec<_>>(), vec![ "a", "b", "c" ]);

Reserves capacity for at least additional more elements to be inserted in the given Pool. The collection may reserve more space because the increasing size must be multiple of underlying chunk_len(). After calling reserve, capacity will be greater than or equal to self.new_index() + additional. Does nothing if capacity is already sufficient.

Panics

Panics if the new capacity overflows usize.

Examples
#[macro_use] extern crate indexed;
use indexed::{Indexed,Pool};

extrusive_indexed!{ Foo{ inner: &'static str }}

let mut pool = Pool::<Foo>::new();

pool.reserve( 0 );
assert_eq!( pool.capacity(), 0 );

pool.reserve( 1 );
let cap = pool.capacity();
assert!( cap >= 1 );

pool.reserve( 1 );
assert_eq!( pool.capacity(), cap );

pool.reserve( 1024 );
assert!( pool.capacity() >= 1024 );

Returns the number of elements in the pool, also referred to as its ‘length’.

#[macro_use] extern crate indexed;
use indexed::{Indexed,Pool};

extrusive_indexed!{ Foo{ inner: &'static str }}

let mut pool = pool!( Foo[ "a", "b", "c" ]);
assert_eq!( pool.len(), 3 );

Sets the length of a pool.

This will explicitly set the size of the pool, without actually modifying its buffers, so it is up to the caller to ensure that the pool is actually the specified size.

#[macro_use] extern crate indexed;
use indexed::{Indexed,Pool};

extrusive_indexed!{ Foo{ inner: char }}

let mut pool = pool!( Foo[ 'r', 'u', 's', 't' ]);

unsafe {
    std::ptr::drop_in_place( &mut pool[3] );
    pool.set_len( 3 );
}

assert_eq!( pool.len(), 3 );
assert_eq!( pool.iter().map( |e| e.inner ).collect::<Vec<_>>(), vec!['r', 'u', 's'] );

In this example, there is a memory leak since the memory locations owned by the first Name were not freed prior to the set_len call:

#[macro_use] extern crate indexed;
use indexed::{Indexed,Pool};

static mut COUNT: usize = 0;

struct Name { index: usize, text: String }

impl_indexed!{ Name{ index: usize }}

impl Drop for Name { fn drop( &mut self ) { unsafe{ COUNT += 1; }}}

impl From<&'static str> for Name {
    fn from( s: &'static str ) -> Self {
        Name{ index: <Self as Indexed>::null(), text: s.to_string() }
    }
}

let mut pool = pool!( Name[ "abc", "def", "g" ]);

unsafe {
    std::ptr::drop_in_place( &mut pool[2] );
    std::ptr::drop_in_place( &mut pool[1] );
    pool.set_len( 0 );
}

assert_eq!( unsafe{ COUNT }, 2 );

In this example, the pool gets expanded from zero to four items without any memory allocations occurring, resulting in pool values of unallocated memory:

#[macro_use] extern crate indexed;
use indexed::{Indexed,Pool};

extrusive_indexed!{ Foo{ inner: &'static str }}

let mut pool = Pool::<Foo>::new();
unsafe { pool.set_len( 3 ); }

Returns the number of elements the vector can hold without more allocating.

Note: the purpose of this method is not to avoid reallocation, which could not happen at all, but to grow the buffer for next incomming write()s.

Returns the pool’s NonNull pointer.

Examples
#[macro_use] extern crate indexed;
use indexed::{Indexed,Pool};

extrusive_indexed!{ Foo{ inner: i32 }}

let mut pool = Pool::<Foo>::new();
let p = pool.non_null();

assert_eq!( p, std::ptr::NonNull::new( Box::into_raw( pool )).unwrap() );

Obtains reference of the pool of an element.

Examples
#[macro_use] extern crate indexed;
use indexed::{Indexed,Pool};

extrusive_indexed!{ Foo{ inner: usize }}

let mut pool = Pool::<Foo>::new();

for i in 0..1024 {
    pool.push( i.into() );
}

for i in 0..1024 {
    assert!( pool.non_null().as_ptr() as *const Pool<Foo> == pool[i].pool() );
}

Obtains mutable reference of the pool from an element.

Safety

This operation is marked unsafe because it obtains a mutable reference of the Pool from one of its immutable element, which may violate the memory safety rule “only one mutable reference, or none but multiple immutable references”.

Examples
#[macro_use] extern crate indexed;
use indexed::{Indexed,Pool};

extrusive_indexed!{ Foo{ inner: usize }}

let mut pool = Pool::<Foo>::new();

for i in 0..1024 {
    pool.push( i.into() );
}

for i in 0..1024 {
    assert_eq!( pool.non_null().as_ptr(),
                unsafe{ pool[i].pool_mut() as *mut Pool<Foo>});
}

Obtains NonNull pointer of the pool from an element.

Returns the expected index for the next new element to be push()ed in.

Returns true if the pool contains no elements.

Examples
#[macro_use] extern crate indexed;
use indexed::{Indexed,Pool};

extrusive_indexed!{ Foo{ inner: &'static str }}

let mut pool = Pool::new();
assert!( pool.is_empty() );

pool.push( Foo::from( "foo" ));
assert!( !pool.is_empty() );

Returns an iterator over the pool.

Examples
#[macro_use] extern crate indexed;
use indexed::{Indexed,Pool};

extrusive_indexed!{ Foo{ inner: &'static str }}

let mut pool = pool!( Foo[ "abc", "def", "g" ]);
let mut iter = pool.iter();

assert_eq!( iter.next().unwrap().inner, "abc" );
assert_eq!( iter.next().unwrap().inner, "def" );
assert_eq!( iter.next().unwrap().inner, "g"   );
assert!( iter.next().is_none() );

Returns an iterator that allows modifying each value.

Examples
#[macro_use] extern crate indexed;
use indexed::{Indexed,Pool};

extrusive_indexed!{ Foo{ inner: i32 }}

let mut pool = pool!( Foo[ 0, 1, 2 ]);

pool.iter_mut().for_each( |elem| { elem.inner += 10; });

assert_eq!( pool.iter().map( |e| e.inner ).collect::<Vec<_>>(), vec![ 10, 11, 12 ]);

Returns a shared reference to the output at indexed location, without performing any bounds checking.

Returns a mutable reference to the output at indexed location, without performing any bounds checking.

Trait Implementations

Formats the value using the given formatter. Read more
Executes the destructor for this type. Read more
The returned type after indexing.
Performs the indexing (container[index]) operation. Read more
Performs the mutable indexing (container[index]) operation. Read more
This method tests for self and other values to be equal, and is used by ==. Read more
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

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

The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.