diff --git a/src/main.rs b/src/main.rs index 7a40d31..033e004 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ mod server; use crate::server::{Command, NoteContext}; use std::io; -use std::io::Read; +use std::io::{Read, Write}; use std::net::UdpSocket; use std::sync::mpsc::*; @@ -23,6 +23,7 @@ fn main() { let listener = UdpSocket::bind(LISTEN).unwrap(); let mut buffer = [0; 1024]; while let Ok((inbound, _outbound)) = listener.recv_from(&mut buffer) { + println!("input command"); let command= Command::from(&buffer[..inbound]); network_cw.send(command).unwrap(); } @@ -34,7 +35,8 @@ fn main() { fn handle_console_input(command_channel: Sender) { let mut key = String::new(); loop { - io::stdin().read_to_string(&mut key).unwrap(); + key.clear(); + io::stdin().read_line(&mut key).unwrap(); if key == "exit" { break; } @@ -42,6 +44,6 @@ fn handle_console_input(command_channel: Sender) { continue; } - command_channel.send(Command::Display(key.clone())).unwrap(); + command_channel.send(Command::Display(key.trim_end().to_string())).unwrap(); } } diff --git a/src/server/handling.rs b/src/server/handling.rs index 4019204..014ece4 100644 --- a/src/server/handling.rs +++ b/src/server/handling.rs @@ -1,9 +1,8 @@ use crate::server::StoredData::*; use crate::server::{Command, NoteContext, StoredData}; use litemap::LiteMap; -use std::io::Write; +use std::io::{stderr, Write, stdout}; use std::string::String; -use log::info; impl NoteContext { pub fn execute_command(&mut self, command: Command) { @@ -16,22 +15,41 @@ impl NoteContext { Command::Push(key, value) => self.push(key, value), Command::Display(key) => self.display(key), Command::SetOutput(generator) => self.output = generator(), + Command::Alias(id, alias) => self.set_alias(id, alias), } } - fn set(&mut self, key: String, value: StoredData) { + fn set(&mut self,mut key: String, value: StoredData) { if key.is_empty() { return; } + if let Some(alias) = self.aliases.get(&key) { + key = alias.to_string(); + } self.entries.insert(key, value); } + fn get_entry(&mut self, mut key: String) -> Option<&StoredData> { + if let Some(alias) = self.aliases.get(&key) { + key = alias.to_string(); + } + self.entries.get(&key) + } + + fn get_entry_mut(&mut self, mut key: String) -> Option<&mut StoredData> { + if let Some(alias) = self.aliases.get(&key) { + key = alias.to_string(); + } + self.entries.get_mut(&key) + } + fn push(&mut self, key: String, value: StoredData) { let mut vectorize: Option = None; - let current = self.entries.get_mut(&key); + let current = self.get_entry_mut(key.clone()); if let Some(current) = current { if let Vec(vec) = current { vec.push(value); + return; } else { vectorize = Some(Vec(vec![current.clone()])); } @@ -50,9 +68,27 @@ impl NoteContext { } fn display(&mut self, key: String) { + if key.starts_with("#"){ + let command = key.trim_start_matches("#").to_string(); + match command.as_str() { + "list" => { + self.entries.iter().for_each(|(k, v)| { + writeln!(&mut self.output, "{}", k).unwrap(); + }) + } + &_ => {} } + + return; + } if let Some(data) = self.entries.get(&key) { - writeln!(self.output, "{}", key).unwrap(); - _ = self.output.write_all(data.to_string().as_bytes()); + writeln!(self.output, "{} value", key).expect("write failed"); + writeln!(&mut self.output, "{}", data).expect("write failed"); + } else { + writeln!(&mut self.output, "Key not found").expect("TODO: panic message"); } } + + fn set_alias(&mut self, id: String, alias: String) { + self.aliases.insert(id, alias); + } } diff --git a/src/server/mod.rs b/src/server/mod.rs index 798bbdc..4a69f94 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -2,9 +2,9 @@ mod handling; mod testing; use litemap::LiteMap; +use minicbor::Decoder; use minicbor::data::Type; use minicbor::decode::Error; -use minicbor::Decoder; use std::collections::HashMap; use std::fmt::{Display, Formatter}; use std::io::Write; @@ -14,6 +14,7 @@ pub enum Command { Set(String, StoredData), Define(String, LiteMap), Push(String, StoredData), + Alias(String, String), Display(String), SetOutput(fn() -> Box), } @@ -37,8 +38,11 @@ impl Display for StoredData { StoredData::Bool(v) => v.fmt(f), StoredData::Line(v) => v.fmt(f), StoredData::Vec(vec) => { - vec.iter().for_each(|d| { - _ = write!(f, "{}\n", d); + vec.iter().enumerate().for_each(|(i, d)| { + write!(f, "{}", d).unwrap(); + if i != vec.len() - 1 { + write!(f, "\n").unwrap(); + } }); Ok(()) } @@ -90,10 +94,9 @@ fn parse_command(data: &[u8]) -> Result { return Ok(Command::Set(id, value)); } if data.starts_with(b"PUSH:") { - println!("{}", String::from_utf8_lossy(data)); let payload = &data[b"PUSH:".len()..]; let mut decoder = Decoder::new(&payload); - decoder.array()?; + _ = decoder.array()?; let id = decoder.str()?.to_string(); let value = decode_value(&mut decoder)?; return Ok(Command::Push(id, value)); @@ -105,6 +108,14 @@ fn parse_command(data: &[u8]) -> Result { let id = decoder.str()?.to_string(); return Ok(Command::Display(id)); } + if data.starts_with(b"ALIAS:") { + let payload = &data[b"ALIAS:".len()..]; + let mut decoder = Decoder::new(&payload); + decoder.array()?; + let id = decoder.str()?.to_string(); + let alias = decoder.str()?.to_string(); + return Ok(Command::Alias(id, alias)); + } Ok(Command::Unknown) } @@ -131,7 +142,7 @@ fn decode_value(decoder: &mut Decoder) -> Result { } else { vec![] }; - if array.is_empty() { + if array.capacity() == 0 { loop { let dt = decoder.datatype()?; if let Type::Break = dt { @@ -139,6 +150,10 @@ fn decode_value(decoder: &mut Decoder) -> Result { } array.push(decode_value(decoder)?); } + } else { + for _ in 0..array.capacity() { + array.push(decode_value(decoder)?); + } } StoredData::Line(Line::from(array)) } @@ -151,6 +166,7 @@ fn decode_value(decoder: &mut Decoder) -> Result { pub struct NoteContext { entries: HashMap, + aliases: HashMap, output: Box, } @@ -158,6 +174,7 @@ impl NoteContext { pub fn default() -> Self { Self { entries: Default::default(), + aliases: Default::default(), output: Box::new(std::io::stdout()), } }