diff options
Diffstat (limited to '')
| -rw-r--r-- | src/bin/client/repl.rs | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/src/bin/client/repl.rs b/src/bin/client/repl.rs new file mode 100644 index 0000000..d38c54d --- /dev/null +++ b/src/bin/client/repl.rs | |||
| @@ -0,0 +1,108 @@ | |||
| 1 | use std::io::{BufRead, BufReader, Write, stdin, stdout}; | ||
| 2 | use std::net::TcpStream; | ||
| 3 | use rusqlite::Connection; | ||
| 4 | |||
| 5 | use crate::connection; | ||
| 6 | use crate::database; | ||
| 7 | |||
| 8 | pub struct ClientState { | ||
| 9 | pub stream: Option<TcpStream>, | ||
| 10 | pub conn: Connection, | ||
| 11 | pub addr: Option<String>, | ||
| 12 | pub default_port: u16, | ||
| 13 | } | ||
| 14 | |||
| 15 | impl ClientState { | ||
| 16 | pub fn new() -> Self { | ||
| 17 | let conn = database::init_db(); | ||
| 18 | let default_ip = "127.0.0.1".to_string(); | ||
| 19 | let default_port = 11525; | ||
| 20 | let last_host = database::get_last_host(&conn); | ||
| 21 | let default_host = format!("{}:{}", default_ip, default_port); | ||
| 22 | let addr = last_host.or(Some(default_host)); | ||
| 23 | |||
| 24 | Self { | ||
| 25 | stream: None, | ||
| 26 | conn, | ||
| 27 | addr, | ||
| 28 | default_port, | ||
| 29 | } | ||
| 30 | } | ||
| 31 | |||
| 32 | pub fn connect_to(&mut self, addr: &str) { | ||
| 33 | self.addr = Some(addr.to_string()); | ||
| 34 | match connection::connect(addr) { | ||
| 35 | Ok(s) => { | ||
| 36 | self.stream = Some(s); | ||
| 37 | database::save_host(&self.conn, addr); | ||
| 38 | } | ||
| 39 | Err(e) => println!("Failed to connect: {}", e), | ||
| 40 | } | ||
| 41 | } | ||
| 42 | |||
| 43 | pub fn run(&mut self) { | ||
| 44 | loop { | ||
| 45 | print!("> "); | ||
| 46 | stdout().flush().unwrap(); | ||
| 47 | let mut line = String::new(); | ||
| 48 | stdin().read_line(&mut line).unwrap(); | ||
| 49 | let line = line.trim(); | ||
| 50 | if line.is_empty() { | ||
| 51 | continue; | ||
| 52 | } | ||
| 53 | let parts: Vec<&str> = line.splitn(2, ' ').collect(); | ||
| 54 | match parts[0] { | ||
| 55 | "connect" => { | ||
| 56 | let addr_str = if parts.len() < 2 { | ||
| 57 | if let Some(h) = &self.addr { | ||
| 58 | h.clone() | ||
| 59 | } else { | ||
| 60 | println!("No host specified and no previous connection. Usage: connect <ip>:<port>"); | ||
| 61 | continue; | ||
| 62 | } | ||
| 63 | } else { | ||
| 64 | let mut a = parts[1].to_string(); | ||
| 65 | if !a.contains(':') { | ||
| 66 | a = format!("{}:{}", a, self.default_port); | ||
| 67 | } | ||
| 68 | a | ||
| 69 | }; | ||
| 70 | self.connect_to(&addr_str); | ||
| 71 | } | ||
| 72 | "send" => { | ||
| 73 | if self.stream.is_none() { | ||
| 74 | println!("Not connected. Use 'connect <ip>:<port>' first."); | ||
| 75 | continue; | ||
| 76 | } | ||
| 77 | if parts.len() < 2 { | ||
| 78 | println!("Usage: send <message>"); | ||
| 79 | continue; | ||
| 80 | } | ||
| 81 | let msg = parts[1]; | ||
| 82 | let s = self.stream.as_mut().unwrap(); | ||
| 83 | let writer_stream = s.try_clone().unwrap(); | ||
| 84 | let mut writer = writer_stream; | ||
| 85 | let response_reader_stream = s.try_clone().unwrap(); | ||
| 86 | let mut response_reader = BufReader::new(response_reader_stream); | ||
| 87 | writeln!(writer, "{}", msg).unwrap(); | ||
| 88 | let mut response = String::new(); | ||
| 89 | response_reader.read_line(&mut response).unwrap(); | ||
| 90 | println!("Echo: {}", response.trim()); | ||
| 91 | } | ||
| 92 | "disconnect" => { | ||
| 93 | self.stream = None; | ||
| 94 | println!("Disconnected"); | ||
| 95 | } | ||
| 96 | "help" => { | ||
| 97 | help(); | ||
| 98 | } | ||
| 99 | "quit" => break, | ||
| 100 | _ => help(), | ||
| 101 | } | ||
| 102 | } | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | fn help() { | ||
| 107 | println!("Available commands: connect <ip>:<port>, send <message>, disconnect, help, quit"); | ||
| 108 | } | ||
