use serde::{Deserialize, Serialize};
use std::sync::atomic::AtomicU64;
use std::sync::atomic::Ordering::Relaxed;
macro_rules! def_id_tracker {
($name:ident) => {
#[derive(Debug, Serialize, Deserialize)]
pub struct $name {
id: AtomicU64,
}
impl $name {
pub fn new() -> Self {
Self {
id: AtomicU64::new(0),
}
}
pub fn new_at(id: u64) -> Self {
Self {
id: AtomicU64::new(id),
}
}
pub fn next(&self) -> u64 {
self.id.fetch_add(1, Relaxed)
}
pub fn peek(&self) -> u64 {
self.id.load(Relaxed)
}
pub fn make_clone(&self) -> Self {
Self {
id: AtomicU64::new(self.id.load(Relaxed)),
}
}
}
impl Default for $name {
fn default() -> Self {
Self::new()
}
}
};
}
macro_rules! def_typed_id_tracker {
($name:ident, $type_name:ident) => {
#[derive(Debug, Serialize, Deserialize)]
pub struct $name {
id: AtomicU64,
}
impl $name {
pub fn new() -> Self {
Self {
id: AtomicU64::new(0),
}
}
pub fn new_at(id: u64) -> Self {
Self {
id: AtomicU64::new(id),
}
}
pub fn next(&self) -> $type_name {
let result = self.id.fetch_add(1, Relaxed);
$type_name(result)
}
pub fn peek(&self) -> u64 {
self.id.load(Relaxed)
}
pub fn make_clone(&self) -> Self {
Self {
id: AtomicU64::new(self.id.load(Relaxed)),
}
}
}
impl Default for $name {
fn default() -> Self {
Self::new()
}
}
};
}
pub struct NameIdInner(pub u64);
#[derive(Eq, PartialEq, PartialOrd, Ord, Hash, Clone, Copy, Serialize, Deserialize, Debug)]
pub struct ExprID(pub u64);
#[derive(Eq, PartialEq, PartialOrd, Ord, Hash, Clone, Copy, Serialize, Deserialize, Debug)]
pub struct ImplID(pub u64);
def_typed_id_tracker!(ExprIdTracker, ExprID);
def_typed_id_tracker!(ImplIdTracker, ImplID);
def_id_tracker!(NameIdTracker);
def_id_tracker!(AAVarTracker);