using J2N.Collections;
using Lucene.Net.Diagnostics;
using Lucene.Net.Util;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
#if NETSTANDARD2_0_OR_GREATER
using System.Runtime.InteropServices;
#endif
using System.Text;

namespace Lucene.Net.Support
{
    /*
     * Licensed to the Apache Software Foundation (ASF) under one or more
     * contributor license agreements.  See the NOTICE file distributed with
     * this work for additional information regarding copyright ownership.
     * The ASF licenses this file to You under the Apache License, Version 2.0
     * (the "License"); you may not use this file except in compliance with
     * the License.  You may obtain a copy of the License at
     *
     *     http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */

    internal static class Arrays
    {
        /// <summary>
        /// Compares the entire members of one array with the other one.
        /// </summary>
        /// <param name="a">The array to be compared.</param>
        /// <param name="b">The array to be compared with.</param>
        /// <returns>Returns true if the two specified arrays of Objects are equal
        /// to one another. The two arrays are considered equal if both arrays
        /// contain the same number of elements, and all corresponding pairs of
        /// elements in the two arrays are equal. Two objects e1 and e2 are
        /// considered equal if (e1==null ? e2==null : e1.Equals(e2)). In other
        /// words, the two arrays are equal if they contain the same elements in
        /// the same order. Also, two array references are considered equal if
        /// both are null.
        /// <para/>
        /// Note that if the type of <typeparam name="T"/> is a <see cref="IDictionary{TKey, TValue}"/>,
        /// <see cref="IList{T}"/>, or <see cref="ISet{T}"/>, its values and any nested collection values
        /// will be compared for equality as well.
        /// </returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool Equals<T>(T[] a, T[] b)
        {
            return ArrayEqualityComparer<T>.OneDimensional.Equals(a, b);
        }

        /// <summary>
        /// Returns a hash code based on the contents of the given array. For any two
        /// <typeparamref name="T"/> arrays <c>a</c> and <c>b</c>, if
        /// <c>Arrays.Equals(b)</c> returns <c>true</c>, it means
        /// that the return value of <c>Arrays.GetHashCode(a)</c> equals <c>Arrays.GetHashCode(b)</c>.
        /// </summary>
        /// <typeparam name="T">The array element type.</typeparam>
        /// <param name="array">The array whose hash code to compute.</param>
        /// <returns>The hash code for <paramref name="array"/>.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static int GetHashCode<T>(T[] array)
        {
            return ArrayEqualityComparer<T>.OneDimensional.GetHashCode(array);
        }

        /// <summary>
        /// Assigns the specified value to each element of the specified array.
        /// </summary>
        /// <typeparam name="T">the type of the array</typeparam>
        /// <param name="a">the array to be filled</param>
        /// <param name="val">the value to be stored in all elements of the array</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void Fill<T>(T[] a, T val)
        {
            ArrayFiller<T>.Default.Fill(a, val, 0, a.Length);
        }

        /// <summary>
        /// Assigns the specified long value to each element of the specified
        /// range of the specified array of longs.  The range to be filled
        /// extends from index <paramref name="fromIndex"/>, inclusive, to index
        /// <paramref name="toIndex"/>, exclusive.  (If <c>fromIndex==toIndex</c>, the
        /// range to be filled is empty.)
        /// </summary>
        /// <typeparam name="T">the type of the array</typeparam>
        /// <param name="a">the array to be filled</param>
        /// <param name="fromIndex">
        /// the index of the first element (inclusive) to be
        /// filled with the specified value
        /// </param>
        /// <param name="toIndex">
        /// the index of the last element (exclusive) to be
        /// filled with the specified value
        /// </param>
        /// <param name="val">the value to be stored in all elements of the array</param>
        /// <exception cref="ArgumentException">if <c>fromIndex &gt; toIndex</c></exception>
        /// <exception cref="ArgumentOutOfRangeException">if <c>fromIndex &lt; 0</c> or <c>toIndex &gt; a.Length</c></exception>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void Fill<T>(T[] a, int fromIndex, int toIndex, T val)
        {
            //Java Arrays.fill exception logic
            if (fromIndex > toIndex)
                throw new ArgumentException("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
            if (fromIndex < 0)
                throw new ArgumentOutOfRangeException(nameof(fromIndex));
            if (toIndex > a.Length)
                throw new ArgumentOutOfRangeException(nameof(toIndex));

            int length = toIndex - fromIndex;
            ArrayFiller<T>.Default.Fill(a, val, fromIndex, length);
        }

        #region ArrayFiller<T>
        private static class ArrayFiller<T>
        {
            public static readonly IArrayFiller<T> Default = LoadArrayFiller();

            private static IArrayFiller<T> LoadArrayFiller()
            {
#if FEATURE_ARRAY_FILL
                if (PlatformDetection.IsNetCore)
                    return new SpanFillArrayFiller<T>();

                return new ArrayFillArrayFiller<T>();
#else
                return new SpanFillArrayFiller<T>();
#endif
            }

        }

        private interface IArrayFiller<in T>
        {
            void Fill(T[] array, T value, int startIndex, int count);
        }

#if FEATURE_ARRAY_FILL
        private sealed class ArrayFillArrayFiller<T> : IArrayFiller<T>
        {
            public void Fill(T[] array, T value, int startIndex, int count)
            {
                Array.Fill(array, value, startIndex, count);
            }
        }
#endif
        private sealed class SpanFillArrayFiller<T> : IArrayFiller<T>
        {
            public void Fill(T[] array, T value, int startIndex, int count)
            {
                array.AsSpan(startIndex, count).Fill(value);
            }
        }

        #endregion ArrayFiller<T>

        /// <summary>
        /// Copies a range of elements from an Array starting at the first element and pastes them
        /// into another Array starting at the first element. The length is specified as a 32-bit integer.
        /// <para/>
        /// <b>Usage Note:</b> This implementation uses the most efficient (known) method for copying the
        /// array based on the data type and platform.
        /// </summary>
        /// <typeparam name="T">The array type.</typeparam>
        /// <param name="sourceArray">The Array that contains the data to copy.</param>
        /// <param name="destinationArray">The Array that receives the data.</param>
        /// <param name="length">A 32-bit integer that represents the number of elements to copy.</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void Copy<T>(T[] sourceArray, T[] destinationArray, int length)
        {
            if (length == 0)
                return;

            if (Debugging.AssertsEnabled) // LUCENENET: Since this is internal, we are relying on Debugging.Assert to ensure the values passed in are correct.
            {
                Debugging.Assert(sourceArray is not null);
                Debugging.Assert(destinationArray is not null);
                Debugging.Assert(length >= 0 || length <= sourceArray.Length || length <= destinationArray.Length);
            }

            ArrayCopier<T>.Default.Copy(sourceArray, sourceIndex: 0, destinationArray, destinationIndex: 0, length);
        }

        /// <summary>
        /// Copies a range of elements from an Array starting at the specified source index and pastes them
        /// to another Array starting at the specified destination index. The length and the indexes are
        /// specified as 32-bit integers.
        /// <para/>
        /// <b>Usage Note:</b> This implementation uses the most efficient (known) method for copying the
        /// array based on the data type and platform.
        /// </summary>
        /// <typeparam name="T">The array type.</typeparam>
        /// <param name="sourceArray">The Array that contains the data to copy.</param>
        /// <param name="sourceIndex">A 32-bit integer that represents the index in the
        /// <paramref name="sourceArray"/> at which copying begins.</param>
        /// <param name="destinationArray">The Array that receives the data.</param>
        /// <param name="destinationIndex">A 32-bit integer that represents the index in the
        /// <paramref name="destinationArray"/> at which storing begins.</param>
        /// <param name="length">A 32-bit integer that represents the number of elements to copy.</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void Copy<T>(T[] sourceArray, int sourceIndex, T[] destinationArray, int destinationIndex, int length)
        {
            if (length == 0)
                return;

            if (Debugging.AssertsEnabled) // LUCENENET: Since this is internal, we are relying on Debugging.Assert to ensure the values passed in are correct.
            {
                Debugging.Assert(sourceArray is not null);
                Debugging.Assert(destinationArray is not null);
                Debugging.Assert(sourceIndex >= 0 || sourceIndex <= sourceArray.Length - length);
                Debugging.Assert(destinationIndex >= 0 || destinationIndex <= destinationArray.Length - length);
                Debugging.Assert(length >= 0 || length < sourceArray.Length || length < destinationArray.Length);
            }

            ArrayCopier<T>.Default.Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, length);
        }

        [SuppressMessage("CodeQuality", "IDE0079:Remove unnecessary suppression", Justification = "This is a SonarCloud issue")]
        [SuppressMessage("CodeQuality", "S3400:Methods should not return constants", Justification = "Clearly, this is not always a constant value (SonarCloud bug)")]
        private static class PlatformDetection
        {
            // We put this in its own class so every type doesn't have to reload it. But, at the same time,
            // we don't want to have to load this just to use the Arrays class.
            public static readonly bool IsFullFramework = LoadIsFullFramework();
            public static readonly bool IsNetCore = LoadIsNetCore();

            private static bool LoadIsFullFramework()
            {
#if NETSTANDARD2_0
                return RuntimeInformation.FrameworkDescription.StartsWith(".NET Framework", StringComparison.OrdinalIgnoreCase);
#elif NET40_OR_GREATER
                return true;
#else
                return false;
#endif
            }

            private static bool LoadIsNetCore()
            {
#if NETSTANDARD2_0_OR_GREATER
                return RuntimeInformation.FrameworkDescription.StartsWith(".NET Core", StringComparison.OrdinalIgnoreCase);
#elif NET5_0_OR_GREATER || NETCOREAPP1_0_OR_GREATER
                return true;
#else
                return false;
#endif
            }
        }

        #region ArrayCopier<T>

        private static class ArrayCopier<T>
        {
            public static readonly IArrayCopier<T> Default = LoadArrayCopier();

            private static IArrayCopier<T> LoadArrayCopier()
            {
                // Default to Array.Copy() for unknown platforms (Span<T>.Copy() is slow on Mono)
                if (!PlatformDetection.IsFullFramework && !PlatformDetection.IsNetCore)
                    return new SystemArrayCopyArrayCopier<T>();

                var type = typeof(T);

                if (!type.IsValueType) // Reference types
                {
                    // Span<T> and Memory<T> are horribly slow on.NET Framework for
                    // copying arrays of reference types.
                    if (PlatformDetection.IsFullFramework)
                        return new SystemArrayCopyArrayCopier<T>();

                    return new SpanArrayCopier<T>();
                }

                // Value types are generally tied with or faster than Buffer.MemoryCopy() using
                // Span<T>.Copy() on Linux and macOS.
                if (!Constants.WINDOWS && !PlatformDetection.IsFullFramework)
                    return new SpanArrayCopier<T>();

                if (type == typeof(byte))
                {
                    // On Windows, copying bytes with Buffer.MemoryCopy() is fastest.
                    return (IArrayCopier<T>)(object)new ByteBufferMemoryCopyArrayCopier();
                }
                else if (type == typeof(sbyte))
                {
                    return (IArrayCopier<T>)(object)new SByteBufferMemoryCopyArrayCopier();
                }
                else if (PlatformDetection.IsFullFramework)
                {
                    // .NET Framework is 2-3x faster to use Buffer.MemoryCopy() than any other method for primitive types.
                    if (type == typeof(short))
                        return (IArrayCopier<T>)(object)new Int16BufferMemoryCopyArrayCopier();
                    if (type == typeof(ushort))
                        return (IArrayCopier<T>)(object)new UInt16BufferMemoryCopyArrayCopier();
                    if (type == typeof(int))
                        return (IArrayCopier<T>)(object)new Int32BufferMemoryCopyArrayCopier();
                    if (type == typeof(uint))
                        return (IArrayCopier<T>)(object)new UInt32BufferMemoryCopyArrayCopier();
                    if (type == typeof(long))
                        return (IArrayCopier<T>)(object)new Int64BufferMemoryCopyArrayCopier();
                    if (type == typeof(ulong))
                        return (IArrayCopier<T>)(object)new UInt64BufferMemoryCopyArrayCopier();
                    if (type == typeof(float))
                        return (IArrayCopier<T>)(object)new SingleBufferMemoryCopyArrayCopier();
                    if (type == typeof(double))
                        return (IArrayCopier<T>)(object)new DoubleBufferMemoryCopyArrayCopier();
                    if (type == typeof(char))
                        return (IArrayCopier<T>)(object)new CharBufferMemoryCopyArrayCopier();
                    if (type == typeof(bool))
                        return (IArrayCopier<T>)(object)new BooleanBufferMemoryCopyArrayCopier();

                    return new SystemArrayCopyArrayCopier<T>();
                }
                else
                {
                    return new SpanArrayCopier<T>();
                }
            }
        }

        private interface IArrayCopier<in T>
        {
            void Copy(T[] sourceArray, int sourceIndex, T[] destinationArray, int destinationIndex, int length);
        }

        private sealed class SpanArrayCopier<T> : IArrayCopier<T>
        {
            public void Copy(T[] sourceArray, int sourceIndex, T[] destinationArray, int destinationIndex, int length)
            {
                sourceArray.AsSpan(sourceIndex, length).CopyTo(destinationArray.AsSpan(destinationIndex, length));
            }
        }

        private sealed class SystemArrayCopyArrayCopier<T> : IArrayCopier<T>
        {
            public void Copy(T[] sourceArray, int sourceIndex, T[] destinationArray, int destinationIndex, int length)
            {
                Array.Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, length);
            }
        }

        #region Primitive Type Buffer.MemoryCopy() Array Copiers
        // We save some arithmetic by having a specialized type for byte, since we know it is measured in bytes.
        private sealed class ByteBufferMemoryCopyArrayCopier : IArrayCopier<byte>
        {
            public void Copy(byte[] sourceArray, int sourceIndex, byte[] destinationArray, int destinationIndex, int length)
            {
                unsafe
                {
                    fixed (byte* sourcePointer = &sourceArray[sourceIndex], destinationPointer = &destinationArray[destinationIndex])
                    {
                        // NOTE: We are relying on the fact that passing the pointers into this method is creating copies of them
                        // that are not fixed.
                        Buffer.MemoryCopy(sourcePointer, destinationPointer, destinationArray.Length - destinationIndex, length);
                    }
                }
            }
        }

        // We save some arithmetic by having a specialized type for byte, since we know it is measured in bytes.
        private sealed class SByteBufferMemoryCopyArrayCopier : IArrayCopier<sbyte>
        {
            public void Copy(sbyte[] sourceArray, int sourceIndex, sbyte[] destinationArray, int destinationIndex, int length)
            {
                unsafe
                {
                    fixed (sbyte* sourcePointer = &sourceArray[sourceIndex], destinationPointer = &destinationArray[destinationIndex])
                    {
                        // NOTE: We are relying on the fact that passing the pointers into this method is creating copies of them
                        // that are not fixed.
                        Buffer.MemoryCopy(sourcePointer, destinationPointer, destinationArray.Length - destinationIndex, length);
                    }
                }
            }
        }

        // LUCENENET NOTE: Tried to make the following types one generic type, but SDKs prior to .NET 7 won't compile it.
        // See: https://github.com/dotnet/runtime/issues/76255

        private sealed class Int16BufferMemoryCopyArrayCopier : IArrayCopier<short>
        {
            public void Copy(short[] sourceArray, int sourceIndex, short[] destinationArray, int destinationIndex, int length)
            {
                unsafe
                {
                    fixed (short* sourcePointer = &sourceArray[sourceIndex], destinationPointer = &destinationArray[destinationIndex])
                    {
                        const int size = sizeof(short);
                        long destinationSizeInBytes = (destinationArray.Length - destinationIndex) * size;
                        long sourceBytesToCopy = length * size;
                        // NOTE: We are relying on the fact that passing the pointers into this method is creating copies of them
                        // that are not fixed.
                        Buffer.MemoryCopy(sourcePointer, destinationPointer, destinationSizeInBytes, sourceBytesToCopy);
                    }
                }
            }
        }

        private sealed class UInt16BufferMemoryCopyArrayCopier : IArrayCopier<ushort>
        {
            public void Copy(ushort[] sourceArray, int sourceIndex, ushort[] destinationArray, int destinationIndex, int length)
            {
                unsafe
                {
                    fixed (ushort* sourcePointer = &sourceArray[sourceIndex], destinationPointer = &destinationArray[destinationIndex])
                    {
                        const int size = sizeof(ushort);
                        long destinationSizeInBytes = (destinationArray.Length - destinationIndex) * size;
                        long sourceBytesToCopy = length * size;
                        // NOTE: We are relying on the fact that passing the pointers into this method is creating copies of them
                        // that are not fixed.
                        Buffer.MemoryCopy(sourcePointer, destinationPointer, destinationSizeInBytes, sourceBytesToCopy);
                    }
                }
            }
        }

        private sealed class Int32BufferMemoryCopyArrayCopier : IArrayCopier<int>
        {
            public void Copy(int[] sourceArray, int sourceIndex, int[] destinationArray, int destinationIndex, int length)
            {
                unsafe
                {
                    fixed (int* sourcePointer = &sourceArray[sourceIndex], destinationPointer = &destinationArray[destinationIndex])
                    {
                        const int size = sizeof(int);
                        long destinationSizeInBytes = (destinationArray.Length - destinationIndex) * size;
                        long sourceBytesToCopy = length * size;
                        // NOTE: We are relying on the fact that passing the pointers into this method is creating copies of them
                        // that are not fixed.
                        Buffer.MemoryCopy(sourcePointer, destinationPointer, destinationSizeInBytes, sourceBytesToCopy);
                    }
                }
            }
        }

        private sealed class UInt32BufferMemoryCopyArrayCopier : IArrayCopier<uint>
        {
            public void Copy(uint[] sourceArray, int sourceIndex, uint[] destinationArray, int destinationIndex, int length)
            {
                unsafe
                {
                    fixed (uint* sourcePointer = &sourceArray[sourceIndex], destinationPointer = &destinationArray[destinationIndex])
                    {
                        const int size = sizeof(uint);
                        long destinationSizeInBytes = (destinationArray.Length - destinationIndex) * size;
                        long sourceBytesToCopy = length * size;
                        // NOTE: We are relying on the fact that passing the pointers into this method is creating copies of them
                        // that are not fixed.
                        Buffer.MemoryCopy(sourcePointer, destinationPointer, destinationSizeInBytes, sourceBytesToCopy);
                    }
                }
            }
        }

        private sealed class Int64BufferMemoryCopyArrayCopier : IArrayCopier<long>
        {
            public void Copy(long[] sourceArray, int sourceIndex, long[] destinationArray, int destinationIndex, int length)
            {
                unsafe
                {
                    fixed (long* sourcePointer = &sourceArray[sourceIndex], destinationPointer = &destinationArray[destinationIndex])
                    {
                        const int size = sizeof(long);
                        long destinationSizeInBytes = (destinationArray.Length - destinationIndex) * size;
                        long sourceBytesToCopy = length * size;
                        // NOTE: We are relying on the fact that passing the pointers into this method is creating copies of them
                        // that are not fixed.
                        Buffer.MemoryCopy(sourcePointer, destinationPointer, destinationSizeInBytes, sourceBytesToCopy);
                    }
                }
            }
        }

        private sealed class UInt64BufferMemoryCopyArrayCopier : IArrayCopier<ulong>
        {
            public void Copy(ulong[] sourceArray, int sourceIndex, ulong[] destinationArray, int destinationIndex, int length)
            {
                unsafe
                {
                    fixed (ulong* sourcePointer = &sourceArray[sourceIndex], destinationPointer = &destinationArray[destinationIndex])
                    {
                        const int size = sizeof(ulong);
                        long destinationSizeInBytes = (destinationArray.Length - destinationIndex) * size;
                        long sourceBytesToCopy = length * size;
                        // NOTE: We are relying on the fact that passing the pointers into this method is creating copies of them
                        // that are not fixed.
                        Buffer.MemoryCopy(sourcePointer, destinationPointer, destinationSizeInBytes, sourceBytesToCopy);
                    }
                }
            }
        }

        private sealed class SingleBufferMemoryCopyArrayCopier : IArrayCopier<float>
        {
            public void Copy(float[] sourceArray, int sourceIndex, float[] destinationArray, int destinationIndex, int length)
            {
                unsafe
                {
                    fixed (float* sourcePointer = &sourceArray[sourceIndex], destinationPointer = &destinationArray[destinationIndex])
                    {
                        const int size = sizeof(float);
                        long destinationSizeInBytes = (destinationArray.Length - destinationIndex) * size;
                        long sourceBytesToCopy = length * size;
                        // NOTE: We are relying on the fact that passing the pointers into this method is creating copies of them
                        // that are not fixed.
                        Buffer.MemoryCopy(sourcePointer, destinationPointer, destinationSizeInBytes, sourceBytesToCopy);
                    }
                }
            }
        }

        private sealed class DoubleBufferMemoryCopyArrayCopier : IArrayCopier<double>
        {
            public void Copy(double[] sourceArray, int sourceIndex, double[] destinationArray, int destinationIndex, int length)
            {
                unsafe
                {
                    fixed (double* sourcePointer = &sourceArray[sourceIndex], destinationPointer = &destinationArray[destinationIndex])
                    {
                        const int size = sizeof(double);
                        long destinationSizeInBytes = (destinationArray.Length - destinationIndex) * size;
                        long sourceBytesToCopy = length * size;
                        // NOTE: We are relying on the fact that passing the pointers into this method is creating copies of them
                        // that are not fixed.
                        Buffer.MemoryCopy(sourcePointer, destinationPointer, destinationSizeInBytes, sourceBytesToCopy);
                    }
                }
            }
        }

        private sealed class CharBufferMemoryCopyArrayCopier : IArrayCopier<char>
        {
            public void Copy(char[] sourceArray, int sourceIndex, char[] destinationArray, int destinationIndex, int length)
            {
                unsafe
                {
                    fixed (char* sourcePointer = &sourceArray[sourceIndex], destinationPointer = &destinationArray[destinationIndex])
                    {
                        const int size = sizeof(char);
                        long destinationSizeInBytes = (destinationArray.Length - destinationIndex) * size;
                        long sourceBytesToCopy = length * size;
                        // NOTE: We are relying on the fact that passing the pointers into this method is creating copies of them
                        // that are not fixed.
                        Buffer.MemoryCopy(sourcePointer, destinationPointer, destinationSizeInBytes, sourceBytesToCopy);
                    }
                }
            }
        }

        private sealed class BooleanBufferMemoryCopyArrayCopier : IArrayCopier<bool>
        {
            public void Copy(bool[] sourceArray, int sourceIndex, bool[] destinationArray, int destinationIndex, int length)
            {
                unsafe
                {
                    fixed (bool* sourcePointer = &sourceArray[sourceIndex], destinationPointer = &destinationArray[destinationIndex])
                    {
                        const int size = sizeof(bool);
                        long destinationSizeInBytes = (destinationArray.Length - destinationIndex) * size;
                        long sourceBytesToCopy = length * size;
                        // NOTE: We are relying on the fact that passing the pointers into this method is creating copies of them
                        // that are not fixed.
                        Buffer.MemoryCopy(sourcePointer, destinationPointer, destinationSizeInBytes, sourceBytesToCopy);
                    }
                }
            }
        }

        // Intentionally not adding support for IntPtr and UIntPtr

        #endregion Primitive Type Buffer.MemoryCopy() Array Copiers

        #endregion ArrayCopier<T>


        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static T[] CopyOf<T>(T[] original, int newLength)
        {
            T[] newArray = new T[newLength];
            Copy(original, newArray, Math.Min(original.Length, newLength));
            return newArray;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static T[] CopyOfRange<T>(T[] original, int startIndexInc, int endIndexExc)
        {
            int newLength = endIndexExc - startIndexInc;
            T[] newArray = new T[newLength];
            Copy(original, startIndexInc, newArray, 0, newLength);
            return newArray;
        }

        /// <summary>
        /// Creates a <see cref="string"/> representation of the array passed.
        /// The result is surrounded by brackets <c>"[]"</c>, each
        /// element is converted to a <see cref="string"/> via the
        /// <see cref="J2N.Text.StringFormatter.InvariantCulture"/> and separated by <c>", "</c>. If
        /// the array is <c>null</c>, then <c>"null"</c> is returned.
        /// </summary>
        /// <typeparam name="T">The type of array element.</typeparam>
        /// <param name="array">The array to convert.</param>
        /// <returns>The converted array string.</returns>
        public static string ToString<T>(T[] array)
        {
            if (array is null)
                return "null"; //$NON-NLS-1$
            if (array.Length == 0)
                return "[]"; //$NON-NLS-1$
            StringBuilder sb = new StringBuilder(2 + array.Length * 4);
            sb.Append('[');
            sb.AppendFormat(J2N.Text.StringFormatter.InvariantCulture, "{0}", array[0]);
            for (int i = 1; i < array.Length; i++)
            {
                sb.Append(", "); //$NON-NLS-1$
                sb.AppendFormat(J2N.Text.StringFormatter.InvariantCulture, "{0}", array[i]);
            }
            sb.Append(']');
            return sb.ToString();
        }
    }
}
