kodept-ast 0.4.1

Simple compiler with dependent types support in mind
Documentation
use std::fmt::{Debug, Formatter};
use std::hash::{Hash, Hasher};

use derive_more::{Display, From};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use slotgraph::{Key, NodeKey};

use crate::graph::{AnyNode, SubEnum};

#[derive(Display, From)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
#[repr(transparent)]
pub struct NodeId<Node>(Key<Node>);

pub type GenericNodeId = NodeId<AnyNode>;
pub type GenericNodeKey = Key<AnyNode>;

impl From<GenericNodeId> for Key<AnyNode> {
    fn from(value: GenericNodeId) -> Self {
        value.0
    }
}

impl<T> From<NodeKey> for NodeId<T> {
    fn from(value: NodeKey) -> Self {
        NodeId(value.into())
    }
}

impl<T> From<NodeId<T>> for NodeKey {
    fn from(value: NodeId<T>) -> Self {
        value.0.into()
    }
}

impl<T> NodeId<T> {
    pub fn null() -> Self {
        Self(Key::null())
    }

    pub fn cast<U>(self) -> NodeId<U>
    where
        U: TryFrom<T> + SubEnum,
    {
        NodeId(self.0.coerce())
    }
}

impl<T: Into<AnyNode>> NodeId<T> {
    pub fn widen(self) -> GenericNodeId {
        NodeId(self.0.coerce())
    }
}

impl GenericNodeId {
    pub fn coerce<U>(self) -> NodeId<U>
    where
        U: SubEnum,
    {
        NodeId(self.0.coerce_unchecked())
    }
}

impl GenericNodeId {
    pub fn narrow<T: TryFrom<AnyNode>>(self) -> NodeId<T> {
        NodeId(self.0.coerce())
    }
}

impl<T> Debug for NodeId<T> {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl<T> Hash for NodeId<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.0.hash(state);
    }
}

impl<T> PartialEq for NodeId<T> {
    fn eq(&self, other: &Self) -> bool {
        self.0.eq(&other.0)
    }
}

impl<T> Eq for NodeId<T> {}

impl<T> Clone for NodeId<T> {
    fn clone(&self) -> Self {
        *self
    }
}

impl<T> Copy for NodeId<T> {}