quick_input/
lib.rs

1//! # Quick Input
2//!
3//! This lightweight library offers a quick and easy way of handling user input, which can then
4//! be assigned to a variable directly. All functions handle the possibility of invalid values by
5//! looping until the desired type is inputted.
6//!
7//! Both an initial prompt message and error message are customisable and optional.
8//! If the error message is left empty (None), a default error message will be displayed
9//! (relaying on the default message should be avoided when possible).
10//!
11//! # Author
12//! - Kevin Claramonte Soler (kevclasol@proton.me).
13//! - 16/03/2025
14
15use std::io;
16use std::io::Write;
17
18// ----- MACROS ----- //
19
20#[macro_export]
21macro_rules! read_string {
22     () => {{
23         let mut input = String::new();
24
25         std::io::stdout().flush().unwrap();
26         std::io::stdin().read_line(&mut input).expect("Unable to read from stdin");
27
28         input.trim().to_string()
29     }};
30
31    ($message:expr) => {{
32        print!("{}", $message);
33        read_string!()
34    }};
35}
36
37// ----- MACROS ----- //
38
39// ----- BASIC ----- //
40/// # ARGUMENTS #
41/// 'msg' (Option<&str>) - an optional message which will be printed at
42/// the same line as the input prompt. Must be set to Some("...") or None.
43///
44/// # DESCRIPTION #
45/// Prompts the user to type a string of text which will then be returned.
46///
47/// Provides an information message on the same line as the prompt if Some(...)
48/// is provided, and just the prompt if None is provided.
49///
50/// # RETURNS #
51/// A trimmed String value provided by the user.
52///
53/// # EXAMPLES #
54/// ```
55/// use quick_input::read_string;
56/// let user_str_with_msg = read_string(Some("Please input some text: "));
57///
58/// let user_str: String = read_string(None);
59/// ```
60pub fn read_string(msg: Option<&str>) -> String {
61    let mut input = String::new();
62
63    if msg.is_some() {
64        print!("{}", msg.unwrap());
65        flush_and_read(&mut input);
66    } else {
67        flush_and_read(&mut input);
68    }
69
70    input.trim().to_string()
71}
72
73/// # ARGUMENTS #
74/// 'msg' (Option<&str>) - an optional message which will be printed at
75/// the same line as the input prompt. Must be set to Some("...") or None.
76///
77/// 'err_msg' (Option<&str>) - an optional error message which will be printed
78/// if the user inputs an invalid value. Must be set to Some("...") or None.
79///
80/// # DESCRIPTION #
81/// Prompts the user to type an integer value (i32) which will then be returned.
82/// In case the user writes an invalid value, they will be prompted to try again.
83///
84/// Provides an information message on the same line as the prompt if Some("...")
85/// is provided, and just the prompt if None is provided.
86///
87/// If err_msg is set to None, a default message will be shown.
88///
89/// # RETURNS #
90/// An integer value of type i32 provided by the user.
91///
92/// # EXAMPLES #
93/// ```
94/// use quick_input::read_i32;
95/// let user_i32_with_msg = read_i32(Some("Please input a number: "), Some("Please input a valid number."));
96///
97/// let user_i32: i32 = read_i32(None, None);
98/// ```
99pub fn read_i32(msg: Option<&str>, err_msg: Option<&str>) -> i32 {
100    let mut input = String::new();
101
102    if msg.is_some() {
103        while input.trim().parse::<i32>().is_err() {
104            input.clear();
105            print!("{}", msg.unwrap());
106            flush_and_read(&mut input);
107
108            if input.trim().parse::<i32>().is_err() {
109                show_error_message(err_msg, "Please enter a valid number (32 bits).");
110            }
111        }
112    } else {
113        while input.trim().parse::<i32>().is_err() {
114            input.clear();
115            flush_and_read(&mut input);
116
117            if input.trim().parse::<i32>().is_err() {
118                show_error_message(err_msg, "Please enter a valid number (32 bits).");
119            }
120        }
121    }
122
123    input.trim().parse().unwrap()
124}
125
126/// # ARGUMENTS #
127/// 'msg' (Option<&str>) - an optional message which will be printed at
128/// the same line as the input prompt. Must be set to Some("...") or None.
129///
130/// 'err_msg' (Option<&str>) - an optional error message which will be printed
131/// if the user inputs an invalid value. Must be set to Some("...") or None.
132///
133/// # DESCRIPTION #
134/// Prompts the user to type an integer value (u32) which will then be returned.
135/// If user writes an invalid value, they will be prompted to try again.
136///
137/// Provides an information message on the same line as the prompt if Some("...")
138/// is provided, and just the prompt if None is provided.
139///
140/// If err_msg is set to None, a default message will be shown.
141///
142/// # RETURNS #
143/// An integer value of type u32 provided by the user.
144///
145/// # EXAMPLES #
146/// ```
147/// use quick_input::read_u32;
148/// let user_u32_with_msg = read_u32(Some("Please input a number: "), Some("Please input a valid number."));
149///
150/// let user_u32: u32 = read_u32(None, None);
151/// ```
152pub fn read_u32(msg: Option<&str>, err_msg: Option<&str>) -> u32 {
153    let mut input = String::new();
154
155    if msg.is_some() {
156        while input.trim().parse::<u32>().is_err() {
157            input.clear();
158            print!("{}", msg.unwrap());
159            flush_and_read(&mut input);
160
161            if input.trim().parse::<u32>().is_err() {
162                show_error_message(err_msg, "Please enter a valid positive number (32 bits).");
163            }
164        }
165    } else {
166        while input.trim().parse::<i32>().is_err() {
167            input.clear();
168            flush_and_read(&mut input);
169
170            if input.trim().parse::<i32>().is_err() {
171                show_error_message(err_msg, "Please enter a valid positive number (32 bits).");
172            }
173        }
174    }
175
176    input.trim().parse().unwrap()
177}
178
179/// # ARGUMENTS #
180/// 'msg' (Option<&str>) - an optional message which will be printed at
181/// the same line as the input prompt. Must be set to Some("...") or None.
182///
183/// 'err_msg' (Option<&str>) - an optional error message which will be printed
184/// if the user inputs an invalid value. Must be set to Some("...") or None.
185///
186/// # DESCRIPTION #
187/// Prompts the user to type a real number with double precision (f64) which will then be returned.
188/// Both '.' and ',' are accepted as separators for the decimal part (Ex: 12.3 and 45,67).
189/// If the user writes an invalid value, they will be prompted to try again.
190///
191/// Provides an information message on the same line as the prompt if Some("...")
192/// is provided, and just the prompt if None is provided.
193///
194/// If err_msg is set to None, a default message will be shown.
195///
196/// # RETURNS #
197/// A floating point value of type f64 provided by the user.
198///
199/// # EXAMPLES #
200/// ```
201/// use quick_input::read_f64;
202/// let user_f64_with_msg = read_f64(Some("Please input a number with decimals: "), Some("Please input a valid number."));
203///
204/// let user_f64: f64 = read_f64(None, None);
205/// ```
206pub fn read_f64(msg: Option<&str>, err_msg: Option<&str>) -> f64 {
207    let mut input = String::new();
208
209    if msg.is_some() {
210        while input.replace(',', ".").trim().parse::<f64>().is_err() {
211            input.clear();
212            print!("{}", msg.unwrap());
213            flush_and_read(&mut input);
214
215            if input.replace(',', ".").trim().parse::<f64>().is_err() {
216                show_error_message(err_msg, "Please enter a valid real number (64 bits).");
217            }
218        }
219    } else {
220        while input.trim().parse::<f64>().is_err() {
221            input.clear();
222            flush_and_read(&mut input);
223
224            if input.replace(',', ".").trim().parse::<f64>().is_err() {
225                show_error_message(err_msg, "Please enter a valid real number (64 bits).");
226            }
227        }
228    }
229
230    input.replace(',', ".").trim().parse().unwrap()
231}
232
233/// # ARGUMENTS #
234/// 'msg' (Option<&str>) - an optional message which will be printed at
235/// the same line as the input prompt. Must be set to Some("...") or None.
236///
237/// # DESCRIPTION #
238/// Prompts the user to type a character (char) which will then be returned.
239///
240/// Provides an information message on the same line as the prompt if Some("...")
241/// is provided, and just the prompt if None is provided.
242///
243/// # RETURNS #
244/// A single character (char) provided by the user.
245///
246/// # EXAMPLES #
247/// ```
248/// use quick_input::read_char;
249/// let user_char_with_msg = read_char(Some("Please input a character: "));
250///
251/// let user_char: char = read_char(None);
252/// ```
253pub fn read_char(msg: Option<&str>) -> char {
254    let mut input = String::from(".");
255
256    if msg.is_some() {
257        input.clear();
258        print!("{}", msg.unwrap());
259        flush_and_read(&mut input);
260    } else {
261        input.clear();
262        flush_and_read(&mut input);
263    }
264
265    input.trim().chars().next().unwrap()
266}
267
268/// # ARGUMENTS #
269/// 'msg' (Option<&str>) - an optional message which will be printed at
270/// the same line as the input prompt. Must be set to Some("...") or None.
271///
272/// 'err_msg' (Option<&str>) - an optional error message which will be printed
273/// if the user inputs an invalid value. Must be set to Some("...") or None.
274///
275/// # DESCRIPTION #
276/// Prompts the user to type a boolean value (bool) manually, which will then be returned.
277/// This function is not case-sensitive, so values like True or fAlSe will still work.
278/// In case the user writes an invalid value, they will be prompted to try again.
279///
280/// Provides an information message on the same line as the prompt if Some("...")
281/// is provided, and just the prompt if None is provided.
282///
283/// If err_msg is set to None, a default message will be shown.
284///
285/// # RETURNS #
286/// A boolean value (bool) provided by the user.
287///
288/// # EXAMPLES #
289/// ```
290/// use quick_input::read_bool;
291/// let user_bool_with_msg = read_bool(Some("Please input a boolean value: "), Some("Please input true or false."));
292///
293/// let user_bool: bool = read_bool(None, None);
294/// ```
295pub fn read_bool(msg: Option<&str>, err_msg: Option<&str>) -> bool {
296    let mut input = String::new();
297
298    if msg.is_some() {
299        while input.trim().parse::<bool>().is_err() {
300            input.clear();
301            print!("{}", msg.unwrap());
302            flush_and_read(&mut input);
303
304            input = input.trim().to_lowercase();
305
306            if input.parse::<bool>().is_err() {
307                show_error_message(err_msg, "Please enter a valid boolean value (true / false).");
308            }
309        }
310    } else {
311        while input.trim().parse::<bool>().is_err() {
312            input.clear();
313            flush_and_read(&mut input);
314
315            input = input.trim().to_lowercase();
316
317            println!("{input}");
318
319            if input.parse::<bool>().is_err() {
320                show_error_message(err_msg, "Please enter a valid boolean value (true / false).");
321            }
322        }
323    }
324
325    input.trim().parse::<bool>().unwrap()
326}
327
328// ----- EXTRA ----- //
329
330/// # ARGUMENTS #
331/// 'msg' (Option<&str>) - an optional message which will be printed at
332/// the same line as the input prompt. Must be set to Some("...") or None.
333///
334/// # DESCRIPTION #
335/// Prompts the user to type a string of text which will then be returned.
336///
337/// Provides an information message on the same line as the prompt if Some(...)
338/// is provided, and just the prompt if None is provided.
339///
340/// # RETURNS #
341/// A non-trimmed String value provided by the user.
342///
343/// # EXAMPLES #
344/// ```
345/// use quick_input::read_string_untrimmed;
346/// let user_str_with_msg = read_string_untrimmed(Some("Please input some text: "));
347///
348/// let user_str: String = read_string_untrimmed(None);
349/// ```
350pub fn read_string_untrimmed(msg: Option<&str>) -> String {
351    let mut input = String::new();
352
353    if msg.is_some() {
354        print!("{}", msg.unwrap());
355        flush_and_read(&mut input);
356    } else {
357        flush_and_read(&mut input);
358    }
359    input
360}
361
362/// # DESCRIPTION #
363/// Prompts the user to type a string of text which will then be returned.
364/// Useful for prototyping and quick tests.
365///
366/// # RETURNS #
367/// A trimmed String value provided by the user.
368///
369/// # EXAMPLES #
370/// ```
371/// use quick_input::read_string_no_msg;
372///
373/// let user_str: String = read_string_no_msg();
374/// ```
375pub fn read_string_no_msg() -> String {
376    read_string(None)
377}
378
379/// # DESCRIPTION #
380/// Prompts the user to type a character (char) which will then be returned.
381/// Useful for prototyping or quick tests.
382///
383/// # RETURNS #
384/// A single character (char) provided by the user.
385///
386/// # EXAMPLES #
387/// ```
388/// use quick_input::read_char_no_msg;
389///
390/// let user_char: char = read_char_no_msg();
391/// ```
392pub fn read_char_no_msg() -> char {
393    read_char(None)
394}
395
396/// # ARGUMENTS #
397/// 'msg' (Option<&str>) - an optional message which will be printed at
398/// the same line as the input prompt. Must be set to Some("...") or None.
399///
400/// # DESCRIPTION #
401/// Prompts the user to type an integer value (i32) which will then be returned.
402/// In case the user writes an invalid value, they will be prompted to try again.
403///
404/// Provides an information message on the same line as the prompt if Some("...")
405/// is provided, and just the prompt if None is provided.
406///
407/// Useful for prototyping and quick tests.
408///
409/// # RETURNS #
410/// An integer value of type i32 provided by the user.
411///
412/// # EXAMPLES #
413/// ```
414/// use quick_input::read_i32_def_err;
415/// let user_i32_with_msg = read_i32_def_err(Some("Please input a number: "));
416///
417/// let user_i32: i32 = read_i32_def_err(None);
418/// ```
419pub fn read_i32_def_err(msg: Option<&str>) -> i32 {
420    read_i32(msg, None)
421}
422
423/// # ARGUMENTS #
424/// 'msg' (Option<&str>) - an optional message which will be printed at
425/// the same line as the input prompt. Must be set to Some("...") or None.
426///
427/// # DESCRIPTION #
428/// Prompts the user to type a real number with double precision (f64) which will then be returned.
429/// Both '.' and ',' are accepted as separators for the decimal part (Ex: 12.3 and 45,67).
430/// If the user writes an invalid value, they will be prompted to try again.
431///
432/// Provides an information message on the same line as the prompt if Some("...")
433/// is provided, and just the prompt if None is provided.
434///
435/// Useful for prototyping and quick tests.
436///
437/// # RETURNS #
438/// A floating point value of type f64 provided by the user.
439///
440/// # EXAMPLES #
441/// ```
442/// use quick_input::read_f64_def_err;
443/// let user_f64_with_msg = read_f64_def_err(Some("Please input a number with decimals: "));
444///
445/// let user_f64: f64 = read_f64_def_err(None);
446/// ```
447pub fn read_f64_def_err(msg: Option<&str>) -> f64 {
448    read_f64(msg, None)
449}
450
451/// # ARGUMENTS #
452/// 'msg' (Option<&str>) - an optional message which will be printed at
453/// the same line as the input prompt. Must be set to Some("...") or None.
454///
455/// # DESCRIPTION #
456/// Prompts the user to type an integer value (u32) which will then be returned.
457/// If user writes an invalid value, they will be prompted to try again.
458///
459/// Provides an information message on the same line as the prompt if Some("...")
460/// is provided, and just the prompt if None is provided.
461///
462/// Useful for prototyping and quick tests.
463///
464/// # RETURNS #
465/// An integer value of type u32 provided by the user.
466///
467/// # EXAMPLES #
468/// ```
469/// use quick_input::read_u32_def_err;
470/// let user_u32_with_msg = read_u32_def_err(Some("Please input a number: "));
471///
472/// let user_u32: u32 = read_u32_def_err(None);
473/// ```
474pub fn read_u32_def_err(msg: Option<&str>) -> u32 {
475    read_u32(msg, None)
476}
477
478/// # ARGUMENTS #
479/// 'msg' (Option<&str>) - an optional message which will be printed at
480/// the same line as the input prompt. Must be set to Some("...") or None.
481///
482/// 'err_msg' (Option<&str>) - an optional error message which will be printed
483/// if the user inputs an invalid value. Must be set to Some("...") or None.
484///
485/// # DESCRIPTION #
486/// Prompts the user to type a real number with single precision (f32) which will then be returned.
487/// Both '.' and ',' are accepted as separators for the decimal part (Ex: 12.3 and 45,67).
488/// If the user writes an invalid value, they will be prompted to try again.
489///
490/// Provides an information message on the same line as the prompt if Some("...")
491/// is provided, and just the prompt if None is provided.
492///
493/// If err_msg is set to None, a default message will be shown.
494///
495/// # RETURNS #
496/// A floating point value of type f32 provided by the user.
497///
498/// # EXAMPLES #
499/// ```
500/// use quick_input::read_f32;
501/// let user_f32_with_msg = read_f32(Some("Please input a number with decimals: "), Some("Please input a valid number."));
502///
503/// let user_f32: f32 = read_f32(None, None);
504/// ```
505pub fn read_f32(msg: Option<&str>, err_msg: Option<&str>) -> f32 {
506    let mut input = String::new();
507
508    if msg.is_some() {
509        while input.replace(',', ".").trim().parse::<f32>().is_err() {
510            input.clear();
511            print!("{}", msg.unwrap());
512            flush_and_read(&mut input);
513
514            if input.replace(',', ".").trim().parse::<f32>().is_err() {
515                show_error_message(err_msg, "Please enter a valid real number (32 bits).");
516            }
517        }
518    } else {
519        while input.trim().parse::<f32>().is_err() {
520            input.clear();
521            flush_and_read(&mut input);
522
523            if input.replace(',', ".").trim().parse::<f32>().is_err() {
524                show_error_message(err_msg, "Please enter a valid real number (32 bits).");
525            }
526        }
527    }
528
529    input.replace(',', ".").trim().parse().unwrap()
530}
531
532/// # ARGUMENTS #
533/// 'msg' (Option<&str>) - an optional message which will be printed at
534/// the same line as the input prompt. Must be set to Some("...") or None.
535///
536/// 'err_msg' (Option<&str>) - an optional error message which will be printed
537/// if the user inputs an invalid value. Must be set to Some("...") or None.
538///
539/// # DESCRIPTION #
540/// Prompts the user to type an integer value (i8) which will then be returned.
541/// In case the user writes an invalid value, they will be prompted to try again.
542///
543/// Provides an information message on the same line as the prompt if Some("...")
544/// is provided, and just the prompt if None is provided.
545///
546/// If err_msg is set to None, a default message will be shown.
547///
548/// # RETURNS #
549/// An integer value of type i8 provided by the user.
550///
551/// # EXAMPLES #
552/// ```
553/// use quick_input::read_i8;
554/// let user_i8_with_msg = read_i8(Some("Please input a number: "),Some("Please input a valid number."));
555///
556/// let user_i8: i8 = read_i8(None, None);
557/// ```
558pub fn read_i8(msg: Option<&str>, err_msg: Option<&str>) -> i8 {
559    let mut input = String::new();
560
561    if msg.is_some() {
562        while input.trim().parse::<i8>().is_err() {
563            input.clear();
564            print!("{}", msg.unwrap());
565            flush_and_read(&mut input);
566
567            if input.trim().parse::<i8>().is_err() {
568                show_error_message(err_msg, "Please enter a valid number (8 bits).");
569            }
570        }
571    } else {
572        while input.trim().parse::<i8>().is_err() {
573            input.clear();
574            flush_and_read(&mut input);
575
576            if input.trim().parse::<i8>().is_err() {
577                show_error_message(err_msg, "Please enter a valid number (8 bits).");
578            }
579        }
580    }
581
582    input.trim().parse().unwrap()
583}
584
585/// # ARGUMENTS #
586/// 'msg' (Option<&str>) - an optional message which will be printed at
587/// the same line as the input prompt. Must be set to Some("...") or None.
588///
589/// 'err_msg' (Option<&str>) - an optional error message which will be printed
590/// if the user inputs an invalid value. Must be set to Some("...") or None.
591///
592/// # DESCRIPTION #
593/// Prompts the user to type an integer value (u8) which will then be returned.
594/// In case the user writes an invalid value, they will be prompted to try again.
595///
596/// Provides an information message on the same line as the prompt if Some("...")
597/// is provided, and just the prompt if None is provided.
598///
599/// If err_msg is set to None, a default message will be shown.
600///
601/// # RETURNS #
602/// An integer value of type u8 provided by the user.
603///
604/// # EXAMPLES #
605/// ```
606/// use quick_input::read_u8;
607/// let user_u8_with_msg = read_u8(Some("Please input a number: "), Some("Please input a valid number."));
608///
609/// let user_u8: u8 = read_u8(None, None);
610/// ```
611pub fn read_u8(msg: Option<&str>, err_msg: Option<&str>) -> u8 {
612    let mut input = String::new();
613
614    if msg.is_some() {
615        while input.trim().parse::<u8>().is_err() {
616            input.clear();
617            print!("{}", msg.unwrap());
618            flush_and_read(&mut input);
619
620            if input.trim().parse::<u8>().is_err() {
621                show_error_message(err_msg, "Please enter a valid positive number (8 bits).");
622            }
623        }
624    } else {
625        while input.trim().parse::<u8>().is_err() {
626            input.clear();
627            flush_and_read(&mut input);
628
629            if input.trim().parse::<u8>().is_err() {
630                show_error_message(err_msg, "Please enter a valid positive number (8 bits).");
631            }
632        }
633    }
634
635    input.trim().parse().unwrap()
636}
637
638/// # ARGUMENTS #
639/// 'msg' (Option<&str>) - an optional message which will be printed at
640/// the same line as the input prompt. Must be set to Some("...") or None.
641///
642/// 'err_msg' (Option<&str>) - an optional error message which will be printed
643/// if the user inputs an invalid value. Must be set to Some("...") or None.
644///
645/// # DESCRIPTION #
646/// Prompts the user to type an integer value (i16) which will then be returned.
647/// In case the user writes an invalid value, they will be prompted to try again.
648///
649/// Provides an information message on the same line as the prompt if Some("...")
650/// is provided, and just the prompt if None is provided.
651///
652/// If err_msg is set to None, a default message will be shown.
653///
654/// # RETURNS #
655/// An integer value of type i16 provided by the user.
656///
657/// # EXAMPLES #
658/// ```
659/// use quick_input::read_i16;
660/// let user_i16_with_msg = read_i16(Some("Please input a number: "), Some("Please input a valid number."));
661///
662/// let user_i16: i16 = read_i16(None, None);
663/// ```
664pub fn read_i16(msg: Option<&str>, err_msg: Option<&str>) -> i16 {
665    let mut input = String::new();
666
667    if msg.is_some() {
668        while input.trim().parse::<i16>().is_err() {
669            input.clear();
670            print!("{}", msg.unwrap());
671            flush_and_read(&mut input);
672
673            if input.trim().parse::<i16>().is_err() {
674                show_error_message(err_msg, "Please enter a valid number (16 bits).");
675            }
676        }
677    } else {
678        while input.trim().parse::<i16>().is_err() {
679            input.clear();
680            flush_and_read(&mut input);
681
682            if input.trim().parse::<i16>().is_err() {
683                show_error_message(err_msg, "Please enter a valid number (16 bits).");
684            }
685        }
686    }
687
688    input.trim().parse().unwrap()
689}
690
691/// # ARGUMENTS #
692/// 'msg' (Option<&str>) - an optional message which will be printed at
693/// the same line as the input prompt. Must be set to Some("...") or None.
694///
695/// 'err_msg' (Option<&str>) - an optional error message which will be printed
696/// if the user inputs an invalid value. Must be set to Some("...") or None.
697///
698/// # DESCRIPTION #
699/// Prompts the user to type an integer value (u16) which will then be returned.
700/// In case the user writes an invalid value, they will be prompted to try again.
701///
702/// Provides an information message on the same line as the prompt if Some("...")
703/// is provided, and just the prompt if None is provided.
704///
705/// If err_msg is set to None, a default message will be shown.
706///
707/// # RETURNS #
708/// An integer value of type u16 provided by the user.
709///
710/// # EXAMPLES #
711/// ```
712/// use quick_input::read_u16;
713/// let user_u16_with_msg = read_u16(Some("Please input a number: "), Some("Please input a valid number."));
714///
715/// let user_u16: u16 = read_u16(None, None);
716/// ```
717pub fn read_u16(msg: Option<&str>, err_msg: Option<&str>) -> u16 {
718    let mut input = String::new();
719
720    if msg.is_some() {
721        while input.trim().parse::<u16>().is_err() {
722            input.clear();
723            print!("{}", msg.unwrap());
724            flush_and_read(&mut input);
725
726            if input.trim().parse::<u16>().is_err() {
727                show_error_message(err_msg, "Please enter a valid positive number (16 bits).");
728            }
729        }
730    } else {
731        while input.trim().parse::<u16>().is_err() {
732            input.clear();
733            flush_and_read(&mut input);
734
735            if input.trim().parse::<u16>().is_err() {
736                show_error_message(err_msg, "Please enter a valid positive number (16 bits).");
737            }
738        }
739    }
740
741    input.trim().parse().unwrap()
742}
743
744/// # ARGUMENTS #
745/// 'msg' (Option<&str>) - an optional message which will be printed at
746/// the same line as the input prompt. Must be set to Some("...") or None.
747///
748/// 'err_msg' (Option<&str>) - an optional error message which will be printed
749/// if the user inputs an invalid value. Must be set to Some("...") or None.
750///
751/// # DESCRIPTION #
752/// Prompts the user to type an integer value (i64) which will then be returned.
753/// In case the user writes an invalid value, they will be prompted to try again.
754///
755/// Provides an information message on the same line as the prompt if Some("...")
756/// is provided, and just the prompt if None is provided.
757///
758/// If err_msg is set to None, a default message will be shown.
759///
760/// # RETURNS #
761/// An integer value of type i64 provided by the user.
762///
763/// # EXAMPLES #
764/// ```
765/// use quick_input::read_i64;
766/// let user_i64_with_msg = read_i64(Some("Please input a number: "), Some("Please input a valid number"));
767///
768/// let user_i64: i64 = read_i64(None, None);
769/// ```
770pub fn read_i64(msg: Option<&str>, err_msg: Option<&str>) -> i64 {
771    let mut input = String::new();
772
773    if msg.is_some() {
774        while input.trim().parse::<i64>().is_err() {
775            input.clear();
776            print!("{}", msg.unwrap());
777            flush_and_read(&mut input);
778
779            if input.trim().parse::<i64>().is_err() {
780                show_error_message(err_msg, "Please enter a valid number (64 bits).");
781            }
782        }
783    } else {
784        while input.trim().parse::<i64>().is_err() {
785            input.clear();
786            flush_and_read(&mut input);
787
788            if input.trim().parse::<i64>().is_err() {
789                show_error_message(err_msg, "Please enter a valid number (64 bits).");
790            }
791        }
792    }
793
794    input.trim().parse().unwrap()
795}
796
797/// # ARGUMENTS #
798/// 'msg' (Option<&str>) - an optional message which will be printed at
799/// the same line as the input prompt. Must be set to Some("...") or None.
800///
801/// 'err_msg' (Option<&str>) - an optional error message which will be printed
802/// if the user inputs an invalid value. Must be set to Some("...") or None.
803///
804/// # DESCRIPTION #
805/// Prompts the user to type an integer value (u64) which will then be returned.
806/// In case the user writes an invalid value, they will be prompted to try again.
807///
808/// Provides an information message on the same line as the prompt if Some("...")
809/// is provided, and just the prompt if None is provided.
810///
811/// If err_msg is set to None, a default message will be shown.
812///
813/// # RETURNS #
814/// An integer value of type u64 provided by the user.
815///
816/// # EXAMPLES #
817/// ```
818/// use quick_input::read_u64;
819/// let user_u64_with_msg = read_u64(Some("Please input a number: "), Some("Please input a valid number."));
820///
821/// let user_u64: u64 = read_u64(None, None);
822/// ```
823pub fn read_u64(msg: Option<&str>, err_msg: Option<&str>) -> u64 {
824    let mut input = String::new();
825
826    if msg.is_some() {
827        while input.trim().parse::<u64>().is_err() {
828            input.clear();
829            print!("{}", msg.unwrap());
830            flush_and_read(&mut input);
831
832            if input.trim().parse::<u64>().is_err() {
833                show_error_message(err_msg, "Please enter a valid positive number (64 bits).");
834            }
835        }
836    } else {
837        while input.trim().parse::<u64>().is_err() {
838            input.clear();
839            flush_and_read(&mut input);
840
841            if input.trim().parse::<u64>().is_err() {
842                show_error_message(err_msg, "Please enter a valid positive number (64 bits).");
843            }
844        }
845    }
846
847    input.trim().parse().unwrap()
848}
849
850/// # ARGUMENTS #
851/// 'msg' (Option<&str>) - an optional message which will be printed at
852/// the same line as the input prompt. Must be set to Some("...") or None.
853///
854/// 'err_msg' (Option<&str>) - an optional error message which will be printed
855/// if the user inputs an invalid value. Must be set to Some("...") or None.
856///
857/// # DESCRIPTION #
858/// Prompts the user to type an integer value (i128) which will then be returned.
859/// In case the user writes an invalid value, they will be prompted to try again.
860///
861/// Provides an information message on the same line as the prompt if Some("...")
862/// is provided, and just the prompt if None is provided.
863///
864/// If err_msg is set to None, a default message will be shown.
865///
866/// # RETURNS #
867/// An integer value of type i128 provided by the user.
868///
869/// # EXAMPLES #
870/// ```
871/// use quick_input::read_i128;
872/// let user_i128_with_msg = read_i128(Some("Please input a number: "), Some("Please input a valid number."));
873///
874/// let user_i128: i128 = read_i128(None, None);
875/// ```
876pub fn read_i128(msg: Option<&str>, err_msg: Option<&str>) -> i128 {
877    let mut input = String::new();
878
879    if msg.is_some() {
880        while input.trim().parse::<i128>().is_err() {
881            input.clear();
882            print!("{}", msg.unwrap());
883            flush_and_read(&mut input);
884
885            if input.trim().parse::<i128>().is_err() {
886                show_error_message(err_msg, "Please enter a valid number (128 bits).");
887            }
888        }
889    } else {
890        while input.trim().parse::<i128>().is_err() {
891            input.clear();
892            flush_and_read(&mut input);
893
894            if input.trim().parse::<i128>().is_err() {
895                show_error_message(err_msg, "Please enter a valid number (128 bits).");
896            }
897        }
898    }
899
900    input.trim().parse().unwrap()
901}
902
903/// # ARGUMENTS #
904/// 'msg' (Option<&str>) - an optional message which will be printed at
905/// the same line as the input prompt. Must be set to Some("...") or None.
906///
907/// 'err_msg' (Option<&str>) - an optional error message which will be printed
908/// if the user inputs an invalid value. Must be set to Some("...") or None.
909///
910/// # DESCRIPTION #
911/// Prompts the user to type an integer value (u128) which will then be returned.
912/// In case the user writes an invalid value, they will be prompted to try again.
913///
914/// Provides an information message on the same line as the prompt if Some("...")
915/// is provided, and just the prompt if None is provided.
916///
917/// If err_msg is set to None, a default message will be shown.
918///
919/// # RETURNS #
920/// An integer value of type u128 provided by the user.
921///
922/// # EXAMPLES #
923/// ```
924/// use quick_input::read_u128;
925/// let user_u128_with_msg = read_u128(Some("Please input a number: "), Some("Please input a valid number."));
926///
927/// let user_u128: u128 = read_u128(None, None);
928/// ```
929pub fn read_u128(msg: Option<&str>, err_msg: Option<&str>) -> u128 {
930    let mut input = String::new();
931
932    if msg.is_some() {
933        while input.trim().parse::<u128>().is_err() {
934            input.clear();
935            print!("{}", msg.unwrap());
936            flush_and_read(&mut input);
937
938            if input.trim().parse::<u128>().is_err() {
939                show_error_message(err_msg, "Please enter a valid positive number (128 bits).");
940            }
941        }
942    } else {
943        while input.trim().parse::<u128>().is_err() {
944            input.clear();
945            flush_and_read(&mut input);
946
947            if input.trim().parse::<u128>().is_err() {
948                show_error_message(err_msg, "Please enter a valid positive number (128 bits).");
949            }
950        }
951    }
952
953    input.trim().parse().unwrap()
954}
955
956/// # ARGUMENTS #
957/// 'msg' (Option<&str>) - an optional message which will be printed at
958/// the same line as the input prompt. Must be set to Some("...") or None.
959///
960/// 'err_msg' (Option<&str>) - an optional error message which will be printed
961/// if the user inputs an invalid value. Must be set to Some("...") or None.
962///
963/// # DESCRIPTION #
964/// Prompts the user to type an integer value (isize) which will then be returned.
965/// In case the user writes an invalid value, they will be prompted to try again.
966///
967/// Provides an information message on the same line as the prompt if Some("...")
968/// is provided, and just the prompt if None is provided.
969///
970/// If err_msg is set to None, a default message will be shown.
971///
972/// # RETURNS #
973/// An integer value of type isize provided by the user.
974///
975/// # EXAMPLES #
976/// ```
977/// use quick_input::read_isize;
978/// let user_isize_with_msg = read_isize(Some("Please input a number: "), Some("Please input a valid number"));
979///
980/// let user_isize: isize = read_isize(None, None);
981/// ```
982pub fn read_isize(msg: Option<&str>, err_msg: Option<&str>) -> isize {
983    let mut input = String::new();
984
985    if msg.is_some() {
986        while input.trim().parse::<isize>().is_err() {
987            input.clear();
988            print!("{}", msg.unwrap());
989            flush_and_read(&mut input);
990
991            if input.trim().parse::<isize>().is_err() {
992                show_error_message(err_msg, "Please enter a valid number (32/64 bits).");
993            }
994        }
995    } else {
996        while input.trim().parse::<isize>().is_err() {
997            input.clear();
998            flush_and_read(&mut input);
999
1000            if input.trim().parse::<isize>().is_err() {
1001                show_error_message(err_msg, "Please enter a valid number (32/64 bits).");
1002            }
1003        }
1004    }
1005
1006    input.trim().parse().unwrap()
1007}
1008
1009/// # ARGUMENTS #
1010/// 'msg' (Option<&str>) - an optional message which will be printed at
1011/// the same line as the input prompt. Must be set to Some("...") or None.
1012///
1013/// 'err_msg' (Option<&str>) - an optional error message which will be printed
1014/// if the user inputs an invalid value. Must be set to Some("...") or None.
1015///
1016/// # DESCRIPTION #
1017/// Prompts the user to type an integer value (usize) which will then be returned.
1018/// In case the user writes an invalid value, they will be prompted to try again.
1019///
1020/// Provides an information message on the same line as the prompt if Some("...")
1021/// is provided, and just the prompt if None is provided.
1022///
1023/// If err_msg is set to None, a default message will be shown.
1024///
1025/// # RETURNS #
1026/// An integer value of type usize provided by the user.
1027///
1028/// # EXAMPLES #
1029/// ```
1030/// use quick_input::read_usize;
1031/// let user_usize_with_msg = read_usize(Some("Please input a number: "), Some("Please input a valid number."));
1032///
1033/// let user_usize: usize = read_usize(None, None);
1034/// ```
1035pub fn read_usize(msg: Option<&str>, err_msg: Option<&str>) -> usize {
1036    let mut input = String::new();
1037
1038    if msg.is_some() {
1039        while input.trim().parse::<usize>().is_err() {
1040            input.clear();
1041            print!("{}", msg.unwrap());
1042            flush_and_read(&mut input);
1043
1044            if input.trim().parse::<usize>().is_err() {
1045                show_error_message(err_msg, "Please enter a valid positive number (32/64 bits).");
1046            }
1047        }
1048    } else {
1049        while input.trim().parse::<usize>().is_err() {
1050            input.clear();
1051            flush_and_read(&mut input);
1052
1053            if input.trim().parse::<usize>().is_err() {
1054                show_error_message(err_msg, "Please enter a valid positive number (32/64 bits).");
1055            }
1056        }
1057    }
1058
1059    input.trim().parse().unwrap()
1060}
1061
1062
1063// ----- PRIVATE METHODS ----- //
1064
1065/// # Arguments #
1066/// 'input' (&mut String) - Mutable reference to the variable containing
1067/// an empty String, which is returned at the end of all read_* methods.
1068///
1069/// # Description #
1070/// Private method used to force the print!() macro to show the &str message provided
1071/// on the same line as the input prompt.
1072///
1073/// This function also obtains the value typed by the user and assings it
1074/// to the "input" variable through the mutable reference provided.
1075fn flush_and_read(input: &mut String) {
1076    io::stdout().flush().unwrap();
1077    io::stdin()
1078        .read_line(input)
1079        .expect("Unable to read from stdin.");
1080}
1081
1082/// # Arguments #
1083/// 'err_msg' (Option<&str>) - Custom error message which will be displayed in case
1084/// the user provides an invalid value. Must be set to Some("...") or None.
1085///
1086/// 'def_err_msg' (&str) - Default error message that will be shown if the user provides
1087/// an invalid value and the provided error message (err_msg) is set to None.
1088///
1089/// # Description #
1090/// Private function used to display a custom error message if the users provides an invalid value.
1091/// This function will display a default error message if the provided custom error message is set to None.
1092fn show_error_message(err_msg: Option<&str>, def_err_msg: &str) {
1093    if err_msg.is_some() {
1094        println!("{}", err_msg.unwrap());
1095        println!("---");
1096    } else {
1097        println!("{def_err_msg}");
1098        println!("---");
1099    }
1100}
1101
1102
1103#[cfg(test)]
1104mod tests {}