public static int ByteLength(Array array) { // Is the array present? if (array == null) { throw new ArgumentNullException(nameof(array)); } // Is it of primitive types? if (!array.GetCorElementTypeOfElementType().IsPrimitiveType()) { throw new ArgumentException(SR.Arg_MustBePrimArray, nameof(array)); } nuint byteLength = (nuint)array.LongLength * (nuint)array.GetElementSize(); // This API is explosed both as Buffer.ByteLength and also used indirectly in argument // checks for Buffer.GetByte/SetByte. // // If somebody called Get/SetByte on 2GB+ arrays, there is a decent chance that // the computation of the index has overflowed. Thus we intentionally always // throw on 2GB+ arrays in Get/SetByte argument checks (even for indicies <2GB) // to prevent people from running into a trap silently. return(checked ((int)byteLength)); }
// Copies from one primitive array to another primitive array without // respecting types. This calls memmove internally. The count and // offset parameters here are in bytes. If you want to use traditional // array element indices and counts, use Array.Copy. public static unsafe void BlockCopy(Array src, int srcOffset, Array dst, int dstOffset, int count) { ArgumentNullException.ThrowIfNull(src); ArgumentNullException.ThrowIfNull(dst); nuint uSrcLen = src.NativeLength; if (src.GetType() != typeof(byte[])) { if (!src.GetCorElementTypeOfElementType().IsPrimitiveType()) { throw new ArgumentException(SR.Arg_MustBePrimArray, nameof(src)); } uSrcLen *= (nuint)src.GetElementSize(); } nuint uDstLen = uSrcLen; if (src != dst) { uDstLen = dst.NativeLength; if (dst.GetType() != typeof(byte[])) { if (!dst.GetCorElementTypeOfElementType().IsPrimitiveType()) { throw new ArgumentException(SR.Arg_MustBePrimArray, nameof(dst)); } uDstLen *= (nuint)dst.GetElementSize(); } } if (srcOffset < 0) { throw new ArgumentOutOfRangeException(nameof(srcOffset), SR.ArgumentOutOfRange_MustBeNonNegInt32); } if (dstOffset < 0) { throw new ArgumentOutOfRangeException(nameof(dstOffset), SR.ArgumentOutOfRange_MustBeNonNegInt32); } if (count < 0) { throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_MustBeNonNegInt32); } nuint uCount = (nuint)count; nuint uSrcOffset = (nuint)srcOffset; nuint uDstOffset = (nuint)dstOffset; if ((uSrcLen < uSrcOffset + uCount) || (uDstLen < uDstOffset + uCount)) { throw new ArgumentException(SR.Argument_InvalidOffLen); } Memmove(ref Unsafe.AddByteOffset(ref MemoryMarshal.GetArrayDataReference(dst), uDstOffset), ref Unsafe.AddByteOffset(ref MemoryMarshal.GetArrayDataReference(src), uSrcOffset), uCount); }