pipecircuit 0.0.10

Correct. Robust. Fast. Portable.
Documentation
use core::{cell::Cell, ops::Range};

use super::LeaseStatus;

#[must_use = "byte leases recycle their extent when dropped unless explicitly retained"]
pub struct ByteLease<'pool> {
    pub(super) slot: usize,
    pub(super) generation: u64,
    pub(super) range: Range<usize>,
    pub(super) status: &'pool Cell<LeaseStatus>,
    pub(super) next: &'pool Cell<Option<usize>>,
    pub(super) released_lease_head: &'pool Cell<Option<usize>>,
    pub(super) storage: &'pool mut [u8],
    pub(super) recycle_on_drop: bool,
}

impl ByteLease<'_> {
    pub fn byte_capacity(&self) -> usize {
        self.storage.len()
    }

    pub fn bytes(&self) -> &[u8] {
        self.storage
    }

    pub fn bytes_mut(&mut self) -> &mut [u8] {
        self.storage
    }

    pub fn retain(mut self) -> RetainedByteLease {
        self.recycle_on_drop = false;
        RetainedByteLease {
            slot: self.slot,
            generation: self.generation,
            range: self.range.clone(),
        }
    }
}

impl Drop for ByteLease<'_> {
    fn drop(&mut self) {
        if self.recycle_on_drop && self.status.get() == LeaseStatus::Leased {
            self.next.set(self.released_lease_head.get());
            self.status.set(LeaseStatus::Released);
            self.released_lease_head.set(Some(self.slot));
        }
    }
}

#[derive(Debug, Eq, PartialEq)]
#[must_use = "retained byte leases must be resumed or recycled"]
pub struct RetainedByteLease {
    pub(super) slot: usize,
    pub(super) generation: u64,
    pub(super) range: Range<usize>,
}

impl RetainedByteLease {
    pub fn byte_capacity(&self) -> usize {
        self.range.len()
    }
}