1use proc_macro2::TokenStream;
2use quote::{ToTokens, quote};
3use std::{borrow::Cow, cmp::min, ffi::CString};
4use syn::Path;
5
6#[derive(Clone)]
7pub enum EitherIterator<A, B>
8where
9 A: Iterator,
10 B: Iterator<Item = A::Item>,
11{
12 Left(A),
13 Right(B),
14}
15impl<A, B> Iterator for EitherIterator<A, B>
16where
17 A: Iterator,
18 B: Iterator<Item = A::Item>,
19{
20 type Item = A::Item;
21 fn next(&mut self) -> Option<Self::Item> {
22 match self {
23 EitherIterator::Left(a) => a.next(),
24 EitherIterator::Right(b) => b.next(),
25 }
26 }
27}
28
29pub fn quote_cow<T: ToOwned + ToTokens + ?Sized>(value: &Cow<T>) -> TokenStream
30where
31 <T as ToOwned>::Owned: ToTokens,
32{
33 match value {
34 Cow::Borrowed(v) => quote! { ::std::borrow::Cow::Borrowed(#v) },
35 Cow::Owned(v) => quote! { ::std::borrow::Cow::Borrowed(#v) },
36 }
37}
38
39pub fn quote_option<T: ToTokens>(value: &Option<T>) -> TokenStream {
40 match value {
41 None => quote! { None },
42 Some(v) => quote! { Some(#v) },
43 }
44}
45
46pub fn matches_path(path: &Path, expect: &[&str]) -> bool {
47 let len = min(path.segments.len(), expect.len());
48 path.segments
49 .iter()
50 .rev()
51 .take(len)
52 .map(|v| &v.ident)
53 .eq(expect.iter().rev().take(len))
54}
55
56pub fn separated_by<T, F>(
57 out: &mut String,
58 values: impl IntoIterator<Item = T>,
59 mut f: F,
60 separator: &str,
61) where
62 F: FnMut(&mut String, T),
63{
64 let mut len = out.len();
65 for v in values {
66 if out.len() > len {
67 out.push_str(separator);
68 }
69 len = out.len();
70 f(out, v);
71 }
72}
73
74pub fn as_c_string<S: Into<Vec<u8>>>(str: S) -> CString {
75 CString::new(str.into()).expect("Expected a valid C string")
76}
77
78#[macro_export]
79macro_rules! possibly_parenthesized {
80 ($buff:ident, $cond:expr, $v:expr) => {
81 if $cond {
82 $buff.push('(');
83 $v;
84 $buff.push(')');
85 } else {
86 $v;
87 }
88 };
89}
90
91#[macro_export]
92macro_rules! printable_query {
93 ($query:expr) => {
94 format_args!(
95 "{}{}\n",
96 &$query[..::std::cmp::min($query.len(), 247)].trim_end(),
97 if $query.len() > 247 { "..." } else { "" },
98 )
99 };
100}
101
102#[macro_export]
104macro_rules! send_value {
105 ($tx:ident, $value:expr) => {{
106 if let Err(e) = $tx.send($value) {
107 log::error!("{:#}", e);
108 }
109 }};
110}
111
112#[macro_export]
116macro_rules! take_until {
117 ($original:expr, $($parser:expr),+ $(,)?) => {{
118 let macro_local_input = $original.fork();
119 let mut macro_local_result = (
120 TokenStream::new(),
121 ($({
122 let _ = $parser;
123 None
124 }),+),
125 );
126 loop {
127 if macro_local_input.is_empty() {
128 break;
129 }
130 let mut parsed = false;
131 let produced = ($({
132 let attempt = macro_local_input.fork();
133 if let Ok(content) = ($parser)(&attempt) {
134 macro_local_input.advance_to(&attempt);
135 parsed = true;
136 Some(content)
137 } else {
138 None
139 }
140 }),+);
141 if parsed {
142 macro_local_result.1 = produced;
143 break;
144 }
145 macro_local_result.0.append(macro_local_input.parse::<TokenTree>()?);
146 }
147 $original.advance_to(¯o_local_input);
148 macro_local_result
149 }};
150}