|
1 | 1 | use std::{ |
2 | | - fmt::Display, |
| 2 | + fmt::{ |
| 3 | + self, |
| 4 | + Display, |
| 5 | + }, |
3 | 6 | ops::Deref, |
4 | 7 | str::FromStr, |
5 | 8 | }; |
@@ -28,11 +31,11 @@ pub const IDENTIFIER_REQUIREMENTS: &str = |
28 | 31 | /// [^3]: <https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp?a=%5B%3AXID_START%3A%5D&g=&i=> |
29 | 32 | /// [^4]: <https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp?a=%5B%3AXID_CONTINUE%3A%5D&g=&i=> |
30 | 33 | pub fn check_valid_identifier(s: &str) -> anyhow::Result<()> { |
31 | | - check_valid_identifier_inner(s).map_err(|e| anyhow::anyhow!(e)) |
| 34 | + check_valid_identifier_inner(s, |e| anyhow::anyhow!(e.to_string())) |
32 | 35 | } |
33 | 36 |
|
34 | 37 | pub fn is_valid_identifier(s: &str) -> bool { |
35 | | - check_valid_identifier_inner(s).is_ok() |
| 38 | + check_valid_identifier_inner(s, |_| ()).is_ok() |
36 | 39 | } |
37 | 40 |
|
38 | 41 | #[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)] |
@@ -77,38 +80,41 @@ impl Deref for Identifier { |
77 | 80 | } |
78 | 81 | } |
79 | 82 |
|
80 | | -fn check_valid_identifier_inner(s: &str) -> Result<(), String> { |
| 83 | +fn check_valid_identifier_inner<E>( |
| 84 | + s: &str, |
| 85 | + error: impl FnOnce(fmt::Arguments<'_>) -> E, |
| 86 | +) -> Result<(), E> { |
81 | 87 | let mut chars = s.chars(); |
82 | 88 | match chars.next() { |
83 | 89 | Some(c) if c.is_ascii_alphabetic() => (), |
84 | 90 | Some('_') => (), |
85 | 91 | Some(c) => { |
86 | | - return Err(format!( |
| 92 | + return Err(error(format_args!( |
87 | 93 | "Invalid first character '{c}' in {s}: Identifiers must start with an alphabetic \ |
88 | 94 | character or underscore" |
89 | | - )) |
| 95 | + ))) |
90 | 96 | }, |
91 | | - None => return Err(format!("Identifier cannot be empty")), |
| 97 | + None => return Err(error(format_args!("Identifier cannot be empty"))), |
92 | 98 | }; |
93 | 99 | for c in chars { |
94 | 100 | if !c.is_ascii_alphanumeric() && c != '_' { |
95 | | - return Err(format!( |
| 101 | + return Err(error(format_args!( |
96 | 102 | "Identifier {s} has invalid character '{c}': Identifiers can only contain \ |
97 | 103 | alphanumeric characters or underscores" |
98 | | - )); |
| 104 | + ))); |
99 | 105 | } |
100 | 106 | } |
101 | 107 | if s.len() > MAX_IDENTIFIER_LEN { |
102 | | - return Err(format!( |
| 108 | + return Err(error(format_args!( |
103 | 109 | "Identifier is too long ({} > maximum {})", |
104 | 110 | s.len(), |
105 | 111 | MAX_IDENTIFIER_LEN |
106 | | - )); |
| 112 | + ))); |
107 | 113 | } |
108 | 114 | if s.chars().all(|c| c == '_') { |
109 | | - return Err(format!( |
| 115 | + return Err(error(format_args!( |
110 | 116 | "Identifier {s} cannot have exclusively underscores" |
111 | | - )); |
| 117 | + ))); |
112 | 118 | } |
113 | 119 | Ok(()) |
114 | 120 | } |
|
0 commit comments