126 lines
4.0 KiB
Markdown
126 lines
4.0 KiB
Markdown
Managed
|
|
=======
|
|
|
|
_managed_ is a library that provides a way to logically own objects, whether or not
|
|
heap allocation is available.
|
|
|
|
Motivation
|
|
----------
|
|
|
|
The _managed_ library exists at the intersection of three concepts: _heap-less environments_,
|
|
_collections_ and _generic code_. Consider this struct representing a network interface:
|
|
|
|
```rust
|
|
pub struct Interface<'a, 'b: 'a,
|
|
DeviceT: Device,
|
|
ProtocolAddrsT: BorrowMut<[IpAddress]>,
|
|
SocketsT: BorrowMut<[Socket<'a, 'b>]>
|
|
> {
|
|
device: DeviceT,
|
|
hardware_addr: EthernetAddress,
|
|
protocol_addrs: ProtocolAddrsT,
|
|
sockets: SocketsT,
|
|
phantom: PhantomData<Socket<'a, 'b>>
|
|
}
|
|
```
|
|
|
|
There are three things the struct `Interface` is parameterized over:
|
|
* an object implementing the trait `DeviceT`, which it owns;
|
|
* a slice of `IPAddress`es, which it either owns or borrows mutably;
|
|
* a slice of `Socket`s, which it either owns or borrows mutably, and which further either
|
|
own or borrow some memory.
|
|
|
|
The motivation for using `BorrowMut` is that in environments with heap, the struct ought to
|
|
own a `Vec`; on the other hand, without heap there is neither `Vec` nor `Box`, and it is only
|
|
possible to use a `&mut`. Both of these implement BorrowMut.
|
|
|
|
Note that owning a `BorrowMut` in this way does not hide the concrete type inside `BorrowMut`;
|
|
if the slice is backed by a `Vec` then the `Vec` may still be resized by external code,
|
|
although not the implementation of `Interface`.
|
|
|
|
In isolation, this struct is easy to use. However, when combined with another codebase, perhaps
|
|
embedded in a scheduler, problems arise. The type parameters have to go somewhere! There
|
|
are two choices:
|
|
* either the type parameters, whole lot of them, infect the scheduler and push ownership
|
|
even higher in the call stack (self-mutably-borrowing structs are not usable in safe Rust,
|
|
so the scheduler could not easily own the slices);
|
|
* or the interface is owned as a boxed trait object, excluding heap-less systems.
|
|
|
|
Clearly, both options are unsatisfying. Enter _managed_!
|
|
|
|
Installation
|
|
------------
|
|
|
|
To use the _managed_ library in your project, add the following to `Cargo.toml`:
|
|
|
|
```toml
|
|
[dependencies]
|
|
managed = "0.6"
|
|
```
|
|
|
|
The default configuration assumes a hosted environment, for ease of evaluation.
|
|
You probably want to disable default features and configure them one by one:
|
|
|
|
```toml
|
|
[dependencies]
|
|
managed = { version = "...", default-features = false, features = ["..."] }
|
|
```
|
|
|
|
### Feature `std`
|
|
|
|
The `std` feature enables use of `Box`, `Vec`, and `BTreeMap` through a dependency
|
|
on the `std` crate.
|
|
|
|
### Feature `alloc`
|
|
|
|
The `alloc` feature enables use of `Box`, `Vec`, and `BTreeMap` through a dependency
|
|
on the `alloc` crate. This only works on nightly rustc.
|
|
|
|
### Feature `map`
|
|
|
|
The `map` feature, disabled by default, enables the `ManagedMap` enum.
|
|
Its interface is not stable yet and is subject to change.
|
|
It also requires the use of a nightly compiler.
|
|
|
|
Usage
|
|
-----
|
|
|
|
_managed_ is an interoperability crate: it does not include complex functionality but rather
|
|
defines an interface that may be used by many downstream crates. It includes three enums:
|
|
|
|
```rust
|
|
pub enum Managed<'a, T: 'a + ?Sized> {
|
|
Borrowed(&'a mut T),
|
|
#[cfg(/* Box available */)]
|
|
Owned(Box<T>),
|
|
}
|
|
|
|
pub enum ManagedSlice<'a, T: 'a> {
|
|
Borrow(&'a mut [T]),
|
|
#[cfg(/* Vec available */)]
|
|
Owned(Vec<T>)
|
|
}
|
|
|
|
// The implementation of ManagedMap is not yet stable, beware!
|
|
pub enum ManagedMap<'a, K: Hash + 'a, V: 'a> {
|
|
Borrowed(&'a mut [Option<(K, V)>]),
|
|
#[cfg(/* BTreeMap available */)]
|
|
Owned(BTreeMap<K, V>)
|
|
}
|
|
```
|
|
|
|
The `Managed` and `ManagedSlice` enums have the `From` implementations from the corresponding
|
|
types, and `Deref`/`DerefMut` implementations to the type `T`, as well as other helper methods,
|
|
and `ManagedMap` is implemented using either a B-tree map or a sorted slice of key-value pairs.
|
|
|
|
See the [full documentation][doc] for details.
|
|
|
|
[doc]: https://docs.rs/managed/
|
|
|
|
License
|
|
-------
|
|
|
|
_managed_ is distributed under the terms of 0-clause BSD license.
|
|
|
|
See [LICENSE-0BSD](LICENSE-0BSD.txt) for details.
|