use super::*; use std::{ hash::Hash, collections::{HashSet, HashMap}, mem, fmt, }; pub trait DedupFullExt { fn dedup_full(&mut self); } impl DedupFullExt for Vec where T: Hash + Default + Eq { fn dedup_full(&mut self) { let mut set: HashMap = HashMap::new(); for (i,x) in (0..).zip(self.iter_mut()) { if !set.contains_key(x) { let us = mem::replace(x, Default::default()); set.insert(us, i); } } // To preserve order: let mut tmp = Vec::with_capacity(self.len()); for item in set.into_iter() { tmp.push(item); } tmp.sort_by(move |a, b| a.1.partial_cmp(&b.1).unwrap()); self.truncate(tmp.len()); for (d,s) in self.iter_mut().zip(tmp.into_iter()) { *d = s.0; } } } pub trait ErrorLogForgetExt: Sized { fn log_and_forget(self, mode: &log::Mode, level: log::Level) -> Option; } impl ErrorLogForgetExt for Result where E: fmt::Display, { fn log_and_forget(self, mode: &log::Mode, level: log::Level) -> Option { match self { Err(e) => { log!(mode.level(level), "{}", &e); if let log::Level::Fatal = level { std::process::exit(1); } None }, Ok(v) => Some(v), } } } pub trait ErrorLogExt: Sized { fn into_log(self, mode: &log::Mode, level: log::Level) -> Self; fn into_fatal(self, mode: Option) -> Self { self.into_log(&mode.unwrap_or(log::Mode::Verbose), log::Level::Fatal) } } impl ErrorLogExt for Result where E: fmt::Display { fn into_log(self, mode: &log::Mode, level: log::Level) -> Self { match self { Err(e) => { log!(mode.level(level), "{}", &e); if let log::Level::Fatal = level { std::process::exit(1); } Err(e) }, Ok(v) => Ok(v), } } } pub trait ErrorExt { fn into_string(self) -> Result; } impl ErrorExt for Result where E: fmt::Display { fn into_string(self) -> Result { match self { Ok(v) => Ok(v), Err(e) => Err(format!("{}", e)), } } } #[cfg(test)] mod test { use super::*; #[test] fn dedup_full() { let mut vec = vec![ "hello", "how", "are", "you", "hello", "hello", "today", "today", "you", "how", "hello", ]; vec.dedup_full(); assert_eq!(vec.len(), 5); assert_eq!(&vec[..], &["hello","how", "are", "you", "today"]); } }