laburnum 1.17.0

An LSP framework for building language servers and compilers, powered by an incremental query tree with content-addressed storage, task-based dataflow, and parallel queries.
Documentation
// Copyright Two Neutron Stars Incorporated and contributors
// SPDX-License-Identifier: BlueOak-1.0.0

use {
  crate::{ContentHash, Ident, database::PartitionKey},
  std::marker::PhantomData,
};

/// A typed handle to a record in a partition.
///
/// `RecordHandle<P>` wraps a `ContentHash` with partition type information.
/// The hash IS the handle - there's no separate slot key or handle invalidation.
///
/// # Type Safety
///
/// The phantom type parameter prevents mixing handles between partitions:
/// a `RecordHandle<Diagnostics>` cannot be used where a `RecordHandle<Symbols>`
/// is expected.
///
/// # Zero Overhead
///
/// `PhantomData<P>` is zero-sized, so `RecordHandle<P>` has the same memory
/// layout as `ContentHash`.
///
/// # No 'static Requirement
///
/// Uses `PartitionKey` instead of `Partition` as the bound because we only
/// need the compile-time key, not the full partition machinery. This avoids
/// propagating `'static` bounds to types that contain handles.
#[derive(Debug)]
pub struct RecordHandle<P: PartitionKey> {
  hash: ContentHash,
  _marker: PhantomData<P>,
}

impl<P: PartitionKey> RecordHandle<P> {
  /// Create a new handle from a content hash.
  #[inline]
  pub fn new(hash: ContentHash) -> Self {
    Self {
      hash,
      _marker: PhantomData,
    }
  }

  /// Get the partition key (compile-time constant).
  #[inline]
  pub fn partition_key() -> Ident {
    P::KEY
  }

  /// Get the underlying content hash.
  #[inline]
  pub fn content_hash(&self) -> ContentHash {
    self.hash
  }
}

impl<P: PartitionKey> Clone for RecordHandle<P> {
  fn clone(&self) -> Self {
    *self
  }
}

impl<P: PartitionKey> Copy for RecordHandle<P> {}

impl<P: PartitionKey> PartialEq for RecordHandle<P> {
  fn eq(&self, other: &Self) -> bool {
    self.hash == other.hash
  }
}

impl<P: PartitionKey> Eq for RecordHandle<P> {}

impl<P: PartitionKey> std::hash::Hash for RecordHandle<P> {
  fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
    self.hash.hash(state);
  }
}

impl<P: PartitionKey> PartialOrd for RecordHandle<P> {
  fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
    Some(self.cmp(other))
  }
}

impl<P: PartitionKey> Ord for RecordHandle<P> {
  fn cmp(&self, other: &Self) -> std::cmp::Ordering {
    self.hash.cmp(&other.hash)
  }
}