use crate::parser::FileId;
use crate::parser::LineColumn;
use crate::parser::SourceMap;
use crate::parser::SourceSpan;
use crate::schema::Component;
use crate::schema::ComponentOrigin;
use std::fmt;
use std::hash::Hash;
use std::hash::Hasher;
use std::ops::Range;
use triomphe::HeaderSlice;
#[derive(serde::Deserialize)]
#[serde(from = "T")]
pub struct Node<T: ?Sized>(triomphe::Arc<HeaderSlice<Header, T>>);
#[derive(Clone)]
struct Header {
location: Option<SourceSpan>,
}
impl<T> Node<T> {
#[inline]
pub fn new_parsed(node: T, location: SourceSpan) -> Self {
Self::new_opt_location(node, Some(location))
}
pub fn new(node: T) -> Self {
Self::new_opt_location(node, None)
}
pub(crate) fn new_opt_location(node: T, location: Option<SourceSpan>) -> Self {
Self(triomphe::Arc::new(HeaderSlice {
header: Header { location },
slice: node,
}))
}
}
impl Node<str> {
#[inline]
pub fn new_str_parsed(node: &str, location: SourceSpan) -> Self {
Self::new_str_opt_location(node, Some(location))
}
pub fn new_str(node: &str) -> Self {
Self::new_str_opt_location(node, None)
}
pub(crate) fn new_str_opt_location(node: &str, location: Option<SourceSpan>) -> Self {
Self(triomphe::Arc::from_header_and_str(
Header { location },
node,
))
}
pub fn as_str(&self) -> &str {
self
}
}
impl<T: ?Sized> Node<T> {
pub fn location(&self) -> Option<SourceSpan> {
self.0.header.location
}
pub fn is_built_in(&self) -> bool {
self.location().map(|l| l.file_id()) == Some(FileId::BUILT_IN)
}
pub fn line_column_range(&self, sources: &SourceMap) -> Option<Range<LineColumn>> {
self.location()?.line_column_range(sources)
}
pub fn same_location<U>(&self, node: U) -> Node<U> {
Node::new_opt_location(node, self.0.header.location)
}
pub fn to_component(&self, origin: ComponentOrigin) -> Component<T> {
Component {
origin,
node: self.clone(),
}
}
pub fn ptr_eq(&self, other: &Self) -> bool {
triomphe::Arc::ptr_eq(&self.0, &other.0)
}
pub fn make_mut(&mut self) -> &mut T
where
T: Clone,
{
let inner = triomphe::Arc::make_mut(&mut self.0);
&mut inner.slice
}
pub fn get_mut(&mut self) -> Option<&mut T> {
triomphe::Arc::get_mut(&mut self.0).map(|inner| &mut inner.slice)
}
}
impl<T: ?Sized> std::ops::Deref for Node<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0.slice
}
}
impl<T: ?Sized> Clone for Node<T> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl<T: Default> Default for Node<T> {
fn default() -> Self {
Self::new(T::default())
}
}
impl<T: ?Sized + fmt::Debug> fmt::Debug for Node<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(location) = self.location() {
write!(f, "{location:?} ")?
}
self.0.slice.fmt(f)
}
}
impl<T: ?Sized + fmt::Display> fmt::Display for Node<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
T::fmt(self, f)
}
}
impl<T: ?Sized + Eq> Eq for Node<T> {}
impl<T: ?Sized + PartialEq> PartialEq for Node<T> {
fn eq(&self, other: &Self) -> bool {
self.ptr_eq(other) || self.0.slice == other.0.slice }
}
impl<T: ?Sized + Hash> Hash for Node<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.slice.hash(state)
}
}
impl<T: ?Sized> std::borrow::Borrow<T> for Node<T> {
fn borrow(&self) -> &T {
self
}
}
impl<T: ?Sized> AsRef<T> for Node<T> {
fn as_ref(&self) -> &T {
self
}
}
impl<T> From<T> for Node<T> {
fn from(node: T) -> Self {
Self::new(node)
}
}
impl From<&'_ str> for Node<str> {
fn from(node: &'_ str) -> Self {
Self::new_str(node)
}
}
impl From<&'_ String> for Node<str> {
fn from(node: &'_ String) -> Self {
Self::new_str(node)
}
}
impl From<String> for Node<str> {
fn from(node: String) -> Self {
Self::new_str(&node)
}
}
impl From<&'_ Node<str>> for String {
fn from(node: &'_ Node<str>) -> Self {
node.as_str().to_owned()
}
}
impl From<Node<str>> for String {
fn from(node: Node<str>) -> Self {
node.as_str().to_owned()
}
}
impl<T: serde::Serialize> serde::Serialize for Node<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
T::serialize(self, serializer)
}
}