/// <summary> /// Returns a data-producer that will yield a specified number of /// contiguous elements from the start of a sequence - i.e. /// "the first <x> elements". /// </summary> /// <param name="source">The source data-producer</param> /// <param name="count">The maximum number of elements to return</param> public static IDataProducer <TSource> Take <TSource>(this IDataProducer <TSource> source, int count) { source.ThrowIfNull("source"); DataProducer <TSource> ret = new DataProducer <TSource>(); Action completion = () => ret.End(); Action <TSource> production = null; production = value => { if (count > 0) { ret.Produce(value); count--; } if (count <= 0) { source.EndOfData -= completion; source.DataProduced -= production; ret.End(); } }; source.DataProduced += production; source.EndOfData += completion; return(ret); }
/// <summary> /// Returns a data-producer that will yield /// elements a sequence as long as a condition /// (involving the element's index in the sequence) /// is satsified; when the condition fails for an element, /// that element and all subsequent elements are ignored. /// </summary> /// <param name="source">The source data-producer</param> /// <param name="predicate">The condition to yield elements</param> public static IDataProducer <TSource> TakeWhile <TSource>(this IDataProducer <TSource> source, DotNet20.Func <TSource, int, bool> predicate) { source.ThrowIfNull("source"); predicate.ThrowIfNull("predicate"); DataProducer <TSource> ret = new DataProducer <TSource>(); Action completion = () => ret.End(); Action <TSource> production = null; int index = 0; production = value => { if (!predicate(value, index++)) { ret.End(); source.DataProduced -= production; source.EndOfData -= completion; } else { ret.Produce(value); } }; source.DataProduced += production; source.EndOfData += completion; return(ret); }
public void EndWithinEnd() { DataProducer<string> subject = new DataProducer<string>(); subject.EndOfData += () => { subject.End(); }; try { subject.End(); } catch (InvalidOperationException) { // Expected } }
public void EndTwice() { DataProducer<string> subject = new DataProducer<string>(); subject.End(); try { subject.End(); Assert.Fail("Expected exception"); } catch (InvalidOperationException) { // Expected } }
public void EndWithinEnd() { DataProducer <string> subject = new DataProducer <string>(); subject.EndOfData += () => { subject.End(); }; try { subject.End(); } catch (InvalidOperationException) { // Expected } }
public void EndTwice() { DataProducer <string> subject = new DataProducer <string>(); subject.End(); try { subject.End(); Assert.Fail("Expected exception"); } catch (InvalidOperationException) { // Expected } }
/// <summary> /// Returns a data-producer that will ignore the /// elements from the start of a sequence while a condition /// (involving the elements's index in the sequence) /// is satsified; when the condition fails for an element, /// that element and all subsequent elements are yielded. /// </summary> /// <param name="source">The source data-producer</param> /// <param name="predicate">The condition to skip elements</param> public static IDataProducer <TSource> SkipWhile <TSource>(this IDataProducer <TSource> source, DotNet20.Func <TSource, int, bool> predicate) { source.ThrowIfNull("source"); predicate.ThrowIfNull("predicate"); DataProducer <TSource> ret = new DataProducer <TSource>(); Action completion = () => ret.End(); bool skipping = true; int index = 0; source.DataProduced += value => { if (skipping) { skipping = predicate(value, index++); } // Note - not an else clause! if (!skipping) { ret.Produce(value); } }; source.EndOfData += completion; return(ret); }
public void LastOrDefaultWithoutData() { DataProducer <int> subject = new DataProducer <int>(); IFuture <int> last = subject.LastOrDefault(); subject.End(); Assert.AreEqual(0, last.Value); }
public void SingleOrDefaultNoData() { DataProducer <int> subject = new DataProducer <int>(); IFuture <int> single = subject.SingleOrDefault(); subject.End(); Assert.AreEqual(0, single.Value); }
public void MaxNullableInt32WithProjectionNoElements() { DataProducer <int?> subject = new DataProducer <int?>(); IFuture <int?> result = subject.Max(x => - x); subject.End(); Assert.IsNull(result.Value); }
public void MinStringWithProjectionToStringNoData() { DataProducer <string> subject = new DataProducer <string>(); IFuture <string> result = subject.Min(x => x + x); subject.End(); Assert.IsNull(result.Value); }
public void AnyWithPredicateNoData() { DataProducer <string> subject = new DataProducer <string>(); IFuture <bool> result = subject.Any(x => x.Length < 5); subject.End(); Assert.IsFalse(result.Value); }
public void AllNoData() { DataProducer <string> subject = new DataProducer <string>(); IFuture <bool> result = subject.All(x => x.Length < 5); subject.End(); Assert.IsTrue(result.Value); }
public void MaxStringNoProjectionNoData() { DataProducer <string> subject = new DataProducer <string>(); IFuture <string> result = subject.Max(); subject.End(); Assert.IsNull(result.Value); }
public void MinNullableInt32NoProjectionEmptySequence() { DataProducer <int?> subject = new DataProducer <int?>(); IFuture <int?> min = subject.Min(); subject.End(); Assert.IsNull(min.Value); }
public void AverageComplex() { var data = new DataProducer <Complex>(); IFuture <Complex> result = data.Average(); data.Produce(new Complex(1, 3)); data.Produce(new Complex(3, 1)); data.End(); Assert.AreEqual(new Complex(2, 2), result.Value); }
public void JustEnd() { DataProducer<string> subject = new DataProducer<string>(); bool endReached = false; subject.DataProduced += val => { throw new Exception(); }; subject.EndOfData += () => endReached = true; subject.End(); Assert.IsTrue(endReached); }
public void JustEnd() { DataProducer <string> subject = new DataProducer <string>(); bool endReached = false; subject.DataProduced += val => { throw new Exception(); }; subject.EndOfData += () => endReached = true; subject.End(); Assert.IsTrue(endReached); }
/// <summary> /// Returns a projection on the data-producer, using a transformation /// (involving the elements's index in the sequence) to /// map each element into a new form. /// </summary> /// <typeparam name="TSource">The source type</typeparam> /// <typeparam name="TResult">The projected type</typeparam> /// <param name="source">The source data-producer</param> /// <param name="projection">The transformation to apply to each element.</param> public static IDataProducer <TResult> Select <TSource, TResult>(this IDataProducer <TSource> source, DotNet20.Func <TSource, int, TResult> projection) { source.ThrowIfNull("source"); projection.ThrowIfNull("projection"); DataProducer <TResult> ret = new DataProducer <TResult>(); int index = 0; source.DataProduced += value => ret.Produce(projection(value, index++)); source.EndOfData += () => ret.End(); return(ret); }
public void OrderByTestDescending() { var data = new DataProducer <Complex>(); IFuture <Complex> result = data.OrderByDescending(x => x.Imaginary) .ThenByDescending(x => - x.Real).First(); data.Produce(new Complex(1, 2)); data.Produce(new Complex(3, 2)); data.Produce(new Complex(1, 4)); data.Produce(new Complex(3, 4)); data.End(); Assert.AreEqual(new Complex(1, 4), result.Value); }
public void MaxInt32WithProjectionNoElements() { DataProducer <int> subject = new DataProducer <int>(); subject.Max(x => - x); try { subject.End(); Assert.Fail("Expected exception"); } catch (InvalidOperationException) { // Expected } }
public void MinStringWithProjectionToInt32NoData() { DataProducer <string> subject = new DataProducer <string>(); subject.Min(x => x == null ? 999 : x.Length); try { subject.End(); Assert.Fail("Expected exception"); } catch (InvalidOperationException) { // Expected } }
public void AsEnumerableWithModificationsInPlace() { DataProducer <int> subject = new DataProducer <int>(); IEnumerable <int> result = subject.AsEnumerable(); Assert.IsTrue(result.SequenceEqual(new int[0])); subject.Produce(10); Assert.IsTrue(result.SequenceEqual(new[] { 10 })); subject.Produce(20); Assert.IsTrue(result.SequenceEqual(new[] { 10, 20 })); subject.End(); Assert.IsTrue(result.SequenceEqual(new[] { 10, 20 })); }
public void SingleNoMatchingData() { DataProducer <string> subject = new DataProducer <string>(); subject.Single(x => x.Length == 5); subject.Produce("a"); subject.Produce("b"); try { subject.End(); Assert.Fail("Expected exception"); } catch (InvalidOperationException) { // Expected } }
public void FirstWithConditionAndNoMatchingData() { DataProducer <string> subject = new DataProducer <string>(); subject.First(x => x[0] > 'b'); subject.Produce("a"); subject.Produce("b"); try { subject.End(); Assert.Fail("Expected exception"); } catch (InvalidOperationException) { // Expected } }
public void OrderByTestDescendingComparer() { var comparer = Comparer <decimal> .Default.Reverse(); var data = new DataProducer <Complex>(); IFuture <Complex> result = data.OrderByDescending(x => x.Imaginary, comparer) .ThenByDescending(x => - x.Real, comparer) .ThenBy(x => x.Imaginary, Comparer <decimal> .Default) .Last(); data.Produce(new Complex(1, 2)); data.Produce(new Complex(3, 2)); data.Produce(new Complex(1, 4)); data.Produce(new Complex(3, 4)); data.End(); Assert.AreEqual(new Complex(1, 4), result.Value); }
public void LastWithConditionButNoMatchingData() { DataProducer <string> subject = new DataProducer <string>(); subject.Last(x => x.Length > 1); subject.Produce("x"); subject.Produce("y"); try { subject.End(); Assert.Fail("Expected exception"); } catch (InvalidOperationException) { // Expected } }
/// <summary> /// Filters a data-producer based on a predicate on each value; the index /// in the sequence is used in the predicate /// </summary> /// <param name="source">The data-producer to be filtered</param> /// <param name="predicate">The condition to be satisfied</param> /// <returns>A filtered data-producer; only matching values will raise the DataProduced event</returns> public static IDataProducer <TSource> Where <TSource>(this IDataProducer <TSource> source, Func <TSource, int, bool> predicate) { source.ThrowIfNull("source"); predicate.ThrowIfNull("predicate"); DataProducer <TSource> ret = new DataProducer <TSource>(); int index = 0; source.DataProduced += value => { if (predicate(value, index++)) { ret.Produce(value); } }; source.EndOfData += () => { ret.End(); }; return(ret); }
/// <summary> /// Returns a data-producer that will ignore a specified number of /// contiguous elements from the start of a sequence, and yield /// all elements after this point - i.e. /// "elements from index <x> onwards". /// </summary> /// <param name="source">The source data-producer</param> /// <param name="count">The number of elements to ignore</param> public static IDataProducer <TSource> Skip <TSource>(this IDataProducer <TSource> source, int count) { source.ThrowIfNull("source"); DataProducer <TSource> ret = new DataProducer <TSource>(); source.DataProduced += value => { if (count > 0) { count--; } else { ret.Produce(value); } }; source.EndOfData += () => ret.End(); return(ret); }
/// <summary> /// Groups the elements of a sequence according to a specified key selector function /// and creates a result value from each group and its key. The elements of each /// group are projected by using a specified function. /// </summary> /// <typeparam name="TElement">The return-type of the transform used to process the /// values within each grouping.</typeparam> /// <typeparam name="TKey">The return-type of the transform used to group the sequence</typeparam> /// <typeparam name="TResult">The final values to be yielded after processing</typeparam> /// <typeparam name="TSource">The values to be yielded by the original data-source</typeparam> /// <param name="comparer">Used to compare grouping keys</param> /// <param name="elementSelector">A function to map each source element to an element in the appropriate group</param> /// <param name="keySelector">A function to extract the key for each element in hte original sequence.</param> /// <param name="resultSelector">A function to create a result value from each group.</param> /// <param name="source">The data-source to be grouped</param> /// <remarks>This will force each unique grouping key to /// be buffered, but not the data itself</remarks> public static IDataProducer <TResult> GroupBy <TSource, TKey, TElement, TResult> (this IDataProducer <TSource> source, Func <TSource, TKey> keySelector, Func <TSource, TElement> elementSelector, Func <TKey, IDataProducer <TElement>, TResult> resultSelector, IEqualityComparer <TKey> comparer) { source.ThrowIfNull("source"); keySelector.ThrowIfNull("keySelector"); elementSelector.ThrowIfNull("elementSelector"); resultSelector.ThrowIfNull("resultSelector"); comparer.ThrowIfNull("comparer"); DataProducer <TResult> ret = new DataProducer <TResult>(); Dictionary <TKey, DataProducer <TElement> > dictionary = new Dictionary <TKey, DataProducer <TElement> >(comparer); source.DataProduced += value => { TKey key = keySelector(value); DataProducer <TElement> subProducer; if (!dictionary.TryGetValue(key, out subProducer)) { subProducer = new DataProducer <TElement>(); dictionary[key] = subProducer; ret.Produce(resultSelector(key, subProducer)); } subProducer.Produce(elementSelector(value)); }; source.EndOfData += () => { foreach (DataProducer <TElement> value in dictionary.Values) { value.End(); } ret.End(); }; return(ret); }
public void ValueThenEnd() { DataProducer<string> subject = new DataProducer<string>(); string pushed = null; bool endReached = false; subject.DataProduced += val => pushed = val; subject.EndOfData += () => endReached = true; Assert.IsFalse(endReached); Assert.IsNull(pushed); subject.Produce("foo"); Assert.IsFalse(endReached); Assert.AreEqual("foo", pushed); subject.End(); Assert.IsTrue(endReached); }
public void ValueThenEnd() { DataProducer <string> subject = new DataProducer <string>(); string pushed = null; bool endReached = false; subject.DataProduced += val => pushed = val; subject.EndOfData += () => endReached = true; Assert.IsFalse(endReached); Assert.IsNull(pushed); subject.Produce("foo"); Assert.IsFalse(endReached); Assert.AreEqual("foo", pushed); subject.End(); Assert.IsTrue(endReached); }
public void ElementAtOutsideRange() { DataProducer <string> subject = new DataProducer <string>(); subject.ElementAt(5); subject.Produce("zero"); subject.Produce("one"); subject.Produce("two"); subject.Produce("three"); try { subject.End(); Assert.Fail("Expected exception"); } catch (ArgumentOutOfRangeException) { // Expected } }
/// <summary> /// Returns a data-producer that yields the first instance of each unique /// value in the sequence; subsequent identical values are ignored. /// </summary> /// <param name="source">The data-producer</param> /// <param name="comparer">Used to determine equaility between values</param> /// <remarks>This will force the first instance of each unique value to be buffered</remarks> public static IDataProducer <TSource> Distinct <TSource>(this IDataProducer <TSource> source, IEqualityComparer <TSource> comparer) { source.ThrowIfNull("source"); comparer.ThrowIfNull("comparer"); DataProducer <TSource> ret = new DataProducer <TSource>(); HashSet <TSource> set = new HashSet <TSource>(comparer); source.DataProduced += value => { if (set.Add(value)) { ret.Produce(value); } }; source.EndOfData += () => ret.End(); return(ret); }
public void FirstWithConditionAndNoMatchingData() { DataProducer<string> subject = new DataProducer<string>(); subject.First(x => x[0] > 'b'); subject.Produce("a"); subject.Produce("b"); try { subject.End(); Assert.Fail("Expected exception"); } catch (InvalidOperationException) { // Expected } }
public void SingleNoMatchingData() { DataProducer<string> subject = new DataProducer<string>(); subject.Single(x => x.Length == 5); subject.Produce("a"); subject.Produce("b"); try { subject.End(); Assert.Fail("Expected exception"); } catch (InvalidOperationException) { // Expected } }
public void LastOrDefaultWithoutData() { DataProducer<int> subject = new DataProducer<int>(); IFuture<int> last = subject.LastOrDefault(); subject.End(); Assert.AreEqual(0, last.Value); }
public void SingleOrDefaultNoData() { DataProducer<int> subject = new DataProducer<int>(); IFuture<int> single = subject.SingleOrDefault(); subject.End(); Assert.AreEqual(0, single.Value); }
public void ElementAtOutsideRange() { DataProducer<string> subject = new DataProducer<string>(); subject.ElementAt(5); subject.Produce("zero"); subject.Produce("one"); subject.Produce("two"); subject.Produce("three"); try { subject.End(); Assert.Fail("Expected exception"); } catch (ArgumentOutOfRangeException) { // Expected } }
public void AllNoData() { DataProducer<string> subject = new DataProducer<string>(); IFuture<bool> result = subject.All(x => x.Length < 5); subject.End(); Assert.IsTrue(result.Value); }
public void AnyWithPredicateNoData() { DataProducer<string> subject = new DataProducer<string>(); IFuture<bool> result = subject.Any(x => x.Length < 5); subject.End(); Assert.IsFalse(result.Value); }
public void LastWithConditionButNoMatchingData() { DataProducer<string> subject = new DataProducer<string>(); subject.Last(x => x.Length > 1); subject.Produce("x"); subject.Produce("y"); try { subject.End(); Assert.Fail("Expected exception"); } catch (InvalidOperationException) { // Expected } }