You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

136 lines
2.4 KiB

use super::*;
use std::{
hash::Hash,
collections::HashMap,
mem,
fmt,
};
pub trait DedupFullExt
{
fn dedup_full(&mut self);
}
impl<T> DedupFullExt for Vec<T>
where T: Hash + Default + Eq
{
fn dedup_full(&mut self)
{
let mut set: HashMap<T, usize> = 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<T, E>: Sized
{
fn log_and_forget(self, mode: &log::Mode, level: log::Level) -> Result<Option<T>, E>;
}
impl<T,E> ErrorLogForgetExt<T,E> for Result<T,E>
where E: fmt::Display,
{
fn log_and_forget(self, mode: &log::Mode, level: log::Level) -> Result<Option<T>, E>
{
Ok(match self {
Err(e) => {
log!(mode.level(level), "{}", &e);
if let log::Level::Fatal = level {
std::process::exit(1);
} else if log::Level::Error == level {
return Err(e);
}
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<log::Mode>) -> Self
{
self.into_log(&mode.unwrap_or(log::Mode::Verbose), log::Level::Fatal)
}
}
impl<T,E> ErrorLogExt for Result<T,E>
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<T>
{
fn into_string(self) -> Result<T, String>;
}
impl<T,E> ErrorExt<T> for Result<T,E>
where E: fmt::Display
{
fn into_string(self) -> Result<T, String>
{
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"]);
}
}