xref: /expo/packages/expo-random/src/Random.ts (revision f8111c10)
1import { UnavailabilityError } from '@unimodules/core';
2import { toByteArray } from 'base64-js';
3
4import ExpoRandom from './ExpoRandom';
5
6function assertByteCount(value: any, methodName: string): void {
7  if (
8    typeof value !== 'number' ||
9    isNaN(value) ||
10    Math.floor(value) < 0 ||
11    Math.floor(value) > 1024
12  ) {
13    throw new TypeError(
14      `expo-random: ${methodName}(${value}) expected a valid number from range 0...1024`
15    );
16  }
17}
18
19// @needsAudit
20/**
21 * Generates completely random bytes using native implementations. The `byteCount` property
22 * is a `number` indicating the number of bytes to generate in the form of a `Uint8Array`.
23 * @param byteCount - A number within the range from `0` to `1024`. Anything else will throw a `TypeError`.
24 * @return An array of random bytes with the same length as the `byteCount`.
25 */
26export function getRandomBytes(byteCount: number): Uint8Array {
27  assertByteCount(byteCount, 'getRandomBytes');
28  const validByteCount = Math.floor(byteCount);
29  if (ExpoRandom.getRandomBytes) {
30    return ExpoRandom.getRandomBytes(validByteCount);
31  } else if (ExpoRandom.getRandomBase64String) {
32    const base64 = ExpoRandom.getRandomBase64String(validByteCount);
33    return toByteArray(base64);
34  } else {
35    throw new UnavailabilityError('expo-random', 'getRandomBytes');
36  }
37}
38
39// @needsAudit
40/**
41 * Generates completely random bytes using native implementations. The `byteCount` property
42 * is a `number` indicating the number of bytes to generate in the form of a `Uint8Array`.
43 * @param byteCount - A number within the range from `0` to `1024`. Anything else will throw a `TypeError`.
44 * @return A promise that fulfills with an array of random bytes with the same length as the `byteCount`.
45 */
46export async function getRandomBytesAsync(byteCount: number): Promise<Uint8Array> {
47  assertByteCount(byteCount, 'getRandomBytesAsync');
48  const validByteCount = Math.floor(byteCount);
49  if (ExpoRandom.getRandomBytesAsync) {
50    return await ExpoRandom.getRandomBytesAsync(validByteCount);
51  } else if (ExpoRandom.getRandomBase64StringAsync) {
52    const base64 = await ExpoRandom.getRandomBase64StringAsync(validByteCount);
53    return toByteArray(base64);
54  } else {
55    throw new UnavailabilityError('expo-random', 'getRandomBytesAsync');
56  }
57}
58