ReadViaArray

ReadViaArray

--- FallDave.Trifles/StreamExtensions.cs
+++ FallDave.Trifles/StreamExtensions.cs
@@ -49,24 +49,38 @@

         #region ReadFully

-        // Repeatedly calls a partial read function until a buffer is full.
-        private static void ReadFullyNoCheck(Func<byte[], int, int, int> readFunction, byte[] buffer, int index, int count)
-        {
-            while (count > 0)
-            {
-                int readLength = readFunction(buffer, index, count);
-
-                if (readLength > 0)
+        // Repeatedly calls a partial read function until a buffer is full or the stream ends.
+        private static int ReadAsFullyAsPossibleNoCheck(Func<byte[], int, int, int> readFunction, byte[] buffer, int index, int count)
+        {
+            int totalReadLength = 0;
+
+            while (totalReadLength < count)
+            {
+                int readLengthThisPass = readFunction(buffer, index + totalReadLength, count - totalReadLength);
+
+                if (readLengthThisPass > 0)
                 {
-                    // At least one byte was read
-                    index += readLength;
-                    count -= readLength;
+                    // At least one byte was read.
+                    totalReadLength += readLengthThisPass;
                 }
                 else
                 {
-                    // Stream ended before full read
-                    throw new EndOfStreamException();
+                    // Stream ended.
+                    break;
                 }
+            }
+
+            return totalReadLength;
+        }
+
+        // Repeatedly calls a partial read function until a buffer is full.
+        private static void ReadFullyNoCheck(Func<byte[], int, int, int> readFunction, byte[] buffer, int index, int count)
+        {
+            int totalReadLength = ReadAsFullyAsPossibleNoCheck(readFunction, buffer, index, count);
+            if (totalReadLength < count)
+            {
+                // Stream ended before full read.
+                throw new EndOfStreamException();
             }
         }

@@ -116,13 +130,771 @@

         #endregion ReadFully

+        #region ReadViaArray
+
+        // This value must be at least 1.
+        private const int DefaultReadBufferSize = 8192;
+
+        private static void EnsureBufferNonZero(byte[] buffer)
+        {
+            if (buffer.Length == 0)
+            {
+                throw new ArgumentException("Buffer array must not be 0-length.");
+            }
+        }
+
+        // Read to the end of the stream using the given byte array as a buffer.
+        private static IEnumerable<int> ReadViaArrayNoCheck(Func<byte[], int, int, int> readFunction, byte[] buffer)
+        {
+            var bufferSize = buffer.Length;
+
+            while (true)
+            {
+                var countThisPass = ReadAsFullyAsPossibleNoCheck(readFunction, buffer, 0, bufferSize);
+
+                if (countThisPass > 0)
+                {
+                    yield return countThisPass;
+                }
+
+                if (countThisPass < bufferSize)
+                {
+                    break;
+                }
+            }
+        }
+
+        // Read up to maxCount bytes or to the end of the stream, whichever comes first, using the
+        // given byte array as a buffer. If requireFullCount is true, throw EndOfStreamException if
+        // fewer than maxCount bytes are read.
+        private static IEnumerable<int> ReadViaArrayNoCheck(Func<byte[], int, int, int> readFunction, int maxCount, byte[] buffer, bool requireFullCount)
+        {
+            var bufferSize = buffer.Length;
+
+            while (maxCount > 0)
+            {
+                var targetCountThisPass = Math.Min(bufferSize, maxCount);
+                var countThisPass = ReadAsFullyAsPossibleNoCheck(readFunction, buffer, 0, targetCountThisPass);
+                if (countThisPass > 0)
+                {
+                    yield return countThisPass;
+                    maxCount -= countThisPass;
+                }
+            }
+
+            if (requireFullCount && maxCount > 0)
+            {
+                throw new EndOfStreamException();
+            }
+        }
+
+        private static IEnumerable<int> ReadViaArrayNoCheck(Func<byte[], int, int, int> readFunction, ulong maxCount, byte[] buffer, bool requireFullCount)
+        {
+            var bufferSize = buffer.Length;
+
+            while (maxCount > 0)
+            {
+                var targetCountThisPass = MathTrifles.Min(bufferSize, maxCount);
+                var countThisPass = ReadAsFullyAsPossibleNoCheck(readFunction, buffer, 0, targetCountThisPass);
+                if (countThisPass > 0)
+                {
+                    yield return countThisPass;
+                    maxCount -= (ulong)countThisPass;
+                }
+            }
+
+            if (requireFullCount && maxCount > 0)
+            {
+                throw new EndOfStreamException();
+            }
+        }
+
+        private static IEnumerable<int> ReadViaArray(Func<byte[], int, int, int> readFunction, byte[] buffer)
+        {
+            Checker.NotNull(buffer, "buffer");
+            EnsureBufferNonZero(buffer);
+            return ReadViaArrayNoCheck(readFunction, buffer);
+        }
+
+        private static IEnumerable<int> ReadViaArray(Func<byte[], int, int, int> readFunction, int maxCount, byte[] buffer, bool requireFullCount)
+        {
+            Checker.NotNull(buffer, "buffer");
+            if (maxCount > 0)
+            {
+                EnsureBufferNonZero(buffer);
+            }
+            return ReadViaArrayNoCheck(readFunction, maxCount, buffer, requireFullCount);
+        }
+
+        private static IEnumerable<int> ReadViaArray(Func<byte[], int, int, int> readFunction, ulong maxCount, byte[] buffer, bool requireFullCount)
+        {
+            Checker.NotNull(buffer, "buffer");
+            if (maxCount > 0)
+            {
+                EnsureBufferNonZero(buffer);
+            }
+            return ReadViaArrayNoCheck(readFunction, maxCount, buffer, requireFullCount);
+        }
+
+        private static void ReadViaArray(Func<byte[], int, int, int> readFunction, Action<byte[], int, int> fillAction, byte[] buffer = null)
+        {
+            Checker.NotNull(fillAction, "fillAction");
+
+            if (buffer == null)
+            {
+                buffer = new byte[DefaultReadBufferSize];
+            }
+
+            foreach (var countThisPass in ReadViaArray(readFunction, buffer))
+            {
+                fillAction(buffer, 0, countThisPass);
+            }
+        }
+
+        private static void ReadViaArray(Func<byte[], int, int, int> readFunction, int maxCount, Action<byte[], int, int> fillAction, byte[] buffer = null, bool requireFullCount = false)
+        {
+            Checker.NotNull(fillAction, "fillAction");
+
+            if (buffer == null)
+            {
+                buffer = new byte[Math.Min(maxCount, DefaultReadBufferSize)];
+            }
+
+            foreach (var countThisPass in ReadViaArray(readFunction, maxCount, buffer, requireFullCount))
+            {
+                fillAction(buffer, 0, countThisPass);
+            }
+        }
+
+        private static void ReadViaArray(Func<byte[], int, int, int> readFunction, ulong maxCount, Action<byte[], int, int> fillAction, byte[] buffer = null, bool requireFullCount = false)
+        {
+            Checker.NotNull(fillAction, "fillAction");
+
+            if (buffer == null)
+            {
+                buffer = new byte[MathTrifles.Min(maxCount, DefaultReadBufferSize)];
+            }
+
+            foreach (var countThisPass in ReadViaArray(readFunction, maxCount, buffer, requireFullCount))
+            {
+                fillAction(buffer, 0, countThisPass);
+            }
+        }
+
+        private static ulong NonnegativeLong(long count)
+        {
+            return count < 0 ? 0UL : (ulong)count;
+        }
+
+        #region ReadViaArray(this Stream ...)
+
+        /// <summary>
+        /// Reads bytes repeatedly from a source stream until the stream ends.
+        /// </summary>
+        /// <remarks>
+        /// As long as the end of the source has not been reached, <paramref name="buffer"/> will be
+        /// repeatedly filled with data read from the source, with the returned enumerable producing
+        /// the number of bytes read each time.
+        /// </remarks>
+        /// <param name="source">A stream to read data from.</param>
+        /// <param name="buffer">An array to receive data from the source.</param>
+        /// <returns>An enumerable that produces the number of bytes read each pass.</returns>
+        /// <exception cref="ArgumentException"><paramref name="buffer"/> is 0-length.</exception>
+        public static IEnumerable<int> ReadViaArray(this Stream source, byte[] buffer)
+        {
+            return ReadViaArray(ReadFunctionOf(Checker.NotNull(source, "source")), buffer);
+        }
+
+        /// <summary>
+        /// Reads bytes repeatedly from a source stream until the stream ends or a given count has
+        /// been read, whichever happens first.
+        /// </summary>
+        /// <remarks>
+        /// <para>
+        /// As long as the end of the source has not been reached and <paramref name="maxCount"/>
+        /// bytes have not yet been read, <paramref name="buffer"/> will be repeatedly filled with
+        /// data read from the source, with the returned enumerable producing the number of bytes
+        /// read each time.
+        /// </para>
+        /// <para>
+        /// If <paramref name="requireFullCount"/> is <c>true</c>, the enumeration will throw an <see
+        /// cref="EndOfStreamException"/> if the end of the source has been reached before <paramref
+        /// name="maxCount"/> bytes have been read. If <c>false</c>, reaching the end of the source
+        /// simply causes the enumeration to end early.
+        /// </para>
+        /// </remarks>
+        /// <param name="source">A stream to read data from.</param>
+        /// <param name="maxCount">The maximum total number of bytes to read from <paramref name="source"/>.</param>
+        /// <param name="buffer">An array to receive data from the source.</param>
+        /// <param name="requireFullCount">
+        /// If <c>true</c>, <see cref="EndOfStreamException"/> will be thrown if the end of the
+        /// source is reached before <paramref name="maxCount"/> bytes are read.
+        /// </param>
+        /// <returns>An enumerable that produces the number of bytes read each pass.</returns>
+        /// <exception cref="ArgumentException">
+        /// <paramref name="buffer"/> is 0-length while <paramref name="maxCount"/> is greater than 0.
+        /// </exception>
+        /// <exception cref="EndOfStreamException">
+        /// The end of the source was reached before <paramref name="maxCount"/> bytes could be read
+        /// while <paramref name="requireFullCount"/> is <c>true</c>. (Thrown from enumeration.)
+        /// </exception>
+        public static IEnumerable<int> ReadViaArray(this Stream source, int maxCount, byte[] buffer, bool requireFullCount = false)
+        {
+            return ReadViaArray(ReadFunctionOf(Checker.NotNull(source, "source")), maxCount, buffer, requireFullCount);
+        }
+
+        /// <summary>
+        /// Reads bytes repeatedly from a source stream until the stream ends or a given count has
+        /// been read, whichever happens first.
+        /// </summary>
+        /// <remarks>
+        /// <para>
+        /// As long as the end of the source has not been reached and <paramref name="maxCount"/>
+        /// bytes have not yet been read, <paramref name="buffer"/> will be repeatedly filled with
+        /// data read from the source, with the returned enumerable producing the number of bytes
+        /// read each time.
+        /// </para>
+        /// <para>
+        /// If <paramref name="requireFullCount"/> is <c>true</c>, the enumeration will throw an <see
+        /// cref="EndOfStreamException"/> if the end of the source has been reached before <paramref
+        /// name="maxCount"/> bytes have been read. If <c>false</c>, reaching the end of the source
+        /// simply causes the enumeration to end early.
+        /// </para>
+        /// </remarks>
+        /// <param name="source">A stream to read data from.</param>
+        /// <param name="maxCount">The maximum total number of bytes to read from <paramref name="source"/>.</param>
+        /// <param name="buffer">An array to receive data from the source.</param>
+        /// <param name="requireFullCount">
+        /// If <c>true</c>, <see cref="EndOfStreamException"/> will be thrown if the end of the
+        /// source is reached before <paramref name="maxCount"/> bytes are read.
+        /// </param>
+        /// <returns>An enumerable that produces the number of bytes read each pass.</returns>
+        /// <exception cref="ArgumentException">
+        /// <paramref name="buffer"/> is 0-length while <paramref name="maxCount"/> is greater than 0.
+        /// </exception>
+        /// <exception cref="EndOfStreamException">
+        /// The end of the source was reached before <paramref name="maxCount"/> bytes could be read
+        /// while <paramref name="requireFullCount"/> is <c>true</c>. (Thrown from enumeration.)
+        /// </exception>
+        public static IEnumerable<int> ReadViaArray(this Stream source, long maxCount, byte[] buffer, bool requireFullCount = false)
+        {
+            return ReadViaArray(ReadFunctionOf(Checker.NotNull(source, "source")), NonnegativeLong(maxCount), buffer, requireFullCount);
+        }
+
+        /// <summary>
+        /// Reads bytes repeatedly from a source stream until the stream ends or a given count has
+        /// been read, whichever happens first.
+        /// </summary>
+        /// <remarks>
+        /// <para>
+        /// As long as the end of the source has not been reached and <paramref name="maxCount"/>
+        /// bytes have not yet been read, <paramref name="buffer"/> will be repeatedly filled with
+        /// data read from the source, with the returned enumerable producing the number of bytes
+        /// read each time.
+        /// </para>
+        /// <para>
+        /// If <paramref name="requireFullCount"/> is <c>true</c>, the enumeration will throw an <see
+        /// cref="EndOfStreamException"/> if the end of the source has been reached before <paramref
+        /// name="maxCount"/> bytes have been read. If <c>false</c>, reaching the end of the source
+        /// simply causes the enumeration to end early.
+        /// </para>
+        /// </remarks>
+        /// <param name="source">A stream to read data from.</param>
+        /// <param name="maxCount">The maximum total number of bytes to read from <paramref name="source"/>.</param>
+        /// <param name="buffer">An array to receive data from the source.</param>
+        /// <param name="requireFullCount">
+        /// If <c>true</c>, <see cref="EndOfStreamException"/> will be thrown if the end of the
+        /// source is reached before <paramref name="maxCount"/> bytes are read.
+        /// </param>
+        /// <returns>An enumerable that produces the number of bytes read each pass.</returns>
+        /// <exception cref="ArgumentException">
+        /// <paramref name="buffer"/> is 0-length while <paramref name="maxCount"/> is greater than 0.
+        /// </exception>
+        /// <exception cref="EndOfStreamException">
+        /// The end of the source was reached before <paramref name="maxCount"/> bytes could be read
+        /// while <paramref name="requireFullCount"/> is <c>true</c>. (Thrown from enumeration.)
+        /// </exception>
+        public static IEnumerable<int> ReadViaArray(this Stream source, ulong maxCount, byte[] buffer, bool requireFullCount = false)
+        {
+            return ReadViaArray(ReadFunctionOf(Checker.NotNull(source, "source")), maxCount, buffer, requireFullCount);
+        }
+
+        /// <summary>
+        /// Reads bytes repeatedly from a source stream until the stream ends, calling the given
+        /// action each time the buffer is filled.
+        /// </summary>
+        /// <remarks>
+        /// <para>
+        /// As long as the end of the source has not been reached, the buffer will be repeatedly
+        /// filled with data read from the source, with <paramref name="fillAction"/> being called
+        /// with the buffer, an offset, and a length as parameters each time the buffer is filled.
+        /// </para>
+        /// <para>
+        /// If <paramref name="buffer"/> is present, it is used as the buffer. If <paramref
+        /// name="buffer"/> is omitted or <c>null</c>, a new array is allocated.
+        /// </para>
+        /// </remarks>
+        /// <param name="source">A stream to read data from.</param>
+        /// <param name="fillAction">
+        /// An action with buffer, offset, and length parameters that is called each time the buffer
+        /// is filled.
+        /// </param>
+        /// <param name="buffer">An array to receive data from the source (may be omitted).</param>
+        /// <exception cref="ArgumentException"><paramref name="buffer"/> is 0-length.</exception>
+        public static void ReadViaArray(this Stream source, Action<byte[], int, int> fillAction, byte[] buffer = null)
+        {
+            ReadViaArray(ReadFunctionOf(Checker.NotNull(source, "source")), fillAction, buffer);
+        }
+
+        /// <summary>
+        /// Reads bytes repeatedly from a source stream until the stream ends or a given count has
+        /// been read, whichever happens first, calling the given action each time the buffer is filled.
+        /// </summary>
+        /// <remarks>
+        /// <para>
+        /// As long as the end of the source has not been reached and <paramref name="maxCount"/>
+        /// bytes have not yet been read, the buffer will be repeatedly filled with data read from
+        /// the source, with <paramref name="fillAction"/> being called with the buffer, an offset,
+        /// and a length as parameters each time the buffer is filled.
+        /// </para>
+        /// <para>
+        /// If <paramref name="buffer"/> is present, it is used as the buffer. If <paramref
+        /// name="buffer"/> is omitted or <c>null</c>, a new array is allocated.
+        /// </para>
+        /// <para>
+        /// If <paramref name="requireFullCount"/> is <c>true</c>, the enumeration will throw an <see
+        /// cref="EndOfStreamException"/> if the end of the source has been reached before <paramref
+        /// name="maxCount"/> bytes have been read. If <c>false</c>, reaching the end of the source
+        /// simply causes the enumeration to end early.
+        /// </para>
+        /// </remarks>
+        /// <param name="source">A stream to read data from.</param>
+        /// <param name="fillAction">
+        /// An action with buffer, offset, and length parameters that is called each time the buffer
+        /// is filled.
+        /// </param>
+        /// <param name="maxCount">The maximum total number of bytes to read from <paramref name="source"/>.</param>
+        /// <param name="buffer">An array to receive data from the source (may be omitted).</param>
+        /// <param name="requireFullCount">
+        /// If <c>true</c>, <see cref="EndOfStreamException"/> will be thrown if the end of the
+        /// source is reached before <paramref name="maxCount"/> bytes are read.
+        /// </param>
+        /// <returns>An enumerable that produces the number of bytes read each pass.</returns>
+        /// <exception cref="ArgumentException">
+        /// <paramref name="buffer"/> is 0-length while <paramref name="maxCount"/> is greater than 0.
+        /// </exception>
+        /// <exception cref="EndOfStreamException">
+        /// The end of the source was reached before <paramref name="maxCount"/> bytes could be read
+        /// while <paramref name="requireFullCount"/> is <c>true</c>. (Thrown from enumeration.)
+        /// </exception>
+        public static void ReadViaArray(this Stream source, Action<byte[], int, int> fillAction, int maxCount, byte[] buffer = null, bool requireFullCount = false)
+        {
+            ReadViaArray(ReadFunctionOf(Checker.NotNull(source, "source")), maxCount, buffer, requireFullCount);
+        }
+
+        /// <summary>
+        /// Reads bytes repeatedly from a source stream until the stream ends or a given count has
+        /// been read, whichever happens first, calling the given action each time the buffer is filled.
+        /// </summary>
+        /// <remarks>
+        /// <para>
+        /// As long as the end of the source has not been reached and <paramref name="maxCount"/>
+        /// bytes have not yet been read, the buffer will be repeatedly filled with data read from
+        /// the source, with <paramref name="fillAction"/> being called with the buffer, an offset,
+        /// and a length as parameters each time the buffer is filled.
+        /// </para>
+        /// <para>
+        /// If <paramref name="buffer"/> is present, it is used as the buffer. If <paramref
+        /// name="buffer"/> is omitted or <c>null</c>, a new array is allocated.
+        /// </para>
+        /// <para>
+        /// If <paramref name="requireFullCount"/> is <c>true</c>, the enumeration will throw an <see
+        /// cref="EndOfStreamException"/> if the end of the source has been reached before <paramref
+        /// name="maxCount"/> bytes have been read. If <c>false</c>, reaching the end of the source
+        /// simply causes the enumeration to end early.
+        /// </para>
+        /// </remarks>
+        /// <param name="source">A stream to read data from.</param>
+        /// <param name="fillAction">
+        /// An action with buffer, offset, and length parameters that is called each time the buffer
+        /// is filled.
+        /// </param>
+        /// <param name="maxCount">The maximum total number of bytes to read from <paramref name="source"/>.</param>
+        /// <param name="buffer">An array to receive data from the source (may be omitted).</param>
+        /// <param name="requireFullCount">
+        /// If <c>true</c>, <see cref="EndOfStreamException"/> will be thrown if the end of the
+        /// source is reached before <paramref name="maxCount"/> bytes are read.
+        /// </param>
+        /// <returns>An enumerable that produces the number of bytes read each pass.</returns>
+        /// <exception cref="ArgumentException">
+        /// <paramref name="buffer"/> is 0-length while <paramref name="maxCount"/> is greater than 0.
+        /// </exception>
+        /// <exception cref="EndOfStreamException">
+        /// The end of the source was reached before <paramref name="maxCount"/> bytes could be read
+        /// while <paramref name="requireFullCount"/> is <c>true</c>. (Thrown from enumeration.)
+        /// </exception>
+        public static void ReadViaArray(this Stream source, Action<byte[], int, int> fillAction, long maxCount, byte[] buffer = null, bool requireFullCount = false)
+        {
+            ReadViaArray(ReadFunctionOf(Checker.NotNull(source, "source")), NonnegativeLong(maxCount), buffer, requireFullCount);
+        }
+
+        /// <summary>
+        /// Reads bytes repeatedly from a source stream until the stream ends or a given count has
+        /// been read, whichever happens first, calling the given action each time the buffer is filled.
+        /// </summary>
+        /// <remarks>
+        /// <para>
+        /// As long as the end of the source has not been reached and <paramref name="maxCount"/>
+        /// bytes have not yet been read, the buffer will be repeatedly filled with data read from
+        /// the source, with <paramref name="fillAction"/> being called with the buffer, an offset,
+        /// and a length as parameters each time the buffer is filled.
+        /// </para>
+        /// <para>
+        /// If <paramref name="buffer"/> is present, it is used as the buffer. If <paramref
+        /// name="buffer"/> is omitted or <c>null</c>, a new array is allocated.
+        /// </para>
+        /// <para>
+        /// If <paramref name="requireFullCount"/> is <c>true</c>, the enumeration will throw an <see
+        /// cref="EndOfStreamException"/> if the end of the source has been reached before <paramref
+        /// name="maxCount"/> bytes have been read. If <c>false</c>, reaching the end of the source
+        /// simply causes the enumeration to end early.
+        /// </para>
+        /// </remarks>
+        /// <param name="source">A stream to read data from.</param>
+        /// <param name="fillAction">
+        /// An action with buffer, offset, and length parameters that is called each time the buffer
+        /// is filled.
+        /// </param>
+        /// <param name="maxCount">The maximum total number of bytes to read from <paramref name="source"/>.</param>
+        /// <param name="buffer">An array to receive data from the source (may be omitted).</param>
+        /// <param name="requireFullCount">
+        /// If <c>true</c>, <see cref="EndOfStreamException"/> will be thrown if the end of the
+        /// source is reached before <paramref name="maxCount"/> bytes are read.
+        /// </param>
+        /// <returns>An enumerable that produces the number of bytes read each pass.</returns>
+        /// <exception cref="ArgumentException">
+        /// <paramref name="buffer"/> is 0-length while <paramref name="maxCount"/> is greater than 0.
+        /// </exception>
+        /// <exception cref="EndOfStreamException">
+        /// The end of the source was reached before <paramref name="maxCount"/> bytes could be read
+        /// while <paramref name="requireFullCount"/> is <c>true</c>. (Thrown from enumeration.)
+        /// </exception>
+        public static void ReadViaArray(this Stream source, Action<byte[], int, int> fillAction, ulong maxCount, byte[] buffer = null, bool requireFullCount = false)
+        {
+            ReadViaArray(ReadFunctionOf(Checker.NotNull(source, "source")), maxCount, buffer, requireFullCount);
+        }
+
+        #endregion ReadViaArray(this Stream ...)
+
+        #region ReadViaArray(this BinaryReader ...)
+
+        /// <summary>
+        /// Reads bytes repeatedly from a source stream until the stream ends.
+        /// </summary>
+        /// <remarks>
+        /// As long as the end of the source has not been reached, <paramref name="buffer"/> will be
+        /// repeatedly filled with data read from the source, with the returned enumerable producing
+        /// the number of bytes read each time.
+        /// </remarks>
+        /// <param name="source">A stream to read data from.</param>
+        /// <param name="buffer">An array to receive data from the source.</param>
+        /// <returns>An enumerable that produces the number of bytes read each pass.</returns>
+        /// <exception cref="ArgumentException"><paramref name="buffer"/> is 0-length.</exception>
+        public static IEnumerable<int> ReadViaArray(this BinaryReader source, byte[] buffer)
+        {
+            return ReadViaArray(ReadFunctionOf(Checker.NotNull(source, "source")), buffer);
+        }
+
+        /// <summary>
+        /// Reads bytes repeatedly from a source stream until the stream ends or a given count has
+        /// been read, whichever happens first.
+        /// </summary>
+        /// <remarks>
+        /// <para>
+        /// As long as the end of the source has not been reached and <paramref name="maxCount"/>
+        /// bytes have not yet been read, <paramref name="buffer"/> will be repeatedly filled with
+        /// data read from the source, with the returned enumerable producing the number of bytes
+        /// read each time.
+        /// </para>
+        /// <para>
+        /// If <paramref name="requireFullCount"/> is <c>true</c>, the enumeration will throw an <see
+        /// cref="EndOfStreamException"/> if the end of the source has been reached before <paramref
+        /// name="maxCount"/> bytes have been read. If <c>false</c>, reaching the end of the source
+        /// simply causes the enumeration to end early.
+        /// </para>
+        /// </remarks>
+        /// <param name="source">A stream to read data from.</param>
+        /// <param name="maxCount">The maximum total number of bytes to read from <paramref name="source"/>.</param>
+        /// <param name="buffer">An array to receive data from the source.</param>
+        /// <param name="requireFullCount">
+        /// If <c>true</c>, <see cref="EndOfStreamException"/> will be thrown if the end of the
+        /// source is reached before <paramref name="maxCount"/> bytes are read.
+        /// </param>
+        /// <returns>An enumerable that produces the number of bytes read each pass.</returns>
+        /// <exception cref="ArgumentException">
+        /// <paramref name="buffer"/> is 0-length while <paramref name="maxCount"/> is greater than 0.
+        /// </exception>
+        /// <exception cref="EndOfStreamException">
+        /// The end of the source was reached before <paramref name="maxCount"/> bytes could be read
+        /// while <paramref name="requireFullCount"/> is <c>true</c>. (Thrown from enumeration.)
+        /// </exception>
+        public static IEnumerable<int> ReadViaArray(this BinaryReader source, int maxCount, byte[] buffer, bool requireFullCount = false)
+        {
+            return ReadViaArray(ReadFunctionOf(Checker.NotNull(source, "source")), maxCount, buffer, requireFullCount);
+        }
+
+        /// <summary>
+        /// Reads bytes repeatedly from a source stream until the stream ends or a given count has
+        /// been read, whichever happens first.
+        /// </summary>
+        /// <remarks>
+        /// <para>
+        /// As long as the end of the source has not been reached and <paramref name="maxCount"/>
+        /// bytes have not yet been read, <paramref name="buffer"/> will be repeatedly filled with
+        /// data read from the source, with the returned enumerable producing the number of bytes
+        /// read each time.
+        /// </para>
+        /// <para>
+        /// If <paramref name="requireFullCount"/> is <c>true</c>, the enumeration will throw an <see
+        /// cref="EndOfStreamException"/> if the end of the source has been reached before <paramref
+        /// name="maxCount"/> bytes have been read. If <c>false</c>, reaching the end of the source
+        /// simply causes the enumeration to end early.
+        /// </para>
+        /// </remarks>
+        /// <param name="source">A stream to read data from.</param>
+        /// <param name="maxCount">The maximum total number of bytes to read from <paramref name="source"/>.</param>
+        /// <param name="buffer">An array to receive data from the source.</param>
+        /// <param name="requireFullCount">
+        /// If <c>true</c>, <see cref="EndOfStreamException"/> will be thrown if the end of the
+        /// source is reached before <paramref name="maxCount"/> bytes are read.
+        /// </param>
+        /// <returns>An enumerable that produces the number of bytes read each pass.</returns>
+        /// <exception cref="ArgumentException">
+        /// <paramref name="buffer"/> is 0-length while <paramref name="maxCount"/> is greater than 0.
+        /// </exception>
+        /// <exception cref="EndOfStreamException">
+        /// The end of the source was reached before <paramref name="maxCount"/> bytes could be read
+        /// while <paramref name="requireFullCount"/> is <c>true</c>. (Thrown from enumeration.)
+        /// </exception>
+        public static IEnumerable<int> ReadViaArray(this BinaryReader source, long maxCount, byte[] buffer, bool requireFullCount = false)
+        {
+            return ReadViaArray(ReadFunctionOf(Checker.NotNull(source, "source")), NonnegativeLong(maxCount), buffer, requireFullCount);
+        }
+
+        /// <summary>
+        /// Reads bytes repeatedly from a source stream until the stream ends or a given count has
+        /// been read, whichever happens first.
+        /// </summary>
+        /// <remarks>
+        /// <para>
+        /// As long as the end of the source has not been reached and <paramref name="maxCount"/>
+        /// bytes have not yet been read, <paramref name="buffer"/> will be repeatedly filled with
+        /// data read from the source, with the returned enumerable producing the number of bytes
+        /// read each time.
+        /// </para>
+        /// <para>
+        /// If <paramref name="requireFullCount"/> is <c>true</c>, the enumeration will throw an <see
+        /// cref="EndOfStreamException"/> if the end of the source has been reached before <paramref
+        /// name="maxCount"/> bytes have been read. If <c>false</c>, reaching the end of the source
+        /// simply causes the enumeration to end early.
+        /// </para>
+        /// </remarks>
+        /// <param name="source">A stream to read data from.</param>
+        /// <param name="maxCount">The maximum total number of bytes to read from <paramref name="source"/>.</param>
+        /// <param name="buffer">An array to receive data from the source.</param>
+        /// <param name="requireFullCount">
+        /// If <c>true</c>, <see cref="EndOfStreamException"/> will be thrown if the end of the
+        /// source is reached before <paramref name="maxCount"/> bytes are read.
+        /// </param>
+        /// <returns>An enumerable that produces the number of bytes read each pass.</returns>
+        /// <exception cref="ArgumentException">
+        /// <paramref name="buffer"/> is 0-length while <paramref name="maxCount"/> is greater than 0.
+        /// </exception>
+        /// <exception cref="EndOfStreamException">
+        /// The end of the source was reached before <paramref name="maxCount"/> bytes could be read
+        /// while <paramref name="requireFullCount"/> is <c>true</c>. (Thrown from enumeration.)
+        /// </exception>
+        public static IEnumerable<int> ReadViaArray(this BinaryReader source, ulong maxCount, byte[] buffer, bool requireFullCount = false)
+        {
+            return ReadViaArray(ReadFunctionOf(Checker.NotNull(source, "source")), maxCount, buffer, requireFullCount);
+        }
+
+        /// <summary>
+        /// Reads bytes repeatedly from a source stream until the stream ends, calling the given
+        /// action each time the buffer is filled.
+        /// </summary>
+        /// <remarks>
+        /// <para>
+        /// As long as the end of the source has not been reached, the buffer will be repeatedly
+        /// filled with data read from the source, with <paramref name="fillAction"/> being called
+        /// with the buffer, an offset, and a length as parameters each time the buffer is filled.
+        /// </para>
+        /// <para>
+        /// If <paramref name="buffer"/> is present, it is used as the buffer. If <paramref
+        /// name="buffer"/> is omitted or <c>null</c>, a new array is allocated.
+        /// </para>
+        /// </remarks>
+        /// <param name="source">A stream to read data from.</param>
+        /// <param name="fillAction">
+        /// An action with buffer, offset, and length parameters that is called each time the buffer
+        /// is filled.
+        /// </param>
+        /// <param name="buffer">An array to receive data from the source (may be omitted).</param>
+        /// <exception cref="ArgumentException"><paramref name="buffer"/> is 0-length.</exception>
+        public static void ReadViaArray(this BinaryReader source, Action<byte[], int, int> fillAction, byte[] buffer = null)
+        {
+            ReadViaArray(ReadFunctionOf(Checker.NotNull(source, "source")), fillAction, buffer);
+        }
+
+        /// <summary>
+        /// Reads bytes repeatedly from a source stream until the stream ends or a given count has
+        /// been read, whichever happens first, calling the given action each time the buffer is filled.
+        /// </summary>
+        /// <remarks>
+        /// <para>
+        /// As long as the end of the source has not been reached and <paramref name="maxCount"/>
+        /// bytes have not yet been read, the buffer will be repeatedly filled with data read from
+        /// the source, with <paramref name="fillAction"/> being called with the buffer, an offset,
+        /// and a length as parameters each time the buffer is filled.
+        /// </para>
+        /// <para>
+        /// If <paramref name="buffer"/> is present, it is used as the buffer. If <paramref
+        /// name="buffer"/> is omitted or <c>null</c>, a new array is allocated.
+        /// </para>
+        /// <para>
+        /// If <paramref name="requireFullCount"/> is <c>true</c>, the enumeration will throw an <see
+        /// cref="EndOfStreamException"/> if the end of the source has been reached before <paramref
+        /// name="maxCount"/> bytes have been read. If <c>false</c>, reaching the end of the source
+        /// simply causes the enumeration to end early.
+        /// </para>
+        /// </remarks>
+        /// <param name="source">A stream to read data from.</param>
+        /// <param name="fillAction">
+        /// An action with buffer, offset, and length parameters that is called each time the buffer
+        /// is filled.
+        /// </param>
+        /// <param name="maxCount">The maximum total number of bytes to read from <paramref name="source"/>.</param>
+        /// <param name="buffer">An array to receive data from the source (may be omitted).</param>
+        /// <param name="requireFullCount">
+        /// If <c>true</c>, <see cref="EndOfStreamException"/> will be thrown if the end of the
+        /// source is reached before <paramref name="maxCount"/> bytes are read.
+        /// </param>
+        /// <returns>An enumerable that produces the number of bytes read each pass.</returns>
+        /// <exception cref="ArgumentException">
+        /// <paramref name="buffer"/> is 0-length while <paramref name="maxCount"/> is greater than 0.
+        /// </exception>
+        /// <exception cref="EndOfStreamException">
+        /// The end of the source was reached before <paramref name="maxCount"/> bytes could be read
+        /// while <paramref name="requireFullCount"/> is <c>true</c>. (Thrown from enumeration.)
+        /// </exception>
+        public static void ReadViaArray(this BinaryReader source, Action<byte[], int, int> fillAction, int maxCount, byte[] buffer = null, bool requireFullCount = false)
+        {
+            ReadViaArray(ReadFunctionOf(Checker.NotNull(source, "source")), maxCount, buffer, requireFullCount);
+        }
+
+        /// <summary>
+        /// Reads bytes repeatedly from a source stream until the stream ends or a given count has
+        /// been read, whichever happens first, calling the given action each time the buffer is filled.
+        /// </summary>
+        /// <remarks>
+        /// <para>
+        /// As long as the end of the source has not been reached and <paramref name="maxCount"/>
+        /// bytes have not yet been read, the buffer will be repeatedly filled with data read from
+        /// the source, with <paramref name="fillAction"/> being called with the buffer, an offset,
+        /// and a length as parameters each time the buffer is filled.
+        /// </para>
+        /// <para>
+        /// If <paramref name="buffer"/> is present, it is used as the buffer. If <paramref
+        /// name="buffer"/> is omitted or <c>null</c>, a new array is allocated.
+        /// </para>
+        /// <para>
+        /// If <paramref name="requireFullCount"/> is <c>true</c>, the enumeration will throw an <see
+        /// cref="EndOfStreamException"/> if the end of the source has been reached before <paramref
+        /// name="maxCount"/> bytes have been read. If <c>false</c>, reaching the end of the source
+        /// simply causes the enumeration to end early.
+        /// </para>
+        /// </remarks>
+        /// <param name="source">A stream to read data from.</param>
+        /// <param name="fillAction">
+        /// An action with buffer, offset, and length parameters that is called each time the buffer
+        /// is filled.
+        /// </param>
+        /// <param name="maxCount">The maximum total number of bytes to read from <paramref name="source"/>.</param>
+        /// <param name="buffer">An array to receive data from the source (may be omitted).</param>
+        /// <param name="requireFullCount">
+        /// If <c>true</c>, <see cref="EndOfStreamException"/> will be thrown if the end of the
+        /// source is reached before <paramref name="maxCount"/> bytes are read.
+        /// </param>
+        /// <returns>An enumerable that produces the number of bytes read each pass.</returns>
+        /// <exception cref="ArgumentException">
+        /// <paramref name="buffer"/> is 0-length while <paramref name="maxCount"/> is greater than 0.
+        /// </exception>
+        /// <exception cref="EndOfStreamException">
+        /// The end of the source was reached before <paramref name="maxCount"/> bytes could be read
+        /// while <paramref name="requireFullCount"/> is <c>true</c>. (Thrown from enumeration.)
+        /// </exception>
+        public static void ReadViaArray(this BinaryReader source, Action<byte[], int, int> fillAction, long maxCount, byte[] buffer = null, bool requireFullCount = false)
+        {
+            ReadViaArray(ReadFunctionOf(Checker.NotNull(source, "source")), NonnegativeLong(maxCount), buffer, requireFullCount);
+        }
+
+        /// <summary>
+        /// Reads bytes repeatedly from a source stream until the stream ends or a given count has
+        /// been read, whichever happens first, calling the given action each time the buffer is filled.
+        /// </summary>
+        /// <remarks>
+        /// <para>
+        /// As long as the end of the source has not been reached and <paramref name="maxCount"/>
+        /// bytes have not yet been read, the buffer will be repeatedly filled with data read from
+        /// the source, with <paramref name="fillAction"/> being called with the buffer, an offset,
+        /// and a length as parameters each time the buffer is filled.
+        /// </para>
+        /// <para>
+        /// If <paramref name="buffer"/> is present, it is used as the buffer. If <paramref
+        /// name="buffer"/> is omitted or <c>null</c>, a new array is allocated.
+        /// </para>
+        /// <para>
+        /// If <paramref name="requireFullCount"/> is <c>true</c>, the enumeration will throw an <see
+        /// cref="EndOfStreamException"/> if the end of the source has been reached before <paramref
+        /// name="maxCount"/> bytes have been read. If <c>false</c>, reaching the end of the source
+        /// simply causes the enumeration to end early.
+        /// </para>
+        /// </remarks>
+        /// <param name="source">A stream to read data from.</param>
+        /// <param name="fillAction">
+        /// An action with buffer, offset, and length parameters that is called each time the buffer
+        /// is filled.
+        /// </param>
+        /// <param name="maxCount">The maximum total number of bytes to read from <paramref name="source"/>.</param>
+        /// <param name="buffer">An array to receive data from the source (may be omitted).</param>
+        /// <param name="requireFullCount">
+        /// If <c>true</c>, <see cref="EndOfStreamException"/> will be thrown if the end of the
+        /// source is reached before <paramref name="maxCount"/> bytes are read.
+        /// </param>
+        /// <returns>An enumerable that produces the number of bytes read each pass.</returns>
+        /// <exception cref="ArgumentException">
+        /// <paramref name="buffer"/> is 0-length while <paramref name="maxCount"/> is greater than 0.
+        /// </exception>
+        /// <exception cref="EndOfStreamException">
+        /// The end of the source was reached before <paramref name="maxCount"/> bytes could be read
+        /// while <paramref name="requireFullCount"/> is <c>true</c>. (Thrown from enumeration.)
+        /// </exception>
+        public static void ReadViaArray(this BinaryReader source, Action<byte[], int, int> fillAction, ulong maxCount, byte[] buffer = null, bool requireFullCount = false)
+        {
+            ReadViaArray(ReadFunctionOf(Checker.NotNull(source, "source")), maxCount, buffer, requireFullCount);
+        }
+
+        #endregion ReadViaArray(this BinaryReader ...)
+
+        #endregion ReadViaArray
+
         #region Write(... IEnumerable<byte> source ...)

         // This value must be at least 1.
         private const int DefaultWriteBufferSize = 8192;

-        // Copies elements from an IList<byte> to a byte array.
-        // Special cases exist for source of byte[] or ImmutableArray<byte>.
+        // Copies elements from an IList<byte> to a byte array. Special cases exist for source of
+        // byte[] or ImmutableArray<byte>.

         private static void CopyToNoCheck(IList<byte> source, int sourceIndex, byte[] destination, int destinationIndex, int length)
         {
@@ -143,8 +915,8 @@
             }
         }

-        // Calls a write action repeatedly while copying bytes from a source through a buffer.
-        // If the provided source is a byte array, the incremental copy is skipped.
+        // Calls a write action repeatedly while copying bytes from a source through a buffer. If the
+        // provided source is a byte array, the incremental copy is skipped.
         private static void WriteNoCheck(Action<byte[], int, int> writeAction, IList<byte> source, int index, int count, int bufferSize)
         {
             if (count > 0)
@@ -168,12 +940,12 @@
                     bufferSize = count;
                 }

-                WriteViaBuffer(source, index, count, writeAction, new byte[bufferSize]);
-            }
-        }
-
-        // Calls a write action repeatedly while copying bytes from a sequential source through a buffer.
-        // If the provided source is an IList<byte>, the algorithm used may be random-access instead.
+                WriteViaArray(source, index, count, writeAction, new byte[bufferSize]);
+            }
+        }
+
+        // Calls a write action repeatedly while copying bytes from a sequential source through a
+        // buffer. If the provided source is an IList<byte>, the algorithm used may be random-access instead.
         private static void WriteNoCheck(Action<byte[], int, int> writeAction, IEnumerable<byte> source, int bufferSize)
         {
             {
@@ -190,10 +962,10 @@
                 bufferSize = DefaultWriteBufferSize;
             }

-            WriteViaBuffer(source, writeAction, new byte[bufferSize]);
-        }
-
-        private static void WriteViaBuffer(IList<byte> source, int index, int count, Action<byte[], int, int> writeAction, byte[] copyBuffer)
+            WriteViaArray(source, writeAction, new byte[bufferSize]);
+        }
+
+        private static void WriteViaArray(IList<byte> source, int index, int count, Action<byte[], int, int> writeAction, byte[] copyBuffer)
         {
             while (count > 0)
             {
@@ -205,7 +977,7 @@
             }
         }

-        private static void WriteViaBuffer(IEnumerable<byte> source, Action<byte[], int, int> writeAction, byte[] copyBuffer)
+        private static void WriteViaArray(IEnumerable<byte> source, Action<byte[], int, int> writeAction, byte[] copyBuffer)
         {
             int i = 0;
             int bufferSize = copyBuffer.Length;
@@ -236,7 +1008,9 @@
         /// <param name="source"></param>
         /// <param name="offset"></param>
         /// <param name="count"></param>
-        /// <param name="bufferSize">The size of the temporary buffer used to copy elements from the provided source.</param>
+        /// <param name="bufferSize">
+        /// The size of the temporary buffer used to copy elements from the provided source.
+        /// </param>
         public static void Write(this Stream stream, IList<byte> source, int offset, int count, int bufferSize = 0)
         {
             Checker.NotNull(stream, "stream");
@@ -250,7 +1024,9 @@
         /// </summary>
         /// <param name="stream"></param>
         /// <param name="source"></param>
-        /// <param name="bufferSize">The size of the temporary buffer used to copy elements from the provided source.</param>
+        /// <param name="bufferSize">
+        /// The size of the temporary buffer used to copy elements from the provided source.
+        /// </param>
         public static void Write(this Stream stream, IList<byte> source, int bufferSize = 0)
         {
             Checker.NotNull(stream, "stream");
@@ -263,7 +1039,9 @@
         /// </summary>
         /// <param name="stream"></param>
         /// <param name="source"></param>
-        /// <param name="bufferSize">The size of the temporary buffer used to copy elements from the provided source.</param>
+        /// <param name="bufferSize">
+        /// The size of the temporary buffer used to copy elements from the provided source.
+        /// </param>
         public static void Write(this Stream stream, IEnumerable<byte> source, int bufferSize = 0)
         {
             Checker.NotNull(stream, "stream");
@@ -278,7 +1056,9 @@
         /// <param name="source"></param>
         /// <param name="offset"></param>
         /// <param name="count"></param>
-        /// <param name="bufferSize">The size of the temporary buffer used to copy elements from the provided source.</param>
+        /// <param name="bufferSize">
+        /// The size of the temporary buffer used to copy elements from the provided source.
+        /// </param>
         public static void Write(this BinaryWriter writer, IList<byte> source, int offset, int count, int bufferSize = 0)
         {
             Checker.NotNull(writer, "writer");
@@ -292,7 +1072,9 @@
         /// </summary>
         /// <param name="writer"></param>
         /// <param name="source"></param>
-        /// <param name="bufferSize">The size of the temporary buffer used to copy elements from the provided source.</param>
+        /// <param name="bufferSize">
+        /// The size of the temporary buffer used to copy elements from the provided source.
+        /// </param>
         public static void Write(this BinaryWriter writer, IList<byte> source, int bufferSize = 0)
         {
             Checker.NotNull(writer, "writer");
@@ -305,7 +1087,9 @@
         /// </summary>
         /// <param name="writer"></param>
         /// <param name="source"></param>
-        /// <param name="bufferSize">The size of the temporary buffer used to copy elements from the provided source.</param>
+        /// <param name="bufferSize">
+        /// The size of the temporary buffer used to copy elements from the provided source.
+        /// </param>
         public static void Write(this BinaryWriter writer, IEnumerable<byte> source, int bufferSize = 0)
         {
             Checker.NotNull(writer, "writer");


Add some plugin functions

Add some plugin functions

--- kynnaugh/Plugin.cs
+++ kynnaugh/Plugin.cs
@@ -6,6 +6,8 @@
 using System.Runtime.InteropServices;
 using System.Text;
 using System.Threading.Tasks;
+
+using anyId = System.UInt16;

 namespace kynnaugh
 {
@@ -103,7 +105,7 @@
         [DllExport]
         void ts3plugin_shutdown()
         {
-
+
         }

         /// <summary>
@@ -128,7 +130,7 @@
         {
             Marshal.FreeHGlobal(data);
         }
-
+

         /// <summary>
         /// Plugin requests to be always automatically loaded by the TeamSpeak 3 client unless
@@ -142,5 +144,18 @@
             return 1;  /* 1 = request autoloaded, 0 = do not request autoload */
         }

+        /// <summary>
+        ///
+        /// </summary>
+        /// <param name="serverConnectionHandlerID"></param>
+        /// <param name="clientID"></param>
+        /// <param name="samples">short*</param>
+        /// <param name="sampleCount"></param>
+        /// <param name="channels"></param>
+        [DllExport]
+        void ts3plugin_onEditPlaybackVoiceDataEvent(UInt64 serverConnectionHandlerID, anyId clientID, IntPtr samples,
+                                                        int sampleCount, int channels)
+        {
+        }
     }
 }


OOM exception due to double buffering.

OOM exception due to double buffering.

--- FlatFiles/FixedLengthRecordParser.cs
+++ FlatFiles/FixedLengthRecordParser.cs
@@ -65,13 +65,11 @@
         {
             private readonly RetryReader reader;
             private readonly IRecordSeparatorMatcher matcher;
-            private readonly StringBuilder builder;

             public SeparatorRecordReader(TextReader reader, string? separator)
             {
                 this.reader = new RetryReader(reader);
                 matcher = RecordSeparatorMatcher.GetMatcher(this.reader, separator);
-                builder = new StringBuilder();
             }

             public bool IsEndOfStream()
@@ -100,14 +98,12 @@
                 }
                 while (!matcher.IsMatch() && reader.Read())
                 {
-                    builder.Append(reader.Current);
                     if (reader.ShouldLoadBuffer(matcher.Size))
                     {
                         reader.LoadBuffer();
                     }
                 }
-                string record = builder.ToString();
-                builder.Clear();
+                string record = matcher.Trim(reader.GetRecord());
                 return record;
             }

@@ -119,14 +115,12 @@
                 }
                 while (!matcher.IsMatch() && reader.Read())
                 {
-                    builder.Append(reader.Current);
                     if (reader.ShouldLoadBuffer(matcher.Size))
                     {
                         await reader.LoadBufferAsync().ConfigureAwait(false);
                     }
                 }
-                string record = builder.ToString();
-                builder.Clear();
+                string record = matcher.Trim(reader.GetRecord());
                 return record;
             }
         }


KeyTransation fix migration in NET 3.5SP1 branch

--- Fluent-net35/Fluent/NativeMethods.cs
+++ Fluent-net35/Fluent/NativeMethods.cs
@@ -929,7 +929,7 @@
         /// Unicode character or characters
         /// </summary>
         /// <returns>1, 2 or more if success, otherwise fail</returns>
-        [DllImport("user32.dll", PreserveSig = false, SetLastError = false)]
+        [DllImport("user32.dll", SetLastError = false)]
         public static extern int ToUnicodeEx(uint wVirtKey, uint wScanCode, byte[] lpKeyState, [Out, MarshalAs(UnmanagedType.LPWStr)] System.Text.StringBuilder pwszBuff, int cchBuff, uint wFlags, IntPtr dwhkl);

         /// <summary>


Set default back to Chrome driver.

Set default back to Chrome driver.

--- cs/WebSpecs/Support/Hooks.cs
+++ cs/WebSpecs/Support/Hooks.cs
@@ -24,10 +24,10 @@
             var configuration = new SessionConfiguration
             {
                 // Uncomment the Browser you want
-                //Browser = Browser.Firefox,
+                Browser = Browser.Firefox,
                 //Browser = Browser.Chrome,
                 //Browser = Browser.InternetExplorer,
-                Browser = Browser.PhantomJS,
+                //Browser = Browser.PhantomJS,
             };
             browser = new PageBrowserSession(configuration);
             objectContainer.RegisterInstanceAs(browser);


Add functionality to ExpenditureDate class to compare dates and format year correctly

--- GeneralUseClasses/ExpenditureDate.cs
+++ GeneralUseClasses/ExpenditureDate.cs
@@ -3,21 +3,104 @@
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using GeneralUseClasses.Exceptions;

 namespace GeneralUseClasses

 {
     public class ExpenditureDate
     {
-        public int day { get; set; }
-        public int month { get; set; }
-        public int year { get; set; }
+        public int day;
+        public int month;
+        public int year;
+
+        public ExpenditureDate()
+        {
+            day = new int();
+            month = new int();
+            year = new int();
+        }

         public ExpenditureDate(int day, int month, int year)
         {
             this.day = day;
             this.month = month;
-            this.year = year;
+            FormatYear(year);
+        }
+
+        private void FormatYear(int year)
+        {
+            if (year.ToString().Length == 4)
+            {
+                this.year = year; ;
+            }
+            else if (year.ToString().Length == 2 || year.ToString().Length == 1)
+            {
+                this.year = year + 2000;
+            }
+            else
+            {
+                throw new ExceptionForUser("Year is in unusable format");
+            }
+        }
+
+        public bool IsNotEarlierThan(ExpenditureDate date)
+        {
+            bool isLaterThan = true;
+            if (!(this.year >= date.year))
+            {
+                isLaterThan = false;
+            }
+            else if (!(this.month >= date.month) && this.year == date.year)
+            {
+                isLaterThan = false;
+            }
+            else if (!(this.day >= date.day) && this.month == date.month && this.year == date.year)
+            {
+                isLaterThan = false;
+            }
+
+            return isLaterThan;
+        }
+
+        public bool IsNotLaterThan(ExpenditureDate date)
+        {
+            bool isEarlierThan = true;
+            if (!(this.year <= date.year))
+            {
+                isEarlierThan = false;
+            }
+            else if (!(this.month <= date.month) && this.year == date.year)
+            {
+                isEarlierThan = false;
+            }
+            else if (!(this.day <= date.day) && this.month == date.month && this.year == date.year)
+            {
+                isEarlierThan = false;
+            }
+
+            return isEarlierThan;
+        }
+
+        public override string ToString()
+        {
+            StringBuilder sb = new StringBuilder();
+            sb.Append(this.day.ToString("D2"));
+            sb.Append("/");
+            sb.Append(this.month.ToString("D2"));
+            sb.Append("/");
+            sb.Append(this.year);
+            return sb.ToString();
+        }
+
+        public bool IsTheSameDateAs(ExpenditureDate date)
+        {
+            bool sameDate = false;
+            sameDate = date.day == this.day ? true : false;
+            sameDate = (date.month == this.month) && sameDate ? true : false;
+            sameDate = (date.year == this.year) && sameDate ? true : false;
+
+            return sameDate;
         }
     }
 }


[Modify] Replace it

[Modify] Replace it

--- websocket-sharp/Net/HttpListener.cs
+++ websocket-sharp/Net/HttpListener.cs
@@ -147,7 +147,9 @@
     /// </exception>
     public AuthenticationSchemes AuthenticationSchemes {
       get {
-        CheckDisposed ();
+        if (_disposed)
+          throw new ObjectDisposedException (_objectName);
+
         return _authSchemes;
       }


Fixing auto generation of string properties

--- GenerateUserTypesFromPdb/UserType.cs
+++ GenerateUserTypesFromPdb/UserType.cs
@@ -138,6 +138,10 @@
                 else if (castingTypeString == "NakedPointer" || castingTypeString == "CodeFunction" || castingTypeString.StartsWith("CodeArray") || castingTypeString.StartsWith("CodePointer") || castWithNewInsteadOfCasting)
                 {
                     constructorText = string.Format("new {0}({1})", castingTypeString, simpleFieldValue);
+                }
+                else if (castingTypeString == "string")
+                {
+                    constructorText = string.Format("{0}.ToString()", simpleFieldValue);
                 }
                 else
                 {


[Modify] Replace it

[Modify] Replace it

--- websocket-sharp/Net/HttpListener.cs
+++ websocket-sharp/Net/HttpListener.cs
@@ -572,7 +572,8 @@
       cleanupContextQueue (force);
       cleanupContextRegistry ();

-      var ex = new ObjectDisposedException (_objectName);
+      var msg = "The listener is closed.";
+      var ex = new HttpListenerException (995, msg);
       cleanupWaitQueue (ex);

       EndPointManager.RemoveListener (this);


Fixing progress bar

Fixing progress bar

--- Giftstarter/Views/Home/Pledge.cshtml
+++ Giftstarter/Views/Home/Pledge.cshtml
@@ -30,8 +30,10 @@
                     @gift.Name

@gift.Price.ToString("C")

-

-

+

+

+                                40% Complete (success)
+


added more unity tests

added more unity tests

--- csharp/NewBehaviourScript.cs
+++ csharp/NewBehaviourScript.cs
@@ -63,14 +63,70 @@
 		return texture;
 	}

+	void TestColorStorage()
+	{
+		var colorStorage = new vectorx.ColorStorage (8, 8, null);
+		//System.UInt32 value = 0xff0000ff;
+		System.UInt32 value32 = 0xff0000ff;
+		System.Byte value8 = 0xff;
+		colorStorage.data.memory.Seek (0, System.IO.SeekOrigin.Begin);
+		for (int i = 0; i < colorStorage.data.allocedLength/4; i++)
+		{
+			//colorStorage.data.offset = i;
+			//colorStorage.data.writeUInt8 (value8);
+			colorStorage.data.writer.Write(value32);
+		}
+
+		colorStorage.data.dump ();
+
+		var texture = createTexture (colorStorage);
+		GetComponent<Renderer> ().material.mainTexture = texture;
+		System.Console.Write ("");
+	}
+
+	void TestPixelFormatRenderer()
+	{
+		Debug.Log ("TestPixelFormatRenderer");
+		var colorStorage = new vectorx.ColorStorage (8, 8, null);
+		Debug.Log ("allocated: " + colorStorage.data.allocedLength);
+		lib.ha.core.memory.MemoryAccess.domainMemory = colorStorage.data;
+
+		for (uint i = 0; i < colorStorage.data.allocedLength; i+=4)
+		{
+			Debug.Log (i / 4);
+			lib.ha.aggx.renderer.PixelFormatRenderer.copyOrBlendPix2 (i, 255, 0, 0, 255);
+			colorStorage.data.dump ();
+		}
+
+		var texture = createTexture (colorStorage);
+		GetComponent<Renderer> ().material.mainTexture = texture;
+		System.Console.Write ("");
+	}
+
 	void TestSvg()
 	{
 		var xml = Xml.parse (svgXml.text);
 		var svg = vectorx.svg.SvgContext.parseSvg (xml);
-		var colorStorage = new vectorx.ColorStorage (32, 32, null);
+
+
+		//var svgBinData = new Data (1024);
+		//vectorx.svg.SvgContext.convertSvgToVectorBin (xml, svgBinData);
+		//svgBinData.offset = 0;
+		//var svg = new lib.ha.svg.SVGData();
+		//vectorx.svg.SvgContext.deserializeVectorBin (svgBinData, svg);
+
+		var colorStorage = new vectorx.ColorStorage (512, 512, null);
+		System.Byte value8 = 0xff;
+		colorStorage.data.memory.Seek (0, System.IO.SeekOrigin.Begin);
+		for (int i = 0; i < colorStorage.data.allocedLength; i++)
+		{
+			//colorStorage.data.writer.Write(value8);
+		}
+
 		var context = new vectorx.svg.SvgContext ();
 		var transform = lib.ha.core.geometry.AffineTransformer.translator(0, 0);
 		context.renderVectorBinToColorStorage (svg, colorStorage, transform);
+
 		//colorStorage.data.dump ();

 		var texture = createTexture (colorStorage);
@@ -85,12 +141,15 @@
 		//TestFloat ();
 		//TestData();
 		TestSvg();
+		//TestColorStorage();
+		//TestPixelFormatRenderer();

 		//DataTest.testAll ();
 	}

 	// Update is called once per frame
-	void Update () {
+	void Update ()
+	{

 	}
 }


more info in error message if OCR is not configured

--- ARKBreedingStats/ocr/ArkOCR.cs
+++ ARKBreedingStats/ocr/ArkOCR.cs
@@ -313,7 +313,7 @@
             double[] finalValues = { 0 };
             if (ocrConfig == null)
             {
-                OcrText = "Error: OCR not configured";
+                OcrText = "Error: OCR not configured.\nYou can configure the OCR in the OCR-tab by loading or creating an OCR config-file.\nFor more details see the online manual.";
                 return finalValues;
             }


Use correct field name setting custom fields in LF

In LF, we need to use the "normalized" field names, not the field labels
from FDO.

--- src/LfMerge/DataConverters/ConvertFdoToMongoCustomField.cs
+++ src/LfMerge/DataConverters/ConvertFdoToMongoCustomField.cs
@@ -131,7 +131,7 @@

 				if (bsonForThisField != null)
 				{
-					customFieldData.Add(label, bsonForThisField["value"]);
+					customFieldData.Add(lfCustomFieldName, bsonForThisField["value"]);
 					BsonValue guid;
 					if (bsonForThisField.TryGetValue("guid", out guid))
 					{


HttpListener: Suppress delay sign warnings.

--- src/Microsoft.Owin.Host.HttpListener/GlobalSuppressions.cs
+++ src/Microsoft.Owin.Host.HttpListener/GlobalSuppressions.cs
@@ -58,4 +58,8 @@

 [assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "Microsoft.Owin.Host.HttpListener.WebSockets", Justification = "By Design")]

+[assembly: SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames", Justification = "Delay signed")]
+
+[assembly: SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly", Justification = "Prerelease version has -ver suffix")]
+


MessageConverterHelper. MessageTypes <-> MarketDataTypes for candles

--- Algo/MessageConverterHelper.cs
+++ Algo/MessageConverterHelper.cs
@@ -51,6 +51,16 @@
 			{ typeof(RenkoCandle), typeof(RenkoCandleMessage) },
 		};

+		private static readonly PairSet<MessageTypes, MarketDataTypes> _candleDataTypes = new PairSet<MessageTypes, MarketDataTypes>
+		{
+			{ MessageTypes.CandleTimeFrame, MarketDataTypes.CandleTimeFrame },
+			{ MessageTypes.CandleTick, MarketDataTypes.CandleTick },
+			{ MessageTypes.CandleVolume, MarketDataTypes.CandleVolume },
+			{ MessageTypes.CandleRange, MarketDataTypes.CandleRange },
+			{ MessageTypes.CandlePnF, MarketDataTypes.CandlePnF },
+			{ MessageTypes.CandleRenko, MarketDataTypes.CandleRenko },
+		};
+
 		/// <summary>
 		/// Преобразовать тип свечи <see cref="Candle"/> в тип сообщения <see cref="CandleMessage"/>.
 		/// </summary>
@@ -75,6 +85,26 @@
 				throw new ArgumentNullException("messageType");

 			return _candleTypes.GetKey(messageType);
+		}
+
+		/// <summary>
+		/// Преобразовать тип свечек <see cref="MarketDataTypes"/> в тип сообщения <see cref="MessageTypes"/>.
+		/// </summary>
+		/// <param name="type">Тип свечек.</param>
+		/// <returns>Тип сообщения.</returns>
+		public static MessageTypes ToCandleMessageType(this MarketDataTypes type)
+		{
+			return _candleDataTypes[type];
+		}
+
+		/// <summary>
+		/// Преобразовать тип сообщения <see cref="MessageTypes"/> в тип свечек <see cref="MarketDataTypes"/>.
+		/// </summary>
+		/// <param name="type">Тип сообщения.</param>
+		/// <returns>Тип свечек.</returns>
+		public static MarketDataTypes ToCandleMarketDataType(this MessageTypes type)
+		{
+			return _candleDataTypes[type];
 		}

 		/// <summary>


If already on the IOLoop, execute the read/write instantly if it's a blocking read/write. This fixes a deadlock condition.

svn path=/trunk/bitsharp/; revision=113132

--- src/MonoTorrent/MonoTorrent.Client/Managers/DiskManager.cs
+++ src/MonoTorrent/MonoTorrent.Client/Managers/DiskManager.cs
@@ -167,6 +167,9 @@
             piece.Blocks[index].Written = true;
             id.TorrentManager.FileManager.RaiseBlockWritten(new BlockEventArgs(data));

+            if (data.WaitHandle != null)
+                data.WaitHandle.Set();
+
             // Release the buffer back into the buffer manager.
             //ClientEngine.BufferManager.FreeBuffer(ref bufferedFileIO.Buffer);
 #warning FIX THIS - don't free the buffer here anymore
@@ -175,31 +178,33 @@
             if (!piece.AllBlocksWritten)
                 return;

-            // Hashcheck the piece as we now have all the blocks.
-            bool result = id.TorrentManager.Torrent.Pieces.IsValid(id.TorrentManager.FileManager.GetHash(piece.Index, false), piece.Index);
-            id.TorrentManager.Bitfield[data.PieceIndex] = result;
-
-            ClientEngine.MainLoop.QueueWait(delegate {
-                id.TorrentManager.PieceManager.UnhashedPieces[piece.Index] = false;
-            });
-
-            id.TorrentManager.HashedPiece(new PieceHashedEventArgs(id.TorrentManager, piece.Index, result));
-            List<PeerId> peers = new List<PeerId>(piece.Blocks.Length);
-            for (int i = 0; i < piece.Blocks.Length; i++)
-                if (piece.Blocks[i].RequestedOff != null && !peers.Contains(piece.Blocks[i].RequestedOff))
-                    peers.Add(piece.Blocks[i].RequestedOff);
-
-            for (int i = 0; i < peers.Count; i++)
-                if (peers[i].Connection != null)
-                    id.Peer.HashedPiece(result);
-
-            // If the piece was successfully hashed, enqueue a new "have" message to be sent out
-            if (result)
-            {
-                ClientEngine.MainLoop.Queue(delegate {
-                    id.TorrentManager.finishedPieces.Enqueue(piece.Index);
+            IOLoop.Queue(delegate {
+                // Hashcheck the piece as we now have all the blocks.
+                bool result = id.TorrentManager.Torrent.Pieces.IsValid(id.TorrentManager.FileManager.GetHash(piece.Index, false), piece.Index);
+                id.TorrentManager.Bitfield[data.PieceIndex] = result;
+
+                ClientEngine.MainLoop.QueueWait(delegate {
+                    id.TorrentManager.PieceManager.UnhashedPieces[piece.Index] = false;
                 });
-            }
+
+                id.TorrentManager.HashedPiece(new PieceHashedEventArgs(id.TorrentManager, piece.Index, result));
+                List<PeerId> peers = new List<PeerId>(piece.Blocks.Length);
+                for (int i = 0; i < piece.Blocks.Length; i++)
+                    if (piece.Blocks[i].RequestedOff != null && !peers.Contains(piece.Blocks[i].RequestedOff))
+                        peers.Add(piece.Blocks[i].RequestedOff);
+
+                for (int i = 0; i < peers.Count; i++)
+                    if (peers[i].Connection != null)
+                        id.Peer.HashedPiece(result);
+
+                // If the piece was successfully hashed, enqueue a new "have" message to be sent out
+                if (result)
+                {
+                    ClientEngine.MainLoop.Queue(delegate {
+                        id.TorrentManager.finishedPieces.Enqueue(piece.Index);
+                    });
+                }
+            });
         }

         private void PerformRead(BufferedIO io)
@@ -231,16 +236,22 @@

         internal void QueueRead(BufferedIO io)
         {
-            IOLoop.Queue(delegate {
-                bufferedReads.Enqueue(io);
-            });
+            if (Thread.CurrentThread == IOLoop.thread && io.WaitHandle != null)
+                PerformRead(io);
+            else
+                IOLoop.Queue(delegate {
+                    bufferedReads.Enqueue(io);
+                });
         }

         internal void QueueWrite(BufferedIO io)
         {
-            IOLoop.Queue(delegate {
-                bufferedWrites.Enqueue(io);
-            });
+            if (Thread.CurrentThread == IOLoop.thread && io.WaitHandle != null)
+                PerformWrite(io);
+            else
+                IOLoop.Queue(delegate {
+                    bufferedWrites.Enqueue(io);
+                });
         }

         #endregion


Bug fixes in SQL Tokenizer.

Bug fixes in SQL Tokenizer.

--- src/NHibernate/SqlCommand/Parser/SqlTokenizerExtensions.cs
+++ src/NHibernate/SqlCommand/Parser/SqlTokenizerExtensions.cs
@@ -62,7 +62,7 @@
 				// [ TOP { integer | ( expression ) } [PERCENT] [ WITH TIES ] ]
 				if (tokenEnum.Current.Equals("top", StringComparison.InvariantCultureIgnoreCase))
 				{
-					if (tokenEnum.MoveNext()) return false;
+					if (!tokenEnum.MoveNext()) return false;
 					if (tokenEnum.Current.TokenType == SqlTokenType.BracketOpen)
 					{
 						do
@@ -70,8 +70,7 @@
 							if (!tokenEnum.MoveNext()) return false;
 						} while (tokenEnum.Current.TokenType != SqlTokenType.BracketClose);
 					}
-					if (tokenEnum.MoveNext()) return false;
-
+					if (!tokenEnum.MoveNext()) return false;

 					if (tokenEnum.Current.Equals("percent", StringComparison.InvariantCultureIgnoreCase))
 					{


Correct property to bson field name mapping when sagadata class is inherited

--- src/NServiceBus.Persistence.MongoDb/Sagas/SagaPersister.cs
+++ src/NServiceBus.Persistence.MongoDb/Sagas/SagaPersister.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Linq;
 using MongoDB.Bson.Serialization;
 using NServiceBus.Persistence.MongoDB.Database;
 using NServiceBus.Saga;
@@ -33,8 +34,7 @@
             }

             var classmap = BsonClassMap.LookupClassMap(sagaDataType);
-            var membermap = classmap.GetMemberMap(uniqueProperty.Name);
-            var uniqueFieldName = membermap.ElementName;
+            var uniqueFieldName = GetFieldName(classmap, uniqueProperty.Name);

             _repo.EnsureUniqueIndex(sagaDataType, uniqueFieldName);
         }
@@ -52,9 +52,7 @@
             var version = (int)versionProperty.GetValue(saga);

             var classmap = BsonClassMap.LookupClassMap(sagaDataType);
-            var membermap = classmap.GetMemberMap(versionProperty.Name);
-            var versionFieldName = membermap.ElementName;
-
+            var versionFieldName = GetFieldName(classmap, versionProperty.Name);

             _repo.Update(saga, versionFieldName, version);
         }
@@ -67,8 +65,7 @@
         public T Get<T>(string property, object value) where T : IContainSagaData
         {
             var classmap = BsonClassMap.LookupClassMap(typeof(T));
-            var membermap = classmap.GetMemberMap(property);
-            var propertyFieldName = membermap.ElementName;
+            var propertyFieldName = GetFieldName(classmap, property);

             var result = _repo.FindByFieldName<T>(propertyFieldName, value);
             return result;
@@ -78,5 +75,11 @@
         {
             _repo.Remove(saga);
         }
+
+        private string GetFieldName(BsonClassMap classMap, string property)
+        {
+            var element = classMap.AllMemberMaps.First(m => m.MemberName == property);
+            return element.ElementName;
+        }
     }
 }


fix redis expires test bug

fix redis expires test bug

--- src/OrigoDB.Core.UnitTests/Models/Redis/ExpirationTests.cs
+++ src/OrigoDB.Core.UnitTests/Models/Redis/ExpirationTests.cs
@@ -20,6 +20,7 @@
             target.Set(key, "value");
             var expires = DateTime.Now;
             target.Expire(key, expires);
+            Thread.Sleep(TimeSpan.FromMilliseconds(1));
             var keys = target.GetExpiredKeys();
             Assert.IsTrue(keys.Single() == key);
             var expected = target.Expires(key);


Revert "Quarantine all ProjectTemplate tests until dotnet new lock issue is resolved." (#21831)

This reverts commit 9a5d3c7640de12d8f7ecba53e9e49433a4d47588.

--- src/ProjectTemplates/test/AssemblyInfo.AssemblyFixtures.cs
+++ src/ProjectTemplates/test/AssemblyInfo.AssemblyFixtures.cs
@@ -10,5 +10,3 @@

 [assembly: Microsoft.AspNetCore.E2ETesting.AssemblyFixture(typeof(ProjectFactoryFixture))]
 [assembly: Microsoft.AspNetCore.E2ETesting.AssemblyFixture(typeof(SeleniumStandaloneServer))]
-
-[assembly: QuarantinedTest("Investigation pending in https://github.com/dotnet/aspnetcore/issues/21748")]


Add more null checks on LineMarker

Add more null checks on LineMarker

--- src/Sarif.Viewer.VisualStudio/Models/SarifErrorListItem.cs
+++ src/Sarif.Viewer.VisualStudio/Models/SarifErrorListItem.cs
@@ -285,23 +285,23 @@

         internal void RemoveMarkers()
         {
-            LineMarker.RemoveMarker();
+            LineMarker?.RemoveMarker();

             foreach (AnnotatedCodeLocationModel location in this.Locations)
             {
-                location.LineMarker.RemoveMarker();
+                location.LineMarker?.RemoveMarker();
             }

             foreach (AnnotatedCodeLocationModel location in this.RelatedLocations)
             {
-                location.LineMarker.RemoveMarker();
+                location.LineMarker?.RemoveMarker();
             }

             foreach (AnnotatedCodeLocationCollection locationCollection in this.CodeFlows)
             {
                 foreach (AnnotatedCodeLocationModel location in locationCollection)
                 {
-                    location.LineMarker.RemoveMarker();
+                    location.LineMarker?.RemoveMarker();
                 }
             }

@@ -309,7 +309,7 @@
             {
                 foreach (StackFrameModel stackFrame in stackCollection)
                 {
-                    stackFrame.LineMarker.RemoveMarker();
+                    stackFrame.LineMarker?.RemoveMarker();
                 }
             }
         }
@@ -399,7 +399,7 @@

         internal void AttachToDocument(string documentName, long docCookie, IVsWindowFrame pFrame)
         {
-            LineMarker.AttachToDocument(documentName, docCookie, pFrame);
+            LineMarker?.AttachToDocument(documentName, docCookie, pFrame);

             foreach (AnnotatedCodeLocationModel location in this.Locations)
             {
@@ -430,7 +430,7 @@

         internal void DetachFromDocument(long docCookie)
         {
-            LineMarker.DetachFromDocument(docCookie);
+            LineMarker?.DetachFromDocument(docCookie);

             foreach (AnnotatedCodeLocationModel location in this.Locations)
             {


Fix order of Assert.Equal args

Fix order of Assert.Equal args

Also make a few Equals into Sames

--- src/System.Net.WebSockets/tests/WebSocketExceptionTests.cs
+++ src/System.Net.WebSockets/tests/WebSocketExceptionTests.cs
@@ -35,8 +35,8 @@
         public void ConstructorTests_WebSocketError_Success(WebSocketError error)
         {
             var wse = new WebSocketException(error);
-            Assert.Equal(wse.WebSocketErrorCode, error);
-            Assert.NotEqual(wse.Message, "");
+            Assert.Equal(error, wse.WebSocketErrorCode);
+            Assert.NotEqual("", wse.Message);
             Assert.Null(wse.InnerException);
         }

@@ -45,8 +45,8 @@
         {
             const string Message = "Message";
             var wse = new WebSocketException(error, Message);
-            Assert.Equal(wse.WebSocketErrorCode, error);
-            Assert.Equal(wse.Message, Message);
+            Assert.Equal(error, wse.WebSocketErrorCode);
+            Assert.Equal(Message, wse.Message);
             Assert.Null(wse.InnerException);
         }

@@ -55,9 +55,9 @@
         {
             var inner = new Exception();
             var wse = new WebSocketException(error, inner);
-            Assert.Equal(wse.WebSocketErrorCode, error);
-            Assert.NotEqual(wse.Message, "");
-            Assert.Equal(wse.InnerException, inner);
+            Assert.Equal(error, wse.WebSocketErrorCode);
+            Assert.NotEqual("", wse.Message);
+            Assert.Same(inner, wse.InnerException);
         }

         [Theory, MemberData(nameof(ErrorData))]
@@ -66,9 +66,9 @@
             const string Message = "Message";
             var inner = new Exception();
             var wse = new WebSocketException(error, Message, inner);
-            Assert.Equal(wse.WebSocketErrorCode, error);
-            Assert.Equal(wse.Message, Message);
-            Assert.Equal(wse.InnerException, inner);
+            Assert.Equal(error, wse.WebSocketErrorCode);
+            Assert.Equal(Message, wse.Message);
+            Assert.Same(inner, wse.InnerException);
         }

         [Theory, MemberData(nameof(NativeErrorData))]
@@ -76,8 +76,8 @@
         {
             var wse = new WebSocketException(nativeError);
             Assert.Equal(expectedHResult, wse.HResult);
-            Assert.Equal(wse.WebSocketErrorCode, webSocketError);
-            Assert.NotEqual(wse.Message, "");
+            Assert.Equal(webSocketError, wse.WebSocketErrorCode);
+            Assert.NotEqual("", wse.Message);
             Assert.Null(wse.InnerException);
         }

@@ -87,8 +87,8 @@
             const string Message = "Message";
             var wse = new WebSocketException(nativeError, Message);
             Assert.Equal(expectedHResult, wse.HResult);
-            Assert.Equal(wse.WebSocketErrorCode, webSocketError);
-            Assert.Equal(wse.Message, Message);
+            Assert.Equal(webSocketError, wse.WebSocketErrorCode);
+            Assert.Equal(Message, wse.Message);
             Assert.Null(wse.InnerException);
         }

@@ -98,9 +98,9 @@
             var inner = new Exception();
             var wse = new WebSocketException(nativeError, inner);
             Assert.Equal(expectedHResult, wse.HResult);
-            Assert.Equal(wse.WebSocketErrorCode, webSocketError);
-            Assert.NotEqual(wse.Message, "");
-            Assert.Equal(wse.InnerException, inner);
+            Assert.Equal(webSocketError, wse.WebSocketErrorCode);
+            Assert.NotEqual("", wse.Message);
+            Assert.Same(inner, wse.InnerException);
         }

         [Theory, MemberData(nameof(UnrelatedErrorData))]
@@ -108,8 +108,8 @@
         {
             var wse = new WebSocketException(error, nativeError);
             Assert.Equal(expectedHResult, wse.HResult);
-            Assert.Equal(wse.WebSocketErrorCode, error);
-            Assert.NotEqual(wse.Message, "");
+            Assert.Equal(error, wse.WebSocketErrorCode);
+            Assert.NotEqual("", wse.Message);
             Assert.Null(wse.InnerException);
         }

@@ -119,8 +119,8 @@
             const string Message = "Message";
             var wse = new WebSocketException(error, nativeError, Message);
             Assert.Equal(expectedHResult, wse.HResult);
-            Assert.Equal(wse.WebSocketErrorCode, error);
-            Assert.Equal(wse.Message, Message);
+            Assert.Equal(error, wse.WebSocketErrorCode);
+            Assert.Equal(Message, wse.Message);
             Assert.Null(wse.InnerException);
         }

@@ -130,9 +130,9 @@
             var inner = new Exception();
             var wse = new WebSocketException(error, nativeError, inner);
             Assert.Equal(expectedHResult, wse.HResult);
-            Assert.Equal(wse.WebSocketErrorCode, error);
-            Assert.NotEqual(wse.Message, "");
-            Assert.Equal(wse.InnerException, inner);
+            Assert.Equal(error, wse.WebSocketErrorCode);
+            Assert.NotEqual("", wse.Message);
+            Assert.Same(inner, wse.InnerException);
         }

         [Theory, MemberData(nameof(UnrelatedErrorData))]
@@ -142,9 +142,9 @@
             var inner = new Exception();
             var wse = new WebSocketException(error, nativeError, Message, inner);
             Assert.Equal(expectedHResult, wse.HResult);
-            Assert.Equal(wse.WebSocketErrorCode, error);
-            Assert.Equal(wse.Message, Message);
-            Assert.Equal(wse.InnerException, inner);
+            Assert.Equal(error, wse.WebSocketErrorCode);
+            Assert.Equal(Message, wse.Message);
+            Assert.Same(inner, wse.InnerException);
         }

         [Fact]
@@ -152,8 +152,8 @@
         {
             const string Message = "Message";
             var wse = new WebSocketException(Message);
-            Assert.Equal(wse.WebSocketErrorCode, WebSocketError.Success);
-            Assert.Equal(wse.Message, Message);
+            Assert.Equal(WebSocketError.Success, wse.WebSocketErrorCode);
+            Assert.Equal(Message, wse.Message);
             Assert.Null(wse.InnerException);
         }

@@ -163,9 +163,9 @@
             const string Message = "Message";
             var inner = new Exception();
             var wse = new WebSocketException(Message, inner);
-            Assert.Equal(wse.WebSocketErrorCode, WebSocketError.Success);
-            Assert.Equal(wse.Message, Message);
-            Assert.Equal(wse.InnerException, inner);
+            Assert.Equal(WebSocketError.Success, wse.WebSocketErrorCode);
+            Assert.Equal(Message, wse.Message);
+            Assert.Same(inner, wse.InnerException);
         }
     }
 }


Improved error message when service stack generation fails.

--- src/TypeScriptDefinitionsGenerator.Common/MainGenerator.cs
+++ src/TypeScriptDefinitionsGenerator.Common/MainGenerator.cs
@@ -561,61 +561,73 @@

                 foreach (var request in requests)
                 {
-                    var requestModel = new ServiceStackRequestModel();
-                    model.Requests.Add(requestModel);
-                    var returnType = _ssHelper.GetResponseTypeForRequest(request);
-                    var returnsVoid = _ssHelper.ReturnsVoid(request);
-
-                    var returnTypeTypeScriptName = returnsVoid ? "void" : (returnType != null ? TypeConverter.GetTypeScriptName(returnType) : "any");
-                    var routes = request.GetCustomAttributes().Where(attr => attr.GetType().FullName == "ServiceStack.RouteAttribute");
-
-                    if (!routes.Any()) continue;
-                    allRequests.Add(request.Name);
-                    requestModel.ReturnTypeTypeScriptName = returnTypeTypeScriptName;
-
-                    requestModel.Name = request.Name;
-
-                    var items = new List<ServiceStackRouteInfo>();
-                    foreach (var route in routes)
-                    {
-                        var verbs = route.GetType().GetProperty("Verbs").GetValue(route) as string;
-                        var path = route.GetType().GetProperty("Path").GetValue(route) as string;
-
-                        foreach (var verb in verbs.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).Select(v => v.Trim()))
-                        {
-                            if (verb.Equals("Options", StringComparison.OrdinalIgnoreCase)) continue;
-
-                            var url = _ssHelper.GenerateUrlFromRoute(path, request, verb.Equals("get", StringComparison.OrdinalIgnoreCase), out var routeParameters);
-                            var routeInfo = new ServiceStackRouteInfo(verb, path, url, routeParameters);
-                            routeInfo.ReturnTypeTypeScriptName = requestModel.ReturnTypeTypeScriptName;
-                            items.Add(routeInfo);
-                            requestModel.Routes.Add(routeInfo);
+                    try
+                    {
+                        var requestModel = new ServiceStackRequestModel();
+                        model.Requests.Add(requestModel);
+                        var returnType = _ssHelper.GetResponseTypeForRequest(request);
+                        var returnsVoid = _ssHelper.ReturnsVoid(request);
+
+                        var returnTypeTypeScriptName = returnsVoid ? "void" : (returnType != null ? TypeConverter.GetTypeScriptName(returnType) : "any");
+                        var routes = request.GetCustomAttributes().Where(attr => attr.GetType().FullName == "ServiceStack.RouteAttribute");
+
+                        if (!routes.Any()) continue;
+                        allRequests.Add(request.Name);
+                        requestModel.ReturnTypeTypeScriptName = returnTypeTypeScriptName;
+
+                        requestModel.Name = request.Name;
+
+                        var items = new List<ServiceStackRouteInfo>();
+                        foreach (var route in routes)
+                        {
+                            var verbs = route.GetType().GetProperty("Verbs").GetValue(route) as string;
+                            var path = route.GetType().GetProperty("Path").GetValue(route) as string;
+
+                            if (string.IsNullOrWhiteSpace(verbs)) throw new Exception("No HTTP verbs defined");
+                            if (string.IsNullOrWhiteSpace(path)) throw new Exception("No route path defined");
+
+                            foreach (var verb in verbs.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).Select(v => v.Trim()))
+                            {
+                                if (verb.Equals("Options", StringComparison.OrdinalIgnoreCase)) continue;
+
+                                var url = _ssHelper.GenerateUrlFromRoute(path, request, verb.Equals("get", StringComparison.OrdinalIgnoreCase), out var routeParameters);
+                                var routeInfo = new ServiceStackRouteInfo(verb, path, url, routeParameters);
+                                routeInfo.ReturnTypeTypeScriptName = requestModel.ReturnTypeTypeScriptName;
+                                items.Add(routeInfo);
+                                requestModel.Routes.Add(routeInfo);
+                            }
                         }
-                    }
-
-                    foreach (var item in items)
-                    {
-                        var actionParameters = _ssHelper.GetActionParameters(request, item);
-                        item.ActionParameters = actionParameters;
-                        if (item.Verb == "POST" || item.Verb == "PUT" || item.Verb == "PATCH")
-                        {
-                            actionParameters.Add(new ActionParameterInfo
+
+                        foreach (var item in items)
+                        {
+                            var actionParameters = _ssHelper.GetActionParameters(request, item);
+                            item.ActionParameters = actionParameters;
+                            if (item.Verb == "POST" || item.Verb == "PUT" || item.Verb == "PATCH")
                             {
-                                Name = "body",
-                                Type = TypeConverter.GetTypeScriptName(request)
-                            });
-                            actionParameters.ForEach(a =>
-                            {
-                                if (a.Type.Contains(".") && !a.Type.StartsWith("Enums."))
+                                actionParameters.Add(new ActionParameterInfo
                                 {
-                                    foreach (var s in a.Type.GetTopLevelNamespaces())
+                                    Name = "body",
+                                    Type = TypeConverter.GetTypeScriptName(request)
+                                });
+                                actionParameters.ForEach(a =>
+                                {
+                                    if (a.Type.Contains(".") && !a.Type.StartsWith("Enums."))
                                     {
-                                        requiredImports.Add(s);
+                                        foreach (var s in a.Type.GetTopLevelNamespaces())
+                                        {
+                                            requiredImports.Add(s);
+                                        }
                                     }
-                                }
-                            });
-                            item.ActionParameters = actionParameters;
+                                });
+                                item.ActionParameters = actionParameters;
+                            }
                         }
+                    }
+                    catch (Exception ex)
+                    {
+                        Console.WriteLine("Failure processing request type: " + request.FullName);
+                        Console.WriteLine("Message: " + ex.Message);
+                        throw;
                     }
                 }
             }


Fixing Window.MaybeUpdateData not to return true every time when Repo is null

--- src/UnityExtension/Assets/Editor/GitHub.Unity/UI/Window.cs
+++ src/UnityExtension/Assets/Editor/GitHub.Unity/UI/Window.cs
@@ -217,15 +217,20 @@
             else
             {
                 nextTab = SubTab.InitProject;
-                repoBranch = null;
-                repoUrl = null;
-            }
-
-            if (repoUrl == null)
-            {
-                repoUrl = DefaultRepoUrl;
-                repoDataChanged = true;
-            }
+
+                if (repoBranch != null)
+                {
+                    repoBranch = null;
+                    repoDataChanged = true;
+                }
+
+                if (repoUrl != DefaultRepoUrl)
+                {
+                    repoUrl = DefaultRepoUrl;
+                    repoDataChanged = true;
+                }
+            }
+
             return repoDataChanged;
         }


Bugfix: If Satu Mare is selected as favorite county, the performers page is not loaded

--- src/WebClient/Controllers/IndicatorPerformersController.cs
+++ src/WebClient/Controllers/IndicatorPerformersController.cs
@@ -27,6 +27,7 @@

         private async Task<object> GetData(bool get12Months, string favouriteCounties)
         {
+            favouriteCounties = favouriteCounties.Replace("Satu Mare", "SatuMare");
             var favouriteCountiesIds = string.IsNullOrWhiteSpace(favouriteCounties) ? new List<int>() : favouriteCounties.Split(' ').Select(x => CountryIds.Counties[x.Replace("-", string.Empty)]);
             var months = GetMonths();
             var performers = new List<IndicatorPerformers>();


fixup! Move to constructors in Tasks tests

--- src/XMakeTasks/UnitTests/ResolveAssemblyReference_Tests.cs
+++ src/XMakeTasks/UnitTests/ResolveAssemblyReference_Tests.cs
@@ -23,7 +23,7 @@

 namespace Microsoft.Build.UnitTests.ResolveAssemblyReference_Tests
 {
-    public class ResolveAssemblyReferenceTestFixture
+    public class ResolveAssemblyReferenceTestFixture : IDisposable
     {
         // Create the mocks.
         internal static Microsoft.Build.Shared.FileExists fileExists = new Microsoft.Build.Shared.FileExists(FileExists);
@@ -166,14 +166,12 @@
 </FileList>"
 ;

-        [TestInitialize]
-        public void Setup()
+        public ResolveAssemblyReferenceTestFixture()
         {
             Environment.SetEnvironmentVariable("MSBUILDDISABLEASSEMBLYFOLDERSEXCACHE", "1");
         }

-        [TestCleanup]
-        public void Cleanup()
+        public void Dispose()
         {
             Environment.SetEnvironmentVariable("MSBUILDDISABLEASSEMBLYFOLDERSEXCACHE", null);
         }


Handle new default value in the code generator.

--- src/CodeGenerator/Program.cs
+++ src/CodeGenerator/Program.cs
@@ -72,6 +72,7 @@
             { "ImVec4(1,1,1,1)", "new Vector4(1, 1, 1, 1)" },
             { "ImDrawCornerFlags_All", "(int)ImDrawCornerFlags.All" },
             { "FLT_MAX", "float.MaxValue" },
+            { "(((ImU32)(255)<<24)|((ImU32)(255)<<16)|((ImU32)(255)<<8)|((ImU32)(255)<<0))", "0xFFFFFFFF" }
         };

         private static readonly Dictionary<string, string> s_identifierReplacements = new Dictionary<string, string>()


expose Module from IGenericParameterProvider

--- Mono.Cecil/IGenericParameterProvider.cs
+++ Mono.Cecil/IGenericParameterProvider.cs
@@ -35,6 +35,7 @@

 		bool HasGenericParameters { get; }
 		bool IsDefinition { get; }
+		ModuleDefinition Module { get; }
 		Collection<GenericParameter> GenericParameters { get; }
 		GenericParameterType GenericParameterType { get; }
 	}


removed useless extra min/max calc

removed useless extra min/max calc

--- MonoGameSceneGraph/Source/Nodes/Node.cs
+++ MonoGameSceneGraph/Source/Nodes/Node.cs
@@ -499,8 +499,6 @@
                     BoundingBox curr = child.GetBoundingBox();
                     min = Vector3.Min(min, curr.Min);
                     max = Vector3.Max(max, curr.Max);
-                    min = Vector3.Min(min, curr.Max);
-                    max = Vector3.Max(max, curr.Min);
                 }
             }

@@ -510,8 +508,6 @@
                 BoundingBox curr = entity.GetBoundingBox(this, _localTransform, _worldTransform);
                 min = Vector3.Min(min, curr.Min);
                 max = Vector3.Max(max, curr.Max);
-                min = Vector3.Min(min, curr.Max);
-                max = Vector3.Max(max, curr.Min);
             }

             // return final bounding box


Fixed crashing on games that have no template folders

--- HedgeEdit/Assets/Scripts/GameList.cs
+++ HedgeEdit/Assets/Scripts/GameList.cs
@@ -43,12 +43,15 @@
                        dataType = dataTypeAttr.Value;

                 //Game Entry
+                var templates = LoadObjectTemplates(shortName);
+                if (templates == null) continue;
+
                 var game = new GameEntry()
                 {
                     Name = (nameAttr == null) ? shortName : nameAttr.Value,
                     DataType = dataType,
                     GameDataType = DataTypes.GetDataType(dataType),
-                    ObjectTemplates = LoadObjectTemplates(shortName),
+                    ObjectTemplates = templates,
                     UnitMultiplier = (unitMultiplierAttr == null) ? 1 :
                         System.Convert.ToSingle(unitMultiplierAttr.Value)
                 };
@@ -112,7 +115,7 @@

                 Games.Add(shortName, game);

-                UnityEngine.Debug.Log("Loaded " + game.ObjectTemplates.Count +
+                Debug.Log("Loaded " + game.ObjectTemplates.Count +
                     " templates for " + game.Name + "."); //TODO: REMOVE THIS
             }