open_sesame/input/
buffer.rs1use std::fmt;
6
7const MAX_INPUT_LENGTH: usize = 64;
13
14#[derive(Debug, Clone, Default)]
19pub struct InputBuffer {
20 chars: Vec<char>,
22}
23
24impl InputBuffer {
25 pub fn new() -> Self {
27 Self { chars: Vec::new() }
28 }
29
30 pub fn push(&mut self, c: char) -> bool {
34 if self.chars.len() >= MAX_INPUT_LENGTH {
35 tracing::debug!(
36 "Input buffer full ({} chars), ignoring input",
37 MAX_INPUT_LENGTH
38 );
39 return false;
40 }
41 self.chars.push(c.to_ascii_lowercase());
43 true
44 }
45
46 pub fn pop(&mut self) -> Option<char> {
48 self.chars.pop()
49 }
50
51 pub fn clear(&mut self) {
53 self.chars.clear();
54 }
55
56 pub fn is_empty(&self) -> bool {
58 self.chars.is_empty()
59 }
60
61 pub fn len(&self) -> usize {
63 self.chars.len()
64 }
65
66 pub fn first_char(&self) -> Option<char> {
68 self.chars.first().copied()
69 }
70
71 pub fn as_str(&self) -> String {
73 self.chars.iter().collect()
74 }
75
76 pub fn chars(&self) -> &[char] {
78 &self.chars
79 }
80}
81
82impl fmt::Display for InputBuffer {
83 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84 write!(f, "{}", self.as_str())
85 }
86}
87
88impl From<&str> for InputBuffer {
89 fn from(s: &str) -> Self {
90 Self {
91 chars: s.to_lowercase().chars().take(MAX_INPUT_LENGTH).collect(),
92 }
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn test_empty_buffer() {
102 let buf = InputBuffer::new();
103 assert!(buf.is_empty());
104 assert_eq!(buf.len(), 0);
105 assert_eq!(buf.as_str(), "");
106 }
107
108 #[test]
109 fn test_push_pop() {
110 let mut buf = InputBuffer::new();
111 buf.push('g');
112 buf.push('G'); assert_eq!(buf.as_str(), "gg");
114 assert_eq!(buf.len(), 2);
115
116 assert_eq!(buf.pop(), Some('g'));
117 assert_eq!(buf.as_str(), "g");
118 }
119
120 #[test]
121 fn test_first_char() {
122 let mut buf = InputBuffer::new();
123 assert_eq!(buf.first_char(), None);
124
125 buf.push('f');
126 buf.push('f');
127 assert_eq!(buf.first_char(), Some('f'));
128 }
129
130 #[test]
131 fn test_from_str() {
132 let buf = InputBuffer::from("GGG");
133 assert_eq!(buf.as_str(), "ggg");
134 }
135
136 #[test]
137 fn test_display() {
138 let buf = InputBuffer::from("test");
139 assert_eq!(format!("{}", buf), "test");
140 }
141
142 #[test]
143 fn test_max_length_push() {
144 let mut buf = InputBuffer::new();
145 for _ in 0..MAX_INPUT_LENGTH {
147 assert!(buf.push('a'));
148 }
149 assert_eq!(buf.len(), MAX_INPUT_LENGTH);
150
151 assert!(!buf.push('b'));
153 assert_eq!(buf.len(), MAX_INPUT_LENGTH);
154 }
155
156 #[test]
157 fn test_max_length_from_str() {
158 let long_string = "a".repeat(MAX_INPUT_LENGTH * 2);
159 let buf = InputBuffer::from(long_string.as_str());
160 assert_eq!(buf.len(), MAX_INPUT_LENGTH);
161 }
162}