#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum TraceContractVersion {
V1,
}
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
pub struct ManagedId(u64);
impl ManagedId {
pub const fn allocation_ordinal(self) -> u64 {
self.0
}
}
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
pub struct RootId(u64);
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub struct ManagedHandle {
id: ManagedId,
}
impl ManagedHandle {
pub const fn id(self) -> ManagedId {
self.id
}
pub const fn downgrade(self) -> WeakHandle {
WeakHandle { id: self.id }
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub struct RootedHandle {
root: RootId,
handle: ManagedHandle,
}
impl RootedHandle {
pub const fn root_id(self) -> RootId {
self.root
}
pub const fn handle(self) -> ManagedHandle {
self.handle
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub struct WeakHandle {
id: ManagedId,
}
impl WeakHandle {
pub const fn id(self) -> ManagedId {
self.id
}
}
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
pub struct EdgeId(pub u32);
impl EdgeId {
pub const fn allocation_ordinal(self) -> u32 {
self.0
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum EdgeKind {
Strong,
Weak,
Ephemeron,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct EdgeLimits {
total: usize,
strong: usize,
weak: usize,
ephemeron: usize,
}
impl EdgeLimits {
pub const DEFAULT: Self = Self::new(65_536, 65_536, 65_536, 65_536);
pub const fn new(total: usize, strong: usize, weak: usize, ephemeron: usize) -> Self {
Self {
total,
strong,
weak,
ephemeron,
}
}
pub const fn total(self) -> usize {
self.total
}
pub const fn for_kind(self, kind: EdgeKind) -> usize {
match kind {
EdgeKind::Strong => self.strong,
EdgeKind::Weak => self.weak,
EdgeKind::Ephemeron => self.ephemeron,
}
}
}
impl Default for EdgeLimits {
fn default() -> Self {
Self::DEFAULT
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum EdgeSnapshot {
Strong {
edge: EdgeId,
target: ManagedId,
},
Weak {
edge: EdgeId,
target: ManagedId,
},
Ephemeron {
edge: EdgeId,
key: ManagedId,
value: ManagedId,
},
}
impl EdgeSnapshot {
pub const fn id(self) -> EdgeId {
match self {
Self::Strong { edge, .. } | Self::Weak { edge, .. } | Self::Ephemeron { edge, .. } => {
edge
}
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub struct TypedEdgeId {
id: EdgeId,
kind: EdgeKind,
}
impl TypedEdgeId {
pub const fn id(self) -> EdgeId {
self.id
}
pub const fn kind(self) -> EdgeKind {
self.kind
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum EdgeAllocationError {
IdentityExhausted,
CapacityExceeded {
kind: EdgeKind,
cap: usize,
},
}
impl fmt::Display for EdgeAllocationError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::IdentityExhausted => f.write_str("managed edge identity space exhausted"),
Self::CapacityExceeded { kind, cap } => {
write!(f, "managed {kind:?} edge cap {cap} reached")
}
}
}
}
impl Error for EdgeAllocationError {}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct EdgeAllocator {
next: Option<u32>,
}
impl EdgeAllocator {
pub const fn new() -> Self {
Self { next: Some(0) }
}
pub fn allocate(&mut self, kind: EdgeKind) -> Result<TypedEdgeId, EdgeAllocationError> {
let ordinal = self.next.ok_or(EdgeAllocationError::IdentityExhausted)?;
self.next = ordinal.checked_add(1);
Ok(TypedEdgeId {
id: EdgeId(ordinal),
kind,
})
}
#[cfg(test)]
pub(crate) const fn starting_at(next: u32) -> Self {
Self { next: Some(next) }
}
}
impl Default for EdgeAllocator {
fn default() -> Self {
Self::new()
}
}