Skip to main content

utf8_to_windows_vkc/
lib.rs

1use phf::phf_map;
2
3mod ascii {
4    // Uppercase letters
5    pub const UPPERCASE_A: u8 = 0x41; // 'A'
6    pub const UPPERCASE_Z: u8 = 0x5A; // 'Z'
7    // Lowercase letters
8    pub const LOWERCASE_A: u8 = 0x61; // 'a'
9    pub const LOWERCASE_Z: u8 = 0x7A; // 'z'
10    // Numbers (0-9)
11    pub const ZERO: u8 = 0x30; // '0'
12    pub const NINE: u8 = 0x39; // '9'
13}
14
15mod vk {
16    // A helpful source: http://www.kbdedit.com/manual/low_level_vk_list.html
17    pub const VK_SHIFT: u8 = 0x10; // Shift key
18}
19
20/// Errors that can occur when mapping a character to a key.
21#[derive(PartialEq)]
22#[derive(Debug)]
23pub enum ErrorCodes {
24    /// Was unable to find a matching key for the given character.
25    NotFound,
26    /// The given character was outside the valid ASCII character range.
27    OutOfRange
28}
29
30#[derive(PartialEq)]
31#[derive(Debug)]
32pub struct KeyError {
33    /// The byte being processed when the error occurred. Do not depend on this field as it can vary
34    /// wildly because not all characters occupy a single byte in memory. Rather this should be used
35    /// as a context clue to help determine the issue.
36    pub byte: u8,
37    /// Type of error that occurred.
38    pub error_code: ErrorCodes
39}
40
41/// The offset in the ASCII character table from [a-z] and [A-Z].
42/// Can be calculated by subtracting the code value of 'a' from 'A'.
43const ASCII_LOWERCASE_TO_UPPERCASE_OFFSET_AND_ASCII_MIN_VALUE: u8 = 32;
44const MAX_VALID_ASCII_CHAR_SIZE: u8 = 127;
45
46static CHAR_TO_KEY_MAP: phf::Map<u8, u16> = phf_map! {
47    // Shift not required
48    0x2Au8 => 0x6A, // Asterisk -> VK_MULTIPLY
49    0x2Du8 => 0x6D, // Minus -> VK_MINUS
50    0x3Du8 => 0xBB, // Equal -> VK_OEM_PLUS
51    0x2Eu8 => 0xBE, // Period -> VK_OME_PERIOD
52    0x2Fu8 => 0x6F, // Slash -> VK_DIVIDE
53    0x20u8 => 0x20, // Space -> VK_SPACE
54    0x3Bu8 => 0xBA, // Semicolon -> VK_OEM_1
55    0x60u8 => 0xC0, // Backtick -> VK_OEM_3
56    0x5Bu8 => 0xDB, // Left Bracket -> VK_OEM_4
57    0x5Cu8 => 0xDC, // Backslash -> VK_OEM_5
58    0x5Du8 => 0xDD, // Right Bracket -> VK_OEM_6
59    0x27u8 => 0xDE, // Single Quote -> VK_OEM_7
60    0x2Cu8 => 0xBC, // Comma -> VK_OEM_COMMA
61
62    // Shift required, left most bit of u8 is flag for shift
63    // See: https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-vkkeyscanexa#return-value
64    0x21u8 => 0x0131, // Exclamation Mark -> VK_1
65    0x40u8 => 0x0132, // At Sign -> VK_2
66    0x23u8 => 0x0133, // Hash -> VK_3
67    0x24u8 => 0x0134, // Dollar -> VK_4
68    0x25u8 => 0x0135, // Percentage -> VK_5
69    0x5Eu8 => 0x0136, // Caret -> VK_6
70    0x26u8 => 0x0137, // Ampersand -> VK_7
71    0x28u8 => 0x0139, // Left Paren -> VK_9
72    0x29u8 => 0x0130, // Right Paren -> VK_0
73    0x2Bu8 => 0x01BB, // Plus -> VK_OEM_PLUS
74    0x3Au8 => 0x01BA, // Colon -> VK_OEM_1
75    0x3Fu8 => 0x01BF, // Question Mark -> VK_OEM_2
76    0x7Eu8 => 0x01C0, // Tilde -> VK_OEM_3
77    0x7Bu8 => 0x01DB, // Left Curly Bracket -> VK_OEM_4
78    0x7Du8 => 0x01DD, // Right Curly Bracket -> VK_OEM_5
79    0x7Cu8 => 0x01DC, // Vertical Bar -> VK_OEM_5
80    0x22u8 => 0x01DE, // Double Quote -> VK_OEM_7
81    0x3Cu8 => 0x01BC, // Less Than -> VK_OEM_COMMA
82    0x3Eu8 => 0x01BE, // Greater Than -> VK_OEM_PERIOD
83    0x5Fu8 => 0x01BD, // Underscore -> VK_OEM_MINUS
84};
85
86// Function that returns a new Vec<u8>
87pub fn to_keystrokes_new(keys: &str) -> Result<Vec<u8>, KeyError> {
88    let mut keystrokes = Vec::new();
89    to_keystrokes_mut(keys, &mut keystrokes)?;
90    Ok(keystrokes)
91}
92
93pub fn to_keystrokes_mut(keys: &str, keystrokes: &mut Vec<u8>) -> Result<(), KeyError> {
94    let characters = keys.as_bytes();
95    let length = keys.len();
96
97    let mut char;
98    let mut is_shifting = false;
99    let mut key_requires_shift: bool; // 0 is false, 1 is true with this var
100    for i in 0..length {
101        char = characters[i];
102
103        // Ensure key value is within valid range
104        if char >= MAX_VALID_ASCII_CHAR_SIZE || char < ASCII_LOWERCASE_TO_UPPERCASE_OFFSET_AND_ASCII_MIN_VALUE {
105            return Err(KeyError{
106                byte: char,
107                error_code: ErrorCodes::OutOfRange
108            })
109        }
110
111        // If the char is within [A-Z] push the value on as these values map directly to window's codes
112        if char >= ascii::UPPERCASE_A && char <= ascii::UPPERCASE_Z {
113            if !is_shifting {
114                is_shifting = true;
115                keystrokes.push(vk::VK_SHIFT);
116            }
117            keystrokes.push(char);
118            continue // Skip
119        }
120
121        // If the char is within [a-z], offset to the uppercase codes and take the shift key into consideration
122        if char >= ascii::LOWERCASE_A && char <= ascii::LOWERCASE_Z {
123            if is_shifting { // We no longer need to be shifting
124                is_shifting = false;
125                keystrokes.push(vk::VK_SHIFT);
126            }
127            keystrokes.push(char - ASCII_LOWERCASE_TO_UPPERCASE_OFFSET_AND_ASCII_MIN_VALUE);
128            continue // Skip
129        }
130
131        // If the char is within [0-9]
132        if char >= ascii::ZERO && char <= ascii::NINE {
133            if is_shifting { // We no longer need to be shifting
134                is_shifting = false;
135                keystrokes.push(vk::VK_SHIFT);
136            }
137            keystrokes.push(char); // ASCII [0-9] maps directly to window's virtual key code values for [0-9]
138            continue
139        }
140
141        if let Some(code) = CHAR_TO_KEY_MAP.get(&char) {
142            let vkc = code & 0xFF;
143            let high_bits = code >> 0x8;
144
145            /*
146            VK_0: 0x0130 // KEY_0 with shift key flag
147            0x0130 is 304 in decimal
148
149            Decimal Perspective:
150            304 / 256 gives us 1 (int math)(mod)
151            304 % 256 just gives us 48 which is 0x30 (vk)
152
153            ** I guess as long as the right hand (denominator) doesn't fit into the left hand (nominator) more than once, subtraction works too, 304 - 256 == 48 (vk)
154
155            Hex Perspective:
156            0x130 / 0x100 us 0x01 (mod)
157            0x130 % 0x100 is 0x30 (vk)
158
159            Binary Bit Shfit Perspective:
160            0000 0001 0011 0000 & 1111 1111 => 0000 0000 0011 0000 = 48 (vk)
161            0000 0001 0011 0000 >> 8 => 0000 0001 => 1 (mod)
162             */
163
164            // Do not bother masking to view only the shift aspect as that is all we support anyway
165            key_requires_shift = high_bits == 0x1u16;
166            if is_shifting && !key_requires_shift { // We no longer need to be shifting
167                is_shifting = false;
168                keystrokes.push(vk::VK_SHIFT);
169            }
170            else if !is_shifting && key_requires_shift { // We need to start shifting
171                is_shifting = true;
172                keystrokes.push(vk::VK_SHIFT);
173            }
174            // Isolate the key code form the shift and push
175            keystrokes.push(vkc as u8);
176            continue
177        }
178
179        return Err(KeyError {
180            byte: char,
181            error_code: ErrorCodes::NotFound
182        })
183    }
184
185    // Add a trailing shift if needed
186    // Occurs when last character as [a-z]
187    if is_shifting { keystrokes.push(vk::VK_SHIFT); }
188
189    Ok(())
190}
191
192
193
194/* ### --- UNIT TEST --- ### */
195
196
197
198#[cfg(test)]
199mod tests {
200    use super::*;
201
202    // Define constants for A-Z keys and the Shift key
203    // Defining as u8 for now instead of u16 as not supporting extended windows virtual keys
204    pub const VK_A: u8 = 0x41;  // 'A'
205    pub const VK_B: u8 = 0x42;  // 'B'
206    pub const VK_C: u8 = 0x43;  // 'C'
207    pub const VK_Z: u8 = 0x5A;  // 'Z'
208    pub const VK_0: u8 = 0x30; // 0 or )
209    pub const VK_1: u8 = 0x31; // 1 or @
210    pub const VK_2: u8 = 0x32; // 2 or @
211    pub const VK_3: u8 = 0x33; // 3 or #
212    pub const VK_4: u8 = 0x34; // 4 or $
213    pub const VK_5: u8 = 0x35; // 5 or %
214    pub const VK_6: u8 = 0x36; // 6 or ^
215    pub const VK_7: u8 = 0x37; // 7 or &
216    pub const VK_8: u8 = 0x38; // 8 or *
217    pub const VK_9: u8 = 0x39; // 9 or (
218
219    pub const VK_SPACE: u8 = 0x20; // Space key
220    pub const VK_MULTIPLY: u8 = 0x6A; // Virtual Key for Multiply (*)
221    pub const VK_MINUS: u8 = 0x6D; // Virtual Key for Minus (-)
222    pub const VK_DIVIDE: u8 = 0x6F; // Virtual Key for Slash (/)
223
224    pub const VK_OEM_1: u8 = 0xBA; // OEM 1 - For semicolon (;) and colon (:) on QWERTY keyboards
225    pub const VK_OEM_PLUS: u8 = 0xBB; // OEM + - For plus (+) and equals (=)
226    pub const VK_OEM_MINUS: u8 = 0xBD; // OEM - + For minus (-) and underscore (_)
227    pub const VK_OEM_COMMA: u8 = 0xBC; // OEM , - For comma (,) and less than (<)
228    pub const VK_OEM_PERIOD: u8 = 0xBE; // OEM . - For period (.) and greater than (>)
229    pub const VK_OEM_2: u8 = 0xBF; // OEM 2 - For forward slash (/) and question mark (?)
230    pub const VK_OEM_3: u8 = 0xC0; // OEM 3 - For grave accent (`) and tilde (~)
231    pub const VK_OEM_4: u8 = 0xDB; // OEM 4 - For left bracket ([) and open square bracket
232    pub const VK_OEM_5: u8 = 0xDC; // OEM 5 - For backslash (\) and pipe (|)
233    pub const VK_OEM_6: u8 = 0xDD; // OEM 6 - For right bracket (]) and closing square bracket
234    pub const VK_OEM_7: u8 = 0xDE; // OEM 7 - For single quote (') and double quote (")
235
236    #[test]
237    fn test_non_valid_character_results_in_error() {
238        let strokes = to_keystrokes_new("æ");
239
240        assert_eq!(strokes.is_err(), true, "should contain error from bounds check");
241        // Do not check the byte field as it can vary depending on character width
242        let err_code = strokes.unwrap_err().error_code;
243        assert_eq!(err_code, ErrorCodes::OutOfRange, "character provided exceeds valid ASCII character range");
244    }
245
246    mod alphabetical {
247        use super::*;
248
249
250        #[test]
251        fn test_lowercase_a() {
252            let strokes = to_keystrokes_new("a").unwrap();
253
254            assert_eq!(strokes.len(), 1, "incorrect key vector length");
255            assert_eq!(strokes[0], VK_A);
256        }
257
258        #[test]
259        fn test_lowercase_z() {
260            let strokes = to_keystrokes_new("z").unwrap();
261
262            assert_eq!(strokes.len(), 1, "incorrect key vector length");
263            assert_eq!(strokes[0], VK_Z);
264        }
265
266        #[test]
267        fn test_uppercase_a() {
268            let strokes = to_keystrokes_new("A").unwrap();
269
270            assert_eq!(strokes.len(), 3, "incorrect key vector length");
271            assert_eq!(strokes[0], vk::VK_SHIFT);
272            assert_eq!(strokes[1], VK_A);
273            assert_eq!(strokes[2], vk::VK_SHIFT);
274        }
275
276        #[test]
277        fn test_uppercase_z() {
278            let strokes = to_keystrokes_new("Z").unwrap();
279
280            assert_eq!(strokes.len(), 3, "incorrect key vector length");
281            assert_eq!(strokes[0], vk::VK_SHIFT);
282            assert_eq!(strokes[1], VK_Z);
283            assert_eq!(strokes[2], vk::VK_SHIFT);
284        }
285
286        #[test]
287        fn test_multiple_lowercases() {
288            let strokes = to_keystrokes_new("abc").unwrap();
289
290            assert_eq!(strokes.len(), 3, "incorrect key vector length");
291            assert_eq!(strokes[0], VK_A);
292            assert_eq!(strokes[1], VK_B);
293            assert_eq!(strokes[2], VK_C);
294        }
295
296        #[test]
297        fn test_multiple_uppercases() {
298            let strokes = to_keystrokes_new("ABC").unwrap();
299
300            assert_eq!(strokes.len(), 5, "incorrect key vector length");
301            assert_eq!(strokes[0], vk::VK_SHIFT);
302            assert_eq!(strokes[1], VK_A);
303            assert_eq!(strokes[2], VK_B);
304            assert_eq!(strokes[3], VK_C);
305            assert_eq!(strokes[4], vk::VK_SHIFT);
306        }
307
308        #[test]
309        fn test_multiple_mixed_cases_v1() {
310            let strokes = to_keystrokes_new("aBc").unwrap();
311
312            assert_eq!(strokes.len(), 5, "incorrect key vector length");
313            assert_eq!(strokes[0], VK_A);
314            assert_eq!(strokes[1], vk::VK_SHIFT);
315            assert_eq!(strokes[2], VK_B);
316            assert_eq!(strokes[3], vk::VK_SHIFT);
317            assert_eq!(strokes[4], VK_C);
318        }
319
320        #[test]
321        fn test_multiple_mixed_cases_v2() {
322            let strokes = to_keystrokes_new("abcABCabc").unwrap();
323
324            assert_eq!(strokes.len(), 11, "incorrect key vector length");
325            assert_eq!(strokes[0], VK_A);
326            assert_eq!(strokes[1], VK_B);
327            assert_eq!(strokes[2], VK_C);
328
329            assert_eq!(strokes[3], vk::VK_SHIFT);
330            assert_eq!(strokes[4], VK_A);
331            assert_eq!(strokes[5], VK_B);
332            assert_eq!(strokes[6], VK_C);
333            assert_eq!(strokes[7], vk::VK_SHIFT);
334
335            assert_eq!(strokes[8], VK_A);
336            assert_eq!(strokes[9], VK_B);
337            assert_eq!(strokes[10], VK_C);
338        }
339
340        #[test]
341        fn test_multiple_mixed_cases_v3() {
342            let strokes = to_keystrokes_new("ZbcAzCaZc").unwrap();
343
344            assert_eq!(strokes.len(), 17, "incorrect key vector length");
345            assert_eq!(strokes[0], vk::VK_SHIFT);
346            assert_eq!(strokes[1], VK_Z);
347            assert_eq!(strokes[2], vk::VK_SHIFT);
348
349            assert_eq!(strokes[3], VK_B);
350            assert_eq!(strokes[4], VK_C);
351
352            assert_eq!(strokes[5], vk::VK_SHIFT);
353            assert_eq!(strokes[6], VK_A);
354            assert_eq!(strokes[7], vk::VK_SHIFT);
355
356            assert_eq!(strokes[8], VK_Z);
357
358            assert_eq!(strokes[9], vk::VK_SHIFT);
359            assert_eq!(strokes[10], VK_C);
360            assert_eq!(strokes[11], vk::VK_SHIFT);
361
362            assert_eq!(strokes[12], VK_A);
363
364            assert_eq!(strokes[13], vk::VK_SHIFT);
365            assert_eq!(strokes[14], VK_Z);
366            assert_eq!(strokes[15], vk::VK_SHIFT);
367
368            assert_eq!(strokes[16], VK_C);
369        }
370    }
371
372    mod vk_0_through_vk_9 {
373        use super::*;
374
375        #[test]
376        fn test_number_one() {
377            let strokes = to_keystrokes_new("1").unwrap();
378
379            assert_eq!(strokes.len(), 1, "incorrect key vector length");
380            assert_eq!(strokes[0], VK_1);
381        }
382
383        #[test]
384        fn test_exclamation_mark() {
385            let strokes = to_keystrokes_new("!").unwrap();
386
387            assert_eq!(strokes.len(), 3, "incorrect key vector length");
388            assert_eq!(strokes[0], vk::VK_SHIFT);
389            assert_eq!(strokes[1], VK_1);
390            assert_eq!(strokes[2], vk::VK_SHIFT);
391        }
392
393        #[test]
394        fn test_number_two() {
395            let strokes = to_keystrokes_new("2").unwrap();
396
397            assert_eq!(strokes.len(), 1, "incorrect key vector length");
398            assert_eq!(strokes[0], VK_2);
399        }
400
401        #[test]
402        fn test_at_sign() {
403            let strokes = to_keystrokes_new("@").unwrap();
404
405            assert_eq!(strokes.len(), 3, "incorrect key vector length");
406            assert_eq!(strokes[0], vk::VK_SHIFT);
407            assert_eq!(strokes[1], VK_2);
408            assert_eq!(strokes[2], vk::VK_SHIFT);
409        }
410
411        #[test]
412        fn test_number_three() {
413            let strokes = to_keystrokes_new("3").unwrap();
414
415            assert_eq!(strokes.len(), 1, "incorrect key vector length");
416            assert_eq!(strokes[0], VK_3);
417        }
418
419        #[test]
420        fn test_hash() {
421            let strokes = to_keystrokes_new("#").unwrap();
422
423            assert_eq!(strokes.len(), 3, "incorrect key vector length");
424            assert_eq!(strokes[0], vk::VK_SHIFT);
425            assert_eq!(strokes[1], VK_3);
426            assert_eq!(strokes[2], vk::VK_SHIFT);
427        }
428
429        #[test]
430        fn test_number_four() {
431            let strokes = to_keystrokes_new("4").unwrap();
432
433            assert_eq!(strokes.len(), 1, "incorrect key vector length");
434            assert_eq!(strokes[0], VK_4);
435        }
436
437        #[test]
438        fn test_dollar_sign() {
439            let strokes = to_keystrokes_new("$").unwrap();
440
441            assert_eq!(strokes.len(), 3, "incorrect key vector length");
442            assert_eq!(strokes[0], vk::VK_SHIFT);
443            assert_eq!(strokes[1], VK_4);
444            assert_eq!(strokes[2], vk::VK_SHIFT);
445        }
446
447        #[test]
448        fn test_number_five() {
449            let strokes = to_keystrokes_new("5").unwrap();
450
451            assert_eq!(strokes.len(), 1, "incorrect key vector length");
452            assert_eq!(strokes[0], VK_5);
453        }
454
455        #[test]
456        fn test_percent() {
457            let strokes = to_keystrokes_new("%").unwrap();
458
459            assert_eq!(strokes.len(), 3, "incorrect key vector length");
460            assert_eq!(strokes[0], vk::VK_SHIFT);
461            assert_eq!(strokes[1], VK_5);
462            assert_eq!(strokes[2], vk::VK_SHIFT);
463        }
464
465        #[test]
466        fn test_number_six() {
467            let strokes = to_keystrokes_new("6").unwrap();
468
469            assert_eq!(strokes.len(), 1, "incorrect key vector length");
470            assert_eq!(strokes[0], VK_6);
471        }
472
473        #[test]
474        fn test_caret() {
475            let strokes = to_keystrokes_new("^").unwrap();
476
477            assert_eq!(strokes.len(), 3, "incorrect key vector length");
478            assert_eq!(strokes[0], vk::VK_SHIFT);
479            assert_eq!(strokes[1], VK_6);
480            assert_eq!(strokes[2], vk::VK_SHIFT);
481        }
482
483        #[test]
484        fn test_seven() {
485            let strokes = to_keystrokes_new("7").unwrap();
486
487            assert_eq!(strokes.len(), 1, "incorrect key vector length");
488            assert_eq!(strokes[0], VK_7);
489        }
490
491        #[test]
492        fn test_ampersand() {
493            let strokes = to_keystrokes_new("&").unwrap();
494
495            assert_eq!(strokes.len(), 3, "incorrect key vector length");
496            assert_eq!(strokes[0], vk::VK_SHIFT);
497            assert_eq!(strokes[1], VK_7);
498            assert_eq!(strokes[2], vk::VK_SHIFT);
499        }
500
501        #[test]
502        fn test_number_eight() {
503            let strokes = to_keystrokes_new("8").unwrap();
504
505            assert_eq!(strokes.len(), 1, "incorrect key vector length");
506            assert_eq!(strokes[0], VK_8);
507        }
508
509        #[test]
510        fn test_number_9() {
511            let strokes = to_keystrokes_new("9").unwrap();
512
513            assert_eq!(strokes.len(), 1, "incorrect key vector length");
514            assert_eq!(strokes[0], VK_9);
515        }
516
517        #[test]
518        fn test_left_paren() {
519            let strokes = to_keystrokes_new("(").unwrap();
520
521            assert_eq!(strokes.len(), 3, "incorrect key vector length");
522            assert_eq!(strokes[0], vk::VK_SHIFT);
523            assert_eq!(strokes[1], VK_9);
524            assert_eq!(strokes[2], vk::VK_SHIFT);
525        }
526
527        #[test]
528        fn test_number_zero() {
529            let strokes = to_keystrokes_new("0").unwrap();
530
531            assert_eq!(strokes.len(), 1, "incorrect key vector length");
532            assert_eq!(strokes[0], VK_0);
533        }
534
535        #[test]
536        fn test_right_paren() {
537            let strokes = to_keystrokes_new(")").unwrap();
538
539            assert_eq!(strokes.len(), 3, "incorrect key vector length");
540            assert_eq!(strokes[0], vk::VK_SHIFT);
541            assert_eq!(strokes[1], VK_0);
542            assert_eq!(strokes[2], vk::VK_SHIFT);
543        }
544    }
545
546    #[test]
547    fn test_multiply() {
548        let strokes = to_keystrokes_new("*").unwrap();
549
550        assert_eq!(strokes.len(), 1, "incorrect key vector length");
551        assert_eq!(strokes[0], VK_MULTIPLY);
552    }
553
554    #[test]
555    fn test_plus() {
556        let strokes = to_keystrokes_new("+").unwrap();
557
558        assert_eq!(strokes.len(), 3, "incorrect key vector length");
559        assert_eq!(strokes[0], vk::VK_SHIFT);
560        assert_eq!(strokes[1], VK_OEM_PLUS);
561        assert_eq!(strokes[2], vk::VK_SHIFT);
562    }
563
564    #[test]
565    fn test_minus() {
566        let strokes = to_keystrokes_new("-").unwrap();
567
568        assert_eq!(strokes.len(), 1, "incorrect key vector length");
569        assert_eq!(strokes[0], VK_MINUS);
570    }
571
572    #[test]
573    fn test_comma() {
574        let strokes = to_keystrokes_new(",").unwrap();
575
576        assert_eq!(strokes.len(), 1, "incorrect key vector length");
577        assert_eq!(strokes[0], VK_OEM_COMMA);
578    }
579
580    #[test]
581    fn test_divide() {
582        let strokes = to_keystrokes_new("/").unwrap();
583
584        assert_eq!(strokes.len(), 1, "incorrect key vector length");
585        assert_eq!(strokes[0], VK_DIVIDE);
586    }
587
588    #[test]
589    fn test_period() {
590        let strokes = to_keystrokes_new(".").unwrap();
591
592        assert_eq!(strokes.len(), 1, "incorrect key vector length");
593        assert_eq!(strokes[0], VK_OEM_PERIOD);
594    }
595
596    #[test]
597    fn test_white_space() {
598        let strokes = to_keystrokes_new(" ").unwrap();
599
600        assert_eq!(strokes.len(), 1, "incorrect key vector length");
601        assert_eq!(strokes[0], VK_SPACE);
602    }
603
604    #[test]
605    fn test_semi_colon() {
606        let strokes = to_keystrokes_new(";").unwrap();
607
608        assert_eq!(strokes.len(), 1, "incorrect key vector length");
609        assert_eq!(strokes[0], VK_OEM_1);
610    }
611
612    #[test]
613    fn test_colon() {
614        let strokes = to_keystrokes_new(":").unwrap();
615
616        assert_eq!(strokes.len(), 3, "incorrect key vector length");
617        assert_eq!(strokes[0], vk::VK_SHIFT);
618        assert_eq!(strokes[1], VK_OEM_1);
619        assert_eq!(strokes[2], vk::VK_SHIFT);
620    }
621
622    #[test]
623    fn test_question_mark() {
624        let strokes = to_keystrokes_new("?").unwrap();
625
626        assert_eq!(strokes.len(), 3, "incorrect key vector length");
627        assert_eq!(strokes[0], vk::VK_SHIFT);
628        assert_eq!(strokes[1], VK_OEM_2);
629        assert_eq!(strokes[2], vk::VK_SHIFT);
630    }
631
632    #[test]
633    fn test_backtick() {
634        let strokes = to_keystrokes_new("`").unwrap();
635
636        assert_eq!(strokes.len(), 1, "incorrect key vector length");
637        assert_eq!(strokes[0], VK_OEM_3);
638    }
639
640    #[test]
641    fn test_tilde() {
642        let strokes = to_keystrokes_new("~").unwrap();
643
644        assert_eq!(strokes.len(), 3, "incorrect key vector length");
645        assert_eq!(strokes[0], vk::VK_SHIFT);
646        assert_eq!(strokes[1], VK_OEM_3);
647        assert_eq!(strokes[2], vk::VK_SHIFT);
648    }
649
650    #[test]
651    fn test_left_bracket() {
652        let strokes = to_keystrokes_new("[").unwrap();
653
654        assert_eq!(strokes.len(), 1, "incorrect key vector length");
655        assert_eq!(strokes[0], VK_OEM_4);
656    }
657
658    #[test]
659    fn test_left_curly_bracket() {
660        let strokes = to_keystrokes_new("{").unwrap();
661
662        assert_eq!(strokes.len(), 3, "incorrect key vector length");
663        assert_eq!(strokes[0], vk::VK_SHIFT);
664        assert_eq!(strokes[1], VK_OEM_4);
665        assert_eq!(strokes[2], vk::VK_SHIFT);
666    }
667
668    #[test]
669    fn test_backslash() {
670        let strokes = to_keystrokes_new("\\").unwrap();
671
672        assert_eq!(strokes.len(), 1, "incorrect key vector length");
673        assert_eq!(strokes[0], VK_OEM_5);
674    }
675
676    #[test]
677    fn test_vertical_bar() {
678        let strokes = to_keystrokes_new("|").unwrap();
679
680        assert_eq!(strokes.len(), 3, "incorrect key vector length");
681        assert_eq!(strokes[0], vk::VK_SHIFT);
682        assert_eq!(strokes[1], VK_OEM_5);
683        assert_eq!(strokes[2], vk::VK_SHIFT);
684    }
685
686    #[test]
687    fn test_right_bracket() {
688        let strokes = to_keystrokes_new("]").unwrap();
689
690        assert_eq!(strokes.len(), 1, "incorrect key vector length");
691        assert_eq!(strokes[0], VK_OEM_6);
692    }
693
694    #[test]
695    fn test_right_curly_bracket() {
696        let strokes = to_keystrokes_new("}").unwrap();
697
698        assert_eq!(strokes.len(), 3, "incorrect key vector length");
699        assert_eq!(strokes[0], vk::VK_SHIFT);
700        assert_eq!(strokes[1], VK_OEM_6);
701        assert_eq!(strokes[2], vk::VK_SHIFT);
702    }
703
704    #[test]
705    fn test_single_quote() {
706        let strokes = to_keystrokes_new("'").unwrap();
707
708        assert_eq!(strokes.len(), 1, "incorrect key vector length");
709        assert_eq!(strokes[0], VK_OEM_7);
710    }
711
712    #[test]
713    fn test_double_quote() {
714        let strokes = to_keystrokes_new("\"").unwrap();
715
716        assert_eq!(strokes.len(), 3, "incorrect key vector length");
717        assert_eq!(strokes[0], vk::VK_SHIFT);
718        assert_eq!(strokes[1], VK_OEM_7);
719        assert_eq!(strokes[2], vk::VK_SHIFT);
720    }
721
722    #[test]
723    fn test_less_than() {
724        let strokes = to_keystrokes_new("<").unwrap();
725
726        assert_eq!(strokes.len(), 3, "incorrect key vector length");
727        assert_eq!(strokes[0], vk::VK_SHIFT);
728        assert_eq!(strokes[1], VK_OEM_COMMA);
729        assert_eq!(strokes[2], vk::VK_SHIFT);
730    }
731
732    #[test]
733    fn test_greater_than() {
734        let strokes = to_keystrokes_new(">").unwrap();
735
736        assert_eq!(strokes.len(), 3, "incorrect key vector length");
737        assert_eq!(strokes[0], vk::VK_SHIFT);
738        assert_eq!(strokes[1], VK_OEM_PERIOD);
739        assert_eq!(strokes[2], vk::VK_SHIFT);
740    }
741
742    #[test]
743    fn test_equal() {
744        let strokes = to_keystrokes_new("=").unwrap();
745
746        assert_eq!(strokes.len(), 1, "incorrect key vector length");
747        assert_eq!(strokes[0], VK_OEM_PLUS);
748    }
749
750    #[test]
751    fn test_underscore() {
752        let strokes = to_keystrokes_new("_").unwrap();
753
754        assert_eq!(strokes.len(), 3, "incorrect key vector length");
755        assert_eq!(strokes[0], vk::VK_SHIFT);
756        assert_eq!(strokes[1], VK_OEM_MINUS);
757        assert_eq!(strokes[2], vk::VK_SHIFT);
758    }
759}