<commit_before>use crate::intrinsics;
use crate::iter::adapters::{zip::try_get_unchecked, InPlaceIterable, SourceIter};
use crate::iter::{
    DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedLen, TrustedRandomAccess,
};
use crate::ops::Try;

/// An iterator that yields `None` forever after the underlying iterator
/// yields `None` once.
///
/// This `struct` is created by [`Iterator::fuse`]. See its documentation
/// for more.
#[derive(Clone, Debug)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Fuse<I> {
    // NOTE: for `I: FusedIterator`, this is always assumed `Some`!
    iter: Option<I>,
}
impl<I> Fuse<I> {
    pub(in crate::iter) fn new(iter: I) -> Fuse<I> {
        Fuse { iter: Some(iter) }
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<I> FusedIterator for Fuse<I> where I: Iterator {}

/// Fuse the iterator if the expression is `None`.
macro_rules! fuse {
    ($self:ident . iter . $($call:tt)+) => {
        match $self.iter {
            Some(ref mut iter) => match iter.$($call)+ {
                None => {
                    $self.iter = None;
                    None
                }
                item => item,
            },
            None => None,
        }
    };
}

// NOTE: for `I: FusedIterator`, we assume that the iterator is always `Some`.
// Implementing this as a directly-expanded macro helps codegen performance.
macro_rules! unchecked {
    ($self:ident) => {
        match $self {
            Fuse { iter: Some(iter) } => iter,
            // SAFETY: the specialized iterator never sets `None`
            Fuse { iter: None } => unsafe { intrinsics::unreachable() },
        }
    };
}

// Any implementation here is made internal to avoid exposing default fns outside this trait
#[stable(feature = "rust1", since = "1.0.0")]
impl<I> Iterator for Fuse<I>
where
    I: Iterator,
{
    type Item = <I as Iterator>::Item;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        FuseImpl::next(self)
    }

    #[inline]
    fn nth(&mut self, n: usize) -> Option<I::Item> {
        FuseImpl::nth(self, n)
    }

    #[inline]
    fn last(self) -> Option<Self::Item> {
        FuseImpl::last(self)
    }

    #[inline]
    fn count(self) -> usize {
        FuseImpl::count(self)
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        FuseImpl::size_hint(self)
    }

    #[inline]
    fn try_fold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Output = Acc>,
    {
        FuseImpl::try_fold(self, acc, fold)
    }

    #[inline]
    fn fold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        FuseImpl::fold(self, acc, fold)
    }

    #[inline]
    fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        FuseImpl::find(self, predicate)
    }

    #[inline]
    #[doc(hidden)]
    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
    where
        Self: TrustedRandomAccess,
    {
        match self.iter {
            // SAFETY: the caller must uphold the contract for
            // `Iterator::__iterator_get_unchecked`.
            Some(ref mut iter) => unsafe { try_get_unchecked(iter, idx) },
            // SAFETY: the caller asserts there is an item at `i`, so we're not exhausted.
            None => unsafe { intrinsics::unreachable() },
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I> DoubleEndedIterator for Fuse<I>
where
    I: DoubleEndedIterator,
{
    #[inline]
    fn next_back(&mut self) -> Option<<I as Iterator>::Item> {
        FuseImpl::next_back(self)
    }

    #[inline]
    fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> {
        FuseImpl::nth_back(self, n)
    }

    #[inline]
    fn try_rfold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Output = Acc>,
    {
        FuseImpl::try_rfold(self, acc, fold)
    }

    #[inline]
    fn rfold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        FuseImpl::rfold(self, acc, fold)
    }

    #[inline]
    fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        FuseImpl::rfind(self, predicate)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I> ExactSizeIterator for Fuse<I>
where
    I: ExactSizeIterator,
{
    fn len(&self) -> usize {
        FuseImpl::len(self)
    }

    fn is_empty(&self) -> bool {
        FuseImpl::is_empty(self)
    }
}

#[unstable(feature = "trusted_len", issue = "37572")]
// SAFETY: `TrustedLen` requires that an accurate length is reported via `size_hint()`. As `Fuse`
// is just forwarding this to the wrapped iterator `I` this property is preserved and it is safe to
// implement `TrustedLen` here.
unsafe impl<I> TrustedLen for Fuse<I> where I: TrustedLen {}

#[doc(hidden)]
#[unstable(feature = "trusted_random_access", issue = "none")]
// SAFETY: `TrustedRandomAccess` requires that `size_hint()` must be exact and cheap to call, and
// `Iterator::__iterator_get_unchecked()` must be implemented accordingly.
//
// This is safe to implement as `Fuse` is just forwarding these to the wrapped iterator `I`, which
// preserves these properties.
unsafe impl<I> TrustedRandomAccess for Fuse<I>
where
    I: TrustedRandomAccess,
{
    const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT;
}

// Fuse specialization trait
#[doc(hidden)]
trait FuseImpl<I> {
    type Item;

    // Functions specific to any normal Iterators
    fn next(&mut self) -> Option<Self::Item>;
    fn nth(&mut self, n: usize) -> Option<Self::Item>;
    fn last(self) -> Option<Self::Item>;
    fn count(self) -> usize;
    fn size_hint(&self) -> (usize, Option<usize>);
    fn try_fold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Output = Acc>;
    fn fold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc;
    fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool;

    // Functions specific to DoubleEndedIterators
    fn next_back(&mut self) -> Option<Self::Item>
    where
        I: DoubleEndedIterator;
    fn nth_back(&mut self, n: usize) -> Option<Self::Item>
    where
        I: DoubleEndedIterator;
    fn try_rfold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Output = Acc>,
        I: DoubleEndedIterator;
    fn rfold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
        I: DoubleEndedIterator;
    fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
        I: DoubleEndedIterator;

    // Functions specific to ExactSizeIterator
    fn len(&self) -> usize
    where
        I: ExactSizeIterator;
    fn is_empty(&self) -> bool
    where
        I: ExactSizeIterator;
}

// General Fuse impl
#[doc(hidden)]
impl<I> FuseImpl<I> for Fuse<I>
where
    I: Iterator,
{
    type Item = <I as Iterator>::Item;

    #[inline]
    default fn next(&mut self) -> Option<<I as Iterator>::Item> {
        fuse!(self.iter.next())
    }

    #[inline]
    default fn nth(&mut self, n: usize) -> Option<I::Item> {
        fuse!(self.iter.nth(n))
    }

    #[inline]
    default fn last(self) -> Option<I::Item> {
        match self.iter {
            Some(iter) => iter.last(),
            None => None,
        }
    }

    #[inline]
    default fn count(self) -> usize {
        match self.iter {
            Some(iter) => iter.count(),
            None => 0,
        }
    }

    #[inline]
    default fn size_hint(&self) -> (usize, Option<usize>) {
        match self.iter {
            Some(ref iter) => iter.size_hint(),
            None => (0, Some(0)),
        }
    }

    #[inline]
    default fn try_fold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Output = Acc>,
    {
        if let Some(ref mut iter) = self.iter {
            acc = iter.try_fold(acc, fold)?;
            self.iter = None;
        }
        try { acc }
    }

    #[inline]
    default fn fold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        if let Some(iter) = self.iter {
            acc = iter.fold(acc, fold);
        }
        acc
    }

    #[inline]
    default fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        fuse!(self.iter.find(predicate))
    }

    #[inline]
    default fn next_back(&mut self) -> Option<<I as Iterator>::Item>
    where
        I: DoubleEndedIterator,
    {
        fuse!(self.iter.next_back())
    }

    #[inline]
    default fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item>
    where
        I: DoubleEndedIterator,
    {
        fuse!(self.iter.nth_back(n))
    }

    #[inline]
    default fn try_rfold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Output = Acc>,
        I: DoubleEndedIterator,
    {
        if let Some(ref mut iter) = self.iter {
            acc = iter.try_rfold(acc, fold)?;
            self.iter = None;
        }
        try { acc }
    }

    #[inline]
    default fn rfold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
        I: DoubleEndedIterator,
    {
        if let Some(iter) = self.iter {
            acc = iter.rfold(acc, fold);
        }
        acc
    }

    #[inline]
    default fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
        I: DoubleEndedIterator,
    {
        fuse!(self.iter.rfind(predicate))
    }

    #[inline]
    default fn len(&self) -> usize
    where
        I: ExactSizeIterator,
    {
        match self.iter {
            Some(ref iter) => iter.len(),
            None => 0,
        }
    }

    #[inline]
    default fn is_empty(&self) -> bool
    where
        I: ExactSizeIterator,
    {
        match self.iter {
            Some(ref iter) => iter.is_empty(),
            None => true,
        }
    }
}

#[doc(hidden)]
impl<I> FuseImpl<I> for Fuse<I>
where
    I: FusedIterator,
{
    #[inline]
    fn next(&mut self) -> Option<<I as Iterator>::Item> {
        unchecked!(self).next()
    }

    #[inline]
    fn nth(&mut self, n: usize) -> Option<I::Item> {
        unchecked!(self).nth(n)
    }

    #[inline]
    fn last(self) -> Option<I::Item> {
        unchecked!(self).last()
    }

    #[inline]
    fn count(self) -> usize {
        unchecked!(self).count()
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        unchecked!(self).size_hint()
    }

    #[inline]
    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Output = Acc>,
    {
        unchecked!(self).try_fold(init, fold)
    }

    #[inline]
    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        unchecked!(self).fold(init, fold)
    }

    #[inline]
    fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        unchecked!(self).find(predicate)
    }

    #[inline]
    fn next_back(&mut self) -> Option<<I as Iterator>::Item>
    where
        I: DoubleEndedIterator,
    {
        unchecked!(self).next_back()
    }

    #[inline]
    fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item>
    where
        I: DoubleEndedIterator,
    {
        unchecked!(self).nth_back(n)
    }

    #[inline]
    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Output = Acc>,
        I: DoubleEndedIterator,
    {
        unchecked!(self).try_rfold(init, fold)
    }

    #[inline]
    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
        I: DoubleEndedIterator,
    {
        unchecked!(self).rfold(init, fold)
    }

    #[inline]
    fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
        I: DoubleEndedIterator,
    {
        unchecked!(self).rfind(predicate)
    }

    #[inline]
    fn len(&self) -> usize
    where
        I: ExactSizeIterator,
    {
        unchecked!(self).len()
    }

    #[inline]
    fn is_empty(&self) -> bool
    where
        I: ExactSizeIterator,
    {
        unchecked!(self).is_empty()
    }
}

#[unstable(issue = "none", feature = "inplace_iteration")]
unsafe impl<S: Iterator, I: FusedIterator> SourceIter for Fuse<I>
where
    I: SourceIter<Source = S>,
{
    type Source = S;

    #[inline]
    unsafe fn as_inner(&mut self) -> &mut S {
        match self.iter {
            // SAFETY: unsafe function forwarding to unsafe function with the same requirements
            Some(ref mut iter) => unsafe { SourceIter::as_inner(iter) },
            // SAFETY: the specialized iterator never sets `None`
            None => unsafe { intrinsics::unreachable() },
        }
    }
}

#[unstable(issue = "none", feature = "inplace_iteration")]
unsafe impl<I: InPlaceIterable> InPlaceIterable for Fuse<I> {}
<commit_msg>Make the specialized Fuse still deal with None<commit_after>use crate::intrinsics;
use crate::iter::adapters::zip::try_get_unchecked;
use crate::iter::{
    DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedLen, TrustedRandomAccess,
};
use crate::ops::Try;

/// An iterator that yields `None` forever after the underlying iterator
/// yields `None` once.
///
/// This `struct` is created by [`Iterator::fuse`]. See its documentation
/// for more.
#[derive(Clone, Debug)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Fuse<I> {
    // NOTE: for `I: FusedIterator`, we never bother setting `None`, but
    // we still have to be prepared for that state due to variance.
    // See rust-lang/rust#85863
    iter: Option<I>,
}
impl<I> Fuse<I> {
    pub(in crate::iter) fn new(iter: I) -> Fuse<I> {
        Fuse { iter: Some(iter) }
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<I> FusedIterator for Fuse<I> where I: Iterator {}

/// Fuse the iterator if the expression is `None`.
macro_rules! fuse {
    ($self:ident . iter . $($call:tt)+) => {
        match $self.iter {
            Some(ref mut iter) => match iter.$($call)+ {
                None => {
                    $self.iter = None;
                    None
                }
                item => item,
            },
            None => None,
        }
    };
}

/// Specialized macro that doesn't check if the expression is `None`.
/// (We trust that a `FusedIterator` will fuse itself.)
macro_rules! spec {
    ($self:ident . iter . $($call:tt)+) => {
        match $self.iter {
            Some(ref mut iter) => iter.$($call)+,
            None => None,
        }
    };
}

// Any specialized implementation here is made internal
// to avoid exposing default fns outside this trait.
#[stable(feature = "rust1", since = "1.0.0")]
impl<I> Iterator for Fuse<I>
where
    I: Iterator,
{
    type Item = <I as Iterator>::Item;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        FuseImpl::next(self)
    }

    #[inline]
    fn nth(&mut self, n: usize) -> Option<I::Item> {
        FuseImpl::nth(self, n)
    }

    #[inline]
    fn last(self) -> Option<Self::Item> {
        match self.iter {
            Some(iter) => iter.last(),
            None => None,
        }
    }

    #[inline]
    fn count(self) -> usize {
        match self.iter {
            Some(iter) => iter.count(),
            None => 0,
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        match self.iter {
            Some(ref iter) => iter.size_hint(),
            None => (0, Some(0)),
        }
    }

    #[inline]
    fn try_fold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Output = Acc>,
    {
        FuseImpl::try_fold(self, acc, fold)
    }

    #[inline]
    fn fold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        if let Some(iter) = self.iter {
            acc = iter.fold(acc, fold);
        }
        acc
    }

    #[inline]
    fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        FuseImpl::find(self, predicate)
    }

    #[inline]
    #[doc(hidden)]
    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
    where
        Self: TrustedRandomAccess,
    {
        match self.iter {
            // SAFETY: the caller must uphold the contract for
            // `Iterator::__iterator_get_unchecked`.
            Some(ref mut iter) => unsafe { try_get_unchecked(iter, idx) },
            // SAFETY: the caller asserts there is an item at `i`, so we're not exhausted.
            None => unsafe { intrinsics::unreachable() },
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I> DoubleEndedIterator for Fuse<I>
where
    I: DoubleEndedIterator,
{
    #[inline]
    fn next_back(&mut self) -> Option<<I as Iterator>::Item> {
        FuseImpl::next_back(self)
    }

    #[inline]
    fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> {
        FuseImpl::nth_back(self, n)
    }

    #[inline]
    fn try_rfold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Output = Acc>,
    {
        FuseImpl::try_rfold(self, acc, fold)
    }

    #[inline]
    fn rfold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        if let Some(iter) = self.iter {
            acc = iter.rfold(acc, fold);
        }
        acc
    }

    #[inline]
    fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        FuseImpl::rfind(self, predicate)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I> ExactSizeIterator for Fuse<I>
where
    I: ExactSizeIterator,
{
    fn len(&self) -> usize {
        match self.iter {
            Some(ref iter) => iter.len(),
            None => 0,
        }
    }

    fn is_empty(&self) -> bool {
        match self.iter {
            Some(ref iter) => iter.is_empty(),
            None => true,
        }
    }
}

#[unstable(feature = "trusted_len", issue = "37572")]
// SAFETY: `TrustedLen` requires that an accurate length is reported via `size_hint()`. As `Fuse`
// is just forwarding this to the wrapped iterator `I` this property is preserved and it is safe to
// implement `TrustedLen` here.
unsafe impl<I> TrustedLen for Fuse<I> where I: TrustedLen {}

#[doc(hidden)]
#[unstable(feature = "trusted_random_access", issue = "none")]
// SAFETY: `TrustedRandomAccess` requires that `size_hint()` must be exact and cheap to call, and
// `Iterator::__iterator_get_unchecked()` must be implemented accordingly.
//
// This is safe to implement as `Fuse` is just forwarding these to the wrapped iterator `I`, which
// preserves these properties.
unsafe impl<I> TrustedRandomAccess for Fuse<I>
where
    I: TrustedRandomAccess,
{
    const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT;
}

/// Fuse specialization trait
///
/// We only need to worry about `&mut self` methods, which
/// may exhaust the iterator without consuming it.
#[doc(hidden)]
trait FuseImpl<I> {
    type Item;

    // Functions specific to any normal Iterators
    fn next(&mut self) -> Option<Self::Item>;
    fn nth(&mut self, n: usize) -> Option<Self::Item>;
    fn try_fold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Output = Acc>;
    fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool;

    // Functions specific to DoubleEndedIterators
    fn next_back(&mut self) -> Option<Self::Item>
    where
        I: DoubleEndedIterator;
    fn nth_back(&mut self, n: usize) -> Option<Self::Item>
    where
        I: DoubleEndedIterator;
    fn try_rfold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Output = Acc>,
        I: DoubleEndedIterator;
    fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
        I: DoubleEndedIterator;
}

/// General `Fuse` impl which sets `iter = None` when exhausted.
#[doc(hidden)]
impl<I> FuseImpl<I> for Fuse<I>
where
    I: Iterator,
{
    type Item = <I as Iterator>::Item;

    #[inline]
    default fn next(&mut self) -> Option<<I as Iterator>::Item> {
        fuse!(self.iter.next())
    }

    #[inline]
    default fn nth(&mut self, n: usize) -> Option<I::Item> {
        fuse!(self.iter.nth(n))
    }

    #[inline]
    default fn try_fold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Output = Acc>,
    {
        if let Some(ref mut iter) = self.iter {
            acc = iter.try_fold(acc, fold)?;
            self.iter = None;
        }
        try { acc }
    }

    #[inline]
    default fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        fuse!(self.iter.find(predicate))
    }

    #[inline]
    default fn next_back(&mut self) -> Option<<I as Iterator>::Item>
    where
        I: DoubleEndedIterator,
    {
        fuse!(self.iter.next_back())
    }

    #[inline]
    default fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item>
    where
        I: DoubleEndedIterator,
    {
        fuse!(self.iter.nth_back(n))
    }

    #[inline]
    default fn try_rfold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Output = Acc>,
        I: DoubleEndedIterator,
    {
        if let Some(ref mut iter) = self.iter {
            acc = iter.try_rfold(acc, fold)?;
            self.iter = None;
        }
        try { acc }
    }

    #[inline]
    default fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
        I: DoubleEndedIterator,
    {
        fuse!(self.iter.rfind(predicate))
    }
}

/// Specialized `Fuse` impl which doesn't bother clearing `iter` when exhausted.
/// However, we must still be prepared for the possibility that it was already cleared!
#[doc(hidden)]
impl<I> FuseImpl<I> for Fuse<I>
where
    I: FusedIterator,
{
    #[inline]
    fn next(&mut self) -> Option<<I as Iterator>::Item> {
        spec!(self.iter.next())
    }

    #[inline]
    fn nth(&mut self, n: usize) -> Option<I::Item> {
        spec!(self.iter.nth(n))
    }

    #[inline]
    fn try_fold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Output = Acc>,
    {
        if let Some(ref mut iter) = self.iter {
            acc = iter.try_fold(acc, fold)?;
        }
        try { acc }
    }

    #[inline]
    fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        spec!(self.iter.find(predicate))
    }

    #[inline]
    fn next_back(&mut self) -> Option<<I as Iterator>::Item>
    where
        I: DoubleEndedIterator,
    {
        spec!(self.iter.next_back())
    }

    #[inline]
    fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item>
    where
        I: DoubleEndedIterator,
    {
        spec!(self.iter.nth_back(n))
    }

    #[inline]
    fn try_rfold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Output = Acc>,
        I: DoubleEndedIterator,
    {
        if let Some(ref mut iter) = self.iter {
            acc = iter.try_rfold(acc, fold)?;
        }
        try { acc }
    }

    #[inline]
    fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
        I: DoubleEndedIterator,
    {
        spec!(self.iter.rfind(predicate))
    }
}
<|endoftext|>


<commit_before>use super::*;
use super::super::packets::{self, Packet};
use std::net;

#[derive(Debug, Copy, Clone)]
pub enum ConnectionState {
    Initialized,
    Establishing,
    Established,
    Closed,
}

#[derive(Debug)]
pub struct Connection {
    pub state: ConnectionState,
    pub local_id: u64,
    pub remote_id: u64,
    pub address: net::SocketAddr,
}

impl Connection {
    pub fn new(address: net::SocketAddr, local_id: u64)->Connection {
        Connection::with_remote_id(address, local_id, 0)
    }

    pub fn with_remote_id(address: net::SocketAddr, local_id: u64, remote_id: u64)->Connection {
        Connection::with_remote_id_and_state(address, local_id, remote_id, ConnectionState::Initialized)
    }

    fn with_remote_id_and_state(address: net::SocketAddr, local_id: u64, remote_id: u64, state: ConnectionState)->Connection {
        Connection {
            state: state,
            local_id: local_id,
            remote_id: remote_id,
            address: address,
        }
    }

    pub fn handle_incoming_packet<T: PacketSender>(&mut self, packet: &packets::Packet, sender: &mut T)->bool {
        match *packet {
            Packet::Echo(id) => {
                sender.send(packet, self.address);
                true
            },
            Packet::Heartbeat{counter: c, sent: s, received: r} => {
                true
            },
            _ => false
        }
    }

    pub fn heartbeat<T: PacketSender>(&mut self, sender: &mut T) {
    }
}
<commit_msg>Internal machinery to count sent and received packets.<commit_after>use super::*;
use super::super::packets::{self, Packet};
use std::net;

#[derive(Debug, Copy, Clone)]
pub enum ConnectionState {
    Initialized,
    Establishing,
    Established,
    Closed,
}

#[derive(Debug)]
pub struct Connection {
    pub state: ConnectionState,
    pub local_id: u64,
    pub remote_id: u64,
    pub address: net::SocketAddr,
    pub received_packets: u64,
    pub sent_packets: u64,
}

impl Connection {
    pub fn new(address: net::SocketAddr, local_id: u64)->Connection {
        Connection::with_remote_id(address, local_id, 0)
    }

    pub fn with_remote_id(address: net::SocketAddr, local_id: u64, remote_id: u64)->Connection {
        Connection::with_remote_id_and_state(address, local_id, remote_id, ConnectionState::Initialized)
    }

    fn with_remote_id_and_state(address: net::SocketAddr, local_id: u64, remote_id: u64, state: ConnectionState)->Connection {
        Connection {
            state: state,
            local_id: local_id,
            remote_id: remote_id,
            address: address,
            sent_packets: 0,
            received_packets: 0,
        }
    }

    pub fn send<T: PacketSender>(&mut self, packet: &packets::Packet, sender: &mut T)->bool {
        self.sent_packets += 1;
        sender.send(packet, self.address)
    }

    pub fn handle_incoming_packet<T: PacketSender>(&mut self, packet: &packets::Packet, sender: &mut T)->bool {
        self.received_packets += 1; //Always.
        match *packet {
            Packet::Echo(id) => {
                self.send(packet, sender);
                true
            },
            Packet::Heartbeat{counter: c, sent: s, received: r} => {
                true
            },
            _ => false
        }
    }

    pub fn heartbeat<T: PacketSender>(&mut self, sender: &mut T) {
    }
}
<|endoftext|>


<commit_before>use Prefab;
use calx::{Dijkstra, hex_neighbors};
use euclid::{vec2, Size2D};
use form::{self, Form};
use location::{Location, Portal, Sector};
use mapgen::{self, DigCavesGen};
use rand::{self, Rand, Rng, SeedableRng};
use serde;
use std::collections::BTreeSet;
use std::collections::HashMap;
use std::slice;
use terrain::Terrain;
use world::Loadout;

/// Static generated world.
pub struct Worldgen {
    seed: u32,
    terrain: HashMap<Location, Terrain>,
    portals: HashMap<Location, Portal>,
    spawns: Vec<(Location, Loadout)>,
    player_entry: Location,
}

impl Worldgen {
    pub fn new(seed: u32) -> Worldgen {
        let mut ret = Worldgen {
            seed: seed,
            terrain: HashMap::new(),
            portals: HashMap::new(),
            spawns: Vec::new(),
            player_entry: Location::new(0, 0, 0),
        };

        let mut rng: ::Rng = SeedableRng::from_seed([seed, seed, seed, seed]);

        let mut cave_entrance = Location::new(9, 0, 0);
        ret.cave_entrance(cave_entrance);
        ret.terrain.insert(
            cave_entrance + vec2(1, 1),
            Terrain::Gate,
        );

        for depth in 1..11 {
            let up_stairs;
            let down_stairs;
            let mut spawns = Vec::new();

            {
                let mut digger = SectorDigger::new(&mut ret, Sector::new(0, 0, depth as i16));
                let gen = DigCavesGen::new(digger.domain());
                gen.dig(&mut rng, &mut digger);

                up_stairs = digger.up_portal.expect("Mapgen didn't create stairs up");
                down_stairs = digger.down_portal.expect(
                    "Mapgen didn't create stairs down",
                );

                // Spawn
                digger.clear_spawns_near_entrance(12);

                let mut spawn_locs = rand::sample(&mut rng, digger.spawn_region.iter(), 20);
                let n_spawns = spawn_locs.len();

                let items = Form::filter(|f| f.is_item() && f.at_depth(depth));
                for &loc in spawn_locs.drain(0..n_spawns / 2) {
                    spawns.push((
                        loc,
                        form::rand(&mut rng, &items)
                            .expect("No item spawn")
                            .loadout
                            .clone(),
                    ))
                }

                let mobs = Form::filter(|f| f.is_mob() && f.at_depth(depth));
                for &loc in spawn_locs {
                    spawns.push((
                        loc,
                        form::rand(&mut rng, &mobs)
                            .expect("No mob spawn")
                            .loadout
                            .clone(),
                    ))
                }
            }

            ret.spawns.extend(spawns.into_iter());
            ret.portal(cave_entrance, up_stairs + vec2(1, 1));
            ret.portal(up_stairs, cave_entrance - vec2(1, 1));
            cave_entrance = down_stairs;

            // TODO: Generator needs an option to not generate stairs down on bottom level
        }

        ret
    }

    fn load_prefab(&mut self, origin: Location, prefab: &Prefab) {
        for (p, &(ref terrain, ref entities)) in prefab.iter() {
            let loc = origin + p;

            self.terrain.insert(loc, *terrain);

            for spawn in entities.iter() {
                if spawn == "player" {
                    self.player_entry = loc;
                } else {
                    let form = Form::named(spawn).expect(&format!(
                        "Bad prefab: Form '{}' not found!",
                        spawn
                    ));
                    self.spawns.push((loc, form.loadout.clone()));
                }
            }
        }
    }

    pub fn seed(&self) -> u32 { self.seed }

    pub fn get_terrain(&self, loc: Location) -> Terrain {
        if let Some(&t) = self.terrain.get(&loc) {
            t
        } else {
            self.default_terrain(loc)
        }
    }

    fn default_terrain(&self, loc: Location) -> Terrain {
        use Terrain::*;
        if loc.z == 0 {
            match loc.noise() {
                n if n > 0.8 => Tree,
                n if n > -0.8 => Grass,
                _ => Water,
            }
        } else {
            Terrain::Rock
        }
    }

    pub fn get_portal(&self, loc: Location) -> Option<Location> {
        self.portals.get(&loc).map(|&p| loc + p)
    }

    pub fn spawns(&self) -> slice::Iter<(Location, Loadout)> { self.spawns.iter() }

    pub fn player_entry(&self) -> Location { self.player_entry }

    /// Make a cave entrance going down.
    fn cave_entrance(&mut self, loc: Location) {
        const DOWNBOUND_ENCLOSURE: [(i32, i32); 5] = [(1, 0), (0, 1), (2, 1), (1, 2), (2, 2)];

        for &v in &DOWNBOUND_ENCLOSURE {
            let loc = loc + vec2(v.0, v.1);
            self.terrain.insert(loc, Terrain::Rock);
        }

        self.terrain.insert(loc, Terrain::Ground);
        self.terrain.insert(loc + vec2(1, 1), Terrain::Ground);
    }

    /// Punch a (one-way) portal between two points.
    fn portal(&mut self, origin: Location, destination: Location) {
        self.portals.insert(
            origin,
            Portal::new(origin, destination),
        );
    }
}

impl serde::Serialize for Worldgen {
    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        self.seed.serialize(s)
    }
}

impl<'a> serde::Deserialize<'a> for Worldgen {
    fn deserialize<D: serde::Deserializer<'a>>(d: D) -> Result<Self, D::Error> {
        Ok(Worldgen::new(serde::Deserialize::deserialize(d)?))
    }
}

struct SectorDigger<'a> {
    worldgen: &'a mut Worldgen,
    sector: Sector,
    up_portal: Option<Location>,
    down_portal: Option<Location>,
    spawn_region: BTreeSet<Location>,
}

impl<'a> SectorDigger<'a> {
    fn new(worldgen: &'a mut Worldgen, sector: Sector) -> SectorDigger<'a> {
        SectorDigger {
            worldgen,
            sector,
            up_portal: None,
            down_portal: None,
            spawn_region: BTreeSet::new(),
        }
    }

    // TODO return impl
    fn domain(&self) -> Vec<mapgen::Point2D> {
        fn is_next_to_diagonal_sector(loc: Location) -> bool {
            hex_neighbors(loc)
                .map(|x| x.sector().taxicab_distance(loc.sector()))
                .any(|d| d > 1)
        }

        let mut ret = Vec::new();

        let sector_origin = self.sector.origin();
        let mapgen_origin = mapgen::Point2D::zero();

        for loc in self.sector.iter() {
            let pos = mapgen_origin +
                sector_origin.v2_at(loc).expect(
                    "Sector points are not Euclidean",
                );

            // Okay, this part is a bit hairy, hang on.
            // Sectors are arranged in a rectangular grid, so there are some cells where you can
            // step diagonally across two sector boundaries. However, we want to pretend that
            // sectors are only connected in the four cardinal directions, so we omit these cells
            // from the domain to prevent surprise holes between two diagonally adjacent shafts.
            if is_next_to_diagonal_sector(loc) {
                continue;
            }

            ret.push(pos);
        }

        ret
    }

    fn loc(&self, pos: mapgen::Point2D) -> Location { self.sector.origin() + pos.to_vector() }

    fn set(&mut self, loc: Location, terrain: Terrain) {
        if terrain != Terrain::Gate {
            debug_assert_ne!(self.up_portal, Some(loc), "mapgen overwriting exit");
            debug_assert_ne!(self.down_portal, Some(loc), "mapgen overwriting exit");
        }
        self.worldgen.terrain.insert(loc, terrain);
    }

    fn clear_spawns_near_entrance(&mut self, range: u32) {
        for loc in Dijkstra::new(
            vec![self.up_portal.expect("No entrance generated")],
            |loc| {
                self.worldgen
                    .terrain
                    .get(loc)
                    .cloned()
                    .unwrap_or(Terrain::Empty)
                    .is_open()
            },
            10_000,
        ).weights
            .iter()
            .filter_map(|(loc, &w)| if w <= range { Some(loc) } else { None })
        {
            self.spawn_region.remove(loc);
        }
    }
}

impl<'a> mapgen::Dungeon for SectorDigger<'a> {
    type Prefab = Room;

    /// Return a random prefab room.
    fn sample_prefab<R: Rng>(&mut self, rng: &mut R) -> Self::Prefab { rng.gen() }

    /// Add a large open continuous region to dungeon.
    fn dig_chamber<I: IntoIterator<Item = mapgen::Point2D>>(&mut self, area: I) {
        for pos in area {
            let loc = self.loc(pos);
            self.spawn_region.insert(loc);
            self.set(loc, Terrain::Ground);
        }
    }

    /// Add a narrow corridor to dungeon.
    fn dig_corridor<I: IntoIterator<Item = mapgen::Point2D>>(&mut self, path: I) {
        for pos in path {
            let loc = self.loc(pos);
            // Do not spawn things in corridors.
            self.spawn_region.remove(&loc);
            self.set(loc, Terrain::Ground);
        }
    }

    fn add_prefab(&mut self, prefab: &Self::Prefab, pos: mapgen::Point2D) {
        // TODO
        unimplemented!();
    }

    fn add_door(&mut self, pos: mapgen::Point2D) {
        let loc = self.loc(pos);
        self.spawn_region.remove(&loc);
        self.set(loc, Terrain::Door);
    }

    fn add_up_stairs(&mut self, pos: mapgen::Point2D) {
        let loc = self.loc(pos);
        self.up_portal = Some(loc);
        self.spawn_region.remove(&loc);
        // TODO: Add debug assertion that up-stairs are dug in the upper wall of a room
        self.set(loc, Terrain::Gate);
    }

    fn add_down_stairs(&mut self, pos: mapgen::Point2D) {
        let loc = self.loc(pos);
        self.down_portal = Some(loc);
        self.spawn_region.remove(&loc);
        self.set(loc, Terrain::Gate);

        // Visual hack to make the down-stairs show up better, carve out the rock blob that would
        // be drawn partially in front of it on screen.
        self.set(loc + vec2(1, 1), Terrain::Empty);
        // TODO: Add a debug assertion here to check that the exit location has proper enclosure to
        // begin with, both it and the rock cell in front of it need to be surrounded by undug
        // front tiles.
        self.spawn_region.remove(&(loc + vec2(1, 1))); // Just in case
    }
}

struct Room {
    size: Size2D<i32>,
}

impl mapgen::Prefab for Room {
    fn contains(&self, pos: mapgen::Point2D) -> bool {
        pos.x >= 0 && pos.y >= 0 && pos.x < self.size.width && pos.y < self.size.height
    }

    fn can_make_door(&self, pos: mapgen::Point2D) -> bool {
        let on_x_wall = pos.x == 0 || pos.x == self.size.width - 1;
        let on_y_wall = pos.y == 0 || pos.y == self.size.height - 1;

        // Must touch one wall, but touching both makes it a corner and we don't want rooms there.
        on_x_wall ^ on_y_wall
    }

    fn size(&self) -> mapgen::Size2D { self.size }
}

impl Rand for Room {
    fn rand<R: Rng>(rng: &mut R) -> Self {
        Room { size: Size2D::new(rng.gen_range(3, 10), rng.gen_range(3, 10)) }
    }
}
<commit_msg>Add check for mapgen running out of bounds<commit_after>use Prefab;
use calx::{Dijkstra, hex_neighbors};
use euclid::{vec2, Size2D};
use form::{self, Form};
use location::{Location, Portal, Sector};
use mapgen::{self, DigCavesGen};
use rand::{self, Rand, Rng, SeedableRng};
use serde;
use std::collections::BTreeSet;
use std::collections::HashMap;
use std::slice;
use terrain::Terrain;
use world::Loadout;

/// Static generated world.
pub struct Worldgen {
    seed: u32,
    terrain: HashMap<Location, Terrain>,
    portals: HashMap<Location, Portal>,
    spawns: Vec<(Location, Loadout)>,
    player_entry: Location,
}

impl Worldgen {
    pub fn new(seed: u32) -> Worldgen {
        let mut ret = Worldgen {
            seed: seed,
            terrain: HashMap::new(),
            portals: HashMap::new(),
            spawns: Vec::new(),
            player_entry: Location::new(0, 0, 0),
        };

        let mut rng: ::Rng = SeedableRng::from_seed([seed, seed, seed, seed]);

        let mut cave_entrance = Location::new(9, 0, 0);
        ret.cave_entrance(cave_entrance);
        ret.terrain.insert(
            cave_entrance + vec2(1, 1),
            Terrain::Gate,
        );

        for depth in 1..11 {
            let up_stairs;
            let down_stairs;
            let mut spawns = Vec::new();

            {
                let mut digger = SectorDigger::new(&mut ret, Sector::new(0, 0, depth as i16));
                let gen = DigCavesGen::new(digger.domain());
                gen.dig(&mut rng, &mut digger);

                up_stairs = digger.up_portal.expect("Mapgen didn't create stairs up");
                down_stairs = digger.down_portal.expect(
                    "Mapgen didn't create stairs down",
                );

                // Spawn
                digger.clear_spawns_near_entrance(12);

                let mut spawn_locs = rand::sample(&mut rng, digger.spawn_region.iter(), 20);
                let n_spawns = spawn_locs.len();

                let items = Form::filter(|f| f.is_item() && f.at_depth(depth));
                for &loc in spawn_locs.drain(0..n_spawns / 2) {
                    spawns.push((
                        loc,
                        form::rand(&mut rng, &items)
                            .expect("No item spawn")
                            .loadout
                            .clone(),
                    ))
                }

                let mobs = Form::filter(|f| f.is_mob() && f.at_depth(depth));
                for &loc in spawn_locs {
                    spawns.push((
                        loc,
                        form::rand(&mut rng, &mobs)
                            .expect("No mob spawn")
                            .loadout
                            .clone(),
                    ))
                }
            }

            ret.spawns.extend(spawns.into_iter());
            ret.portal(cave_entrance, up_stairs + vec2(1, 1));
            ret.portal(up_stairs, cave_entrance - vec2(1, 1));
            cave_entrance = down_stairs;

            // TODO: Generator needs an option to not generate stairs down on bottom level
        }

        ret
    }

    fn load_prefab(&mut self, origin: Location, prefab: &Prefab) {
        for (p, &(ref terrain, ref entities)) in prefab.iter() {
            let loc = origin + p;

            self.terrain.insert(loc, *terrain);

            for spawn in entities.iter() {
                if spawn == "player" {
                    self.player_entry = loc;
                } else {
                    let form = Form::named(spawn).expect(&format!(
                        "Bad prefab: Form '{}' not found!",
                        spawn
                    ));
                    self.spawns.push((loc, form.loadout.clone()));
                }
            }
        }
    }

    pub fn seed(&self) -> u32 { self.seed }

    pub fn get_terrain(&self, loc: Location) -> Terrain {
        if let Some(&t) = self.terrain.get(&loc) {
            t
        } else {
            self.default_terrain(loc)
        }
    }

    fn default_terrain(&self, loc: Location) -> Terrain {
        use Terrain::*;
        if loc.z == 0 {
            match loc.noise() {
                n if n > 0.8 => Tree,
                n if n > -0.8 => Grass,
                _ => Water,
            }
        } else {
            Terrain::Rock
        }
    }

    pub fn get_portal(&self, loc: Location) -> Option<Location> {
        self.portals.get(&loc).map(|&p| loc + p)
    }

    pub fn spawns(&self) -> slice::Iter<(Location, Loadout)> { self.spawns.iter() }

    pub fn player_entry(&self) -> Location { self.player_entry }

    /// Make a cave entrance going down.
    fn cave_entrance(&mut self, loc: Location) {
        const DOWNBOUND_ENCLOSURE: [(i32, i32); 5] = [(1, 0), (0, 1), (2, 1), (1, 2), (2, 2)];

        for &v in &DOWNBOUND_ENCLOSURE {
            let loc = loc + vec2(v.0, v.1);
            self.terrain.insert(loc, Terrain::Rock);
        }

        self.terrain.insert(loc, Terrain::Ground);
        self.terrain.insert(loc + vec2(1, 1), Terrain::Ground);
    }

    /// Punch a (one-way) portal between two points.
    fn portal(&mut self, origin: Location, destination: Location) {
        self.portals.insert(
            origin,
            Portal::new(origin, destination),
        );
    }
}

impl serde::Serialize for Worldgen {
    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        self.seed.serialize(s)
    }
}

impl<'a> serde::Deserialize<'a> for Worldgen {
    fn deserialize<D: serde::Deserializer<'a>>(d: D) -> Result<Self, D::Error> {
        Ok(Worldgen::new(serde::Deserialize::deserialize(d)?))
    }
}

struct SectorDigger<'a> {
    worldgen: &'a mut Worldgen,
    sector: Sector,
    up_portal: Option<Location>,
    down_portal: Option<Location>,
    spawn_region: BTreeSet<Location>,
}

impl<'a> SectorDigger<'a> {
    fn new(worldgen: &'a mut Worldgen, sector: Sector) -> SectorDigger<'a> {
        SectorDigger {
            worldgen,
            sector,
            up_portal: None,
            down_portal: None,
            spawn_region: BTreeSet::new(),
        }
    }

    // TODO return impl
    fn domain(&self) -> Vec<mapgen::Point2D> {
        let mut ret = Vec::new();

        let sector_origin = self.sector.origin();
        let mapgen_origin = mapgen::Point2D::zero();

        for loc in self.sector.iter() {
            let pos = mapgen_origin +
                sector_origin.v2_at(loc).expect(
                    "Sector points are not Euclidean",
                );

            // Okay, this part is a bit hairy, hang on.
            // Sectors are arranged in a rectangular grid, so there are some cells where you can
            // step diagonally across two sector boundaries. However, we want to pretend that
            // sectors are only connected in the four cardinal directions, so we omit these cells
            // from the domain to prevent surprise holes between two diagonally adjacent shafts.
            if Self::is_next_to_diagonal_sector(loc) {
                continue;
            }

            ret.push(pos);
        }

        ret
    }

    fn loc(&self, pos: mapgen::Point2D) -> Location { self.sector.origin() + pos.to_vector() }

    fn set(&mut self, loc: Location, terrain: Terrain) {
        if terrain != Terrain::Gate {
            debug_assert_ne!(self.up_portal, Some(loc), "mapgen overwriting exit");
            debug_assert_ne!(self.down_portal, Some(loc), "mapgen overwriting exit");
        }

        debug_assert!(
            !Self::is_next_to_diagonal_sector(loc) &&
            self.sector.iter().find(|x| x == &loc).is_some(),
            "Setting a location outsides sector area");

        self.worldgen.terrain.insert(loc, terrain);
    }

    fn clear_spawns_near_entrance(&mut self, range: u32) {
        for loc in Dijkstra::new(
            vec![self.up_portal.expect("No entrance generated")],
            |loc| {
                self.worldgen
                    .terrain
                    .get(loc)
                    .cloned()
                    .unwrap_or(Terrain::Empty)
                    .is_open()
            },
            10_000,
        ).weights
            .iter()
            .filter_map(|(loc, &w)| if w <= range { Some(loc) } else { None })
        {
            self.spawn_region.remove(loc);
        }
    }

    fn is_next_to_diagonal_sector(loc: Location) -> bool {
        hex_neighbors(loc)
            .map(|x| x.sector().taxicab_distance(loc.sector()))
            .any(|d| d > 1)
    }

}

impl<'a> mapgen::Dungeon for SectorDigger<'a> {
    type Prefab = Room;

    /// Return a random prefab room.
    fn sample_prefab<R: Rng>(&mut self, rng: &mut R) -> Self::Prefab { rng.gen() }

    /// Add a large open continuous region to dungeon.
    fn dig_chamber<I: IntoIterator<Item = mapgen::Point2D>>(&mut self, area: I) {
        for pos in area {
            let loc = self.loc(pos);
            self.spawn_region.insert(loc);
            self.set(loc, Terrain::Ground);
        }
    }

    /// Add a narrow corridor to dungeon.
    fn dig_corridor<I: IntoIterator<Item = mapgen::Point2D>>(&mut self, path: I) {
        for pos in path {
            let loc = self.loc(pos);
            // Do not spawn things in corridors.
            self.spawn_region.remove(&loc);
            self.set(loc, Terrain::Ground);
        }
    }

    fn add_prefab(&mut self, prefab: &Self::Prefab, pos: mapgen::Point2D) {
        // TODO
        unimplemented!();
    }

    fn add_door(&mut self, pos: mapgen::Point2D) {
        let loc = self.loc(pos);
        self.spawn_region.remove(&loc);
        self.set(loc, Terrain::Door);
    }

    fn add_up_stairs(&mut self, pos: mapgen::Point2D) {
        let loc = self.loc(pos);
        self.up_portal = Some(loc);
        self.spawn_region.remove(&loc);
        // TODO: Add debug assertion that up-stairs are dug in the upper wall of a room
        self.set(loc, Terrain::Gate);
    }

    fn add_down_stairs(&mut self, pos: mapgen::Point2D) {
        let loc = self.loc(pos);
        self.down_portal = Some(loc);
        self.spawn_region.remove(&loc);
        self.set(loc, Terrain::Gate);

        // Visual hack to make the down-stairs show up better, carve out the rock blob that would
        // be drawn partially in front of it on screen.
        self.set(loc + vec2(1, 1), Terrain::Empty);
        // TODO: Add a debug assertion here to check that the exit location has proper enclosure to
        // begin with, both it and the rock cell in front of it need to be surrounded by undug
        // front tiles.
        self.spawn_region.remove(&(loc + vec2(1, 1))); // Just in case
    }
}

struct Room {
    size: Size2D<i32>,
}

impl mapgen::Prefab for Room {
    fn contains(&self, pos: mapgen::Point2D) -> bool {
        pos.x >= 0 && pos.y >= 0 && pos.x < self.size.width && pos.y < self.size.height
    }

    fn can_make_door(&self, pos: mapgen::Point2D) -> bool {
        let on_x_wall = pos.x == 0 || pos.x == self.size.width - 1;
        let on_y_wall = pos.y == 0 || pos.y == self.size.height - 1;

        // Must touch one wall, but touching both makes it a corner and we don't want rooms there.
        on_x_wall ^ on_y_wall
    }

    fn size(&self) -> mapgen::Size2D { self.size }
}

impl Rand for Room {
    fn rand<R: Rng>(rng: &mut R) -> Self {
        Room { size: Size2D::new(rng.gen_range(3, 10), rng.gen_range(3, 10)) }
    }
}
<|endoftext|>


<commit_before>//! Data for tracking user information.
use std::str::FromStr;

/// IRC User data.
#[deriving(Clone, Show)]
pub struct User {
    /// The user's nickname.
    name: String,
    /// The user's access level.
    /// For simplicity, this is not used to determine the equality of two users.
    /// That is a user is equal if and only if their nickname is the same.
    access_level: AccessLevel,
}

impl User {
    /// Creates a new User.
    pub fn new(name: &str) -> User {
        let rank = from_str(name);
        User {
            name: if let Some(AccessLevel::Member) = rank {
                name.into_string()
            } else {
                name[1..].into_string()
            },
            access_level: rank.unwrap(),
        }
    }

    /// Gets the nickname of the user.
    pub fn get_name(&self) -> &str {
        self.name[]
    }

    /// Gets the user's access level.
    pub fn access_level(&self) -> AccessLevel {
        self.access_level
    }

    /// Updates the user's access level.
    pub fn update_access_level(&mut self, mode: &str) {
        self.access_level = match mode {
            "+q" => AccessLevel::Owner,
            "-q" => AccessLevel::Member,
            "+a" => AccessLevel::Admin,
            "-a" => AccessLevel::Member,
            "+o" => AccessLevel::Oper,
            "-o" => AccessLevel::Member,
            "+h" => AccessLevel::HalfOp,
            "-h" => AccessLevel::Member,
            "+v" => AccessLevel::Voice,
            "-v" => AccessLevel::Member,
            _ => self.access_level,
        }
    }
}

impl PartialEq for User {
    fn eq(&self, other: &User) -> bool {
        self.name == other.name
    }
}

/// The user's access level.
#[deriving(PartialEq, Clone, Show)]
pub enum AccessLevel {
    /// The channel owner (~).
    Owner,
    /// A channel administrator (&).
    Admin,
    /// A channel operator (@),
    Oper,
    /// A channel half-oper (%),
    HalfOp,
    /// A user with voice (+),
    Voice,
    /// A normal user,
    Member,
}

impl FromStr for AccessLevel {
    fn from_str(s: &str) -> Option<AccessLevel> {
        if s.len() == 0 { Some(AccessLevel::Member) } else {
            Some(match s.char_at(0) {
                '~' => AccessLevel::Owner,
                '&' => AccessLevel::Admin,
                '@' => AccessLevel::Oper,
                '%' => AccessLevel::HalfOp,
                '+' => AccessLevel::Voice,
                 _  => AccessLevel::Member,
            })
        }
    }
}

#[cfg(test)]
mod test {
    use super::{AccessLevel, User};
    use super::AccessLevel::{Admin, HalfOp, Member, Oper, Owner, Voice};

    #[test]
    fn access_level_from_str() {
        assert_eq!(from_str::<AccessLevel>("member").unwrap(), Member);
        assert_eq!(from_str::<AccessLevel>("~owner").unwrap(), Owner);
        assert_eq!(from_str::<AccessLevel>("&admin").unwrap(), Admin);
        assert_eq!(from_str::<AccessLevel>("@oper").unwrap(), Oper);
        assert_eq!(from_str::<AccessLevel>("%halfop").unwrap(), HalfOp);
        assert_eq!(from_str::<AccessLevel>("+voice").unwrap(), Voice);
        assert_eq!(from_str::<AccessLevel>("").unwrap(), Member);
    }

    #[test]
    fn create_user() {
        let user = User::new("~owner");
        let exp = User {
            name: format!("owner"),
            access_level: Owner,
        };
        assert_eq!(user, exp);
        assert_eq!(user.access_level, exp.access_level);
    }

    #[test]
    fn get_name() {
        let user = User::new("~owner");
        assert_eq!(user.get_name(), "owner");
    }

    #[test]
    fn access_level() {
        let user = User::new("~owner");
        assert_eq!(user.access_level(), Owner);
    }

    #[test]
    fn update_user_rank() {
        let mut user = User::new("user");
        assert_eq!(user.access_level, Member);
        user.update_access_level("+q");
        assert_eq!(user.access_level, Owner);
        user.update_access_level("-q");
        assert_eq!(user.access_level, Member);
        user.update_access_level("+a");
        assert_eq!(user.access_level, Admin);
        user.update_access_level("-a");
        assert_eq!(user.access_level, Member);
        user.update_access_level("+o");
        assert_eq!(user.access_level, Oper);
        user.update_access_level("-o");
        assert_eq!(user.access_level, Member);
        user.update_access_level("+h");
        assert_eq!(user.access_level, HalfOp);
        user.update_access_level("-h");
        assert_eq!(user.access_level, Member);
        user.update_access_level("+v");
        assert_eq!(user.access_level, Voice);
        user.update_access_level("-v");
        assert_eq!(user.access_level, Member);
    }
}
<commit_msg>Stability annotations for user.<commit_after>//! Data for tracking user information.
#![unstable]
use std::str::FromStr;

/// IRC User data.
#[unstable]
#[deriving(Clone, Show)]
pub struct User {
    /// The user's nickname.
    name: String,
    /// The user's access level.
    /// For simplicity, this is not used to determine the equality of two users.
    /// That is a user is equal if and only if their nickname is the same.
    access_level: AccessLevel,
}

impl User {
    /// Creates a new User.
    #[stable]
    pub fn new(name: &str) -> User {
        let rank = from_str(name);
        User {
            name: if let Some(AccessLevel::Member) = rank {
                name.into_string()
            } else {
                name[1..].into_string()
            },
            access_level: rank.unwrap(),
        }
    }

    /// Gets the nickname of the user.
    #[stable]
    pub fn get_name(&self) -> &str {
        self.name[]
    }

    /// Gets the user's access level.
    #[experimental]
    pub fn access_level(&self) -> AccessLevel {
        self.access_level
    }

    /// Updates the user's access level.
    #[unstable]
    pub fn update_access_level(&mut self, mode: &str) {
        self.access_level = match mode {
            "+q" => AccessLevel::Owner,
            "-q" => AccessLevel::Member,
            "+a" => AccessLevel::Admin,
            "-a" => AccessLevel::Member,
            "+o" => AccessLevel::Oper,
            "-o" => AccessLevel::Member,
            "+h" => AccessLevel::HalfOp,
            "-h" => AccessLevel::Member,
            "+v" => AccessLevel::Voice,
            "-v" => AccessLevel::Member,
            _ => self.access_level,
        }
    }
}

impl PartialEq for User {
    fn eq(&self, other: &User) -> bool {
        self.name == other.name
    }
}

/// The user's access level.
#[stable]
#[deriving(PartialEq, Clone, Show)]
pub enum AccessLevel {
    /// The channel owner (~).
    Owner,
    /// A channel administrator (&).
    Admin,
    /// A channel operator (@),
    Oper,
    /// A channel half-oper (%),
    HalfOp,
    /// A user with voice (+),
    Voice,
    /// A normal user,
    Member,
}

impl FromStr for AccessLevel {
    fn from_str(s: &str) -> Option<AccessLevel> {
        if s.len() == 0 { Some(AccessLevel::Member) } else {
            Some(match s.char_at(0) {
                '~' => AccessLevel::Owner,
                '&' => AccessLevel::Admin,
                '@' => AccessLevel::Oper,
                '%' => AccessLevel::HalfOp,
                '+' => AccessLevel::Voice,
                 _  => AccessLevel::Member,
            })
        }
    }
}

#[cfg(test)]
mod test {
    use super::{AccessLevel, User};
    use super::AccessLevel::{Admin, HalfOp, Member, Oper, Owner, Voice};

    #[test]
    fn access_level_from_str() {
        assert_eq!(from_str::<AccessLevel>("member").unwrap(), Member);
        assert_eq!(from_str::<AccessLevel>("~owner").unwrap(), Owner);
        assert_eq!(from_str::<AccessLevel>("&admin").unwrap(), Admin);
        assert_eq!(from_str::<AccessLevel>("@oper").unwrap(), Oper);
        assert_eq!(from_str::<AccessLevel>("%halfop").unwrap(), HalfOp);
        assert_eq!(from_str::<AccessLevel>("+voice").unwrap(), Voice);
        assert_eq!(from_str::<AccessLevel>("").unwrap(), Member);
    }

    #[test]
    fn create_user() {
        let user = User::new("~owner");
        let exp = User {
            name: format!("owner"),
            access_level: Owner,
        };
        assert_eq!(user, exp);
        assert_eq!(user.access_level, exp.access_level);
    }

    #[test]
    fn get_name() {
        let user = User::new("~owner");
        assert_eq!(user.get_name(), "owner");
    }

    #[test]
    fn access_level() {
        let user = User::new("~owner");
        assert_eq!(user.access_level(), Owner);
    }

    #[test]
    fn update_user_rank() {
        let mut user = User::new("user");
        assert_eq!(user.access_level, Member);
        user.update_access_level("+q");
        assert_eq!(user.access_level, Owner);
        user.update_access_level("-q");
        assert_eq!(user.access_level, Member);
        user.update_access_level("+a");
        assert_eq!(user.access_level, Admin);
        user.update_access_level("-a");
        assert_eq!(user.access_level, Member);
        user.update_access_level("+o");
        assert_eq!(user.access_level, Oper);
        user.update_access_level("-o");
        assert_eq!(user.access_level, Member);
        user.update_access_level("+h");
        assert_eq!(user.access_level, HalfOp);
        user.update_access_level("-h");
        assert_eq!(user.access_level, Member);
        user.update_access_level("+v");
        assert_eq!(user.access_level, Voice);
        user.update_access_level("-v");
        assert_eq!(user.access_level, Member);
    }
}
<|endoftext|>


<commit_before>//! Exceptions
//!
//! All the exceptions prefixed with an underscore (`_`) can be overridden by
//! the top crate. Check out
//! [this example](../examples/override_exception/index.html).

use cortex_m::{self, Handler};
#[cfg(feature = "default-exception-handler")]
use cortex_m::StackFrame;

/// Kind of exception
#[derive(Debug)]
pub enum Exception {
    /// i.e. currently not servicing an exception
    ThreadMode,
    /// Non-maskable interrupt.
    Nmi,
    /// All class of fault.
    HardFault,
    /// Memory management.
    MemoryManagementFault,
    /// Pre-fetch fault, memory access fault.
    BusFault,
    /// Undefined instruction or illegal state.
    UsageFault,
    /// System service call via SWI instruction
    SVCall,
    /// Pendable request for system service
    PendSV,
    /// System tick timer
    Systick,
    /// An interrupt
    Interrupt(u8),
    // Unreachable variant
    #[doc(hidden)]
    Reserved,
}

impl Exception {
    /// Returns the exception that's currently being serviced
    pub fn current() -> Exception {
        match cortex_m::peripheral::scb().icsr.read() as u8 {
            0 => Exception::ThreadMode,
            2 => Exception::Nmi,
            3 => Exception::HardFault,
            4 => Exception::MemoryManagementFault,
            5 => Exception::BusFault,
            6 => Exception::UsageFault,
            11 => Exception::SVCall,
            14 => Exception::PendSV,
            15 => Exception::Systick,
            n if n >= 16 => Exception::Interrupt(n - 16),
            _ => Exception::Reserved,

        }
    }
}

#[cfg(all(target_arch = "arm", feature = "default-exception-handler"))]
#[doc(hidden)]
#[export_name = "_default_exception_handler"]
#[naked]
pub unsafe extern "C" fn default_handler_entry_point() {
    use core::intrinsics;

    // NOTE need asm!, #[naked] and unreachable() to avoid modifying the stack
    // pointer (MSP)
    asm!("mrs r0, MSP
          ldr r1, [r0, #20]
          b _default_exception_handler_impl" :::: "volatile");

    intrinsics::unreachable();
}

#[cfg(feature = "default-exception-handler")]
#[doc(hidden)]
#[export_name = "_default_exception_handler_impl"]
pub unsafe extern "C" fn default_handler(sf: &StackFrame) -> ! {
    iprintln!("EXCEPTION {:?} @ PC=0x{:08x}", Exception::current(), sf.pc);

    bkpt!();

    loop {}
}

/// List of all the exceptions minus the reset handler as allocated in the
/// vector table.
///
/// `None` indicates that the spot is RESERVED.
#[doc(hidden)]
#[export_name = "_EXCEPTIONS"]
pub static EXCEPTIONS: [Option<Handler>; 14] = [Some(_nmi),
                                                Some(_hard_fault),
                                                Some(_memmanage_fault),
                                                Some(_bus_fault),
                                                Some(_usage_fault),
                                                None,
                                                None,
                                                None,
                                                None,
                                                Some(_svcall),
                                                None,
                                                None,
                                                Some(_pendsv),
                                                Some(_systick)];

extern "C" {
    /// Non-maskable interrupt.
    pub fn _nmi();
    /// All class of fault.
    pub fn _hard_fault();
    /// Memory management.
    pub fn _memmanage_fault();
    /// Pre-fetch fault, memory access fault.
    pub fn _bus_fault();
    /// Undefined instruction or illegal state.
    pub fn _usage_fault();
    /// System service call via SWI instruction
    pub fn _svcall();
    /// Pendable request for system service
    pub fn _pendsv();
    /// System tick timer
    pub fn _systick();
}

/// Reset handler
#[doc(hidden)]
#[export_name = "_reset"]
pub unsafe extern "C" fn reset() -> ! {
    #[cfg(feature = "default-init")]
    use ::_init;

    extern "C" {
        static _ebss: u32;
        static _edata: u32;
        static _sidata: u32;
        static mut _sbss: u32;
        static mut _sdata: u32;
    }

    extern "Rust" {
        #[cfg(not(feature = "default-init"))]
        fn _init();

        // `main`, the entry point of the user program
        // NOTE the right signature of `main` is `fn() -> !`. But the user might
        // get that wrong so let's err on the side of caution and install a
        // safety net. (See below)
        fn main();
    }

    match () {
        #[cfg(feature = "static-ram")]
        () => {
            if &_sbss as *const _ as usize != &_ebss as *const _ as usize {
                ::r0::zero_bss(&mut _sbss, &_ebss);
            }

            if &_sdata as *const _ as usize != &_edata as *const _ as usize {
                ::r0::init_data(&mut _sdata, &_edata, &_sidata);
            }
        }
        #[cfg(not(feature = "static-ram"))]
        () => {}
    }

    _init();

    main();

    // safety net in case `main` returns
    panic!("returned from `main`!")
}
<commit_msg>get rid of the '_default_exception_handler_impl' symbol<commit_after>//! Exceptions
//!
//! All the exceptions prefixed with an underscore (`_`) can be overridden by
//! the top crate. Check out
//! [this example](../examples/override_exception/index.html).

use cortex_m::{self, Handler};
#[cfg(feature = "default-exception-handler")]
use cortex_m::StackFrame;

/// Kind of exception
#[derive(Debug)]
pub enum Exception {
    /// i.e. currently not servicing an exception
    ThreadMode,
    /// Non-maskable interrupt.
    Nmi,
    /// All class of fault.
    HardFault,
    /// Memory management.
    MemoryManagementFault,
    /// Pre-fetch fault, memory access fault.
    BusFault,
    /// Undefined instruction or illegal state.
    UsageFault,
    /// System service call via SWI instruction
    SVCall,
    /// Pendable request for system service
    PendSV,
    /// System tick timer
    Systick,
    /// An interrupt
    Interrupt(u8),
    // Unreachable variant
    #[doc(hidden)]
    Reserved,
}

impl Exception {
    /// Returns the exception that's currently being serviced
    pub fn current() -> Exception {
        match cortex_m::peripheral::scb().icsr.read() as u8 {
            0 => Exception::ThreadMode,
            2 => Exception::Nmi,
            3 => Exception::HardFault,
            4 => Exception::MemoryManagementFault,
            5 => Exception::BusFault,
            6 => Exception::UsageFault,
            11 => Exception::SVCall,
            14 => Exception::PendSV,
            15 => Exception::Systick,
            n if n >= 16 => Exception::Interrupt(n - 16),
            _ => Exception::Reserved,

        }
    }
}

#[cfg(all(target_arch = "arm", feature = "default-exception-handler"))]
#[doc(hidden)]
#[naked]
#[no_mangle]
pub unsafe extern "C" fn _default_exception_handler() {
    use core::intrinsics;

    // NOTE need asm!, #[naked] and unreachable() to avoid modifying the stack
    // pointer (MSP)
    asm!("mrs r0, MSP
          ldr r1, [r0, #20]
          b $0" :: "i"(deh as extern "C" fn(&StackFrame) -> !) :: "volatile");

    intrinsics::unreachable();
}

#[cfg(feature = "default-exception-handler")]
#[doc(hidden)]
extern "C" fn deh(sf: &StackFrame) -> ! {
    iprintln!("EXCEPTION {:?} @ PC=0x{:08x}", Exception::current(), sf.pc);

    unsafe {
        bkpt!();
    }

    loop {}
}

/// List of all the exceptions minus the reset handler as allocated in the
/// vector table.
///
/// `None` indicates that the spot is RESERVED.
#[doc(hidden)]
#[export_name = "_EXCEPTIONS"]
pub static EXCEPTIONS: [Option<Handler>; 14] = [Some(_nmi),
                                                Some(_hard_fault),
                                                Some(_memmanage_fault),
                                                Some(_bus_fault),
                                                Some(_usage_fault),
                                                None,
                                                None,
                                                None,
                                                None,
                                                Some(_svcall),
                                                None,
                                                None,
                                                Some(_pendsv),
                                                Some(_systick)];

extern "C" {
    /// Non-maskable interrupt.
    pub fn _nmi();
    /// All class of fault.
    pub fn _hard_fault();
    /// Memory management.
    pub fn _memmanage_fault();
    /// Pre-fetch fault, memory access fault.
    pub fn _bus_fault();
    /// Undefined instruction or illegal state.
    pub fn _usage_fault();
    /// System service call via SWI instruction
    pub fn _svcall();
    /// Pendable request for system service
    pub fn _pendsv();
    /// System tick timer
    pub fn _systick();
}

/// Reset handler
#[doc(hidden)]
#[export_name = "_reset"]
pub unsafe extern "C" fn reset() -> ! {
    #[cfg(feature = "default-init")]
    use ::_init;

    extern "C" {
        static _ebss: u32;
        static _edata: u32;
        static _sidata: u32;
        static mut _sbss: u32;
        static mut _sdata: u32;
    }

    extern "Rust" {
        #[cfg(not(feature = "default-init"))]
        fn _init();

        // `main`, the entry point of the user program
        // NOTE the right signature of `main` is `fn() -> !`. But the user might
        // get that wrong so let's err on the side of caution and install a
        // safety net. (See below)
        fn main();
    }

    match () {
        #[cfg(feature = "static-ram")]
        () => {
            if &_sbss as *const _ as usize != &_ebss as *const _ as usize {
                ::r0::zero_bss(&mut _sbss, &_ebss);
            }

            if &_sdata as *const _ as usize != &_edata as *const _ as usize {
                ::r0::init_data(&mut _sdata, &_edata, &_sidata);
            }
        }
        #[cfg(not(feature = "static-ram"))]
        () => {}
    }

    _init();

    main();

    // safety net in case `main` returns
    panic!("returned from `main`!")
}
<|endoftext|>


<commit_before><commit_msg>fix Binary ambiguity<commit_after><|endoftext|>


<commit_before>use std::io;
use std::io::Write;

use rustbox::{RustBox};
use termbox_sys::tb_change_cell;
// use termbox_sys;

use tui::style;

/// A single line added to the widget. May be rendered as multiple lines on the
/// screen.
#[derive(Debug)]
pub struct Line {
    /// Note that this String may not be directly renderable because of color
    /// encodings.
    str       : String,

    /// Number of _visible_ (i.e. excludes color encodings) characters in the
    /// line.
    len_chars : i32,

    /// Visible char indexes (not counting color encodings) of split positions
    /// of the string - when the line doesn't fit into the screen we split it
    /// into multiple lines using these.
    ///
    /// It's important that these are really indices ignoring invisible chars,
    /// as we use difference between two indices in this vector as length of
    /// substrings.
    splits    : Vec<i32>,
}

impl Line {
    pub fn new() -> Line {
        Line {
            str: String::new(),
            len_chars: 0,
            splits: Vec::new(),
        }
    }

    pub fn set_style(&mut self, style : &style::Style) {
        self.str.push(style::TERMBOX_COLOR_PREFIX);
        self.str.push(((style.fg >> 8) as u8) as char);
        self.str.push((style.fg as u8) as char);
        self.str.push((style.bg as u8) as char);
    }

    pub fn add_text(&mut self, str : &str) {
        self.str.reserve(str.len());

        let mut iter = str.chars();
        while let Some(char) = iter.next() {
            if char == style::TERMBOX_COLOR_PREFIX {
                self.str.push(char);
                // read style (bold, underline etc.)
                self.str.push(iter.next().unwrap());
                // read fg
                self.str.push(iter.next().unwrap());
                // read bg
                self.str.push(iter.next().unwrap());
            }

            else if char == style::COLOR_RESET_PREFIX {
                self.str.push(char);
            }

            else if char > '\x08' {
                self.str.push(char);
                if char.is_whitespace() {
                    self.splits.push(self.len_chars);
                }
                self.len_chars += 1;
            }
        }
    }

    pub fn add_char(&mut self, char : char) {
        assert!(char != style::TERMBOX_COLOR_PREFIX);
        if char.is_whitespace() {
            self.splits.push(self.len_chars);
        }
        self.str.push(char);
        self.len_chars += 1;
    }

    pub fn len_chars(&self) -> i32 {
        self.len_chars
    }

    /// How many lines does this take when rendered? O(n) where n = number of
    /// split positions in the lines (i.e.  whitespaces).
    pub fn rendered_height(&self, width : i32) -> i32 {
        let mut lines : i32 = 1;
        let mut line_start : i32 = 0;

        for split_idx in 0 .. self.splits.len() {
            let char_idx = *unsafe { self.splits.get_unchecked(split_idx) };
            // writeln!(io::stderr(), "rendered_height: char_idx: {}", char_idx);
            let col = char_idx - line_start;

            // How many more chars can we render in this line?
            let slots_in_line : i32 = width - (col + 1);

            // How many chars do we need to render if until the next split
            // point?
            let chars_until_next_split : i32 =
                // -1 because we don't need to render the space or EOL.
                *self.splits.get(split_idx + 1).unwrap_or(&self.len_chars) - 1 - char_idx;

            // writeln!(io::stderr(),
            //          "rendered_height: slots_in_line: {}, chars_until_next_split: {}",
            //          slots_in_line, chars_until_next_split);

            if (chars_until_next_split as i32) > slots_in_line {
                // writeln!(io::stderr(), "splitting at {}", char_idx);
                lines += 1;
                line_start = char_idx + 1;
            }
        }

        lines
    }

    #[inline]
    pub fn draw(&self, rustbox : &RustBox, pos_x : i32, pos_y : i32, width : i32) {
        self.draw_from(rustbox, pos_x, pos_y, 0, width);
    }

    pub fn draw_from(&self, _ : &RustBox, pos_x : i32, pos_y : i32, first_line : i32, width : i32) {
        writeln!(io::stderr(), "drawing {:?}", self.str).unwrap();

        let mut col = pos_x;
        let mut line = 0;

        let mut next_split_idx : usize = 0;

        let mut char_idx : i32 = 0;

        let mut fg : u16 = 0;
        let mut bg : u16 = 0;

        let mut iter = self.str.chars();
        while let Some(char) = iter.next() {
            if char == style::TERMBOX_COLOR_PREFIX {
                let b1 = iter.next().unwrap() as u8;
                let b2 = iter.next().unwrap() as u8;
                let b3 = iter.next().unwrap() as u8;
                fg = ((b1 as u16) << 8) | (b2 as u16);
                bg = b3 as u16;
            }

            else if char == style::COLOR_RESET_PREFIX {
                fg = style::CLEAR.fg;
                bg = style::CLEAR.bg;
            }

            else if char.is_whitespace() {
                // We may want to move to the next line
                next_split_idx += 1;
                let next_split = self.splits.get(next_split_idx).unwrap_or(&self.len_chars);

                // How many more chars can we render in this line?
                let slots_in_line = width - (col - pos_x);

                // How many chars do we need to render if until the next
                // split point?
                assert!(*next_split > char_idx);
                let chars_until_next_split : i32 = *next_split - char_idx;

                // writeln!(io::stderr(), "chars_until_next_split: {}, slots_in_line: {}",
                //          chars_until_next_split, slots_in_line);

                if (chars_until_next_split as i32) <= slots_in_line {
                    // keep rendering chars
                    if line >= first_line {
                        unsafe { tb_change_cell(col, pos_y + line, char as u32, fg, bg); }
                    }
                    col += 1;
                } else {
                    // need to split here. ignore whitespace char.
                    line += 1;
                    col = pos_x;
                }

                char_idx += 1;
            }

            else {
                // Not possible to split. Need to make sure we don't render out
                // of bounds.
                if col - pos_x < width {
                    if line >= first_line {
                        unsafe { tb_change_cell(col, pos_y + line, char as u32, fg, bg); }
                    }
                    col += 1;
                }

                char_idx += 1;
            }
        }
    }
}

////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {

extern crate test;

use self::test::Bencher;
use std::fs::File;
use std::io::Read;
use super::*;

#[test]
fn height_test_1() {
    let mut line = Line::new();
    line.add_text("a b c d e");
    assert_eq!(line.rendered_height(1), 5);
    assert_eq!(line.rendered_height(2), 5);
    assert_eq!(line.rendered_height(3), 3);
    assert_eq!(line.rendered_height(4), 3);
    assert_eq!(line.rendered_height(5), 2);
    assert_eq!(line.rendered_height(6), 2);
    assert_eq!(line.rendered_height(7), 2);
    assert_eq!(line.rendered_height(8), 2);
    assert_eq!(line.rendered_height(9), 1);
}

#[test]
fn height_test_2() {
    let mut line = Line::new();
    line.add_text("ab c d e");
    assert_eq!(line.rendered_height(1), 4);
    assert_eq!(line.rendered_height(2), 4);
    assert_eq!(line.rendered_height(3), 3);
    assert_eq!(line.rendered_height(4), 2);
    assert_eq!(line.rendered_height(5), 2);
    assert_eq!(line.rendered_height(6), 2);
    assert_eq!(line.rendered_height(7), 2);
    assert_eq!(line.rendered_height(8), 1);
}

#[test]
fn height_test_3() {
    let mut line = Line::new();
    line.add_text("ab cd e");
    assert_eq!(line.rendered_height(1), 3);
    assert_eq!(line.rendered_height(2), 3);
    assert_eq!(line.rendered_height(3), 3);
    assert_eq!(line.rendered_height(4), 2);
    assert_eq!(line.rendered_height(5), 2);
    assert_eq!(line.rendered_height(6), 2);
    assert_eq!(line.rendered_height(7), 1);
}

#[test]
fn height_test_4() {
    let mut line = Line::new();
    line.add_text("ab cde");
    assert_eq!(line.rendered_height(1), 2);
    assert_eq!(line.rendered_height(2), 2);
    assert_eq!(line.rendered_height(3), 2);
    assert_eq!(line.rendered_height(4), 2);
    assert_eq!(line.rendered_height(5), 2);
    assert_eq!(line.rendered_height(6), 1);
}

#[test]
fn height_test_5() {
    let mut line = Line::new();
    line.add_text("abcde");
    for i in 0 .. 6 {
        assert_eq!(line.rendered_height(i), 1);
    }
}

#[test]
fn height_test_6() {
    let mut text = String::new();
    {
        let mut file = File::open("test/lipsum.txt").unwrap();
        file.read_to_string(&mut text).unwrap();
    }

    let mut line = Line::new();
    line.add_text(&text);
    assert!(line.rendered_height(1) >= 1160);
}

#[bench]
fn bench_rendered_height(b : &mut Bencher) {

    // 1160 words, 2,237 ns/iter (+/- 150)

    let mut text = String::new();
    {
        let mut file = File::open("test/lipsum.txt").unwrap();
        file.read_to_string(&mut text).unwrap();
    }

    let mut line = Line::new();
    line.add_text(&text);
    b.iter(|| {
        line.rendered_height(1)
    });
}

} // mod tests
<commit_msg>line: disable a debug print<commit_after>// use std::io;
// use std::io::Write;

use rustbox::{RustBox};
use termbox_sys::tb_change_cell;
// use termbox_sys;

use tui::style;

/// A single line added to the widget. May be rendered as multiple lines on the
/// screen.
#[derive(Debug)]
pub struct Line {
    /// Note that this String may not be directly renderable because of color
    /// encodings.
    str       : String,

    /// Number of _visible_ (i.e. excludes color encodings) characters in the
    /// line.
    len_chars : i32,

    /// Visible char indexes (not counting color encodings) of split positions
    /// of the string - when the line doesn't fit into the screen we split it
    /// into multiple lines using these.
    ///
    /// It's important that these are really indices ignoring invisible chars,
    /// as we use difference between two indices in this vector as length of
    /// substrings.
    splits    : Vec<i32>,
}

impl Line {
    pub fn new() -> Line {
        Line {
            str: String::new(),
            len_chars: 0,
            splits: Vec::new(),
        }
    }

    pub fn set_style(&mut self, style : &style::Style) {
        self.str.push(style::TERMBOX_COLOR_PREFIX);
        self.str.push(((style.fg >> 8) as u8) as char);
        self.str.push((style.fg as u8) as char);
        self.str.push((style.bg as u8) as char);
    }

    pub fn add_text(&mut self, str : &str) {
        self.str.reserve(str.len());

        let mut iter = str.chars();
        while let Some(char) = iter.next() {
            if char == style::TERMBOX_COLOR_PREFIX {
                self.str.push(char);
                // read style (bold, underline etc.)
                self.str.push(iter.next().unwrap());
                // read fg
                self.str.push(iter.next().unwrap());
                // read bg
                self.str.push(iter.next().unwrap());
            }

            else if char == style::COLOR_RESET_PREFIX {
                self.str.push(char);
            }

            else if char > '\x08' {
                self.str.push(char);
                if char.is_whitespace() {
                    self.splits.push(self.len_chars);
                }
                self.len_chars += 1;
            }
        }
    }

    pub fn add_char(&mut self, char : char) {
        assert!(char != style::TERMBOX_COLOR_PREFIX);
        if char.is_whitespace() {
            self.splits.push(self.len_chars);
        }
        self.str.push(char);
        self.len_chars += 1;
    }

    pub fn len_chars(&self) -> i32 {
        self.len_chars
    }

    /// How many lines does this take when rendered? O(n) where n = number of
    /// split positions in the lines (i.e.  whitespaces).
    pub fn rendered_height(&self, width : i32) -> i32 {
        let mut lines : i32 = 1;
        let mut line_start : i32 = 0;

        for split_idx in 0 .. self.splits.len() {
            let char_idx = *unsafe { self.splits.get_unchecked(split_idx) };
            // writeln!(io::stderr(), "rendered_height: char_idx: {}", char_idx);
            let col = char_idx - line_start;

            // How many more chars can we render in this line?
            let slots_in_line : i32 = width - (col + 1);

            // How many chars do we need to render if until the next split
            // point?
            let chars_until_next_split : i32 =
                // -1 because we don't need to render the space or EOL.
                *self.splits.get(split_idx + 1).unwrap_or(&self.len_chars) - 1 - char_idx;

            // writeln!(io::stderr(),
            //          "rendered_height: slots_in_line: {}, chars_until_next_split: {}",
            //          slots_in_line, chars_until_next_split);

            if (chars_until_next_split as i32) > slots_in_line {
                // writeln!(io::stderr(), "splitting at {}", char_idx);
                lines += 1;
                line_start = char_idx + 1;
            }
        }

        lines
    }

    #[inline]
    pub fn draw(&self, rustbox : &RustBox, pos_x : i32, pos_y : i32, width : i32) {
        self.draw_from(rustbox, pos_x, pos_y, 0, width);
    }

    pub fn draw_from(&self, _ : &RustBox, pos_x : i32, pos_y : i32, first_line : i32, width : i32) {
        let mut col = pos_x;
        let mut line = 0;

        let mut next_split_idx : usize = 0;

        let mut char_idx : i32 = 0;

        let mut fg : u16 = 0;
        let mut bg : u16 = 0;

        let mut iter = self.str.chars();
        while let Some(char) = iter.next() {
            if char == style::TERMBOX_COLOR_PREFIX {
                let b1 = iter.next().unwrap() as u8;
                let b2 = iter.next().unwrap() as u8;
                let b3 = iter.next().unwrap() as u8;
                fg = ((b1 as u16) << 8) | (b2 as u16);
                bg = b3 as u16;
            }

            else if char == style::COLOR_RESET_PREFIX {
                fg = style::CLEAR.fg;
                bg = style::CLEAR.bg;
            }

            else if char.is_whitespace() {
                // We may want to move to the next line
                next_split_idx += 1;
                let next_split = self.splits.get(next_split_idx).unwrap_or(&self.len_chars);

                // How many more chars can we render in this line?
                let slots_in_line = width - (col - pos_x);

                // How many chars do we need to render if until the next
                // split point?
                assert!(*next_split > char_idx);
                let chars_until_next_split : i32 = *next_split - char_idx;

                // writeln!(io::stderr(), "chars_until_next_split: {}, slots_in_line: {}",
                //          chars_until_next_split, slots_in_line);

                if (chars_until_next_split as i32) <= slots_in_line {
                    // keep rendering chars
                    if line >= first_line {
                        unsafe { tb_change_cell(col, pos_y + line, char as u32, fg, bg); }
                    }
                    col += 1;
                } else {
                    // need to split here. ignore whitespace char.
                    line += 1;
                    col = pos_x;
                }

                char_idx += 1;
            }

            else {
                // Not possible to split. Need to make sure we don't render out
                // of bounds.
                if col - pos_x < width {
                    if line >= first_line {
                        unsafe { tb_change_cell(col, pos_y + line, char as u32, fg, bg); }
                    }
                    col += 1;
                }

                char_idx += 1;
            }
        }
    }
}

////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {

extern crate test;

use self::test::Bencher;
use std::fs::File;
use std::io::Read;
use super::*;

#[test]
fn height_test_1() {
    let mut line = Line::new();
    line.add_text("a b c d e");
    assert_eq!(line.rendered_height(1), 5);
    assert_eq!(line.rendered_height(2), 5);
    assert_eq!(line.rendered_height(3), 3);
    assert_eq!(line.rendered_height(4), 3);
    assert_eq!(line.rendered_height(5), 2);
    assert_eq!(line.rendered_height(6), 2);
    assert_eq!(line.rendered_height(7), 2);
    assert_eq!(line.rendered_height(8), 2);
    assert_eq!(line.rendered_height(9), 1);
}

#[test]
fn height_test_2() {
    let mut line = Line::new();
    line.add_text("ab c d e");
    assert_eq!(line.rendered_height(1), 4);
    assert_eq!(line.rendered_height(2), 4);
    assert_eq!(line.rendered_height(3), 3);
    assert_eq!(line.rendered_height(4), 2);
    assert_eq!(line.rendered_height(5), 2);
    assert_eq!(line.rendered_height(6), 2);
    assert_eq!(line.rendered_height(7), 2);
    assert_eq!(line.rendered_height(8), 1);
}

#[test]
fn height_test_3() {
    let mut line = Line::new();
    line.add_text("ab cd e");
    assert_eq!(line.rendered_height(1), 3);
    assert_eq!(line.rendered_height(2), 3);
    assert_eq!(line.rendered_height(3), 3);
    assert_eq!(line.rendered_height(4), 2);
    assert_eq!(line.rendered_height(5), 2);
    assert_eq!(line.rendered_height(6), 2);
    assert_eq!(line.rendered_height(7), 1);
}

#[test]
fn height_test_4() {
    let mut line = Line::new();
    line.add_text("ab cde");
    assert_eq!(line.rendered_height(1), 2);
    assert_eq!(line.rendered_height(2), 2);
    assert_eq!(line.rendered_height(3), 2);
    assert_eq!(line.rendered_height(4), 2);
    assert_eq!(line.rendered_height(5), 2);
    assert_eq!(line.rendered_height(6), 1);
}

#[test]
fn height_test_5() {
    let mut line = Line::new();
    line.add_text("abcde");
    for i in 0 .. 6 {
        assert_eq!(line.rendered_height(i), 1);
    }
}

#[test]
fn height_test_6() {
    let mut text = String::new();
    {
        let mut file = File::open("test/lipsum.txt").unwrap();
        file.read_to_string(&mut text).unwrap();
    }

    let mut line = Line::new();
    line.add_text(&text);
    assert!(line.rendered_height(1) >= 1160);
}

#[bench]
fn bench_rendered_height(b : &mut Bencher) {

    // 1160 words, 2,237 ns/iter (+/- 150)

    let mut text = String::new();
    {
        let mut file = File::open("test/lipsum.txt").unwrap();
        file.read_to_string(&mut text).unwrap();
    }

    let mut line = Line::new();
    line.add_text(&text);
    b.iter(|| {
        line.rendered_height(1)
    });
}

} // mod tests
<|endoftext|>


<commit_before>use syntax::abi;
use syntax::ast;
use syntax::ast_util;
use syntax::codemap::DUMMY_SP;
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::ptr::P;

use block::{Block, Describe, It, Bench};

pub trait Generate {
    fn generate(self, cx: &mut ExtCtxt, up: Option<&Describe>) -> P<ast::Item>;
}

impl Generate for Block {
    fn generate(self, cx: &mut ExtCtxt, up: Option<&Describe>) -> P<ast::Item> {
        match self {
            Block::Describe(describe) => describe.generate(cx, up),
            Block::It(it) => it.generate(cx, up),
            Block::Bench(bench) => bench.generate(cx, up)
        }
    }
}

impl Generate for Describe {
    fn generate(mut self,
                cx: &mut ExtCtxt,
                up: Option<&Describe>) -> P<ast::Item> {
        let name = cx.ident_of(&self.name);

        if let Some(ref up) = up {
            if let Some(ref before) = up.before {
                self.before = match self.before {
                    Some(ref now) => Some(merge_blocks(before, now)),
                    None => Some(before.clone())
                }
            }

            if let Some(ref after) = up.after {
                self.after = match self.after {
                    Some(ref now) => Some(merge_blocks(now, after)),
                    None => Some(after.clone())
                }
            }
        }

        let mut items = self.blocks.iter().map(|block| {
            block.clone().generate(cx, Some(&self))
        }).collect::<Vec<_>>();

        let pub_use_super_star = cx.item_use_glob(DUMMY_SP,
                                                  ast::Visibility::Public,
                                                  vec![cx.ident_of("super")]);

        items.push(pub_use_super_star);

        cx.item_mod(DUMMY_SP,
                    DUMMY_SP,
                    name,
                    vec![],
                    items)
    }
}

impl Generate for It {
    fn generate(self, cx: &mut ExtCtxt, up: Option<&Describe>) -> P<ast::Item> {
        let name = cx.ident_of(&self.name);
        let attrs = vec![quote_attr!(cx, #[test])];

        let block = if let Some(ref up) = up {
            match (&up.before, &up.after) {
                (&Some(ref before), &Some(ref after)) => {
                    merge_blocks(&merge_blocks(before, &self.block), after)
                },
                (&Some(ref before), &None) => merge_blocks(before, &self.block),
                (&None, &Some(ref after)) => merge_blocks(&self.block, after),
                (&None, &None) => self.block.clone()
            }
        } else {
            self.block
        };

        cx.item(DUMMY_SP, name, attrs,
                ast::ItemFn(
                    P(ast::FnDecl {
                        inputs: vec![],
                        output: ast::DefaultReturn(DUMMY_SP),
                        variadic: false
                    }),
                    ast::Unsafety::Normal,
                    ast::Constness::NotConst,
                    abi::Rust,
                    ast_util::empty_generics(),
                    block
                ))
    }
}

impl Generate for Bench {
    fn generate(self, cx: &mut ExtCtxt, up: Option<&Describe>) -> P<ast::Item> {
        let name = cx.ident_of(&self.name);

        let attrs = vec![quote_attr!(cx, #[bench])];

        let args = vec![
            cx.arg(DUMMY_SP, self.ident, quote_ty!(cx, &mut ::test::Bencher))
        ];

        let block = if let Some(ref up) = up {
            match (&up.before, &up.after) {
                (&Some(ref before), &Some(ref after)) => {
                    merge_blocks(&merge_blocks(before, &self.block), after)
                },
                (&Some(ref before), &None) => merge_blocks(before, &self.block),
                (&None, &Some(ref after)) => merge_blocks(&self.block, after),
                (&None, &None) => self.block.clone()
            }
        } else {
            self.block
        };

        cx.item(DUMMY_SP, name, attrs,
                ast::ItemFn(
                    P(ast::FnDecl {
                        inputs: args,
                        output: ast::DefaultReturn(DUMMY_SP),
                        variadic: false
                    }),
                    ast::Unsafety::Normal,
                    ast::Constness::NotConst,
                    abi::Rust,
                    ast_util::empty_generics(),
                    block
                ))
    }
}

fn merge_blocks(left: &P<ast::Block>, right: &P<ast::Block>) -> P<ast::Block> {
    use std::ops::Deref;

    let mut stmts = left.stmts.clone();
    stmts.extend(right.stmts.clone());

    P(ast::Block {
        stmts: stmts,
        ..left.deref().clone()
    })
}
<commit_msg>Simplify code using `quote_item!`.<commit_after>use syntax::abi;
use syntax::ast;
use syntax::ast_util;
use syntax::codemap::DUMMY_SP;
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::ptr::P;

use block::{Block, Describe, It, Bench};

pub trait Generate {
    fn generate(self, cx: &mut ExtCtxt, up: Option<&Describe>) -> P<ast::Item>;
}

impl Generate for Block {
    fn generate(self, cx: &mut ExtCtxt, up: Option<&Describe>) -> P<ast::Item> {
        match self {
            Block::Describe(describe) => describe.generate(cx, up),
            Block::It(it) => it.generate(cx, up),
            Block::Bench(bench) => bench.generate(cx, up)
        }
    }
}

impl Generate for Describe {
    fn generate(mut self,
                cx: &mut ExtCtxt,
                up: Option<&Describe>) -> P<ast::Item> {
        let name = cx.ident_of(&self.name);

        if let Some(ref up) = up {
            if let Some(ref before) = up.before {
                self.before = match self.before {
                    Some(ref now) => Some(merge_blocks(before, now)),
                    None => Some(before.clone())
                }
            }

            if let Some(ref after) = up.after {
                self.after = match self.after {
                    Some(ref now) => Some(merge_blocks(now, after)),
                    None => Some(after.clone())
                }
            }
        }

        let mut items = self.blocks.iter().map(|block| {
            block.clone().generate(cx, Some(&self))
        }).collect::<Vec<_>>();

        items.push(quote_item!(cx, pub use super::*;).unwrap());

        cx.item_mod(DUMMY_SP,
                    DUMMY_SP,
                    name,
                    vec![],
                    items)
    }
}

impl Generate for It {
    fn generate(self, cx: &mut ExtCtxt, up: Option<&Describe>) -> P<ast::Item> {
        let name = cx.ident_of(&self.name);
        let attrs = vec![quote_attr!(cx, #[test])];

        let block = if let Some(ref up) = up {
            match (&up.before, &up.after) {
                (&Some(ref before), &Some(ref after)) => {
                    merge_blocks(&merge_blocks(before, &self.block), after)
                },
                (&Some(ref before), &None) => merge_blocks(before, &self.block),
                (&None, &Some(ref after)) => merge_blocks(&self.block, after),
                (&None, &None) => self.block.clone()
            }
        } else {
            self.block
        };

        cx.item(DUMMY_SP, name, attrs,
                ast::ItemFn(
                    P(ast::FnDecl {
                        inputs: vec![],
                        output: ast::DefaultReturn(DUMMY_SP),
                        variadic: false
                    }),
                    ast::Unsafety::Normal,
                    ast::Constness::NotConst,
                    abi::Rust,
                    ast_util::empty_generics(),
                    block
                ))
    }
}

impl Generate for Bench {
    fn generate(self, cx: &mut ExtCtxt, up: Option<&Describe>) -> P<ast::Item> {
        let name = cx.ident_of(&self.name);

        let attrs = vec![quote_attr!(cx, #[bench])];

        let args = vec![
            cx.arg(DUMMY_SP, self.ident, quote_ty!(cx, &mut ::test::Bencher))
        ];

        let block = if let Some(ref up) = up {
            match (&up.before, &up.after) {
                (&Some(ref before), &Some(ref after)) => {
                    merge_blocks(&merge_blocks(before, &self.block), after)
                },
                (&Some(ref before), &None) => merge_blocks(before, &self.block),
                (&None, &Some(ref after)) => merge_blocks(&self.block, after),
                (&None, &None) => self.block.clone()
            }
        } else {
            self.block
        };

        cx.item(DUMMY_SP, name, attrs,
                ast::ItemFn(
                    P(ast::FnDecl {
                        inputs: args,
                        output: ast::DefaultReturn(DUMMY_SP),
                        variadic: false
                    }),
                    ast::Unsafety::Normal,
                    ast::Constness::NotConst,
                    abi::Rust,
                    ast_util::empty_generics(),
                    block
                ))
    }
}

fn merge_blocks(left: &P<ast::Block>, right: &P<ast::Block>) -> P<ast::Block> {
    use std::ops::Deref;

    let mut stmts = left.stmts.clone();
    stmts.extend(right.stmts.clone());

    P(ast::Block {
        stmts: stmts,
        ..left.deref().clone()
    })
}
<|endoftext|>