1#![no_std]
103
104#[cfg(feature = "alloc")]
105extern crate alloc;
106
107#[doc(hidden)]
108#[macro_export]
109#[cfg(feature = "alloc")]
110macro_rules! _stub_impl_dyn {
111 ($ty:ty) => {{
112 $crate::_stub_box::<$ty>()
113 }};
114}
115
116#[doc(hidden)]
117#[macro_export]
118#[cfg(not(feature = "alloc"))]
119macro_rules! _stub_impl_dyn {
120 ($ty:ty) => {{
121 compile_error!("stub!(impl dyn ...) requires the `alloc` feature")
122 }};
123}
124
125#[macro_export]
127macro_rules! stub {
128 (impl $ty:ty) => {{
129 $crate::_stub_impl_dyn!($ty)
130 }};
131 ($ty:ty, $fmt:expr) => {{
132 $crate::_stub_msg::<$ty>(format_args!($fmt))
133 }};
134 ($ty:ty, $fmt:expr, $($args:tt)*) => {{
135 $crate::_stub_msg::<$ty>(format_args!($fmt, $($args)*))
136 }};
137 ($ty:ty) => {{
138 $crate::_stub::<$ty>()
139 }};
140 ($fmt:expr) => {{
141 $crate::_stub_msg(format_args!($fmt))
142 }};
143 ($fmt:expr, $($args:tt)*) => {{
144 $crate::_stub_msg(format_args!($fmt, $($args)*))
145 }};
146 () => {{
147 $crate::_stub()
148 }};
149}
150
151#[macro_export]
153macro_rules! stub_iter {
154 () => {
155 $crate::_stub::<core::iter::Empty<_>>()
156 };
157 ($fmt:expr) => {
158 $crate::_stub_msg::<core::iter::Empty<_>>(format_args!($fmt))
159 };
160 ($fmt:expr, $($args:tt)*) => {
161 $crate::_stub_msg::<core::iter::Empty<_>>(format_args!($fmt, $($args)*))
162 };
163}
164
165#[macro_export]
167#[cfg(feature = "futures")]
168macro_rules! stub_stream {
169 () => {
170 $crate::_stub::<$crate::_StubEmptyStream<_>>()
171 };
172 ($fmt:expr) => {
173 $crate::_stub_msg::<$crate::_StubEmptyStream<_>>(format_args!($fmt))
174 };
175 ($fmt:expr, $($args:tt)*) => {
176 $crate::_stub_msg::<$crate::_StubEmptyStream<_>>(format_args!($fmt, $($args)*))
177 };
178}
179
180#[doc(hidden)]
181#[cfg(feature = "futures")]
182pub use futures_util_0_3::stream::Empty as _StubEmptyStream;
183
184#[doc(hidden)]
185pub fn _stub<T>() -> T {
186 todo!()
187}
188
189#[doc(hidden)]
190#[cfg(feature = "alloc")]
191pub fn _stub_box<T: ?Sized>() -> alloc::boxed::Box<T> {
192 _stub::<alloc::boxed::Box<T>>()
193}
194
195#[doc(hidden)]
196pub fn _stub_msg<T>(msg: core::fmt::Arguments<'_>) -> T {
197 todo!("{msg}")
198}
199
200#[cfg(test)]
201mod tests {
202 #[test]
203 #[should_panic]
204 fn test_panic() {
205 stub!()
206 }
207
208 #[test]
209 #[should_panic(expected = "Assigned to: John")]
210 fn test_panic_msg() {
211 let _: u32 = stub!(u32, "Assigned to: {}", "John");
212 }
213
214 #[cfg(feature = "alloc")]
215 #[test]
216 #[should_panic(expected = "Assigned to: x")]
217 fn test_panic_msg_with_path_expression() {
218 let _: u32 = stub!(u32, "Assigned to: {}", alloc::string::String::from("x"));
219 }
220
221 #[test]
222 #[should_panic(expected = "Assigned to: John")]
223 fn test_panic_msg_with_format_expression() {
224 let _: u32 = stub!(u32, concat!("Assigned to: ", "{}"), "John");
225 }
226
227 #[test]
228 #[should_panic(expected = "Assigned to: John")]
229 fn test_panic_msg_with_named_argument() {
230 let name = "John";
231 let _: u32 = stub!(u32, "Assigned to: {name}", name = name);
232 }
233
234 #[test]
235 #[should_panic]
236 fn test_panic_iter() {
237 fn iter() -> impl Iterator<Item = u32> {
238 stub_iter!()
239 }
240 let _ = iter();
241 }
242
243 #[cfg(feature = "alloc")]
244 #[test]
245 #[should_panic(expected = "Assigned to: x")]
246 fn test_panic_iter_with_path_expression() {
247 fn iter() -> impl Iterator<Item = u32> {
248 stub_iter!("Assigned to: {}", alloc::string::String::from("x"))
249 }
250 let _ = iter();
251 }
252
253 #[test]
254 #[should_panic(expected = "Assigned to: John")]
255 fn test_panic_iter_with_format_expression() {
256 fn iter() -> impl Iterator<Item = u32> {
257 stub_iter!(concat!("Assigned to: ", "{}"), "John")
258 }
259 let _ = iter();
260 }
261
262 #[test]
263 #[should_panic(expected = "Assigned to: John")]
264 fn test_panic_iter_with_named_argument() {
265 fn iter() -> impl Iterator<Item = u32> {
266 let name = "John";
267 stub_iter!("Assigned to: {name}", name = name)
268 }
269 let _ = iter();
270 }
271
272 #[cfg(feature = "alloc")]
273 #[test]
274 #[should_panic]
275 fn test_panic_dyn_display() {
276 fn display() -> impl core::fmt::Display {
277 stub!(impl dyn core::fmt::Display)
278 }
279 let _ = display();
280 }
281
282 #[cfg(feature = "alloc")]
283 #[test]
284 #[should_panic]
285 fn test_panic_dyn_iter() {
286 fn iter() -> impl Iterator<Item = u32> {
287 stub!(impl dyn Iterator<Item = u32>)
288 }
289 let _ = iter();
290 }
291
292 #[cfg(feature = "futures")]
293 #[test]
294 #[should_panic]
295 fn test_panic_stream() {
296 fn stream() -> impl futures_core_0_3::stream::Stream<Item = u32> {
297 stub_stream!()
298 }
299 let _ = stream();
300 }
301
302 #[cfg(all(feature = "alloc", feature = "futures"))]
303 #[test]
304 #[should_panic(expected = "Assigned to: x")]
305 fn test_panic_stream_with_path_expression() {
306 fn stream() -> impl futures_core_0_3::stream::Stream<Item = u32> {
307 stub_stream!("Assigned to: {}", alloc::string::String::from("x"))
308 }
309 let _ = stream();
310 }
311
312 #[cfg(feature = "futures")]
313 #[test]
314 #[should_panic(expected = "Assigned to: John")]
315 fn test_panic_stream_with_format_expression() {
316 fn stream() -> impl futures_core_0_3::stream::Stream<Item = u32> {
317 stub_stream!(concat!("Assigned to: ", "{}"), "John")
318 }
319 let _ = stream();
320 }
321
322 #[cfg(feature = "futures")]
323 #[test]
324 #[should_panic(expected = "Assigned to: John")]
325 fn test_panic_stream_with_named_argument() {
326 fn stream() -> impl futures_core_0_3::stream::Stream<Item = u32> {
327 let name = "John";
328 stub_stream!("Assigned to: {name}", name = name)
329 }
330 let _ = stream();
331 }
332}