aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe-pcre/src/preg.rs
blob: 753a46780b16d2f963a219b1e7daa839251fc74b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
//! ref: composer/vendor/composer/pcre/src/Preg.php
//!
//! The following two exception classes are intentionally not ported:
//!
//! - `PcreException`: thrown when a `preg_*()` call returns false. Composer never feeds a pattern
//!   that fails to compile at runtime, so such a failure would be a programming error rather than
//!   a recoverable condition; they panic instead.
//! - `UnexpectedNullMatchException`: thrown by the `Preg::*StrictGroups()` variants when a capture
//!   group did not participate. Those variants were dropped because Rust's `Option` already
//!   distinguishes participating from non-participating groups.
//!
//! See docs/dev/regex-porting.md for more detailed regex porting rules.

pub use shirabe_php_shim::{CaptureKey, PregMatches, PregMatchesAll, PregMatchesAllWithOffsets};
use shirabe_php_shim::{
    PregPattern, preg_grep, preg_match_all_offset_capture, preg_match_all2, preg_match2,
    preg_replace_callback, preg_replace2,
};

#[derive(Debug)]
pub struct Preg;

impl Preg {
    pub fn match3<'h>(pattern: impl PregPattern, subject: &'h str) -> Option<PregMatches<'h>> {
        Self::match4(pattern, subject, 0)
    }

    pub fn match4<'h>(
        pattern: impl PregPattern,
        subject: &'h str,
        offset: usize,
    ) -> Option<PregMatches<'h>> {
        preg_match2(pattern, subject, offset)
    }

    pub fn match_all(pattern: impl PregPattern, subject: &str) -> usize {
        Self::match_all2(pattern, subject).occurrence_count()
    }

    pub fn match_all2(pattern: impl PregPattern, subject: &str) -> PregMatchesAll {
        preg_match_all2(pattern, subject)
    }

    fn match_all_with_offsets5(
        pattern: impl PregPattern,
        subject: &str,
    ) -> PregMatchesAllWithOffsets {
        preg_match_all_offset_capture(pattern, subject)
    }

    pub fn replace(pattern: impl PregPattern, replacement: &str, subject: &str) -> String {
        preg_replace2(pattern, replacement, subject, -1, None)
    }

    pub fn replace4(
        pattern: impl PregPattern,
        replacement: &str,
        subject: &str,
        limit: i64,
    ) -> String {
        preg_replace2(pattern, replacement, subject, limit, None)
    }

    pub fn replace5(
        pattern: impl PregPattern,
        replacement: &str,
        subject: &str,
        limit: i64,
        count: &mut usize,
    ) -> String {
        preg_replace2(pattern, replacement, subject, limit, Some(count))
    }

    pub fn replace_callback<'h, F: FnMut(&PregMatches<'h>) -> String>(
        pattern: impl PregPattern,
        mut replacement: F,
        subject: &'h str,
    ) -> String {
        let adapter = |matches: &PregMatches<'h>| Ok(replacement(matches));

        preg_replace_callback(pattern, adapter, subject).expect("$replacement cannot fail")
    }

    pub fn grep<T: AsRef<str>>(
        pattern: impl PregPattern,
        array: impl IntoIterator<Item = T>,
    ) -> impl Iterator<Item = T> {
        preg_grep(pattern, array)
    }

    pub fn is_match(pattern: impl PregPattern, subject: &str) -> bool {
        Self::match4(pattern, subject, 0).is_some()
    }

    pub fn is_match3<'h>(pattern: impl PregPattern, subject: &'h str) -> Option<PregMatches<'h>> {
        Self::match4(pattern, subject, 0)
    }

    pub fn is_match4<'h>(
        pattern: impl PregPattern,
        subject: &'h str,
        offset: usize,
    ) -> Option<PregMatches<'h>> {
        Self::match4(pattern, subject, offset)
    }

    pub fn is_match_all(pattern: impl PregPattern, subject: &str) -> PregMatchesAll {
        Self::match_all2(pattern, subject)
    }

    pub fn is_match_all_with_offsets3(
        pattern: impl PregPattern,
        subject: &str,
    ) -> PregMatchesAllWithOffsets {
        Self::match_all_with_offsets5(pattern, subject)
    }
}