1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#![deny(unsafe_code)]
#![warn(
	clippy::cargo,
	clippy::nursery,
	clippy::pedantic,
	clippy::restriction,
	future_incompatible,
	rust_2018_idioms
)]
#![warn(
	box_pointers,
	macro_use_extern_crate,
	meta_variable_misuse,
	missing_copy_implementations,
	missing_crate_level_docs,
	missing_debug_implementations,
	missing_docs,
	non_ascii_idents,
	single_use_lifetimes,
	trivial_casts,
	trivial_numeric_casts,
	unaligned_references,
	unreachable_pub,
	unused_import_braces,
	unused_lifetimes,
	unused_qualifications,
	unused_results,
	variant_size_differences
)]
#![allow(
	clippy::blanket_clippy_restriction_lints,
	clippy::else_if_without_else,
	clippy::exhaustive_enums,
	clippy::future_not_send,
	clippy::implicit_return,
	clippy::missing_inline_in_public_items,
	clippy::non_ascii_literal,
	clippy::pattern_type_mismatch,
	clippy::redundant_pub_crate,
	clippy::shadow_reuse,
	clippy::tabs_in_doc_comments,
	clippy::unreachable,
	clippy::wildcard_enum_match_arm,
	variant_size_differences
)]
#![allow(clippy::cargo_common_metadata)]
#![cfg_attr(
	doc,
	warn(rustdoc::all),
	allow(rustdoc::missing_doc_code_examples, rustdoc::private_doc_tests)
)]

//! Proc-Macros for the `allochronic-util` crate.

use proc_macro::TokenStream;
use proc_macro2::Span;
use syn::Error;

mod select;

/// Easy generation of errors in proc macros.
fn error(span: Span, message: &str) -> TokenStream {
	Error::new(span, message).into_compile_error().into()
}

/// Polls all passed [`Future`](std::future::Future)s or
/// [`Stream`](std::stream::Stream)s until one is ready and returns
/// it. Prioritizes by order.
///
/// # Raw-mode
/// If the `complete` item is unspecified, [`Future`](std::future::Future)s and
/// [`Stream`](std::stream::Stream)s will be pulled beyond exhaustion. If a high
/// priority item is exhausted and [`select!`](crate::select!) is being used in
/// a loop, it will continuously return the same result, which might be
/// unintended.
///
/// # Fused-mode
/// If the `complete` item is specified, all polled items have to implement
/// `FusedFuture` or `FusedStream`, for [`Stream`](std::stream::Stream)s this
/// will unwrap the [`Option`]. The `complete` item will be executed once all
/// items have been exhausted. Items will not be pulled beyond exhaustion.
///
/// # Examples
/// Raw-mode:
/// ```
/// # futures_executor::block_on(async {
/// use futures_util::stream;
/// use allochronic_util::select;
///
/// let mut stream1 = stream::iter(1..=3);
/// let mut stream2 = stream::iter(4..=6);
/// let mut stream3 = stream::iter(7..=9);
///
/// let mut counter = 0;
///
/// while let Some(result) = select![
/// 	result: &mut stream1 => result,
/// 	result: &mut stream2 => result,
/// 	result: &mut stream3 => result,
/// ] {
/// 	counter += 1;
/// 	assert_eq!(counter, result);
/// }
///
/// // this loop will only reach the number of three, because it will abort after the first stream
/// // is exhausted
/// assert_eq!(counter, 3);
/// # });
/// ```
/// Fused-mode:
/// ```
/// # futures_executor::block_on(async {
/// use futures_util::stream::{self, StreamExt};
/// use allochronic_util::select;
///
/// let mut stream1 = stream::iter(1..=3).fuse();
/// let mut stream2 = stream::iter(4..=6).fuse();
/// let mut stream3 = stream::iter(7..=9).fuse();
///
/// let mut counter = 0;
///
/// while let Some(result) = select![
/// 	result: &mut stream1 => Some(result),
/// 	result: &mut stream2 => Some(result),
/// 	result: &mut stream3 => Some(result),
/// 	complete => None,
/// ] {
/// 	counter += 1;
/// 	assert_eq!(counter, result);
/// }
///
/// assert_eq!(counter, 9);
/// # });
/// ```
#[proc_macro]
pub fn select(item: TokenStream) -> TokenStream {
	select::select(item)
}