Bug: 182523976

Clone this repo:
  1. 316566c Update Android.bp by running cargo_embargo am: 02f165065a by James Farrell · 8 weeks ago main master
  2. 02f1650 Update Android.bp by running cargo_embargo by James Farrell · 8 weeks ago
  3. bc8ab14 Update Android.bp by running cargo_embargo am: 7a7636da2d by James Farrell · 10 weeks ago
  4. 7a7636d Update Android.bp by running cargo_embargo by James Farrell · 10 weeks ago
  5. 023b95c Migrate to cargo_embargo. am: c1a6703d1d am: 7d16e942d2 am: 0a9dd6d149 by Andrew Walbran · 9 months ago android14-qpr3-release android14-qpr3-s2-release android-14.0.0_r50 android-14.0.0_r51 android-14.0.0_r52 android-14.0.0_r53 android-14.0.0_r54

Managed

managed is a library that provides a way to logically own objects, whether or not heap allocation is available. It works with rustc 1.26 or later.

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:

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 IPAddresses, which it either owns or borrows mutably;
  • a slice of Sockets, 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:

[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:

[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. It requires the use of 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 rustc 1.28 or later.

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:

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 for details.

License

managed is distributed under the terms of 0-clause BSD license.

See LICENSE-0BSD for details.