lang_util/node/
content.rs1use std::fmt;
2
3use crate::position::{LexerPosition, NodeSpan};
4
5pub trait NodeContent: fmt::Debug + Clone + PartialEq + Sized {
9 fn into_node<T>(self) -> Node<T>
11 where
12 T: From<Self> + NodeContent,
13 {
14 Node::new(self.into(), None)
15 }
16
17 fn spanned(self, start: LexerPosition, end: LexerPosition) -> Node<Self> {
19 assert_eq!(start.source_id, end.source_id);
20
21 Node {
22 content: self,
23 span: Some(NodeSpan::from_lexer(start, end)),
24 }
25 }
26}
27
28#[derive(Debug, Clone)]
30#[cfg_attr(feature = "serde", derive(rserde::Serialize, rserde::Deserialize))]
31#[cfg_attr(feature = "serde", serde(crate = "rserde"))]
32pub struct Node<T: NodeContent> {
33 pub content: T,
35 pub span: Option<NodeSpan>,
37}
38
39impl<T: NodeContent> Node<T> {
40 pub fn new(content: T, span: Option<NodeSpan>) -> Self {
42 Self { content, span }
43 }
44
45 pub fn into_inner(self) -> T {
47 self.content
48 }
49
50 pub fn map<U: NodeContent>(self, f: impl FnOnce(T) -> U) -> Node<U> {
52 Node {
53 content: f(self.content),
54 span: self.span,
55 }
56 }
57
58 pub fn map_spanned<U: NodeContent>(self, f: impl FnOnce(Self) -> U) -> Node<U> {
60 let span = self.span;
61
62 Node {
63 content: f(self),
64 span,
65 }
66 }
67}
68
69impl<T: NodeContent> std::ops::Deref for Node<T> {
70 type Target = T;
71
72 fn deref(&self) -> &Self::Target {
73 &self.content
74 }
75}
76
77impl<T: NodeContent> std::ops::DerefMut for Node<T> {
78 fn deref_mut(&mut self) -> &mut Self::Target {
79 &mut self.content
80 }
81}
82
83impl<T: NodeContent + Copy> Copy for Node<T> {}
85
86impl<T: NodeContent + fmt::Display> fmt::Display for Node<T> {
88 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89 <T as fmt::Display>::fmt(&self.content, f)
90 }
91}
92
93impl<T: NodeContent> From<T> for Node<T> {
94 fn from(inner: T) -> Self {
95 Node::new(inner, None)
96 }
97}
98
99impl NodeContent for &'static str {}
100
101impl<U, T: NodeContent + AsRef<U>> AsRef<U> for Node<T> {
102 fn as_ref(&self) -> &U {
103 self.content.as_ref()
104 }
105}
106
107impl<T: NodeContent + PartialEq> PartialEq for Node<T> {
108 fn eq(&self, other: &Self) -> bool {
109 self.content.eq(&other.content)
110 }
111}
112
113impl<T: NodeContent + Eq> Eq for Node<T> {}
114
115impl<T: NodeContent + PartialOrd> PartialOrd for Node<T> {
116 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
117 self.content.partial_cmp(&other.content)
118 }
119}
120
121impl<T: NodeContent + Ord> Ord for Node<T> {
122 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
123 self.content.cmp(&other.content)
124 }
125}
126
127impl<T: NodeContent + std::hash::Hash> std::hash::Hash for Node<T> {
128 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
129 self.content.hash(state)
130 }
131}