tank_core/
util.rs

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}