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 matches_path(path: &Path, expect: &[&str]) -> bool {
40 let len = min(path.segments.len(), expect.len());
41 path.segments
42 .iter()
43 .rev()
44 .take(len)
45 .map(|v| &v.ident)
46 .eq(expect.iter().rev().take(len))
47}
48
49pub fn separated_by<T, F>(
50 out: &mut String,
51 values: impl IntoIterator<Item = T>,
52 mut f: F,
53 separator: &str,
54) where
55 F: FnMut(&mut String, T),
56{
57 let mut len = out.len();
58 for v in values {
59 if out.len() > len {
60 out.push_str(separator);
61 }
62 len = out.len();
63 f(out, v);
64 }
65}
66
67pub fn as_c_string<S: Into<Vec<u8>>>(str: S) -> CString {
68 CString::new(str.into()).expect("Expected a valid C string")
69}
70
71#[macro_export]
72macro_rules! possibly_parenthesized {
73 ($buff:ident, $cond:expr, $v:expr) => {
74 if $cond {
75 $buff.push('(');
76 $v;
77 $buff.push(')');
78 } else {
79 $v;
80 }
81 };
82}
83
84#[macro_export]
85macro_rules! printable_query {
86 ($query:expr) => {
87 format_args!(
88 "{}{}\n",
89 &$query[..::std::cmp::min($query.len(), 247)].trim_end(),
90 if $query.len() > 247 { "..." } else { "" },
91 )
92 };
93}
94
95#[macro_export]
96macro_rules! send_error {
97 ($tx:ident, $error:expr) => {{
98 let error = $error;
99 ::log::error!("{:#}", error);
100 if let Err(send_error) = $tx.send(Err(error)) {
101 ::log::error!("{:#}", send_error)
102 }
103 }};
104}