1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
use crate::{ReadLine, read_string, BoxResult};
use std::collections::{HashMap, LinkedList, VecDeque};





pub fn read_input_option<T: ToString + Clone>(choices: &[T]) -> BoxResult<T> {
	let choice_strings = choices.iter().map(ToString::to_string).collect::<Vec<_>>();
	loop {
		println!("Enter one of the following:");
		for choice in &choice_strings {
			println!("'{choice}'");
		}
		let output = read_string()?;
		for (i, choice) in choice_strings.iter().enumerate() {
			if choice.eq_ignore_ascii_case(&output) {
				return Ok(choices[i].clone());
			}
		}
		println!("Invalid option.");
	}
}






impl<T> ReadLine for &[T]
	where T: ToString + Clone
{
	type Output = T;
	fn try_read_line(&self) -> BoxResult<Self::Output> {
		read_input_option(self)
	}
}

impl<T, const LEN: usize> ReadLine for &[T; LEN]
	where T: ToString + Clone
{
	type Output = T;
	fn try_read_line(&self) -> BoxResult<Self::Output> {
		read_input_option(*self)
	}
}

impl<T> ReadLine for Vec<T>
	where T: ToString + Clone
{
	type Output = T;
	fn try_read_line(&self) -> BoxResult<Self::Output> {
		read_input_option(self)
	}
}

impl<T> ReadLine for VecDeque<T>
	where T: ToString + Clone
{
	type Output = T;
	fn try_read_line(&self) -> BoxResult<Self::Output> {
		read_input_option(&self.iter().cloned().collect::<Vec<_>>())
	}
}

impl<K, T> ReadLine for HashMap<K, T>
	where T: ToString + Clone
{
	type Output = T;
	fn try_read_line(&self) -> BoxResult<Self::Output> {
		read_input_option(&self.values().cloned().collect::<Vec<_>>())
	}
}

impl<T> ReadLine for LinkedList<T>
	where T: ToString + Clone
{
	type Output = T;
	fn try_read_line(&self) -> BoxResult<Self::Output> {
		read_input_option(&self.iter().cloned().collect::<Vec<_>>())
	}
}