From e7f821782251f89ae377800217d0a24a02fe96b2 Mon Sep 17 00:00:00 2001 From: PiyushXCoder Date: Tue, 16 Feb 2021 00:23:11 +0530 Subject: [PATCH] more changes --- .gitignore | 1 + Cargo.lock | 5 + Cargo.toml | 1 + api.txt | 13 +- src/chat_pinnd.rs | 88 ++++++++--- src/config.rs | 2 +- src/errors/mod.rs | 1 - src/main.rs | 1 - src/messages.rs | 49 ++++--- src/vyakti_list.rs | 98 ------------- src/ws_sansad.rs | 138 +++++++++++++++--- static/index.html | 14 +- vecmap/Cargo.lock | 5 + vecmap/Cargo.toml | 9 ++ .../src/errors.rs | 0 vecmap/src/lib.rs | 113 ++++++++++++++ 16 files changed, 374 insertions(+), 164 deletions(-) delete mode 100644 src/vyakti_list.rs create mode 100644 vecmap/Cargo.lock create mode 100644 vecmap/Cargo.toml rename src/errors/vayakti_list_error.rs => vecmap/src/errors.rs (100%) create mode 100644 vecmap/src/lib.rs diff --git a/.gitignore b/.gitignore index ea8c4bf..b6f2f37 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +/vecmap/target \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 15d9851..30ad0ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1067,6 +1067,7 @@ dependencies = [ "rand 0.8.3", "serde", "serde_json", + "vecmap", ] [[package]] @@ -1975,6 +1976,10 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +[[package]] +name = "vecmap" +version = "0.1.0" + [[package]] name = "version_check" version = "0.1.5" diff --git a/Cargo.toml b/Cargo.toml index 9e487fe..2dca4fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,3 +19,4 @@ serde = "1.0.123" serde_json = "1.0.62" rand = "0.8.3" futures = "0.3.12" +vecmap = { path = "vecmap" } \ No newline at end of file diff --git a/api.txt b/api.txt index ce648e8..aaccdd2 100644 --- a/api.txt +++ b/api.txt @@ -1,7 +1,9 @@ -Set name: +Set Info: { - cmd: "name", - name: name + cmd: "seinfo", + name: name, + kunjika: kunjika, + tags: tags } Join Grih: @@ -22,4 +24,9 @@ Send Message: text: message } +RandomUser: +{ + cmd: "rnd" +} + diff --git a/src/chat_pinnd.rs b/src/chat_pinnd.rs index 0b983e4..0955387 100644 --- a/src/chat_pinnd.rs +++ b/src/chat_pinnd.rs @@ -4,6 +4,7 @@ use std::collections::HashMap; use actix::prelude::*; use actix_broker::BrokerSubscribe; +use vecmap::VecMap; use ws_sansad::WsSansad; use crate::{errors, ws_sansad, messages as ms}; @@ -11,8 +12,8 @@ use crate::{errors, ws_sansad, messages as ms}; #[allow(dead_code)] pub struct ChatPinnd { grih: HashMap, // id, Grih - vyaktigat_waitlist: Vec>, - vyakti: Vec // id, tags + vyaktigat_waitlist: Vec, + vyakti: VecMap // id, vayakti } pub struct Grih { @@ -20,11 +21,17 @@ pub struct Grih { loog: Vec> } +#[derive(Clone)] pub struct Vyakti { - kunjika: String, + name: String, tags: Vec } +pub struct VyaktiWatchlist { + kunjika: String, + addr: Addr +} + impl Actor for ChatPinnd { type Context = Context; @@ -34,34 +41,44 @@ impl Actor for ChatPinnd { } } -impl Handler for ChatPinnd { - type Result = Result<(), errors::AlreadyExistError>; +impl Handler for ChatPinnd { + type Result = Option; - fn handle(&mut self, msg: ms::SetKunjikaUser, ctx: &mut Self::Context) -> Self::Result { - let kunjika = msg.kunjika; - let vyakti = self.vyakti.iter().find(|a| a.kunjika == kunjika); - Ok(()) + fn handle(&mut self, msg: ms::SetInfoVyakti, _: &mut Self::Context) -> Self::Result { + if !msg.modify { + if self.vyakti.key_exist(&msg.kunjika) { + return Some("Kunjika Exists".to_owned()); + } + } + + self.vyakti.insert(msg.kunjika, Vyakti { + name: msg.name, + tags: msg.tags + }); + + None } } -impl Handler for ChatPinnd { +impl Handler for ChatPinnd { type Result = Result<(), errors::GrihFullError>; - fn handle(&mut self, msg: ms::JoinUser, _: &mut Self::Context) -> Self::Result { + fn handle(&mut self, msg: ms::JoinGrih, _: &mut Self::Context) -> Self::Result { match self.grih.get_mut(&msg.grih_kunjika) { Some(grih) =>{ if let Some(n) = grih.length { - println!("length check {}, {}, {}", grih.loog.len(), n,grih.loog.len() >= n); if grih.loog.len() >= n { return Err(errors::GrihFullError); } } grih.loog.push(msg.addr); - let username = msg.name.clone(); + let username = self.vyakti.get(&msg.kunjika).unwrap().name.to_owned(); + let kunjika = msg.kunjika.clone(); grih.loog.iter().for_each(move |a: &Addr| { a.do_send(ms::WsConnected { - user: username.clone() + name: username.clone(), + kunjika: kunjika.clone() }) }); }, None => { @@ -70,7 +87,8 @@ impl Handler for ChatPinnd { loog: vec![msg.addr.clone()] }); msg.addr.do_send(ms::WsConnected { - user: msg.name + name: self.vyakti.get(&msg.kunjika).unwrap().name.to_owned(), + kunjika: msg.kunjika.clone() }); } } @@ -79,6 +97,40 @@ impl Handler for ChatPinnd { } } +impl Handler for ChatPinnd { + type Result = Option<()>; + fn handle(&mut self, msg: ms::JoinRandom, _: &mut Self::Context) -> Self::Result { + if self.vyaktigat_waitlist.len() == 0 { + self.vyaktigat_waitlist.push(VyaktiWatchlist { + kunjika: msg.kunjika, + addr: msg.addr + }); + return None; + } + + let vayakti_watchlist = self.vyaktigat_waitlist.remove(0); + let vayakti1 = self.vyakti.get(&msg.kunjika).unwrap(); + let vayakti2 = self.vyakti.get(&vayakti_watchlist.kunjika).unwrap(); + let group_kunjika = format!("gupt_{}>{}",msg.kunjika, vayakti_watchlist.kunjika); + self.grih.insert(group_kunjika.clone(), Grih { + length: Some(2), + loog: vec![msg.addr.clone(), vayakti_watchlist.addr.clone()] + }); + + msg.addr.do_send(ms::WsConnectedRandom { + ajnyat_name: vayakti2.name.clone(), + grih_kunjika: group_kunjika.clone() + }); + + vayakti_watchlist.addr.do_send(ms::WsConnectedRandom { + ajnyat_name: vayakti1.name.clone(), + grih_kunjika: group_kunjika.clone() + }); + + Some(()) + } +} + impl Handler for ChatPinnd { type Result = (); @@ -86,7 +138,7 @@ impl Handler for ChatPinnd { if let Some(grih) = self.grih.get(&msg.grih_kunjika) { grih.loog.iter().for_each(|c| { c.do_send(ms::WsMessage { - sender: msg.sender_name.clone(), + sender: msg.kunjika.clone(), text: msg.text.clone(), }); }); @@ -108,7 +160,7 @@ impl Handler for ChatPinnd { } else { grih.loog.iter().for_each(|a| { a.do_send(ms::WsDisconnected { - user: "u".to_owned() + kunjika: msg.kunjika.clone() }) }); } @@ -121,7 +173,7 @@ impl Default for ChatPinnd { ChatPinnd { grih: HashMap::new(), vyaktigat_waitlist: Vec::new(), - vyakti: Vec::new() + vyakti: VecMap::new() } } } diff --git a/src/config.rs b/src/config.rs index 1062e1d..d84e2e6 100644 --- a/src/config.rs +++ b/src/config.rs @@ -12,7 +12,7 @@ impl Config { .author(env!("CARGO_PKG_AUTHORS")) .about(env!("CARGO_PKG_DESCRIPTION")) .arg(Arg::with_name("static_path") - .short("b") + .short("s") .long("static_path") .value_name("DIR") .help("Path of directory with index.html") diff --git a/src/errors/mod.rs b/src/errors/mod.rs index 04a155e..f9ca0f0 100644 --- a/src/errors/mod.rs +++ b/src/errors/mod.rs @@ -1,6 +1,5 @@ mod grih_full_error; mod user_kunjika_error; -pub mod vayakti_list_error; pub use grih_full_error::GrihFullError; pub use user_kunjika_error::AlreadyExistError; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index ce8e14b..0d75f08 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,6 @@ mod errors; mod messages; mod ws_sansad; mod chat_pinnd; -mod vyakti_list; #[actix_web::main] async fn main() -> std::io::Result<()> { diff --git a/src/messages.rs b/src/messages.rs index 8a14135..06967a9 100644 --- a/src/messages.rs +++ b/src/messages.rs @@ -4,27 +4,38 @@ use actix::prelude::*; use crate::ws_sansad::WsSansad; use crate::errors; -// For ChatPinnd + +//################################################## For ChatPinnd ################################################## #[derive(Clone, Message)] -#[rtype(result = "Result<(), errors::AlreadyExistError>")] -pub struct SetKunjikaUser { - pub kunjika: String +#[rtype(result = "Option")] // None if no error +pub struct SetInfoVyakti { + pub kunjika: String, + pub name: String, + pub tags: Vec, + pub modify: bool } #[derive(Clone, Message)] #[rtype(result = "Result<(), errors::GrihFullError>")] -pub struct JoinUser { +pub struct JoinGrih { pub grih_kunjika: String, pub length: Option, pub addr: Addr, - pub name: String + pub kunjika: String +} + +#[derive(Clone, Message)] +#[rtype(result = "Option<()>")] +pub struct JoinRandom { + pub addr: Addr, + pub kunjika: String } #[derive(Clone, Message)] #[rtype(result = "()")] pub struct SendText { pub grih_kunjika: String, - pub sender_name: String, + pub kunjika: String, pub text: String } @@ -32,17 +43,11 @@ pub struct SendText { #[rtype(result = "()")] pub struct LeaveUser { pub grih_kunjika: String, + pub kunjika: String, pub addr: Addr } -#[derive(Clone, Message)] -#[rtype(result = "()")] -pub struct AddUserKunjika { - pub old_kunjika: Option, - pub kunjika: String -} - -// For WsSansad +//################################################## For WsSansad ################################################## #[derive(Clone, Message)] #[rtype(result = "()")] pub struct WsMessage { @@ -53,13 +58,14 @@ pub struct WsMessage { #[derive(Clone, Message)] #[rtype(result = "()")] pub struct WsConnected { - pub user: String + pub name: String, + pub kunjika: String } #[derive(Clone, Message)] #[rtype(result = "()")] pub struct WsDisconnected { - pub user: String + pub kunjika: String } #[derive(Clone, Message)] @@ -68,3 +74,12 @@ pub struct WsResponse { pub result: String, pub message: String } + + +#[derive(Clone, Message)] +#[rtype(result = "()")] +pub struct WsConnectedRandom { + pub ajnyat_name: String, + pub grih_kunjika: String +} + diff --git a/src/vyakti_list.rs b/src/vyakti_list.rs deleted file mode 100644 index a7c58a8..0000000 --- a/src/vyakti_list.rs +++ /dev/null @@ -1,98 +0,0 @@ -use std::error::Error; - -use crate::errors::vayakti_list_error as er; - -#[derive(Debug, Clone)] -pub struct VecMap(Vec>); - -#[derive(Debug, Clone)] -pub struct VecMapElement { - key: K, - value: V -} - -impl IntoIterator for VecMap { - type IntoIter = std::vec::IntoIter>; - type Item = VecMapElement; - - fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() - } -} - -impl VecMap { - pub fn new() -> VecMap { - VecMap(Vec::new()) - } - - pub fn insert(&mut self, key: K, value: V) { - let key_tmp = key.clone(); - match self.0.iter_mut().find(move |a| { - a.key == key_tmp - }) { - Some(i) => { - i.value = value.clone(); - } - None => { - self.0.push(VecMapElement { - key, - value - }); - } - } - } - - pub fn get(&self, key: K) -> Option<&V> { - match self.0.iter().find(|a| { - a.key == key - }) { - Some(v) => Some(&v.value), - None => None - } - } - - pub fn get_mut(&mut self, key: K) -> Option<&mut V> { - match self.0.iter_mut().find(move |a| { - a.key == key - }) { - Some(v) => Some(&mut v.value), - None => None - } - } - - pub fn remove(&mut self, key: K) -> Result<(), er::ElementNotFount> { - match self.0.iter().position(move |a| { - a.key == key - }) { - Some(i) => { - self.0.remove(i); - } - None => { - return Err(er::ElementNotFount); - } - } - Ok(()) - } - - pub fn change_key(&mut self, key: K, new_key: K) -> Result<(), &dyn Error> { - let key_tmp = key.clone(); - if let Some(_) = self.0.iter().position(move |a| { - a.key == key_tmp - }) { - return Err(&er::KeyAlreadyExist); - } - - - match self.0.iter_mut().find(move |a| { - a.key == key - }) { - Some(i) => { - i.key = new_key; - } - None => { - return Err(&er::ElementNotFount); - } - } - Ok(()) - } -} diff --git a/src/ws_sansad.rs b/src/ws_sansad.rs index b77837a..1adaa4a 100644 --- a/src/ws_sansad.rs +++ b/src/ws_sansad.rs @@ -8,17 +8,16 @@ use crate::{chat_pinnd::ChatPinnd, messages as ms}; use crate::errors; pub struct WsSansad { - name: String, kunjika: Option, isthiti: Isthiti, addr: Option>, } -#[allow(dead_code)] +#[derive(Debug)] enum Isthiti { None, Grih(String), - // VraktigatWaitlist + VraktigatWaitlist } impl Actor for WsSansad { @@ -55,7 +54,7 @@ impl Handler for WsSansad { let json = json!({ "cmd": "text", "text": msg.text, - "sender": msg.sender + "kunjika": msg.sender // Sender's kunjuka }); ctx.text(json.to_string()); } @@ -78,7 +77,8 @@ impl Handler for WsSansad { fn handle(&mut self, msg: ms::WsConnected, ctx: &mut Self::Context) -> Self::Result { let json = json!({ "cmd": "connected", - "user": msg.user + "name": msg.name, + "kunjika": msg.kunjika }); ctx.text(json.to_string()); } @@ -89,17 +89,30 @@ impl Handler for WsSansad { fn handle(&mut self, msg: ms::WsDisconnected, ctx: &mut Self::Context) -> Self::Result { let json = json!({ "cmd": "disconnected", - "user": msg.user + "name": msg.kunjika }); ctx.text(json.to_string()); } } +impl Handler for WsSansad { + type Result = (); + fn handle(&mut self, msg: ms::WsConnectedRandom, ctx: &mut Self::Context) -> Self::Result { + self.isthiti = Isthiti::Grih(msg.grih_kunjika); + let json = json!({ + "cmd": "connected", + "ajnyat": msg.ajnyat_name + }); + ctx.text(json.to_string()); + } +} + + + impl WsSansad { pub fn new() -> Self { WsSansad { - name: "()".to_owned(), kunjika: None, isthiti: Isthiti::None, addr: None, @@ -107,12 +120,11 @@ impl WsSansad { } async fn parse_text_handle(&mut self, msg: String) { - println!("{}", msg); if let Ok(val) = serde_json::from_str::(&msg) { match val.get("cmd").unwrap().as_str().unwrap() { - "name" => { self.set_name(val).await }, - "kunjika" => { self.set_kunjika(val).await }, + "seinfo" => { self.set_info(val).await }, "join" => { self.join_grih(val).await }, + "rand" => { self.join_random().await }, "text" => { self.send_text(val).await }, "leave" => { self.leave_grih().await }, _ => () @@ -134,14 +146,79 @@ impl WsSansad { }); } - async fn set_name(&mut self, val: Value) { - self.name = val.get("name").unwrap().as_str().unwrap().to_owned(); + async fn set_info(&mut self, val: Value) { + let kunjika = match val.get("kunjika") { + Some(val ) => val.as_str().unwrap().to_owned(), + None => { + self.send_err_response("Invalid request"); + return; + } + }; + let name = match val.get("name") { + Some(val ) => val.as_str().unwrap().to_owned(), + None => { + self.send_err_response("Invalid request"); + return; + } + }; + let tags = match val.get("tags") { + Some(val ) => { + let mut v = Vec::new(); + for x in val.as_str().unwrap().split_ascii_whitespace() { + v.push(x.to_owned()); + } + v + }, + None => { + self.send_err_response("Invalid request"); + return; + } + }; + + let modify = self.kunjika == Some(kunjika.clone()); + + let result: Option = ChatPinnd::from_registry().send(ms::SetInfoVyakti { + kunjika: kunjika.clone(), + name, + tags, + modify + }).await.unwrap(); + + if let Some(msg) = result { + self.send_err_response(&msg); + return; + } + + self.kunjika = Some(kunjika); self.send_ok_response(); } - async fn set_kunjika(&mut self, val: Value) { - self.name = val.get("name").unwrap().as_str().unwrap().to_owned(); - self.send_ok_response(); + async fn join_random(&mut self) { + if let None = self.kunjika { + self.send_err_response("No user kunjika set"); + return; + } + + if let Isthiti::VraktigatWaitlist = self.isthiti { + self.addr.clone().unwrap().do_send(ms::WsResponse { + result: "Ok".to_owned(), + message: "watchlist".to_owned() + }); + return; + } + + let result: Option<()> = ChatPinnd::from_registry().send(ms::JoinRandom{ + addr: self.addr.clone().unwrap(), + kunjika: self.kunjika.clone().unwrap() + }).await.unwrap(); + + if let None = result { + self.addr.clone().unwrap().do_send(ms::WsResponse { + result: "Ok".to_owned(), + message: "watchlist".to_owned() + }); + self.isthiti = Isthiti::VraktigatWaitlist; + } } async fn join_grih(&mut self, val: Value) { @@ -150,28 +227,34 @@ impl WsSansad { return; } - let kunjika = match val.get("kunjika") { + let grih_kunjika = match val.get("kunjika") { Some(val) => val, None => { self.send_err_response("Invalid request"); return; } }.as_str().unwrap().to_owned(); + + if grih_kunjika.starts_with("gupt_") { + self.send_err_response("Such grih kunjika is restricted"); + return; + } + let length: Option = match val.get("length") { Some(val) => Some(val.as_i64().unwrap() as usize), None => None }; - let result: Result<(), errors::GrihFullError> = ChatPinnd::from_registry().send(ms::JoinUser { - grih_kunjika: kunjika.clone(), + let result: Result<(), errors::GrihFullError> = ChatPinnd::from_registry().send(ms::JoinGrih { + grih_kunjika: grih_kunjika.clone(), length, addr: self.addr.clone().unwrap(), - name: self.name.clone() + kunjika: self.kunjika.clone().unwrap() }).await.unwrap(); match result { Ok(_) => { - self.isthiti = Isthiti::Grih(kunjika); + self.isthiti = Isthiti::Grih(grih_kunjika); self.send_ok_response() }, Err(e) => self.send_err_response(&format!("{}", e)) @@ -179,6 +262,16 @@ impl WsSansad { } async fn send_text(&mut self, val: Value) { + if let None = self.kunjika { + self.send_err_response("No user kunjika set"); + return; + } + + if let Isthiti::None = self.isthiti { + self.send_err_response("Grih not connected"); + return; + } + let text = match val.get("text") { Some(val) => val, None => { @@ -189,13 +282,13 @@ impl WsSansad { let grih_kunjika = match &self.isthiti { Isthiti::Grih(g) => { g.clone() - }, Isthiti::None => { + }, _ => { return; } }; Broker::::issue_async(ms::SendText { grih_kunjika, - sender_name: self.name.clone(), + kunjika: self.kunjika.clone().unwrap(), text }); } @@ -204,6 +297,7 @@ impl WsSansad { if let Isthiti::Grih(val) = &mut self.isthiti { Broker::::issue_async(ms::LeaveUser { grih_kunjika: val.clone(), + kunjika: self.kunjika.clone().unwrap(), addr: self.addr.clone().unwrap() }); diff --git a/static/index.html b/static/index.html index 24effc2..aa1baec 100644 --- a/static/index.html +++ b/static/index.html @@ -46,10 +46,18 @@ function send(t) { })); } -function name(t) { +function info(k, n, t) { socket.send(JSON.stringify({ - cmd: "name", - name: t + cmd: "seinfo", + kunjika: k, + name: n, + tags: t + })); +} + +function joinrand() { + socket.send(JSON.stringify({ + cmd: "rand" })); } diff --git a/vecmap/Cargo.lock b/vecmap/Cargo.lock new file mode 100644 index 0000000..ebcd948 --- /dev/null +++ b/vecmap/Cargo.lock @@ -0,0 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "hashmap_mod" +version = "0.1.0" diff --git a/vecmap/Cargo.toml b/vecmap/Cargo.toml new file mode 100644 index 0000000..00af475 --- /dev/null +++ b/vecmap/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "vecmap" +version = "0.1.0" +authors = ["piyush"] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/errors/vayakti_list_error.rs b/vecmap/src/errors.rs similarity index 100% rename from src/errors/vayakti_list_error.rs rename to vecmap/src/errors.rs diff --git a/vecmap/src/lib.rs b/vecmap/src/lib.rs new file mode 100644 index 0000000..ec74516 --- /dev/null +++ b/vecmap/src/lib.rs @@ -0,0 +1,113 @@ +use std::error::Error; + +pub mod errors; + +#[derive(Debug, Clone)] +pub struct VecMap(Vec>); + +#[derive(Debug, Clone)] +pub struct VecMapElement { + key: K, + value: V +} + +impl IntoIterator for VecMap { + type IntoIter = std::vec::IntoIter>; + type Item = VecMapElement; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +impl VecMap { + pub fn new() -> VecMap { + VecMap(Vec::new()) + } + + pub fn insert(&mut self, key: K, value: V) { + let key_tmp = key.clone(); + match self.0.iter_mut().find(move |a| a.key == key_tmp) { + Some(i) => { + i.value = value.clone(); + } + None => { + self.0.push(VecMapElement { + key, + value + }); + } + } + } + + pub fn get(&self, key: &K) -> Option<&V> { + match self.0.iter().find(|a| &a.key == key) { + Some(v) => Some(&v.value), + None => None + } + } + + pub fn get_mut(&mut self, key: &K) -> Option<&mut V> { + match self.0.iter_mut().find(move |a| &a.key == key) { + Some(v) => Some(&mut v.value), + None => None + } + } + + pub fn remove(&mut self, key: &K) -> Result<(), errors::ElementNotFount> { + match self.0.iter().position(move |a| &a.key == key) { + Some(i) => { + self.0.remove(i); + } + None => { + return Err(errors::ElementNotFount); + } + } + Ok(()) + } + + pub fn change_key(&mut self, key: &K, new_key: &K) -> Result<(), &dyn Error> { + let key_tmp = key.clone(); + if let Some(_) = self.0.iter().position(move |a| a.key == key_tmp) { + return Err(&errors::KeyAlreadyExist); + } + + + match self.0.iter_mut().find(move |a| &a.key == key) { + Some(i) => { + i.key = new_key.to_owned(); + } + None => { + return Err(&errors::ElementNotFount); + } + } + Ok(()) + } + + pub fn key_exist(&self, key: &K) -> bool { + match self.0.iter().position(move |a| &a.key == key) { + Some(_) => true, + None => false + } + } +} + +#[cfg(test)] +mod tests { + + use crate::VecMap; + + #[test] + fn it_works() { + let mut a: VecMap = super::VecMap::new(); + + a.insert(1, 5); + a.insert(2, 10); + a.change_key(1, 2).unwrap(); + a.insert(2, 15); + + a.into_iter().enumerate().for_each(|(i,e)| { + println!("{}\t-> {:?}", i,e); + }); + } +}