salsa/src/intern_id.rs

130 lines
3.5 KiB
Rust
Raw Normal View History

2019-03-30 09:43:16 +00:00
use std::fmt;
2019-03-31 09:49:41 +00:00
use std::num::NonZeroU32;
2019-03-30 09:43:16 +00:00
/// The "raw-id" is used for interned keys in salsa -- it is basically
/// a newtype'd u32. Typically, it is wrapped in a type of your own
/// devising. For more information about interned keys, see [the
/// interned key RFC][rfc].
2019-03-30 09:43:16 +00:00
///
2019-04-03 14:00:59 +00:00
/// # Creating a `InternId`
2019-03-30 09:43:16 +00:00
//
2019-04-03 14:00:59 +00:00
/// InternId values can be constructed using the `From` impls,
2019-03-30 09:43:16 +00:00
/// which are implemented for `u32` and `usize`:
///
/// ```
2019-04-03 14:00:59 +00:00
/// # use salsa::InternId;
/// let intern_id1 = InternId::from(22_u32);
/// let intern_id2 = InternId::from(22_usize);
/// assert_eq!(intern_id1, intern_id2);
2019-03-30 09:43:16 +00:00
/// ```
///
/// # Converting to a u32 or usize
///
/// Normally, there should be no need to access the underlying integer
2019-04-03 14:00:59 +00:00
/// in a `InternId`. But if you do need to do so, you can convert to a
/// `usize` using the `as_u32` or `as_usize` methods or the `From` impls.
///
/// ```
2019-04-03 14:00:59 +00:00
/// # use salsa::InternId;
/// let intern_id = InternId::from(22_u32);
/// let value = u32::from(intern_id);
2019-03-30 09:43:16 +00:00
/// assert_eq!(value, 22);
/// ```
///
/// ## Illegal values
///
2019-04-03 14:00:59 +00:00
/// Be warned, however, that `InternId` values cannot be created from
2019-03-30 09:43:16 +00:00
/// *arbitrary* values -- in particular large values greater than
2019-04-03 14:00:59 +00:00
/// `InternId::MAX` will panic. Those large values are reserved so that
2019-03-30 09:43:16 +00:00
/// the Rust compiler can use them as sentinel values, which means
2019-04-03 14:00:59 +00:00
/// that (for example) `Option<InternId>` is represented in a single
2019-03-30 09:43:16 +00:00
/// word.
///
/// ```should_panic
2019-04-03 14:00:59 +00:00
/// # use salsa::InternId;
/// InternId::from(InternId::MAX);
2019-03-30 09:43:16 +00:00
/// ```
///
/// [rfc]: https://github.com/salsa-rs/salsa-rfcs/pull/2
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
2019-04-03 14:00:59 +00:00
pub struct InternId {
2019-03-31 09:49:41 +00:00
value: NonZeroU32,
2019-03-30 09:43:16 +00:00
}
2019-04-03 14:00:59 +00:00
impl InternId {
/// The maximum allowed `InternId`. This value can grow between
2019-03-30 09:43:16 +00:00
/// releases without affecting semver.
pub const MAX: u32 = 0xFFFF_FF00;
2019-04-03 14:00:59 +00:00
/// Creates a new InternId. Unsafe as `value` must be less than `MAX`
2019-03-31 09:49:41 +00:00
/// and this is not checked in release builds.
2019-03-30 09:43:16 +00:00
unsafe fn new_unchecked(value: u32) -> Self {
2019-04-03 14:00:59 +00:00
debug_assert!(value < InternId::MAX);
InternId {
2019-03-31 09:49:41 +00:00
value: NonZeroU32::new_unchecked(value + 1),
}
2019-03-30 09:43:16 +00:00
}
/// Convert this raw-id into a u32 value.
///
/// ```
2019-04-03 14:00:59 +00:00
/// # use salsa::InternId;
/// let intern_id = InternId::from(22_u32);
/// let value = intern_id.as_usize();
/// assert_eq!(value, 22);
/// ```
pub fn as_u32(self) -> u32 {
self.value.get() - 1
}
2019-03-30 09:43:16 +00:00
/// Convert this raw-id into a usize value.
///
/// ```
2019-04-03 14:00:59 +00:00
/// # use salsa::InternId;
/// let intern_id = InternId::from(22_u32);
/// let value = intern_id.as_usize();
/// assert_eq!(value, 22);
/// ```
2019-03-30 09:43:16 +00:00
pub fn as_usize(self) -> usize {
self.as_u32() as usize
}
}
2019-04-03 14:00:59 +00:00
impl From<InternId> for u32 {
fn from(raw: InternId) -> u32 {
raw.as_u32()
2019-03-30 09:43:16 +00:00
}
}
2019-04-03 14:00:59 +00:00
impl From<InternId> for usize {
fn from(raw: InternId) -> usize {
2019-03-31 09:49:41 +00:00
raw.as_usize()
2019-03-30 09:43:16 +00:00
}
}
2019-04-03 14:00:59 +00:00
impl From<u32> for InternId {
fn from(id: u32) -> InternId {
assert!(id < InternId::MAX);
unsafe { InternId::new_unchecked(id) }
2019-03-30 09:43:16 +00:00
}
}
2019-04-03 14:00:59 +00:00
impl From<usize> for InternId {
fn from(id: usize) -> InternId {
assert!(id < (InternId::MAX as usize));
unsafe { InternId::new_unchecked(id as u32) }
2019-03-30 09:43:16 +00:00
}
}
2019-04-03 14:00:59 +00:00
impl fmt::Debug for InternId {
2019-03-30 09:43:16 +00:00
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2019-03-31 09:49:41 +00:00
self.as_usize().fmt(f)
2019-03-30 09:43:16 +00:00
}
}
2019-04-03 14:00:59 +00:00
impl fmt::Display for InternId {
2019-03-30 09:43:16 +00:00
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2019-03-31 09:49:41 +00:00
self.as_usize().fmt(f)
2019-03-30 09:43:16 +00:00
}
}