sedregex/
regex_flags.rs

1use crate::ErrorKind;
2use regex::RegexBuilder;
3use std::{collections::BTreeSet, str::FromStr};
4
5/// A single regex flag.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
7pub enum RegexFlag {
8    /// Regex should be case insensitive. Corresponds to `i`.
9    CaseInsensitive,
10    /// Regex is run for every match in a string. Corresponds to `g`.
11    Global,
12    /// "Greedy swap" flag. Corresponds to `U`.
13    GreedySwap,
14    /// Ignore whitespaces. Corresponds to `x`.
15    IgnoreWhitespaces,
16}
17
18/// A set of regex flags.
19#[derive(Debug, Default, PartialEq, Eq)]
20pub struct RegexFlags(BTreeSet<RegexFlag>);
21
22impl RegexFlags {
23    /// Applies stored flags on a regex builder.
24    pub fn apply(&self, builder: &mut RegexBuilder) {
25        builder.case_insensitive(self.0.contains(&RegexFlag::CaseInsensitive));
26        builder.swap_greed(self.0.contains(&RegexFlag::GreedySwap));
27        builder.ignore_whitespace(self.0.contains(&RegexFlag::IgnoreWhitespaces));
28    }
29
30    /// If the regex should be run for all the matches or just for the first one.
31    pub fn is_global(&self) -> bool {
32        self.0.contains(&RegexFlag::Global)
33    }
34}
35
36impl<I: IntoIterator<Item = RegexFlag>> From<I> for RegexFlags {
37    fn from(i: I) -> Self {
38        RegexFlags(i.into_iter().collect())
39    }
40}
41
42impl FromStr for RegexFlags {
43    type Err = ErrorKind;
44
45    fn from_str(s: &str) -> Result<Self, Self::Err> {
46        s.chars()
47            .map(|c| match c {
48                'i' => Ok(RegexFlag::CaseInsensitive),
49                'g' => Ok(RegexFlag::Global),
50                'U' => Ok(RegexFlag::GreedySwap),
51                'x' => Ok(RegexFlag::IgnoreWhitespaces),
52                c => Err(ErrorKind::UnknownFlag(c)),
53            })
54            .collect::<Result<_, _>>()
55            .map(RegexFlags)
56    }
57}