surrealdb_core/mac/
mod.rs1#[macro_export]
3#[doc(hidden)]
4macro_rules! bytes {
5 ($expression:expr) => {
6 format!("{}\n", $expression).into_bytes()
7 };
8}
9
10#[macro_export]
12#[doc(hidden)]
13macro_rules! map {
14 ($($k:expr => $v:expr),* $(,)? $( => $x:expr )?) => {{
15 let mut m = ::std::collections::BTreeMap::new();
16 $(m.extend($x.iter().map(|(k, v)| (k.clone(), v.clone())));)?
17 $(m.insert($k, $v);)+
18 m
19 }};
20}
21
22#[macro_export]
24#[doc(hidden)]
25macro_rules! get_cfg {
26 ($i:ident : $($s:expr),+) => (
27 let $i = || { $( if cfg!($i=$s) { return $s; } );+ "unknown"};
28 )
29}
30
31#[macro_export]
46macro_rules! lazy_env_parse {
47 ($key:expr, $t:ty, $default:expr) => {
48 once_cell::sync::Lazy::new(|| {
49 std::env::var($key)
50 .and_then(|s| Ok(s.parse::<$t>().unwrap_or($default)))
51 .unwrap_or($default)
52 })
53 };
54}
55
56#[macro_export]
69macro_rules! lazy_env_parse_or_else {
70 ($key:expr, $t:ty, $default:expr) => {
71 once_cell::sync::Lazy::new(|| {
72 std::env::var($key)
73 .and_then(|s| Ok(s.parse::<$t>().unwrap_or_else($default)))
74 .unwrap_or_else($default)
75 })
76 };
77}
78
79#[cfg(test)]
80#[macro_export]
81macro_rules! async_defer{
82 (let $bind:ident = ($capture:expr) defer { $($d:tt)* } after { $($t:tt)* }) => {
83 async {
84 async_defer!(@captured);
85 async_defer!(@catch_unwind);
86
87 #[allow(unused_mut)]
88 let mut v = Some($capture);
89 #[allow(unused_mut)]
90 let mut $bind = Captured(&mut v);
91 let res = CatchUnwindFuture(async { $($t)* }).await;
92 #[allow(unused_variables,unused_mut)]
93 if let Some(mut $bind) = v.take(){
94 async { $($d)* }.await;
95 }
96 match res{
97 Ok(x) => x,
98 Err(e) => ::std::panic::resume_unwind(e)
99 }
100
101 }
102 };
103
104 (defer { $($d:tt)* } after { $($t:tt)* }) => {
105 async {
106 async_defer!(@catch_unwind);
107
108 let res = CatchUnwindFuture(async { $($t)* }).await;
109 #[allow(unused_variables)]
110 async { $($d)* }.await;
111 match res{
112 Ok(x) => x,
113 Err(e) => ::std::panic::resume_unwind(e)
114 }
115
116 }
117 };
118
119 (@captured) => {
120 pub struct Captured<'a,T>(&'a mut Option<T>);
122 impl<T> ::std::ops::Deref for Captured<'_,T>{
123 type Target = T;
124
125 fn deref(&self) -> &T{
126 self.0.as_ref().unwrap()
127 }
128 }
129 impl<T> ::std::ops::DerefMut for Captured<'_,T>{
130 fn deref_mut(&mut self) -> &mut T{
131 self.0.as_mut().unwrap()
132 }
133 }
134 impl<T> Captured<'_,T>{
135 #[allow(dead_code)]
136 pub fn take(self) -> T{
137 self.0.take().unwrap()
138 }
139 }
140 };
141
142 (@catch_unwind) => {
143 struct CatchUnwindFuture<F>(F);
144 impl<F,R> ::std::future::Future for CatchUnwindFuture<F>
145 where F: ::std::future::Future<Output = R>,
146 {
147 type Output = ::std::thread::Result<R>;
148
149 fn poll(self: ::std::pin::Pin<&mut Self>, cx: &mut ::std::task::Context<'_>) -> ::std::task::Poll<Self::Output>{
150 let pin = unsafe{ self.map_unchecked_mut(|x| &mut x.0) };
151 match ::std::panic::catch_unwind(::std::panic::AssertUnwindSafe(||{
152 pin.poll(cx)
153 })) {
154 Ok(x) => x.map(Ok),
155 Err(e) => ::std::task::Poll::Ready(Err(e))
156 }
157 }
158 }
159 };
160}
161
162#[cfg(test)]
163mod test {
164 #[tokio::test]
165 async fn async_defer_basic() {
166 let mut counter = 0;
167
168 async_defer!(defer {
169 assert_eq!(counter,1);
170 } after {
171 assert_eq!(counter,0);
172 counter += 1;
173 })
174 .await;
175
176 async_defer!(let t = (()) defer {
177 panic!("shouldn't be called");
178 } after {
179 assert_eq!(counter,1);
180 counter += 1;
181 t.take();
182 })
183 .await;
184 }
185
186 #[tokio::test]
187 #[should_panic(expected = "this is should be the message of the panic")]
188 async fn async_defer_panic() {
189 let mut counter = 0;
190
191 async_defer!(defer {
192 assert_eq!(counter,1);
194 panic!("this is should be the message of the panic")
195 } after {
196 assert_eq!(counter,0);
197 counter += 1;
198 panic!("this panic should be caught")
199 })
200 .await;
201 }
202}