1
+ use std:: mem:: transmute;
1
2
use std:: fmt;
2
3
#[ cfg( feature="unstable" ) ]
3
4
use std:: ascii:: AsciiExt ;
4
5
5
6
use AsciiCast ;
6
7
8
+ #[ allow( non_camel_case_types) ]
7
9
/// Datatype to hold one ascii character. It wraps a `u8`, with the highest bit always zero.
8
10
#[ derive( Clone , PartialEq , PartialOrd , Ord , Eq , Hash , Copy ) ]
9
- pub struct Ascii { chr : u8 }
11
+ #[ repr( u8 ) ]
12
+ pub enum Ascii {
13
+ /**`'\0'`*/ Null = 0 ,
14
+ /** [Start Of Heading](http://en.wikipedia.org/wiki/Start_of_Heading)
15
+ */ SOH = 1 ,
16
+ /** [Start Of teXt](http://en.wikipedia.org/wiki/Start_of_Text)
17
+ */ SOX = 2 ,
18
+ /** [End Of teXt](http://en.wikipedia.org/wiki/End-of-Text_character)
19
+ */ ETX = 3 ,
20
+ /** [End Of Transmission](http://en.wikipedia.org/wiki/End-of-Transmission_character)
21
+ */ EOT = 4 ,
22
+ /** [Enquiry](http://en.wikipedia.org/wiki/Enquiry_character)
23
+ */ ENQ = 5 ,
24
+ /** [Acknowledgement](http://en.wikipedia.org/wiki/Acknowledge_character)
25
+ */ ACK = 6 ,
26
+ /** [bell / alarm / audible](http://en.wikipedia.org/wiki/Bell_character)
27
+
28
+ '\a' is not supported by Rust.
29
+ */ Bell = 7 ,
30
+ /** [Backspace character](http://en.wikipedia.org/wiki/Backspace)
31
+
32
+ '\b' is not supported by Rust.
33
+ */ BackSpace = 8 ,
34
+ /**`'\t'`*/ Tab = 9 ,
35
+ /**`'\n'`*/ LineFeed = 10 ,
36
+ /** [Vertical tab](http://en.wikipedia.org/wiki/Vertical_Tab)
37
+
38
+ '\v' is not supported by Rust.
39
+ */ VerticalTab = 11 ,
40
+ /** [Form Feed](http://en.wikipedia.org/wiki/Form_Feed)
41
+
42
+ '\f' is not supported by Rust.
43
+ */ FormFeed = 12 ,
44
+ /**`'\r'`*/ CarriageReturn = 13 ,
45
+ /** [Shift In](http://en.wikipedia.org/wiki/Shift_Out_and_Shift_In_characters)
46
+ */ SI = 14 ,
47
+ /** [Shift Out](http://en.wikipedia.org/wiki/Shift_Out_and_Shift_In_characters)
48
+ */ SO = 15 ,
49
+ /** [Data Link Escape](http://en.wikipedia.org/wiki/Data_Link_Escape)
50
+ */ DLE = 16 ,
51
+ /** [Device control 1, often XON](http://en.wikipedia.org/wiki/Device_Control_1)
52
+ */ DC1 = 17 ,
53
+ /** Device control 2
54
+ */ DC2 = 18 ,
55
+ /** Device control 3, Often XOFF
56
+ */ DC3 = 19 ,
57
+ /** Device control 4
58
+ */ DC4 = 20 ,
59
+ /** [Negative Acknowledgement](http://en.wikipedia.org/wiki/Negative-acknowledge_character)
60
+ */ NAK = 21 ,
61
+ /** [Synchronous idle](http://en.wikipedia.org/wiki/Synchronous_Idle)
62
+ */ SYN = 22 ,
63
+ /** [End of Transmission Block](http://en.wikipedia.org/wiki/End-of-Transmission-Block_character)
64
+ */ ETB = 23 ,
65
+ /** [Cancel](http://en.wikipedia.org/wiki/Cancel_character)
66
+ */ CAN = 24 ,
67
+ /** [End of Medium](http://en.wikipedia.org/wiki/End_of_Medium)
68
+ */ EM = 25 ,
69
+ /** [Substitute](http://en.wikipedia.org/wiki/Substitute_character)
70
+ */ SUB = 26 ,
71
+ /** [Escape](http://en.wikipedia.org/wiki/Escape_character)
72
+
73
+ '\e' is not supported in Rust.
74
+ */ Escape = 27 ,
75
+ /** [File Separator](http://en.wikipedia.org/wiki/File_separator)
76
+ */ FS = 28 ,
77
+ /** [Group Separator](http://en.wikipedia.org/wiki/Group_separator)
78
+ */ GS = 29 ,
79
+ /** [Record Separator](http://en.wikipedia.org/wiki/Record_separator)
80
+ */ RS = 30 ,
81
+ /** [Unit Separator](http://en.wikipedia.org/wiki/Unit_separator)
82
+ */ US = 31 ,
83
+ /**`' '`*/ Space = 32 ,
84
+ /**`'!'`*/ Exclamation = 33 ,
85
+ /**`'"'`*/ Quotation = 34 ,
86
+ /**`'''`*/ Hash = 35 ,
87
+ /**`'$'`*/ Dollar = 36 ,
88
+ /**`'%'`*/ Percent = 37 ,
89
+ /**`'&'`*/ Ampersand = 38 ,
90
+ /**`'''`*/ Apostrophe = 39 ,
91
+ /**`'('`*/ ParenOpen = 40 ,
92
+ /**`')'`*/ ParenClose = 41 ,
93
+ /**`'*'`*/ Asterisk = 42 ,
94
+ /**`'+'`*/ Plus = 43 ,
95
+ /**`','`*/ Comma = 44 ,
96
+ /**`'-'`*/ Minus = 45 ,
97
+ /**`'.'`*/ Dot = 46 ,
98
+ /**`'/'`*/ Slash = 47 ,
99
+ /**`'0'`*/ _0 = 48 ,
100
+ /**`'1'`*/ _1 = 49 ,
101
+ /**`'2'`*/ _2 = 50 ,
102
+ /**`'3'`*/ _3 = 51 ,
103
+ /**`'4'`*/ _4 = 52 ,
104
+ /**`'5'`*/ _5 = 53 ,
105
+ /**`'6'`*/ _6 = 54 ,
106
+ /**`'7'`*/ _7 = 55 ,
107
+ /**`'8'`*/ _8 = 56 ,
108
+ /**`'9'`*/ _9 = 57 ,
109
+ /**`':'`*/ Colon = 58 ,
110
+ /**`';'`*/ SemiColon = 59 ,
111
+ /**`'<'`*/ LessThan = 60 ,
112
+ /**`'='`*/ Equal = 61 ,
113
+ /**`'>'`*/ GreaterThan = 62 ,
114
+ /**`'?'`*/ Question = 63 ,
115
+ /**`'@'`*/ At = 64 ,
116
+ /**`'A'`*/ A = 65 ,
117
+ /**`'B'`*/ B = 66 ,
118
+ /**`'C'`*/ C = 67 ,
119
+ /**`'D'`*/ D = 68 ,
120
+ /**`'E'`*/ E = 69 ,
121
+ /**`'F'`*/ F = 70 ,
122
+ /**`'G'`*/ G = 71 ,
123
+ /**`'H'`*/ H = 72 ,
124
+ /**`'I'`*/ I = 73 ,
125
+ /**`'J'`*/ J = 74 ,
126
+ /**`'K'`*/ K = 75 ,
127
+ /**`'L'`*/ L = 76 ,
128
+ /**`'M'`*/ M = 77 ,
129
+ /**`'N'`*/ N = 78 ,
130
+ /**`'O'`*/ O = 79 ,
131
+ /**`'P'`*/ P = 80 ,
132
+ /**`'Q'`*/ Q = 81 ,
133
+ /**`'R'`*/ R = 82 ,
134
+ /**`'S'`*/ S = 83 ,
135
+ /**`'T'`*/ T = 84 ,
136
+ /**`'U'`*/ U = 85 ,
137
+ /**`'V'`*/ V = 86 ,
138
+ /**`'W'`*/ W = 87 ,
139
+ /**`'X'`*/ X = 88 ,
140
+ /**`'Y'`*/ Y = 89 ,
141
+ /**`'Z'`*/ Z = 90 ,
142
+ /**`'['`*/ BracketOpen = 91 ,
143
+ /**`'\'`*/ BackSlash = 92 ,
144
+ /**`']'`*/ BracketClose = 93 ,
145
+ /**`'_'`*/ Caret = 94 ,
146
+ /**`'_'`*/ UnderScore = 95 ,
147
+ /**`'`'`*/ Grave = 96 ,
148
+ /**`'a'`*/ a = 97 ,
149
+ /**`'b'`*/ b = 98 ,
150
+ /**`'c'`*/ c = 99 ,
151
+ /**`'d'`*/ d = 100 ,
152
+ /**`'e'`*/ e = 101 ,
153
+ /**`'f'`*/ f = 102 ,
154
+ /**`'g'`*/ g = 103 ,
155
+ /**`'h'`*/ h = 104 ,
156
+ /**`'i'`*/ i = 105 ,
157
+ /**`'j'`*/ j = 106 ,
158
+ /**`'k'`*/ k = 107 ,
159
+ /**`'l'`*/ l = 108 ,
160
+ /**`'m'`*/ m = 109 ,
161
+ /**`'n'`*/ n = 110 ,
162
+ /**`'o'`*/ o = 111 ,
163
+ /**`'p'`*/ p = 112 ,
164
+ /**`'q'`*/ q = 113 ,
165
+ /**`'r'`*/ r = 114 ,
166
+ /**`'s'`*/ s = 115 ,
167
+ /**`'t'`*/ t = 116 ,
168
+ /**`'u'`*/ u = 117 ,
169
+ /**`'v'`*/ v = 118 ,
170
+ /**`'w'`*/ w = 119 ,
171
+ /**`'x'`*/ x = 120 ,
172
+ /**`'y'`*/ y = 121 ,
173
+ /**`'z'`*/ z = 122 ,
174
+ /**`'{'`*/ CurlyBraceOpen = 123 ,
175
+ /**`'|'`*/ VerticalBar = 124 ,
176
+ /**`'}'`*/ CurlyBraceClose = 125 ,
177
+ /**`'~'`*/ Tilde = 126 ,
178
+ /** [Delete](http://en.wikipedia.org/wiki/Delete_character)
179
+ */ DEL = 127 ,
180
+ }
10
181
11
182
impl Ascii {
12
183
/// Constructs an Ascii character from a `char`.
@@ -23,9 +194,9 @@ impl Ascii {
23
194
/// ```
24
195
#[ inline]
25
196
pub fn from ( ch : char ) -> Result < Ascii , ( ) > {
26
- if ch as u32 <= 0x7F {
27
- return Ok ( Ascii { chr : ch as u8 } ) ;
28
- }
197
+ unsafe { if ch as u32 <= 0x7F {
198
+ return Ok ( ch . to_ascii_nocheck ( ) ) ;
199
+ } }
29
200
Err ( ( ) )
30
201
}
31
202
@@ -44,36 +215,37 @@ impl Ascii {
44
215
/// ```
45
216
#[ inline]
46
217
pub fn from_byte ( ch : u8 ) -> Result < Ascii , ( ) > {
47
- if ch <= 0x7F {
48
- return Ok ( Ascii { chr : ch } ) ;
49
- }
218
+ unsafe { if ch <= 0x7F {
219
+ return Ok ( ch . to_ascii_nocheck ( ) ) ;
220
+ } }
50
221
Err ( ( ) )
51
222
}
52
223
53
224
/// Converts an ascii character into a `u8`.
54
225
#[ inline]
55
226
pub fn as_byte ( & self ) -> u8 {
56
- self . chr
227
+ * self as u8
57
228
}
58
229
59
230
/// Converts an ascii character into a `char`.
60
231
#[ inline]
61
232
pub fn as_char ( & self ) -> char {
62
- self . chr as char
233
+ self . as_byte ( ) as char
63
234
}
64
235
65
236
// the following methods are like ctype, and the implementation is inspired by musl
66
237
67
238
/// Check if the character is a letter (a-z, A-Z)
68
239
#[ inline]
69
240
pub fn is_alphabetic ( & self ) -> bool {
70
- ( self . chr >= 0x41 && self . chr <= 0x5A ) || ( self . chr >= 0x61 && self . chr <= 0x7A )
241
+ let c = self . as_byte ( ) | 0b010_0000 ; // Turns uppercase into lowercase.
242
+ c >= b'a' && c <= b'z'
71
243
}
72
244
73
245
/// Check if the character is a number (0-9)
74
246
#[ inline]
75
247
pub fn is_digit ( & self ) -> bool {
76
- self . chr >= 0x30 && self . chr <= 0x39
248
+ self >= & Ascii :: _0 && self <= & Ascii :: _9
77
249
}
78
250
79
251
/// Check if the character is a letter or number
@@ -85,7 +257,7 @@ impl Ascii {
85
257
/// Check if the character is a space or horizontal tab
86
258
#[ inline]
87
259
pub fn is_blank ( & self ) -> bool {
88
- self . chr == b' ' || self . chr == b'\t'
260
+ * self == Ascii :: Space || * self == Ascii :: Tab
89
261
}
90
262
91
263
/// Check if the character is a control character
@@ -101,7 +273,7 @@ impl Ascii {
101
273
/// ```
102
274
#[ inline]
103
275
pub fn is_control ( & self ) -> bool {
104
- self . chr < 0x20 || self . chr == 0x7F
276
+ self . as_byte ( ) < 0x20 || * self == Ascii :: DEL
105
277
}
106
278
107
279
/// Checks if the character is printable (except space)
@@ -116,7 +288,7 @@ impl Ascii {
116
288
/// ```
117
289
#[ inline]
118
290
pub fn is_graph ( & self ) -> bool {
119
- self . chr . wrapping_sub ( 0x21 ) < 0x5E
291
+ self . as_byte ( ) . wrapping_sub ( 0x21 ) < 0x5E
120
292
}
121
293
122
294
/// Checks if the character is printable (including space)
@@ -131,7 +303,7 @@ impl Ascii {
131
303
/// ```
132
304
#[ inline]
133
305
pub fn is_print ( & self ) -> bool {
134
- self . chr . wrapping_sub ( 0x20 ) < 0x5F
306
+ self . as_byte ( ) . wrapping_sub ( 0x20 ) < 0x5F
135
307
}
136
308
137
309
/// Checks if the character is alphabetic and lowercase
@@ -146,7 +318,7 @@ impl Ascii {
146
318
/// ```
147
319
#[ inline]
148
320
pub fn is_lowercase ( & self ) -> bool {
149
- self . chr . wrapping_sub ( b'a' ) < 26
321
+ self . as_byte ( ) . wrapping_sub ( b'a' ) < 26
150
322
}
151
323
152
324
/// Checks if the character is alphabetic and uppercase
@@ -161,7 +333,7 @@ impl Ascii {
161
333
/// ```
162
334
#[ inline]
163
335
pub fn is_uppercase ( & self ) -> bool {
164
- self . chr . wrapping_sub ( b'A' ) < 26
336
+ self . as_byte ( ) . wrapping_sub ( b'A' ) < 26
165
337
}
166
338
167
339
/// Checks if the character is punctuation
@@ -193,7 +365,7 @@ impl Ascii {
193
365
/// ```
194
366
#[ inline]
195
367
pub fn is_hex ( & self ) -> bool {
196
- self . is_digit ( ) || ( self . chr | 32u8 ) . wrapping_sub ( b'a' ) < 6
368
+ self . is_digit ( ) || ( self . as_byte ( ) | 32u8 ) . wrapping_sub ( b'a' ) < 6
197
369
}
198
370
}
199
371
@@ -219,25 +391,25 @@ impl AsciiExt for Ascii {
219
391
}
220
392
221
393
fn to_ascii_uppercase ( & self ) -> Ascii {
222
- Ascii { chr : self . chr . to_ascii_uppercase ( ) }
394
+ unsafe { self . as_byte ( ) . to_ascii_uppercase ( ) . to_ascii_nocheck ( ) }
223
395
}
224
396
225
397
fn to_ascii_lowercase ( & self ) -> Ascii {
226
- Ascii { chr : self . chr . to_ascii_lowercase ( ) }
398
+ unsafe { self . as_byte ( ) . to_ascii_uppercase ( ) . to_ascii_nocheck ( ) }
227
399
}
228
400
229
401
fn eq_ignore_ascii_case ( & self , other : & Self ) -> bool {
230
- self . chr . eq_ignore_ascii_case ( & other. chr )
402
+ self . as_byte ( ) . eq_ignore_ascii_case ( & other. as_byte ( ) )
231
403
}
232
404
233
405
#[ inline]
234
406
fn make_ascii_uppercase ( & mut self ) {
235
- self . chr . make_ascii_uppercase ( )
407
+ * self = self . to_ascii_uppercase ( ) ;
236
408
}
237
409
238
410
#[ inline]
239
411
fn make_ascii_lowercase ( & mut self ) {
240
- self . chr . make_ascii_lowercase ( )
412
+ * self = self . to_ascii_lowercase ( ) ;
241
413
}
242
414
}
243
415
@@ -246,7 +418,7 @@ impl<'a> AsciiCast<'a> for u8 {
246
418
247
419
#[ inline]
248
420
unsafe fn to_ascii_nocheck ( & self ) -> Ascii {
249
- Ascii { chr : * self }
421
+ transmute ( * self )
250
422
}
251
423
}
252
424
@@ -255,7 +427,7 @@ impl<'a> AsciiCast<'a> for char {
255
427
256
428
#[ inline]
257
429
unsafe fn to_ascii_nocheck ( & self ) -> Ascii {
258
- Ascii { chr : * self as u8 }
430
+ ( * self as u8 ) . to_ascii_nocheck ( )
259
431
}
260
432
}
261
433
@@ -266,10 +438,10 @@ mod tests {
266
438
267
439
#[ test]
268
440
fn to_ascii ( ) {
269
- assert_eq ! ( 65_u8 . to_ascii( ) , Ok ( Ascii { chr : 65_u8 } ) ) ;
441
+ assert_eq ! ( 65_u8 . to_ascii( ) , Ok ( Ascii :: A ) ) ;
270
442
assert_eq ! ( 255_u8 . to_ascii( ) , Err ( ( ) ) ) ;
271
443
272
- assert_eq ! ( 'A' . to_ascii( ) , Ok ( Ascii { chr : 65_u8 } ) ) ;
444
+ assert_eq ! ( 'A' . to_ascii( ) , Ok ( Ascii :: A ) ) ;
273
445
assert_eq ! ( 'λ' . to_ascii( ) , Err ( ( ) ) ) ;
274
446
}
275
447
@@ -302,13 +474,11 @@ mod tests {
302
474
303
475
#[ test]
304
476
fn fmt_display_ascii ( ) {
305
- let s = Ascii { chr : b't' } ;
306
- assert_eq ! ( format!( "{}" , s) , "t" . to_string( ) ) ;
477
+ assert_eq ! ( format!( "{}" , Ascii :: t) , "t" . to_string( ) ) ;
307
478
}
308
479
309
480
#[ test]
310
481
fn fmt_debug_ascii ( ) {
311
- let c = Ascii { chr : b't' } ;
312
- assert_eq ! ( format!( "{:?}" , c) , "'t'" . to_string( ) ) ;
482
+ assert_eq ! ( format!( "{:?}" , Ascii :: t) , "'t'" . to_string( ) ) ;
313
483
}
314
484
}
0 commit comments