dynode
A framework for making node-based structures with dynamically-sized values.
GitHub | docs.rs (latest) | crates.io (latest) | lib.rs
The main feature is the NodePtr
type which primarily consists of functions for allocation and deallocation.
The library also includes a MaybeUninitNode
type that is designed to be exposed to users of your library.
Features
alloc
- Adds features that require thealloc
crate. This includes operations specific to theGlobal
allocator and sets it as the default allocator in generics.std
(requiresalloc
, default) - Adds features that require thestd
crate. Currently, this adds nothing, but disabling it enables theno_std
attribute.
Creating a Structure
A Linked Queue
Let's create a simple linked queue.
This example will only have sized elements and will not use MaybeUninitNode
s.
Below, there is another example that does use these.
//
// (0) The Node
// It's recommended to create a type alias for `NodePtr`.
//
use NodePtr;
type Node<T> = ;
//
// (1) The Header
// Each node has a header, which contains the structural information.
// For our linked queue, we only need the pointer to the next element.
//
//
// (2) The Structure
// Next, let's define the structure.
// A linked queue has a front and a back. If one exists, then the other must too,
// so I'm collapsing them into a single `Option` but the alternative is fine too.
//
//
// (3) Queuing
//
//
// (4) Dequeuing
//
//
// (5) Dropping
// Once our user is done with their queue, we want to deallocate the nodes after
// dropping their values.
// I'm going to use a 'drop guard' to continue dropping even if `<T as Drop>::drop`
// panics once.
// This is not absolutely necessary though.
//
//
// (6) Testing
//
let mut queue = new;
queue.queue;
assert!;
println!; // > Some(1)
queue.queue;
queue.queue;
println!; // > Some(2)
queue.queue;
queue.queue;
println!; // > Some(3)
println!; // > Some(4)
println!; // > Some(5)
assert!;
println!; // > None
// Give something for our drop implementation to drop
// I highly recommend using miri to test your structures; it will tell you when
// things don't get deallocated
// Try commenting out the `Drop` implementation and then running `cargo miri test`
queue.queue;
A ThinSlot
ThinBox
es are thin-pointers to unsized values. The value's metadata is stored in the box on the heap.
In this, we will create a 'thin slot', which may hold a value. This is just to show unsized nodes and MaybeUninitNode
s.
use ;
use ;
//
// (0) The Structure
// This may contain a single node.
//
;
type Node<T> = ;
//
// (1) Implement `StructureHandle`
// This is required to make use of `MaybeUninitNode`s.
// It uses `HeaderOpaqueNodePtr`s to avoid forcing the header type to be public.
//
// Expose a type alias for `MaybeUninitNode`
pub type MaybeUninitNode<'a, T> = MaybeUninitNode;
//
// (2) Allocating
// Next, we'll write some functions to allow our users to allocate `MaybeUninitNode`s.
//
//
// (3) Setting
// These functions may allow completely safe ways for your users to add nodes.
//
//
// (4) Dropping
//
//
// (5) Testing
//
let mut slot = new;
assert!;
println!; // > None
slot.set_sized;
assert!;
println!; // > Some(5)
let mut slot = new;
slot.set_copy_from_slice;
println!; // > Some([0, 1, 2, 3, 4, 5])
slot.set_copy_from_slice;
println!; // > Some([0, 0, 1, 0, 2, .. ])
// Manual initialisation:
let s = "Hello, World!";
// allocate the node
let mut node = slot.allocate_uninit_array;
// initialise the data
node.copy_from_slice;
// insert the node
unsafe ;
println!; // > Some([72, 101, 108, 108, 111, .. ])
let mut slot = new;
slot.set_unsize;
println!; // > Some("Hello, World!")
// `MaybeUninitNode`s that don't get inserted are dropped automatically.
let _ = slot.;
TODO
This library is still in development and breaking changes may occur.
- Comment
unsafe
blocks. - Add tests.
License
The dynode
project is dual-licensed under either the Apache License Version 2.0 or MIT license at your option.