diff --git a/src/impls.rs b/src/impls.rs index 5d510c5..3e450fd 100644 --- a/src/impls.rs +++ b/src/impls.rs @@ -189,7 +189,7 @@ macro_rules! mk_impl { use std::prelude::v1::*; use std::{$f, usize}; - use {Ieee754, Iter}; + use {Ieee754}; // test both `next`, and any potential internal-iteration // optimisations that the iterators support (which will @@ -202,7 +202,6 @@ macro_rules! mk_impl { fn count_fold(it: I) -> usize { it.fold(0, |i, _| i + 1) } - #[cfg(nightly)] fn count_try_fold(mut it: I) -> usize { const AT_A_TIME: usize = 5; (0..10).map(|_| { @@ -217,28 +216,10 @@ macro_rules! mk_impl { }).unwrap_or_else(|x| x.0) }).take_while(|x| *x > 0).sum() } - #[cfg(not(nightly))] - fn count_try_fold(it: I) -> usize { - count_fold(it) - } - fn count_try_fold_result(mut it: Iter<$f>) -> usize { + fn count_try_rfold(mut it: I) -> usize { const AT_A_TIME: usize = 5; (0..10).map(|_| { - it.try_fold_result(0, |i, _| { - let count = i + 1; - if count < AT_A_TIME { - Ok(count) - } else { - // make the error value different to the ok one - Err((count,)) - } - }).unwrap_or_else(|x| x.0) - }).take_while(|x| *x > 0).sum() - } - fn count_try_rfold_result(mut it: Iter<$f>) -> usize { - const AT_A_TIME: usize = 5; - (0..10).map(|_| { - it.try_rfold_result(0, |i, _| { + it.try_rfold(0, |i, _| { let count = i + 1; if count < AT_A_TIME { Ok(count) @@ -271,7 +252,6 @@ macro_rules! mk_impl { fn collect_fold(it: I) -> Vec { it.fold(vec![], |mut v, x| { v.push(x); v }) } - #[cfg(nightly)] fn collect_try_fold(mut it: I) -> Vec { const AT_A_TIME: usize = 5; (0..10).map(|_| { @@ -281,23 +261,10 @@ macro_rules! mk_impl { }).unwrap_or_else(|x| x) }).take_while(|x| x.len() > 0).flat_map(|x| x).collect() } - #[cfg(not(nightly))] - fn collect_try_fold(it: I) -> Vec { - collect_fold(it) - } - fn collect_try_fold_result(mut it: Iter<$f>) -> Vec<$f> { - const AT_A_TIME: usize = 5; - (0..10).map(|_| { - it.try_fold_result(vec![], |mut v, x| { - v.push(x); - if v.len() < AT_A_TIME { Ok(v) } else { Err(v) } - }).unwrap_or_else(|x| x) - }).take_while(|x| x.len() > 0).flat_map(|x| x).collect() - } - fn collect_try_rfold_result(mut it: Iter<$f>) -> Vec<$f> { + fn collect_try_rfold(mut it: I) -> Vec { const AT_A_TIME: usize = 5; (0..10).map(|_| { - it.try_rfold_result(vec![], |mut v, x| { + it.try_rfold(vec![], |mut v, x| { v.push(x); if v.len() < AT_A_TIME { Ok(v) } else { Err(v) } }).unwrap_or_else(|x| x) @@ -319,31 +286,31 @@ macro_rules! mk_impl { fn upto() { let one = (0.0 as $f).upto(0.0); assert_eq!(collect(one.clone()), &[0.0]); - assert_eq!(collect_try_fold_result(one), &[0.0]); + assert_eq!(collect_try_fold(one), &[0.0]); let ten = $f::recompose(false, 1, 1).upto($f::recompose(false, 1, 10)); assert_eq!(count(ten.clone()), 10); - assert_eq!(count_try_fold_result(ten), 10); + assert_eq!(count_try_fold(ten), 10); let twenty_one = $f::recompose(true, -$f::exponent_bias(), 10) .upto($f::recompose(false, -$f::exponent_bias(), 10)); assert_eq!(count(twenty_one.clone()), 21); - assert_eq!(count_try_fold_result(twenty_one), 21); + assert_eq!(count_try_fold(twenty_one), 21); } #[test] fn upto_rev() { let one = (0.0 as $f).upto(0.0); assert_eq!(collect(one.clone().rev()), &[0.0]); - assert_eq!(collect_try_rfold_result(one), &[0.0]); + assert_eq!(collect_try_rfold(one), &[0.0]); let ten = $f::recompose(false, 1, 1).upto($f::recompose(false, 1, 10)); assert_eq!(count(ten.clone().rev()), 10); - assert_eq!(count_try_rfold_result(ten), 10); + assert_eq!(count_try_rfold(ten), 10); let twenty_one = $f::recompose(true, -$f::exponent_bias(), 10) .upto($f::recompose(false, -$f::exponent_bias(), 10)); assert_eq!(count(twenty_one.clone().rev()), 21); - assert_eq!(count_try_rfold_result(twenty_one), 21); + assert_eq!(count_try_rfold(twenty_one), 21); } #[test] diff --git a/src/iter/mod.rs b/src/iter/mod.rs index 87a7e8e..58ba482 100644 --- a/src/iter/mod.rs +++ b/src/iter/mod.rs @@ -1,6 +1,6 @@ +use core::ops::ControlFlow; use core::usize; use core::fmt; -#[cfg(nightly)] use core::ops::Try; use {Bits, Ieee754}; @@ -52,34 +52,12 @@ fn u64_to_size_hint(x: u64) -> (usize, Option) { } } -#[cfg(nightly)] -fn result_to_try(r: Result) -> R { - match r { - Ok(ok) => R::from_ok(ok), - Err(error) => R::from_error(error) - } -} - impl Iter { fn len(&self) -> u64 { self.neg.len() + self.pos.len() } fn done(&self) -> bool { self.neg.done() && self.pos.done() } - - /// A non-nightly only version of `Iterator::try_fold`. - pub fn try_fold_result(&mut self, init: B, mut f: F) -> Result - where F: FnMut(B, T) -> Result { - let next = self.neg.try_fold_result(init, &mut f)?; - self.pos.try_fold_result(next, f) - } - - /// A non-nightly only version of `Iterator::try_fold`. - pub fn try_rfold_result(&mut self, init: B, mut f: F) -> Result - where F: FnMut(B, T) -> Result { - let next = self.pos.try_rfold_result(init, &mut f)?; - self.neg.try_fold_result(next, f) - } } impl Iterator for Iter { @@ -100,18 +78,24 @@ impl Iterator for Iter { self.pos.fold(next, f) } - #[cfg(nightly)] fn try_fold(&mut self, init: B, mut f: F) -> R - where F: FnMut(B, Self::Item) -> R, - R: Try { - result_to_try(self.try_fold_result(init, |b, x| f(b, x).into_result())) + where F: FnMut(B, T) -> R, R: Try { + let next = self.neg.try_fold(init, &mut f)?; + self.pos.try_fold(next, f) } + } impl DoubleEndedIterator for Iter { fn next_back(&mut self) -> Option { self.pos.next_back().or_else(|| self.neg.next_back()) } + + fn try_rfold(&mut self, init: B, mut f: F) -> R + where F: FnMut(B, T) -> R, R: Try { + let next = self.pos.try_rfold(init, &mut f)?; + self.neg.try_rfold(next, f) + } } // equal if they would iterate the same elements, even if the precise @@ -197,36 +181,6 @@ impl SingleSignIter { self.from == self.to } - fn try_fold_result(&mut self, mut value: B, mut f: F) -> Result - where F: FnMut(B, T) -> Result { - let SingleSignIter { mut from, to, .. } = *self; - while from != to { - let this = T::from_bits(from); - from = S::to_pos_inf(from); - value = f(value, this).map_err(|e| { - // save the new state before leaving, since we might iterate again - self.from = from; - e - })?; - } - self.from = from; - Ok(value) - } - - fn try_rfold_result(&mut self, mut value: B, mut f: F) -> Result - where F: FnMut(B, T) -> Result { - let SingleSignIter { from, mut to, .. } = *self; - while from != to { - to = S::to_neg_inf(to); - let this = T::from_bits(to); - value = f(value, this).map_err(|e| { - self.to = to; - e - })?; - } - self.to = to; - Ok(value) - } } impl Iterator for SingleSignIter { @@ -246,24 +200,42 @@ impl Iterator for SingleSignIter { u64_to_size_hint(self.len()) } + fn try_fold(&mut self, mut value: B, mut f: F) -> R + where F: FnMut(B, T) -> R, + R: Try { + let SingleSignIter { mut from, to, .. } = *self; + while from != to { + let this = T::from_bits(from); + from = S::to_pos_inf(from); + let cf = f(value, this).branch(); + match cf { + ControlFlow::Continue(a) => value = a, + ControlFlow::Break(r) => { + // save the new state before leaving, since we might iterate again + self.from = from; + return R::from_residual(r) + } + } + } + self.from = from; + R::from_output(value) + } + fn fold(mut self, init: B, mut f: F) -> B where F: FnMut(B, Self::Item) -> B, { enum Void {} - match self.try_fold_result(init, |b, x| Ok::<_, Void>(f(b, x))) { - Ok(result) => result, - Err(_) => unreachable!() + let cf = self.try_fold(init, |b, x| -> ControlFlow { + Try::from_output(f(b, x)) + }); + match cf { + ControlFlow::Continue(accum) => accum, + ControlFlow::Break(_) => unreachable!() } } - #[cfg(nightly)] - fn try_fold(&mut self, init: B, mut f: F) -> R - where F: FnMut(B, Self::Item) -> R, - R: Try { - result_to_try(self.try_fold_result(init, |b, x| f(b, x).into_result())) - } } impl DoubleEndedIterator for SingleSignIter { @@ -276,10 +248,39 @@ impl DoubleEndedIterator for SingleSignIter { } } - #[cfg(nightly)] - fn try_rfold(&mut self, init: B, mut f: F) -> R - where F: FnMut(B, Self::Item) -> R, - R: Try { - result_to_try(self.try_fold_result(init, |b, x| f(b, x).into_result())) + fn try_rfold(&mut self, mut value: B, mut f: F) -> R + where F: FnMut(B, T) -> R, + R: Try { + let SingleSignIter { from, mut to, .. } = *self; + while from != to { + to = S::to_neg_inf(to); + let this = T::from_bits(to); + let cf = f(value, this).branch(); + match cf { + ControlFlow::Continue(a) => value = a, + ControlFlow::Break(r) => { + // save the new state before leaving, since we might iterate again + self.to = to; + return R::from_residual(r) + } + } + } + self.to = to; + R::from_output(value) + } + + fn rfold(mut self, init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + enum Void {} + + let cf = self.try_rfold(init, |b, x| -> ControlFlow { + Try::from_output(f(b, x)) + }); + match cf { + ControlFlow::Continue(accum) => accum, + ControlFlow::Break(_) => unreachable!() + } } } diff --git a/src/lib.rs b/src/lib.rs index a573527..336958e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,7 +47,8 @@ //! ``` #![no_std] -#![cfg_attr(nightly, feature(try_trait))] +//#![cfg_attr(nightly, feature(try_trait_v2))] +#![feature(try_trait_v2)] #[cfg(test)] #[macro_use] extern crate std; mod iter;