risingwave_frontend/utils/
mod.rs1mod pretty_serde;
16pub use pretty_serde::PrettySerde;
17mod column_index_mapping;
18use std::any::Any;
19use std::hash::{Hash, Hasher};
20use std::sync::LazyLock;
21
22pub use column_index_mapping::*;
23mod condition;
24pub mod data_type;
25pub use condition::*;
26mod connected_components;
27pub(crate) use connected_components::*;
28mod stream_graph_formatter;
29pub use stream_graph_formatter::*;
30mod with_options;
31use tokio::runtime::Runtime;
32pub use with_options::*;
33mod rewrite_index;
34pub use rewrite_index::*;
35mod index_set;
36pub use index_set::*;
37pub(crate) mod group_by;
38pub mod overwrite_options;
39pub use group_by::*;
40pub use overwrite_options::*;
41
42use crate::expr::{Expr, ExprImpl, ExprRewriter, InputRef};
43
44pub static FRONTEND_RUNTIME: LazyLock<Runtime> = LazyLock::new(|| {
45 tokio::runtime::Builder::new_multi_thread()
46 .thread_name("rw-frontend")
47 .enable_all()
48 .build()
49 .expect("failed to build frontend runtime")
50});
51
52pub struct Substitute {
54 pub mapping: Vec<ExprImpl>,
55}
56
57impl ExprRewriter for Substitute {
58 fn rewrite_input_ref(&mut self, input_ref: InputRef) -> ExprImpl {
59 assert_eq!(
60 input_ref.return_type(),
61 self.mapping[input_ref.index()].return_type(),
62 "Type mismatch when substituting {:?} with {:?}",
63 input_ref,
64 self.mapping[input_ref.index()],
65 );
66 self.mapping[input_ref.index()].clone()
67 }
68}
69
70pub trait Layer: Sized {
81 type Sub;
82
83 fn map<F>(self, f: F) -> Self
86 where
87 F: FnMut(Self::Sub) -> Self::Sub;
88
89 fn descent<F>(&self, f: F)
93 where
94 F: FnMut(&Self::Sub);
95}
96
97pub trait Tree = Layer<Sub = Self>;
99
100pub trait Endo<T: Tree> {
109 fn pre(&mut self, t: T) -> T {
110 t
111 }
112
113 fn post(&mut self, t: T) -> T {
114 t
115 }
116
117 fn apply(&mut self, t: T) -> T;
123
124 fn tree_apply(&mut self, t: T) -> T {
126 let t = self.pre(t).map(|s| self.apply(s));
127 self.post(t)
128 }
129}
130
131#[allow(unused_variables)]
134pub trait Visit<T: Tree> {
135 fn pre(&mut self, t: &T) {}
136
137 fn post(&mut self, t: &T) {}
138
139 fn visit(&mut self, t: &T);
140
141 fn tree_visit(&mut self, t: &T) {
142 self.pre(t);
143 t.descent(|i| self.visit(i));
144 self.post(t);
145 }
146}
147
148pub trait DynEq: Any {
154 fn as_any(&self) -> &dyn Any;
155 fn dyn_eq(&self, other: &dyn DynEq) -> bool;
156}
157
158impl<T: Any + Eq> DynEq for T {
159 fn as_any(&self) -> &dyn Any {
160 self
161 }
162
163 fn dyn_eq(&self, other: &dyn DynEq) -> bool {
164 let other = other.as_any().downcast_ref::<T>();
165 other.is_some_and(|other| self == other)
166 }
167}
168
169impl PartialEq<dyn DynEq + 'static> for dyn DynEq {
170 fn eq(&self, other: &Self) -> bool {
171 self.dyn_eq(other)
172 }
173}
174
175impl Eq for dyn DynEq {
176 fn assert_receiver_is_total_eq(&self) {}
177}
178
179pub trait DynHash: DynEq {
182 fn as_dyn_eq(&self) -> &dyn DynEq;
183 fn dyn_hash(&self, state: &mut dyn Hasher);
184}
185
186impl<T: DynEq + Hash> DynHash for T {
187 fn as_dyn_eq(&self) -> &dyn DynEq {
188 self
189 }
190
191 fn dyn_hash(&self, mut state: &mut dyn Hasher) {
192 T::hash(self, &mut state);
193 self.type_id().hash(&mut state);
194 }
195}
196
197impl Hash for dyn DynHash {
198 fn hash<H: Hasher>(&self, state: &mut H) {
199 self.dyn_hash(state);
200 }
201}
202
203pub fn ordinal(i: usize) -> String {
204 let s = i.to_string();
205 let suffix = if s.ends_with('1') && !s.ends_with("11") {
206 "st"
207 } else if s.ends_with('2') && !s.ends_with("12") {
208 "nd"
209 } else if s.ends_with('3') && !s.ends_with("13") {
210 "rd"
211 } else {
212 "th"
213 };
214 s + suffix
215}