| 1 | //! This uses the name `AsciiChar`, even though it's not exposed that way right now, |
| 2 | //! because it avoids a whole bunch of "are you sure you didn't mean `char`?" |
| 3 | //! suggestions from rustc if you get anything slightly wrong in here, and overall |
| 4 | //! helps with clarity as we're also referring to `char` intentionally in here. |
| 5 | |
| 6 | use crate::mem::transmute; |
| 7 | use crate::{assert_unsafe_precondition, fmt}; |
| 8 | |
| 9 | /// One of the 128 Unicode characters from U+0000 through U+007F, |
| 10 | /// often known as the [ASCII] subset. |
| 11 | /// |
| 12 | /// Officially, this is the first [block] in Unicode, _Basic Latin_. |
| 13 | /// For details, see the [*C0 Controls and Basic Latin*][chart] code chart. |
| 14 | /// |
| 15 | /// This block was based on older 7-bit character code standards such as |
| 16 | /// ANSI X3.4-1977, ISO 646-1973, and [NIST FIPS 1-2]. |
| 17 | /// |
| 18 | /// # When to use this |
| 19 | /// |
| 20 | /// The main advantage of this subset is that it's always valid UTF-8. As such, |
| 21 | /// the `&[ascii::Char]` -> `&str` conversion function (as well as other related |
| 22 | /// ones) are O(1): *no* runtime checks are needed. |
| 23 | /// |
| 24 | /// If you're consuming strings, you should usually handle Unicode and thus |
| 25 | /// accept `str`s, not limit yourself to `ascii::Char`s. |
| 26 | /// |
| 27 | /// However, certain formats are intentionally designed to produce ASCII-only |
| 28 | /// output in order to be 8-bit-clean. In those cases, it can be simpler and |
| 29 | /// faster to generate `ascii::Char`s instead of dealing with the variable width |
| 30 | /// properties of general UTF-8 encoded strings, while still allowing the result |
| 31 | /// to be used freely with other Rust things that deal in general `str`s. |
| 32 | /// |
| 33 | /// For example, a UUID library might offer a way to produce the string |
| 34 | /// representation of a UUID as an `[ascii::Char; 36]` to avoid memory |
| 35 | /// allocation yet still allow it to be used as UTF-8 via `as_str` without |
| 36 | /// paying for validation (or needing `unsafe` code) the way it would if it |
| 37 | /// were provided as a `[u8; 36]`. |
| 38 | /// |
| 39 | /// # Layout |
| 40 | /// |
| 41 | /// This type is guaranteed to have a size and alignment of 1 byte. |
| 42 | /// |
| 43 | /// # Names |
| 44 | /// |
| 45 | /// The variants on this type are [Unicode names][NamesList] of the characters |
| 46 | /// in upper camel case, with a few tweaks: |
| 47 | /// - For `<control>` characters, the primary alias name is used. |
| 48 | /// - `LATIN` is dropped, as this block has no non-latin letters. |
| 49 | /// - `LETTER` is dropped, as `CAPITAL`/`SMALL` suffices in this block. |
| 50 | /// - `DIGIT`s use a single digit rather than writing out `ZERO`, `ONE`, etc. |
| 51 | /// |
| 52 | /// [ASCII]: https://www.unicode.org/glossary/index.html#ASCII |
| 53 | /// [block]: https://www.unicode.org/glossary/index.html#block |
| 54 | /// [chart]: https://www.unicode.org/charts/PDF/U0000.pdf |
| 55 | /// [NIST FIPS 1-2]: https://nvlpubs.nist.gov/nistpubs/Legacy/FIPS/fipspub1-2-1977.pdf |
| 56 | /// [NamesList]: https://www.unicode.org/Public/15.0.0/ucd/NamesList.txt |
| 57 | #[derive (Copy, Hash)] |
| 58 | #[derive_const (Clone, Eq, PartialEq, Ord, PartialOrd)] |
| 59 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 60 | #[repr (u8)] |
| 61 | pub enum AsciiChar { |
| 62 | /// U+0000 (The default variant) |
| 63 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 64 | Null = 0, |
| 65 | /// U+0001 |
| 66 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 67 | StartOfHeading = 1, |
| 68 | /// U+0002 |
| 69 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 70 | StartOfText = 2, |
| 71 | /// U+0003 |
| 72 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 73 | EndOfText = 3, |
| 74 | /// U+0004 |
| 75 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 76 | EndOfTransmission = 4, |
| 77 | /// U+0005 |
| 78 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 79 | Enquiry = 5, |
| 80 | /// U+0006 |
| 81 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 82 | Acknowledge = 6, |
| 83 | /// U+0007 |
| 84 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 85 | Bell = 7, |
| 86 | /// U+0008 |
| 87 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 88 | Backspace = 8, |
| 89 | /// U+0009 |
| 90 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 91 | CharacterTabulation = 9, |
| 92 | /// U+000A |
| 93 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 94 | LineFeed = 10, |
| 95 | /// U+000B |
| 96 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 97 | LineTabulation = 11, |
| 98 | /// U+000C |
| 99 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 100 | FormFeed = 12, |
| 101 | /// U+000D |
| 102 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 103 | CarriageReturn = 13, |
| 104 | /// U+000E |
| 105 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 106 | ShiftOut = 14, |
| 107 | /// U+000F |
| 108 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 109 | ShiftIn = 15, |
| 110 | /// U+0010 |
| 111 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 112 | DataLinkEscape = 16, |
| 113 | /// U+0011 |
| 114 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 115 | DeviceControlOne = 17, |
| 116 | /// U+0012 |
| 117 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 118 | DeviceControlTwo = 18, |
| 119 | /// U+0013 |
| 120 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 121 | DeviceControlThree = 19, |
| 122 | /// U+0014 |
| 123 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 124 | DeviceControlFour = 20, |
| 125 | /// U+0015 |
| 126 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 127 | NegativeAcknowledge = 21, |
| 128 | /// U+0016 |
| 129 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 130 | SynchronousIdle = 22, |
| 131 | /// U+0017 |
| 132 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 133 | EndOfTransmissionBlock = 23, |
| 134 | /// U+0018 |
| 135 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 136 | Cancel = 24, |
| 137 | /// U+0019 |
| 138 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 139 | EndOfMedium = 25, |
| 140 | /// U+001A |
| 141 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 142 | Substitute = 26, |
| 143 | /// U+001B |
| 144 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 145 | Escape = 27, |
| 146 | /// U+001C |
| 147 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 148 | InformationSeparatorFour = 28, |
| 149 | /// U+001D |
| 150 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 151 | InformationSeparatorThree = 29, |
| 152 | /// U+001E |
| 153 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 154 | InformationSeparatorTwo = 30, |
| 155 | /// U+001F |
| 156 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 157 | InformationSeparatorOne = 31, |
| 158 | /// U+0020 |
| 159 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 160 | Space = 32, |
| 161 | /// U+0021 |
| 162 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 163 | ExclamationMark = 33, |
| 164 | /// U+0022 |
| 165 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 166 | QuotationMark = 34, |
| 167 | /// U+0023 |
| 168 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 169 | NumberSign = 35, |
| 170 | /// U+0024 |
| 171 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 172 | DollarSign = 36, |
| 173 | /// U+0025 |
| 174 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 175 | PercentSign = 37, |
| 176 | /// U+0026 |
| 177 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 178 | Ampersand = 38, |
| 179 | /// U+0027 |
| 180 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 181 | Apostrophe = 39, |
| 182 | /// U+0028 |
| 183 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 184 | LeftParenthesis = 40, |
| 185 | /// U+0029 |
| 186 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 187 | RightParenthesis = 41, |
| 188 | /// U+002A |
| 189 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 190 | Asterisk = 42, |
| 191 | /// U+002B |
| 192 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 193 | PlusSign = 43, |
| 194 | /// U+002C |
| 195 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 196 | Comma = 44, |
| 197 | /// U+002D |
| 198 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 199 | HyphenMinus = 45, |
| 200 | /// U+002E |
| 201 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 202 | FullStop = 46, |
| 203 | /// U+002F |
| 204 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 205 | Solidus = 47, |
| 206 | /// U+0030 |
| 207 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 208 | Digit0 = 48, |
| 209 | /// U+0031 |
| 210 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 211 | Digit1 = 49, |
| 212 | /// U+0032 |
| 213 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 214 | Digit2 = 50, |
| 215 | /// U+0033 |
| 216 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 217 | Digit3 = 51, |
| 218 | /// U+0034 |
| 219 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 220 | Digit4 = 52, |
| 221 | /// U+0035 |
| 222 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 223 | Digit5 = 53, |
| 224 | /// U+0036 |
| 225 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 226 | Digit6 = 54, |
| 227 | /// U+0037 |
| 228 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 229 | Digit7 = 55, |
| 230 | /// U+0038 |
| 231 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 232 | Digit8 = 56, |
| 233 | /// U+0039 |
| 234 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 235 | Digit9 = 57, |
| 236 | /// U+003A |
| 237 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 238 | Colon = 58, |
| 239 | /// U+003B |
| 240 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 241 | Semicolon = 59, |
| 242 | /// U+003C |
| 243 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 244 | LessThanSign = 60, |
| 245 | /// U+003D |
| 246 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 247 | EqualsSign = 61, |
| 248 | /// U+003E |
| 249 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 250 | GreaterThanSign = 62, |
| 251 | /// U+003F |
| 252 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 253 | QuestionMark = 63, |
| 254 | /// U+0040 |
| 255 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 256 | CommercialAt = 64, |
| 257 | /// U+0041 |
| 258 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 259 | CapitalA = 65, |
| 260 | /// U+0042 |
| 261 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 262 | CapitalB = 66, |
| 263 | /// U+0043 |
| 264 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 265 | CapitalC = 67, |
| 266 | /// U+0044 |
| 267 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 268 | CapitalD = 68, |
| 269 | /// U+0045 |
| 270 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 271 | CapitalE = 69, |
| 272 | /// U+0046 |
| 273 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 274 | CapitalF = 70, |
| 275 | /// U+0047 |
| 276 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 277 | CapitalG = 71, |
| 278 | /// U+0048 |
| 279 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 280 | CapitalH = 72, |
| 281 | /// U+0049 |
| 282 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 283 | CapitalI = 73, |
| 284 | /// U+004A |
| 285 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 286 | CapitalJ = 74, |
| 287 | /// U+004B |
| 288 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 289 | CapitalK = 75, |
| 290 | /// U+004C |
| 291 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 292 | CapitalL = 76, |
| 293 | /// U+004D |
| 294 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 295 | CapitalM = 77, |
| 296 | /// U+004E |
| 297 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 298 | CapitalN = 78, |
| 299 | /// U+004F |
| 300 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 301 | CapitalO = 79, |
| 302 | /// U+0050 |
| 303 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 304 | CapitalP = 80, |
| 305 | /// U+0051 |
| 306 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 307 | CapitalQ = 81, |
| 308 | /// U+0052 |
| 309 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 310 | CapitalR = 82, |
| 311 | /// U+0053 |
| 312 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 313 | CapitalS = 83, |
| 314 | /// U+0054 |
| 315 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 316 | CapitalT = 84, |
| 317 | /// U+0055 |
| 318 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 319 | CapitalU = 85, |
| 320 | /// U+0056 |
| 321 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 322 | CapitalV = 86, |
| 323 | /// U+0057 |
| 324 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 325 | CapitalW = 87, |
| 326 | /// U+0058 |
| 327 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 328 | CapitalX = 88, |
| 329 | /// U+0059 |
| 330 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 331 | CapitalY = 89, |
| 332 | /// U+005A |
| 333 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 334 | CapitalZ = 90, |
| 335 | /// U+005B |
| 336 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 337 | LeftSquareBracket = 91, |
| 338 | /// U+005C |
| 339 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 340 | ReverseSolidus = 92, |
| 341 | /// U+005D |
| 342 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 343 | RightSquareBracket = 93, |
| 344 | /// U+005E |
| 345 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 346 | CircumflexAccent = 94, |
| 347 | /// U+005F |
| 348 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 349 | LowLine = 95, |
| 350 | /// U+0060 |
| 351 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 352 | GraveAccent = 96, |
| 353 | /// U+0061 |
| 354 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 355 | SmallA = 97, |
| 356 | /// U+0062 |
| 357 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 358 | SmallB = 98, |
| 359 | /// U+0063 |
| 360 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 361 | SmallC = 99, |
| 362 | /// U+0064 |
| 363 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 364 | SmallD = 100, |
| 365 | /// U+0065 |
| 366 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 367 | SmallE = 101, |
| 368 | /// U+0066 |
| 369 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 370 | SmallF = 102, |
| 371 | /// U+0067 |
| 372 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 373 | SmallG = 103, |
| 374 | /// U+0068 |
| 375 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 376 | SmallH = 104, |
| 377 | /// U+0069 |
| 378 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 379 | SmallI = 105, |
| 380 | /// U+006A |
| 381 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 382 | SmallJ = 106, |
| 383 | /// U+006B |
| 384 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 385 | SmallK = 107, |
| 386 | /// U+006C |
| 387 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 388 | SmallL = 108, |
| 389 | /// U+006D |
| 390 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 391 | SmallM = 109, |
| 392 | /// U+006E |
| 393 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 394 | SmallN = 110, |
| 395 | /// U+006F |
| 396 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 397 | SmallO = 111, |
| 398 | /// U+0070 |
| 399 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 400 | SmallP = 112, |
| 401 | /// U+0071 |
| 402 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 403 | SmallQ = 113, |
| 404 | /// U+0072 |
| 405 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 406 | SmallR = 114, |
| 407 | /// U+0073 |
| 408 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 409 | SmallS = 115, |
| 410 | /// U+0074 |
| 411 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 412 | SmallT = 116, |
| 413 | /// U+0075 |
| 414 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 415 | SmallU = 117, |
| 416 | /// U+0076 |
| 417 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 418 | SmallV = 118, |
| 419 | /// U+0077 |
| 420 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 421 | SmallW = 119, |
| 422 | /// U+0078 |
| 423 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 424 | SmallX = 120, |
| 425 | /// U+0079 |
| 426 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 427 | SmallY = 121, |
| 428 | /// U+007A |
| 429 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 430 | SmallZ = 122, |
| 431 | /// U+007B |
| 432 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 433 | LeftCurlyBracket = 123, |
| 434 | /// U+007C |
| 435 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 436 | VerticalLine = 124, |
| 437 | /// U+007D |
| 438 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 439 | RightCurlyBracket = 125, |
| 440 | /// U+007E |
| 441 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 442 | Tilde = 126, |
| 443 | /// U+007F |
| 444 | #[unstable (feature = "ascii_char_variants" , issue = "110998" )] |
| 445 | Delete = 127, |
| 446 | } |
| 447 | |
| 448 | impl AsciiChar { |
| 449 | /// The character with the lowest ASCII code. |
| 450 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 451 | pub const MIN: Self = Self::Null; |
| 452 | |
| 453 | /// The character with the highest ASCII code. |
| 454 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 455 | pub const MAX: Self = Self::Delete; |
| 456 | |
| 457 | /// Creates an ASCII character from the byte `b`, |
| 458 | /// or returns `None` if it's too large. |
| 459 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 460 | #[inline ] |
| 461 | pub const fn from_u8(b: u8) -> Option<Self> { |
| 462 | if b <= 127 { |
| 463 | // SAFETY: Just checked that `b` is in-range |
| 464 | Some(unsafe { Self::from_u8_unchecked(b) }) |
| 465 | } else { |
| 466 | None |
| 467 | } |
| 468 | } |
| 469 | |
| 470 | /// Creates an ASCII character from the byte `b`, |
| 471 | /// without checking whether it's valid. |
| 472 | /// |
| 473 | /// # Safety |
| 474 | /// |
| 475 | /// `b` must be in `0..=127`, or else this is UB. |
| 476 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 477 | #[inline ] |
| 478 | pub const unsafe fn from_u8_unchecked(b: u8) -> Self { |
| 479 | // SAFETY: Our safety precondition is that `b` is in-range. |
| 480 | unsafe { transmute(b) } |
| 481 | } |
| 482 | |
| 483 | /// When passed the *number* `0`, `1`, …, `9`, returns the *character* |
| 484 | /// `'0'`, `'1'`, …, `'9'` respectively. |
| 485 | /// |
| 486 | /// If `d >= 10`, returns `None`. |
| 487 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 488 | #[inline ] |
| 489 | pub const fn digit(d: u8) -> Option<Self> { |
| 490 | if d < 10 { |
| 491 | // SAFETY: Just checked it's in-range. |
| 492 | Some(unsafe { Self::digit_unchecked(d) }) |
| 493 | } else { |
| 494 | None |
| 495 | } |
| 496 | } |
| 497 | |
| 498 | /// When passed the *number* `0`, `1`, …, `9`, returns the *character* |
| 499 | /// `'0'`, `'1'`, …, `'9'` respectively, without checking that it's in-range. |
| 500 | /// |
| 501 | /// # Safety |
| 502 | /// |
| 503 | /// This is immediate UB if called with `d > 64`. |
| 504 | /// |
| 505 | /// If `d >= 10` and `d <= 64`, this is allowed to return any value or panic. |
| 506 | /// Notably, it should not be expected to return hex digits, or any other |
| 507 | /// reasonable extension of the decimal digits. |
| 508 | /// |
| 509 | /// (This loose safety condition is intended to simplify soundness proofs |
| 510 | /// when writing code using this method, since the implementation doesn't |
| 511 | /// need something really specific, not to make those other arguments do |
| 512 | /// something useful. It might be tightened before stabilization.) |
| 513 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 514 | #[inline ] |
| 515 | #[track_caller ] |
| 516 | pub const unsafe fn digit_unchecked(d: u8) -> Self { |
| 517 | assert_unsafe_precondition!( |
| 518 | check_library_ub, |
| 519 | "`ascii::Char::digit_unchecked` input cannot exceed 9." , |
| 520 | (d: u8 = d) => d < 10 |
| 521 | ); |
| 522 | |
| 523 | // SAFETY: `'0'` through `'9'` are U+00030 through U+0039, |
| 524 | // so because `d` must be 64 or less the addition can return at most |
| 525 | // 112 (0x70), which doesn't overflow and is within the ASCII range. |
| 526 | unsafe { |
| 527 | let byte = b'0' .unchecked_add(d); |
| 528 | Self::from_u8_unchecked(byte) |
| 529 | } |
| 530 | } |
| 531 | |
| 532 | /// Gets this ASCII character as a byte. |
| 533 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 534 | #[inline ] |
| 535 | pub const fn to_u8(self) -> u8 { |
| 536 | self as u8 |
| 537 | } |
| 538 | |
| 539 | /// Gets this ASCII character as a `char` Unicode Scalar Value. |
| 540 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 541 | #[inline ] |
| 542 | pub const fn to_char(self) -> char { |
| 543 | self as u8 as char |
| 544 | } |
| 545 | |
| 546 | /// Views this ASCII character as a one-code-unit UTF-8 `str`. |
| 547 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 548 | #[inline ] |
| 549 | pub const fn as_str(&self) -> &str { |
| 550 | crate::slice::from_ref(self).as_str() |
| 551 | } |
| 552 | |
| 553 | /// Makes a copy of the value in its upper case equivalent. |
| 554 | /// |
| 555 | /// Letters 'a' to 'z' are mapped to 'A' to 'Z'. |
| 556 | /// |
| 557 | /// To uppercase the value in-place, use [`make_uppercase`]. |
| 558 | /// |
| 559 | /// # Examples |
| 560 | /// |
| 561 | /// ``` |
| 562 | /// #![feature(ascii_char, ascii_char_variants)] |
| 563 | /// use std::ascii; |
| 564 | /// |
| 565 | /// let lowercase_a = ascii::Char::SmallA; |
| 566 | /// |
| 567 | /// assert_eq!( |
| 568 | /// ascii::Char::CapitalA, |
| 569 | /// lowercase_a.to_uppercase(), |
| 570 | /// ); |
| 571 | /// ``` |
| 572 | /// |
| 573 | /// [`make_uppercase`]: Self::make_uppercase |
| 574 | #[must_use = "to uppercase the value in-place, use `make_uppercase()`" ] |
| 575 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 576 | #[inline ] |
| 577 | pub const fn to_uppercase(self) -> Self { |
| 578 | let uppercase_byte = self.to_u8().to_ascii_uppercase(); |
| 579 | // SAFETY: Toggling the 6th bit won't convert ASCII to non-ASCII. |
| 580 | unsafe { Self::from_u8_unchecked(uppercase_byte) } |
| 581 | } |
| 582 | |
| 583 | /// Makes a copy of the value in its lower case equivalent. |
| 584 | /// |
| 585 | /// Letters 'A' to 'Z' are mapped to 'a' to 'z'. |
| 586 | /// |
| 587 | /// To lowercase the value in-place, use [`make_lowercase`]. |
| 588 | /// |
| 589 | /// # Examples |
| 590 | /// |
| 591 | /// ``` |
| 592 | /// #![feature(ascii_char, ascii_char_variants)] |
| 593 | /// use std::ascii; |
| 594 | /// |
| 595 | /// let uppercase_a = ascii::Char::CapitalA; |
| 596 | /// |
| 597 | /// assert_eq!( |
| 598 | /// ascii::Char::SmallA, |
| 599 | /// uppercase_a.to_lowercase(), |
| 600 | /// ); |
| 601 | /// ``` |
| 602 | /// |
| 603 | /// [`make_lowercase`]: Self::make_lowercase |
| 604 | #[must_use = "to lowercase the value in-place, use `make_lowercase()`" ] |
| 605 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 606 | #[inline ] |
| 607 | pub const fn to_lowercase(self) -> Self { |
| 608 | let lowercase_byte = self.to_u8().to_ascii_lowercase(); |
| 609 | // SAFETY: Setting the 6th bit won't convert ASCII to non-ASCII. |
| 610 | unsafe { Self::from_u8_unchecked(lowercase_byte) } |
| 611 | } |
| 612 | |
| 613 | /// Checks that two values are a case-insensitive match. |
| 614 | /// |
| 615 | /// This is equivalent to `to_lowercase(a) == to_lowercase(b)`. |
| 616 | /// |
| 617 | /// # Examples |
| 618 | /// |
| 619 | /// ``` |
| 620 | /// #![feature(ascii_char, ascii_char_variants)] |
| 621 | /// use std::ascii; |
| 622 | /// |
| 623 | /// let lowercase_a = ascii::Char::SmallA; |
| 624 | /// let uppercase_a = ascii::Char::CapitalA; |
| 625 | /// |
| 626 | /// assert!(lowercase_a.eq_ignore_case(uppercase_a)); |
| 627 | /// ``` |
| 628 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 629 | #[inline ] |
| 630 | pub const fn eq_ignore_case(self, other: Self) -> bool { |
| 631 | // FIXME(const-hack) `arg.to_u8().to_ascii_lowercase()` -> `arg.to_lowercase()` |
| 632 | // once `PartialEq` is const for `Self`. |
| 633 | self.to_u8().to_ascii_lowercase() == other.to_u8().to_ascii_lowercase() |
| 634 | } |
| 635 | |
| 636 | /// Converts this value to its upper case equivalent in-place. |
| 637 | /// |
| 638 | /// Letters 'a' to 'z' are mapped to 'A' to 'Z'. |
| 639 | /// |
| 640 | /// To return a new uppercased value without modifying the existing one, use |
| 641 | /// [`to_uppercase`]. |
| 642 | /// |
| 643 | /// # Examples |
| 644 | /// |
| 645 | /// ``` |
| 646 | /// #![feature(ascii_char, ascii_char_variants)] |
| 647 | /// use std::ascii; |
| 648 | /// |
| 649 | /// let mut letter_a = ascii::Char::SmallA; |
| 650 | /// |
| 651 | /// letter_a.make_uppercase(); |
| 652 | /// |
| 653 | /// assert_eq!(ascii::Char::CapitalA, letter_a); |
| 654 | /// ``` |
| 655 | /// |
| 656 | /// [`to_uppercase`]: Self::to_uppercase |
| 657 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 658 | #[inline ] |
| 659 | pub const fn make_uppercase(&mut self) { |
| 660 | *self = self.to_uppercase(); |
| 661 | } |
| 662 | |
| 663 | /// Converts this value to its lower case equivalent in-place. |
| 664 | /// |
| 665 | /// Letters 'A' to 'Z' are mapped to 'a' to 'z'. |
| 666 | /// |
| 667 | /// To return a new lowercased value without modifying the existing one, use |
| 668 | /// [`to_lowercase`]. |
| 669 | /// |
| 670 | /// # Examples |
| 671 | /// |
| 672 | /// ``` |
| 673 | /// #![feature(ascii_char, ascii_char_variants)] |
| 674 | /// use std::ascii; |
| 675 | /// |
| 676 | /// let mut letter_a = ascii::Char::CapitalA; |
| 677 | /// |
| 678 | /// letter_a.make_lowercase(); |
| 679 | /// |
| 680 | /// assert_eq!(ascii::Char::SmallA, letter_a); |
| 681 | /// ``` |
| 682 | /// |
| 683 | /// [`to_lowercase`]: Self::to_lowercase |
| 684 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 685 | #[inline ] |
| 686 | pub const fn make_lowercase(&mut self) { |
| 687 | *self = self.to_lowercase(); |
| 688 | } |
| 689 | |
| 690 | /// Checks if the value is an alphabetic character: |
| 691 | /// |
| 692 | /// - 0x41 'A' ..= 0x5A 'Z', or |
| 693 | /// - 0x61 'a' ..= 0x7A 'z'. |
| 694 | /// |
| 695 | /// # Examples |
| 696 | /// |
| 697 | /// ``` |
| 698 | /// #![feature(ascii_char, ascii_char_variants)] |
| 699 | /// use std::ascii; |
| 700 | /// |
| 701 | /// let uppercase_a = ascii::Char::CapitalA; |
| 702 | /// let uppercase_g = ascii::Char::CapitalG; |
| 703 | /// let a = ascii::Char::SmallA; |
| 704 | /// let g = ascii::Char::SmallG; |
| 705 | /// let zero = ascii::Char::Digit0; |
| 706 | /// let percent = ascii::Char::PercentSign; |
| 707 | /// let space = ascii::Char::Space; |
| 708 | /// let lf = ascii::Char::LineFeed; |
| 709 | /// let esc = ascii::Char::Escape; |
| 710 | /// |
| 711 | /// assert!(uppercase_a.is_alphabetic()); |
| 712 | /// assert!(uppercase_g.is_alphabetic()); |
| 713 | /// assert!(a.is_alphabetic()); |
| 714 | /// assert!(g.is_alphabetic()); |
| 715 | /// assert!(!zero.is_alphabetic()); |
| 716 | /// assert!(!percent.is_alphabetic()); |
| 717 | /// assert!(!space.is_alphabetic()); |
| 718 | /// assert!(!lf.is_alphabetic()); |
| 719 | /// assert!(!esc.is_alphabetic()); |
| 720 | /// ``` |
| 721 | #[must_use ] |
| 722 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 723 | #[inline ] |
| 724 | pub const fn is_alphabetic(self) -> bool { |
| 725 | self.to_u8().is_ascii_alphabetic() |
| 726 | } |
| 727 | |
| 728 | /// Checks if the value is an uppercase character: |
| 729 | /// 0x41 'A' ..= 0x5A 'Z'. |
| 730 | /// |
| 731 | /// # Examples |
| 732 | /// |
| 733 | /// ``` |
| 734 | /// #![feature(ascii_char, ascii_char_variants)] |
| 735 | /// use std::ascii; |
| 736 | /// |
| 737 | /// let uppercase_a = ascii::Char::CapitalA; |
| 738 | /// let uppercase_g = ascii::Char::CapitalG; |
| 739 | /// let a = ascii::Char::SmallA; |
| 740 | /// let g = ascii::Char::SmallG; |
| 741 | /// let zero = ascii::Char::Digit0; |
| 742 | /// let percent = ascii::Char::PercentSign; |
| 743 | /// let space = ascii::Char::Space; |
| 744 | /// let lf = ascii::Char::LineFeed; |
| 745 | /// let esc = ascii::Char::Escape; |
| 746 | /// |
| 747 | /// assert!(uppercase_a.is_uppercase()); |
| 748 | /// assert!(uppercase_g.is_uppercase()); |
| 749 | /// assert!(!a.is_uppercase()); |
| 750 | /// assert!(!g.is_uppercase()); |
| 751 | /// assert!(!zero.is_uppercase()); |
| 752 | /// assert!(!percent.is_uppercase()); |
| 753 | /// assert!(!space.is_uppercase()); |
| 754 | /// assert!(!lf.is_uppercase()); |
| 755 | /// assert!(!esc.is_uppercase()); |
| 756 | /// ``` |
| 757 | #[must_use ] |
| 758 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 759 | #[inline ] |
| 760 | pub const fn is_uppercase(self) -> bool { |
| 761 | self.to_u8().is_ascii_uppercase() |
| 762 | } |
| 763 | |
| 764 | /// Checks if the value is a lowercase character: |
| 765 | /// 0x61 'a' ..= 0x7A 'z'. |
| 766 | /// |
| 767 | /// # Examples |
| 768 | /// |
| 769 | /// ``` |
| 770 | /// #![feature(ascii_char, ascii_char_variants)] |
| 771 | /// use std::ascii; |
| 772 | /// |
| 773 | /// let uppercase_a = ascii::Char::CapitalA; |
| 774 | /// let uppercase_g = ascii::Char::CapitalG; |
| 775 | /// let a = ascii::Char::SmallA; |
| 776 | /// let g = ascii::Char::SmallG; |
| 777 | /// let zero = ascii::Char::Digit0; |
| 778 | /// let percent = ascii::Char::PercentSign; |
| 779 | /// let space = ascii::Char::Space; |
| 780 | /// let lf = ascii::Char::LineFeed; |
| 781 | /// let esc = ascii::Char::Escape; |
| 782 | /// |
| 783 | /// assert!(!uppercase_a.is_lowercase()); |
| 784 | /// assert!(!uppercase_g.is_lowercase()); |
| 785 | /// assert!(a.is_lowercase()); |
| 786 | /// assert!(g.is_lowercase()); |
| 787 | /// assert!(!zero.is_lowercase()); |
| 788 | /// assert!(!percent.is_lowercase()); |
| 789 | /// assert!(!space.is_lowercase()); |
| 790 | /// assert!(!lf.is_lowercase()); |
| 791 | /// assert!(!esc.is_lowercase()); |
| 792 | /// ``` |
| 793 | #[must_use ] |
| 794 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 795 | #[inline ] |
| 796 | pub const fn is_lowercase(self) -> bool { |
| 797 | self.to_u8().is_ascii_lowercase() |
| 798 | } |
| 799 | |
| 800 | /// Checks if the value is an alphanumeric character: |
| 801 | /// |
| 802 | /// - 0x41 'A' ..= 0x5A 'Z', or |
| 803 | /// - 0x61 'a' ..= 0x7A 'z', or |
| 804 | /// - 0x30 '0' ..= 0x39 '9'. |
| 805 | /// |
| 806 | /// # Examples |
| 807 | /// |
| 808 | /// ``` |
| 809 | /// #![feature(ascii_char, ascii_char_variants)] |
| 810 | /// use std::ascii; |
| 811 | /// |
| 812 | /// let uppercase_a = ascii::Char::CapitalA; |
| 813 | /// let uppercase_g = ascii::Char::CapitalG; |
| 814 | /// let a = ascii::Char::SmallA; |
| 815 | /// let g = ascii::Char::SmallG; |
| 816 | /// let zero = ascii::Char::Digit0; |
| 817 | /// let percent = ascii::Char::PercentSign; |
| 818 | /// let space = ascii::Char::Space; |
| 819 | /// let lf = ascii::Char::LineFeed; |
| 820 | /// let esc = ascii::Char::Escape; |
| 821 | /// |
| 822 | /// assert!(uppercase_a.is_alphanumeric()); |
| 823 | /// assert!(uppercase_g.is_alphanumeric()); |
| 824 | /// assert!(a.is_alphanumeric()); |
| 825 | /// assert!(g.is_alphanumeric()); |
| 826 | /// assert!(zero.is_alphanumeric()); |
| 827 | /// assert!(!percent.is_alphanumeric()); |
| 828 | /// assert!(!space.is_alphanumeric()); |
| 829 | /// assert!(!lf.is_alphanumeric()); |
| 830 | /// assert!(!esc.is_alphanumeric()); |
| 831 | /// ``` |
| 832 | #[must_use ] |
| 833 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 834 | #[inline ] |
| 835 | pub const fn is_alphanumeric(self) -> bool { |
| 836 | self.to_u8().is_ascii_alphanumeric() |
| 837 | } |
| 838 | |
| 839 | /// Checks if the value is a decimal digit: |
| 840 | /// 0x30 '0' ..= 0x39 '9'. |
| 841 | /// |
| 842 | /// # Examples |
| 843 | /// |
| 844 | /// ``` |
| 845 | /// #![feature(ascii_char, ascii_char_variants)] |
| 846 | /// use std::ascii; |
| 847 | /// |
| 848 | /// let uppercase_a = ascii::Char::CapitalA; |
| 849 | /// let uppercase_g = ascii::Char::CapitalG; |
| 850 | /// let a = ascii::Char::SmallA; |
| 851 | /// let g = ascii::Char::SmallG; |
| 852 | /// let zero = ascii::Char::Digit0; |
| 853 | /// let percent = ascii::Char::PercentSign; |
| 854 | /// let space = ascii::Char::Space; |
| 855 | /// let lf = ascii::Char::LineFeed; |
| 856 | /// let esc = ascii::Char::Escape; |
| 857 | /// |
| 858 | /// assert!(!uppercase_a.is_digit()); |
| 859 | /// assert!(!uppercase_g.is_digit()); |
| 860 | /// assert!(!a.is_digit()); |
| 861 | /// assert!(!g.is_digit()); |
| 862 | /// assert!(zero.is_digit()); |
| 863 | /// assert!(!percent.is_digit()); |
| 864 | /// assert!(!space.is_digit()); |
| 865 | /// assert!(!lf.is_digit()); |
| 866 | /// assert!(!esc.is_digit()); |
| 867 | /// ``` |
| 868 | #[must_use ] |
| 869 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 870 | #[inline ] |
| 871 | pub const fn is_digit(self) -> bool { |
| 872 | self.to_u8().is_ascii_digit() |
| 873 | } |
| 874 | |
| 875 | /// Checks if the value is an octal digit: |
| 876 | /// 0x30 '0' ..= 0x37 '7'. |
| 877 | /// |
| 878 | /// # Examples |
| 879 | /// |
| 880 | /// ``` |
| 881 | /// #![feature(ascii_char, ascii_char_variants, is_ascii_octdigit)] |
| 882 | /// |
| 883 | /// use std::ascii; |
| 884 | /// |
| 885 | /// let uppercase_a = ascii::Char::CapitalA; |
| 886 | /// let a = ascii::Char::SmallA; |
| 887 | /// let zero = ascii::Char::Digit0; |
| 888 | /// let seven = ascii::Char::Digit7; |
| 889 | /// let eight = ascii::Char::Digit8; |
| 890 | /// let percent = ascii::Char::PercentSign; |
| 891 | /// let lf = ascii::Char::LineFeed; |
| 892 | /// let esc = ascii::Char::Escape; |
| 893 | /// |
| 894 | /// assert!(!uppercase_a.is_octdigit()); |
| 895 | /// assert!(!a.is_octdigit()); |
| 896 | /// assert!(zero.is_octdigit()); |
| 897 | /// assert!(seven.is_octdigit()); |
| 898 | /// assert!(!eight.is_octdigit()); |
| 899 | /// assert!(!percent.is_octdigit()); |
| 900 | /// assert!(!lf.is_octdigit()); |
| 901 | /// assert!(!esc.is_octdigit()); |
| 902 | /// ``` |
| 903 | #[must_use ] |
| 904 | // This is blocked on two unstable features. Please ensure both are |
| 905 | // stabilized before marking this method as stable. |
| 906 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 907 | // #[unstable(feature = "is_ascii_octdigit", issue = "101288")] |
| 908 | #[inline ] |
| 909 | pub const fn is_octdigit(self) -> bool { |
| 910 | self.to_u8().is_ascii_octdigit() |
| 911 | } |
| 912 | |
| 913 | /// Checks if the value is a hexadecimal digit: |
| 914 | /// |
| 915 | /// - 0x30 '0' ..= 0x39 '9', or |
| 916 | /// - 0x41 'A' ..= 0x46 'F', or |
| 917 | /// - 0x61 'a' ..= 0x66 'f'. |
| 918 | /// |
| 919 | /// # Examples |
| 920 | /// |
| 921 | /// ``` |
| 922 | /// #![feature(ascii_char, ascii_char_variants)] |
| 923 | /// use std::ascii; |
| 924 | /// |
| 925 | /// let uppercase_a = ascii::Char::CapitalA; |
| 926 | /// let uppercase_g = ascii::Char::CapitalG; |
| 927 | /// let a = ascii::Char::SmallA; |
| 928 | /// let g = ascii::Char::SmallG; |
| 929 | /// let zero = ascii::Char::Digit0; |
| 930 | /// let percent = ascii::Char::PercentSign; |
| 931 | /// let space = ascii::Char::Space; |
| 932 | /// let lf = ascii::Char::LineFeed; |
| 933 | /// let esc = ascii::Char::Escape; |
| 934 | /// |
| 935 | /// assert!(uppercase_a.is_hexdigit()); |
| 936 | /// assert!(!uppercase_g.is_hexdigit()); |
| 937 | /// assert!(a.is_hexdigit()); |
| 938 | /// assert!(!g.is_hexdigit()); |
| 939 | /// assert!(zero.is_hexdigit()); |
| 940 | /// assert!(!percent.is_hexdigit()); |
| 941 | /// assert!(!space.is_hexdigit()); |
| 942 | /// assert!(!lf.is_hexdigit()); |
| 943 | /// assert!(!esc.is_hexdigit()); |
| 944 | /// ``` |
| 945 | #[must_use ] |
| 946 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 947 | #[inline ] |
| 948 | pub const fn is_hexdigit(self) -> bool { |
| 949 | self.to_u8().is_ascii_hexdigit() |
| 950 | } |
| 951 | |
| 952 | /// Checks if the value is a punctuation character: |
| 953 | /// |
| 954 | /// - 0x21 ..= 0x2F `! " # $ % & ' ( ) * + , - . /`, or |
| 955 | /// - 0x3A ..= 0x40 `: ; < = > ? @`, or |
| 956 | /// - 0x5B ..= 0x60 `` [ \ ] ^ _ ` ``, or |
| 957 | /// - 0x7B ..= 0x7E `{ | } ~` |
| 958 | /// |
| 959 | /// # Examples |
| 960 | /// |
| 961 | /// ``` |
| 962 | /// #![feature(ascii_char, ascii_char_variants)] |
| 963 | /// use std::ascii; |
| 964 | /// |
| 965 | /// let uppercase_a = ascii::Char::CapitalA; |
| 966 | /// let uppercase_g = ascii::Char::CapitalG; |
| 967 | /// let a = ascii::Char::SmallA; |
| 968 | /// let g = ascii::Char::SmallG; |
| 969 | /// let zero = ascii::Char::Digit0; |
| 970 | /// let percent = ascii::Char::PercentSign; |
| 971 | /// let space = ascii::Char::Space; |
| 972 | /// let lf = ascii::Char::LineFeed; |
| 973 | /// let esc = ascii::Char::Escape; |
| 974 | /// |
| 975 | /// assert!(!uppercase_a.is_punctuation()); |
| 976 | /// assert!(!uppercase_g.is_punctuation()); |
| 977 | /// assert!(!a.is_punctuation()); |
| 978 | /// assert!(!g.is_punctuation()); |
| 979 | /// assert!(!zero.is_punctuation()); |
| 980 | /// assert!(percent.is_punctuation()); |
| 981 | /// assert!(!space.is_punctuation()); |
| 982 | /// assert!(!lf.is_punctuation()); |
| 983 | /// assert!(!esc.is_punctuation()); |
| 984 | /// ``` |
| 985 | #[must_use ] |
| 986 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 987 | #[inline ] |
| 988 | pub const fn is_punctuation(self) -> bool { |
| 989 | self.to_u8().is_ascii_punctuation() |
| 990 | } |
| 991 | |
| 992 | /// Checks if the value is a graphic character: |
| 993 | /// 0x21 '!' ..= 0x7E '~'. |
| 994 | /// |
| 995 | /// # Examples |
| 996 | /// |
| 997 | /// ``` |
| 998 | /// #![feature(ascii_char, ascii_char_variants)] |
| 999 | /// use std::ascii; |
| 1000 | /// |
| 1001 | /// let uppercase_a = ascii::Char::CapitalA; |
| 1002 | /// let uppercase_g = ascii::Char::CapitalG; |
| 1003 | /// let a = ascii::Char::SmallA; |
| 1004 | /// let g = ascii::Char::SmallG; |
| 1005 | /// let zero = ascii::Char::Digit0; |
| 1006 | /// let percent = ascii::Char::PercentSign; |
| 1007 | /// let space = ascii::Char::Space; |
| 1008 | /// let lf = ascii::Char::LineFeed; |
| 1009 | /// let esc = ascii::Char::Escape; |
| 1010 | /// |
| 1011 | /// assert!(uppercase_a.is_graphic()); |
| 1012 | /// assert!(uppercase_g.is_graphic()); |
| 1013 | /// assert!(a.is_graphic()); |
| 1014 | /// assert!(g.is_graphic()); |
| 1015 | /// assert!(zero.is_graphic()); |
| 1016 | /// assert!(percent.is_graphic()); |
| 1017 | /// assert!(!space.is_graphic()); |
| 1018 | /// assert!(!lf.is_graphic()); |
| 1019 | /// assert!(!esc.is_graphic()); |
| 1020 | /// ``` |
| 1021 | #[must_use ] |
| 1022 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 1023 | #[inline ] |
| 1024 | pub const fn is_graphic(self) -> bool { |
| 1025 | self.to_u8().is_ascii_graphic() |
| 1026 | } |
| 1027 | |
| 1028 | /// Checks if the value is a whitespace character: |
| 1029 | /// 0x20 SPACE, 0x09 HORIZONTAL TAB, 0x0A LINE FEED, |
| 1030 | /// 0x0C FORM FEED, or 0x0D CARRIAGE RETURN. |
| 1031 | /// |
| 1032 | /// Rust uses the WhatWG Infra Standard's [definition of ASCII |
| 1033 | /// whitespace][infra-aw]. There are several other definitions in |
| 1034 | /// wide use. For instance, [the POSIX locale][pct] includes |
| 1035 | /// 0x0B VERTICAL TAB as well as all the above characters, |
| 1036 | /// but—from the very same specification—[the default rule for |
| 1037 | /// "field splitting" in the Bourne shell][bfs] considers *only* |
| 1038 | /// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace. |
| 1039 | /// |
| 1040 | /// If you are writing a program that will process an existing |
| 1041 | /// file format, check what that format's definition of whitespace is |
| 1042 | /// before using this function. |
| 1043 | /// |
| 1044 | /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace |
| 1045 | /// [pct]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01 |
| 1046 | /// [bfs]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05 |
| 1047 | /// |
| 1048 | /// # Examples |
| 1049 | /// |
| 1050 | /// ``` |
| 1051 | /// #![feature(ascii_char, ascii_char_variants)] |
| 1052 | /// use std::ascii; |
| 1053 | /// |
| 1054 | /// let uppercase_a = ascii::Char::CapitalA; |
| 1055 | /// let uppercase_g = ascii::Char::CapitalG; |
| 1056 | /// let a = ascii::Char::SmallA; |
| 1057 | /// let g = ascii::Char::SmallG; |
| 1058 | /// let zero = ascii::Char::Digit0; |
| 1059 | /// let percent = ascii::Char::PercentSign; |
| 1060 | /// let space = ascii::Char::Space; |
| 1061 | /// let lf = ascii::Char::LineFeed; |
| 1062 | /// let esc = ascii::Char::Escape; |
| 1063 | /// |
| 1064 | /// assert!(!uppercase_a.is_whitespace()); |
| 1065 | /// assert!(!uppercase_g.is_whitespace()); |
| 1066 | /// assert!(!a.is_whitespace()); |
| 1067 | /// assert!(!g.is_whitespace()); |
| 1068 | /// assert!(!zero.is_whitespace()); |
| 1069 | /// assert!(!percent.is_whitespace()); |
| 1070 | /// assert!(space.is_whitespace()); |
| 1071 | /// assert!(lf.is_whitespace()); |
| 1072 | /// assert!(!esc.is_whitespace()); |
| 1073 | /// ``` |
| 1074 | #[must_use ] |
| 1075 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 1076 | #[inline ] |
| 1077 | pub const fn is_whitespace(self) -> bool { |
| 1078 | self.to_u8().is_ascii_whitespace() |
| 1079 | } |
| 1080 | |
| 1081 | /// Checks if the value is a control character: |
| 1082 | /// 0x00 NUL ..= 0x1F UNIT SEPARATOR, or 0x7F DELETE. |
| 1083 | /// Note that most whitespace characters are control |
| 1084 | /// characters, but SPACE is not. |
| 1085 | /// |
| 1086 | /// # Examples |
| 1087 | /// |
| 1088 | /// ``` |
| 1089 | /// #![feature(ascii_char, ascii_char_variants)] |
| 1090 | /// use std::ascii; |
| 1091 | /// |
| 1092 | /// let uppercase_a = ascii::Char::CapitalA; |
| 1093 | /// let uppercase_g = ascii::Char::CapitalG; |
| 1094 | /// let a = ascii::Char::SmallA; |
| 1095 | /// let g = ascii::Char::SmallG; |
| 1096 | /// let zero = ascii::Char::Digit0; |
| 1097 | /// let percent = ascii::Char::PercentSign; |
| 1098 | /// let space = ascii::Char::Space; |
| 1099 | /// let lf = ascii::Char::LineFeed; |
| 1100 | /// let esc = ascii::Char::Escape; |
| 1101 | /// |
| 1102 | /// assert!(!uppercase_a.is_control()); |
| 1103 | /// assert!(!uppercase_g.is_control()); |
| 1104 | /// assert!(!a.is_control()); |
| 1105 | /// assert!(!g.is_control()); |
| 1106 | /// assert!(!zero.is_control()); |
| 1107 | /// assert!(!percent.is_control()); |
| 1108 | /// assert!(!space.is_control()); |
| 1109 | /// assert!(lf.is_control()); |
| 1110 | /// assert!(esc.is_control()); |
| 1111 | /// ``` |
| 1112 | #[must_use ] |
| 1113 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 1114 | #[inline ] |
| 1115 | pub const fn is_control(self) -> bool { |
| 1116 | self.to_u8().is_ascii_control() |
| 1117 | } |
| 1118 | |
| 1119 | /// Returns an iterator that produces an escaped version of a |
| 1120 | /// character. |
| 1121 | /// |
| 1122 | /// The behavior is identical to |
| 1123 | /// [`ascii::escape_default`](crate::ascii::escape_default). |
| 1124 | /// |
| 1125 | /// # Examples |
| 1126 | /// |
| 1127 | /// ``` |
| 1128 | /// #![feature(ascii_char, ascii_char_variants)] |
| 1129 | /// use std::ascii; |
| 1130 | /// |
| 1131 | /// let zero = ascii::Char::Digit0; |
| 1132 | /// let tab = ascii::Char::CharacterTabulation; |
| 1133 | /// let cr = ascii::Char::CarriageReturn; |
| 1134 | /// let lf = ascii::Char::LineFeed; |
| 1135 | /// let apostrophe = ascii::Char::Apostrophe; |
| 1136 | /// let double_quote = ascii::Char::QuotationMark; |
| 1137 | /// let backslash = ascii::Char::ReverseSolidus; |
| 1138 | /// |
| 1139 | /// assert_eq!("0" , zero.escape_ascii().to_string()); |
| 1140 | /// assert_eq!(" \\t" , tab.escape_ascii().to_string()); |
| 1141 | /// assert_eq!(" \\r" , cr.escape_ascii().to_string()); |
| 1142 | /// assert_eq!(" \\n" , lf.escape_ascii().to_string()); |
| 1143 | /// assert_eq!(" \\'" , apostrophe.escape_ascii().to_string()); |
| 1144 | /// assert_eq!(" \\\"" , double_quote.escape_ascii().to_string()); |
| 1145 | /// assert_eq!(" \\\\" , backslash.escape_ascii().to_string()); |
| 1146 | /// ``` |
| 1147 | #[must_use = "this returns the escaped character as an iterator, \ |
| 1148 | without modifying the original" ] |
| 1149 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 1150 | #[inline ] |
| 1151 | pub fn escape_ascii(self) -> super::EscapeDefault { |
| 1152 | super::escape_default(self.to_u8()) |
| 1153 | } |
| 1154 | } |
| 1155 | |
| 1156 | macro_rules! into_int_impl { |
| 1157 | ($($ty:ty)*) => { |
| 1158 | $( |
| 1159 | #[unstable(feature = "ascii_char" , issue = "110998" )] |
| 1160 | #[rustc_const_unstable(feature = "const_convert" , issue = "143773" )] |
| 1161 | impl const From<AsciiChar> for $ty { |
| 1162 | #[inline] |
| 1163 | fn from(chr: AsciiChar) -> $ty { |
| 1164 | chr as u8 as $ty |
| 1165 | } |
| 1166 | } |
| 1167 | )* |
| 1168 | } |
| 1169 | } |
| 1170 | |
| 1171 | into_int_impl!(u8 u16 u32 u64 u128 char); |
| 1172 | |
| 1173 | impl [AsciiChar] { |
| 1174 | /// Views this slice of ASCII characters as a UTF-8 `str`. |
| 1175 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 1176 | #[inline ] |
| 1177 | pub const fn as_str(&self) -> &str { |
| 1178 | let ascii_ptr: *const Self = self; |
| 1179 | let str_ptr: *const str = ascii_ptr as *const str; |
| 1180 | // SAFETY: Each ASCII codepoint in UTF-8 is encoded as one single-byte |
| 1181 | // code unit having the same value as the ASCII byte. |
| 1182 | unsafe { &*str_ptr } |
| 1183 | } |
| 1184 | |
| 1185 | /// Views this slice of ASCII characters as a slice of `u8` bytes. |
| 1186 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 1187 | #[inline ] |
| 1188 | pub const fn as_bytes(&self) -> &[u8] { |
| 1189 | self.as_str().as_bytes() |
| 1190 | } |
| 1191 | } |
| 1192 | |
| 1193 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 1194 | impl fmt::Display for AsciiChar { |
| 1195 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 1196 | <str as fmt::Display>::fmt(self.as_str(), f) |
| 1197 | } |
| 1198 | } |
| 1199 | |
| 1200 | #[unstable (feature = "ascii_char" , issue = "110998" )] |
| 1201 | impl fmt::Debug for AsciiChar { |
| 1202 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 1203 | use AsciiChar::{Apostrophe, Null, ReverseSolidus as Backslash}; |
| 1204 | |
| 1205 | fn backslash(a: AsciiChar) -> ([AsciiChar; 6], usize) { |
| 1206 | ([Apostrophe, Backslash, a, Apostrophe, Null, Null], 4) |
| 1207 | } |
| 1208 | |
| 1209 | let (buf, len) = match self { |
| 1210 | AsciiChar::Null => backslash(AsciiChar::Digit0), |
| 1211 | AsciiChar::CharacterTabulation => backslash(AsciiChar::SmallT), |
| 1212 | AsciiChar::CarriageReturn => backslash(AsciiChar::SmallR), |
| 1213 | AsciiChar::LineFeed => backslash(AsciiChar::SmallN), |
| 1214 | AsciiChar::ReverseSolidus => backslash(AsciiChar::ReverseSolidus), |
| 1215 | AsciiChar::Apostrophe => backslash(AsciiChar::Apostrophe), |
| 1216 | _ if self.to_u8().is_ascii_control() => { |
| 1217 | const HEX_DIGITS: [AsciiChar; 16] = *b"0123456789abcdef" .as_ascii().unwrap(); |
| 1218 | |
| 1219 | let byte = self.to_u8(); |
| 1220 | let hi = HEX_DIGITS[usize::from(byte >> 4)]; |
| 1221 | let lo = HEX_DIGITS[usize::from(byte & 0xf)]; |
| 1222 | ([Apostrophe, Backslash, AsciiChar::SmallX, hi, lo, Apostrophe], 6) |
| 1223 | } |
| 1224 | _ => ([Apostrophe, *self, Apostrophe, Null, Null, Null], 3), |
| 1225 | }; |
| 1226 | |
| 1227 | f.write_str(buf[..len].as_str()) |
| 1228 | } |
| 1229 | } |
| 1230 | |