/// <summary>
        /// Returns a data-producer that will yield a specified number of
        /// contiguous elements from the start of a sequence - i.e.
        /// "the first &lt;x&gt; 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);
        }
示例#3
0
        public void EndWithinEnd()
        {
            DataProducer<string> subject = new DataProducer<string>();
            subject.EndOfData += () => { subject.End(); };

            try
            {
                subject.End();
            }
            catch (InvalidOperationException)
            {
                // Expected
            }
        }
示例#4
0
        public void EndTwice()
        {
            DataProducer<string> subject = new DataProducer<string>();
            subject.End();

            try
            {
                subject.End();
                Assert.Fail("Expected exception");
            }
            catch (InvalidOperationException)
            {
                // Expected
            }
        }
示例#5
0
        public void EndWithinEnd()
        {
            DataProducer <string> subject = new DataProducer <string>();

            subject.EndOfData += () => { subject.End(); };

            try
            {
                subject.End();
            }
            catch (InvalidOperationException)
            {
                // Expected
            }
        }
示例#6
0
        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);
        }
示例#17
0
        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);
        }
示例#18
0
        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
            }
        }
示例#28
0
        /// <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);
        }
示例#29
0
        /// <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 &lt;x&gt; 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);
        }
示例#31
0
        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);
        }
示例#32
0
        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
     }
 }