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