md_analysis 0.2.1

molecular dynamics
use std::{fmt::Debug, str::FromStr};

/// parse the range str to Vector of tuple
/// range fmt: b1:e1,b2:e2,be3,b4:e4. corresponds to [[b1, e1], [b2, e2], [be3, be3], [b4, e4]]. left inclusive, right inclusive
#[allow(unused)]
pub fn range_parser<T>(range_str: &str) -> Vec<(T, T)>
where
    T: FromStr,
    <T as FromStr>::Err: Debug,
{
    range_str
        .trim()
        .split(",")
        .map(|single_range| {
            let items = single_range
                .trim()
                .split(":")
                .filter(|item| item.trim().len() != 0)
                .collect::<Vec<_>>();
            return if items.len() == 2 {
                (
                    items[0].parse::<T>().expect(&format!("{}", items[0])),
                    items[1].parse::<T>().expect(&format!("{}", items[1])),
                )
            } else {
                (
                    items[0].parse::<T>().expect(&format!("{}", items[0])),
                    items[0].parse::<T>().expect(&format!("{}", items[0])),
                )
            };
        })
        .collect::<Vec<_>>()
}

#[derive(Debug, Clone)]
pub struct Range<T> {
    range: Vec<(T, T)>,
}

impl<T> Range<T>
where
    T: PartialOrd,
    T: FromStr,
    <T as FromStr>::Err: Debug,
{
    pub fn new(range_str: &str) -> Self {
        Self {
            range: range_parser::<T>(range_str),
        }
    }

    pub fn within_range(&self, v: T) -> bool {
        let mut result = false;
        for (b, e) in &self.range {
            if *b <= v && v <= *e {
                result = true;
                break;
            }
        }
        result
    }
}

#[cfg(test)]
mod test {
    use super::range_parser;

    #[test]
    fn test_range_parser() {
        eprintln!("{:?}", range_parser::<i32>("1:3,2,4:10"));
        eprintln!("{:?}", range_parser::<f32>("1.0:3.2,2.1,4.1:10.4"));
    }
}