use crate::error::{Error, Result};
use proc_macro2::{Span, TokenTree};
pub fn input_to_string(token: TokenTree, raw_mode: bool) -> Result<String> {
let repr = token.to_string();
let repr = repr.trim();
let is_string = repr.starts_with('"') || repr.starts_with('r');
let is_byte_string = repr.starts_with("b\"") || repr.starts_with("br");
if !is_string && !is_byte_string {
return Err(Error::new(
token.span(),
"argument must be a single string literal",
));
}
let begin = repr.find('"').unwrap() + 1;
let end = repr.rfind('"').unwrap();
let s = repr[begin..end].to_string();
let mut line_data = s
.lines()
.map(move |l| {
let is_blank = l.trim().is_empty();
let indentation = l.len() - l.trim_start().len();
(is_blank, indentation, l)
})
.collect::<Vec<(bool, usize, &str)>>();
if !line_data.is_empty() {
let mut start = 0;
let mut end = line_data.len() - 1;
while end > 0 && end >= start && line_data[end].0 {
end -= 1;
}
while start <= end && line_data[start].0 {
start += 1;
}
if start <= end {
line_data = line_data[start..=end].to_vec();
} else {
return Err(Error::new(
Span::call_site(),
&format!(
"Blank input provided! Need non-empty lines! {}/{}",
start, end
),
));
}
}
let lines =
if raw_mode {
line_data
.iter()
.map(|x| x.2)
.collect::<Vec<&str>>()
.join("\n")
} else {
let min_indentation = line_data
.iter()
.fold(usize::MAX, |acc, x| if x.1 < acc { x.1 } else { acc });
line_data
.iter()
.map(|x| &x.2[min_indentation..])
.collect::<Vec<&str>>()
.join("\n")
};
Ok(lines)
}