use crate::parser::SourceSpan;
use crate::Name;
use crate::Node;
use std::fmt;
use std::hash;
use std::ops::Deref;
use std::ops::DerefMut;
use triomphe::Arc;
#[derive(Debug, Clone)]
pub struct Component<T: ?Sized> {
pub origin: ComponentOrigin,
pub node: Node<T>,
}
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum ComponentOrigin {
Definition,
Extension(ExtensionId),
}
#[derive(Debug, Clone, Eq)]
pub struct ExtensionId {
arc: Arc<Option<SourceSpan>>,
}
impl ExtensionId {
pub fn new<T>(extension: &Node<T>) -> Self {
Self {
arc: Arc::new(extension.location()),
}
}
pub fn location(&self) -> Option<SourceSpan> {
*self.arc
}
pub fn same_location<T>(&self, node: T) -> Node<T> {
Node::new_opt_location(node, self.location())
}
}
impl PartialEq for ExtensionId {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.arc, &other.arc)
}
}
impl hash::Hash for ExtensionId {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
Arc::as_ptr(&self.arc).hash(state);
}
}
impl ComponentOrigin {
pub fn extension_id(&self) -> Option<&ExtensionId> {
match self {
ComponentOrigin::Definition => None,
ComponentOrigin::Extension(id) => Some(id),
}
}
}
impl<T> Component<T> {
pub fn new(node: T) -> Self {
Self {
origin: ComponentOrigin::Definition,
node: Node::new(node),
}
}
}
impl<T: ?Sized + hash::Hash> hash::Hash for Component<T> {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.node.hash(state); }
}
impl<T: ?Sized + Eq> Eq for Component<T> {}
impl<T: ?Sized + PartialEq> PartialEq for Component<T> {
fn eq(&self, other: &Self) -> bool {
self.node == other.node }
}
impl<T: ?Sized> Deref for Component<T> {
type Target = Node<T>;
fn deref(&self) -> &Self::Target {
&self.node
}
}
impl<T: ?Sized> DerefMut for Component<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.node
}
}
impl<T: ?Sized> AsRef<T> for Component<T> {
fn as_ref(&self) -> &T {
&self.node
}
}
impl<T> From<T> for Component<T> {
fn from(node: T) -> Self {
Component::new(node)
}
}
#[derive(Debug, Clone)]
pub struct ComponentName {
pub origin: ComponentOrigin,
pub name: Name,
}
impl From<&Name> for ComponentName {
fn from(value: &Name) -> Self {
value.to_component(ComponentOrigin::Definition)
}
}
impl From<Name> for ComponentName {
fn from(value: Name) -> Self {
value.to_component(ComponentOrigin::Definition)
}
}
impl hash::Hash for ComponentName {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.name.hash(state); }
}
impl Eq for ComponentName {}
impl PartialEq for ComponentName {
fn eq(&self, other: &Self) -> bool {
self.name == other.name }
}
impl PartialEq<str> for ComponentName {
fn eq(&self, other: &str) -> bool {
self.as_str() == other
}
}
impl PartialEq<Name> for ComponentName {
fn eq(&self, other: &Name) -> bool {
self.name == *other
}
}
impl Deref for ComponentName {
type Target = Name;
#[inline]
fn deref(&self) -> &Self::Target {
&self.name
}
}
impl std::borrow::Borrow<Name> for ComponentName {
fn borrow(&self) -> &Name {
self
}
}
impl std::borrow::Borrow<str> for ComponentName {
fn borrow(&self) -> &str {
self
}
}
impl AsRef<str> for ComponentName {
fn as_ref(&self) -> &str {
self
}
}
impl fmt::Display for ComponentName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.name.fmt(f)
}
}