@@ -2371,23 +2371,27 @@ impl<'c, 'h> ExactSizeIterator for SubCaptureMatches<'c, 'h> {}
2371
2371
2372
2372
impl < ' c , ' h > core:: iter:: FusedIterator for SubCaptureMatches < ' c , ' h > { }
2373
2373
2374
- /// If a closure implements this for all `'a`, then it also implements
2375
- /// [`Replacer`].
2376
- pub trait ReplacerClosure < ' a >
2377
- where
2378
- Self : FnMut ( & ' a Captures < ' _ > ) -> <Self as ReplacerClosure < ' a > >:: Output ,
2379
- {
2380
- /// Return type of the closure (may depend on lifetime `'a`).
2381
- type Output : AsRef < str > ;
2382
- }
2383
-
2384
- impl < ' a , F : ?Sized , O > ReplacerClosure < ' a > for F
2385
- where
2386
- F : FnMut ( & ' a Captures < ' _ > ) -> O ,
2387
- O : AsRef < str > ,
2388
- {
2389
- type Output = O ;
2374
+ /// Contains helper trait for blanket implementation for [`Replacer`].
2375
+ mod replacer_closure {
2376
+ use super :: * ;
2377
+ /// If a closure implements this for all `'a` and `'b`, then it also
2378
+ /// implements [`Replacer`].
2379
+ pub trait ReplacerClosure < ' a >
2380
+ where
2381
+ Self : FnMut ( & ' a Captures < ' _ > ) -> <Self as ReplacerClosure < ' a > >:: Output ,
2382
+ {
2383
+ /// Return type of the closure (may depend on lifetime `'a`).
2384
+ type Output : AsRef < str > ;
2385
+ }
2386
+ impl < ' a , F : ?Sized , O > ReplacerClosure < ' a > for F
2387
+ where
2388
+ F : FnMut ( & ' a Captures < ' _ > ) -> O ,
2389
+ O : AsRef < str > ,
2390
+ {
2391
+ type Output = O ;
2392
+ }
2390
2393
}
2394
+ use replacer_closure:: * ;
2391
2395
2392
2396
/// A trait for types that can be used to replace matches in a haystack.
2393
2397
///
@@ -2421,6 +2425,69 @@ where
2421
2425
/// let result = re.replace("Springsteen, Bruce", NameSwapper);
2422
2426
/// assert_eq!(result, "Bruce Springsteen");
2423
2427
/// ```
2428
+ ///
2429
+ /// # Implementation by closures
2430
+ ///
2431
+ /// Closures that take an argument of type `&'a Captures<'b>` for any `'a` and
2432
+ /// `'b: 'a` and which return a type `T: AsRef<str>` (that may depend on `'a`)
2433
+ /// implement the `Replacer` trait through a blanket implementation.
2434
+ ///
2435
+ /// A simple example looks like this:
2436
+ ///
2437
+ /// ```
2438
+ /// use regex::{Captures, Regex};
2439
+ ///
2440
+ /// let re = Regex::new(r"[0-9]+").unwrap();
2441
+ /// let result = re.replace_all("1234,12345", |caps: &Captures<'_>| {
2442
+ /// format!("[number with {} digits]", caps[0].len())
2443
+ /// });
2444
+ /// assert_eq!(result, "[number with 4 digits],[number with 5 digits]");
2445
+ /// ```
2446
+ ///
2447
+ /// Note that the return type of the closure may depend on the lifetime of the
2448
+ /// reference that is passed as an argument to the closure. This requires the
2449
+ /// closure to be a function, unless [closure lifetime binders] are being used:
2450
+ ///
2451
+ /// [closure lifetime binders]: https://rust-lang.github.io/rfcs/3216-closure-lifetime-binder.html
2452
+ /// [`Cow`]: std::borrow::Cow
2453
+ ///
2454
+ /// ```
2455
+ /// use regex::{Captures, Regex, Replacer};
2456
+ /// use std::borrow::Cow;
2457
+ ///
2458
+ /// let re = Regex::new(r"[0-9]+").unwrap();
2459
+ /// fn prepend_odd<'a>(caps: &'a Captures<'_>) -> Cow<'a, str> {
2460
+ /// if caps[0].len() % 2 == 1 {
2461
+ /// Cow::Owned(format!("0{}", &caps[0]))
2462
+ /// } else {
2463
+ /// Cow::Borrowed(&caps[0])
2464
+ /// }
2465
+ /// }
2466
+ /// let result = re.replace_all("1234,12345", prepend_odd);
2467
+ /// assert_eq!(result, "1234,012345");
2468
+ /// ```
2469
+ ///
2470
+ /// The same example using closure lifetime binders:
2471
+ ///
2472
+ /// ```
2473
+ /// #![feature(closure_lifetime_binder)]
2474
+ ///
2475
+ /// use regex::{Captures, Regex, Replacer};
2476
+ /// use std::borrow::Cow;
2477
+ ///
2478
+ /// let re = Regex::new(r"[0-9]+").unwrap();
2479
+ /// let result = re.replace_all(
2480
+ /// "1234,12345",
2481
+ /// for<'a, 'b> |caps: &'a Captures<'b>| -> Cow<'a, str> {
2482
+ /// if caps[0].len() % 2 == 1 {
2483
+ /// Cow::Owned(format!("0{}", &caps[0]))
2484
+ /// } else {
2485
+ /// Cow::Borrowed(&caps[0])
2486
+ /// }
2487
+ /// },
2488
+ /// );
2489
+ /// assert_eq!(result, "1234,012345");
2490
+ /// ```
2424
2491
pub trait Replacer {
2425
2492
/// Appends possibly empty data to `dst` to replace the current match.
2426
2493
///
0 commit comments