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.

180 lines
3.9 KiB

//! Extensions
use super::*;
use std::{
borrow::{
Borrow, ToOwned,
},
iter,
};
pub trait Tuple2MapExt<T>
{
fn map<F, U>(self, fun: F) -> (U, U)
where F: FnMut(T) -> U;
}
impl<T> Tuple2MapExt<T> for (T,T)
{
fn map<F, U>(self, mut fun: F) -> (U, U)
where F: FnMut(T) -> U
{
(fun(self.0), fun(self.1))
}
}
pub trait JitterExt<T>
{
/// Produce a random value between `self.0` and `self.1` inclusive
fn jitter(self) -> T;
}
impl<T> JitterExt<T> for (T, T)
where T: rand::distributions::uniform::SampleUniform
{
fn jitter(self) -> T
{
util::jitter(self.0, self.1)
}
}
pub trait Unreference<T>
{
fn cloned(self) -> Option<T>;
}
impl<'a, T> Unreference<T> for Option<&'a T>
where T: Clone
{
fn cloned(self) -> Option<T> {
self.map(Clone::clone)
}
}
/// An iterator over `char` that maps certain characters to others
pub struct CharSubstituteIter<'map, I, T= char>
where I: Iterator<Item = T>,
{
iter: I,
map: &'map smallmap::Map<char, char>,
}
impl<'a, I, T> Iterator for CharSubstituteIter<'a, I, T>
where I: Iterator<Item = T>,
T: From<char> + smallmap::Collapse,
char: Borrow<T>
{
type Item = T;
fn next(&mut self) -> Option<Self::Item>
{
self.iter.next()
.map(|item| self.map.get(&item)
.cloned()
.map(T::from)
.unwrap_or(item))
}
#[inline] fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a, I, T> DoubleEndedIterator for CharSubstituteIter<'a, I, T>
where I: Iterator<Item = T> + DoubleEndedIterator,
T: From<char> + smallmap::Collapse,
char: Borrow<T>
{
fn next_back(&mut self) -> Option<Self::Item>
{
self.iter.next_back()
.map(|item| self.map.get(&item)
.cloned()
.map(T::from)
.unwrap_or(item))
}
}
impl<'a, I, T> iter::FusedIterator for CharSubstituteIter<'a, I, T>
where I: Iterator<Item = T> + iter::FusedIterator,
T: From<char> + smallmap::Collapse,
char: Borrow<T>{}
impl<'a, I, T> iter::ExactSizeIterator for CharSubstituteIter<'a, I, T>
where I: Iterator<Item = T> + ExactSizeIterator,
T: From<char> + smallmap::Collapse,
char: Borrow<T>{}
pub trait CharMapExt<T>: Sized + IntoIterator<Item=T>
{
/// Creates an iterator that maps chars over this one
fn replace_chars(self, map: &smallmap::Map<char, char>) -> CharSubstituteIter<'_, Self::IntoIter, T>;
}
impl<S, T> CharMapExt<T> for S
where S: IntoIterator<Item=T>,
T: From<char> + smallmap::Collapse,
char: Borrow<T>
{
#[inline] fn replace_chars(self, map: &smallmap::Map<char, char>) -> CharSubstituteIter<'_, Self::IntoIter, T> {
CharSubstituteIter {
iter: self.into_iter(),
map,
}
}
}
/// The ID type used for backing ID types;
pub type GenericID = uuid::Uuid;
/// Create a type that contains a (globally) unique ID.
#[macro_export] macro_rules! id_type {
($name:ident $(: $doc:literal)?) => ($crate::id_type!{pub(self) $name $(: $doc)?});
($vis:vis $name:ident $(: $doc:literal)?) => {
$(#[doc=$doc])?
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
$vis struct $name($crate::ext::GenericID);
impl $name
{
/// Create a new unique ID.
#[inline(always)] fn id_new() -> Self
{
Self($crate::ext::GenericID::new_v4())
}
/// The generic ID type backing this one
#[inline(always)] fn id_generic(&self) -> &$crate::ext::GenericID
{
&self.0
}
/// Consume into the generic ID
#[inline(always)] fn id_into_generic(self) -> $crate::ext::GenericID
{
self.0
}
/// Create from a generic ID
#[inline(always)] fn id_from_generic(gen: $crate::ext::GenericID) -> Self
{
Self(gen)
}
}
impl ::std::fmt::Display for $name
{
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result
{
use ::std::fmt::Write;
f.write_str(concat!(stringify!($name),"<"))?;
self.0.fmt(f)?;
f.write_str(">")
}
}
}
}