1use std::ops::RangeBounds;
2
3use proc_macro2::{Ident, Span};
4use syn::LitStr;
5
6/// Joins the arguments with `&&` operators.
7macro_rules! and {
8 ($($expr:expr),* $(,)?) => {
9 $($expr)&&*
10 };
11}
12
13/// Joins the arguments with `||` operators.
14#[cfg(feature = "terminfo")]
15macro_rules! or {
16 ($($expr:expr),* $(,)?) => {
17 $($expr)||*
18 };
19}
20
21/// Creates a new [`Ident`] which can be tokenized.
22pub fn ident(s: &str) -> Ident {
23 Ident::new(string:s, Span::call_site())
24}
25
26/// Creates a new [`struct@LitStr`] which can be tokenized.
27pub fn literal_string(s: &str) -> LitStr {
28 LitStr::new(value:s, Span::call_site())
29}
30
31/// Unfortunately, unless a nightly compiler is used, this function will actually only return the
32/// original input span.
33///
34/// Returns the subspan corresponding to the range of `inside` inside `input`, considering that:
35/// - `input` is exactly `&input_lit_str.value()`,
36/// - `inside` is a subslice of `input`,
37///
38/// Warning: may panic if the conditions are not met.
39/// TODO: improve safety
40pub fn inner_span<'a>(input: &'a str, input_lit_str: &LitStr, inside: &'a str) -> Span {
41 let input_offset: usize = (inside.as_ptr() as usize) - (input.as_ptr() as usize);
42 let range: Range = input_offset + 1..input_offset + inside.len() + 1;
43 subspan(input_lit_str.span(), range).unwrap_or_else(|| input_lit_str.span())
44}
45
46/// Returns a subspan of the given span.
47///
48/// TODO: the implementation is really... wtf! But i didn't find a better way to do it.
49fn subspan<R: RangeBounds<usize>>(span: Span, range: R) -> Option<Span> {
50 let mut lit: Literal = proc_macro2::Literal::i8_suffixed(0); // wtf...
51 lit.set_span(span);
52 lit.subspan(range)
53}
54