<commit_before>use crate::fmt;
use crate::ops::Try;

use super::super::{Iterator, DoubleEndedIterator, FusedIterator};
use super::Map;

/// An iterator that maps each element to an iterator, and yields the elements
/// of the produced iterators.
///
/// This `struct` is created by the [`flat_map`] method on [`Iterator`]. See its
/// documentation for more.
///
/// [`flat_map`]: trait.Iterator.html#method.flat_map
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct FlatMap<I, U: IntoIterator, F> {
    inner: FlattenCompat<Map<I, F>, <U as IntoIterator>::IntoIter>
}
impl<I: Iterator, U: IntoIterator, F: FnMut(I::Item) -> U> FlatMap<I, U, F> {
    pub(in super::super) fn new(iter: I, f: F) -> FlatMap<I, U, F> {
        FlatMap { inner: FlattenCompat::new(iter.map(f)) }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Clone, U, F: Clone> Clone for FlatMap<I, U, F>
where
    U: Clone + IntoIterator<IntoIter: Clone>,
{
    fn clone(&self) -> Self { FlatMap { inner: self.inner.clone() } }
}

#[stable(feature = "core_impl_debug", since = "1.9.0")]
impl<I: fmt::Debug, U, F> fmt::Debug for FlatMap<I, U, F>
where
    U: IntoIterator<IntoIter: fmt::Debug>,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("FlatMap").field("inner", &self.inner).finish()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Iterator, U: IntoIterator, F> Iterator for FlatMap<I, U, F>
    where F: FnMut(I::Item) -> U,
{
    type Item = U::Item;

    #[inline]
    fn next(&mut self) -> Option<U::Item> { self.inner.next() }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) { self.inner.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<Ok=Acc>
    {
        self.inner.try_fold(init, fold)
    }

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

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F>
where
    F: FnMut(I::Item) -> U,
    U: IntoIterator,
    U::IntoIter: DoubleEndedIterator,
{
    #[inline]
    fn next_back(&mut self) -> Option<U::Item> { self.inner.next_back() }

    #[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<Ok=Acc>
    {
        self.inner.try_rfold(init, fold)
    }

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

#[stable(feature = "fused", since = "1.26.0")]
impl<I, U, F> FusedIterator for FlatMap<I, U, F>
    where I: FusedIterator, U: IntoIterator, F: FnMut(I::Item) -> U {}

/// An iterator that flattens one level of nesting in an iterator of things
/// that can be turned into iterators.
///
/// This `struct` is created by the [`flatten`] method on [`Iterator`]. See its
/// documentation for more.
///
/// [`flatten`]: trait.Iterator.html#method.flatten
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "iterator_flatten", since = "1.29.0")]
pub struct Flatten<I: Iterator>
where
    I::Item: IntoIterator,
{
    inner: FlattenCompat<I, <I::Item as IntoIterator>::IntoIter>,
}

impl<I: Iterator<Item: IntoIterator>> Flatten<I> {
    pub(in super::super) fn new(iter: I) -> Flatten<I> {
        Flatten { inner: FlattenCompat::new(iter) }
    }
}

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> fmt::Debug for Flatten<I>
where
    I: fmt::Debug + Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: fmt::Debug + Iterator,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Flatten").field("inner", &self.inner).finish()
    }
}

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> Clone for Flatten<I>
where
    I: Clone + Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: Clone + Iterator,
{
    fn clone(&self) -> Self { Flatten { inner: self.inner.clone() } }
}

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> Iterator for Flatten<I>
where
    I: Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: Iterator,
{
    type Item = U::Item;

    #[inline]
    fn next(&mut self) -> Option<U::Item> { self.inner.next() }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) { self.inner.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<Ok=Acc>
    {
        self.inner.try_fold(init, fold)
    }

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

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> DoubleEndedIterator for Flatten<I>
where
    I: DoubleEndedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: DoubleEndedIterator,
{
    #[inline]
    fn next_back(&mut self) -> Option<U::Item> { self.inner.next_back() }

    #[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<Ok=Acc>
    {
        self.inner.try_rfold(init, fold)
    }

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

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> FusedIterator for Flatten<I>
where
    I: FusedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: Iterator,
{}

/// Real logic of both `Flatten` and `FlatMap` which simply delegate to
/// this type.
#[derive(Clone, Debug)]
struct FlattenCompat<I, U> {
    iter: I,
    frontiter: Option<U>,
    backiter: Option<U>,
}
impl<I, U> FlattenCompat<I, U> {
    /// Adapts an iterator by flattening it, for use in `flatten()` and `flat_map()`.
    fn new(iter: I) -> FlattenCompat<I, U> {
        FlattenCompat { iter, frontiter: None, backiter: None }
    }
}

impl<I, U> Iterator for FlattenCompat<I, U>
where
    I: Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: Iterator,
{
    type Item = U::Item;

    #[inline]
    fn next(&mut self) -> Option<U::Item> {
        loop {
            if let Some(ref mut inner) = self.frontiter {
                if let elt@Some(_) = inner.next() { return elt }
            }
            match self.iter.next() {
                None => return self.backiter.as_mut()?.next(),
                Some(inner) => self.frontiter = Some(inner.into_iter()),
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), U::size_hint);
        let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), U::size_hint);
        let lo = flo.saturating_add(blo);
        match (self.iter.size_hint(), fhi, bhi) {
            ((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(b)),
            _ => (lo, None)
        }
    }

    #[inline]
    fn try_fold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R where
        Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
    {
        #[inline]
        fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>(
            frontiter: &'a mut Option<T::IntoIter>,
            fold: &'a mut impl FnMut(Acc, T::Item) -> R,
        ) -> impl FnMut(Acc, T) -> R + 'a {
            move |acc, x| {
                let mut mid = x.into_iter();
                let r = mid.try_fold(acc, &mut *fold);
                *frontiter = Some(mid);
                r
            }
        }

        if let Some(ref mut front) = self.frontiter {
            init = front.try_fold(init, &mut fold)?;
        }
        self.frontiter = None;

        init = self.iter.try_fold(init, flatten(&mut self.frontiter, &mut fold))?;
        self.frontiter = None;

        if let Some(ref mut back) = self.backiter {
            init = back.try_fold(init, &mut fold)?;
        }
        self.backiter = None;

        Try::from_ok(init)
    }

    #[inline]
    fn fold<Acc, Fold>(self, init: Acc, ref mut fold: Fold) -> Acc
        where Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        #[inline]
        fn flatten<U: Iterator, Acc>(
            fold: &mut impl FnMut(Acc, U::Item) -> Acc,
        ) -> impl FnMut(Acc, U) -> Acc + '_ {
            move |acc, iter| iter.fold(acc, &mut *fold)
        }

        self.frontiter.into_iter()
            .chain(self.iter.map(IntoIterator::into_iter))
            .chain(self.backiter)
            .fold(init, flatten(fold))
    }
}

impl<I, U> DoubleEndedIterator for FlattenCompat<I, U>
where
    I: DoubleEndedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: DoubleEndedIterator,
{
    #[inline]
    fn next_back(&mut self) -> Option<U::Item> {
        loop {
            if let Some(ref mut inner) = self.backiter {
                if let elt@Some(_) = inner.next_back() { return elt }
            }
            match self.iter.next_back() {
                None => return self.frontiter.as_mut()?.next_back(),
                next => self.backiter = next.map(IntoIterator::into_iter),
            }
        }
    }

    #[inline]
    fn try_rfold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R where
        Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
    {
        #[inline]
        fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>(
            backiter: &'a mut Option<T::IntoIter>,
            fold: &'a mut impl FnMut(Acc, T::Item) -> R,
        ) -> impl FnMut(Acc, T) -> R + 'a where
            T::IntoIter: DoubleEndedIterator,
        {
            move |acc, x| {
                let mut mid = x.into_iter();
                let r = mid.try_rfold(acc, &mut *fold);
                *backiter = Some(mid);
                r
            }
        }

        if let Some(ref mut back) = self.backiter {
            init = back.try_rfold(init, &mut fold)?;
        }
        self.backiter = None;

        init = self.iter.try_rfold(init, flatten(&mut self.backiter, &mut fold))?;
        self.backiter = None;

        if let Some(ref mut front) = self.frontiter {
            init = front.try_rfold(init, &mut fold)?;
        }
        self.frontiter = None;

        Try::from_ok(init)
    }

    #[inline]
    fn rfold<Acc, Fold>(self, init: Acc, ref mut fold: Fold) -> Acc
        where Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        #[inline]
        fn flatten<U: DoubleEndedIterator, Acc>(
            fold: &mut impl FnMut(Acc, U::Item) -> Acc,
        ) -> impl FnMut(Acc, U) -> Acc + '_ {
            move |acc, iter| iter.rfold(acc, &mut *fold)
        }

        self.frontiter.into_iter()
            .chain(self.iter.map(IntoIterator::into_iter))
            .chain(self.backiter)
            .rfold(init, flatten(fold))
    }
}
<commit_msg>Rollup merge of #63584 - Centril:cleanup-core-with-more-atb, r=alexreg<commit_after>use crate::fmt;
use crate::ops::Try;

use super::super::{Iterator, DoubleEndedIterator, FusedIterator};
use super::Map;

/// An iterator that maps each element to an iterator, and yields the elements
/// of the produced iterators.
///
/// This `struct` is created by the [`flat_map`] method on [`Iterator`]. See its
/// documentation for more.
///
/// [`flat_map`]: trait.Iterator.html#method.flat_map
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct FlatMap<I, U: IntoIterator, F> {
    inner: FlattenCompat<Map<I, F>, <U as IntoIterator>::IntoIter>
}
impl<I: Iterator, U: IntoIterator, F: FnMut(I::Item) -> U> FlatMap<I, U, F> {
    pub(in super::super) fn new(iter: I, f: F) -> FlatMap<I, U, F> {
        FlatMap { inner: FlattenCompat::new(iter.map(f)) }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Clone, U, F: Clone> Clone for FlatMap<I, U, F>
where
    U: Clone + IntoIterator<IntoIter: Clone>,
{
    fn clone(&self) -> Self { FlatMap { inner: self.inner.clone() } }
}

#[stable(feature = "core_impl_debug", since = "1.9.0")]
impl<I: fmt::Debug, U, F> fmt::Debug for FlatMap<I, U, F>
where
    U: IntoIterator<IntoIter: fmt::Debug>,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("FlatMap").field("inner", &self.inner).finish()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Iterator, U: IntoIterator, F> Iterator for FlatMap<I, U, F>
    where F: FnMut(I::Item) -> U,
{
    type Item = U::Item;

    #[inline]
    fn next(&mut self) -> Option<U::Item> { self.inner.next() }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) { self.inner.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<Ok=Acc>
    {
        self.inner.try_fold(init, fold)
    }

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

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F>
where
    F: FnMut(I::Item) -> U,
    U: IntoIterator<IntoIter: DoubleEndedIterator>,
{
    #[inline]
    fn next_back(&mut self) -> Option<U::Item> { self.inner.next_back() }

    #[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<Ok=Acc>
    {
        self.inner.try_rfold(init, fold)
    }

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

#[stable(feature = "fused", since = "1.26.0")]
impl<I, U, F> FusedIterator for FlatMap<I, U, F>
    where I: FusedIterator, U: IntoIterator, F: FnMut(I::Item) -> U {}

/// An iterator that flattens one level of nesting in an iterator of things
/// that can be turned into iterators.
///
/// This `struct` is created by the [`flatten`] method on [`Iterator`]. See its
/// documentation for more.
///
/// [`flatten`]: trait.Iterator.html#method.flatten
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "iterator_flatten", since = "1.29.0")]
pub struct Flatten<I: Iterator<Item: IntoIterator>> {
    inner: FlattenCompat<I, <I::Item as IntoIterator>::IntoIter>,
}

impl<I: Iterator<Item: IntoIterator>> Flatten<I> {
    pub(in super::super) fn new(iter: I) -> Flatten<I> {
        Flatten { inner: FlattenCompat::new(iter) }
    }
}

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> fmt::Debug for Flatten<I>
where
    I: fmt::Debug + Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: fmt::Debug + Iterator,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Flatten").field("inner", &self.inner).finish()
    }
}

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> Clone for Flatten<I>
where
    I: Clone + Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: Clone + Iterator,
{
    fn clone(&self) -> Self { Flatten { inner: self.inner.clone() } }
}

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> Iterator for Flatten<I>
where
    I: Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: Iterator,
{
    type Item = U::Item;

    #[inline]
    fn next(&mut self) -> Option<U::Item> { self.inner.next() }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) { self.inner.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<Ok=Acc>
    {
        self.inner.try_fold(init, fold)
    }

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

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> DoubleEndedIterator for Flatten<I>
where
    I: DoubleEndedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: DoubleEndedIterator,
{
    #[inline]
    fn next_back(&mut self) -> Option<U::Item> { self.inner.next_back() }

    #[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<Ok=Acc>
    {
        self.inner.try_rfold(init, fold)
    }

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

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> FusedIterator for Flatten<I>
where
    I: FusedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: Iterator,
{}

/// Real logic of both `Flatten` and `FlatMap` which simply delegate to
/// this type.
#[derive(Clone, Debug)]
struct FlattenCompat<I, U> {
    iter: I,
    frontiter: Option<U>,
    backiter: Option<U>,
}
impl<I, U> FlattenCompat<I, U> {
    /// Adapts an iterator by flattening it, for use in `flatten()` and `flat_map()`.
    fn new(iter: I) -> FlattenCompat<I, U> {
        FlattenCompat { iter, frontiter: None, backiter: None }
    }
}

impl<I, U> Iterator for FlattenCompat<I, U>
where
    I: Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: Iterator,
{
    type Item = U::Item;

    #[inline]
    fn next(&mut self) -> Option<U::Item> {
        loop {
            if let Some(ref mut inner) = self.frontiter {
                if let elt@Some(_) = inner.next() { return elt }
            }
            match self.iter.next() {
                None => return self.backiter.as_mut()?.next(),
                Some(inner) => self.frontiter = Some(inner.into_iter()),
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), U::size_hint);
        let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), U::size_hint);
        let lo = flo.saturating_add(blo);
        match (self.iter.size_hint(), fhi, bhi) {
            ((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(b)),
            _ => (lo, None)
        }
    }

    #[inline]
    fn try_fold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R where
        Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
    {
        #[inline]
        fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>(
            frontiter: &'a mut Option<T::IntoIter>,
            fold: &'a mut impl FnMut(Acc, T::Item) -> R,
        ) -> impl FnMut(Acc, T) -> R + 'a {
            move |acc, x| {
                let mut mid = x.into_iter();
                let r = mid.try_fold(acc, &mut *fold);
                *frontiter = Some(mid);
                r
            }
        }

        if let Some(ref mut front) = self.frontiter {
            init = front.try_fold(init, &mut fold)?;
        }
        self.frontiter = None;

        init = self.iter.try_fold(init, flatten(&mut self.frontiter, &mut fold))?;
        self.frontiter = None;

        if let Some(ref mut back) = self.backiter {
            init = back.try_fold(init, &mut fold)?;
        }
        self.backiter = None;

        Try::from_ok(init)
    }

    #[inline]
    fn fold<Acc, Fold>(self, init: Acc, ref mut fold: Fold) -> Acc
        where Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        #[inline]
        fn flatten<U: Iterator, Acc>(
            fold: &mut impl FnMut(Acc, U::Item) -> Acc,
        ) -> impl FnMut(Acc, U) -> Acc + '_ {
            move |acc, iter| iter.fold(acc, &mut *fold)
        }

        self.frontiter.into_iter()
            .chain(self.iter.map(IntoIterator::into_iter))
            .chain(self.backiter)
            .fold(init, flatten(fold))
    }
}

impl<I, U> DoubleEndedIterator for FlattenCompat<I, U>
where
    I: DoubleEndedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: DoubleEndedIterator,
{
    #[inline]
    fn next_back(&mut self) -> Option<U::Item> {
        loop {
            if let Some(ref mut inner) = self.backiter {
                if let elt@Some(_) = inner.next_back() { return elt }
            }
            match self.iter.next_back() {
                None => return self.frontiter.as_mut()?.next_back(),
                next => self.backiter = next.map(IntoIterator::into_iter),
            }
        }
    }

    #[inline]
    fn try_rfold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R where
        Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
    {
        #[inline]
        fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>(
            backiter: &'a mut Option<T::IntoIter>,
            fold: &'a mut impl FnMut(Acc, T::Item) -> R,
        ) -> impl FnMut(Acc, T) -> R + 'a where
            T::IntoIter: DoubleEndedIterator,
        {
            move |acc, x| {
                let mut mid = x.into_iter();
                let r = mid.try_rfold(acc, &mut *fold);
                *backiter = Some(mid);
                r
            }
        }

        if let Some(ref mut back) = self.backiter {
            init = back.try_rfold(init, &mut fold)?;
        }
        self.backiter = None;

        init = self.iter.try_rfold(init, flatten(&mut self.backiter, &mut fold))?;
        self.backiter = None;

        if let Some(ref mut front) = self.frontiter {
            init = front.try_rfold(init, &mut fold)?;
        }
        self.frontiter = None;

        Try::from_ok(init)
    }

    #[inline]
    fn rfold<Acc, Fold>(self, init: Acc, ref mut fold: Fold) -> Acc
        where Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        #[inline]
        fn flatten<U: DoubleEndedIterator, Acc>(
            fold: &mut impl FnMut(Acc, U::Item) -> Acc,
        ) -> impl FnMut(Acc, U) -> Acc + '_ {
            move |acc, iter| iter.rfold(acc, &mut *fold)
        }

        self.frontiter.into_iter()
            .chain(self.iter.map(IntoIterator::into_iter))
            .chain(self.backiter)
            .rfold(init, flatten(fold))
    }
}
<|endoftext|>


<commit_before>// Code for creating styled buffers

use crate::snippet::{Style, StyledString};

#[derive(Debug)]
pub struct StyledBuffer {
    text: Vec<Vec<char>>,
    styles: Vec<Vec<Style>>,
}

impl StyledBuffer {
    pub fn new() -> StyledBuffer {
        StyledBuffer {
            text: vec![],
            styles: vec![],
        }
    }

    fn replace_tabs(&mut self) {
        for (line_pos, line) in self.text.iter_mut().enumerate() {
            let mut tab_pos = vec![];
            for (pos, c) in line.iter().enumerate() {
                if *c == '\t' {
                    tab_pos.push(pos);
                }
            }
            // start with the tabs at the end of the line to replace them with 4 space chars
            for pos in tab_pos.iter().rev() {
                assert_eq!(line.remove(*pos), '\t');
                // fix the position of the style to match up after replacing the tabs
                let s = self.styles[line_pos].remove(*pos);
                for _ in 0..4 {
                    line.insert(*pos, ' ');
                    self.styles[line_pos].insert(*pos, s);
                }
            }
        }
    }

    pub fn render(&mut self) -> Vec<Vec<StyledString>> {
        let mut output: Vec<Vec<StyledString>> = vec![];
        let mut styled_vec: Vec<StyledString> = vec![];

        // before we render, replace tabs with spaces
        self.replace_tabs();

        for (row, row_style) in self.text.iter().zip(&self.styles) {
            let mut current_style = Style::NoStyle;
            let mut current_text = String::new();

            for (&c, &s) in row.iter().zip(row_style) {
                if s != current_style {
                    if !current_text.is_empty() {
                        styled_vec.push(StyledString {
                            text: current_text,
                            style: current_style,
                        });
                    }
                    current_style = s;
                    current_text = String::new();
                }
                current_text.push(c);
            }
            if !current_text.is_empty() {
                styled_vec.push(StyledString {
                    text: current_text,
                    style: current_style,
                });
            }

            // We're done with the row, push and keep going
            output.push(styled_vec);

            styled_vec = vec![];
        }

        output
    }

    fn ensure_lines(&mut self, line: usize) {
        while line >= self.text.len() {
            self.text.push(vec![]);
            self.styles.push(vec![]);
        }
    }

    pub fn putc(&mut self, line: usize, col: usize, chr: char, style: Style) {
        self.ensure_lines(line);
        if col < self.text[line].len() {
            self.text[line][col] = chr;
            self.styles[line][col] = style;
        } else {
            let mut i = self.text[line].len();
            while i < col {
                self.text[line].push(' ');
                self.styles[line].push(Style::NoStyle);
                i += 1;
            }
            self.text[line].push(chr);
            self.styles[line].push(style);
        }
    }

    pub fn puts(&mut self, line: usize, col: usize, string: &str, style: Style) {
        let mut n = col;
        for c in string.chars() {
            self.putc(line, n, c, style);
            n += 1;
        }
    }

    pub fn prepend(&mut self, line: usize, string: &str, style: Style) {
        self.ensure_lines(line);
        let string_len = string.len();

        // Push the old content over to make room for new content
        for _ in 0..string_len {
            self.styles[line].insert(0, Style::NoStyle);
            self.text[line].insert(0, ' ');
        }

        self.puts(line, 0, string, style);
    }

    pub fn append(&mut self, line: usize, string: &str, style: Style) {
        if line >= self.text.len() {
            self.puts(line, 0, string, style);
        } else {
            let col = self.text[line].len();
            self.puts(line, col, string, style);
        }
    }

    pub fn num_lines(&self) -> usize {
        self.text.len()
    }

    pub fn set_style_range(&mut self,
                           line: usize,
                           col_start: usize,
                           col_end: usize,
                           style: Style,
                           overwrite: bool) {
        for col in col_start..col_end {
            self.set_style(line, col, style, overwrite);
        }
    }

    pub fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) {
        if let Some(ref mut line) = self.styles.get_mut(line) {
            if let Some(s) = line.get_mut(col) {
                if *s == Style::NoStyle || *s == Style::Quotation || overwrite {
                    *s = style;
                }
            }
        }
    }
}
<commit_msg>Rollup merge of #65120 - AnthonyMikh:fix_65119, r=estebank<commit_after>// Code for creating styled buffers

use crate::snippet::{Style, StyledString};

#[derive(Debug)]
pub struct StyledBuffer {
    text: Vec<Vec<char>>,
    styles: Vec<Vec<Style>>,
}

impl StyledBuffer {
    pub fn new() -> StyledBuffer {
        StyledBuffer {
            text: vec![],
            styles: vec![],
        }
    }

    fn replace_tabs(&mut self) {
        for (line_pos, line) in self.text.iter_mut().enumerate() {
            let mut tab_pos = vec![];
            for (pos, c) in line.iter().enumerate() {
                if *c == '\t' {
                    tab_pos.push(pos);
                }
            }
            // start with the tabs at the end of the line to replace them with 4 space chars
            for pos in tab_pos.iter().rev() {
                assert_eq!(line.remove(*pos), '\t');
                // fix the position of the style to match up after replacing the tabs
                let s = self.styles[line_pos].remove(*pos);
                for _ in 0..4 {
                    line.insert(*pos, ' ');
                    self.styles[line_pos].insert(*pos, s);
                }
            }
        }
    }

    pub fn render(&mut self) -> Vec<Vec<StyledString>> {
        let mut output: Vec<Vec<StyledString>> = vec![];
        let mut styled_vec: Vec<StyledString> = vec![];

        // before we render, replace tabs with spaces
        self.replace_tabs();

        for (row, row_style) in self.text.iter().zip(&self.styles) {
            let mut current_style = Style::NoStyle;
            let mut current_text = String::new();

            for (&c, &s) in row.iter().zip(row_style) {
                if s != current_style {
                    if !current_text.is_empty() {
                        styled_vec.push(StyledString {
                            text: current_text,
                            style: current_style,
                        });
                    }
                    current_style = s;
                    current_text = String::new();
                }
                current_text.push(c);
            }
            if !current_text.is_empty() {
                styled_vec.push(StyledString {
                    text: current_text,
                    style: current_style,
                });
            }

            // We're done with the row, push and keep going
            output.push(styled_vec);

            styled_vec = vec![];
        }

        output
    }

    fn ensure_lines(&mut self, line: usize) {
        while line >= self.text.len() {
            self.text.push(vec![]);
            self.styles.push(vec![]);
        }
    }

    pub fn putc(&mut self, line: usize, col: usize, chr: char, style: Style) {
        self.ensure_lines(line);
        if col < self.text[line].len() {
            self.text[line][col] = chr;
            self.styles[line][col] = style;
        } else {
            let mut i = self.text[line].len();
            while i < col {
                self.text[line].push(' ');
                self.styles[line].push(Style::NoStyle);
                i += 1;
            }
            self.text[line].push(chr);
            self.styles[line].push(style);
        }
    }

    pub fn puts(&mut self, line: usize, col: usize, string: &str, style: Style) {
        let mut n = col;
        for c in string.chars() {
            self.putc(line, n, c, style);
            n += 1;
        }
    }

    pub fn prepend(&mut self, line: usize, string: &str, style: Style) {
        self.ensure_lines(line);
        let string_len = string.chars().count();

        // Push the old content over to make room for new content
        for _ in 0..string_len {
            self.styles[line].insert(0, Style::NoStyle);
            self.text[line].insert(0, ' ');
        }

        self.puts(line, 0, string, style);
    }

    pub fn append(&mut self, line: usize, string: &str, style: Style) {
        if line >= self.text.len() {
            self.puts(line, 0, string, style);
        } else {
            let col = self.text[line].len();
            self.puts(line, col, string, style);
        }
    }

    pub fn num_lines(&self) -> usize {
        self.text.len()
    }

    pub fn set_style_range(&mut self,
                           line: usize,
                           col_start: usize,
                           col_end: usize,
                           style: Style,
                           overwrite: bool) {
        for col in col_start..col_end {
            self.set_style(line, col, style, overwrite);
        }
    }

    pub fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) {
        if let Some(ref mut line) = self.styles.get_mut(line) {
            if let Some(s) = line.get_mut(col) {
                if *s == Style::NoStyle || *s == Style::Quotation || overwrite {
                    *s = style;
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>// Kevin Cantu
// basic Rust function behavior

/*
               native fn       fn~        fn@            fn&

closures       none            unique/     boxed         stack/block
                               sendable

closure        n/a            immutable   immutable      mutable
mutability

statmt def     yes            no          no             no          e.g., fn xyz () {...}

let def        no             yes         yes            no          e.g., let xyz = fn@ () {...};

{||} def       yes            yes         yes            yes         e.g., abc({|| ...});

can also be    ~,@,&          &           &
used _as_

*/

// why do the types, fn(), fn~(), fn@(), and fn&() require parens?
// why isn't there a way to name a fn&?
// why isn't there a top level equivalent to fn for each of the others?

use std;

#[test]
fn testFunctionClosure () {

   let fruit = "banana";

   // top level fn syntax
   fn innerFunction1 () {
      let fruit = "orange";   // commenting this out leads to an error
                              // (does not make a fn& with closure)

      assert fruit == "orange";
   }

/* COMPILER ERROR
   // let fn syntax
   let innerFunction2 = native fn () {
      let fruit = "orange";
      assert fruit == "orange";
   };
*/

   innerFunction1 ();
//   innerFunction2 ();
   assert fruit == "banana";
}

#[test]
fn testSendfnClosure () {

   let fruit = "banana";

   // let sendfn syntax
   let innerSendfn = fn~ () {
      assert fruit == "banana";

      // overwrite the value
      let fruit = "mango";
      assert fruit == "mango";
   };

   innerSendfn ();

   assert fruit == "banana";
}

#[test]
fn testLambdaClosure () {

   let fruit = "banana";

   // let lambda syntax
   let innerLambda = fn@ () {
      assert fruit == "banana";

      // overwrite the value
      let fruit = "tangerine";
      assert fruit == "tangerine";
   };

   innerLambda ();

   assert fruit == "banana";
}

#[test]
fn testBlockClosure () {

   let fruit = "banana";

   fn run1 ( b : fn& () ) {
      let i = 1u;
      while (i > 0u) { i = 0u;
         b ();
      }
   }

   // callee explicit fn& syntax
   // (Is there no way to define a fn&
   // before positioning it as an argument?)
   run1 ( fn& () {
      assert fruit == "banana";

      // overwrite the value
      fruit = "pineapple";
      assert fruit == "pineapple";
   });

   assert fruit == "pineapple";
}

fn message () { (); }
fn usingFunction ( f : native fn() ) { f(); }
fn usingSendfn   ( f : fn~() ) { f(); }
fn usingLambda   ( f : fn@() ) { f(); }
fn usingBlock    ( f : fn& () ) { f(); }

#[test]
fn testFnTypes () {
   //let f1 = native fn     () { message (); }; // compiler error
   fn f1 () {
      message ();
   }
   let s1 = fn~ () { message (); };
   let l1 = fn@ () { message (); };

   usingFunction (f1);
   //usingFunction (s1);                        // compiler error
   //usingFunction (l1);                        // compiler error
   //usingFunction (fn& () { message ();});   // compiler error
   usingFunction ({|| message ();});

   usingSendfn (f1);
   usingSendfn (s1);
   //usingSendfn (l1);                          // compiler error
   //usingSendfn (fn& () { message ();});     // compiler error
   usingSendfn ({|| message ();});

   usingLambda (f1);
   //usingLambda (s1);                          // compiler error
   usingLambda (l1);
   //usingLambda (fn& () { message ();});     // compiler error
   usingLambda ({|| message ();});

   usingBlock (f1);
   usingBlock (s1);
   usingBlock (l1);
   usingBlock (fn& () { message ();});
   usingBlock ({|| message ();});
}

fn main () {
   std::io::println ("Running...");
}

<commit_msg>updated function basics test<commit_after>// Kevin Cantu
// basic Rust function behavior

/*
               native fn       fn~        fn@            fn&

closures       none            unique/     boxed         stack/block
                               sendable

closure        n/a            immutable   immutable      mutable
mutability

statmt def     yes            no          no             no          e.g., fn xyz () {...}

let def        no             yes         yes            no          e.g., let xyz = fn@ () {...};

{||} def       yes            yes         yes            yes         e.g., abc({|| ...});

can also be    fn~,fn@,fn&    fn          fn             fn
used _as_

*/

// Why do the types native fn(), fn~(), fn@(), and fn&() require parens?
// Why isn't there a way to name a fn&?

use std;

fn message () { (); }

#[cfg(test)]
mod native {

   #[test]
   fn statement () {
      let fruit = "banana";

      fn innerFunction1 () {
         let fruit = "orange";   // commenting this out leads to an error
                                 // (does not make a fn& with closure)
         assert fruit == "orange";
      }

      innerFunction1 ();
      assert fruit == "banana";
   }

/*
   #[test]
   fn expression () {
      fail
      let innerFunction2 = native fn () {
         let fruit = "orange";
         assert fruit == "orange";
      };

      innerFunction2 ();
      assert fruit == "banana";
   }
*/

   fn call ( f : native fn() ) { f(); }

   #[test]
   fn with_native () {
      fn f1 () { message (); }
      call(f1);
   }

/*
   #[test]
   // compiler error
   fn with_sendfn () {
      let s1 = fn~ () { message (); };
      call (s1);
   }
*/

/*
   #[test]
   // compiler error
   fn with_lambda () {
      let l1 = fn@ () { message (); };
      call (l1);                        // compiler error
   }
*/

/*
   #[test]
   // compiler error
   fn with_block () {
      call (fn& () { message ();});   // compiler error
   }
*/

   #[test]
   fn with_literal () {
      call ({|| message ();});
   }
}

#[cfg(test)]
mod sendfn {
   #[test]
   fn expression () {
      let fruit = "banana";

      // let sendfn syntax
      let innerSendfn = fn~ () {
         assert fruit == "banana";

         // overwrite the value
         let fruit = "mango";
         assert fruit == "mango";
      };

      innerSendfn ();

      assert fruit == "banana";
   }

   #[test]
   fn statement () {
   }

   fn call ( f : fn~() ) { f(); }

   #[test]
   fn with_native () {
      fn f1 () { message (); }
      call(f1);
   }

   #[test]
   fn with_sendfn () {
      let s1 = fn~ () { message (); };
      call (s1);
   }

/*
   #[test]
   fn with_lambda () {
      let l1 = fn@ () { message (); };
      call (l1);
   }

   #[test]
   fn with_block () {
      call (fn& () { message ();});
   }
*/

   #[test]
   fn with_literal () {
      call ({|| message ();});
   }
}

#[cfg(test)]
mod lambda {
   fn call   ( f : fn@() ) { f(); }

   #[test]
   fn expression () {

      let fruit = "banana";

      // let lambda syntax
      let innerLambda = fn@ () {
         assert fruit == "banana";

         // overwrite the value
         let fruit = "tangerine";
         assert fruit == "tangerine";
      };

      innerLambda ();

      assert fruit == "banana";
   }

   #[test]
   fn with_native () {
      fn f1 () { message (); }

      call (f1);
   }

/*
   #[test]
   fn with_sendfn () {
      let s1 = fn~ () { message (); };
      call (s1);                          // compiler error
   }
*/

   #[test]
   fn with_lambda () {
      let l1 = fn@ () { message (); };
      call (l1);
   }

/*
   #[test]
   fn with_block () {
      call (fn& () { message ();});     // compiler error
   }
*/

   #[test]
   fn with_literal () {
      call ({|| message ();});
   }
}

#[cfg(test)]
mod block {
   fn call    ( f : fn& () ) { f(); }

   #[test]
   fn expression () {

      let fruit = "banana";

      fn run1 ( b : fn& () ) {
         let i = 1u;
         while (i > 0u) { i = 0u;
            b ();
         }
      }

      // callee explicit fn& syntax
      // (Is there no way to define a fn&
      // before positioning it as an argument?)
      run1 ( fn& () {
         assert fruit == "banana";

         // overwrite the value
         fruit = "pineapple";
         assert fruit == "pineapple";
      });

      assert fruit == "pineapple";
   }

   #[test]
   fn with_native () {
      fn f1 () { message (); }
      call (f1);
   }

/*
   #[test]
   fn with_sendfn () {
      let s1 = fn~ () { message (); };
      //call (s1);
   }

   #[test]
   fn with_lambda () {
      let l1 = fn@ () { message (); };
      //call (l1);
   }
*/

   #[test]
   fn with_block () {
      call (fn& () { message ();});
   }

   #[test]
   fn with_literal () {
      call ({|| message ();});
   }

}

#[cfg(test)]
mod fn {
   fn call       ( f : fn () ) { f(); }

   #[test]
   fn with_native () {
      fn f1 () { message (); }
      call (f1);
   }

   #[test]
   fn with_sendfn () {
      let s1 = fn~ () { message (); };
      call (s1);
   }

   #[test]
   fn with_lambda () {
      let l1 = fn@ () { message (); };
      call (l1);
   }

   #[test]
   fn with_block () {
      call (fn& () { message ();});
   }

   #[test]
   fn with_literal () {
      call ({|| message ();});
   }
}

fn main () {
   std::io::println ("Running...");
}

<|endoftext|>


<commit_before>use std::time::Duration;

#[derive(Default, Clone)]
struct FrameInfo {
    frame: u32,
    elapsed: Duration,
}

impl FrameInfo {
    fn new(frame: u32, elapsed: Duration) -> Self {
        FrameInfo {
            frame: frame,
            elapsed: elapsed,
        }
    }

    fn elapse(&self, elapsed: Duration) -> Self {
        FrameInfo::new(self.frame, elapsed)
    }
}

#[derive(Clone)]
pub struct FrameAnimator {
    max: u32,
    duration: Duration,
    repeat: bool,
    current: Option<FrameInfo>,
}

impl FrameAnimator {
    pub fn new(max: u32, duration: Duration, repeat: bool) -> FrameAnimator {
        FrameAnimator {
            max: max,
            duration: duration,
            repeat: repeat,
            current: None,
        }
    }

    pub fn started(max: u32, duration: Duration, repeat: bool) -> FrameAnimator {
        FrameAnimator {
            max: max,
            duration: duration,
            repeat: repeat,
            current: Some(Default::default()),
        }
    }

    pub fn start(&mut self) {
        self.current = Some(Default::default());
    }

    pub fn frame(&self) -> Option<u32> {
        self.current.as_ref().map(|c| c.frame)
    }

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

    pub fn animate(&mut self, delta: Duration) {
        self.current = self.current.as_ref().map_or(Some(Default::default()),
                                                    |f| self.next(f.frame, f.elapsed + delta));
    }

    fn next(&self, current: u32, elapsed: Duration) -> Option<FrameInfo> {
        let mut frame = current;
        let mut remaining = elapsed;
        while remaining >= self.duration {
            frame += 1;
            remaining = remaining - self.duration;
        }
        if frame < self.max || self.repeat {
            Some(FrameInfo::new(frame % self.max, remaining))
        } else {
            None
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn new_animator() {
        let animator = FrameAnimator::new(3, Duration::from_secs(5), true);
        assert!(animator.frame().is_none());
    }

    #[test]
    fn started_animator() {
        let animator = FrameAnimator::started(3, Duration::from_secs(5), true);
        assert!(animator.frame().is_some());
        assert_eq!(animator.frame().unwrap(), 0);
    }

    #[test]
    fn start() {
        let mut animator = FrameAnimator::new(3, Duration::from_secs(5), true);
        animator.start();
        assert!(animator.frame().is_some());
        assert_eq!(animator.frame().unwrap(), 0);
    }

    #[test]
    fn animate() {
        let mut animator = FrameAnimator::started(6, Duration::from_secs(5), true);

        animator.animate(Duration::from_secs(5));
        assert_eq!(animator.frame().unwrap(), 1);

        animator.animate(Duration::from_secs(3));
        assert_eq!(animator.frame().unwrap(), 1);

        animator.animate(Duration::from_secs(4));
        assert_eq!(animator.frame().unwrap(), 2);

        animator.animate(Duration::from_secs(4));
        assert_eq!(animator.frame().unwrap(), 3);

        animator.animate(Duration::from_secs(10));
        assert_eq!(animator.frame().unwrap(), 5);
    }

    #[test]
    fn repeat() {
        let mut animator = FrameAnimator::started(2, Duration::from_secs(2), true);

        animator.animate(Duration::from_secs(2));
        assert_eq!(animator.frame().unwrap(), 1);

        animator.animate(Duration::from_secs(2));
        assert_eq!(animator.frame().unwrap(), 0);

        animator.animate(Duration::from_secs(4));
        assert_eq!(animator.frame().unwrap(), 0);
    }

    #[test]
    fn no_repeat() {
        let mut animator = FrameAnimator::started(2, Duration::from_secs(2), false);

        animator.animate(Duration::from_secs(2));
        assert_eq!(animator.frame().unwrap(), 1);

        animator.animate(Duration::from_secs(3));
        assert!(animator.frame().is_none());

        animator.start();
        animator.animate(Duration::from_secs(1));
        assert_eq!(animator.frame().unwrap(), 0);

        animator.animate(Duration::from_secs(3));
        assert!(animator.frame().is_none())
    }
}
<commit_msg>improving tests<commit_after>use std::time::Duration;

#[derive(Default, Clone)]
struct FrameInfo {
    frame: u32,
    elapsed: Duration,
}

impl FrameInfo {
    fn new(frame: u32, elapsed: Duration) -> Self {
        FrameInfo {
            frame: frame,
            elapsed: elapsed,
        }
    }
}

#[derive(Clone)]
pub struct FrameAnimator {
    max: u32,
    duration: Duration,
    repeat: bool,
    current: Option<FrameInfo>,
}

impl FrameAnimator {
    pub fn new(max: u32, duration: Duration, repeat: bool) -> FrameAnimator {
        FrameAnimator {
            max: max,
            duration: duration,
            repeat: repeat,
            current: None,
        }
    }

    pub fn started(max: u32, duration: Duration, repeat: bool) -> FrameAnimator {
        FrameAnimator {
            max: max,
            duration: duration,
            repeat: repeat,
            current: Some(Default::default()),
        }
    }

    pub fn start(&mut self) {
        self.current = Some(Default::default());
    }

    pub fn frame(&self) -> Option<u32> {
        self.current.as_ref().map(|c| c.frame)
    }

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

    pub fn animate(&mut self, delta: Duration) {
        self.current = self.current.as_ref().map_or(Some(Default::default()),
                                                    |f| self.next(f.frame, f.elapsed + delta));
    }

    fn next(&self, current: u32, elapsed: Duration) -> Option<FrameInfo> {
        let mut frame = current;
        let mut remaining = elapsed;
        while remaining >= self.duration {
            frame += 1;
            remaining = remaining - self.duration;
        }
        if frame < self.max || self.repeat {
            Some(FrameInfo::new(frame % self.max, remaining))
        } else {
            None
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn new_animator() {
        let animator = FrameAnimator::new(3, Duration::from_secs(5), true);
        assert!(animator.frame().is_none());
    }

    #[test]
    fn started_animator() {
        let animator = FrameAnimator::started(3, Duration::from_secs(5), true);
        assert!(animator.frame().is_some());
        assert_eq!(animator.frame().unwrap(), 0);
    }

    #[test]
    fn start() {
        let mut animator = FrameAnimator::new(3, Duration::from_secs(5), true);
        animator.start();
        assert!(animator.frame().is_some());
        assert_eq!(animator.frame().unwrap(), 0);
    }

    #[test]
    fn animate() {
        let mut animator = FrameAnimator::started(6, Duration::from_secs(5), true);

        animator.animate(Duration::from_secs(5));
        assert_eq!(animator.frame().unwrap(), 1);

        animator.animate(Duration::from_secs(3));
        assert_eq!(animator.frame().unwrap(), 1);

        animator.animate(Duration::from_secs(4));
        assert_eq!(animator.frame().unwrap(), 2);

        animator.animate(Duration::from_secs(4));
        assert_eq!(animator.frame().unwrap(), 3);

        animator.animate(Duration::from_secs(10));
        assert_eq!(animator.frame().unwrap(), 5);
    }

    #[test]
    fn repeat() {
        let mut animator = FrameAnimator::started(2, Duration::from_secs(2), true);

        animator.animate(Duration::from_secs(2));
        assert_eq!(animator.frame().unwrap(), 1);

        animator.animate(Duration::from_secs(3));
        assert_eq!(animator.frame().unwrap(), 0);

        animator.animate(Duration::from_secs(1));
        assert_eq!(animator.frame().unwrap(), 1);
    }

    #[test]
    fn no_repeat() {
        let mut animator = FrameAnimator::started(2, Duration::from_secs(2), false);

        animator.animate(Duration::from_secs(2));
        assert_eq!(animator.frame().unwrap(), 1);

        animator.animate(Duration::from_secs(3));
        assert!(animator.frame().is_none());

        animator.start();
        animator.animate(Duration::from_secs(1));
        assert_eq!(animator.frame().unwrap(), 0);

        animator.animate(Duration::from_secs(3));
        assert!(animator.frame().is_none())
    }
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::sync::{Arc, Mutex, Weak};

use {CreationError, MouseCursor, WindowAttributes};
use dpi::{LogicalPosition, LogicalSize};
use platform::MonitorId as PlatformMonitorId;
use window::MonitorId as RootMonitorId;

use sctk::window::{BasicFrame, Event as WEvent, Window as SWindow};
use sctk::reexports::client::{Display, Proxy};
use sctk::reexports::client::protocol::{wl_seat, wl_surface, wl_output};
use sctk::reexports::client::protocol::wl_compositor::RequestsTrait as CompositorRequests;
use sctk::reexports::client::protocol::wl_surface::RequestsTrait as SurfaceRequests;
use sctk::output::OutputMgr;

use super::{make_wid, EventsLoop, MonitorId, WindowId};
use platform::platform::wayland::event_loop::{get_available_monitors, get_primary_monitor};

pub struct Window {
    surface: Proxy<wl_surface::WlSurface>,
    frame: Arc<Mutex<SWindow<BasicFrame>>>,
    monitors: Arc<Mutex<MonitorList>>, // Monitors this window is currently on
    outputs: OutputMgr, // Access to info for all monitors
    size: Arc<Mutex<(u32, u32)>>,
    kill_switch: (Arc<Mutex<bool>>, Arc<Mutex<bool>>),
    display: Arc<Display>,
    need_frame_refresh: Arc<Mutex<bool>>,
}

impl Window {
    pub fn new(evlp: &EventsLoop, attributes: WindowAttributes) -> Result<Window, CreationError> {
        // TODO: Update for new DPI API
        //let (width, height) = attributes.dimensions.unwrap_or((800, 600));
        let (width, height) = (64, 64);
        // Create the window
        let size = Arc::new(Mutex::new((width, height)));

        // monitor tracking
        let monitor_list = Arc::new(Mutex::new(MonitorList::new()));

        let surface = evlp.env.compositor.create_surface().unwrap().implement({
            let list = monitor_list.clone();
            let omgr = evlp.env.outputs.clone();
            let window_store = evlp.store.clone();
            move |event, surface: Proxy<wl_surface::WlSurface>| match event {
                wl_surface::Event::Enter { output } => {
                    let dpi_change = list.lock().unwrap().add_output(MonitorId {
                        proxy: output,
                        mgr: omgr.clone(),
                    });
                    if let Some(dpi) = dpi_change {
                        if surface.version() >= 3 {
                            // without version 3 we can't be dpi aware
                            window_store.lock().unwrap().dpi_change(&surface, dpi);
                            surface.set_buffer_scale(dpi);
                        }
                    }
                },
                wl_surface::Event::Leave { output } => {
                    let dpi_change = list.lock().unwrap().del_output(&output);
                    if let Some(dpi) = dpi_change {
                        if surface.version() >= 3 {
                            // without version 3 we can't be dpi aware
                            window_store.lock().unwrap().dpi_change(&surface, dpi);
                            surface.set_buffer_scale(dpi);
                        }
                    }
                }
            }
        });

        let window_store = evlp.store.clone();
        let my_surface = surface.clone();
        let mut frame = SWindow::<BasicFrame>::init(
            surface.clone(),
            (width, height),
            &evlp.env.compositor,
            &evlp.env.subcompositor,
            &evlp.env.shm,
            &evlp.env.shell,
            move |event, ()| match event {
                WEvent::Configure { new_size, .. } => {
                    let mut store = window_store.lock().unwrap();
                    for window in &mut store.windows {
                        if window.surface.equals(&my_surface) {
                            window.newsize = new_size;
                            window.need_refresh = true;
                            *(window.need_frame_refresh.lock().unwrap()) = true;
                            return;
                        }
                    }
                }
                WEvent::Refresh => {
                    let store = window_store.lock().unwrap();
                    for window in &store.windows {
                        if window.surface.equals(&my_surface) {
                            *(window.need_frame_refresh.lock().unwrap()) = true;
                            return;
                        }
                    }
                }
                WEvent::Close => {
                    let mut store = window_store.lock().unwrap();
                    for window in &mut store.windows {
                        if window.surface.equals(&my_surface) {
                            window.closed = true;
                            return;
                        }
                    }
                }
            },
        ).unwrap();

        for &(_, ref seat) in evlp.seats.lock().unwrap().iter() {
            frame.new_seat(seat);
        }

        // Check for fullscreen requirements
        if let Some(RootMonitorId {
            inner: PlatformMonitorId::Wayland(ref monitor_id),
        }) = attributes.fullscreen
        {
            frame.set_fullscreen(Some(&monitor_id.proxy));
        } else if attributes.maximized {
            frame.set_maximized();
        }

        frame.set_resizable(attributes.resizable);

        // set decorations
        frame.set_decorate(attributes.decorations);

        // min-max dimensions
        // TODO: Update for new DPI API
        //frame.set_min_size(attributes.min_dimensions);
        //frame.set_max_size(attributes.max_dimensions);

        let kill_switch = Arc::new(Mutex::new(false));
        let need_frame_refresh = Arc::new(Mutex::new(true));
        let frame = Arc::new(Mutex::new(frame));

        evlp.store.lock().unwrap().windows.push(InternalWindow {
            closed: false,
            newsize: None,
            size: size.clone(),
            need_refresh: false,
            need_frame_refresh: need_frame_refresh.clone(),
            surface: surface.clone(),
            kill_switch: kill_switch.clone(),
            frame: Arc::downgrade(&frame),
            current_dpi: 1,
            new_dpi: None,
        });
        evlp.evq.borrow_mut().sync_roundtrip().unwrap();

        Ok(Window {
            display: evlp.display.clone(),
            surface: surface,
            frame: frame,
            monitors: monitor_list,
            outputs: evlp.env.outputs.clone(),
            size: size,
            kill_switch: (kill_switch, evlp.cleanup_needed.clone()),
            need_frame_refresh: need_frame_refresh,
        })
    }

    #[inline]
    pub fn id(&self) -> WindowId {
        make_wid(&self.surface)
    }

    pub fn set_title(&self, title: &str) {
        self.frame.lock().unwrap().set_title(title.into());
    }

    #[inline]
    pub fn show(&self) {
        // TODO
    }

    #[inline]
    pub fn hide(&self) {
        // TODO
    }

    #[inline]
    pub fn get_position(&self) -> Option<LogicalPosition> {
        // Not possible with wayland
        None
    }

    #[inline]
    pub fn get_inner_position(&self) -> Option<LogicalPosition> {
        // Not possible with wayland
        None
    }

    #[inline]
    pub fn set_position(&self, _pos: LogicalPosition) {
        // Not possible with wayland
    }

    pub fn get_inner_size(&self) -> Option<LogicalSize> {
        Some(self.size.lock().unwrap().clone().into())
    }

    #[inline]
    pub fn get_outer_size(&self) -> Option<LogicalSize> {
        let (w, h) = self.size.lock().unwrap().clone();
        // let (w, h) = super::wayland_window::add_borders(w as i32, h as i32);
        Some((w, h).into())
    }

    #[inline]
    // NOTE: This will only resize the borders, the contents must be updated by the user
    pub fn set_inner_size(&self, size: LogicalSize) {
        let (w, h) = size.into();
        self.frame.lock().unwrap().resize(w, h);
        *(self.size.lock().unwrap()) = (w, h);
    }

    #[inline]
    pub fn set_min_dimensions(&self, dimensions: Option<LogicalSize>) {
        self.frame.lock().unwrap().set_min_size(dimensions.map(Into::into));
    }

    #[inline]
    pub fn set_max_dimensions(&self, dimensions: Option<LogicalSize>) {
        self.frame.lock().unwrap().set_max_size(dimensions.map(Into::into));
    }

    #[inline]
    pub fn set_resizable(&self, resizable: bool) {
        self.frame.lock().unwrap().set_resizable(resizable);
    }

    #[inline]
    pub fn hidpi_factor(&self) -> i32 {
        self.monitors.lock().unwrap().compute_hidpi_factor()
    }

    pub fn set_decorations(&self, decorate: bool) {
        self.frame.lock().unwrap().set_decorate(decorate);
        *(self.need_frame_refresh.lock().unwrap()) = true;
    }

    pub fn set_maximized(&self, maximized: bool) {
        if maximized {
            self.frame.lock().unwrap().set_maximized();
        } else {
            self.frame.lock().unwrap().unset_maximized();
        }
    }

    pub fn set_fullscreen(&self, monitor: Option<RootMonitorId>) {
        if let Some(RootMonitorId {
            inner: PlatformMonitorId::Wayland(ref monitor_id),
        }) = monitor
        {
            self.frame
                .lock()
                .unwrap()
                .set_fullscreen(Some(&monitor_id.proxy));
        } else {
            self.frame.lock().unwrap().unset_fullscreen();
        }
    }

    #[inline]
    pub fn set_cursor(&self, _cursor: MouseCursor) {
        // TODO
    }

    #[inline]
    pub fn hide_cursor(&self, _hide: bool) {
        // TODO: This isn't possible on Wayland yet
    }

    #[inline]
    pub fn grab_cursor(&self, _grab: bool) -> Result<(), String> {
        Err("Cursor grabbing is not yet possible on Wayland.".to_owned())
    }

    #[inline]
    pub fn set_cursor_position(&self, _pos: LogicalPosition) -> Result<(), String> {
        Err("Setting the cursor position is not yet possible on Wayland.".to_owned())
    }

    pub fn get_display(&self) -> &Display {
        &*self.display
    }

    pub fn get_surface(&self) -> &Proxy<wl_surface::WlSurface> {
        &self.surface
    }

    pub fn get_current_monitor(&self) -> MonitorId {
        // we don't know how much each monitor sees us so...
        // just return the most recent one ?
        let guard = self.monitors.lock().unwrap();
        guard.monitors.last().unwrap().clone()
    }

    pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
        get_available_monitors(&self.outputs)
    }

    pub fn get_primary_monitor(&self) -> MonitorId {
        get_primary_monitor(&self.outputs)
    }
}

impl Drop for Window {
    fn drop(&mut self) {
        *(self.kill_switch.0.lock().unwrap()) = true;
        *(self.kill_switch.1.lock().unwrap()) = true;
    }
}

/*
 * Internal store for windows
 */

struct InternalWindow {
    surface: Proxy<wl_surface::WlSurface>,
    newsize: Option<(u32, u32)>,
    size: Arc<Mutex<(u32, u32)>>,
    need_refresh: bool,
    need_frame_refresh: Arc<Mutex<bool>>,
    closed: bool,
    kill_switch: Arc<Mutex<bool>>,
    frame: Weak<Mutex<SWindow<BasicFrame>>>,
    current_dpi: i32,
    new_dpi: Option<i32>
}

pub struct WindowStore {
    windows: Vec<InternalWindow>,
}

impl WindowStore {
    pub fn new() -> WindowStore {
        WindowStore {
            windows: Vec::new(),
        }
    }

    pub fn find_wid(&self, surface: &Proxy<wl_surface::WlSurface>) -> Option<WindowId> {
        for window in &self.windows {
            if surface.equals(&window.surface) {
                return Some(make_wid(surface));
            }
        }
        None
    }

    pub fn cleanup(&mut self) -> Vec<WindowId> {
        let mut pruned = Vec::new();
        self.windows.retain(|w| {
            if *w.kill_switch.lock().unwrap() {
                // window is dead, cleanup
                pruned.push(make_wid(&w.surface));
                w.surface.destroy();
                false
            } else {
                true
            }
        });
        pruned
    }

    pub fn new_seat(&self, seat: &Proxy<wl_seat::WlSeat>) {
        for window in &self.windows {
            if let Some(w) = window.frame.upgrade() {
                w.lock().unwrap().new_seat(seat);
            }
        }
    }

    fn dpi_change(&mut self, surface: &Proxy<wl_surface::WlSurface>, new: i32) {
        for window in &mut self.windows {
            if surface.equals(&window.surface) {
                window.new_dpi = Some(new);
            }
        }
    }

    pub fn for_each<F>(&mut self, mut f: F)
    where
        F: FnMut(Option<(u32, u32)>, &mut (u32, u32), Option<i32>, bool, bool, bool, WindowId, Option<&mut SWindow<BasicFrame>>),
    {
        for window in &mut self.windows {
            let opt_arc = window.frame.upgrade();
            let mut opt_mutex_lock = opt_arc.as_ref().map(|m| m.lock().unwrap());
            f(
                window.newsize.take(),
                &mut *(window.size.lock().unwrap()),
                window.new_dpi,
                window.need_refresh,
                ::std::mem::replace(&mut *window.need_frame_refresh.lock().unwrap(), false),
                window.closed,
                make_wid(&window.surface),
                opt_mutex_lock.as_mut().map(|m| &mut **m),
            );
            if let Some(dpi) = window.new_dpi.take() {
                window.current_dpi = dpi;
            }
            window.need_refresh = false;
            // avoid re-spamming the event
            window.closed = false;
        }
    }
}

/*
 * Monitor list with some covenience method to compute DPI
 */

struct MonitorList {
    monitors: Vec<MonitorId>
}

impl MonitorList {
    fn new() -> MonitorList {
        MonitorList {
            monitors: Vec::new()
        }
    }

    fn compute_hidpi_factor(&self) -> i32 {
        let mut factor = 1;
        for monitor_id in &self.monitors {
            let monitor_dpi = monitor_id.get_hidpi_factor();
            if monitor_dpi > factor { factor = monitor_dpi; }
        }
        factor
    }

    fn add_output(&mut self, monitor: MonitorId) -> Option<i32> {
        let old_dpi = self.compute_hidpi_factor();
        let monitor_dpi = monitor.get_hidpi_factor();
        self.monitors.push(monitor);
        if monitor_dpi > old_dpi {
            Some(monitor_dpi)
        } else {
            None
        }
    }

    fn del_output(&mut self, output: &Proxy<wl_output::WlOutput>) -> Option<i32> {
        let old_dpi = self.compute_hidpi_factor();
        self.monitors.retain(|m| !m.proxy.equals(output));
        let new_dpi = self.compute_hidpi_factor();
        if new_dpi != old_dpi {
            Some(new_dpi)
        } else {
            None
        }
    }
}
<commit_msg>Wayland: Fix window creation dimensions (#577)<commit_after>use std::collections::VecDeque;
use std::sync::{Arc, Mutex, Weak};

use {CreationError, MouseCursor, WindowAttributes};
use dpi::{LogicalPosition, LogicalSize};
use platform::MonitorId as PlatformMonitorId;
use window::MonitorId as RootMonitorId;

use sctk::window::{BasicFrame, Event as WEvent, Window as SWindow};
use sctk::reexports::client::{Display, Proxy};
use sctk::reexports::client::protocol::{wl_seat, wl_surface, wl_output};
use sctk::reexports::client::protocol::wl_compositor::RequestsTrait as CompositorRequests;
use sctk::reexports::client::protocol::wl_surface::RequestsTrait as SurfaceRequests;
use sctk::output::OutputMgr;

use super::{make_wid, EventsLoop, MonitorId, WindowId};
use platform::platform::wayland::event_loop::{get_available_monitors, get_primary_monitor};

pub struct Window {
    surface: Proxy<wl_surface::WlSurface>,
    frame: Arc<Mutex<SWindow<BasicFrame>>>,
    monitors: Arc<Mutex<MonitorList>>, // Monitors this window is currently on
    outputs: OutputMgr, // Access to info for all monitors
    size: Arc<Mutex<(u32, u32)>>,
    kill_switch: (Arc<Mutex<bool>>, Arc<Mutex<bool>>),
    display: Arc<Display>,
    need_frame_refresh: Arc<Mutex<bool>>,
}

impl Window {
    pub fn new(evlp: &EventsLoop, attributes: WindowAttributes) -> Result<Window, CreationError> {
        let (width, height) = attributes.dimensions.map(Into::into).unwrap_or((800, 600));
        // Create the window
        let size = Arc::new(Mutex::new((width, height)));

        // monitor tracking
        let monitor_list = Arc::new(Mutex::new(MonitorList::new()));

        let surface = evlp.env.compositor.create_surface().unwrap().implement({
            let list = monitor_list.clone();
            let omgr = evlp.env.outputs.clone();
            let window_store = evlp.store.clone();
            move |event, surface: Proxy<wl_surface::WlSurface>| match event {
                wl_surface::Event::Enter { output } => {
                    let dpi_change = list.lock().unwrap().add_output(MonitorId {
                        proxy: output,
                        mgr: omgr.clone(),
                    });
                    if let Some(dpi) = dpi_change {
                        if surface.version() >= 3 {
                            // without version 3 we can't be dpi aware
                            window_store.lock().unwrap().dpi_change(&surface, dpi);
                            surface.set_buffer_scale(dpi);
                        }
                    }
                },
                wl_surface::Event::Leave { output } => {
                    let dpi_change = list.lock().unwrap().del_output(&output);
                    if let Some(dpi) = dpi_change {
                        if surface.version() >= 3 {
                            // without version 3 we can't be dpi aware
                            window_store.lock().unwrap().dpi_change(&surface, dpi);
                            surface.set_buffer_scale(dpi);
                        }
                    }
                }
            }
        });

        let window_store = evlp.store.clone();
        let my_surface = surface.clone();
        let mut frame = SWindow::<BasicFrame>::init(
            surface.clone(),
            (width, height),
            &evlp.env.compositor,
            &evlp.env.subcompositor,
            &evlp.env.shm,
            &evlp.env.shell,
            move |event, ()| match event {
                WEvent::Configure { new_size, .. } => {
                    let mut store = window_store.lock().unwrap();
                    for window in &mut store.windows {
                        if window.surface.equals(&my_surface) {
                            window.newsize = new_size;
                            window.need_refresh = true;
                            *(window.need_frame_refresh.lock().unwrap()) = true;
                            return;
                        }
                    }
                }
                WEvent::Refresh => {
                    let store = window_store.lock().unwrap();
                    for window in &store.windows {
                        if window.surface.equals(&my_surface) {
                            *(window.need_frame_refresh.lock().unwrap()) = true;
                            return;
                        }
                    }
                }
                WEvent::Close => {
                    let mut store = window_store.lock().unwrap();
                    for window in &mut store.windows {
                        if window.surface.equals(&my_surface) {
                            window.closed = true;
                            return;
                        }
                    }
                }
            },
        ).unwrap();

        for &(_, ref seat) in evlp.seats.lock().unwrap().iter() {
            frame.new_seat(seat);
        }

        // Check for fullscreen requirements
        if let Some(RootMonitorId {
            inner: PlatformMonitorId::Wayland(ref monitor_id),
        }) = attributes.fullscreen
        {
            frame.set_fullscreen(Some(&monitor_id.proxy));
        } else if attributes.maximized {
            frame.set_maximized();
        }

        frame.set_resizable(attributes.resizable);

        // set decorations
        frame.set_decorate(attributes.decorations);

        // min-max dimensions
        frame.set_min_size(attributes.min_dimensions.map(Into::into));
        frame.set_max_size(attributes.max_dimensions.map(Into::into));

        let kill_switch = Arc::new(Mutex::new(false));
        let need_frame_refresh = Arc::new(Mutex::new(true));
        let frame = Arc::new(Mutex::new(frame));

        evlp.store.lock().unwrap().windows.push(InternalWindow {
            closed: false,
            newsize: None,
            size: size.clone(),
            need_refresh: false,
            need_frame_refresh: need_frame_refresh.clone(),
            surface: surface.clone(),
            kill_switch: kill_switch.clone(),
            frame: Arc::downgrade(&frame),
            current_dpi: 1,
            new_dpi: None,
        });
        evlp.evq.borrow_mut().sync_roundtrip().unwrap();

        Ok(Window {
            display: evlp.display.clone(),
            surface: surface,
            frame: frame,
            monitors: monitor_list,
            outputs: evlp.env.outputs.clone(),
            size: size,
            kill_switch: (kill_switch, evlp.cleanup_needed.clone()),
            need_frame_refresh: need_frame_refresh,
        })
    }

    #[inline]
    pub fn id(&self) -> WindowId {
        make_wid(&self.surface)
    }

    pub fn set_title(&self, title: &str) {
        self.frame.lock().unwrap().set_title(title.into());
    }

    #[inline]
    pub fn show(&self) {
        // TODO
    }

    #[inline]
    pub fn hide(&self) {
        // TODO
    }

    #[inline]
    pub fn get_position(&self) -> Option<LogicalPosition> {
        // Not possible with wayland
        None
    }

    #[inline]
    pub fn get_inner_position(&self) -> Option<LogicalPosition> {
        // Not possible with wayland
        None
    }

    #[inline]
    pub fn set_position(&self, _pos: LogicalPosition) {
        // Not possible with wayland
    }

    pub fn get_inner_size(&self) -> Option<LogicalSize> {
        Some(self.size.lock().unwrap().clone().into())
    }

    #[inline]
    pub fn get_outer_size(&self) -> Option<LogicalSize> {
        let (w, h) = self.size.lock().unwrap().clone();
        // let (w, h) = super::wayland_window::add_borders(w as i32, h as i32);
        Some((w, h).into())
    }

    #[inline]
    // NOTE: This will only resize the borders, the contents must be updated by the user
    pub fn set_inner_size(&self, size: LogicalSize) {
        let (w, h) = size.into();
        self.frame.lock().unwrap().resize(w, h);
        *(self.size.lock().unwrap()) = (w, h);
    }

    #[inline]
    pub fn set_min_dimensions(&self, dimensions: Option<LogicalSize>) {
        self.frame.lock().unwrap().set_min_size(dimensions.map(Into::into));
    }

    #[inline]
    pub fn set_max_dimensions(&self, dimensions: Option<LogicalSize>) {
        self.frame.lock().unwrap().set_max_size(dimensions.map(Into::into));
    }

    #[inline]
    pub fn set_resizable(&self, resizable: bool) {
        self.frame.lock().unwrap().set_resizable(resizable);
    }

    #[inline]
    pub fn hidpi_factor(&self) -> i32 {
        self.monitors.lock().unwrap().compute_hidpi_factor()
    }

    pub fn set_decorations(&self, decorate: bool) {
        self.frame.lock().unwrap().set_decorate(decorate);
        *(self.need_frame_refresh.lock().unwrap()) = true;
    }

    pub fn set_maximized(&self, maximized: bool) {
        if maximized {
            self.frame.lock().unwrap().set_maximized();
        } else {
            self.frame.lock().unwrap().unset_maximized();
        }
    }

    pub fn set_fullscreen(&self, monitor: Option<RootMonitorId>) {
        if let Some(RootMonitorId {
            inner: PlatformMonitorId::Wayland(ref monitor_id),
        }) = monitor
        {
            self.frame
                .lock()
                .unwrap()
                .set_fullscreen(Some(&monitor_id.proxy));
        } else {
            self.frame.lock().unwrap().unset_fullscreen();
        }
    }

    #[inline]
    pub fn set_cursor(&self, _cursor: MouseCursor) {
        // TODO
    }

    #[inline]
    pub fn hide_cursor(&self, _hide: bool) {
        // TODO: This isn't possible on Wayland yet
    }

    #[inline]
    pub fn grab_cursor(&self, _grab: bool) -> Result<(), String> {
        Err("Cursor grabbing is not yet possible on Wayland.".to_owned())
    }

    #[inline]
    pub fn set_cursor_position(&self, _pos: LogicalPosition) -> Result<(), String> {
        Err("Setting the cursor position is not yet possible on Wayland.".to_owned())
    }

    pub fn get_display(&self) -> &Display {
        &*self.display
    }

    pub fn get_surface(&self) -> &Proxy<wl_surface::WlSurface> {
        &self.surface
    }

    pub fn get_current_monitor(&self) -> MonitorId {
        // we don't know how much each monitor sees us so...
        // just return the most recent one ?
        let guard = self.monitors.lock().unwrap();
        guard.monitors.last().unwrap().clone()
    }

    pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
        get_available_monitors(&self.outputs)
    }

    pub fn get_primary_monitor(&self) -> MonitorId {
        get_primary_monitor(&self.outputs)
    }
}

impl Drop for Window {
    fn drop(&mut self) {
        *(self.kill_switch.0.lock().unwrap()) = true;
        *(self.kill_switch.1.lock().unwrap()) = true;
    }
}

/*
 * Internal store for windows
 */

struct InternalWindow {
    surface: Proxy<wl_surface::WlSurface>,
    newsize: Option<(u32, u32)>,
    size: Arc<Mutex<(u32, u32)>>,
    need_refresh: bool,
    need_frame_refresh: Arc<Mutex<bool>>,
    closed: bool,
    kill_switch: Arc<Mutex<bool>>,
    frame: Weak<Mutex<SWindow<BasicFrame>>>,
    current_dpi: i32,
    new_dpi: Option<i32>
}

pub struct WindowStore {
    windows: Vec<InternalWindow>,
}

impl WindowStore {
    pub fn new() -> WindowStore {
        WindowStore {
            windows: Vec::new(),
        }
    }

    pub fn find_wid(&self, surface: &Proxy<wl_surface::WlSurface>) -> Option<WindowId> {
        for window in &self.windows {
            if surface.equals(&window.surface) {
                return Some(make_wid(surface));
            }
        }
        None
    }

    pub fn cleanup(&mut self) -> Vec<WindowId> {
        let mut pruned = Vec::new();
        self.windows.retain(|w| {
            if *w.kill_switch.lock().unwrap() {
                // window is dead, cleanup
                pruned.push(make_wid(&w.surface));
                w.surface.destroy();
                false
            } else {
                true
            }
        });
        pruned
    }

    pub fn new_seat(&self, seat: &Proxy<wl_seat::WlSeat>) {
        for window in &self.windows {
            if let Some(w) = window.frame.upgrade() {
                w.lock().unwrap().new_seat(seat);
            }
        }
    }

    fn dpi_change(&mut self, surface: &Proxy<wl_surface::WlSurface>, new: i32) {
        for window in &mut self.windows {
            if surface.equals(&window.surface) {
                window.new_dpi = Some(new);
            }
        }
    }

    pub fn for_each<F>(&mut self, mut f: F)
    where
        F: FnMut(Option<(u32, u32)>, &mut (u32, u32), Option<i32>, bool, bool, bool, WindowId, Option<&mut SWindow<BasicFrame>>),
    {
        for window in &mut self.windows {
            let opt_arc = window.frame.upgrade();
            let mut opt_mutex_lock = opt_arc.as_ref().map(|m| m.lock().unwrap());
            f(
                window.newsize.take(),
                &mut *(window.size.lock().unwrap()),
                window.new_dpi,
                window.need_refresh,
                ::std::mem::replace(&mut *window.need_frame_refresh.lock().unwrap(), false),
                window.closed,
                make_wid(&window.surface),
                opt_mutex_lock.as_mut().map(|m| &mut **m),
            );
            if let Some(dpi) = window.new_dpi.take() {
                window.current_dpi = dpi;
            }
            window.need_refresh = false;
            // avoid re-spamming the event
            window.closed = false;
        }
    }
}

/*
 * Monitor list with some covenience method to compute DPI
 */

struct MonitorList {
    monitors: Vec<MonitorId>
}

impl MonitorList {
    fn new() -> MonitorList {
        MonitorList {
            monitors: Vec::new()
        }
    }

    fn compute_hidpi_factor(&self) -> i32 {
        let mut factor = 1;
        for monitor_id in &self.monitors {
            let monitor_dpi = monitor_id.get_hidpi_factor();
            if monitor_dpi > factor { factor = monitor_dpi; }
        }
        factor
    }

    fn add_output(&mut self, monitor: MonitorId) -> Option<i32> {
        let old_dpi = self.compute_hidpi_factor();
        let monitor_dpi = monitor.get_hidpi_factor();
        self.monitors.push(monitor);
        if monitor_dpi > old_dpi {
            Some(monitor_dpi)
        } else {
            None
        }
    }

    fn del_output(&mut self, output: &Proxy<wl_output::WlOutput>) -> Option<i32> {
        let old_dpi = self.compute_hidpi_factor();
        self.monitors.retain(|m| !m.proxy.equals(output));
        let new_dpi = self.compute_hidpi_factor();
        if new_dpi != old_dpi {
            Some(new_dpi)
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>use clap::{App, Arg, ArgMatches};
use itertools::Itertools;

use CliResult;
use commands::Config;
use event::Event;

pub fn make_app<'a, 'b: 'a>(app: App<'a, 'b>) -> App<'a, 'b>
{
    app
        .about("sends an event to sentry")
        .arg(Arg::with_name("level")
             .value_name("LEVEL")
             .long("level")
             .short("l")
             .help("Set the log level. Defaults to error"))
        .arg(Arg::with_name("release")
             .value_name("RELEASE")
             .long("release")
             .short("r")
             .help("Set the release."))
        .arg(Arg::with_name("message")
             .value_name("MESSAGE")
             .long("message")
             .short("m")
             .multiple(true)
             .help("Set the message to log"))
        .arg(Arg::with_name("platform")
             .value_name("PLATFORM")
             .long("platform")
             .short("p")
             .help("Overrides the default 'other' platform"))
        .arg(Arg::with_name("tags")
             .value_name("TAG")
             .long("tag")
             .short("t")
             .multiple(true)
             .help("Adds a tag (key:value) to the event."))
        .arg(Arg::with_name("extra")
             .value_name("EXTRA")
             .long("extra")
             .short("e")
             .multiple(true)
             .help("Adds extra information (key:value) to the event."))
}

pub fn execute<'a>(matches: &ArgMatches<'a>, config: &Config) -> CliResult<()> {
    let mut event = Event::new();
    event.level = matches.value_of("level").unwrap_or("error").into();
    event.release = matches.value_of("release").map(|x| x.into());
    event.platform = matches.value_of("platform").unwrap_or("other").into();
    event.message = matches.values_of("message").map(|mut x| x.join("\n"));

    if let Some(tags) = matches.values_of("tags") {
        for tag in tags {
            let mut split = tag.splitn(2, ':');
            let key = split.next().ok_or("missing tag key")?;
            let value = split.next().ok_or("missing tag value")?;
            event.tags.insert(key.into(), value.into());
        }
    }

    if let Some(extra) = matches.values_of("tags") {
        for pair in extra {
            let mut split = pair.splitn(2, ':');
            let key = split.next().ok_or("missing extra key")?;
            let value = split.next().ok_or("missing extra value")?;
            event.extra.insert(key.into(), value.into());
        }
    }

    let event_id = config.send_event(&event)?;
    println!("Event sent: {}", event_id);
    Ok(())
}
<commit_msg>sentry -> Sentry<commit_after>use clap::{App, Arg, ArgMatches};
use itertools::Itertools;

use CliResult;
use commands::Config;
use event::Event;

pub fn make_app<'a, 'b: 'a>(app: App<'a, 'b>) -> App<'a, 'b>
{
    app
        .about("sends an event to Sentry")
        .arg(Arg::with_name("level")
             .value_name("LEVEL")
             .long("level")
             .short("l")
             .help("Set the log level. Defaults to error"))
        .arg(Arg::with_name("release")
             .value_name("RELEASE")
             .long("release")
             .short("r")
             .help("Set the release."))
        .arg(Arg::with_name("message")
             .value_name("MESSAGE")
             .long("message")
             .short("m")
             .multiple(true)
             .help("Set the message to log"))
        .arg(Arg::with_name("platform")
             .value_name("PLATFORM")
             .long("platform")
             .short("p")
             .help("Overrides the default 'other' platform"))
        .arg(Arg::with_name("tags")
             .value_name("TAG")
             .long("tag")
             .short("t")
             .multiple(true)
             .help("Adds a tag (key:value) to the event."))
        .arg(Arg::with_name("extra")
             .value_name("EXTRA")
             .long("extra")
             .short("e")
             .multiple(true)
             .help("Adds extra information (key:value) to the event."))
}

pub fn execute<'a>(matches: &ArgMatches<'a>, config: &Config) -> CliResult<()> {
    let mut event = Event::new();
    event.level = matches.value_of("level").unwrap_or("error").into();
    event.release = matches.value_of("release").map(|x| x.into());
    event.platform = matches.value_of("platform").unwrap_or("other").into();
    event.message = matches.values_of("message").map(|mut x| x.join("\n"));

    if let Some(tags) = matches.values_of("tags") {
        for tag in tags {
            let mut split = tag.splitn(2, ':');
            let key = split.next().ok_or("missing tag key")?;
            let value = split.next().ok_or("missing tag value")?;
            event.tags.insert(key.into(), value.into());
        }
    }

    if let Some(extra) = matches.values_of("tags") {
        for pair in extra {
            let mut split = pair.splitn(2, ':');
            let key = split.next().ok_or("missing extra key")?;
            let value = split.next().ok_or("missing extra value")?;
            event.extra.insert(key.into(), value.into());
        }
    }

    let event_id = config.send_event(&event)?;
    println!("Event sent: {}", event_id);
    Ok(())
}
<|endoftext|>


<commit_before>use bifrost::vector_clock::{StandardVectorClock, Relation};
use std::collections::{BTreeSet, HashMap};
use chashmap::{CHashMap, WriteGuard};
use ram::types::{Id};
use ram::cell::{Cell, ReadError, WriteError};
use server::NebServer;
use super::*;

pub struct CellMeta {
    read: Option<TransactionId>,
    write: Option<TransactionId>,
    owner: Option<TransactionId>, // transaction that owns the cell in Committing state
    waiting: BTreeSet<TransactionId>, // transactions that waiting for owner to finish
}

#[derive(Debug, Serialize, Deserialize)]
pub enum CellCommit {
    Write(Cell),
    Update(Cell),
    Remove(Id)
}

#[derive(Debug, Serialize, Deserialize)]
pub enum CellPrepare {
    Write(Id),
    Update(Id),
    Remove(Id)
}

#[derive(Debug, Eq, PartialEq)]
enum TransactionState {
    Started,
    Aborted,
    Committing,
    Committed
}

struct Transaction {
    server: u64,
    id: TransactionId,
    state: TransactionState
}

pub struct DataManager {
    cells: CHashMap<Id, CellMeta>,
    tnxs: CHashMap<TransactionId, Transaction>,
    server: Arc<NebServer>
}

service! {
    rpc read(server_id: u64, clock: StandardVectorClock, tid: TransactionId, id: Id) -> DataSiteResponse<TransactionExecResult<Cell, ReadError>>;

    // two phase commit
    rpc prepare(clock :StandardVectorClock, tid: TransactionId, cells: Vec<CellPrepare>) -> DataSiteResponse<bool>;
    rpc commit(clock :StandardVectorClock, tid: TransactionId, cells: Vec<CellCommit>) -> DataSiteResponse<bool>;

    rpc abort(clock :StandardVectorClock, tid: TransactionId) -> DataSiteResponse<()>;
}

dispatch_rpc_service_functions!(DataManager);

impl DataManager {
    fn local_clock(&self) -> StandardVectorClock {
        self.server.tnx_peer.clock.to_clock()
    }
    fn update_clock(&self, clock: &StandardVectorClock) {
        self.server.tnx_peer.clock.merge_with(clock);
    }
    fn get_transaction(&self, tid: &TransactionId, server: &u64) -> WriteGuard<TransactionId, Transaction> {
        if !self.tnxs.contains_key(tid) {
            self.tnxs.upsert(tid.clone(), ||{
                Transaction {
                    id: tid.clone(),
                    server: *server,
                    state: TransactionState::Started
                }
            }, |t|{});
        }
        match self.tnxs.get_mut(tid) {
            Some(tnx) => tnx,
            _ => self.get_transaction(tid, server) // it should be rare
        }
    }
    fn get_cell_meta(&self, id: &Id) -> WriteGuard<Id, CellMeta > {
        if !self.cells.contains_key(id) {
            self.cells.upsert(id.clone(), || {
                CellMeta {
                    read: None,
                    write: None,
                    owner: None,
                    waiting: BTreeSet::new()
                }
            }, |c|{});
        }
        match self.cells.get_mut(id) {
            Some(cell) => cell,
            _ => self.get_cell_meta(id)
        }
    }
    fn response_with<T>(&self, data: T)
        -> Result<DataSiteResponse<T>, ()>{
        Ok(DataSiteResponse::new(&self.server.tnx_peer, data))
    }
}

impl Service for DataManager {
    fn read(&self, server_id: &u64, clock: &StandardVectorClock, tid: &TransactionId, id: &Id)
        -> Result<DataSiteResponse<TransactionExecResult<Cell, ReadError>>, ()> {
        let local_clock = self.local_clock();
        self.update_clock(clock);
        let mut tnx = self.get_transaction(tid, server_id);
        let mut meta = self.get_cell_meta(id);
        let committing = meta.owner.is_some();
        let read_too_late = !meta.write.is_none() && match meta.write {
            Some(ref w) => w > tid,
            _ => false
        };
        if read_too_late { // not realizable
            return self.response_with(TransactionExecResult::Rejected);
        }
        if committing { // ts >= wt but committing, need to wait until it committed
            meta.waiting.insert(tid.clone());
            return self.response_with(TransactionExecResult::Wait);
        }
        let cell = match self.server.chunks.read_cell(id) {
            Ok(cell) => {cell}
            Err(read_error) => {
                // cannot read
                return self.response_with(TransactionExecResult::Error(read_error));
            }
        };
        let update_read = {
            meta.read.is_none() || match meta.read {
                Some(ref r) => r < tid,
                None => true
            }
        };
        if update_read {
            meta.read = Some(tid.clone())
        }
        self.response_with(TransactionExecResult::Accepted(cell))
    }
    fn prepare(&self, clock :&StandardVectorClock, tid: &TransactionId, cells: &Vec<CellPrepare>)
        -> Result<DataSiteResponse<bool>, ()> {
        let local_clock = self.local_clock();
        self.update_clock(clock);
        unimplemented!()
    }
    fn commit(&self, clock :&StandardVectorClock, tid: &TransactionId, cells: &Vec<CellCommit>)
        -> Result<DataSiteResponse<bool>, ()>  {
        let local_clock = self.local_clock();
        self.update_clock(clock);
        unimplemented!()
    }
    fn abort(&self, clock :&StandardVectorClock, tid: &TransactionId)
        -> Result<DataSiteResponse<()>, ()>  {
        let local_clock = self.local_clock();
        self.update_clock(clock);
        unimplemented!()
    }
}<commit_msg>prepare in data manager for writes<commit_after>use bifrost::vector_clock::{StandardVectorClock, Relation};
use std::collections::{BTreeSet, HashMap};
use chashmap::{CHashMap, WriteGuard};
use ram::types::{Id};
use ram::cell::{Cell, ReadError, WriteError};
use server::NebServer;
use super::*;

pub type CellMetaGuard <'a> = WriteGuard<'a, Id, CellMeta>;

pub struct CellMeta {
    read: TransactionId,
    write: TransactionId,
    owner: Option<TransactionId>, // transaction that owns the cell in Committing state
    waiting: BTreeSet<TransactionId>, // transactions that waiting for owner to finish
}

#[derive(Debug, Serialize, Deserialize)]
pub enum CellCommit {
    Write(Cell),
    Update(Cell),
    Remove(Id)
}

#[derive(Debug, Serialize, Deserialize)]
pub enum PrepareResult {
    Wait,
    Success,
    TransactionNotExisted,
    NotRealizable,
}

#[derive(Debug, Eq, PartialEq)]
enum TransactionState {
    Started,
    Aborted,
    Committing,
    Committed
}

struct Transaction {
    server: u64,
    id: TransactionId,
    state: TransactionState
}

pub struct DataManager {
    cells: CHashMap<Id, CellMeta>,
    tnxs: CHashMap<TransactionId, Transaction>,
    server: Arc<NebServer>
}

service! {
    rpc read(server_id: u64, clock: StandardVectorClock, tid: TransactionId, id: Id) -> DataSiteResponse<TransactionExecResult<Cell, ReadError>>;

    // two phase commit
    rpc prepare(clock :StandardVectorClock, tid: TransactionId, cell_ids: Vec<Id>) -> DataSiteResponse<PrepareResult>;
    rpc commit(clock :StandardVectorClock, tid: TransactionId, cells: Vec<CellCommit>) -> DataSiteResponse<bool>;

    rpc abort(clock :StandardVectorClock, tid: TransactionId) -> DataSiteResponse<()>;
}

dispatch_rpc_service_functions!(DataManager);

impl DataManager {
    fn local_clock(&self) -> StandardVectorClock {
        self.server.tnx_peer.clock.to_clock()
    }
    fn update_clock(&self, clock: &StandardVectorClock) {
        self.server.tnx_peer.clock.merge_with(clock);
    }
    fn get_transaction(&self, tid: &TransactionId, server: &u64) -> WriteGuard<TransactionId, Transaction> {
        if !self.tnxs.contains_key(tid) {
            self.tnxs.upsert(tid.clone(), ||{
                Transaction {
                    id: tid.clone(),
                    server: *server,
                    state: TransactionState::Started
                }
            }, |t|{});
        }
        match self.tnxs.get_mut(tid) {
            Some(tnx) => tnx,
            _ => self.get_transaction(tid, server) // it should be rare
        }
    }
    fn get_cell_meta(&self, id: &Id) -> CellMetaGuard {
        if !self.cells.contains_key(id) {
            self.cells.upsert(id.clone(), || {
                CellMeta {
                    read: TransactionId::new(),
                    write: TransactionId::new(),
                    owner: None,
                    waiting: BTreeSet::new()
                }
            }, |c|{});
        }
        match self.cells.get_mut(id) {
            Some(cell) => cell,
            _ => self.get_cell_meta(id)
        }
    }
    fn response_with<T>(&self, data: T)
        -> Result<DataSiteResponse<T>, ()>{
        Ok(DataSiteResponse::new(&self.server.tnx_peer, data))
    }
}

impl Service for DataManager {
    fn read(&self, server_id: &u64, clock: &StandardVectorClock, tid: &TransactionId, id: &Id)
        -> Result<DataSiteResponse<TransactionExecResult<Cell, ReadError>>, ()> {
        self.update_clock(clock);
        let mut tnx = self.get_transaction(tid, server_id);
        let mut meta = self.get_cell_meta(id);
        let committing = meta.owner.is_some();
        let read_too_late = &meta.write > tid;
        if read_too_late { // not realizable
            return self.response_with(TransactionExecResult::Rejected);
        }
        if committing { // ts >= wt but committing, need to wait until it committed
            meta.waiting.insert(tid.clone());
            return self.response_with(TransactionExecResult::Wait);
        }
        let cell = match self.server.chunks.read_cell(id) {
            Ok(cell) => {cell}
            Err(read_error) => {
                // cannot read
                return self.response_with(TransactionExecResult::Error(read_error));
            }
        };
        let update_read = &meta.read < tid;
        if update_read {
            meta.read = tid.clone()
        }
        self.response_with(TransactionExecResult::Accepted(cell))
    }
    fn prepare(&self, clock :&StandardVectorClock, tid: &TransactionId, cell_ids: &Vec<Id>)
        -> Result<DataSiteResponse<PrepareResult>, ()> {
        // In this stage, data manager will not do any write operation but mark cell owner in their meta as a lock
        // It will also check if write are realizable. If not, transaction manager should retry with new id
        // cell_ids must be sorted to avoid deadlock. It can be done from data manager by using BTreeMap keys
        self.update_clock(clock);
        let mut tnx = match self.tnxs.get_mut(tid) {
            Some(tnx) => tnx,
            _ => {
                return self.response_with(PrepareResult::TransactionNotExisted);
            }
        };
        let mut cell_metas: Vec<CellMetaGuard> = Vec::new();
        for cell_id in cell_ids {
            let meta = self.get_cell_meta(cell_id);
            if tid < &meta.read { // write too late
                break;
            }
            if tid < &meta.write {
                if meta.owner.is_some() { // not committed, should wait and try prepare again
                    return self.response_with(PrepareResult::Wait)
                }
            }
            cell_metas.push(meta);
        }
        if cell_metas.len() < cell_ids.len() {
            return self.response_with(PrepareResult::NotRealizable); // need retry
        } else {
            for mut meta in cell_metas {
                meta.owner = Some(tid.clone()) // set owner to lock this cell
            }
            return self.response_with(PrepareResult::Success);
        }
    }
    fn commit(&self, clock :&StandardVectorClock, tid: &TransactionId, cells: &Vec<CellCommit>)
        -> Result<DataSiteResponse<bool>, ()>  {
        self.update_clock(clock);
        unimplemented!()
    }
    fn abort(&self, clock :&StandardVectorClock, tid: &TransactionId)
        -> Result<DataSiteResponse<()>, ()>  {
        self.update_clock(clock);
        unimplemented!()
    }
}<|endoftext|>