UNPKG

shuffrand

Version:

Cryptographically secure randomness and shuffling — with soul.

104 lines (103 loc) 3.65 kB
import { shuffleParamsSchema as y } from "./types.es.js"; import { cryptoRandom as x } from "./random.es.js"; /** * shuffrand - Cryptographically Secure Array Shuffling * * This file contains the core logic for shuffling arrays using a cryptographically secure method, * adhering to a flat, dot-categorized structure for clarity. * * @author Doron Brayer <doronbrayer@outlook.com> * @license MIT */ function g(I = [], e = {}) { if (e === null) throw new TypeError( "Invalid cryptoShuffle parameters: 'options' cannot be null. Please provide an object or omit it." ); if (e.startIndex !== void 0) { if (typeof e.startIndex != "number") throw new TypeError( `Invalid cryptoShuffle parameters: startIndex must be a number (was ${typeof e.startIndex})` ); if (!Number.isInteger(e.startIndex)) throw new TypeError( `Invalid cryptoShuffle parameters: startIndex must be an integer (was ${e.startIndex})` ); } if (e.endIndex !== void 0) { if (typeof e.endIndex != "number") throw new TypeError( `Invalid cryptoShuffle parameters: endIndex must be a number (was ${typeof e.endIndex})` ); if (!Number.isInteger(e.endIndex)) throw new TypeError( `Invalid cryptoShuffle parameters: endIndex must be an integer (was ${e.endIndex})` ); } const n = { arr: I, isDestructive: e.isDestructive ?? !1, preventIdentical: e.preventIdentical ?? !1, startIndex: e.startIndex, // Will be undefined if not provided, which is valid per schema endIndex: e.endIndex // Will be undefined if not provided, which is valid per schema }; let c; try { y.assert(n), c = { arr: n.arr ?? [], isDestructive: n.isDestructive ?? !1, preventIdentical: n.preventIdentical ?? !1, // Apply defaults for startIndex and endIndex startIndex: n.startIndex ?? 0, endIndex: n.endIndex ?? n.arr?.length ?? 0 // Default to array length or 0 if arr is undefined/empty }; } catch (r) { throw new TypeError(`Invalid cryptoShuffle parameters: ${r.summary || r.message}`); } const { arr: d, isDestructive: h, preventIdentical: m, startIndex: l, endIndex: s } = c, i = d.length; if (l < 0 || l > i) throw new TypeError( `Invalid cryptoShuffle parameters: 'startIndex' (${l}) must be between 0 and the array length (${i}), inclusive.` ); if (s < 0 || s > i) throw new TypeError( `Invalid cryptoShuffle parameters: 'endIndex' (${s}) must be between 0 and the array length (${i}), inclusive.` ); const t = h ? d : [...d], a = t.length, o = Math.max(0, Math.min(l, a)), p = Math.max(o, Math.min(s, a)); let u = null; if (m) try { u = JSON.stringify(d); } catch (r) { throw new TypeError( `Invalid cryptoShuffle parameters: Array elements cannot be serialized for 'preventIdentical' comparison. Ensure all elements are JSON-serializable. Original error: ${r.message}` ); } for (let r = p - 1; r > o; r--) { const f = x({ lowerBound: o, upperBound: r, typeOfNum: "integer", exclusion: "none" }); [t[r], t[f]] = [t[f], t[r]]; } if (m && u !== null && a > 1) { let r; try { r = JSON.stringify(t); } catch (f) { throw new TypeError( `Invalid cryptoShuffle parameters: Shuffled array elements cannot be serialized for 'preventIdentical' comparison. Ensure all elements are JSON-serializable. Original error: ${f.message}` ); } r === u && ([t[0], t[a - 1]] = [t[a - 1], t[0]]); } return t; } export { g as cryptoShuffle };