Created
May 6, 2023 21:59
-
-
Save cyyynthia/e77c744cb6494dabe37d0182506526b9 to your computer and use it in GitHub Desktop.
An utility to generate a large random TOML file. Used to benchmark https://github.com/squirrelchat/smol-toml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! | |
* BSD Zero Clause License | |
* Copyright (c) Cynthia Rey | |
* SPDX-License-Identifier: 0BSD | |
* | |
* Permission to use, copy, modify, and/or distribute this software for any | |
* purpose with or without fee is hereby granted. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH | |
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | |
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, | |
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM | |
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR | |
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | |
* PERFORMANCE OF THIS SOFTWARE. | |
*/ | |
const TABLES_COUNT = 1000 | |
const MAX_KEYS_PER_TABLE = 50 | |
const MAX_TABLE_ARRAY = 10 | |
const MAX_ELEMENTS_PER_INLINE_STRUCT = 10 | |
const STRING_LENGTH = [ 10, 50 ] | |
const ML_STRING_MAX_WORDS = 10 | |
const ML_STRING_MAX_LINES = 10 | |
const KEY_PART_LENGTH = [ 5, 10 ] | |
const MAX_KEY_DEPTH = 3 | |
const ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" | |
function generateKey (maxDepth = 1) { | |
let key = '' | |
const depth = ((Math.random() * maxDepth) | 0) + 1 | |
for (let i = 0; i < depth; i++) { | |
if (i !== 0) key += '.' | |
const targetLength = ((Math.random() * (KEY_PART_LENGTH[1] - KEY_PART_LENGTH[0])) | 0) + KEY_PART_LENGTH[0] | |
for (let j = 0; j < targetLength; j++) { | |
key += ALPHABET[(Math.random() * ALPHABET.length) | 0] | |
} | |
} | |
return key | |
} | |
function generateWord () { | |
let word = '' | |
const targetLength = ((Math.random() * (STRING_LENGTH[1] - STRING_LENGTH[0])) | 0) + STRING_LENGTH[0] | |
for (let j = 0; j < targetLength; j++) { | |
word += ALPHABET[(Math.random() * ALPHABET.length) | 0] | |
} | |
return word | |
} | |
const ESCAPES = [ '\\b', '\\t', '\\n', '\\f', '\\r', '\\"', '\\\\', '\\u2764', '\\U0001F43F' ] | |
function generateString (isInline) { | |
let str = '' | |
const isLiteral = Math.random() < .2 | |
const isMl = isInline ? false : Math.random() < .1 | |
const lines = (isMl && (Math.random() * ML_STRING_MAX_LINES)) + 1 | |
const escapeEol = Math.random() < .1 | |
for (let i = 0; i < lines; i++) { | |
if (i !== 0) { | |
if (escapeEol) str += ' \\' | |
str += '\n' | |
} | |
const words = (isMl && (Math.random() * ML_STRING_MAX_WORDS)) + 1 | |
for (let j = 0; j < words; j++) { | |
if (j !== 0) str += ' ' | |
str += generateWord() | |
if (!isLiteral && Math.random() < .1) { | |
str += ESCAPES[(Math.random() * ESCAPES.length) | 0] | |
} | |
} | |
} | |
let strMark = isLiteral ? "'" : '"' | |
if (isMl) strMark = strMark.repeat(3) | |
return isLiteral | |
? strMark + str + strMark | |
: strMark + str + strMark | |
} | |
function generateInteger () { | |
const isLarge = Math.random() < .1 | |
const number = Math.floor(Math.random() * (isLarge ? Number.MAX_SAFE_INTEGER - 1 : 10000)) | |
if (Math.random() < .4) { | |
if (Math.random() < .2) { | |
return '0b' + number.toString(2) | |
} | |
if (Math.random() < .2) { | |
return '0o' + number.toString(8) | |
} | |
const hex = Math.random() < .5 ? number.toString(16) : number.toString(16).toUpperCase() | |
return '0x' + (isLarge ? hex.replace(/(\d)(?=(\d{4})+(?!\d))/g, "$1_") : hex) | |
} | |
const sign = Math.random() < .5 ? '-' : (Math.random() < .05 ? '+' : '') | |
return sign + (isLarge ? number.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1_") : number) | |
} | |
const FLOAT_SPECIAL = [ 'inf', '+inf', '-inf', 'nan', '+nan', '-nan' ] | |
function generateFloat () { | |
if (Math.random() < .05) { | |
return FLOAT_SPECIAL[(Math.random() * FLOAT_SPECIAL.length) | 0] | |
} | |
const sign = Math.random() < .5 ? '-' : (Math.random() < .05 ? '+' : '') | |
const intPart = ((Math.random() * 10000) | 0).toString() | |
const decPart = ((Math.random() * 10000) | 0).toString() | |
let exponent = '' | |
if (Math.random() < .2) { | |
exponent += Math.random() < .5 ? 'e' : 'E' | |
exponent += Math.random() < .5 ? '-' : (Math.random() < .05 ? '+' : '') | |
exponent += ((Math.random() * 100) | 0).toString() | |
} | |
return sign + intPart + '.' + decPart + exponent | |
} | |
function generateBoolean () { | |
return (Math.random() < .5).toString() | |
} | |
function generateDate () { | |
const date = new Date(Math.round(Math.random() * Date.now())).toISOString().split(/T|Z/) | |
date.splice(1, 0, Math.random() < .5 ? ' ' : 'T') | |
if (Math.random() < .6) { | |
date[2] = date[2].slice(0, 8) | |
} | |
if (Math.random() < .6) { | |
if (Math.random() < .2) { | |
const sign = Math.random() < .5 ? '-' : '+' | |
const hours = ((Math.random() * 12) | 0).toString().padStart(2, '0') | |
const mins = Math.random() < .5 ? '30' : '00' | |
date[3] = sign + hours + ':' + mins | |
} else { | |
date[3] = 'Z' | |
} | |
} | |
if (Math.random() < .3) { | |
return date[0] | |
} | |
if (Math.random() < .3) { | |
return date[2] | |
} | |
return date.join('') | |
} | |
function generateArray () { | |
let str = '[ ' | |
const targetCount = ((Math.random() * MAX_ELEMENTS_PER_INLINE_STRUCT) | 0) + 1 | |
for (let i = 0; i < targetCount; i++) { | |
if (i !== 0) str += ', ' | |
str += generateValue(.05) | |
} | |
return str + ' ]' | |
} | |
function generateInlineTable () { | |
let str = '{ ' | |
const targetCount = ((Math.random() * MAX_ELEMENTS_PER_INLINE_STRUCT) | 0) + 1 | |
for (let i = 0; i < targetCount; i++) { | |
if (i !== 0) str += ', ' | |
str += generateKey() | |
str += ' = ' | |
str += generateValue(.1) | |
} | |
return str + ' }' | |
} | |
function generateValue (isInline) { | |
if (Math.random() < (isInline ? .05 : .2)) { | |
return Math.random() < .5 | |
? generateInlineTable() | |
: generateArray() | |
} | |
const kind = (Math.random() * 4) | 0 | |
switch (kind) { | |
case 0: return generateString() | |
case 1: return generateInteger() | |
case 2: return generateFloat() | |
case 3: return generateDate() | |
} | |
} | |
let document = '' | |
let table = '' | |
let currentDepth = 0 | |
let arrayDepthToGo = 0 | |
for (let i = 0; i < TABLES_COUNT; i++) { | |
if (arrayDepthToGo) { | |
i-- | |
arrayDepthToGo-- | |
document += `[[${table}]]\n` | |
} else { | |
if (currentDepth && currentDepth < MAX_KEY_DEPTH && Math.random() < .6) { | |
table += '.' + generateKey(1) | |
currentDepth++ | |
} else { | |
currentDepth = 1 | |
table = generateKey(1) | |
} | |
if (Math.random() < .05) { | |
i-- | |
arrayDepthToGo = ((Math.random() * MAX_TABLE_ARRAY) | 0) + 1 | |
continue | |
} | |
document += `[${table}]\n` | |
} | |
const keyCount = ((Math.random() * MAX_KEYS_PER_TABLE) | 0) + 1 | |
for (let j = 0; j < keyCount; j++) { | |
const key = generateKey(MAX_KEY_DEPTH) | |
document += `${key} = ${generateValue()}\n` | |
} | |
document += `\n` | |
} | |
console.log(document) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment