use std::{borrow::Cow, path::PathBuf};
use crate::{advanced::*, *};
impl FromScanf<'_> for String {
fn get_matcher(_: &FormatOptions) -> Matcher {
Matcher::from_regex(r".+?").unwrap()
}
fn from_match(matches: Match<'_, '_>, _: &FormatOptions) -> Option<Self> {
Some(matches.text().to_string())
}
}
impl AcceptsRegexOverride<'_> for String {
fn from_regex_match(input: &str, _: &FormatOptions) -> Option<Self> {
Some(input.to_string())
}
}
impl<'input> FromScanf<'input> for &'input str {
fn get_matcher(_: &FormatOptions) -> Matcher {
Matcher::from_regex(r".+?").unwrap()
}
fn from_match(matches: Match<'_, 'input>, _: &FormatOptions) -> Option<Self> {
Some(matches.text())
}
}
impl<'input> AcceptsRegexOverride<'input> for &'input str {
fn from_regex_match(input: &'input str, _: &FormatOptions) -> Option<Self> {
Some(input)
}
}
impl<'input> FromScanf<'input> for Cow<'input, str> {
fn get_matcher(_: &FormatOptions) -> Matcher {
Matcher::from_regex(r".+?").unwrap()
}
fn from_match(matches: Match<'_, 'input>, _: &FormatOptions) -> Option<Self> {
Some(Cow::Borrowed(matches.text()))
}
}
impl<'input> AcceptsRegexOverride<'input> for Cow<'input, str> {
fn from_regex_match(input: &'input str, _: &FormatOptions) -> Option<Self> {
Some(Cow::Borrowed(input))
}
}
impl FromScanf<'_> for char {
fn get_matcher(_: &FormatOptions) -> Matcher {
Matcher::from_regex(r".").unwrap()
}
fn from_match(matches: Match<'_, '_>, _: &FormatOptions) -> Option<Self> {
parse_char(matches.text())
}
}
impl AcceptsRegexOverride<'_> for char {
fn from_regex_match(input: &str, _: &FormatOptions) -> Option<Self> {
parse_char(input)
}
}
fn parse_char(input: &str) -> Option<char> {
let mut iter = input.chars();
let ret = iter.next()?;
if iter.next().is_some() {
return None;
}
Some(ret)
}
impl FromScanf<'_> for bool {
fn get_matcher(_: &FormatOptions) -> Matcher {
Matcher::from_regex(r"(?i:true|false|1|0|yes|no|on|off|t|f)").unwrap()
}
fn from_match(matches: Match<'_, '_>, _: &FormatOptions) -> Option<Self> {
parse_bool(matches.text())
}
}
impl AcceptsRegexOverride<'_> for bool {
fn from_regex_match(input: &str, _: &FormatOptions) -> Option<Self> {
parse_bool(input)
}
}
fn parse_bool(input: &str) -> Option<bool> {
match input.to_ascii_lowercase().as_str() {
"true" | "1" | "yes" | "on" | "t" => Some(true),
"false" | "0" | "no" | "off" | "f" => Some(false),
_ => None,
}
}
impl FromScanf<'_> for PathBuf {
fn get_matcher(_: &FormatOptions) -> Matcher {
Matcher::from_regex(r".+?").unwrap()
}
fn from_match(matches: Match<'_, '_>, _: &FormatOptions) -> Option<Self> {
matches.text().parse().ok()
}
}
impl AcceptsRegexOverride<'_> for PathBuf {
fn from_regex_match(input: &str, _: &FormatOptions) -> Option<Self> {
input.parse().ok()
}
}
#[cfg(test)]
mod tests {
use super::*;
impl<'input, A, B> FromScanf<'input> for (A, B)
where
A: FromScanf<'input>,
B: FromScanf<'input>,
{
fn get_matcher(options: &FormatOptions) -> Matcher {
Matcher::Seq(vec![
MatchPart::literal("("),
A::get_matcher(options).into(),
MatchPart::regex(r",\s*").unwrap(),
B::get_matcher(options).into(),
MatchPart::literal(")"),
])
}
fn from_match(matches: Match<'_, 'input>, options: &FormatOptions) -> Option<Self> {
let matches = matches.as_seq();
let a = matches.parse_at(1, options)?;
let b = matches.parse_at(3, options)?;
Some((a, b))
}
}
#[test]
fn test_tuple_parser() {
let input = "(1, 2)";
type Tuple = (u8, u8);
let output = parse::<Tuple>(input);
assert_eq!(output.unwrap(), (1, 2));
}
}