Added more extensions for tuples and iterators. (TODO: Extract these into a library like `linebuffer`) Fortune for day14's current commit: Blessing − 吉master
parent
2eb60791bf
commit
bfccf7a426
@ -0,0 +1,207 @@
|
||||
//! Extensions
|
||||
use std::iter::{
|
||||
self,
|
||||
FusedIterator,
|
||||
};
|
||||
|
||||
/// An iterator adaptor for taking two items off an iterator
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TakeTwo<I: ?Sized>(I);
|
||||
|
||||
impl<I: ?Sized, T> Iterator for TakeTwo<I>
|
||||
where I: Iterator<Item=T>
|
||||
{
|
||||
type Item = (T, Option<T>);
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item>
|
||||
{
|
||||
let first = self.0.next()?;
|
||||
Some((first, self.0.next()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let (low, high) = self.0.size_hint();
|
||||
(low / 2, high.map(|x| x/2))
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: ?Sized + ExactSizeIterator> ExactSizeIterator for TakeTwo<I>{}
|
||||
impl<I: ?Sized + FusedIterator> FusedIterator for TakeTwo<I> {}
|
||||
|
||||
pub trait TakeTwoExt: Sized {
|
||||
/// Create an adaptor from `T` to `(T, Option<T>)`, taking the next available value if one exists in the iterator
|
||||
fn take_two(self) -> TakeTwo<Self>;
|
||||
}
|
||||
pub trait TakeTwoBoxedExt {
|
||||
/// Create an adaptor from `T` to `(T, Option<T>)`, taking the next available value if one exists in the iterator
|
||||
fn take_two(self: Box<Self>) -> TakeTwo<Box<Self>>;
|
||||
}
|
||||
|
||||
impl<I: Iterator> TakeTwoExt for I
|
||||
{
|
||||
#[inline(always)]
|
||||
fn take_two(self) -> TakeTwo<Self> {
|
||||
TakeTwo(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: ?Sized + Iterator> TakeTwoBoxedExt for I
|
||||
{
|
||||
#[inline(always)]
|
||||
fn take_two(self: Box<Self>) -> TakeTwo<Box<Self>> {
|
||||
TakeTwo(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Tuple2OptExt<T, U>: Sized
|
||||
{
|
||||
/// The unwrapped type for the option in the tuple
|
||||
type OptionType;
|
||||
/// Unwrap a tuple containing an option into an option containing the full tuple if the `Option` value in the tuple is `Some`
|
||||
fn unwrap_two(self) -> Option<(T, U)>;
|
||||
|
||||
/// Unwrap the option value or get the value from `f`
|
||||
fn unwrap_two_or_else<F>(self, f: F) -> (T, U)
|
||||
where F: FnOnce() -> Self::OptionType;
|
||||
}
|
||||
|
||||
impl<T, U> Tuple2OptExt<T, U> for (T, Option<U>)
|
||||
{
|
||||
type OptionType = U;
|
||||
|
||||
#[inline]
|
||||
fn unwrap_two(self) -> Option<(T, U)> {
|
||||
self.1.map(move |u| (self.0, u))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn unwrap_two_or_else<F>(self, f: F) -> (T, U)
|
||||
where F: FnOnce() -> Self::OptionType {
|
||||
match self.1 {
|
||||
Some(u) => (self.0, u),
|
||||
None => (self.0, f()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Tuple2OptExt<T, U> for (Option<T>, U)
|
||||
{
|
||||
type OptionType = T;
|
||||
#[inline]
|
||||
fn unwrap_two(self) -> Option<(T, U)> {
|
||||
self.0.map(move |u| (u, self.1))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn unwrap_two_or_else<F>(self, f: F) -> (T, U)
|
||||
where F: FnOnce() -> Self::OptionType {
|
||||
match self.0 {
|
||||
Some(u) => (u, self.1),
|
||||
None => (f(), self.1),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Tuple2OptExt<T, U> for (Option<T>, Option<U>)
|
||||
{
|
||||
type OptionType = (T, U);
|
||||
#[inline]
|
||||
fn unwrap_two(self) -> Option<(T, U)> {
|
||||
self.0.and_then(move |u| self.1.map(move |v| (u, v)))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn unwrap_two_or_else<F>(self, f: F) -> (T, U)
|
||||
where F: FnOnce() -> Self::OptionType {
|
||||
match self {
|
||||
//XXX: This is not ideal...
|
||||
(Some(u), Some(v)) => (u, v),
|
||||
(Some(u), None) => (u, f().1),
|
||||
(None, Some(v)) => (f().0, v),
|
||||
_ => f()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Tuple2Ext<T,U>: Sized
|
||||
{
|
||||
/// Swap the elements in a 2-tuple
|
||||
fn swap(self) -> (U, T);
|
||||
|
||||
/// Reduce the tuple elements into `V`
|
||||
fn reduce<V>(self, into: V) -> V
|
||||
where V: Extend<T> + Extend<U>;
|
||||
|
||||
/// Collect the tuple elements into `O`
|
||||
fn collect<V, O>(self) -> O
|
||||
where V: From<T> + From<U> + FromIterator<V>,
|
||||
O: FromIterator<V>;
|
||||
|
||||
/// Consume into `V`
|
||||
fn consume<V>(self) -> V
|
||||
where V: FromIterator<T> + Extend<U>;
|
||||
|
||||
/// Consume both elements into a new single type.
|
||||
fn into<V>(self) -> (V, V)
|
||||
where V: From<T> + From<U>;
|
||||
}
|
||||
|
||||
pub trait Tuple2STExt<T>: Sized
|
||||
{
|
||||
/// Consume into an array of two elements.
|
||||
fn into_array(self) -> [T; 2];
|
||||
|
||||
/// Consume into an iterator of both elements
|
||||
fn into_iter(self) -> <[T; 2] as IntoIterator>::IntoIter;
|
||||
}
|
||||
|
||||
impl<T, U> Tuple2Ext<T, U> for (T, U)
|
||||
{
|
||||
#[inline]
|
||||
fn swap(self) -> (U, T) {
|
||||
(self.1, self.0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn reduce<V>(self, mut into: V) -> V
|
||||
where V: Extend<T> + Extend<U> {
|
||||
into.extend(iter::once(self.0));
|
||||
into.extend(iter::once(self.1));
|
||||
into
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn collect<V, O>(self) -> O
|
||||
where V: From<T> + From<U>,
|
||||
O: FromIterator<V> {
|
||||
[self.0.into(), self.1.into()].into_iter().collect()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn consume<V>(self) -> V
|
||||
where V: FromIterator<T> + Extend<U> {
|
||||
let mut o: V = iter::once(self.0).collect();
|
||||
o.extend(iter::once(self.1));
|
||||
o
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into<V>(self) -> (V, V)
|
||||
where V: From<T> + From<U> {
|
||||
(self.0.into(), self.1.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Tuple2STExt<T> for (T, T)
|
||||
{
|
||||
#[inline]
|
||||
fn into_array(self) -> [T; 2] {
|
||||
[self.0, self.1]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_iter(self) -> <[T; 2] as IntoIterator>::IntoIter {
|
||||
self.into_array().into_iter()
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
//! Grid of lines and sands
|
||||
use super::*;
|
||||
|
Loading…
Reference in new issue