Reflect recent NS2.1 changes (#14679)
[mono-project.git] / mcs / class / corlib / corefx / RandomNumberGenerator.cs
blobd181358f82d57f17bc481ddbc2ca6f36cbe48c07
1 using System.Buffers;
2 using System.Runtime.InteropServices;
4 namespace System.Security.Cryptography
6 partial class RandomNumberGenerator
8 public static void Fill (Span<byte> data)
10 FillSpan (data);
13 internal static unsafe void FillSpan (Span<byte> data)
15 if (data.Length > 0) {
16 fixed (byte* ptr = data) Interop.GetRandomBytes (ptr, data.Length);
20 public virtual void GetBytes(Span<byte> data)
22 byte[] array = ArrayPool<byte>.Shared.Rent(data.Length);
23 try
25 GetBytes(array, 0, data.Length);
26 new ReadOnlySpan<byte>(array, 0, data.Length).CopyTo(data);
28 finally
30 Array.Clear(array, 0, data.Length);
31 ArrayPool<byte>.Shared.Return(array);
35 public virtual void GetNonZeroBytes(Span<byte> data)
37 byte[] array = ArrayPool<byte>.Shared.Rent(data.Length);
38 try
40 // NOTE: There is no GetNonZeroBytes(byte[], int, int) overload, so this call
41 // may end up retrieving more data than was intended, if the array pool
42 // gives back a larger array than was actually needed.
43 GetNonZeroBytes(array);
44 new ReadOnlySpan<byte>(array, 0, data.Length).CopyTo(data);
46 finally
48 Array.Clear(array, 0, data.Length);
49 ArrayPool<byte>.Shared.Return(array);
53 public static int GetInt32(int fromInclusive, int toExclusive)
55 if (fromInclusive >= toExclusive)
56 throw new ArgumentException(SR.Argument_InvalidRandomRange);
58 // The total possible range is [0, 4,294,967,295).
59 // Subtract one to account for zero being an actual possibility.
60 uint range = (uint)toExclusive - (uint)fromInclusive - 1;
62 // If there is only one possible choice, nothing random will actually happen, so return
63 // the only possibility.
64 if (range == 0)
66 return fromInclusive;
69 // Create a mask for the bits that we care about for the range. The other bits will be
70 // masked away.
71 uint mask = range;
72 mask |= mask >> 1;
73 mask |= mask >> 2;
74 mask |= mask >> 4;
75 mask |= mask >> 8;
76 mask |= mask >> 16;
78 Span<uint> resultSpan = stackalloc uint[1];
79 uint result;
83 FillSpan(MemoryMarshal.AsBytes(resultSpan));
84 result = mask & resultSpan[0];
86 while (result > range);
88 return (int)result + fromInclusive;
91 public static int GetInt32(int toExclusive)
93 if (toExclusive <= 0)
94 throw new ArgumentOutOfRangeException(nameof(toExclusive), SR.ArgumentOutOfRange_NeedPosNum);
96 return GetInt32(0, toExclusive);