1use crate as rune;
4use crate::alloc::{self, try_format, Vec};
5use crate::compile;
6use crate::macros::{quote, FormatArgs, MacroContext, TokenStream};
7use crate::runtime::Function;
8use crate::{docstring, Any, ContextError, Module};
9
10#[rune::module(::std::test)]
12pub fn module() -> Result<Module, ContextError> {
13 let mut m = Module::from_meta(self::module__meta)?.with_unique("std::test");
14
15 m.macro_meta(assert)?;
16 m.macro_meta(assert_eq)?;
17 m.macro_meta(assert_ne)?;
18
19 m.ty::<Bencher>()?.docs(docstring! {
20 })?;
24
25 m.function_meta(Bencher::iter)?;
26 Ok(m)
27}
28
29#[derive(Default, Any)]
31#[rune(module = crate, item = ::std::test)]
32pub struct Bencher {
33 fns: Vec<Function>,
34}
35
36impl Bencher {
37 pub fn into_functions(self) -> Vec<Function> {
39 self.fns
40 }
41
42 #[rune::function]
44 fn iter(&mut self, f: Function) -> alloc::Result<()> {
45 self.fns.try_push(f)
46 }
47}
48
49#[rune::macro_]
64pub(crate) fn assert(
65 cx: &mut MacroContext<'_, '_, '_>,
66 stream: &TokenStream,
67) -> compile::Result<TokenStream> {
68 use crate as rune;
69
70 let mut it = cx.exprs(stream)?.into_iter().peekable();
71
72 let Some(expr) = it.next() else {
73 return Err(compile::Error::msg(
74 cx.input_span(),
75 "expected an expression to assert",
76 ));
77 };
78
79 let message = if it.peek().is_some() {
80 Some(FormatArgs::from_exprs(cx, it)?)
81 } else {
82 None
83 };
84
85 let output = if let Some(message) = &message {
86 let expanded = message.expand(cx)?;
87
88 quote!(if !(#expr) {
89 ::std::panic("assertion failed: " + (#expanded));
90 })
91 } else {
92 let message = try_format!("assertion failed: {}", cx.stringify(&expr)?);
93 let message = cx.lit(&message)?;
94
95 quote!(if !(#expr) {
96 ::std::panic(#message);
97 })
98 };
99
100 Ok(output.into_token_stream(cx)?)
101}
102
103#[rune::macro_]
115pub(crate) fn assert_eq(
116 cx: &mut MacroContext<'_, '_, '_>,
117 stream: &TokenStream,
118) -> compile::Result<TokenStream> {
119 use crate as rune;
120
121 let mut it = cx.exprs(stream)?.into_iter().peekable();
122
123 let (Some(left), Some(right)) = (it.next(), it.next()) else {
124 return Err(compile::Error::msg(
125 cx.input_span(),
126 "expected two expressions to compare",
127 ));
128 };
129
130 let message = if it.peek().is_some() {
131 Some(FormatArgs::from_exprs(cx, it)?)
132 } else {
133 None
134 };
135
136 let output = if let Some(message) = &message {
137 let message = message.expand(cx)?;
138
139 quote! {{
140 let left = #left;
141 let right = #right;
142
143 if !(left == right) {
144 let message = #message;
145 message += ::std::fmt::format!("\nleft: {:?}", left);
146 message += ::std::fmt::format!("\nright: {:?}", right);
147 ::std::panic("assertion failed (left == right): " + message);
148 }
149 }}
150 } else {
151 let message = cx.lit("assertion failed (left == right):")?;
152
153 quote! {{
154 let left = #left;
155 let right = #right;
156
157 if !(left == right) {
158 let message = ::std::string::String::from(#message);
159 message += ::std::fmt::format!("\nleft: {:?}", left);
160 message += ::std::fmt::format!("\nright: {:?}", right);
161 ::std::panic(message);
162 }
163 }}
164 };
165
166 Ok(output.into_token_stream(cx)?)
167}
168
169#[rune::macro_]
181pub(crate) fn assert_ne(
182 cx: &mut MacroContext<'_, '_, '_>,
183 stream: &TokenStream,
184) -> compile::Result<TokenStream> {
185 use crate as rune;
186
187 let mut it = cx.exprs(stream)?.into_iter().peekable();
188
189 let (Some(left), Some(right)) = (it.next(), it.next()) else {
190 return Err(compile::Error::msg(
191 cx.input_span(),
192 "expected two expressions to compare",
193 ));
194 };
195
196 let message = if it.peek().is_some() {
197 Some(FormatArgs::from_exprs(cx, it)?)
198 } else {
199 None
200 };
201
202 let output = if let Some(message) = &message {
203 let message = message.expand(cx)?;
204
205 quote! {{
206 let left = #left;
207 let right = #right;
208
209 if !(left != right) {
210 let message = #message;
211 message += ::std::fmt::format!("\nleft: {:?}", left);
212 message += ::std::fmt::format!("\nright: {:?}", right);
213 ::std::panic("assertion failed (left != right): " + message);
214 }
215 }}
216 } else {
217 let message = cx.lit("assertion failed (left != right):")?;
218
219 quote! {{
220 let left = #left;
221 let right = #right;
222
223 if !(left != right) {
224 let message = ::std::string::String::from(#message);
225 message += ::std::fmt::format!("\nleft: {:?}", left);
226 message += ::std::fmt::format!("\nright: {:?}", right);
227 ::std::panic(message);
228 }
229 }}
230 };
231
232 Ok(output.into_token_stream(cx)?)
233}