blob: 91c7c362c87b3b5a6d58a074e32edbf9f235c302 (
plain) (
blame)
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
|
// Copyright (C) 2022 Soni L.
// SPDX-License-Identifier: 0BSD
//! A replacement for char
//! ======================
//!
//! Because Rust's `char::is_ascii*` family of functions takes `&self`, it's
//! impossible to use them as patterns. This is inconsistent with the rest of
//! `char::is_*`, which takes `self`.
//!
//! This crate provides `char`-taking variants of the `is_ascii*` family of
//! functions.
//!
//! # Examples
//!
//! This works:
//!
//! ```rust
//! "hello".trim_start_matches(char::is_numeric);
//! ```
//!
//! This doesn't:
//!
//! ```rust compile_fail
//! "hello".trim_start_matches(char::is_ascii_digit);
//! ```
//!
//! This crate provides an alternative:
//!
//! ```rust
//! "hello".trim_start_matches(charx::is_ascii_digit);
//! ```
macro_rules! charx_fn {
($name:ident) => {
#[doc=concat!("Same as [`char::", stringify!($name), "`] but takes `char` instead of `&char`.")]
///
/// # Examples
///
/// This doesn't compile:
///
/// ```rust compile_fail
#[doc=concat!("\"hello\".trim_start_matches(char::", stringify!($name), ");")]
/// ```
///
/// But this does:
///
/// ```rust
#[doc=concat!("\"hello\".trim_start_matches(charx::", stringify!($name), ");")]
/// ```
#[inline(always)]
pub fn $name(c: char) -> bool {
char::$name(&c)
}
mod $name {
#[test]
fn test() {
for c in '\0'..='\u{10FFFF}' {
assert_eq!(char::$name(&c), crate::$name(c));
}
}
}
};
($($name:ident)*) => {
$(charx_fn!($name);)*
};
}
charx_fn!(is_ascii
is_ascii_alphabetic
is_ascii_alphanumeric
is_ascii_control
is_ascii_digit
is_ascii_graphic
is_ascii_hexdigit
is_ascii_lowercase
is_ascii_punctuation
is_ascii_uppercase
is_ascii_whitespace);
|